#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/console_protos.h>
#include <clib/icon_protos.h>
#include <clib/intuition_protos.h>
#include <clib/macros.h>
#include <devices/input.h>
#include <exec/interrupts.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
#include <libraries/dosextens.h>
#include <workbench/startup.h>

struct NewWindow PassWindow = {
  0,0,0,60,0,1,
  NULL,
  NOCAREREFRESH+SMART_REFRESH+ACTIVATE,
  NULL,NULL,
  NULL,NULL,NULL,
  150,50,640,261,CUSTOMSCREEN };

struct Device *ConsoleDevice;
struct IOStdReq *InputReq, *ConsoleReq;
struct MsgPort *LockPort;
struct Interrupt HandlerStuff;

struct Task *LockTask;
WORD PassCount, OldPri;
struct Window *Wnd;
BOOL HandlerInstalled, InputOpened, DoGUI;
char *LeadTxt = "Please enter password:", *PassWord = "let me in";
char Entered[55];

LONG Result[4];
struct RDArgs *Args;
struct DiskObject *DiskObj;

void Center(char *, WORD);
void PrintStar(void);
__geta4 struct InputEvent *HotKeyHandler(__A0 struct InputEvent *, __A1 struct HotStuff *);
void InstallHandler(void);
void RemoveHandler(void);

extern struct GfxBase *GfxBase;
extern struct IntuitionBase *IntuitionBase;
extern struct WBStartup *_WBMsg;

_main(int argc, char *argv)
{
    if (_WBMsg)
    {
	CurrentDir(_WBMsg->sm_ArgList->wa_Lock);
	if (DiskObj = GetDiskObject(_WBMsg->sm_ArgList->wa_Name))
	{
	    char **toolarray;

	    toolarray = (char **)DiskObj->do_ToolTypes;

	    Result[0] = FindToolType(toolarray, "GUI");
	    Result[1] = FindToolType(toolarray, "LEADTXT");
	    Result[2] = FindToolType(toolarray, "PASSWORD");
	}
    } else if ( ! (Args = ReadArgs("GUI/S,LEADTXT,PASSWORD", Result, NULL)) )
    {
	PrintFault(IoErr(), NULL);
	RemoveHandler();
    }

    if (Result[0])
	DoGUI = TRUE;

    if (Result[1])
	LeadTxt = (char *)Result[1];

    if (Result[2])
	PassWord = (char *)Result[2];

    LockTask = FindTask(NULL);
    OldPri = SetTaskPri( LockTask, 127);

    if (DoGUI)
    {
	PassWindow.Screen = IntuitionBase->ActiveScreen;
	PassWindow.Width = PassWindow.Screen->Width;
	PassWindow.Height = MIN(GfxBase->DefaultFont->tf_YSize * 2 + 30, PassWindow.Screen->Height);
	PassWindow.TopEdge = (PassWindow.Screen->Height - PassWindow.Height) / 2;
	Wnd = OpenWindow(&PassWindow);
	if (!Wnd)
	    RemoveHandler();

	Center(LeadTxt, GfxBase->DefaultFont->tf_Baseline + 10);
    }

    InstallHandler();
    Wait(SIGBREAKF_CTRL_C);
    RemoveHandler();
}

void
Center(char *str, WORD y)
{
    WORD textlen = TextLength(Wnd->RPort, str, strlen(str));

    SetAPen(Wnd->RPort, 1);
    SetDrMd(Wnd->RPort, JAM2);
    Move(Wnd->RPort, (PassWindow.Width - textlen) / 2, y);
    Text(Wnd->RPort, str, strlen(str));
}

void
PrintStar(void)
{
    WORD i = 0;
    char stars[55];

    stars[i++] = ' ';
    for (; i<=PassCount; i++)
	stars[i] = '*';
    stars[i++] = ' ';
    stars[i++] = '\0';

    Center(stars, GfxBase->DefaultFont->tf_YSize + GfxBase->DefaultFont->tf_Baseline + 20);
}

__geta4 struct InputEvent *
HotKeyHandler(__A0 struct InputEvent *HotEvent,__A1 struct HotStuff *HotInfo)
{
    BOOL getout = FALSE;
    struct InputEvent *ev;

    Forbid();
    for (ev = HotEvent; ev; ev = ev->ie_NextEvent)
    {
	if (ev->ie_Class == IECLASS_RAWKEY)
	    if ( !(ev->ie_Code & IECODE_UP_PREFIX) )
	    {
		char t;

		if (DoGUI)
		{
		    if (ev->ie_Code == 65)
		    {
			if (PassCount)
			    PassCount--;
		    } else if (RawKeyConvert(ev, &t, 1, NULL) > 0)
		    {
			Entered[PassCount] = t;
			if (PassCount < 50)
			    PassCount++;
		    }
		    PrintStar();
		    Entered[PassCount] = 0;
		    if (strcmp(PassWord, Entered) == 0)
			getout = TRUE;
		} else
		{
		    if (RawKeyConvert(ev, &t, 1, NULL) > 0)
		    {
			if (t != PassWord[PassCount])
			    PassCount = (t == PassWord[0]);
			else
			    PassCount++;

			if (PassWord[PassCount] == '\0')
			    getout = TRUE;
		    }
		}
	    }

	if ((ev->ie_Class == IECLASS_RAWKEY) || (ev->ie_Class == IECLASS_RAWMOUSE))
	    HotEvent = ev->ie_NextEvent;
    }

    Permit();
    if (getout)
	Signal(LockTask, SIGBREAKF_CTRL_C);
    return(HotEvent);
}

void
InstallHandler(void)
{
    if( !(LockPort = CreatePort(NULL, NULL)))
	RemoveHandler();
    if( !(InputReq = CreateStdIO(LockPort)))
	RemoveHandler();

    HandlerStuff.is_Code = (ULONG (*)())HotKeyHandler;
    HandlerStuff.is_Node.ln_Pri = 127;

    if(OpenDevice("input.device", NULL, InputReq, NULL) != NULL)
	RemoveHandler();
    InputOpened = TRUE;

    InputReq->io_Command = IND_ADDHANDLER;
    InputReq->io_Data = (APTR)&HandlerStuff;
    DoIO(InputReq);
    HandlerInstalled = TRUE;

    if( !(ConsoleReq = CreateStdIO(LockPort)))
	RemoveHandler();
    if(OpenDevice("console.device", -1, ConsoleReq, NULL) != NULL)
	RemoveHandler();
    ConsoleDevice = ConsoleReq->io_Device;
}

void
RemoveHandler(void)
{
    SetTaskPri( LockTask, OldPri);

    if (Args)
	FreeArgs(Args);

    if (DiskObj)
	FreeDiskObject(DiskObj);

    if (Wnd)
	CloseWindow(Wnd);

    if(InputReq)
    {
	if (HandlerInstalled)
	{
	    InputReq->io_Command = IND_REMHANDLER;
	    InputReq->io_Data = (APTR)&HandlerStuff;
	    DoIO(InputReq);
	}
	if (InputOpened)
	    CloseDevice(InputReq);
	DeleteStdIO(InputReq);
    }

    if (ConsoleReq)
    {
	if (ConsoleDevice)
	    CloseDevice(ConsoleReq);
	DeleteStdIO(ConsoleReq);
    }

    if (LockPort)
	DeletePort(LockPort);
    _exit(0);
}

routine_that_is_never_called()
{
    _waitwbmsg();
}

