Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1636 lines
69 KiB

/*
This is a part of a dynamic link library that runs under Windows 3.00.
Routines in this module are common to the other two modules:
Dump.c - routines for taking, saving, and deleting screen snapshots.
Comp.c - routines for comparing and displaying 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] 03-Mar-1990 AngelaCh: add info for version number
and programming environment
to the header of screen file
[ 2] 12-Mar-1990 AngelaCh: added functions for retrieving
info on version number, total
number of screens in file, and
programming enviornment
[ 3] 14-Mar-1990 AngelaCh: changed the way restoring the
a window (from restore to
show) (bug #40)
[ 4] 16-Mar-1990 AngelaCh: added another parameter to
indication the failure when
fail to open a screen file
[ 5] 20-Mar-1990 AngelaCh: add 300 to all return codes
[ 6] 27-Mar-1990 AngelaCh: moved SwapXY, GetDimensions,
and fGetScreenParams to here
(from module Dump.c)
[ 7] 11-Apr-1990 AngelaCh: Changed error codes from num
const to symbolic constants
[ 8] 13-Mar-1990 AngelaCh: added code to release memory
18-Apr-1990 that was allocated for the
compressed screen image
(bug #32)
moved procedure DiBToBM from
comp.c to here
[ 9] 18-Apr-1990 AngelaCh: Create function ReadDibBytes
[10] 20-Apr-1990 AngelaCh: moved PaletteSize, GetDiBMap,
fWriteScreen, and fAddScreen
to here (from module Dump.c)
[11] 20-Apr-1990 AngelaCh: add parameter fFlag to proc
GetDiBMap, fWriteScreen, and
and fAddScreen to determine
if image is written to a
screen file or DIB file
[12] 25-Apr-1990 AngelaCh: after calling GetWindowRect,
subtract 1 pixel from the
lower-right corner - it seems
that GetWindowRect returns 1
pixel too many to the right
and on the bottom
[13] 04-May-1990 AngelaCh: change error code for invalid
mode (from 4 to InValSrnMd
bug #63)
[14] 03-Jul-1990 AngelaCh: added support for Video 7
and 8515/a (bug #64)
[15] 07-Aug-1991 DavidSc: added generic screen size
support
******************************************************************************/
#include "windows.h"
#include <port1632.h>
#include "dump.h"
VM VideoModeTab[vmdMax+1] = /* Built-in video modes - from old method */
{
{ 0 , 0 , 0L } , // This is an invalid video mode - a placeholder
{ 320 , 200 , 4L } ,
{ 640 , 200 , 2L } ,
{ 320 , 200 , 16L } ,
{ 640 , 200 , 16L } ,
{ 640 , 350 , 2L } ,
{ 640 , 350 , 4L } ,
{ 640 , 350 , 16L } ,
{ 640 , 480 , 2L } ,
{ 640 , 480 , 16L } ,
{ 320 , 200 , 20L } , /*[14]*/
{ 640 , 400 , 20L } , /*[14]*/
{ 640 , 480 , 20L } , /*[14]*/
{ 720 , 348 , 2L } ,
{ 720 , 512 , 20L } , /*[14]*/
{ 720 , 540 , 16L } ,
{ 800 , 600 , 16L } ,
{ 800 , 600 , 20L } ,
{ 1024 , 768 , 16L } ,
{ 1024 , 768 , 256L } ,
{ 1024 , 768 , 20L } /*[14]*/
};
/******************************************************************************
* initialization function for the library in Windows *
******************************************************************************/
BOOL LibMain( HINSTANCE hInstance, DWORD fdwReason, LPVOID lpvReserved ) {
return 1 ;
}
/******************************************************************************
* PURPOSE: Calculate the palette size in bytes by looking at the number of *
* bits per pixel(biBitCount) or the number of colour used *
* (biClrUsed) infomration from the header of a DIBitmap *
* RETURN: Palette size in number of bytes *
* GLOBALS: None *
* CONDITIONS:bi is pointing to the header of a device-independent bitmap *
******************************************************************************/
WORD PRIVATE PaletteSize(bi) /* [10] */
LPBITMAPINFOHEADER bi ; /* header of the DIBitmap */
{
if (bi->biClrUsed != 0) /* if biClrUsed = 0, max number of */
return(((WORD)bi->biClrUsed) * sizeof(RGBQUAD)) ; /* colour available */
/* will be used */
if ( bi->biBitCount > 8 ) /* bit count per pixel = 24 */
return 0 ; /* the DIBitmap has no table */
else
return ((1 << bi->biBitCount) * sizeof(RGBQUAD)) ;
}
/******************************************************************************
* PURPOSE: Create a logical color palette from the color table of a Device-*
* Independent Bitmap *
* RETURN: Handle to a logical color palette *
* GLOBALS: Information about the color table: ClrTab & fssScreen.ClrUse *
* CONDITIONS:Value of ClrTab & fssScreen.ClrUse are knwon *
******************************************************************************/
HPALETTE PRIVATE CreatePalFromDIB () /* [14] */
{
LOCALHANDLE hMem ; /* handle to local heap */
NPLOGPALETTE pPal ; /* handle to logical color palette */
HPALETTE lhPal = NULL ; /* handle to the logical color pal */
RGBQUAD FAR *pRgb ; /* pointer to color structure */
WORD nNumColors ;
INT i ;
pRgb = (RGBQUAD FAR *)(ClrTab) ; /* pRgb is now pointing to col table */
nNumColors = fssScreen.ClrUse ; /* size of color table */
hMem = LocalAlloc (LMEM_MOVEABLE | LMEM_DISCARDABLE | LMEM_ZEROINIT,
(sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * nNumColors))) ;
if ( !hMem ) /* out of memory */
return NULL ;
pPal = (NPLOGPALETTE) LocalLock (hMem) ;
pPal->palVersion = PalVer ; /* Windows version number for palette */
pPal->palNumEntries = nNumColors ; /* number of palette entries */
for (i = 0 ; i < nNumColors ; i++) /* fill in the palette entries from */
{ /* the DIB table */
pPal->palPalEntry[i].peRed = pRgb[i].rgbRed ;
pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen ;
pPal->palPalEntry[i].peBlue = pRgb[i].rgbBlue ;
} /* palPalEntry[i].peFlags = (BYTE) 0; */
lhPal = CreatePalette((LPLOGPALETTE)pPal) ; /* create a logical palette */
if ( LocalUnlock(hMem) || LocalFree(hMem) )
return (NULL) ;
else
return lhPal ;
}
/******************************************************************************
* PURPOSE: Create a logical color palette for the current display device *
* RETURN: Handle to a logical color palette *
* GLOBALS: None *
* CONDITIONS: *
******************************************************************************/
HPALETTE PRIVATE MakePal () /* [14] */
{
LOCALHANDLE hMem ;
NPLOGPALETTE pLogPal ; /* ptr to area for logical color pal */
HPALETTE lhPal ; /* handle to a logical color palette */
WORD i ;
/* allocate memory for logical palette */
hMem = LocalAlloc (LMEM_MOVEABLE | LMEM_DISCARDABLE | LMEM_ZEROINIT,
(sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * (MaxPal)))) ;
if ( !hMem ) /* out of memory */
return NULL ;
pLogPal = (NPLOGPALETTE) LocalLock (hMem) ;
pLogPal->palVersion = PalVer ; /* Windows version number for palette */
pLogPal->palNumEntries = MaxPal ; /* number of palette entries */
for ( i = 0 ; i < MaxPal ; i++ ) /* fill in intensities for all */
{ /* palette entry colors */
*((WORD *)(&pLogPal->palPalEntry[i].peRed)) = i ;
pLogPal->palPalEntry[i].peFlags = PC_EXPLICIT ;
} /* palPalEntry[i].peBlue = 0 */
lhPal = CreatePalette((LPLOGPALETTE)pLogPal) ; /* create logical color */
/* palette based on info in LOGPALETTE */
if ( LocalUnlock(hMem) || LocalFree(hMem) )
return (NULL) ;
else
return lhPal ;
}
/******************************************************************************
* PURPOSE: Swap values of two integers *
* RETURN: integers whose values have been exchanged *
* GLOBALS: None *
* CONDITIONS:None *
******************************************************************************/
VOID PRIVATE SwapXY(x, y) /* [6] */
INT FAR *x ; /* pointing to the integers whose */
INT FAR *y ; /* value will be exchanged */
{
INT i ;
i = *x ;
*x = *y ;
*y = i ;
}
/******************************************************************************
* PURPOSE: Calculate the exact dimension of a line given the starting and *
* end ing coordinates *
* RETURN: the starting coordinate and the size of the line *
* GLOBALS: None *
* CONDITIONS:i is the starting coordinate *
* j is the ending coordinate *
* k is the max value of the ending coordinate *
* 0 is assume to be the min value of the starting coordinate *
******************************************************************************/
VOID PRIVATE GetDimensions(i, j, k) /* [6] */
INT FAR *i ; /* starting coordinate */
INT FAR *j ; /* ending coordinate */
INT k ; /* max value of coordinate */
{
INT m, n ;
m = *i ; /* m = starting coordinate */
n = *j ; /* n = ending coordinate */
if ( m > n ) /* starting coord > ending coord */
SwapXY(&m, &n) ; /* exchange their values */
if ( n <= 0 || n > k ) /* ending x-coord out of range */
n = k ; /* set it to max */
if ( m < 0 || m >= k ) /* starting x-coord out of range */
m = 0 ; /* set it to min */
if ( m == n ) /* starting x-coord = ending x-coord */
m = 0 ; /* set starting x-coord to min */
*i = m ; /* starting coordinate */
*j = n - m + 1 ; /* width of the region */
}
/******************************************************************************
* PURPOSE: Determine the display mode of the system the way it used to *
* RETURN: The display mode if it supported; the max column and row size *
* of the current screen mode will also be returned *
* GLOBALS: none *
* CONDITIONS:none *
******************************************************************************/
VMD PRIVATE OLDDetermineMode(MaxCol, MaxRow)
INT FAR *MaxCol ; /* max column size */
INT FAR *MaxRow ; /* max row size */
{
VMD vd = vmdNull ;
INT i ;
VM vm;
vd = GetCurrentVideoMode( &vm );
if( vd == vmdNull )
return vmdNull;
/* vd = vmdGeneric now; if no match is found in table, use this mode */
for ( i = 1; i < vmdMax && vd == vmdGeneric; i++ )
if ( VideoModesEqual( vm, VideoModeTab[i] ) )
vd = (VMD)(i) ; /* found video mode */
*MaxCol = vm.XresMAX ; /* max column size */
*MaxRow = vm.YresMAX ; /* max row size */
return (vd) ;
}
/******************************************************************************
* PURPOSE: Determine the display mode of the system, given the way it *
* used to be stored. *
* RETURN: nothing *
* GLOBALS: VideoModeTab *
* CONDITIONS:oldVd is a valid entry in the table *
******************************************************************************/
VOID FARPUBLIC WhatIsNewMode(VMD oldVd, VM FAR *vdNew)
{
if ( (oldVd < vmdMax) && (oldVd >= 0) )
{
*vdNew = VideoModeTab[oldVd];
if ( 20 == vdNew->PaletteSizeMAX )
vdNew->PaletteSizeMAX = 256;
}
}
/******************************************************************************
* PURPOSE: Determine the display mode of the system *
* RETURN: The display mode if it supported; the max column and row size *
* of the current screen mode will also be returned *
* GLOBALS: fssScreen.fst.Ver *
* CONDITIONS:none *
******************************************************************************/
VMD FARPUBLIC DetermineMode(MaxCol, MaxRow)
INT FAR *MaxCol ; /* max column size */
INT FAR *MaxRow ; /* max row size */
{
VMD vd = vmdNull ;
VM vm ;
if (fssScreen.fst.Ver == OldVer)
return (OLDDetermineMode(MaxCol, MaxRow) );
vd = GetCurrentVideoMode( &vm );
*MaxCol = vm.XresMAX;
*MaxRow = vm.YresMAX;
return (vd) ;
}
/******************************************************************************
* PURPOSE: Determine the number of colours in the screen's generic display *
* mode *
* RETURN: The number of colours supported *
* GLOBALS: none *
* CONDITIONS:none *
******************************************************************************/
LONG FARPUBLIC DetermineColours(VOID)
{
VM vm ;
GetCurrentVideoMode( &vm );
return (vm.PaletteSizeMAX) ;
}
VMD FARPUBLIC GetCurrentVideoMode( VM FAR *vm )
{
HDC hIC ;
VMD vmd = vmdGeneric;
INT clr;
hIC = CreateIC("Display", NULL, NULL, NULL) ; /* create an info context */
if ( hIC )
{
vm->XresMAX = GetDeviceCaps(hIC, HORZRES) ;
vm->YresMAX = GetDeviceCaps(hIC, VERTRES) ;
// The following is the TRUE number of colours that can be
// represented by the monitor, not just the number which Windows
// reserves. This can be different from return of NUMCOLORS.
// (EG: often 256 are available, but windows reserves only 20)
// Note: ZERO means more than 2^32 colours can be represented
vm->PaletteSizeMAX =
1L << ( GetDeviceCaps(hIC, PLANES) * GetDeviceCaps(hIC, BITSPIXEL) ) ;
clr = GetDeviceCaps(hIC, NUMCOLORS) ;/* number of device colours */
IsPalDev = GetDeviceCaps(hIC, RASTERCAPS) & RC_PALETTE ; /* is the */
/* current display device a */
/* palette device? [14] */
if ( clr == 20 && !IsPalDev ) /* it is not a palette device */
vmd = vmdNull ; /* but number of colour is */
/* not supported [14] */
DeleteDC(hIC) ;
}
else
{
vm->XresMAX = 0;
vm->YresMAX = 0;
vm->PaletteSizeMAX = 0L;
vmd = vmdNull;
}
return vmd ;
}
BOOL FARPUBLIC VideoModesEqual( VM vm1, VM vm2 )
{
if( ( vm1.XresMAX == vm2.XresMAX ) &&
( vm1.YresMAX == vm2.YresMAX ) &&
( vm1.PaletteSizeMAX == vm2.PaletteSizeMAX ) )
return TRUE;
else
return FALSE;
}
/******************************************************************************
* PURPOSE: Calculate the width and height of the screen region *
* RETURN: 0 will be returned if current video mode is supported *
* *rn will be filled with starting coord, width, and height *
* GLOBALS: fssScreen (fssScreen.vmd field will be filled) *
* CONDITIONS:(rn->col, rn->row) and (rn->width, rn->height) are 2 opposite *
* corners of a rectangular region *
******************************************************************************/
INT PRIVATE fGetScreenParams(rn) /* [6] */
REN FAR *rn ; /* pointing to a screen region */
{
INT ColMax ; /* max column bases on screen mode */
INT RowMax ; /* max row bases on screen mode */
VMD vd ;
VM vmCurr ;
vd = DetermineMode(&ColMax, &RowMax) ; /* check the current video mode */
ColMax--;
RowMax--;
if ( vd == vmdNull )
return InValSrnMd ; /* [5] [7] */
if ( fssScreen.cscr == 0 )
fssScreen.vmd = vd ; /* record the video mode */
else
{
/* if current video mode not match what was recorded [13] */
GetCurrentVideoMode( &vmCurr );
if ( !VideoModesEqual( vmCurr, fssScreen.vmG ) )
return InValSrnMd ;
}
/* set column size */
GetDimensions(&(rn->col), &(rn->width), ColMax) ;
/* set row size */
GetDimensions(&(rn->row), &(rn->height), RowMax) ;
return NoError ; /* [7] */
}
/******************************************************************************
* PURPOSE: Check if the file is a valid screen file by checking the 1st *
* 3 bytes of the file *
* RETURN: True if it is a valid screen file *
* GLOBALS: fssScreen, consisting of information about file, which will be *
* filled after this function call *
* CONDITIONS:fd is a valid file handle *
* action is valid action (FALSE, TRUE) *
******************************************************************************/
INT PRIVATE ValidateFile(fd, action) /* [1], [2] */
FD fd ; /* file handle */
BOOL action ; /* validate version number or not */
{
M_llseek(fd, 0L, smFromBegin); /* go to the beginning of the file */
// Read fst
M_lread (fd, (LPSTR) &fssScreen.fst.FileId, 3);
M_lread (fd, (LPSTR) &fssScreen.fst.Ver, 1);
M_lread (fd, (LPSTR) &fssScreen.fst.Env, 1);
// read vmd
M_lread (fd, (LPSTR) &fssScreen.vmd, 1);
// read BitCount
M_lread (fd, (LPSTR) &fssScreen.BitCount, 2);
// read ClrUse
M_lread (fd, (LPSTR) &fssScreen.ClrUse, 2);
// read cscr
M_lread (fd, (LPSTR) &fssScreen.cscr, 2);
// read lfo
M_lread (fd, (LPSTR) &fssScreen.lfo, 4);
// read vmG
M_lread (fd, (LPSTR) &fssScreen.vmG.XresMAX, 2);
M_lread (fd, (LPSTR) &fssScreen.vmG.YresMAX, 2);
M_lread (fd, (LPSTR) &fssScreen.vmG.PaletteSizeMAX, 4);
// read reserved1
M_lread (fd, (LPSTR) &fssScreen.reserved1, 4);
// read reserved2
M_lread (fd, (LPSTR) &fssScreen.reserved2, 4);
/* the first 3 character in file is expected to be '@@@' */
if (fssScreen.fst.FileId[0] != '@' || fssScreen.fst.FileId[1] != '@'
|| fssScreen.fst.FileId[2] != '@')
return InValidFil ; /* [5] [7] */
if ( action) /* validate version of screen file [2]*/
if ( ( (INT)fssScreen.fst.Ver != VerCur) && /* but be bckwd compat with ver 2 [15] */
( (INT)fssScreen.fst.Ver != OldVer) ) /* screen file is in unsupported */
return OFileForm ; /* format [1] [5] [7] */
if ( (INT)fssScreen.fst.Ver == OldVer)
WhatIsNewMode( fssScreen.vmd, &(fssScreen.vmG) );
// M_llseek(fd, 10L, smFromBegin); /* go to end of old header */
return NoError ; /* [7] */
}
/******************************************************************************
* PURPOSE: Open a file and read in the first several bytes of information *
* RETURN: Handle to the file if it is a valid screen file *
* GLOBALS: None *
* CONDITIONS:Name of file is assumed in the correct format (8:3) *
* oMode is valid file access mode *
* action is valid action (FALSE, TRUE) *
******************************************************************************/
FD PRIVATE fReadHeader(FileName, oMode, action, failflag) /* [2] [4] */
LPSTR FileName ; /* name of the screen file */
BYTE oMode ; /* file access mode */
BOOL action ; /* [2] */
INT FAR *failflag ; /* [4] */
{
FD fd = fdNull ; /* Currently opened dump file. */
/* open file for writing */
if ( (fd = M_lopen(FileName,oMode)) == fdNull )
*failflag = FileAccess ; /* [7] */
else
if ( (*failflag = ValidateFile(fd, action)) != 0 ) /* is it a valid [2] */
{ /* screen file? [4] */
M_lclose(fd) ;
fd = fdNull ; /* invalid file format */
}
return fd ;
}
/******************************************************************************
* PURPOSE: Read the screen and colour tables that are stored in a valid *
* screen file *
* RETURN: 0 will be returned and contents of the tables (rgscr & ClrTab) *
* will be filled if no error is detected *
* GLOBALS: fssScreen, rgscr, and ClrTab *
* CONDITIONS:fd is a valid file handle *
******************************************************************************/
INT PRIVATE fReadTables(fd)
FD fd ; /* handle to the file */
{
WORD fl;
INT i, j;
/* move to the beginning of the screen tables */
if (M_llseek(fd, fssScreen.lfo, smFromBegin) != (LONG2DWORD)(fssScreen.lfo))
return InValSrnMd ; /* [5] [7] */
for (i = 0 ; i < fssScreen.cscr ; i++)
{
for (j = 0 ; j < MaxCb ; j++)
{
if (M_lread (fd, &rgscr[i].cb[j], 2) != 2)
return RWSrnTable;
}
for (j = 0 ; j < MaxCbComp ; j++)
{
if (M_lread (fd, &rgscr[i].cbComp[j], 2) != 2)
return RWSrnTable;
}
if (M_lread (fd, &rgscr[i].ren.col, 2) != 2)
return RWSrnTable;
if (M_lread (fd, &rgscr[i].ren.row, 2) != 2)
return RWSrnTable;
if (M_lread (fd, &rgscr[i].ren.width, 2) != 2)
return RWSrnTable;
if (M_lread (fd, &rgscr[i].ren.height, 2) != 2)
return RWSrnTable;
if (M_lread (fd, &rgscr[i].lfo, 4) != 4)
return RWSrnTable;
}
fl = (WORD) fssScreen.ClrUse ; /* read colour table */
for (i = 0 ; i < fl ; i++)
{
if (M_lread (fd, (LPSTR) &ClrTab [i], 1) != 1)
return RWColTable ; /* [5] [7] */
}
return NoError ; /* here if no error occurs when [7] */
} /* reading all the tables */
/******************************************************************************
* PURPOSE: Open, check, and prepare a screen file for further action *
* RETURN: 0 will be returned if file is now ready for further action *
* GLOBALS: fssScreen and rgscr *
* CONDITIONS:FileName is in correct format (8:3) *
* oMode is valid file access mode *
******************************************************************************/
INT PRIVATE ProcessSrnFile(FileName, fd, n, oMode)
LPSTR FileName ; /* name of file to be processed */
FD FAR *fd ; /* handle to file */
INT n ; /* screen idenifier */
BYTE oMode ;
{
FD lfd = fdNull ;
INT i = 0 ;
if ( n <= 0 ) /* screen identifer invalid */
return InValSrnId ; /* [5] [7] */
if ( (lfd = fReadHeader(FileName, oMode, TRUE, &i)) == fdNull ) /* [2] */
return i ; /* file access error [4] */
if ( fssScreen.cscr < n ) /* desire screen does not exist */
i = InValSrnId ; /* [5] [7] */
if ( i == 0 )
i = fReadTables(lfd) ; /* read in screen & colour tables */
/* position the file, so that the current position is at the
beginning of the screen info */
if ( i == 0 )
if (M_llseek(lfd, rgscr[n-1].lfo, smFromBegin) != (LONG2DWORD)(rgscr[n-1].lfo))
i = ReadSrnFil ; /* [5] [7] */
if ( i == 0 ) /* if no error is deteccted, */
*fd = lfd ; /* return the file handle */
else
M_lclose (lfd) ;
return i ;
}
/******************************************************************************
* PURPOSE: Hide the window of the application that calls this DLL and send *
* message to repaint all other applications *
* RETURN: handle of the calling app's window will be returned if window is*
* hidden successfully; otherwise, Null will be returned *
* GLOBALS: None *
* CONDITIONS:None *
******************************************************************************/
HWND PRIVATE HideApp()
{
HWND hWndCallingApp ; /* handle of the calling app's window */
HWND hWndNextApp; /* handle of other app's window */
// BabakJ: API changed
// hWndCallingApp = GetActiveWindow() ;/* Get the handle of the window that */
hWndCallingApp = GetForegroundWindow() ;/* Get the handle of the window that */
if ( hWndCallingApp ) /* calls this DLL and hide its */
{ /* window; then repaint the windows */
ShowWindow(hWndCallingApp,SW_HIDE) ; /* of all other applications */
if ( hWndNextApp = GetWindow(GetDesktopWindow(),GW_CHILD) )
do {
InvalidateRect(hWndNextApp,NULL,TRUE);
UpdateWindow(hWndNextApp);
} while (hWndNextApp = GetWindow(hWndNextApp,GW_HWNDNEXT));
}
return (hWndCallingApp) ;
}
/******************************************************************************
* PURPOSE: Restore the calling application's window that has previously *
* been hidden *
* RETURN: None *
* GLOBALS: None *
* CONDITIONS:hWndCallingApp is a valid handle of a window *
******************************************************************************/
VOID PRIVATE RestoreApp(hWndCallingApp)
HWND hWndCallingApp ; /* handle of the calling app's window */
{
ShowWindow(hWndCallingApp,SW_SHOW);/* [3] */
}
/******************************************************************************
* PURPOSE: calling API function to find out the dimension of a particular *
* window *
* RETURN: 0 if desired infomation is obtained successfully *
* GLOBALS: None *
* CONDITIONS:hActive is a handle of a window (can be NULL) *
******************************************************************************/
INT PRIVATE fGetWndDim(hActive, hCalling, hFlag, rn)
HWND hActive ; /* handle of the active window */
HWND FAR *hCalling ; /* handle of the calling app's wnd */
INT FAR *hFlag ; /* if need to hide the calling app's wnd */
REN FAR *rn ; /* coord of the active window */
{
HWND hWnd = NULL ;
if ( !hActive ) /* if value of the handle is unknown */
{
if ( *hFlag ) /* need to hide the window of the */
{ /* calling app first */
if ( !(hWnd = HideApp ()) )
return HideWin ;
*hFlag = FALSE ; /* no need to hide any more window */
*hCalling = hWnd ; /* save the handle of the calling */
} /* application */
// BabakJ: API changed
// hActive = GetActiveWindow () ; /* then get the handle of the next */
hActive = GetForegroundWindow () ; /* then get the handle of the next */
} /* active window */
GetWindowRect(hActive, (LPRECT)rn) ;/* get the measurement of the window */
rn->width-- ; /* [12] */
rn->height-- ; /* [12] */
return NoError ;
}
/******************************************************************************
* PURPOSE: Obtain a bitmap which represents what is currently on screen *
* RETURN: Handle of the bitmap *
* GLOBALS: None *
* CONDITIONS:(x, y) is assume to be the upper-left of the screen region *
* width and height of the screen region are assume to be correct *
* (non-zero) *
******************************************************************************/
HBITMAP PRIVATE GetBMap(x, y, width, height)
INT x ; /* starting x-coord */
INT y ; /* starting y-coord */
INT width ; /* width of screen region */
INT height ; /* height of screen region */
{
HDC hDC ; /* handle of a device context */
HDC hMemDC ; /* handle of a memory device context */
HBITMAP hbm ; /* handle of a bitmap */
hDC = CreateDC("DISPLAY", NULL, NULL, NULL) ;/* device context for screen */
hMemDC = CreateCompatibleDC(hDC) ;
hbm = CreateCompatibleBitmap(hDC, width, height) ;
if ( hbm ) /* an empty bitmap is created */
{ /* copy the image of the screen */
SelectObject(hMemDC, hbm) ; /* region to it */
BitBlt(hMemDC, 0, 0, width, height, hDC, x, y, SRCCOPY) ;
}
DeleteDC (hDC) ; /* release resources before return */
DeleteDC (hMemDC) ;
return hbm ;
}
/******************************************************************************
* PURPOSE: Read om a Device-dependent bitmap from a screen file *
* RETURN: Size of the Device-Independent bitmap if succeed *
* GLOBALS: fssScreen *
* CONDITIONS:lpCall pointer to memory location capable of receiving all data *
* fd is a valid file handle *
* width and height of the bitmap are valid (non-zero) *
* cb is the size of the bitmap stored in file (non-zero) *
* IsComp tells if the bitmap image has been compressed or not *
* ****************************************************************************/
WORD PRIVATE ReadDibBytes(lpCall, fd, width, height, cb, IsComp) /* [9] */
LPSTR lpCall ; /* byte pointer to receive bytes */
FD fd ; /* handle to the screen file */
INT width ; /* y-coord of the upper-left of bitmap */
INT height ; /* height of the bitmap */
WORD cb ; /* size of the DiBitmap */
INT IsComp ; /* has compression be performed? */
{
LPBITMAPINFOHEADER lpbi ; /* point to the DiBitmap header */
BITMAPINFOHEADER bi ; /* header of the DiBitmap */
LPSTR lp ;
GLOBALHANDLE hGMem ;
LPSTR lpIn ;
INT i ;
/* create the necessary bitmap header bases on the information
stored in the screen file */
bi.biSize = sizeof(BITMAPINFOHEADER) ;
bi.biWidth = width ; /* width of bitmap */
bi.biHeight = height ; /* height of bitmap */
bi.biPlanes = dbiPlanes ; /* number of planes - must be 1 */
bi.biBitCount = (WORD) fssScreen.BitCount ;
bi.biCompression = (DWORD)MaxComp ; /* Max compression style */
bi.biXPelsPerMeter = 0 ;
bi.biYPelsPerMeter = 0 ;
bi.biClrUsed = (DWORD) fssScreen.ClrUse/sizeof(RGBQUAD) ;
bi.biClrImportant = 0 ;
lpbi = (LPBITMAPINFOHEADER) lpCall ;
lp = (LPSTR)lpbi + (WORD)bi.biSize ;/* lp is at the beginning of the */
/* colour table */
for (i = 0 ; i < fssScreen.ClrUse ; i++ ) /* put the colour table */
*(lp++) = ClrTab[i] ; /* in place */
i = 0 ;
/* lp is now in place to receive the bytes of the bitmap from file */
if ( !IsComp ) /* compression hasn't been performed */
{ /* bitmap is what stored in file */
// BabakJ: added (UINT) cast
if ( M_lread(fd, lp, cb) != (UINT)cb )
i = ReadSrnFil ;
}
else /* allocate memory for reading */
{ /* the compressed image of bitmap */
hGMem = GlobalAlloc (GMEM_MOVEABLE | GMEM_DISCARDABLE, (DWORD)cb) ;
if ( !hGMem ) /* no memory is allocated */
i = OutOMemory ;
else
{
lpIn = GlobalLock(hGMem) ;
if ( M_lread(fd, lpIn, cb) != (UINT)cb )
{
GlobalUnlock(hGMem) ;
GlobalFree(hGMem) ;
i = ReadSrnFil ;
}
else /* decompress bytes that are stored */
{ /* in file; resulting number of bytes */
cb = DeCompressBytes(lpIn, lp, cb) ; /* number of bytes after */
/* decompression=sizeof bitmap */
if ( GlobalUnlock(hGMem) )/* release memory for the compressed */
i = RelMemory ; /* screen [8] */
if ( GlobalFree(hGMem) )
i = RelMemory ;
} /* if M_lread */
} /* if ( !hGMem ) */
} /* if ( !IsComp ) */
if ( i )
return 0 ; /* unsucessfully reading screen */
else
{
bi.biSizeImage = (DWORD)cb ; /* cb = size of the bitmap */
*lpbi = bi ; /* put the head in place */
return cb ;
}
}
/******************************************************************************
* PURPOSE: Create a bitmap in device-dependent format from a device- *
* independent bitmap *
* RETURN: Hanle of the device-independent bitmap if succeed *
* GLOBALS: fssScreen *
* CONDITIONS:fd is a valid file handle *
* width and height of the bitmap are valid (non-zero) *
* cb is the size of the bitmap stored in file (non-zero) *
* IsComp tells if the bitmap image has been compressed or not *
******************************************************************************/
HBITMAP PRIVATE DiBToBM(fd, width, height, cb, IsComp)
FD fd ; /* handle to the screen file */
INT width ; /* y-coord of the upper-left of bitmap */
INT height ; /* height of the bitmap */
WORD cb ; /* size of the DiBitmap */
INT IsComp ; /* has compression be performed? */
{
LPBITMAPINFOHEADER lpbi ; /* point to the DiBitmap header */
GLOBALHANDLE hGlobalMemory ; /* handle of a global memory area */
HBITMAP hbm ; /* handle of the DDBitmap */
HPALETTE hPalO ; /* handle of the existing color pal */
LPSTR lp ;
HDC hDC ;
LONG fb ;
INT i ;
/* allocate space for the DiBitmap: header + colour table + bitmap */
if ( !IsComp ) /* compression hasn't been performed */
fb = sizeof(BITMAPINFOHEADER) + fssScreen.ClrUse + cb ;
else
fb = sizeof(BITMAPINFOHEADER) + fssScreen.ClrUse + MaxSize ;
hGlobalMemory = GlobalAlloc (GMEM_MOVEABLE | GMEM_DISCARDABLE, fb) ;
if ( !hGlobalMemory ) /* no memory is allocated */
return NULL;
/* read in the bitmap; fail if no bytes were read */
lpbi = (LPBITMAPINFOHEADER) GlobalLock (hGlobalMemory) ;
if ( !(ReadDibBytes((LPSTR)lpbi, fd, width, height, cb, IsComp)) ) /* [9] */
return NULL ;
lp = (LPSTR)lpbi + (WORD)sizeof(BITMAPINFOHEADER) + (WORD)fssScreen.ClrUse ;
hDC = GetDC(NULL) ; /* obtain a device context */
if ( IsPalDev ) /* this is a palette device, need to */
{ /* load all available colours [14] */
hPalO = SelectPalette(hDC, hPal, FALSE) ;
RealizePalette(hDC) ;
}
hbm = CreateDIBitmap(hDC, lpbi, (LONG)CBM_INIT, lp, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS) ;
if ( IsPalDev )
SelectPalette(hDC, hPalO, FALSE) ; /* restore old color palette [14]*/
ReleaseDC(NULL, hDC) ; /* release memory before return */
if ( GlobalUnlock(hGlobalMemory) ) /* if there is problem in releasing */
return NULL ; /* memories */
if ( GlobalFree(hGlobalMemory) )
return NULL ;
return hbm ;
}
/******************************************************************************
* PURPOSE: Convert a device-dependent bitmap to device-independent and out-*
* put the contents of the device-independent bitmap to a file*
* RETURN: 0 will be returned if the conversion is done and contents is *
* written to a file successfully *
* number of bytes written to file will be returned via variable cb*
* GLOBALS: fssScreen - ClrUse field of fssScreen will be filled in *
* ClrTab - contents of the colour table, will be filled in *
* CONDITIONS:fd is a valid file handle *
* hbm is a valid handle to a device-dependent bitmap *
* bm consists of the valid information about the device-dep bitmap*
* fFlag is pointer to an integer (>= 0); if *fFlag = 0, screen *
* image is written to a screen file; otherwise, it will be *
* written as a Device-Independent Bitmap *
******************************************************************************/
INT PRIVATE GetDiBMap(fd, hbm, bm, cb, IsComp, fFlag) /* [10] [11] */
FD fd ; /* handle of the screen file */
HBITMAP hbm ; /* handle of the DDBitmap */
LPBITMAP bm ; /* consists of info about the bitmap */
WORD FAR *cb ; /* total number of bytes written */
INT FAR *IsComp ; /* will the bytes been compressed? */
INT FAR *fFlag ; /* type of output file [11] */
{
BITMAPINFOHEADER bi ;
LPBITMAPINFOHEADER lpbi ; /* will point to the DiBitmap */
GLOBALHANDLE hdib ; /* handle of the global memory */
GLOBALHANDLE hRe ; /* handle of the global memory */
HPALETTE hPalO ; /* handle of a existing color palette */
HDC hDC ; /* handle of a device context */
WORD hb ;
DWORD fb ;
LPSTR lp ;
INT i, j;
WORD fl;
/* create the header of a device */
bi.biSize = sizeof(BITMAPINFOHEADER) ; /* independent bitmap */
bi.biWidth = bm->bmWidth ; /* width of bitmap */
bi.biHeight = bm->bmHeight ; /* height of bitmap */
bi.biPlanes = dbiPlanes ; /* number of planes - must be 1 */
bi.biBitCount = fssScreen.BitCount ;/* no of bit per pixel */
bi.biCompression = (DWORD)MaxComp ; /* Max compression style */
bi.biSizeImage = bi.biHeight*((((bi.biBitCount*bi.biWidth)+31)&(~31))>>3) ; /*[14]*/
bi.biXPelsPerMeter = 0 ;
bi.biYPelsPerMeter = 0 ;
bi.biClrUsed = 0 ; /* filled by function GetDIBits */
bi.biClrImportant = 0 ;
/* allocate space for the header of the DIBitmap: bi + array of colours */
fb = (DWORD)bi.biSize+(DWORD)MaxPal*sizeof(RGBQUAD) ;
hdib = GlobalAlloc(GMEM_MOVEABLE | GMEM_DISCARDABLE, fb) ;
if ( !hdib ) /* no space has been allocated */
return OutOMemory ; /* signal Out of Memory [5] [7] */
lpbi = (LPBITMAPINFOHEADER) GlobalLock (hdib) ; /* protect the global heap */
*lpbi = bi ; /* copy contents of the bitmap header */
/* call GetDIBits with a NULL lpBits param, to fill the biSizeImage field */
hDC = GetDC(NULL) ;
if ( IsPalDev ) /* this is a palette device, need to */
{ /* load all available colours [14] */
hPalO = SelectPalette(hDC, hPal, FALSE) ;
RealizePalette(hDC) ;
}
hb = GetDIBits(hDC, hbm, 0, (WORD)bi.biHeight, NULL, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS) ;
if (hb == 0 && bi.biSizeImage == 0) /* GetDIBits fails */
{
GlobalUnlock(hdib) ;
GlobalFree(hdib) ;
if ( IsPalDev ) /* [14] */
SelectPalette(hDC, hPalO, FALSE) ; /* restore old palette */
ReleaseDC(NULL, hDC) ;
return CreateDIB ; /* [5] [7] */
}
bi = *lpbi ; /* fill in contents of bi */
fssScreen.ClrUse = PaletteSize(&bi) ;/* size of the color table */
if ( fssScreen.ClrUse != 0 && IsFst ) /* copy the colours used to the */
{ /* colour table if table exists */
lp = (LPSTR)lpbi+(WORD)lpbi->biSize ;
for (i = 0 ; i < fssScreen.ClrUse ; i++)
ClrTab[i] = *(lp++) ;
IsFst = FALSE ; /* the 1st time is through */
}
/**** Note this should be able to use GlobalReAlloc instead of deallocate
the memory and allocate it again ****/
if ( GlobalUnlock(hdib) ) /* release memory */
{
if ( IsPalDev ) /* [14] */
SelectPalette(hDC, hPalO, FALSE) ; /* restore old palette */
ReleaseDC(NULL, hDC) ;
return RelMemory ; /* [5] [7] */
}
else
if ( GlobalFree(hdib) )
{
if ( IsPalDev ) /* [14] */
SelectPalette(hDC, hPalO, FALSE) ; /* restore old palette */
ReleaseDC(NULL, hDC) ;
return RelMemory ; /* [5] [7] */
}
/* reallocate memory for receiving the bitmap: bi+colour table + bitmap */
fb = (DWORD)bi.biSize + fssScreen.ClrUse + bi.biSizeImage ;
hdib = GlobalAlloc(GMEM_MOVEABLE | GMEM_DISCARDABLE, fb) ;
if ( !hdib )
{
if ( IsPalDev ) /* [14] */
SelectPalette(hDC, hPalO, FALSE) ; /* restore old palette */
ReleaseDC(NULL, hDC) ;
return OutOMemory ; /* [5] [7] */
}
lpbi = (LPBITMAPINFOHEADER) GlobalLock (hdib) ;
*lpbi = bi ; /* copy contents of the bitmap header */
lp = (LPSTR)lpbi+(WORD)lpbi->biSize ; /* load the colour table */
for (i = 0 ; i < fssScreen.ClrUse ; i++)
*(lp++) = ClrTab[i] ;
/* call GetDIBits with a non-NULL lpBits param, to obtain the actual bits
representing the bitmap (in device-independent format) */
i = NoError;
if ( !(hb = GetDIBits(hDC, hbm, 0, (WORD)bi.biHeight,
(LPSTR)lpbi+(WORD)lpbi->biSize+fssScreen.ClrUse,
(LPBITMAPINFO)lpbi, DIB_RGB_COLORS)) )
i = CreateDIB ; /* GetDIBits fails [5] [7]*/
else
{
lp = (LPSTR)lpbi+(WORD)lpbi->biSize+fssScreen.ClrUse ;
if ( *fFlag ) /* output file is a DIB file [11] */
{
if ( *fFlag == DIBFirst ) /* this is the first writing */
{ /* need to output colour info first */
fl = (WORD) fssScreen.ClrUse;
for (j = 0 ; j < fl ; j++)
{
if (M_lwrite (fd, (LPSTR) ClrTab, fl) != (UINT) fl )
i = RWColTable; /* [5] [7] */
}
if (i != RWColTable)
(*fFlag)++ ; /* no need to write colour table */
} /* any more */
*cb = (WORD)bi.biSizeImage ; /* output the image itself */
if ( M_lwrite(fd, (LPSTR)lp, *cb) != *cb )
i = WSrnImage ;
}
else /* write the contents of the device-independent bitmap to the */
{ /* screen file after compressing the bytes (if possible) */
i = WriteCompBytes(fd, lp, (WORD)bi.biSizeImage, cb, IsComp) ;
}
} /* if ( !(hb = ) */
if ( IsPalDev ) /* [14] */
SelectPalette(hDC, hPalO, FALSE) ; /* restore old palette */
ReleaseDC(NULL, hDC) ; /* release resources before return */
if ( GlobalUnlock(hdib) || GlobalFree(hdib) ) /* can't release or un- */
if ( !i ) /* lock global memory */
i = RelMemory ; /* [5] [7] */
return i ;
}
/******************************************************************************
* PURPOSE: Write screen region (in segments if bitmap is larger than 64K), *
* in DIB format, to a file *
* RETURN: 0 will be returned if contents are written successfully *
* GLOBALS: fssScreen - BitCount field will be filled *
* CONDITIONS:fd is valid file handle *
* pscr consists of the size of the screen region; the actual size *
* in bytes representing the bitmap (pscr->cb[i])will be filled *
* fFlag is pointer to an integer (>= 0); if *fFlag = 0, screen *
* image is written to a screen file; otherwise, it will be *
* written as a Device-Independent Bitmap *
******************************************************************************/
INT PRIVATE fWriteScreen(fd, pscr, fFlag) /* [10] [11] */
FD fd ; /* File handle for file to write to */
SCR *pscr ; /* pointing to the screen table */
INT FAR *fFlag ; /* type of output file [11] */
{
HBITMAP hbitmap ; /* handle of a device-dependent bitmap */
BITMAP bm ; /* infomration about a DDBitmap */
WORD cb ; /* size of bitmap after compression */
INT IsComp ; /* which bitmap has been compressed */
INT y ;
INT oHeight ;
INT nHeight ;
BOOL FirstTime = TRUE ;
INT i , j = 0 ;
LONG l ;
for ( i = 0 ; i < MaxCb ; i++ )
pscr->cb[i] = 0 ; /* no byte has been written */
for ( i = 0 ; i < MaxCbComp ; i++ )
pscr->cbComp[i] = 0 ; /* nothing has been compressed */
i = 0 ;
y = pscr->ren.row ;
oHeight = pscr->ren.height ;
IsFst = TRUE ; /* the 1st time to create a DIB */
do
{
nHeight = (INT)(oHeight / (i+1)) ;
if ( nHeight > 0 ) /* get a bitmap representing the */
{ /* current screen */
if ( !(hbitmap = GetBMap(pscr->ren.col, y, pscr->ren.width, nHeight)) )
return CreateDDB ; /* cannot create such a bitmap [5] [7] */
/* obtain info about the bitmap */
if ( GetObject(hbitmap, sizeof(bm), (LPSTR)&bm) == 0 )
return CreateDDB ; /* [5] [7] */
if ( FirstTime ) /* first time this loop is run */
{
/* record # of colour planes * bits/pixel on each plane */
fssScreen.BitCount = bm.bmPlanes * bm.bmBitsPixel ;
if ( fssScreen.BitCount >= 24 ) /* value of bit per pixel */
fssScreen.BitCount = 24 ; /* cannot be bigger than 24 */
if ( IsPalDev ) /* this is a palette device, need to */
{
hPal = MakePal () ; /* create a logical color palette */
if ( !hPal ) /* all available colours [14] */
return CreatePal ;
}
/* calculate the size of the resulting bitmap and determine
if it is more than 64K. If it is, divide the screen region
horizontally into smaller regions */
l = (LONG) (bm.bmWidthBytes * bm.bmPlanes) ;
l *= (LONG) (bm.bmBitsPixel * bm.bmHeight) ;
i = (INT)(l / MaxSize) ;
if (i > 0 && i < MaxCb) /* bitmap is more than 64K */
{
nHeight = (INT)(oHeight / (i+1)) ;
DeleteObject(hbitmap) ; /* re-obtain a smaller bitmap */
if ( *fFlag ) /* if save screen as DIB file, [11] */
y += oHeight - nHeight ; /* origin is lower-left corner */
if ( !(hbitmap = GetBMap(pscr->ren.col, y, pscr->ren.width, nHeight)) )
return CreateDDB ; /* [5] [7] */
if ( GetObject(hbitmap, sizeof(bm), (LPSTR)&bm) == 0)
return CreateDDB ; /* [5] [7] */
}
FirstTime = FALSE ;
}
/* obtain a device independent bitmap representing the screen
region */
if (i < MaxCb)
{
cb = IsComp = 0 ;
j = GetDiBMap(fd, hbitmap, (LPBITMAP)&bm, (WORD FAR *)&cb, (INT FAR *)&IsComp, fFlag) ;
if ( j == 0 ) /* record the size of the bitmap */
{ /* that has just been written out */
pscr->cb[MaxCb-i-1] = cb ; /* and whether the bytes */
if ( IsComp ) /* compression has been performaed */
pscr->cbComp[(MaxCb-i-1)>>4] += 1 << ( ((MaxCb - i - 1) % 16) ) ; /* [14] */
}
oHeight -= nHeight ; /* get the size of the next region */
if ( *fFlag ) /* if output file is DIB, origin is */
{ /* lower-left, so bytes are saved */
if ( i ) /* from the bottom up */
y -= (INT)oHeight/i ;
}
else /* otherwise, bytes are saved from */
y += nHeight ; /* top down */
DeleteObject(hbitmap) ; /* release memory related to the */
} /* DI-bitmap */
else
j = ScreenSize ; /* can't handle screen size [5] [7] */
} /* if nHeight > 0 */
i-- ;
} while (i >= 0 && j == 0) ;
if ( IsPalDev )
DeleteObject(hPal) ;
return j ;
}
/******************************************************************************
* PURPOSE: This routine will be called when a request for adding a screen *
* RETURN: 0 will be returned if screen is added successfully *
* GLOBALS: None *
* CONDITIONS:fd is valid file handl *
* pscr points to the screen table whick contains the dimensions *
* of the new screen *
* hFlag contains valid info of whether the active window should be*
* hidden before taking the snapshot or not *
* fFlag is pointer to an integer (>= 0); if *fFlag = 0, screen *
* image is written to a screen file; otherwise, it will be *
* written as a Device-Independent Bitmap *
******************************************************************************/
INT PRIVATE fAddScreen(fd, pscr, hFlag, fFlag) /* [10] [11] */
FD fd ; /* handle of the sceen file */
SCR *pscr ; /* point to the current screen table */
INT hFlag ; /* where in the file */
INT FAR *fFlag ; /* type of output file [11] */
{
HWND hWndCallingApp ; /* handle of the calling app's window */
INT i = 0;
/* get current video mode and calculate the exact dimensions of the
screen region */
if ( (i = fGetScreenParams((REN FAR *)&(pscr->ren))) != 0 )
return i ;
/* position to write new screen: go to the end of all of the screens */
if ( M_llseek(fd, pscr->lfo, smFromBegin) != (LONG2DWORD)(pscr->lfo ))
i = ReadSrnFil ; /* error in reading file [5] [7] */
if ( hFlag ) /* need to hide the calling app's */
if ( !(hWndCallingApp = HideApp ()) ) /* window before taking picture */
return HideWin ; /* on the current screen [5] [7] */
i = fWriteScreen(fd, pscr, fFlag) ; /* it is at the correct position [11] */
/* to begin writing screen data */
if ( hFlag ) /* restore window of the calling */
RestoreApp(hWndCallingApp) ; /* app if it is hidden */
return i ;
}
/******************************************************************************
* PURPOSE: Copy a block of bytes from one file to another *
* RETURN: 0 will be returned if bytes are copies successfully *
* GLOBALS: none *
* CONDITIONS:fd1, fd2 are valid file handles *
* pos1 and pos2 >= 0 *
* cb > 0 *
******************************************************************************/
INT PRIVATE CopyBytes(fd1, pos1, fd2, pos2, cb)
FD fd1 ; /* handle of the source file */
LFO pos1 ; /* position in file to read from */
FD fd2 ; /* handle of the destination file */
LFO pos2 ; /* position in file to write to */
WORD cb ; /* number of bytes to be copied */
{
GLOBALHANDLE hGMem ; /* handle of the global memory */
LPSTR lpBuf ;
INT i = 0 ;
if ( pos1 ) /* need to move to a paricular */
if ( M_llseek(fd1, pos1, smFromBegin) != (LONG2DWORD)pos1 ) /* location in file */
return ReadSrnFil ; /* [5] [7] */
/* allocate space to receive bytes from file */
hGMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DISCARDABLE, (DWORD)cb) ;
if ( !hGMem ) /* no space has been allocated */
return OutOMemory ; /* signal Out of Memory [5] [7] */
lpBuf = (LPSTR) GlobalLock (hGMem) ;/* protect the global heap */
// BabakJ: Added UINT cast
if ( M_lread(fd1, lpBuf, cb) != (UINT)cb ) /* read from file */
i = ReadSrnFil ; /* error in reading in data [5] [7] */
if ( pos2 && !i ) /* need to move to a paricular */
if ( M_llseek(fd2, pos2, smFromBegin) != (LONG2DWORD)pos2 ) /* location in file */
i = ReadSrnFil ; /* [5] [7] */
if ( !i )
if ( M_lwrite(fd2, lpBuf, cb) != cb ) /* writing data to file */
i = WSrnImage ; /* if unexpected error occurs [5] [7] */
if ( !i ) /* release memory before returning */
{
if ( GlobalUnlock(hGMem) )
i = RelMemory ; /* [5] [7] */
else
if ( GlobalFree(hGMem) )
i = RelMemory ; /* [5] [7] */
}
else
{
GlobalUnlock(hGMem) ;
GlobalFree(hGMem) ;
}
return i ;
}
/******************************************************************************
* PURPOSE: Check if a block of data is more than MaxSize bytes; if it is, * *
* divide to data up into smaller blocks *
* RETURN: 0 will be returned if data are divided and copied successfully *
* GLOBALS: None *
* CONDITIONS:fd1 and fd2 are valid file handle *
* pos1 and pos2 are valid file position (>= 0) *
* tLfo is valid (> 0) *
******************************************************************************/
INT PRIVATE CpBlock(fd1, pos1, fd2, pos2, tLfo)
FD fd1 ; /* handle of the source file */
LFO pos1 ; /* position in file to read from */
FD fd2 ; /* handle of the destination file */
LFO pos2 ; /* position in file to write to */
LFO tLfo ; /* number of bytes to be copied */
{
WORD cb ;
INT i = 0 , j = 0 ;
i = (INT)(tLfo / MaxSize) ; /* can only copy 64K bytes at once */
i++ ; /* so check to see if block is */
/* bigger than MaxSize */
do
{ /* divide the data up to smller */
cb = (WORD)(tLfo / i) ; /* blocks if necessary */
if ( cb != 0 ) /* move a block of bytes upward */
j = CopyBytes(fd1, pos1, fd2, pos2, cb) ;
tLfo -= (LFO)cb ; /* some bytes have been copied */
if ( fd1 == fd2 ) /* if read and write files are */
{ /* the same file, advance the read */
pos1 += (LFO)cb ; /* and write pointers; otherwise, */
pos2 += (LFO)cb ; /* just keep on reading and writing */
} /* at the current position */
else
pos1 = pos2 = 0 ;
i-- ;
}
while ( i > 0 && j == 0 ) ;
return j ;
}
/******************************************************************************
* PURPOSE: Re-write all the tables (file header, screen tables, and colour * *
* table) back to the screen file *
* RETURN: 0 will be returned if screen is tables are written successfully *
* GLOBALS: fssScreen, rgscr, ClrTab *
* CONDITIONS:fd is valid file handle *
* all globals are assume to hold the correct information *
******************************************************************************/
INT PRIVATE fReWriteTables(fd)
FD fd ; /* handle of the screen file */
{
LFO tLfo ;
INT i, j;
WORD fl;
/* Write new table back to file. The current file position is
the correct place to write the table. */
for (i = 0 ; i < fssScreen.cscr ; i++)
{
for (j = 0 ; j < MaxCb ; j++)
{
if (M_lwrite (fd, (LPSTR) &rgscr[i].cb[j], 2) != 2)
{
M_lclose(fd) ; /* unexpected error when writing */
return RWSrnTable ; /* screen tables [5] [7] */
}
}
for (j = 0 ; j < MaxCbComp ; j++)
{
if (M_lwrite (fd, (LPSTR) &rgscr[i].cbComp[j], 2) != 2)
{
M_lclose(fd) ; /* unexpected error when writing */
return RWSrnTable ; /* screen tables [5] [7] */
}
}
if (M_lwrite (fd, (LPSTR) &rgscr[i].ren.col, 2) != 2)
{
M_lclose(fd) ; /* unexpected error when writing */
return RWSrnTable ; /* screen tables [5] [7] */
}
if (M_lwrite (fd, (LPSTR) &rgscr[i].ren.row, 2) != 2)
{
M_lclose(fd) ; /* unexpected error when writing */
return RWSrnTable ; /* screen tables [5] [7] */
}
if (M_lwrite (fd, (LPSTR) &rgscr[i].ren.width, 2) != 2)
{
M_lclose(fd) ; /* unexpected error when writing */
return RWSrnTable ; /* screen tables [5] [7] */
}
if (M_lwrite (fd, (LPSTR) &rgscr[i].ren.height, 2) != 2)
{
M_lclose(fd) ; /* unexpected error when writing */
return RWSrnTable ; /* screen tables [5] [7] */
}
if (M_lwrite (fd, (LPSTR) &rgscr[i].lfo, 4) != 4)
{
M_lclose(fd) ; /* unexpected error when writing */
return RWSrnTable ; /* screen tables [5] [7] */
}
}
/* Write colour table back to file if table exists */
if (fssScreen.ClrUse != 0)
{
fl = (WORD) fssScreen.ClrUse ; /* read colour table */
for (i = 0 ; i < fl ; i++)
{
if (M_lwrite (fd, (LPSTR) &ClrTab [i], 1) != 1)
{
M_lclose(fd) ; /* unexpected error when writing */
return RWColTable ; /* [5] [7] */
}
}
}
/* Rewrite header of file: update offset to the screen tables and
total number of screen contents in file */
M_llseek(fd, 0L, smFromBegin) ;
// Write fst
if (M_lwrite (fd, (LPSTR) &fssScreen.fst.FileId, 3) != 3)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
if (M_lwrite (fd, (LPSTR) &fssScreen.fst.Ver, 1) != 1)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
if (M_lwrite (fd, (LPSTR) &fssScreen.fst.Env, 1) != 1)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
// Write vmd
if (M_lwrite (fd, (LPSTR) &fssScreen.vmd, 1) != 1)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
// Write BitCount
if (M_lwrite (fd, (LPSTR) &fssScreen.BitCount, 2) != 2)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
// Write ClrUse
if (M_lwrite (fd, (LPSTR) &fssScreen.ClrUse, 2) != 2)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
// Write cscr
if (M_lwrite (fd, (LPSTR) &fssScreen.cscr, 2) != 2)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
// Write lfo
if (M_lwrite (fd, (LPSTR) &fssScreen.lfo, 4) != 4)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
// Write vmG
if (M_lwrite (fd, (LPSTR) &fssScreen.vmG.XresMAX, 2) != 2)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
if (M_lwrite (fd, (LPSTR) &fssScreen.vmG.YresMAX, 2) != 2)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
if (M_lwrite (fd, (LPSTR) &fssScreen.vmG.PaletteSizeMAX, 4) != 4)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
// Write reserved1
if (M_lwrite (fd, (LPSTR) &fssScreen.reserved1, 4) != 4)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
// Write reserved2
if (M_lwrite (fd, (LPSTR) &fssScreen.reserved2, 4) != 4)
{
M_lclose(fd) ; /* unexpected error when writing */
return WFileHead ; /* file header [5] [7] */
}
/* move to the end of file and write 0 bytes -> truncate or extend file */
tLfo = fssScreen.lfo + fssScreen.cscr * 226 + fssScreen.ClrUse ;
if ( M_llseek(fd, tLfo, smFromBegin) != (LONG2DWORD)tLfo )
{
M_lclose(fd) ;
return ReadSrnFil ; /* [5] [7] */
}
return ((INT) M_lwrite(fd, (LPSTR)NULL, 0)) ;
}
/******************************************************************************
* exit function for the library in Windows *
******************************************************************************/
VOID APIENTRY WEP (bSystemExit)
WORD bSystemExit ;
{
if ( bSystemExit )
{
/* not sure what to put here */
}
else
{
/* not sure what to put here */
}
}