/************************************************************/
/*                                                          */
/* Sample source for Moire 2 screen saver for Intermission  */
/*                                                          */
/* This code shows how to use the hsvpal.h information for  */
/* 15 and 24 bit graphics modes. No other files for this    */
/* project have been provided.                              */
/*                                                          */
/* Copyright (C) 1990,1991 Anthony Andersen                 */
/*                                                          */
/* All rights reserved.                                     */
/*                                                          */
/* The author grants permission for registered owners of    */
/* Intermission to modify this code to create new screen    */
/* savers and to distribute the modified savers freely.     */
/* This sample code is only legally available to registered */
/* users of Intermission.                                   */
/*                                                          */
/************************************************************/



#include <windows.h>
#include "moire2.h"
#include "hsvpal.h"

unsigned long seed;
char buffer[10];


char savername[]  = "Moire 2";
char profname[]   = "ANTSW.INI";
char clearcount[] = "Clear Count";
char colchang[]   = "Color Change";
char step[]       = "Step";

RECT      rect;
int       clipcx;
int       clipcy;
HBRUSH    hbrush;
unsigned  colormax;
unsigned  color;
int       x;
int       y;
int       dir;
int       count;
int       fillcount;
int       offset;
int       corner;
int       cornerx;
int       cornery;
int       totcount;
int       colorchange;

HANDLE    holdpen;
HANDLE    pen;
COLORREF  cr;



/* this is called by the default dll entry code during the  */
/* load library call - always happens BEFORE any other call */
/* in the dll.                                              */

int FAR PASCAL LibMain(hModule, wDataSeg, cbHeapSize, lpszCmdLine)

HANDLE	hModule;
WORD     wDataSeg;
WORD     cbHeapSize;
LPSTR    lpszCmdLine;

{

   /* set up things here */

	fillcount = GetPrivateProfileInt(savername,clearcount,20,profname);
	offset = GetPrivateProfileInt(savername,step,5,profname);
	colorchange = GetPrivateProfileInt(savername,colchang,20,profname);

	return (1);
}


/* this is called by Windows when the dll is released */

int FAR PASCAL WEP (bSystemExit)
int  bSystemExit;

{
    /* get rid of things you allocated in the LibMain proc here */

    return (1);
}

/* this is called (probably lots of times) by Screen Peace */
/* be careful not to allocate memory in here               */

char FAR * FAR PASCAL saverinit(BOOL far *realize)

{
	/* tell enable state */

	*realize = 2; // get HSV color table

	return(savername);
}

/* dialog proc for user customization */

BOOL FAR PASCAL saverdlgproc(HWND hdlg,unsigned message,WORD wparam,LONG lparam)

{
	int i;
	int whichfield;
	int minval;
	int maxval;

	switch (message) {

	case WM_INITDIALOG:
		SetDlgItemInt(hdlg,5,offset,FALSE);
		SetDlgItemInt(hdlg,6,fillcount,FALSE);
		SetDlgItemInt(hdlg,7,colorchange,FALSE);

		SetScrollRange(GetDlgItem(hdlg,25),SB_CTL,1,1280,FALSE);
		SetScrollPos(GetDlgItem(hdlg,25),SB_CTL,offset,FALSE);

		SetScrollRange(GetDlgItem(hdlg,26),SB_CTL,0,5000,FALSE);
		SetScrollPos(GetDlgItem(hdlg,26),SB_CTL,fillcount,FALSE);

		SetScrollRange(GetDlgItem(hdlg,27),SB_CTL,1,2000,FALSE);
		SetScrollPos(GetDlgItem(hdlg,27),SB_CTL,colorchange,FALSE);

		return (TRUE);
		break;

	case WM_HSCROLL:

		whichfield = GetDlgCtrlID((HWND)(HIWORD(lparam)))-20;
		i = GetDlgItemInt(hdlg,whichfield,NULL,FALSE);

		switch (whichfield) {

		case 5:
			minval = 1;
			maxval = 1280;
			break;
		case 6:
			minval = 0;
			maxval = 5000;
			break;
		case 7:
			minval = 1;
			maxval = 2000;
			break;

		}

		switch (wparam) {

		case SB_LINEDOWN:
			if (i<maxval) i++;
			break;

		case SB_LINEUP:
			if (i>minval) i--;
			break;

		case SB_PAGEDOWN:
			if (i<=maxval-10) i += 10;
			else i = maxval;
			break;

		case SB_PAGEUP:
			if (i>=minval+10) i -= 10;
			else i = minval;
			break;

		case SB_BOTTOM:
			i = maxval;
			break;

		case SB_TOP:
			i = minval;
			break;

		case SB_THUMBTRACK:
		case SB_THUMBPOSITION:
			i = LOWORD(lparam);
			break;

		}

		SetDlgItemInt(hdlg,whichfield,i,FALSE);
		SetScrollPos(GetDlgItem(hdlg,whichfield+20),SB_CTL,i,TRUE);
		break;

	case WM_COMMAND:
		if (wparam == IDOK) {

			offset = GetDlgItemInt(hdlg,5,NULL,FALSE);
			wsprintf(buffer,"%d",offset);
			WritePrivateProfileString(savername,step,buffer,profname);

			fillcount = GetDlgItemInt(hdlg,6,NULL,FALSE);
			wsprintf(buffer,"%d",fillcount);
			WritePrivateProfileString(savername,clearcount,buffer,profname);

			colorchange = GetDlgItemInt(hdlg,7,NULL,FALSE);
			wsprintf(buffer,"%d",colorchange);
			WritePrivateProfileString(savername,colchang,buffer,profname);

			EndDialog(hdlg,TRUE);
			return (TRUE);
		}
		else if (wparam == IDCANCEL) {
			EndDialog(hdlg,FALSE);
			return (TRUE);
		}
      break;
	}

	return (FALSE);
}

