994 lines
42 KiB
C
994 lines
42 KiB
C
|
/*
|
||
|
|
||
|
This is a dynamic link library that runs under Windows 3.00. Duties of
|
||
|
this library include saving screen image to a file, retrieving screen
|
||
|
image from file & displaying it on screen, and comparing two screen
|
||
|
images.
|
||
|
|
||
|
Routines in this module are responsible for taking, saving, and deleting
|
||
|
screen images.
|
||
|
|
||
|
For the usage of this libray, please refer to the WattScr user's guide,
|
||
|
WattScrU.doc. For the technical information, please refer to the
|
||
|
WattScr maintenance's guide, WattScrT.doc.
|
||
|
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
[ 0] 20-Feb-1990 AngelaCh: Created program
|
||
|
[ 1] 05-Mar-1990 AngelaCh: Increase limit of screen
|
||
|
in file (30 to 100) -
|
||
|
changed made in dump.h
|
||
|
[ 2] 03-Mar-1990 AngelaCh: add info for version number
|
||
|
and programming environment
|
||
|
to the header of screen file
|
||
|
[ 3] 12-Mar-1990 AngelaCh: added functions for retrieving
|
||
|
info on version number, total
|
||
|
number of screens in file, and
|
||
|
programming enviornment
|
||
|
[ 4] 13-Mar-1990 AngelaCh: change return code to 24 when
|
||
|
trying to add screen to file
|
||
|
with 100 screens
|
||
|
[ 5] 14-Mar-1990 AngelaCh: added checking for replacing
|
||
|
screen n (n<=0 or n>maxsize)
|
||
|
when file is full (bug #39)
|
||
|
[ 6] 20-Mar-1990 AngelaCh: add 300 to all return codes
|
||
|
[ 7] 20-Mar-1990 AngelaCh: add function fDumpWindow
|
||
|
[ 8] 27-Mar-1990 AngelaCh: correct typo in function dec
|
||
|
[ 9] 11-Apr-1990 AngelaCh: Changed error codes from num
|
||
|
const to symbolic constants
|
||
|
[10] 20-Apr-1990 AngelaCh: add parameter fFlag to proc
|
||
|
fAddScreen to designate that
|
||
|
image is written to a screen
|
||
|
file
|
||
|
[11] 05-Jul-1990 AngelaCh: add function fIntsToStr for
|
||
|
calling functions, which re-
|
||
|
quire pointer to a structure,
|
||
|
from Excel
|
||
|
[12] 18-Jul-1991 DavidSc: Added WattDrvr TRAP support
|
||
|
[13] 13-Aug-1991 DavidSc: Add arbitrary screen support
|
||
|
[14] 12-16-91 dougbo: add Activate version of some
|
||
|
routines
|
||
|
******************************************************************************/
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#include "windows.h"
|
||
|
#include <port1632.h>
|
||
|
#include "dump.h"
|
||
|
|
||
|
#ifndef WIN32
|
||
|
#define _MT
|
||
|
#include <io.h>
|
||
|
#else
|
||
|
#define rename MoveFile
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define intBase 8
|
||
|
|
||
|
/* Global Variables */
|
||
|
|
||
|
CHAR TempFile[] = "@@@Dump.tmp" ; /* name of temp file */
|
||
|
|
||
|
BOOL fIgnoreEvntErrTrap = FALSE; // Trap either WinMissing, or EvntErr, not both
|
||
|
INT vWINTrapID; // WattDrvr TrapID for missing windows
|
||
|
INT vERRTrapID; // WattDrvr TrapID for entrypoint errors
|
||
|
TrapCallBack WINTrapCallBack = NULL;// WattDrvr Callback for missing windows
|
||
|
TrapCallBack ERRTrapCallBack = NULL;// WattDrvr Callback for entrypoint errors
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: Returns the internal representation of an integer *
|
||
|
* RETURN: A string of 2 characters representing an integer *
|
||
|
* GLOBALS: None *
|
||
|
* CONDITIONS:x is the integer whose internal representation will be returned *
|
||
|
* in s *
|
||
|
******************************************************************************/
|
||
|
|
||
|
VOID fIToS(x, s) /* [11] */
|
||
|
|
||
|
INT x ;
|
||
|
LPSTR s ;
|
||
|
{
|
||
|
|
||
|
if ( x < 0 ) /* if the integer is negative, change */
|
||
|
x = 0 ; /* it to 0 */
|
||
|
|
||
|
*s = x - ( (x >> intBase) << intBase ) ;
|
||
|
*(s+1) = (x >> intBase) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: Returns the internal representation of 8 integers *
|
||
|
* RETURN: A string of 9 characters representing 8 integers *
|
||
|
* GLOBALS: None *
|
||
|
* CONDITIONS:x1, y1, x2, y2 are the integers whose internal representation *
|
||
|
* will be returned in s *
|
||
|
* no error checking will be performed in this routine *
|
||
|
* Special Note: This routine is only useful when calling Wattscr functions *
|
||
|
* that required pointer to a structure from Excel. Since Excel *
|
||
|
* does not support structure data type, a string representing *
|
||
|
* the upper-left and lower-rigth coordinates of a screen region*
|
||
|
* will be used instead. *
|
||
|
******************************************************************************/
|
||
|
|
||
|
LPSTR FARPUBLIC fIntsToStr (s, x1, y1, x2, y2)
|
||
|
|
||
|
LPSTR s ;
|
||
|
INT x1 ;
|
||
|
INT y1 ;
|
||
|
INT x2 ;
|
||
|
INT y2 ;
|
||
|
{
|
||
|
|
||
|
*s = 8 ; /* number of char's will be returned */
|
||
|
|
||
|
fIToS(x1, s+1) ; /* find out the internal represent- */
|
||
|
fIToS(y1, s+3) ; /* ation of these integers 1 integer */
|
||
|
fIToS(x2, s+5) ; /* at a time */
|
||
|
fIToS(y2, s+7) ;
|
||
|
|
||
|
return s ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: Create the appropriate Screen File Header. *
|
||
|
* RETURN: Ture if current video mode is supported; otherwise, False will *
|
||
|
* be returned. *
|
||
|
* GLOBALS: fssScreen, consisting of information about file, which will be *
|
||
|
* filled after this function call *
|
||
|
* CONDITIONS:None *
|
||
|
******************************************************************************/
|
||
|
|
||
|
VOID PRIVATE CreateHeader(void)
|
||
|
|
||
|
{
|
||
|
VM vm ;
|
||
|
|
||
|
fssScreen.fst.FileId[0] = '@' ; /* file id for the screen files [2] */
|
||
|
fssScreen.fst.FileId[1] = '@' ;
|
||
|
fssScreen.fst.FileId[2] = '@' ;
|
||
|
fssScreen.fst.Ver = (BYTE)VerCur ; /* record version number [2] */
|
||
|
fssScreen.fst.Env = (BYTE)EnvCur ; /* record programming env [2] */
|
||
|
|
||
|
fssScreen.cscr = 0 ; /* no screen has been dumped yet */
|
||
|
fssScreen.lfo = 0x20; //sizeof (FSS) /* offset to the 1st screen contents */
|
||
|
|
||
|
GetCurrentVideoMode( &vm ) ;
|
||
|
fssScreen.vmG = vm ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: Try to compress some bytes of data before writing them out to a *
|
||
|
* file; if the compression fails, write out the orginal data *
|
||
|
* RETURN: 0 will be returned if the data are written out successfully *
|
||
|
* number of bytes written to file will be returned via variable cb*
|
||
|
* if compression is successful or not will be returned via IsComp *
|
||
|
* GLOBALS: none *
|
||
|
* CONDITIONS:fd is a valid file handle *
|
||
|
* lpIn points a string of data to be written *
|
||
|
* biSize number of bytes to be written *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT PRIVATE WriteCompBytes(FD fd, LPSTR lpIn, WORD biSize, WORD FAR *cb, INT FAR *IsComp)
|
||
|
|
||
|
// FD fd ; /* handle of the screen file */
|
||
|
// LPSTR lpIn ; /* points to data to be written */
|
||
|
// WORD biSize ; /* number of bytes to be written */
|
||
|
// WORD FAR *cb ; /* actual number of bytes written */
|
||
|
// INT FAR *IsComp ; /* is compression done successfully? */
|
||
|
{
|
||
|
LPSTR lpOut ;
|
||
|
GLOBALHANDLE hGMem ;
|
||
|
WORD hb ;
|
||
|
INT i = 0 ;
|
||
|
|
||
|
hGMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DISCARDABLE, (DWORD)biSize) ;
|
||
|
if ( !hGMem ) /* allocate memory for receiving */
|
||
|
return OutOMemory ; /* bytes after compression [6] [9] */
|
||
|
|
||
|
lpOut = (LPSTR) GlobalLock(hGMem) ;
|
||
|
|
||
|
/* if compress the data resulting in more bytes, write out original data */
|
||
|
if ( (hb = CompressBytes(lpIn, lpOut, biSize)) > biSize )
|
||
|
if ( M_lwrite(fd, lpIn, biSize) != biSize )
|
||
|
i = WSrnImage ; /* [6] [9] */
|
||
|
else
|
||
|
*cb = biSize ;
|
||
|
else /* otherwise, write out compressed */
|
||
|
if ( M_lwrite(fd, lpOut, hb) != hb ) /* data */
|
||
|
i = WSrnImage ; /* [6] [9] */
|
||
|
else
|
||
|
{
|
||
|
*cb = hb ;
|
||
|
*IsComp = 1 ;
|
||
|
}
|
||
|
|
||
|
if ( GlobalUnlock(hGMem) )
|
||
|
{
|
||
|
if ( i )
|
||
|
return i ;
|
||
|
else
|
||
|
return RelMemory ; /* [6] [9] */
|
||
|
}
|
||
|
|
||
|
if ( GlobalFree(hGMem) )
|
||
|
{
|
||
|
if ( i )
|
||
|
return i;
|
||
|
else
|
||
|
return RelMemory ; /* [6] [9] */
|
||
|
}
|
||
|
else
|
||
|
return NoError ; /* [9] */
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: This routine will be called when a request for adding screen to *
|
||
|
* the end of a screen file is received *
|
||
|
* RETURN: 0 will be returned if screen is added successfully *
|
||
|
* GLOBALS: fssScreen (file header) and rgscr (screen table) *
|
||
|
* CONDITIONS:fd is valid file handl *
|
||
|
* rn contains the x-y coordinates of the upper-left & lower-right *
|
||
|
* of the screen region in concern *
|
||
|
* hFlag contains valid info of whether the active window should be*
|
||
|
* hidden before taking the snapshot or not *
|
||
|
* file header and screen table are assumed to have proper info *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT PRIVATE fAppendSrn(FD fd, REN FAR *rn, INT hFlag)
|
||
|
|
||
|
// FD fd ; /* handle of the sceen file */
|
||
|
// REN FAR *rn ; /* coord of the screen region */
|
||
|
// INT hFlag ; /* where in the file */
|
||
|
{
|
||
|
SCR *pscr ;
|
||
|
INT i = 0 , j ;
|
||
|
|
||
|
pscr = &rgscr[fssScreen.cscr]; /* points to the current screen table */
|
||
|
pscr->lfo = fssScreen.lfo; /* offset to the contents of screen */
|
||
|
pscr->ren = *rn ; /* fill screen table with the x-y */
|
||
|
/* coordinates of the screen region */
|
||
|
j = 0 ; /* [10] */
|
||
|
if ( (i = fAddScreen(fd, pscr, hFlag, &j)) == 0 ) /* add the screen [10] */
|
||
|
{
|
||
|
fssScreen.cscr++ ; /* a screen has been added */
|
||
|
fssScreen.lfo = pscr->lfo ; /* update size of screens */
|
||
|
for ( j = 0 ; j < MaxCb ; j++)
|
||
|
fssScreen.lfo += pscr->cb[j];
|
||
|
}
|
||
|
else /* if error occurs in adding screen */
|
||
|
M_llseek(fd, fssScreen.lfo, smFromBegin) ; /* restore the old file */
|
||
|
|
||
|
j = fReWriteTables(fd) ; /* rewrite tables to file */
|
||
|
|
||
|
M_lclose(fd) ;
|
||
|
if ( i ) /* if error occurs in adding screen */
|
||
|
return i ;
|
||
|
else
|
||
|
return j ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: Update information of the screen tables after 1 of the screen *
|
||
|
* has been replaced by a new screen snapshot *
|
||
|
* RETURN: 0 will be returned if tables are updated successfully *
|
||
|
* GLOBALS: fssScreen (file header) and rgscr (screen table) *
|
||
|
* CONDITIONS:fd1 and fd2 are valid file handles *
|
||
|
* pscr contains the information of the screen before it was re- *
|
||
|
* placed *
|
||
|
* n is valid screen identifier (n > 0) *
|
||
|
* file header and screen table are assumed to have proper info *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT PRIVATE ReplaceSrnTable(FD fd1, FD fd2, SCR FAR *pscr, INT n)
|
||
|
|
||
|
// FD fd1 ; /* handle of the temp (old) file */
|
||
|
// FD fd2 ; /* handle of the screen (new) file */
|
||
|
// SCR FAR *pscr ; /* contains info of the old screen */
|
||
|
// INT n ; /* screen identifier */
|
||
|
{
|
||
|
LFO tLfo ;
|
||
|
INT i = 0 ;
|
||
|
|
||
|
/* part of the info of the old has been copied; skip info of the old */
|
||
|
tLfo = fssScreen.lfo - rgscr[n].lfo ; /* screen and copy the rest */
|
||
|
if ( (i = CpBlock(fd1, rgscr[n].lfo, fd2, 0L, tLfo)) != 0 )
|
||
|
return i ; /* of the file to the new file */
|
||
|
|
||
|
tLfo = 0 ; /* after the screen is replaced */
|
||
|
for ( i = 0 ; i < MaxCb ; i++ ) /* how many bytes of data are */
|
||
|
tLfo += (LFO)rgscr[n-1].cb[i]-(LFO)pscr->cb[i]; /* increased/reduced ? */
|
||
|
|
||
|
fssScreen.lfo += tLfo ; /* update the size of screen info */
|
||
|
/* (offset to the screen tables */
|
||
|
for ( i = n ; i < fssScreen.cscr ; i++ ) /* update the screen tables */
|
||
|
rgscr[i].lfo += tLfo ; /* (offset to the screen info) */
|
||
|
|
||
|
return NoError ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: Update information of the screen tables after a new screen has *
|
||
|
* been inserted among the old screens *
|
||
|
* RETURN: 0 will be returned if tables are updated successfully *
|
||
|
* GLOBALS: fssScreen (file header) and rgscr (screen table) *
|
||
|
* CONDITIONS:fd1 and fd2 are valid file handles *
|
||
|
* pscr contains the information of the screen before a new screen *
|
||
|
* takes its place *
|
||
|
* n is valid screen identifier (n > 0) *
|
||
|
* file header and screen table are assumed to have proper info *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT PRIVATE AddSrnTable(FD fd1, FD fd2, SCR FAR *pscr, INT n)
|
||
|
|
||
|
// FD fd1 ; /* handle of the temp (old) file */
|
||
|
// FD fd2 ; /* handle of the screen (new) file */
|
||
|
// SCR FAR *pscr ; /* contains info of the old screen */
|
||
|
// INT n ; /* screen identifier */
|
||
|
{
|
||
|
LFO tLfo ;
|
||
|
INT i = 0;
|
||
|
/* part of the info of the old */
|
||
|
tLfo = fssScreen.lfo - rgscr[n-1].lfo ; /* has been copied to the new */
|
||
|
if ( (i = CpBlock(fd1, 0L, fd2, 0L, tLfo)) != 0 ) /* file; now copy the */
|
||
|
return i ; /* rest if it to the new file */
|
||
|
|
||
|
tLfo = 0 ; /* after the a screen is added */
|
||
|
for ( i = 0 ; i < MaxCb ; i++ ) /* how many bytes of data are */
|
||
|
tLfo += (LFO) rgscr[n-1].cb[i] ; /* increased ? */
|
||
|
|
||
|
fssScreen.lfo += tLfo ; /* update the size of screen info */
|
||
|
/* (offset to the screen tables */
|
||
|
for ( i = fssScreen.cscr ; i > n ; i-- ) /* update the screen tables */
|
||
|
{ /* every single screen after the */
|
||
|
rgscr[i] = rgscr[i-1] ; /* insertion point must be moved */
|
||
|
rgscr[i].lfo += tLfo ; /* down by 1 screen */
|
||
|
}
|
||
|
|
||
|
rgscr[n] = *pscr ; /* this is the old nth screen, now */
|
||
|
rgscr[n].lfo = pscr->lfo + tLfo ; /* it becomes the (n+1)th screen */
|
||
|
|
||
|
fssScreen.cscr++ ; /* just added a new screen */
|
||
|
return NoError ; /* [9] */
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: The routine will be called when a request for inserting or re- *
|
||
|
* placing a screen is received *
|
||
|
* RETURN: 0 will be returned if screen is updated successfully *
|
||
|
* GLOBALS: fssScreen (file header) and rgscr (screen table) *
|
||
|
* CONDITIONS:FileName is valid file name in 8.3 format *
|
||
|
* rn contains the x-y coordinates of the upper-left & lower-right *
|
||
|
* of the screen region in concern *
|
||
|
* action contains valid action code for updating file *
|
||
|
* hFlag contains valid info of whether the active window should be*
|
||
|
* hidden before taking the snapshot or not *
|
||
|
* file header and screen table are assumed to have proper info *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT PRIVATE fUpdateSrnFile(LPSTR FileName, REN FAR *rn, INT action, INT n, INT hFlag)
|
||
|
|
||
|
// LPSTR FileName ; /* Name of the screen file */
|
||
|
// REN FAR *rn ; /* coord of the screen region */
|
||
|
// INT action ; /* insert of replace a screen */
|
||
|
// INT n ; /* screen identifier */
|
||
|
// INT hFlag ; /* where in the file */
|
||
|
{
|
||
|
FD fd1 = fdNull ;
|
||
|
FD fd2 = fdNull ;
|
||
|
SCR scr ;
|
||
|
SCR *pscr ;
|
||
|
INT i = 0, j = 0 ; /* [10] */
|
||
|
OFSTRUCT of;
|
||
|
|
||
|
if ( rename(FileName, TempFile) != 0 ) /* rename the screen file */
|
||
|
return CTempFile ; /* [6] [9] */
|
||
|
|
||
|
if ( (fd1 = M_lopen((LPSTR)TempFile, omRead)) == fdNull )
|
||
|
return CTempFile ; /* open temp file [6] [9] */
|
||
|
|
||
|
if ( (fd2 = M_lcreat(FileName, 0)) == fdNull ) /* create a new screen file */
|
||
|
{
|
||
|
M_lclose(fd1) ;
|
||
|
rename(TempFile, FileName) ;
|
||
|
return CTempFile ; /* [6] [9] */
|
||
|
}
|
||
|
|
||
|
if ( (i = CpBlock(fd1, 0L, fd2, 0L, rgscr[n-1].lfo)) == 0 )
|
||
|
{ /* copy screen info from the temp file until file is at position */
|
||
|
/* where the update should occur */
|
||
|
scr = rgscr[n-1] ; /* record the info of the old screen */
|
||
|
pscr = &rgscr[n-1] ;
|
||
|
pscr->ren = *rn ; /* take a snapshot of the screen */
|
||
|
i = fAddScreen(fd2, pscr, hFlag, &j) ; /* that is currently being */
|
||
|
/* displayed [10] */
|
||
|
if ( !i ) /* update screen table differently */
|
||
|
if ( action == Replace ) /* according to different updating */
|
||
|
i = ReplaceSrnTable(fd1, fd2, &scr, n) ; /* actions */
|
||
|
else
|
||
|
i = AddSrnTable(fd1, fd2, &scr, n) ;
|
||
|
|
||
|
if ( !i )
|
||
|
i = fReWriteTables(fd2) ; /* re-write tables to the file */
|
||
|
}
|
||
|
|
||
|
M_lclose(fd1) ;
|
||
|
M_lclose(fd2) ;
|
||
|
|
||
|
if ( !i )
|
||
|
i = MOpenFile(TempFile, &of, OF_DELETE); /* delete the temp file before */
|
||
|
else
|
||
|
{ /* if unpected error occurs */
|
||
|
MOpenFile(FileName, &of, OF_DELETE ); /* restore the old screenfile */
|
||
|
rename(TempFile, FileName) ;
|
||
|
}
|
||
|
return i ;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: This is called everytime a request to take a picture of a screen*
|
||
|
* region that is currently being displayed is received *
|
||
|
* RETURN: 0 will be returned if contents of the screen region is written *
|
||
|
* to a file successfully *
|
||
|
* GLOBALS: fssScreen - information of the file, will be filled *
|
||
|
* rgscr - information of a particular screen, will be filled *
|
||
|
* ClrTab - information about the colours used, will be filled *
|
||
|
* CONDITIONS:FileName is in the correct format (8:3) *
|
||
|
* rn consists of (x1, y1) and (x2, y2) which are the opposite *
|
||
|
* corner of a rectangular screen region *
|
||
|
* action is 0, 1, or 2 *
|
||
|
* hFlag is either 0 or 1 *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT FARPUBLIC fDumpScreenActivate(FileName, OpenKeys,CloseKeys,rn, action, n, hFlag) /* [8] */
|
||
|
|
||
|
LPSTR FileName ; /* name of the screen file */
|
||
|
LPSTR OpenKeys; /* keys to activate something */
|
||
|
LPSTR CloseKeys; /* keys to deactivate something */
|
||
|
REN FAR *rn ; /* xy-coord of the screen region */
|
||
|
INT action ; /* where the screen to be put in file */
|
||
|
INT n ; /* screen identifier */
|
||
|
INT hFlag ; /* if action window need to be hidden */
|
||
|
{
|
||
|
INT ret;
|
||
|
HWND hWndCallingApp ; /* window of the calling application */
|
||
|
|
||
|
|
||
|
if ( hFlag && !(hWndCallingApp = HideApp()) ) /* application first */
|
||
|
return ErrorTrap(HideWin) ;
|
||
|
|
||
|
if (LoadTESTEVT())
|
||
|
return ErrorTrap(LibLoadErr);
|
||
|
|
||
|
if (OpenKeys)
|
||
|
{
|
||
|
DoKeys(OpenKeys);
|
||
|
|
||
|
/* do some yields to allow keys to get to app and some time for it
|
||
|
** to respond.
|
||
|
*/
|
||
|
yield(); yield(); yield(); yield(); yield();
|
||
|
|
||
|
}
|
||
|
|
||
|
ret = fDumpScreen(FileName,rn, action, n, FALSE);
|
||
|
if (CloseKeys)
|
||
|
DoKeys(CloseKeys);
|
||
|
|
||
|
if ( hFlag ) /* if window has been hidded */
|
||
|
RestoreApp(hWndCallingApp) ; /* restore it */
|
||
|
|
||
|
FreeTESTEVT();
|
||
|
return NoTrap(ret);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: This is called everytime a request to take a picture of a screen*
|
||
|
* region that is currently being displayed is received *
|
||
|
* RETURN: 0 will be returned if contents of the screen region is written *
|
||
|
* to a file successfully *
|
||
|
* GLOBALS: fssScreen - information of the file, will be filled *
|
||
|
* rgscr - information of a particular screen, will be filled *
|
||
|
* ClrTab - information about the colours used, will be filled *
|
||
|
* CONDITIONS:FileName is in the correct format (8:3) *
|
||
|
* rn consists of (x1, y1) and (x2, y2) which are the opposite *
|
||
|
* corner of a rectangular screen region *
|
||
|
* action is 0, 1, or 2 *
|
||
|
* hFlag is either 0 or 1 *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT FARPUBLIC fDumpScreen(FileName, rn, action, n, hFlag) /* [8] */
|
||
|
|
||
|
LPSTR FileName ; /* name of the screen file */
|
||
|
REN FAR *rn ; /* xy-coord of the screen region */
|
||
|
INT action ; /* where the screen to be put in file */
|
||
|
INT n ; /* screen identifier */
|
||
|
INT hFlag ; /* if action window need to be hidden */
|
||
|
{
|
||
|
FD fdScreen = fdNull; /* screen file has not been opened */
|
||
|
INT i ;
|
||
|
|
||
|
if ( action != Append && action != Replace && action != Insert )
|
||
|
return ErrorTrap( InValidAct) ; /* check if action is acceptable [6] [9] */
|
||
|
|
||
|
/* open file for read and write */
|
||
|
|
||
|
if ((fdScreen = M_lopen (FileName,omReadWrite)) == fdNull)
|
||
|
{
|
||
|
/* if file does not exist, create file and header */
|
||
|
if ((fdScreen = M_lcreat(FileName, 0)) == fdNull)
|
||
|
return ErrorTrap(FileAccess) ; /* File Access Error [6] [9] */
|
||
|
CreateHeader() ;
|
||
|
/* add screen to the end of file */
|
||
|
return ErrorTrap(( fAppendSrn(fdScreen, rn, hFlag) ));
|
||
|
}
|
||
|
|
||
|
if ( (i = ValidateFile(fdScreen, TRUE)) != 0 )/* check if the existing [3] */
|
||
|
{ /* file is a valid screen file [2] */
|
||
|
M_lclose(fdScreen) ; /* it is ok eventhough programming */
|
||
|
return ErrorTrap(i) ; /* environment is different */
|
||
|
}
|
||
|
|
||
|
if (fssScreen.cscr == cscrMax)
|
||
|
if ( action != Replace || n <= 0 || n > fssScreen.cscr ) /*[5]*/
|
||
|
{ /* file already consists of max */
|
||
|
M_lclose(fdScreen) ; /* number of screens, cannot add */
|
||
|
return ErrorTrap(SrnFileFul) ; /* any more [4] [6] [9] */
|
||
|
}
|
||
|
|
||
|
if (fssScreen.fst.Env != EnvCur)
|
||
|
{
|
||
|
M_lclose(fdScreen) ;
|
||
|
return ErrorTrap (EnvNotSame) ;
|
||
|
}
|
||
|
|
||
|
if ( (i = fReadTables(fdScreen)) != 0 ) /* read the screen and colour */
|
||
|
{ /* tables */
|
||
|
M_lclose(fdScreen) ;
|
||
|
return ErrorTrap(i) ;
|
||
|
}
|
||
|
|
||
|
if ( (action == Append) || (n > fssScreen.cscr) || (n <= 0) )
|
||
|
return ErrorTrap(fAppendSrn(fdScreen, rn, hFlag) ) ;/* add screen to the end */
|
||
|
/* of the file */
|
||
|
|
||
|
if ( (n == fssScreen.cscr) && (action == Replace) ) /* replace the last */
|
||
|
{ /* screen == add to the end of file */
|
||
|
fssScreen.lfo = rgscr[n-1].lfo ; /* back up 1 screen */
|
||
|
fssScreen.cscr-- ; /* and add the new screen at the */
|
||
|
return ErrorTrap( fAppendSrn(fdScreen, rn, hFlag) ) ; /* end of the file */
|
||
|
}
|
||
|
|
||
|
M_lclose(fdScreen) ; /* get ready to insert/replace a */
|
||
|
return ErrorTrap(fUpdateSrnFile(FileName, rn, action, n, hFlag)) ; /* screen */
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: This is called everytime a request to take a picture of a *
|
||
|
* particular window *
|
||
|
* RETURN: 0 will be returned if contents of the screen region is written *
|
||
|
* to a file successfully *
|
||
|
* GLOBALS: fssScreen - information of the file, will be filled *
|
||
|
* rgscr - information of a particular screen, will be filled *
|
||
|
* ClrTab - information about the colours used, will be filled *
|
||
|
* CONDITIONS:FileName is in the correct format (8:3) *
|
||
|
* hWnd is handle of a window or NULL *
|
||
|
* action is 0, 1, or 2 *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT FARPUBLIC fDumpWindowActivate(FileName, OpenKeys, CloseKeys, action, n, hFlag) /* [7][8] */
|
||
|
|
||
|
LPSTR FileName ; /* name of the screen file */
|
||
|
LPSTR OpenKeys ; /* dokeys string to bring up window */
|
||
|
LPSTR CloseKeys ; /* dokeys string to remove window */
|
||
|
INT action ; /* where the screen to be put in file */
|
||
|
INT n ; /* screen identifier */
|
||
|
INT hFlag ; /* if action window need to be hidden */
|
||
|
{
|
||
|
INT ret;
|
||
|
HWND hWndCallingApp ; /* window of the calling application */
|
||
|
|
||
|
if ( hFlag && !(hWndCallingApp = HideApp()) ) /* application first */
|
||
|
return ErrorTrap(HideWin) ;
|
||
|
|
||
|
if (LoadTESTEVT())
|
||
|
return ErrorTrap(LibLoadErr);
|
||
|
|
||
|
if (OpenKeys)
|
||
|
{
|
||
|
DoKeys(OpenKeys);
|
||
|
|
||
|
/* do some yields to allow keys to get to app and some time for it
|
||
|
** to respond.
|
||
|
*/
|
||
|
yield(); yield(); yield(); yield(); yield();
|
||
|
|
||
|
}
|
||
|
|
||
|
ret = fDumpWindow(FileName,NULL, action, n, FALSE);
|
||
|
if (CloseKeys)
|
||
|
DoKeys(CloseKeys);
|
||
|
|
||
|
if ( hFlag ) /* if window has been hidded */
|
||
|
RestoreApp(hWndCallingApp) ; /* restore it */
|
||
|
|
||
|
FreeTESTEVT();
|
||
|
return NoTrap(ret);
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: This is called everytime a request to take a picture of a *
|
||
|
* particular window *
|
||
|
* RETURN: 0 will be returned if contents of the screen region is written *
|
||
|
* to a file successfully *
|
||
|
* GLOBALS: fssScreen - information of the file, will be filled *
|
||
|
* rgscr - information of a particular screen, will be filled *
|
||
|
* ClrTab - information about the colours used, will be filled *
|
||
|
* CONDITIONS:FileName is in the correct format (8:3) *
|
||
|
* hWnd is handle of a window or NULL *
|
||
|
* action is 0, 1, or 2 *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT FARPUBLIC fDumpWindow(FileName, hWnd, action, n, hFlag) /* [7][8] */
|
||
|
|
||
|
LPSTR FileName ; /* name of the screen file */
|
||
|
HWND hWnd ; /* handle of a window */
|
||
|
INT action ; /* where the screen to be put in file */
|
||
|
INT n ; /* screen identifier */
|
||
|
INT hFlag ; /* if action window need to be hidden */
|
||
|
{
|
||
|
REN rn ; /* store coordinates of the window */
|
||
|
HWND hWndCallingApp = NULL ; /* handle of the calling app's window */
|
||
|
INT i ;
|
||
|
|
||
|
if( !FWinTrapCheckAndTrap( hWnd ) )
|
||
|
{
|
||
|
/* get dimenions of the active window */
|
||
|
if ( (i = fGetWndDim(hWnd, &hWndCallingApp, &hFlag, (REN FAR *)&rn)) != 0 )
|
||
|
return ErrorTrap(i) ;
|
||
|
|
||
|
i = fDumpScreen(FileName, (REN FAR *)&rn, action, n, hFlag) ;
|
||
|
/* take picture of the screen region */
|
||
|
if ( hWndCallingApp ) /* need to restore the calling app's */
|
||
|
RestoreApp(hWndCallingApp) ; /* window if it has been hidden */
|
||
|
|
||
|
return NoTrap(i) ; // No ErrorTrap, already done in fDumpScreen
|
||
|
}
|
||
|
else
|
||
|
return ErrorTrap(InValWHand);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: This is called everytime a request to delete a screen image from*
|
||
|
* the screen file is received *
|
||
|
* RETURN: 0 will be returned if screen is deleted successfully *
|
||
|
* GLOBALS: None *
|
||
|
* CONDITIONS:FileName is name of file in correct format (8.3) *
|
||
|
* nscr is valid (> 0) *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT FARPUBLIC fDelScreen(FileName, nscr)
|
||
|
|
||
|
LPSTR FileName ; /* name of screen file */
|
||
|
INT nscr ; /* screen identifier */
|
||
|
{
|
||
|
FD fdScreen = fdNull ; /* handle to screen file */
|
||
|
LFO tLfo ;
|
||
|
INT i = 0 , j = 0 ;
|
||
|
OFSTRUCT of;
|
||
|
|
||
|
/* prepare screen file for deletion */
|
||
|
if ( (i = ProcessSrnFile(FileName, &fdScreen, nscr, omReadWrite)) != 0 )
|
||
|
return ErrorTrap(i) ;
|
||
|
|
||
|
if ( fssScreen.cscr == nscr && fssScreen.cscr == 1) /* if it is the only */
|
||
|
{ /* screen in file, delete the file */
|
||
|
M_lclose(fdScreen) ;
|
||
|
return ErrorTrap( MOpenFile(FileName, &of, OF_DELETE) ) ;
|
||
|
}
|
||
|
|
||
|
if ( nscr != fssScreen.cscr ) /* if it is not the last screen, move */
|
||
|
{ /* the rest of the screens upward */
|
||
|
tLfo = fssScreen.lfo - rgscr[nscr].lfo ; /* no of bytes to be copied */
|
||
|
i = CpBlock(fdScreen, rgscr[nscr].lfo, fdScreen, rgscr[nscr-1].lfo, tLfo) ;
|
||
|
if ( i != 0 )
|
||
|
{
|
||
|
M_lclose(fdScreen) ;
|
||
|
return ErrorTrap(i) ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fssScreen.cscr-- ; /* a screen has been deleted */
|
||
|
for ( i = 0 ; i < MaxCb ; i++ ) /* number of bytes reomved */
|
||
|
fssScreen.lfo -= (LFO)rgscr[nscr- 1].cb[i] ; /* after the deletion */
|
||
|
|
||
|
i = nscr - 1 ; /* now update the screen tables */
|
||
|
while ( i < fssScreen.cscr )
|
||
|
{
|
||
|
tLfo = 0 ;
|
||
|
for ( j = 0 ; j < MaxCb ; j++)
|
||
|
tLfo += rgscr[i-1].cb[j] ;/* size of the previous screen */
|
||
|
rgscr[i] = rgscr[i+1] ;
|
||
|
if ( i == 0 ) /* if it is the 1st file */
|
||
|
rgscr[i].lfo = sizeof(FSS) ;
|
||
|
else
|
||
|
rgscr[i].lfo = rgscr[i-1].lfo + tLfo ; /* offset to the current */
|
||
|
i++ ; /* screen = offset to the previous */
|
||
|
} /* screen+size of the previous screen */
|
||
|
|
||
|
if ( M_llseek(fdScreen, fssScreen.lfo, smFromBegin) != (LONG2DWORD)fssScreen.lfo )
|
||
|
{ /* go to the end of all screens and */
|
||
|
M_lclose(fdScreen) ; /* get ready to rewrite all tables */
|
||
|
return ErrorTrap(ReadSrnFil) ; /* [6] [9] */
|
||
|
}
|
||
|
|
||
|
i = fReWriteTables (fdScreen) ; /* rewrite all tables to file */
|
||
|
|
||
|
M_lclose(fdScreen) ;
|
||
|
return ErrorTrap(i) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------
|
||
|
// WATTDRVR TRAP ROUTINES
|
||
|
//---------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
// Determine if the window is enabled and visible
|
||
|
INT PRIVATE FBadWindow(hwnd)
|
||
|
HWND hwnd;
|
||
|
{
|
||
|
return(!IsWindowEnabled(hwnd) || !IsWindowVisible(hwnd));
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: This is called by all routines which need to check the validity *
|
||
|
* of a window, generating a trap if the window is invalid. *
|
||
|
* RETURN: TRUE if a trap was generated, FALSE otherwise. *
|
||
|
* GLOBALS: WINTrapCallBack and vWINTrapID and fIgnoreEvntErrTrap *
|
||
|
******************************************************************************/
|
||
|
|
||
|
BOOL PRIVATE FWinTrapCheckAndTrap( HWND hWnd )
|
||
|
{
|
||
|
if( WINTrapCallBack != NULL )
|
||
|
{
|
||
|
if( FBadWindow(hWnd) )
|
||
|
{
|
||
|
WINTrapCallBack(vWINTrapID);
|
||
|
fIgnoreEvntErrTrap = TRUE;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: This is called by WattDrvr when a script includes a *
|
||
|
* WindowMissing Trap, to turn on that trapping support. *
|
||
|
* RETURN: Nothing *
|
||
|
* GLOBALS: WINTrapCallBack and vWINTrapID *
|
||
|
******************************************************************************/
|
||
|
|
||
|
VOID FARPUBLIC WSCR_WindowMissing(INT TrapID, INT Action, TrapCallBack CallBack)
|
||
|
{
|
||
|
if( Action == 0 )
|
||
|
WINTrapCallBack = NULL;
|
||
|
else
|
||
|
{
|
||
|
vWINTrapID = TrapID;
|
||
|
WINTrapCallBack = CallBack;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: This is called by WattDrvr when a script includes *
|
||
|
* Error Trap support, to turn on that trap. *
|
||
|
* RETURN: Nothing *
|
||
|
* GLOBALS: ERRTrapCallBack and vERRTrapID *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT PRIVATE NoTrap( INT n ) // just for cleanup purposes
|
||
|
{
|
||
|
fIgnoreEvntErrTrap = FALSE;
|
||
|
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: This is called by all PUBLIC routines which return values that *
|
||
|
* could be Errors, so that the trap can be generated if required. *
|
||
|
* If a Window trap was already generated, this one will not be. *
|
||
|
* RETURN: The value passed in - to be passed on to the WTD script *
|
||
|
* GLOBALS: ERRTrapCallBack and vERRTrapID and fIgnoreEvntErrTrap *
|
||
|
******************************************************************************/
|
||
|
|
||
|
INT PRIVATE ErrorTrap( INT n )
|
||
|
{
|
||
|
if( ( ERRTrapCallBack != NULL ) && n && !fIgnoreEvntErrTrap )
|
||
|
if( ( n != ImageDiff ) && ( n != SrnSizeDif ) )
|
||
|
ERRTrapCallBack(vERRTrapID);
|
||
|
|
||
|
// if( ( DIFFTrapCallBack != NULL ) && ( (n==ImageDiff)||(n==SrnSizeDif) ) )
|
||
|
// DIFFTrapCallBack(vERRTrapID);
|
||
|
|
||
|
fIgnoreEvntErrTrap = FALSE;
|
||
|
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* PURPOSE: This is called by WattDrvr when a script includes *
|
||
|
* Error Trap support, to turn on that trap. *
|
||
|
* RETURN: Nothing *
|
||
|
* GLOBALS: ERRTrapCallBack and vERRTrapID *
|
||
|
******************************************************************************/
|
||
|
|
||
|
VOID FARPUBLIC WSCR_EventError(INT TrapID, INT Action, TrapCallBack CallBack)
|
||
|
{
|
||
|
if( Action == 0 )
|
||
|
ERRTrapCallBack = NULL;
|
||
|
else
|
||
|
{
|
||
|
vERRTrapID = TrapID;
|
||
|
ERRTrapCallBack = CallBack;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
INT ( APIENTRY *DoKeys)(LPSTR) = NULL;
|
||
|
|
||
|
static HANDLE hTESTEVT = 0;
|
||
|
|
||
|
//*-----------------------------------------------------------------------
|
||
|
//| LoadTESTEVT
|
||
|
//|
|
||
|
//| PURPOSE: Load the TESTEVT DLL library and set the DoKeys pointer
|
||
|
//| to the DoKeys routine.
|
||
|
//|
|
||
|
//|
|
||
|
//*-----------------------------------------------------------------------
|
||
|
INT FARPUBLIC LoadTESTEVT ()
|
||
|
{
|
||
|
// Load the library, and return error if not successful
|
||
|
//----------------------------------------------------------------
|
||
|
hTESTEVT = MLoadLibrary ("TESTEVNT.DLL");
|
||
|
if (hTESTEVT < (HANDLE) 32)
|
||
|
return (LibLoadErr);
|
||
|
|
||
|
// Set DoKeys accordingly, and return success/failure
|
||
|
//----------------------------------------------------------------
|
||
|
(FARPROC) DoKeys = GetProcAddress (hTESTEVT, "DoKeys");
|
||
|
if (!DoKeys)
|
||
|
return (LibLoadErr);
|
||
|
return (NoError);
|
||
|
}
|
||
|
|
||
|
//*-----------------------------------------------------------------------
|
||
|
//| FreeTESTEVT
|
||
|
//|
|
||
|
//| PURPOSE: Free the TESTEVT DLL library and set the DoKeys pointer
|
||
|
//| to NULL.
|
||
|
//|
|
||
|
//|
|
||
|
//*-----------------------------------------------------------------------
|
||
|
VOID FARPUBLIC FreeTESTEVT ()
|
||
|
{
|
||
|
DoKeys = NULL;
|
||
|
FreeLibrary (hTESTEVT);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*==========================================================================
|
||
|
; Purpose:
|
||
|
; Compress a string of bytes; count the repeating bytes;
|
||
|
; remember the number of repeating byte and the value of
|
||
|
; the byte. Stops if the resulting string is longer than
|
||
|
; the original one.
|
||
|
; Entry:
|
||
|
; lpIn points to a string of bytes before compression
|
||
|
; lpOut points to resulting string after the compression
|
||
|
; tb is total number of bytes to be compressed
|
||
|
; Exit:
|
||
|
; ax = number of bytes after compression or -1 if fail to compress
|
||
|
;
|
||
|
; History: 5-20-92 Babakj: Brought from Winplay port
|
||
|
;
|
||
|
==========================================================================*/
|
||
|
|
||
|
UINT PRIVATE CompressBytes (LPBYTE lpIn, LPBYTE lpOut, UINT wLen)
|
||
|
{
|
||
|
LPBYTE lpt1, lpt2;
|
||
|
BYTE cCurrent;
|
||
|
UINT wLeft, i, wNewSize;
|
||
|
|
||
|
lpt1 = lpIn;
|
||
|
lpt2 = lpOut;
|
||
|
wLeft = wLen;
|
||
|
wNewSize = 0;
|
||
|
|
||
|
#define MaxSizeCb 0xFF
|
||
|
|
||
|
while (wLeft != 0)
|
||
|
{
|
||
|
i = 1;
|
||
|
cCurrent = *lpt1++;
|
||
|
wLeft--;
|
||
|
while ((cCurrent == *lpt1) && (wLeft))
|
||
|
{
|
||
|
wLeft--;
|
||
|
lpt1++;
|
||
|
i++;
|
||
|
}
|
||
|
while (i > MaxSizeCb) /* We read over the limit of a byte. */
|
||
|
{
|
||
|
*lpt2++ = MaxSizeCb;
|
||
|
*lpt2++ = cCurrent;
|
||
|
if ((wNewSize += 2) >= wLen)
|
||
|
return ((UINT)-1); /* we are longer than the original. */
|
||
|
i -= MaxSizeCb;
|
||
|
}
|
||
|
*lpt2++ = (BYTE)i;
|
||
|
*lpt2++ = cCurrent;
|
||
|
if ((wNewSize += 2) >= wLen)
|
||
|
return ((UINT)-1);
|
||
|
|
||
|
}
|
||
|
return (wNewSize);
|
||
|
}
|
||
|
|
||
|
/*==========================================================================
|
||
|
; Purpose:
|
||
|
; De-compress a string of bytes to its original form
|
||
|
; Entry:
|
||
|
; lpIn points to a string of bytes before de-compression
|
||
|
; lpOut points to resulting string after de-compression
|
||
|
; tb is total number of bytes to be de-compressed
|
||
|
; Exit:
|
||
|
; ax = number of bytes after decompression
|
||
|
;
|
||
|
; History: 5-20-92 Babakj: Brought from Winplay port
|
||
|
;
|
||
|
==========================================================================*/
|
||
|
|
||
|
UINT FARPUBLIC DeCompressBytes (LPBYTE lpIn, LPBYTE lpOut, UINT wLen)
|
||
|
{
|
||
|
LPBYTE lpt1, lpt2;
|
||
|
register UINT wLeft, i, wNewSize;
|
||
|
BYTE cCurrent;
|
||
|
|
||
|
lpt1 = lpIn;
|
||
|
lpt2 = lpOut;
|
||
|
wLeft = wLen;
|
||
|
wNewSize = 0;
|
||
|
|
||
|
while (wLeft > 0)
|
||
|
{
|
||
|
i = (UINT) *lpt1++;
|
||
|
cCurrent = *lpt1++;
|
||
|
wLeft -= 2;
|
||
|
while (i-- > 0)
|
||
|
{
|
||
|
*lpt2++ = cCurrent;
|
||
|
wNewSize++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (wNewSize);
|
||
|
}
|