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

293 lines
6.3 KiB
C

// "Shuffle" module for IdleWild.
//
// Blts a pattern over the screen (to "darken" it), then
// divides the screen into blocks and shuffles them around.
//
// 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"
INT rand();
INT dxScreen, dyScreen;
INT xBlock, yBlock;
INT xBlockMax, yBlockMax;
INT dx, dy, dir, lastOppDirection = 0;
INT xBlockSize, yBlockSize;
#define ROP_PANDD (DWORD)0x00A000C9 /* dest = pattern AND dest */
#define ROP_INVPANDD (DWORD)0x000A0329 /* dest = ~pattern AND dest */
typedef WORD BMP[8]; /* Monochrome brush-sized bitmap is 8 words */
#define stdchance 2 /* One in 2 times only pick from standard bmps */
#define ibmpStdMax 5
#define ibmpMax 17
BMP rgbmp[ibmpMax] =
{
{ 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }, /* Dither 1x1 */
{ 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC }, /* Dither 2x1 */
{ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, /* Horiz stripe */
{ 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00 }, /* Vert stripe */
{ 0x88, 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44 }, /* Slash */
{ 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC }, /* Dither 2x2 */
{ 0xFF, 0x0C, 0x0C, 0x0C, 0xFF, 0xC0, 0xC0, 0xC0 }, /* Brick */
{ 0x38, 0x7C, 0xEE, 0xC6, 0xEE, 0x7C, 0x38, 0x00 }, /* Small Hollow Circle */
{ 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x00 }, /* Small Circle */
{ 0xF8, 0xF1, 0xE3, 0xC7, 0x8F, 0x1F, 0x3E, 0x7C }, /* Thick Slash */
{ 0xF8, 0xF1, 0xE3, 0xC7, 0x8F, 0xC7, 0xE3, 0xF1 }, /* Thick ZigZag */
{ 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x3F, 0x7F }, /* Tile edge */
{ 0xF8, 0x74, 0x22, 0x47, 0x8F, 0x17, 0x22, 0x71 }, /* Thatch */
{ 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xF0 }, /* Waffle */
{ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, 0x00 }, /* Small Solid Box */
{ 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00 }, /* Solid Diamond */
{ 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0 }, /* Dither 4x1 */
};
/* Pick new direction */
/* Don't move back onto square just vacated */
/* Also don't move off screen */
VOID GetDxDy()
{
INT xNew, yNew, oppDir;
do
{
dir = WRand(4);
switch(dir)
{
case 0: /* Left */
dx = -1;
dy = 0;
oppDir = 1;
break;
case 1: /* Right */
dx = 1;
dy = 0;
oppDir = 0;
break;
case 2: /* Up */
dx = 0;
dy = 1;
oppDir = 3;
break;
case 3: /* Down */
dx = 0;
dy = -1;
oppDir = 2;
break;
}
xNew = xBlock + dx;
yNew = yBlock + dy;
}
while (dir == lastOppDirection || xNew < 0 || xNew >= xBlockMax ||
yNew < 0 || yNew >= yBlockMax);
lastOppDirection = oppDir;
}
BOOL EXPENTRY ScrSaveProc(INT ssm, LPVOID l1, LONG_PTR l2, LONG_PTR l3)
{
static INT csecReblank;
CHAR FAR * lpsz;
CHAR FAR * lpch;
switch (ssm)
{
default:
return fFalse;
case SSM_OPEN:
lpsz = (PSZ) l1;
lpch = "Shuffle";
while ((*lpsz++ = *lpch++) != '\0')
;
lpsz = (PSZ) l2;
lpch = "Divide and\nShuffle Screen\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;
HBITMAP hbmp;
HBRUSH hbr, hbrOld;
HPEN hpenOld;
INT x, y;
ScrRestoreScreen();
cvs = (CVS) l1;
csecReblank = 60 * 20;
#ifdef DARKEN
/* Darken screen */
hbmp = NULL;
hbr = NULL;
/*hbmp = +++CreateBitmap - Not Recommended(use CreateDIBitmap)+++(8, 8, 1, 1, (LPSTR) &(rgbmp[ */
hbmp = CreateBitmap(8, 8, 1, 1, (LPSTR) &(rgbmp[
WRand(stdchance) ? WRand(ibmpMax) : WRand(ibmpStdMax)]));
if (hbmp == NULL)
goto LFail;
hbr = CreatePatternBrush(hbmp);
if (hbr == NULL)
goto LFail;
hbrOld = SelectObject(cvs, hbr);
PatBlt(cvs, 0, 0, dxScreen, dyScreen,
WRand(2) ? ROP_PANDD : ROP_INVPANDD);
SelectObject(cvs, hbrOld);
LFail:
if (hbmp != NULL)
DeleteObject(hbmp);
if (hbr != NULL)
DeleteObject(hbr);
#endif
/* Select and Blacken random block */
xBlockSize = 24 + 8*WRand(10);
yBlockSize = xBlockSize * GetDeviceCaps(cvs, ASPECTX)
/ GetDeviceCaps(cvs, ASPECTY);
yBlockSize = ((yBlockSize + 4) / 8) * 8; /* Round to nearest 8 */
if (yBlockSize == 0) /* Assure a minimum */
yBlockSize = 8;
xBlockMax = dxScreen / xBlockSize;
yBlockMax = dyScreen / yBlockSize;
xBlock = WRand(xBlockMax);
yBlock = WRand(yBlockMax);
PatBlt(cvs, xBlock * xBlockSize, yBlock * yBlockSize,
xBlockSize, yBlockSize, BLACKNESS);
/* Draw Gridlines */
hpenOld = SelectObject(cvs, GetStockObject(BLACK_PEN));
for (x = 0; x < dxScreen; x += xBlockSize)
{
(VOID)MMoveTo(cvs, x, 0);
LineTo(cvs, x, dyScreen);
}
for (y = 0; y < dyScreen; y += yBlockSize)
{
(VOID)MMoveTo(cvs, 0, y);
LineTo(cvs, dxScreen, y);
}
SelectObject(cvs, hpenOld);
}
break;
case SSM_SECOND:
if (csecReblank-- == 0)
ScrChooseRandomServer();
break;
case SSM_ANIMATE:
{
CVS cvs;
INT cd, step;
INT xSrc, ySrc;
INT xDest, yDest;
INT xFill, yFill;
INT dxFill, dyFill;
static INT iSkip = 0;
if (iSkip++ == 1)
{
iSkip = 0;
break;
}
cvs = (CVS) l1;
GetDxDy();
xBlock += dx;
yBlock += dy;
dx *= 4;
step = dx + dy;
if (step < 0)
step = -step;
/* Source */
xSrc = xBlock * xBlockSize;
ySrc = yBlock * yBlockSize;
/* Dest */
xDest = xSrc - dx;
yDest = ySrc - dy;
for (cd = 0; cd < (dx == 0 ? yBlockSize : xBlockSize); cd += step)
{
BitBlt(cvs, xDest, yDest, xBlockSize, yBlockSize,
cvs, xSrc, ySrc, SRCCOPY);
xFill = xSrc;
yFill = ySrc;
dxFill = dx > 0 ? dx : -dx;
dyFill = dy > 0 ? dy : -dy;
switch (dir)
{
case 0: /* Left */
dyFill = yBlockSize;
break;
case 1: /* Right */
xFill = xDest + xBlockSize;
dyFill = yBlockSize;
break;
case 2: /* Up */
yFill = yDest + yBlockSize;
dxFill = xBlockSize;
break;
case 3: /* Down */
dxFill = xBlockSize;
break;
}
PatBlt(cvs, xFill, yFill, dxFill, dyFill, BLACKNESS);
xSrc -= dx;
ySrc -= dy;
xDest -= dx;
yDest -= dy;
}
break;
}
}
return fTrue;
}