/* returns pseudorandom number from 0 to x-1 */

int arand(int x)
{
	seed = seed*0x343fd+0x269ec3;
	return (int)(((seed>>16)&0x7fff)*x>>15);
}

COLORREF makehsv(HPALETTE hpal,int thecolor)

{
	COLORREF   cr;

	cr = hsvpal[thecolor];

	if (hpal) cr = PALETTEINDEX(GetNearestPaletteIndex(hpal,cr));
	else if (colormax == 13) {
		cr = hsv4bit[thecolor];
	}
	else if (colormax == 2) {
		cr = 0xFFFFFF;
	}

	return (cr);
}

/* the main drawing routine */

VOID FAR PASCAL saverdraw(HWND hwnd,HDC hdc,HANDLE hinst,HPALETTE hpal,int opcode)

{
	int resbits;

	if (opcode == 1) {
		if (GetDeviceCaps(hdc,RASTERCAPS) & RC_PALETTE) {
			colormax = GetDeviceCaps(hdc,SIZEPALETTE);  // have color palette

			if (colormax < 100) colormax = 16;          // doesn't work with
		}                                              // less than 100 entry
                                                     // palettes
		else {
			resbits = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
			if (resbits <= 8)	colormax = 1<<(resbits);  // no palette
			else colormax = 0xFFFF;                     // 15 or 24 bit color
		}
		if (colormax == 256) colormax = 215;           // only 216 colors in palette
		else if (colormax == 16) colormax = 13;        // only 13 colors in array

		GetClipBox(hdc,&rect);

		clipcx = rect.right-rect.left;
		clipcy = rect.bottom-rect.top;

		/* seed the pseudorandom number generator */

		seed = GetTickCount();

		/* erase background */

		hbrush = GetStockObject(BLACK_BRUSH);
		FillRect(hdc,&rect,hbrush);

		color = 0;
		x = rect.left;
		y = rect.top;
		dir = 0;
		count = 0;
		cornerx = arand(clipcx)+rect.left;
		cornery = arand(clipcy)+rect.top;
		totcount = 0;
	}

	else if (!opcode) {

		cr = makehsv(hpal,color);

		pen = CreatePen(PS_SOLID,1,cr);

		holdpen = SelectObject(hdc,pen);

		MoveTo(hdc,cornerx,cornery);
		LineTo(hdc,x,y);

		SelectObject(hdc,holdpen);
		DeleteObject(pen);

		totcount++;
		if (totcount == colorchange) {
			color++;
			totcount = 0;
		}

		if (color >= colormax || color >= 216) color = 0;

		if (!dir) {
			if (x < rect.right-offset) x += offset;
			else {
				x = rect.right;
				dir = 1;
			}
		}
		else if (dir == 1) {
			if (y < rect.bottom-offset) y += offset;
			else {
				y = rect.bottom;
				dir = 2;
			}
		}
		else if (dir == 2) {
			if (x > rect.left+offset) x -= offset;
			else {
				x = rect.left;
				dir = 3;
			}
		}
		else if (dir == 3) {
			if (y > rect.top+offset) y -= offset;
			else {
				cornerx = arand(clipcx)+rect.left;
				cornery = arand(clipcy)+rect.top;
				x = rect.left;
				y = rect.top;
				dir = 0;
				count++;
				if (count == fillcount) {
					FillRect(hdc,&rect,hbrush);
					count = 0;
				}
			}
		}
	}
}
