/*
 *	PatchReq-Seg.c - Copyright © 1991 by Devil's child.
 *
 *	Created:	27 Jan 1991  19:32:31
 *	Modified:	25 Jul 1991  19:47:22
 *
 *	Make>> cc -qf -ps -m0b -md -so -sb -wu -wd -wp -hi ram:small.sym <file>.c
 *	Make>> ln <file>.o -lreql
 *
 *	MUST be compiled in LARGE_DATA model to allow access to global data from
 *	different processes and loader.
 */


#define BUFSIZE 2000
#define SOFTWARE_ERROR	"Software error"
#define ERROR_STR_LEN	14


/* defined in loader too */
#define	DIR_CACHE	1
#define NOAUTOREQ	2


struct ExtendedFileReq {
	struct FileReq Freq;
	char File[REQ_FCHARS+1];
	char Dir[REQ_DSIZE+1];
	char Path[REQ_DSIZE+REQ_FCHARS+2];
};


struct ExecBase *SysBase;
struct ArpBase *ArpBase;
struct ReqLib *ReqBase;
struct IntuitionBase *IntuitionBase;
PVF FuncTab[3];

/* directory cache handling variables */
struct ExtendedFileReq *LastEFR;
short Usage;
short PatchFlags; 
long (*OldTextRequest)();
long (*OldAutoRequest)();

void setmem(void *mem, size_t size, long value);


long AsmOldAutoReq(struct Window *Window, struct IntuiText *Body, struct IntuiText *PText, struct IntuiText *NText, long PFlag, long NFlag, long W, long H);
#pragma regcall(AsmOldAutoReq(a0,a1,a2,a3,d0,d1,d2,d3))

long NewAutoRequest(struct Window *Window, struct IntuiText *Body, struct IntuiText *PText, struct IntuiText *NText, long PFlag, long NFlag, long W, long H);
#pragma regcall(NewAutoRequest(a0,a1,a2,a3,d0,d1,d2,d3))

long NewTextRequest(struct TRStructure *TRS);
#pragma regcall(NewTextRequest(a0))

long NewFileRequest(struct FileRequester *);
#pragma regcall(NewFileRequest(a0))


PVF *Setup(struct ArpBase *Arp, struct ReqLib *Req, long (*OldTR)(), long (*OldAR)(), short Flags)
{
	SysBase = *((struct ExecBase **)4L);
	ArpBase = Arp;
	ReqBase = Req;
	IntuitionBase = ReqBase->IntuiLib;
	OldTextRequest = OldTR;
	OldAutoRequest = OldAR;
	PatchFlags = Flags;
	FuncTab[0] = (PVF)NewAutoRequest;
	FuncTab[1] = (PVF)NewTextRequest;
	FuncTab[2] = (PVF)NewFileRequest;
	return FuncTab;
}


char *WideText(char *Text, char *buf)
{
	if (strlen(Text) <= 3) {
		Format(buf, " %s ", Text);
		return buf;
	}
	else
		return Text;
}


long NewAutoRequest(struct Window *Window, struct IntuiText *Body, struct IntuiText *PText, struct IntuiText *NText, long PFlag, long NFlag, long W, long H)
{
	struct Process *ThisProc;
	struct IntuiText *IT;
	struct TRStructure TRS;
	char nbuf[6],pbuf[6],ProcName[40],CliNum[30],space[10];
	char *s,*d;
	long RC;
	BOOL Guru = FALSE;
	short i;

	if (!Strncmp((char *)Body->IText, SOFTWARE_ERROR, ERROR_STR_LEN))
		Guru = TRUE;
	else if (PatchFlags & NOAUTOREQ)
		return AsmOldAutoReq(Window, Body, PText, NText, PFlag, NFlag, W, H);
	setmem(&TRS, sizeof(struct TRStructure), 0);
	TRS.Text = d = AllocMem(BUFSIZE, MEMF_PUBLIC);
	TRS.Window = Window;
	if (PText) TRS.PositiveText = WideText((char *)PText->IText, pbuf);
	if (NText) TRS.NegativeText = WideText((char *)NText->IText, nbuf);
	TRS.Title = "System Request";
	TRS.KeyMask = 0xFFFF;
	TRS.textcolor = 1;
	TRS.detailcolor = (Window) ? Window->DetailPen : 0;
	TRS.blockcolor = (Window) ? Window->BlockPen : 1;
	if (Guru) {
		TRS.PositiveText = "Suspend";
		ThisProc = (struct Process *)SysBase->ThisTask;
		if (ThisProc->pr_Task.tc_Node.ln_Type == NT_TASK || !ThisProc->pr_CLI) {
			s = ThisProc->pr_Task.tc_Node.ln_Name;
			CliNum[0] = 0;
		}
		else {
			BtoCStr(ProcName, ((struct CommandLineInterface *)(ThisProc->pr_CLI << 2))->cli_CommandName, 80);
			s = BaseName(ProcName);
			Format(CliNum, "\n        CLI Number %ld", ThisProc->pr_TaskNum);
		}
		strcpy(space, "        ");
		i = 16-strlen(s);
		space[(i>0) ? i>>1 : 0] = '\0';
		Format(d, "       Software error\n%sTask \"%s\" held%s\n ", space, s, CliNum);
		d += strlen(d);
		IT = Body->NextText;
	}
	else
		IT = Body;
	while(IT) {
		s = (char *)IT->IText;
		while(*d++ = *s++);
		*(d-1) = '\n';
		*d = '\0';
		IT = IT->NextText;
	}
	*(d-1) = '\0';
	RC = TextRequest(&TRS);
	FreeMem(TRS.Text, BUFSIZE);
	if (Guru == TRUE && RC)
		Wait(0L);
	else
		return RC;
}


