
/*
 *  BLANKER.C
 *
 *  Example external screen blanker for DMouse.
 */

#include <local/typedefs.h>
#include <local/ipc.h>
#include <local/xmisc.h>

#ifdef LATTICE
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int __stdargs CXBRK(void);

__stdargs	/*  bug in lcr.lib  */
CXBRK()
{
    return(0);
}

#else
extern int Enable_Abort;    /*	CLI break enable	*/
#endif


#define RATE	1000000

typedef struct IORequest IORequest;

static SCR *Scr;
static TA   Ta = {  (ubyte *)"topaz.font", 8 };
static NS   Ns = {  0, 0, 320, -1, 1, -1, -1, 0, CUSTOMSCREEN|SCREENQUIET, &Ta };

static IOT Iot;
static char Ioip;
static char *TStr = "Blank";
static char *TSpa = "     ";
static long TLen = 5;

void main ARGS((int, char **));
void screenon ARGS((void));
void screenoff ARGS((void));
void screengraphics ARGS((void));
long myrand ARGS((void));

void
main(ac,av)
char **av;
{
    PORT *dmport;
    PORT *ipport;
    PORT *tp;
    IORequest	AddReq;
    IORequest	RemReq;
    char foo;	/*  dummy   */
    char notdone = 1;

#ifndef LATTICE
    Enable_Abort = 0;
#endif

    tp	   = CreatePort(NULL, 0);
    ipport = CreatePort(NULL, 0);

    AddReq.io_Message.mn_ReplyPort = ipport;
    AddReq.io_Command = 0x84;
    AddReq.io_Unit = (struct Unit *)&foo;
    AddReq.io_Flags = 0x0C;	/* %1100 (screen blanker, no mouse blanker) */

    RemReq.io_Message.mn_ReplyPort = ipport;
    RemReq.io_Command = 0x85;
    RemReq.io_Unit = (struct Unit *)&foo;

    if (openlibs(INTUITION_LIB|GRAPHICS_LIB) == 0)
	goto fail;
    if (OpenDevice("timer.device", UNIT_VBLANK, &Iot, 0)) {
	Write(Output(), "Unable to open timer.device\n", 28);
	goto fail;
    }
    Iot.tr_node.io_Message.mn_ReplyPort = tp;
    Iot.tr_node.io_Command = TR_ADDREQUEST;

    SetSignal(0, SIGBREAKF_CTRL_C);
    Forbid();
    if (dmport = FindPort("DMouse.ipc"))
	PutMsg(dmport, &AddReq.io_Message);
    Permit();
    if (dmport == NULL) {
	puts("DMouse not running or <V1.20");
	goto fail;
    }

    while (notdone) {
	long mask = (1 << tp->mp_SigBit) | (1 << ipport->mp_SigBit) | SIGBREAKF_CTRL_C;
	mask = Wait(mask);

	if (mask & SIGBREAKF_CTRL_C) {
	    notdone = 0;
	}
	if ((mask & (1 << tp->mp_SigBit)) && Scr && Ioip && CheckIO(&Iot)) {
	    WaitIO(&Iot);
	    Iot.tr_time.tv_secs  = RATE / 1000000;
	    Iot.tr_time.tv_micro = RATE % 1000000;
	    SendIO(&Iot);
	    screengraphics();
	}
	if (mask & (1 << ipport->mp_SigBit)) {
	    IORequest *ior;
	    while (ior = (IORequest *)GetMsg(ipport)) {
		if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {   /* my AddHand req */
		    notdone = 0;
		    continue;
		}
		switch(ior->io_Command) {
		case 0x80:
		case 0x81:
		    break;
		case 0x82:
		    screenon();
		    break;
		case 0x83:
		    screenoff();
		    break;
		case 0x86:
		    notdone = 0;
		    break;
		}
		ReplyMsg(&ior->io_Message);
	    }
	}
    }
    PutMsg(dmport, &RemReq.io_Message);
    WaitMsg(&RemReq);
    {
	register IORequest *ior = NULL;
	while (ior != &AddReq) {    /*  last msg will be AddReq */
	    WaitPort(ipport);
	    ior = (IORequest *)GetMsg(ipport);
	    if (ior->io_Message.mn_Node.ln_Type == NT_MESSAGE)
		ReplyMsg(&ior->io_Message);
	}
    }
fail:
    if (Ioip) {
	AbortIO(&Iot);
	WaitIO(&Iot);
    }
    if (Iot.tr_node.io_Device)
	CloseDevice(&Iot);
    if (tp)
	DeletePort(tp);
    if (ipport)
	DeletePort(ipport);
    closelibs(-1);
}

void
screenoff()
{
    if (Scr)
	ScreenToFront(Scr);
    else if (Scr = OpenScreen(&Ns)) {
	if (!Ioip) {
	    Iot.tr_time.tv_secs  = 3;
	    Iot.tr_time.tv_micro = 0;
	    SendIO(&Iot);
	    Ioip = 1;
	}
    }
}

void
screenon()
{
    if (Scr)
	CloseScreen(Scr);
    Scr = NULL;
    if (Ioip) {
	AbortIO(&Iot);
	WaitIO(&Iot);
	Ioip = 0;
    }
}

/*
 *  Simple Stupid
 *
 *  Warning:  Note that no clipping is done when using the screen's
 *	      rastport, all rendering must be IN BOUNDS!
 */

void
screengraphics()
{
    static short oldx, oldy;
    short x, y;

    x = (myrand() & 4095) % (Scr->Width - TextLength(&Scr->RastPort, TStr, TLen) - 8);
    y = (myrand() & 4095) % (Scr->Height- Scr->RastPort.TxHeight - Scr->RastPort.TxBaseline - 8);
    if (x < 0 || y < 0)
	return;
    y += Scr->RastPort.TxBaseline + 4;

    SetAPen(&Scr->RastPort, 0);
    Move(&Scr->RastPort, oldx, oldy);
    Text(&Scr->RastPort, TSpa, TLen);

    oldx = x;
    oldy = y;
    SetRGB4(&Scr->ViewPort, 1, myrand()&15, myrand()&15, myrand()&15);

    SetAPen(&Scr->RastPort, 1);
    Move(&Scr->RastPort, oldx, oldy);
    Text(&Scr->RastPort, TStr, TLen);
}


long
myrand()
{
    static long rv = 34987;
    rv = (rv * 13 + 1) ^ (rv >> 13);
    return(rv);
}



