/*
 *	Process.c - Copyright © 1991 by S.R. & P.C.
 *
 *	Created:	01 Jun 1991  17:58:12
 *	Modified:	20 Jul 1991  12:26:54
 *
 *	Make>> make
 */

#include "Global.h"
#include "FileList.h"
#include "Process.h"
#include "Actions.h"
#include "proto/Process.h"
#include "proto/Windows.h"	/* for SetWaitPointer() */
#include "proto/FileList.h"
#include "proto/File.h"
#include "proto/Actions.h"
#include "proto/Copy.h"
#include "proto/ActionBack.h"

extern struct ExecBase *SysBase;
extern struct ArpBase *ArpBase;
extern struct Process *MainProcess;
extern struct BrowserWindow *CurrentWin;
extern struct Config Config;
extern struct ParMConfig ParMConfig;
extern struct MsgPort *ProcessPort;
extern short NumProcess;
extern char *ReqTitle;
extern char *Copyright;

void DummySegment(void);	/* for CreateProc() */
void geta4(void);

BPTR UntrackedDupLock(BPTR);
void UntrackedUnLock(BPTR);
#pragma	amicall(ArpBase, 0x60, UntrackedDupLock(d1))
#pragma	amicall(ArpBase, 0x5a, UntrackedUnLock(d1))


void FreeBrowserMsg(struct BrowserMsg *Msg)
{
	switch(Msg->bm_Type) {
	case BM_STARTUP:
		UntrackedUnLock(Msg->bm_Info.Startup.Lock);
		break;
	case BM_ACTIONBACK:
		CleanFileInfo(&Msg->bm_Info.ActionBack.sfi.FileInfo);
		break;
	case BM_UPDATEDIR:
		break;
	}
	FreeMem(Msg, sizeof(struct BrowserMsg));
}


void FreeProcessRepliedMsg(struct TaskData *TaskData)
{
	struct BrowserMsg *Msg;

	while(Msg = (struct BrowserMsg *)GetMsg(TaskData->td_ReplyPort)) {
		FreeBrowserMsg(Msg);
		TaskData->td_MsgCount--;
	}
}


void WaitAllMsg(struct TaskData *TaskData)
{
	while(TaskData->td_MsgCount > 0) {
		WaitPort(TaskData->td_ReplyPort);
		FreeProcessRepliedMsg(TaskData);
	}
}


struct BrowserMsg *AllocBrowserMsg(void)
{
	struct BrowserMsg *Msg;

	if (Msg = AllocMem(sizeof(struct BrowserMsg), MEMF_PUBLIC|MEMF_CLEAR)) {
		Msg->bm_ExecMessage.mn_Length = sizeof(struct BrowserMsg);
		Msg->bm_ExecMessage.mn_Node.ln_Type = NT_MESSAGE;
	}
	return Msg;
}


static struct BrowserMsg *AllocStartupMsg(void)
{
	struct BrowserMsg *Msg;

	if (!(Msg = AllocBrowserMsg()))
		return NULL;
	Msg->bm_ExecMessage.mn_ReplyPort = ProcessPort;
	Msg->bm_Type = BM_STARTUP;
	Msg->bm_Info.Startup.Lock = UntrackedDupLock(MainProcess->pr_CurrentDir);
	return Msg;
}


static void CreateBrowserProcess(struct BrowserMsg *Msg)
{
	struct MsgPort *Process;
	BPTR Segment;

	Segment = (long)DummySegment >> 2;
	if (Process = CreateProc("BrowserII Background Process", 0, Segment, 4096)) {
		PutMsg(Process, (struct Message *)Msg);
		NumProcess++;
	}
	else {
		SimpleRequest(ReqTitle, "Couldn't create process.\n%s.", StrIoErr());
		FreeMem(Msg, sizeof(struct BrowserMsg));
	}
}


