windows-nt/Source/XPSP1/NT/shell/osshell/ep/idlewild/dropout/dropout.c
2020-09-26 16:20:57 +08:00

232 lines
4.8 KiB
C

// "Dropout" module for IdleWild.
//
// By Tony Krueger
#ifdef PM
#define INCL_WIN
#define INCL_GPI
#include <os2.h>
/*int _acrtused = 0;*/
#endif
#ifdef WIN
#include <windows.h>
#include <port1632.h>
#endif
#include "std.h"
#include "scrsave.h"
#define cMovesMax 20 /* Max number of moves in one ANIMATE call */
#define cxBlockMax 32 /* Enough for 8514 */
#define cyBlockMax 24
#define FUsedXY(x, y) rgf[x + y * cxBlock]
// Globals
INT dxScreen, dyScreen;
HDC hMemoryDC = NULL;
HBITMAP hbmpScreen = NULL;
HBITMAP hbmpBlock = NULL;
HBITMAP hbmpOld = NULL;
INT fBlock;
INT x, y, dx, dy, dyVel;
INT dxBlock, dyBlock;
INT cxBlock, cyBlock;
INT fAbove;
INT cBlockRemain;
UCHAR rgf[cxBlockMax * cyBlockMax];
INT rand();
BOOL EXPENTRY ScrSaveProc(INT ssm, LPVOID l1, LONG_PTR l2, LONG_PTR l3)
{
CHAR FAR * lpsz;
CHAR FAR * lpch;
switch (ssm)
{
default:
return fFalse;
case SSM_OPEN:
lpsz = (PSZ) l1;
lpch = "Dropout";
while ((*lpsz++ = *lpch++) != '\0')
;
lpsz = (PSZ) l2;
lpch = "Screen Blocks\nDrop Out\n\nby Tony Krueger";
while ((*lpsz++ = *lpch++) != '\0')
;
#ifdef PM
dxScreen = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
dyScreen = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
#endif
#ifdef WIN
dxScreen = GetSystemMetrics(SM_CXSCREEN);
dyScreen = GetSystemMetrics(SM_CYSCREEN);
#endif
break;
case SSM_BLANK:
{
CVS cvs;
ScrRestoreScreen();
cvs = (CVS) l1;
dxBlock = 32;
dyBlock = dxBlock * GetDeviceCaps(cvs, ASPECTX)
/ GetDeviceCaps(cvs, ASPECTY);
if (dyBlock <= 0) // Assure at least one
dyBlock = 1;
cxBlock = (dxScreen + dxBlock - 1) / dxBlock;
cyBlock = (dyScreen + dyBlock - 1) / dyBlock;
// Assure number of blocks small enough
while (cxBlock * cyBlock > cxBlockMax * cyBlockMax)
{
dxBlock *= 2;
dyBlock *= 2;
cxBlock = (dxScreen + dxBlock - 1) / dxBlock;
cyBlock = (dyScreen + dyBlock - 1) / dyBlock;
}
cBlockRemain = cxBlock * cyBlock;
for (x = 0; x < cxBlock; x++)
for (y = 0; y < cyBlock; y++)
FUsedXY(x, y) = fFalse;
hMemoryDC = CreateCompatibleDC(cvs);
hbmpScreen = CreateCompatibleBitmap(cvs, dxScreen, dyScreen);
hbmpBlock = CreateCompatibleBitmap(cvs, dxBlock, dyBlock);
if (hMemoryDC == NULL || hbmpScreen == NULL || hbmpBlock == NULL)
{
if (hMemoryDC != NULL)
DeleteDC(hMemoryDC);
hMemoryDC = NULL;
if (hbmpScreen != NULL)
DeleteObject(hbmpScreen);
hbmpScreen = NULL;
if (hbmpBlock != NULL)
DeleteObject(hbmpBlock);
hbmpBlock = NULL;
ScrChooseRandomServer();
}
else
{
hbmpOld = SelectObject(hMemoryDC, hbmpScreen);
BitBlt(hMemoryDC, 0, 0, dxScreen, dyScreen, cvs, 0, 0, SRCCOPY);
}
fBlock = fFalse;
}
break;
case SSM_UNBLANK:
if (hMemoryDC != NULL)
{
SelectObject(hMemoryDC, hbmpOld);
DeleteDC(hMemoryDC);
}
if (hbmpScreen != NULL)
DeleteObject(hbmpScreen);
if (hbmpBlock != NULL)
DeleteObject(hbmpBlock);
break;
case SSM_ANIMATE:
{
CVS cvs;
cvs = (CVS) l1;
if (fBlock)
{
INT cMoves = 0;
while (cMoves < cMovesMax && x <= dxScreen && x >= -dxBlock)
{
SelectObject(hMemoryDC, hbmpBlock);
BitBlt(cvs, x, y, dxBlock, dyBlock, hMemoryDC, 0, 0, SRCCOPY);
SelectObject(hMemoryDC, hbmpScreen);
dyVel += 1;
dy = dyVel / 16;
if (dy > 0)
BitBlt(cvs, x, y, dxBlock, dy, hMemoryDC, x, y, SRCCOPY);
else if (dy < 0)
BitBlt(cvs, x, y + dyBlock + dy, dxBlock, -dy, hMemoryDC, x, y + dyBlock + dy, SRCCOPY);
if (dx > 0)
BitBlt(cvs, x, y, dx, dyBlock, hMemoryDC, x, y, SRCCOPY);
else if (dx < 0)
BitBlt(cvs, x + dxBlock + dx, y, -dx, dyBlock, hMemoryDC, x + dxBlock + dx, y, SRCCOPY);
y += dy;
x += dx;
if (y >= dyScreen - dyBlock && fAbove)
{
dyVel = -dyVel * 3 / 4 ;
fAbove = fFalse;
}
else
fAbove = fTrue;
cMoves++;
}
fBlock = (x <= dxScreen && x >= -dxBlock);
}
else
{
INT cMoves = 0;
do
{
// Choose random block
x = WRand(cxBlock);
y = WRand(cyBlock);
}
while (cMoves++ < cMovesMax && FUsedXY(x, y) == fTrue);
if (cBlockRemain <= 0 || hMemoryDC == NULL)
{
ScrChooseRandomServer();
}
else if (cMoves < cMovesMax)
{
FUsedXY(x, y) = fTrue;
cBlockRemain--;
x *= dxBlock;
y *= dyBlock;
// Copy original block into block bitmap
SelectObject(hMemoryDC, hbmpBlock);
BitBlt(hMemoryDC, 0, 0, dxBlock, dyBlock, cvs, x, y, SRCCOPY);
// Black out block on screen
PatBlt(cvs, x, y, dxBlock, dyBlock, BLACKNESS);
// And on screen bitmap
SelectObject(hMemoryDC, hbmpScreen);
PatBlt(hMemoryDC, x, y, dxBlock, dyBlock, BLACKNESS);
do
{
dx = WRand(5) - 2;
dyVel = -(WRand(5) * 16);
}
while (dx == 0);
fAbove = fTrue;
fBlock = fTrue;
}
}
}
break;
}
return fTrue;
}