543 lines
12 KiB
C
543 lines
12 KiB
C
|
#include "sol.h"
|
||
|
VSZASSERT
|
||
|
|
||
|
|
||
|
/* flags for _lseek */
|
||
|
#define SEEK_CUR 1
|
||
|
#define SEEK_END 2
|
||
|
#define SEEK_SET 0
|
||
|
|
||
|
#define cbBand 8192
|
||
|
|
||
|
BGND bgnd;
|
||
|
|
||
|
|
||
|
BOOL _FValidBm(BMP *pbm)
|
||
|
{
|
||
|
return((pbm->biBitCount == 1 || pbm->biBitCount == 4)
|
||
|
&& pbm->biPlanes == 1 && pbm->biSize == sizeof(BMP));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL FInitBgnd(TCHAR *szFile)
|
||
|
{
|
||
|
INT fh;
|
||
|
BOOL fResult;
|
||
|
LONG lcbBm;
|
||
|
LONG dwBmSize;
|
||
|
|
||
|
fResult = fFalse;
|
||
|
bgnd.fUseBitmap = fFalse;
|
||
|
if((fh = OpenFile(szFile, &bgnd.of, OF_CANCEL|OF_READ)) == -1)
|
||
|
return fFalse;
|
||
|
|
||
|
if(!FReadDibBitmapInfo(fh, &bgnd.bm))
|
||
|
goto ReturnClose;
|
||
|
bgnd.dwOfsBits = M_llseek( fh, 0L, SEEK_CUR);
|
||
|
|
||
|
if(!_FValidBm(&bgnd.bm))
|
||
|
goto ReturnClose;
|
||
|
|
||
|
|
||
|
/* BUG: check if bitmap is ok */
|
||
|
bgnd.cbLine = (((INT) bgnd.bm.biWidth * bgnd.bm.biBitCount+31)/32)*4;
|
||
|
lcbBm = (LONG) bgnd.cbLine * DyBmp(bgnd.bm);
|
||
|
bgnd.ibndMac = (INT) ((lcbBm+cbBand-1) / cbBand);
|
||
|
if((bgnd.rghbnd = PAlloc(bgnd.ibndMac*sizeof(HANDLE))) == NULL)
|
||
|
goto ReturnClose;
|
||
|
bgnd.dyBand = (INT) ((LONG) DyBmp(bgnd.bm) * cbBand / lcbBm);
|
||
|
bgnd.fUseBitmap = fTrue;
|
||
|
SetBgndOrg();
|
||
|
fResult = fTrue;
|
||
|
ReturnClose:
|
||
|
M_lclose(fh);
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL FDestroyBgnd()
|
||
|
{
|
||
|
INT ibnd;
|
||
|
HANDLE *phbnd;
|
||
|
|
||
|
if(bgnd.fUseBitmap)
|
||
|
{
|
||
|
for(ibnd = 0; ibnd < bgnd.ibndMac; ibnd++)
|
||
|
{
|
||
|
if(*(phbnd = &bgnd.rghbnd[ibnd]) != NULL)
|
||
|
{
|
||
|
GlobalFree(*phbnd);
|
||
|
*phbnd = NULL;
|
||
|
}
|
||
|
}
|
||
|
FreeP(bgnd.rghbnd);
|
||
|
}
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL FGetBgndFile(TCHAR *sz)
|
||
|
{
|
||
|
if(bgnd.fUseBitmap)
|
||
|
PszCopy(bgnd.of.szPathName, sz);
|
||
|
else
|
||
|
sz[0] = TEXT('\000');
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL _FLoadBand(INT ibnd, Y y)
|
||
|
{
|
||
|
HANDLE hbnd;
|
||
|
BYTE[ ]*FAR[ ]**lpb;
|
||
|
INT ipln;
|
||
|
INT fh;
|
||
|
LONG lcbpln;
|
||
|
HANDLE *phbnd;
|
||
|
DY dy;
|
||
|
|
||
|
phbnd = &bgnd.rghbnd[ibnd];
|
||
|
|
||
|
if(*phbnd != NULL)
|
||
|
GlobalFree(*phbnd);
|
||
|
hbnd = GlobalAlloc(GMEM_MOVEABLE|GMEM_DISCARDABLE, (LONG) cbBand);
|
||
|
lpb = GlobalLock(hbnd);
|
||
|
if(lpb == NULL)
|
||
|
return fFalse;
|
||
|
fh = OpenFile("", &bgnd.of, OF_REOPEN|OF_READ );
|
||
|
|
||
|
lcbpln = 0L;
|
||
|
dy = WMin(bgnd.dyBand, DyBmp(bgnd.bm)-y);
|
||
|
for(ipln = 0; ipln < CplnBmp(bgnd.bm); ipln++)
|
||
|
{
|
||
|
M_llseek( fh, (LONG)OfsBits(bgnd)+ipln*lcbpln+(y)*CbLine(bgnd), 0);
|
||
|
M_lread( fh, (LPSTR) lpb+ipln*CbLine(bgnd)*bgnd.dyBand, dy * CbLine(bgnd));
|
||
|
}
|
||
|
|
||
|
GlobalUnlock(hbnd);
|
||
|
*phbnd = hbnd;
|
||
|
M_lclose(fh);
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
Y _YDrawBand(HDC hdcMem, HBITMAP hbm, X xLeft, Y yTop, X xRight, Y yBot)
|
||
|
{
|
||
|
HBITMAP hbmSav;
|
||
|
HANDLE hbnd;
|
||
|
BYTE[ ]*FAR[ ]**lpb;
|
||
|
Y y;
|
||
|
INT ibnd;
|
||
|
|
||
|
/* round yTop to nearest band */
|
||
|
y = ((yTop-bgnd.ptOrg.y)/bgnd.dyBand)*bgnd.dyBand;
|
||
|
|
||
|
ibnd = y/bgnd.dyBand;
|
||
|
if(ibnd < 0)
|
||
|
return bgnd.ptOrg.y;
|
||
|
if(ibnd >= bgnd.ibndMac)
|
||
|
return yBot+1;
|
||
|
ibnd = bgnd.ibndMac-ibnd-1;
|
||
|
Assert(ibnd >= 0);
|
||
|
Assert(ibnd < bgnd.ibndMac);
|
||
|
while((hbnd = bgnd.rghbnd[ibnd]) == NULL ||
|
||
|
(lpb = (BYTE[ ]*FAR[ ]**) GlobalLock(hbnd)) == NULL)
|
||
|
{
|
||
|
if(!_FLoadBand(ibnd, y))
|
||
|
/* KLUDGE:, should back out gracefully */
|
||
|
return yBot;
|
||
|
}
|
||
|
|
||
|
Assert(lpb != NULL);
|
||
|
SetDIBitsToDevice(hdcCur, xLeft-xOrgCur, yTop-yOrgCur,
|
||
|
WMin(xRight-xLeft, DyBmp(bgnd.bm)-xLeft+bgnd.ptOrg.x),
|
||
|
WMin(WMin(bgnd.dyBand, yBot-yTop), DyBmp(bgnd.bm)-yTop+bgnd.ptOrg.y),
|
||
|
0, 0,
|
||
|
y-bgnd.ptOrg.y,
|
||
|
bgnd.dyBand,
|
||
|
|
||
|
// xLeft-bgnd.ptOrg.x, yTop-y-bgnd.ptOrg.y,
|
||
|
// 0,
|
||
|
// WMin(WMin(bgnd.dyBand, yBot-yTop), DyBmp(bgnd.bm)-yTop+bgnd.ptOrg.y),
|
||
|
lpb,
|
||
|
(BITMAPINFO FAR *)&bgnd.bm,
|
||
|
DIB_RGB_COLORS);
|
||
|
|
||
|
GlobalUnlock(hbnd);
|
||
|
return y+bgnd.dyBand+bgnd.ptOrg.y;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID DrawBgnd(X xLeft, Y yTop, X xRight, Y yBot)
|
||
|
{
|
||
|
INT dy;
|
||
|
Y y;
|
||
|
HDC hdcMem;
|
||
|
HBITMAP hbm;
|
||
|
HBRUSH hbr;
|
||
|
|
||
|
if(bgnd.fUseBitmap)
|
||
|
{
|
||
|
|
||
|
for(y = yTop; y <= yBot; )
|
||
|
{
|
||
|
y = _YDrawBand(hdcMem, hbm, xLeft, y, xRight, yBot);
|
||
|
}
|
||
|
ExcludeClipRect(hdcCur, bgnd.ptOrg.x-xOrgCur, bgnd.ptOrg.y-yOrgCur, bgnd.ptOrg.x+DxBmp(bgnd.bm)-xOrgCur, bgnd.ptOrg.y+DyBmp(bgnd.bm)-yOrgCur);
|
||
|
}
|
||
|
|
||
|
MSetBrushOrg(hdcCur, xOrgCur, yOrgCur);
|
||
|
MUnrealizeObject( hbrTable );
|
||
|
hbr = SelectObject(hdcCur, hbrTable);
|
||
|
Assert(xRight >= xLeft);
|
||
|
Assert(yBot >= yTop);
|
||
|
PatBlt(hdcCur, xLeft-xOrgCur, yTop-yOrgCur, xRight-xLeft, yBot-yTop, PATCOPY);
|
||
|
SelectObject(hdcCur, hbr);
|
||
|
|
||
|
if(bgnd.fUseBitmap)
|
||
|
SelectClipRgn(hdcCur, NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
VOID SetBgndOrg()
|
||
|
{
|
||
|
bgnd.ptOrg.x = (rcClient.xRight - DxBmp(bgnd.bm))/2;
|
||
|
bgnd.ptOrg.y = (rcClient.yBot - DyBmp(bgnd.bm))/2;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ReadDibBitmapInfo()
|
||
|
*
|
||
|
* Will read a file in DIB format and return a global HANDLE to it's
|
||
|
* BITMAPINFO. This function will work with both "old" and "new"
|
||
|
* bitmap formats, but will allways return a "new" BITMAPINFO
|
||
|
*
|
||
|
*/
|
||
|
BOOL FReadDibBitmapInfo(INT fh, BITMAPINFO *pbi)
|
||
|
{
|
||
|
DWORD off;
|
||
|
HANDLE hbi = NULL;
|
||
|
INT size;
|
||
|
INT i;
|
||
|
WORD nNumColors;
|
||
|
|
||
|
RGBQUAD FAR *pRgb;
|
||
|
BITMAPINFOHEADER bi;
|
||
|
BITMAPCOREHEADER bc;
|
||
|
LPBITMAPINFOHEADER lpbi;
|
||
|
BITMAPFILEHEADER bf;
|
||
|
|
||
|
if (fh == -1)
|
||
|
return NULL;
|
||
|
|
||
|
off = M_llseek( fh, 0L, SEEK_CUR);
|
||
|
|
||
|
if (sizeof(bf) != M_lread( fh, (LPSTR)&bf, sizeof(bf)) )
|
||
|
return fFalse;
|
||
|
|
||
|
/*
|
||
|
* do we have a RC HEADER?
|
||
|
*/
|
||
|
if (!ISDIB(bf.bfType))
|
||
|
{
|
||
|
bf.bfOffBits = 0L;
|
||
|
M_llseek( fh, off, SEEK_SET );
|
||
|
}
|
||
|
|
||
|
if (sizeof(bi) != M_lread( fh, (LPSTR)&bi, sizeof(bi)) )
|
||
|
return fFalse;
|
||
|
|
||
|
nNumColors = DibNumColors(&bi);
|
||
|
|
||
|
/*
|
||
|
* what type of bitmap info is this?
|
||
|
*/
|
||
|
switch (size = (INT)bi.biSize)
|
||
|
{
|
||
|
case sizeof(BITMAPINFOHEADER):
|
||
|
break;
|
||
|
|
||
|
case sizeof(BITMAPCOREHEADER):
|
||
|
bc = *(BITMAPCOREHEADER*)&bi;
|
||
|
bi.biSize = sizeof(BITMAPINFOHEADER);
|
||
|
bi.biWidth = (DWORD)bc.bcWidth;
|
||
|
bi.biHeight = (DWORD)bc.bcHeight;
|
||
|
bi.biPlanes = (WORD)bc.bcPlanes;
|
||
|
bi.biBitCount = (WORD)bc.bcBitCount;
|
||
|
bi.biStyle = 0;
|
||
|
bi.biSizeImage = 0;
|
||
|
bi.biXPelsPerMeter = 0;
|
||
|
bi.biYPelsPerMeter = 0;
|
||
|
bi.biClrUsed = nNumColors;
|
||
|
bi.biClrImportant = nNumColors;
|
||
|
|
||
|
M_llseek(fh, (LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER), SEEK_CUR);
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return fFalse; /* not a DIB */
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* fill in some default values!
|
||
|
*/
|
||
|
if (bi.biSizeImage == 0)
|
||
|
{
|
||
|
bi.biSizeImage = WIDTHBYTES((DWORD)bi.biWidth * bi.biBitCount)
|
||
|
* bi.biHeight;
|
||
|
}
|
||
|
|
||
|
if (bi.biXPelsPerMeter == 0)
|
||
|
{
|
||
|
bi.biXPelsPerMeter = 0; // ??????????????
|
||
|
}
|
||
|
|
||
|
if (bi.biYPelsPerMeter == 0)
|
||
|
{
|
||
|
bi.biYPelsPerMeter = 0; // ??????????????
|
||
|
}
|
||
|
|
||
|
if (bi.biClrUsed == 0)
|
||
|
{
|
||
|
bi.biClrUsed = DibNumColors(&bi);
|
||
|
}
|
||
|
|
||
|
|
||
|
lpbi = (VOID FAR *)pbi;
|
||
|
*lpbi = bi;
|
||
|
|
||
|
pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + bi.biSize);
|
||
|
|
||
|
if (nNumColors)
|
||
|
{
|
||
|
if (size == sizeof(BITMAPCOREHEADER))
|
||
|
{
|
||
|
/*
|
||
|
* convert a old color table (3 byte entries) to a new
|
||
|
* color table (4 byte entries)
|
||
|
*/
|
||
|
M_lread( fh, (LPSTR)pRgb, nNumColors * sizeof(RGBTRIPLE) );
|
||
|
|
||
|
for (i=nNumColors-1; i>=0; i--)
|
||
|
{
|
||
|
RGBQUAD rgb;
|
||
|
|
||
|
rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
|
||
|
rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
|
||
|
rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
|
||
|
rgb.rgbReserved = (BYTE)0;
|
||
|
|
||
|
pRgb[i] = rgb; // BUG, this is wrong!!!!
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
M_lread(fh, (LPSTR)pRgb, nNumColors * sizeof(RGBQUAD));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bf.bfOffBits != 0L)
|
||
|
M_llseek( fh, off + bf.bfOffBits, SEEK_SET );
|
||
|
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* How Many colors does this DIB have?
|
||
|
* this will work on both PM and Windows bitmap info structures.
|
||
|
*/
|
||
|
WORD DibNumColors(VOID FAR * pv)
|
||
|
{
|
||
|
INT bits;
|
||
|
|
||
|
/*
|
||
|
* with the new format headers, the size of the palette is in biClrUsed
|
||
|
* else is dependent on bits per pixel
|
||
|
*/
|
||
|
if (((LPBITMAPINFOHEADER)pv)->biSize != sizeof(BITMAPCOREHEADER))
|
||
|
{
|
||
|
if (((LPBITMAPINFOHEADER)pv)->biClrUsed != 0)
|
||
|
return (WORD)((LPBITMAPINFOHEADER)pv)->biClrUsed;
|
||
|
|
||
|
bits = ((LPBITMAPINFOHEADER)pv)->biBitCount;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bits = ((LPBITMAPCOREHEADER)pv)->bcBitCount;
|
||
|
}
|
||
|
|
||
|
switch (bits)
|
||
|
{
|
||
|
case 1:
|
||
|
return 2;
|
||
|
case 4:
|
||
|
return 16;
|
||
|
case 8:
|
||
|
Assert(fFalse); // NYI
|
||
|
return 256;
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef LATER
|
||
|
|
||
|
HDC HdcCreateImage(HDC hdcApp, INT idbMask, INT idbImage, LONG rgb, DX *pdx, DY *pdy)
|
||
|
{
|
||
|
HDC hdcMem, hdcMem1;
|
||
|
HBITMAP hbmT, hbmTT, hbmMask;
|
||
|
HBRUSH hbr;
|
||
|
BITMAP bm;
|
||
|
|
||
|
hdcMem = CreateCompatibleDC(hdcApp);
|
||
|
hbmMask = LoadBitmap(hinstApp, MAKEINTRESOURCE(idbMask));
|
||
|
GetObject(hbmMask, sizeof(BITMAP), (LPSTR) &bm);
|
||
|
|
||
|
/* enlarge the size of hdc */
|
||
|
hbmT = SelectObject(hdcMem, CreateCompatibleBitmap(hdcApp, bm.bmWidth, bm.bmHeight));
|
||
|
hbr = SelectObject(hdcMem, hbrTable);
|
||
|
PatBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, PATCOPY);
|
||
|
SelectObject(hdcMem, hbr);
|
||
|
|
||
|
hdcMem1 = CreateCompatibleDC(hdcApp);
|
||
|
hbmTT = SelectObject(hdcMem1, hbmMask);
|
||
|
BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem1, 0, 0, SRCAND);
|
||
|
/* load image and delete hbmMask */
|
||
|
DeleteObject(SelectObject(hdcMem1, LoadBitmap(hinstApp, MAKEINTRESOURCE(idbImage))));
|
||
|
/* load brush to color image */
|
||
|
hbr = SelectObject(hdcMem, CreateSolidBrush(rgb));
|
||
|
|
||
|
#define ropDPSao 0x00EA02E9 /* (Source & Pattern) | Dest */
|
||
|
BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem1, 0, 0, ropDPSao);
|
||
|
DeleteObject(SelectObject(hdcMem, hbr));
|
||
|
DeleteObject(SelectObject(hdcMem1, hbmTT));
|
||
|
DeleteDC(hdcMem1);
|
||
|
*pdx = bm.bmWidth;
|
||
|
*pdy = bm.bmHeight;
|
||
|
return hdcMem;
|
||
|
}
|
||
|
|
||
|
Marquee(RC *prc)
|
||
|
{
|
||
|
HDC hdc;
|
||
|
HDC hdcObj;
|
||
|
X x;
|
||
|
Y y;
|
||
|
DX dxObj;
|
||
|
DY dyObj;
|
||
|
DX dx;
|
||
|
DY dy;
|
||
|
INT dobjX, dobjY; /* # of objects per dir */
|
||
|
INT iobj;
|
||
|
INT iSlice, iSlice1;
|
||
|
|
||
|
hdc = GetDC(hwndApp);
|
||
|
hdcObj = HdcCreateImage(hdc, idbBlackBear, idbWhiteBear, RGB(255, 0, 0), &dxObj, &dyObj);
|
||
|
dobjX = (prc->xRight-prc->xLeft)/dxObj;
|
||
|
dobjY = (prc->yBot-prc->yTop)/dyObj;
|
||
|
dx = dxObj*2;
|
||
|
dy = 0;
|
||
|
y = prc->yTop-dyObj;
|
||
|
x = prc->xLeft-dxObj+iSlice%dxObj;
|
||
|
for(iobj = 0; iobj < 2*dobjX+2*dobjY; iobj++)
|
||
|
{
|
||
|
BitBlt(hdc, x, y, dxObj, dyObj, hdcObj, 0, 0, SRCCOPY);
|
||
|
if(dy == 0)
|
||
|
{
|
||
|
if(x > prc->xRight+dxObj)
|
||
|
{
|
||
|
dy = dyObj*2;
|
||
|
dx = 0;
|
||
|
}
|
||
|
else if(x < prc->xLeft-dxObj)
|
||
|
{
|
||
|
dy = -dyObj*2;
|
||
|
dx = 0;
|
||
|
}
|
||
|
}
|
||
|
else if(dx == 0)
|
||
|
{
|
||
|
if(y > prc->yBot+dyObj)
|
||
|
{
|
||
|
dx = -dxObj*2;
|
||
|
dy = 0;
|
||
|
}
|
||
|
}
|
||
|
x+=dx;
|
||
|
y+=dy;
|
||
|
}
|
||
|
for(iSlice = 0; iSlice < 5; iSlice++)
|
||
|
{
|
||
|
for(iSlice1 = 0; iSlice1 < dxObj; iSlice1++)
|
||
|
{
|
||
|
BitBlt(hdc, prc->xLeft-dxObj+iSlice1+1, prc->yTop-dyObj, prc->xRight-prc->xLeft+dxObj, dyObj,
|
||
|
hdc, prc->xLeft-dxObj+iSlice1, prc->yTop-dyObj, SRCCOPY);
|
||
|
BitBlt(hdc, prc->xRight+dxObj, prc->yTop-dyObj+iSlice1+1, dxObj, prc->yBot-prc->yTop+dyObj,
|
||
|
hdc, prc->xRight+dxObj, prc->yTop-dyObj+iSlice1, SRCCOPY);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
DeleteDC(hdcObj);
|
||
|
ReleaseDC(hwndApp, hdc);
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
Animation()
|
||
|
{
|
||
|
INT iX, iY, ihdc;
|
||
|
DX dx;
|
||
|
DY dy;
|
||
|
HDC hdc;
|
||
|
HDC rghdc[3];
|
||
|
|
||
|
RC rc;
|
||
|
|
||
|
|
||
|
rc.xLeft = 100; rc.xRight = 300;
|
||
|
rc.yTop = 100; rc.yBot = 200;
|
||
|
Marquee(&rc);
|
||
|
return fTrue;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif /* LATER */
|
||
|
|
||
|
|