long NewFileRequest(struct FileRequester *ArpFR)
{
	struct ExtendedFileReq *EFR;
	long RC;
	BOOL KeepIt = FALSE;

	if (strlen(ArpFR->fr_Dir) == 0)
		PathName(((struct Process *)SysBase->ThisTask)->pr_CurrentDir, ArpFR->fr_Dir, LONG_DSIZE);
	Forbid();
	if (!(EFR = LastEFR) || Usage != 0)
		EFR = AllocMem(sizeof(struct ExtendedFileReq), MEMF_PUBLIC|MEMF_CLEAR);
	if ((PatchFlags & DIR_CACHE) && Usage == 0) {
		Usage = 1;
		KeepIt = TRUE;
		LastEFR = EFR;						/* needed first call */
		EFR->Freq.Flags = FRQCACHINGM;		/* needed first call */
		if (Strcmp(EFR->Dir, ArpFR->fr_Dir))
			PurgeFiles((struct FileReq *)EFR);
	}
	Permit();
	if (!EFR)
		return 0;
	EFR->Freq.Dir = EFR->Dir;
	EFR->Freq.File = EFR->File;
	EFR->Freq.PathName = EFR->Path;
	EFR->Freq.Flags |= FRQINFOGADGETM;
	EFR->Freq.dirnamescolor = 3;
	EFR->Freq.devicenamescolor = 3;
	EFR->Freq.stringnamecolor = 2;
	EFR->Freq.stringgadgetcolor = 2;
	EFR->Freq.boxbordercolor = 2;
	EFR->Freq.gadgetboxcolor = 2;
	EFR->Freq.Window = ArpFR->fr_Window;
	strcpy(EFR->Dir, ArpFR->fr_Dir);
	strcpy(EFR->File, ArpFR->fr_File);
	EFR->Freq.Title = ArpFR->fr_Hail;
	RC = FileRequester((struct FileReq *)EFR);
	if (RC) {
		strcpy(ArpFR->fr_Dir, EFR->Dir);
		strcpy(ArpFR->fr_File, EFR->File);
	}
	if ((PatchFlags & DIR_CACHE) && KeepIt)
		Usage = 0;
	else
		FreeMem(EFR, sizeof(struct ExtendedFileReq));
	return RC;
}


#asm

ThisTask		equ		276
pr_WindowPtr	equ		184
WBenchToFront	equ		-342
Window			equ		8

		far 	data				; large data model

		xdef	_Format
		xdef	_NewTextRequest
		xdef	_AsmOldAutoReq

_NewTextRequest:
		movem.l	a3/a6,-(sp)
		move.l	a0,a3				; save TRS
		move.l	_SysBase,a0
		move.l	ThisTask(a0),a1
		tst.l	Window(a3)
		bne		EndIf
		tst.l	pr_WindowPtr(a1)
		bne		EndIf
		move.l	_IntuitionBase,a6
		jsr		WBenchToFront(a6)
EndIf
		move.l	a3,a0				; give back TRS to a0
		move.l	_OldTextRequest,a1
		move.l	_ReqBase,a6
		jsr		(a1)
		movem.l	(sp)+,a3/a6
		rts


_AsmOldAutoReq:
		movem.l	a4/a6,-(sp)
		move.l	_IntuitionBase,a6
		move.l	_OldAutoRequest,a4
		jsr		(a4)
		movem.l	(sp)+,a4/a6
		rts		


		public _setmem

_setmem
		move.l	4(sp),a0
		movem.l	8(sp),d0/d1
		bra		.l2
.l1
		move.b	d1,(a0)+
.l2
		dbra	d0,.l1
		rts

#endasm
