/* misc.c */

#include <OSIncludes.h>

#pragma header

#include "KeyReq.h"

static void GadSelect(struct Gadget *gad,struct Window *win,BOOL on)
{
	LONG oldpos;
	
	oldpos=RemoveGadget(win,gad);

	if (on)
	{
		gad->Flags|=GFLG_SELECTED;
	} else {
		gad->Flags&=(~GFLG_SELECTED);
	}

	AddGadget(win,gad,oldpos);
	RefreshGList(gad,win,0,1);
}

struct Gadget *FindGadget(struct Window *win,WORD id)
{
	struct Gadget *gad;
	
	gad=win->FirstGadget;

	while (gad)
	{
		if ((gad->GadgetType&GTYP_SYSTYPEMASK)==0)
		if (gad->TopEdge>win->BorderTop)
		{
			if (gad->GadgetID==id)
			{
				break;
			}
		}
		gad=gad->NextGadget;
	}
	
	return gad;
}

BOOL KeyGadget(struct Window *win,struct Gadget *gad,WORD icode)
{
	struct IntuiMessage *msg;
	ULONG oldidcmp;
	BYTE buff[2];
	char c;
	BOOL rc=TRUE,exitme=FALSE,exitok=FALSE;
	
	c=icode;
	if (gad && (!(Flags&PFLG_NOKEYGADGET)) &&(MapANSI(&c,1,buff,1,0)==1))
	{
		if (buff[0]==67) buff[1]=68;
			else if (buff[0]==68) buff[1]=67;
				else buff[1]=buff[0];
		
		oldidcmp=win->IDCMPFlags;
		ModifyIDCMP(win,IDCMP_RAWKEY);
		
		GadSelect(gad,win,TRUE);
		
		while(!(exitme && exitok))
		{
			WaitPort(win->UserPort);
			while ((msg=(struct IntuiMessage *)GetMsg(win->UserPort)))
			{
				if (msg->Class==IDCMP_RAWKEY)
				{
					if (!exitme)
					{
						// LSHIFT, RSHIFT, ESC?
						if (msg->Code==0x60 || msg->Code==0x61 || (buff[0]!=69 && msg->Code==69))
						{
							rc=FALSE;exitme=TRUE;
							GadSelect(gad,win,FALSE);
						}
					}
					// initial key released?
					if (msg->Code==(buff[0] | IECODE_UP_PREFIX) || msg->Code==(buff[1] | IECODE_UP_PREFIX))
					{
						exitme=TRUE;
						exitok=TRUE;
					}
				}
				ReplyMsg((struct Message *)msg);
			}		
		}
		GadSelect(gad,win,FALSE);
		ModifyIDCMP(win,oldidcmp);
	}
	
	return rc;
}

void HighlightGadget(struct Window *win,struct DrawInfo *di,WORD gid,WORD mode, WORD col)
{
	static UWORD pat[8]={0x5555,0xAAAA};
	struct Gadget *gad;
	
	if (!(Flags&PFLG_NOHIGHLIGHT))
	if ((gad=FindGadget(win,gid)))
	{
		if (mode==GRMOD_NORMAL)
		{
			SetAPen(win->RPort,col);
		} else {
			SetAPen(win->RPort,di ? di->dri_Pens[SHINEPEN] : 2);
			SetBPen(win->RPort,di ? di->dri_Pens[BACKGROUNDPEN] : 0);
			SetAfPt(win->RPort,pat,1);
		}
		
		RectFill(win->RPort,gad->LeftEdge-1,gad->TopEdge-1,gad->LeftEdge+gad->Width,gad->TopEdge-1);
		RectFill(win->RPort,gad->LeftEdge+gad->Width,gad->TopEdge,gad->LeftEdge+gad->Width,gad->TopEdge+gad->Height);
		RectFill(win->RPort,gad->LeftEdge-1,gad->TopEdge+gad->Height,gad->LeftEdge+gad->Width-1,gad->TopEdge+gad->Height);
		RectFill(win->RPort,gad->LeftEdge-1,gad->TopEdge,gad->LeftEdge-1,gad->TopEdge+gad->Height-1);
		
		if (mode!=GRMOD_NORMAL)
		{
			WaitBlit();
			SetAfPt(win->RPort,0,0);
		}
	
	} // if ((gad=FindGadget ...
}

struct ReqEntry *Add_Requester(struct Window *req)
{
	struct ReqEntry *r;
	
	// since only a very small piece of memory will
	// be alloced I use MEMF_REVERSE to avoid frag-
	// mentation. Memory pools? What's that ;)

	if ((r=AllocVec(sizeof(struct ReqEntry),MEMF_PUBLIC|MEMF_CLEAR|MEMF_REVERSE)))
	{
		r->req=req;
		ObtainSemaphore(&ReqSem);
		AddTail(&ReqList,&r->node);
		ReleaseSemaphore(&ReqSem);
	}

	return r;
}

struct ReqEntry *Find_Requester(struct Window *req)
{
	struct ReqEntry *r;
	
	ObtainSemaphoreShared(&ReqSem);

	r=(struct ReqEntry *)ReqList.lh_Head;
	while (r->node.ln_Succ)
	{
		if (r->req == req) break;
		r=(struct ReqEntry *)r->node.ln_Succ;
	}
	
	ReleaseSemaphore(&ReqSem);
	
	return r->node.ln_Succ ? r : 0;
}

void Remove_Requester(struct ReqEntry *r)
{
	if (r)
	{
		ObtainSemaphore(&ReqSem);
		Remove(&r->node);
		ReleaseSemaphore(&ReqSem);

		if ((r->highcol != -1) && (HCTyp==HCTYP_RGB))
		{
			ReleasePen(r->req->WScreen->ViewPort.ColorMap,r->highcol);
		}

		FreeVec(r);
	}
}

BOOL OutOfAction(void)
{
	BOOL rc=FALSE;
	
	ObtainSemaphore(&ReqSem);
	if ((IsListEmpty(&ReqList)) && (ReqEntryCount==0)) rc=TRUE;
	ReleaseSemaphore(&ReqSem);
	
	return rc;
}

char *GetTaskName(void)
{
	struct CommandLineInterface *cli;
	struct Task *task;
	char *rc;

	task=FindTask(0);

	rc=task->tc_Node.ln_Name;

	if (task->tc_Node.ln_Type == NT_PROCESS)
	{
		if ((cli=(struct CommandLineInterface *)BADDR(((struct Process *)task)->pr_CLI)))
		{
			if (cli->cli_CommandName)
			{
				rc=BADDR(cli->cli_CommandName);
				rc++;
			}
		}
	}
	
	return rc;
}