void RunAction(struct HeadFileList *hfl, short ActionNum)
{
	struct BrowserMsg *Msg;
	BPTR DestDir = NULL;
	BOOL ASync;

	ASync = (Config.Options & OPT_ASYNCHRONOUS);
	if (ASync) {
		if (!(Msg = AllocStartupMsg()))
			return;
		Msg->bm_Info.Startup.ActionNum = ActionNum;
		Msg->bm_Info.Startup.hfl = hfl;
	}
	else {
		SetWaitPointer(TRUE);
		SetTaskPri((struct Task *)MainProcess, 0);
	}
	switch(ActionNum) {
	case BROWSERACTION_COPYMOVE:
		if (ASync)
			CreateBrowserProcess(Msg);
		else
			CopyMove(hfl);
		break;
	default:
		if (CurrentWin->bw_Type == BW_DIR)
			DestDir = DupLock(CurrentWin->bw_DirLock);
		if(hfl = MakeSelectedList(NULL, DestDir, NULL)) {
			if (ASync) {
				Msg->bm_Info.Startup.hfl = hfl;
				CreateBrowserProcess(Msg);
			}
			else
				InitAndDoAction(hfl, ActionNum);
		}
	}
	if (!ASync) {
		FreeFileList(hfl);
		SetWaitPointer(FALSE);
		SetTaskPri((struct Task *)MainProcess, 1);
	}
}


void ASyncWBRun(struct ParMConfig *PCfg, struct Extended_WBStartup *EWBS, BYTE Pri)
{
	struct BrowserMsg *Msg;
	struct Window *W;
	char buf[80];

	if (Config.Options & OPT_ASYNCHRONOUS) {
		if (!(Msg = AllocStartupMsg()))
			return;
		W = CurrentWin->bw_Window;
		SPrintf(buf, "BrowserII: Attempting to load \"%s\".", EWBS->WBStartup.sm_ArgList->wa_Name);
		SetWindowTitles(W, (char *)W->Title, buf);
		Msg->bm_Info.Startup.EWBS = EWBS;
		Msg->bm_Info.Startup.Pri = Pri;
		Msg->bm_Info.Startup.ActionNum = BROWSERACTION_WBRUN;
		CreateBrowserProcess(Msg);
		Delay(20);	/* Let user see the message */
		SetWindowTitles(W, (char *)W->Title, Copyright);
	}
	else
		WBRun(PCfg, EWBS, Pri);
}


/* Entry point of browser processes */

void BrowserProcess(void)
{
	struct Process *pp;
	struct BrowserMsg *Msg;
	struct TaskData *TaskData;
	struct HeadFileList *hfl;
	short ActionNum;

	geta4();
	pp = (struct Process *)SysBase->ThisTask;
	WaitPort(&pp->pr_MsgPort);
	Msg = (struct BrowserMsg *)GetMsg(&pp->pr_MsgPort);
	OpenLibrary("arp.library", 39L);	/* Arp resources are tracked for each process */
	CurrentDir(((struct BrowserMsg *)Msg)->bm_Info.Startup.Lock);
	pp->pr_COS = MainProcess->pr_COS;
	pp->pr_CIS = MainProcess->pr_CIS;
	TaskData = AllocMem(sizeof(struct TaskData), MEMF_PUBLIC|MEMF_CLEAR);
	TaskData->td_ReplyPort = CreatePort(0,0);
	pp->pr_Task.tc_UserData = (APTR)TaskData;
	hfl = Msg->bm_Info.Startup.hfl;
	ActionNum = Msg->bm_Info.Startup.ActionNum;
	switch(ActionNum) {
	case BROWSERACTION_COPYMOVE:
		CopyMove(hfl);
		FreeFileList(hfl);
		break;
	case BROWSERACTION_WBRUN:
		WBRun(&ParMConfig, Msg->bm_Info.Startup.EWBS, Msg->bm_Info.Startup.Pri);
		break;
	default:
		InitAndDoAction(hfl, ActionNum);
		FreeFileList(hfl);
	}
	WaitAllMsg(TaskData);
	DeletePort(TaskData->td_ReplyPort);
	FreeMem(TaskData, sizeof(struct TaskData));
	CloseLibrary(ArpBase);
	Forbid();
	ReplyMsg((struct Message *)Msg);
	/* end of Browser processes */
}



#asm

	public _DummySegment
	public _BrowserProcess

	cseg

_DummySegment:
	dc.l	0
	nop
	nop
	jmp		_BrowserProcess

#endasm


