#include "PostPre.h"
#include "Global.h"
#include "Global.c"

#include <dos/dostags.h>
#include <proto/utility.h>

#define	TICKS_TO_DELAY	5
#define	SCROLL_INC		15

void	__regargs __chkabort(void);
void	__regargs __chkabort(void) { return; }

int	main (int argc, char **argv)
{
	ULONG		rec_sig;
	int		i, idcmpupdate_ticks = 0;
	int		(*func)(void);
	struct	Message *msg;
	struct	MenuItem *tempitem;
	UWORD		code;
	char		subtaskname[30];

	strcpy(pubscreenname, STD_PUBSCREEN);

	Options			= DefaultOptions;
	IffOptions		= DefaultOptions;
	PrintOptions	= DefaultOptions;
	NewOptions		= DefaultOptions;

	init_list(&DefaultOptions.startuplist);
	init_list(&Options.startuplist);
	init_list(&IffOptions.startuplist);
	init_list(&PrintOptions.startuplist);
	init_list(&NewOptions.startuplist);
	LoadPostOptions("ENV:POST", &Options);
	LoadPostOptions("ENV:POST", &NewOptions);
	LoadPostOptions("ENV:POST.iff", &IffOptions);
	LoadPostOptions("ENV:POST.print", &PrintOptions);

	strcpy(pubscreenname, Options.Screen.pubscrname);
	if(open_libs() == FALSE)
	{
		close_libs();
		return(20);
	}

	Forbid();
	do
	{
		post_count++;
		sprintf(subtaskname, "post%d.render", post_count);
	} while (FindTask(subtaskname));
	Permit();

	if(parse(argc, NULL))
	{
		close_libs();
		return(20);
	}

	RexxStuff=InitARexx(AREXXPORTNAME, AREXXEXTENSION);

	if(argwindow)
	{
		filerequester = (struct FileRequester *) AllocAslRequestTags(ASL_FileRequest,
						ASLFR_SleepWindow,	TRUE,
						ASLFR_PrivateIDCMP,	TRUE,
						ASLFR_DoPatterns,		TRUE,
						ASLFR_InitialPattern,(ULONG) "(#?.ps|#?.eps|#?.epsf)",
						ASLFR_InitialDrawer,	(ULONG) Options.lastdir,
						ASLFR_InitialFile, 	(ULONG) FilePart(Options.lastfile),
						ASLFR_InitialHeight, 300,
						TAG_DONE);
		filereq = filerequester;
		if (filerequester == NULL)
		{
			okmsg("can't get file requester");
			errorende();
			return(20);
		}
		fontrequester = (struct FileRequester *) AllocAslRequestTags(ASL_FileRequest,
						ASLFR_SleepWindow,	TRUE,
						ASLFR_PrivateIDCMP,	TRUE,
						ASLFR_DoPatterns,		TRUE,
						TAG_DONE);
		if (fontrequester == NULL)
		{
			okmsg("can't get file requester");
			errorende();
			return(20);
		}
	}
	if((mainport = CreatePort(NULL, 0)) == NULL)
	{
		okmsg("can't create messageport!");
		errorende();
		return(20);
	}

	menumsg.ExecMessage.mn_ReplyPort = mainport;
	menumsg.ExecMessage.mn_Node.ln_Type = NT_MESSAGE;
	menumsg.ExecMessage.mn_Length = sizeof(struct PSmessage);
	rendertask = CreateNewProcTags(NP_Entry, (ULONG) SubTask,
					NP_Name, (ULONG) subtaskname, NP_StackSize, 4096,
					NP_Priority, 0, NP_Input, Input(), NP_Output, Output(),
					NP_Error, Output(), NP_CloseInput, FALSE, NP_CloseOutput,
					FALSE, NP_CloseError, FALSE, TAG_DONE);
	if(rendertask)
	{
		Wait(1L << create_signal);
		if (renderport == NULL)
		{
			okmsg("subtask can't create messageport!");
			errorende();
			return(20);
		}
		if(argwindow) SetTaskPri((struct Task *) rendertask, 0);
		else SetTaskPri((struct Task *) rendertask, -1);
	}
	else
	{
		okmsg("can't create subtask");
		errorende();
		return(20);
	}

/* Open the screen and load the color map  */

	if(Options.Screen.custscreen && argwindow) openscreen();
	else if (argwindow)
	{
		if(openpubscreen(&pubscrcontext, pubscreenname) == FALSE)
		{
			errorende();
			exit(20);
		}
		if(pubscrcontext.pens_ok == FALSE) Options.PostOpts.depth = 1;
		ScreenToFront(pubscrcontext.pubscreen);
	}

	colormap.Count = 1 << Options.PostOpts.depth;
	if(Options.PostOpts.depth == 1) colormap.ColorTable = (APTR) bcolors;
	else colormap.ColorTable = (APTR) ccolors;

	if(argwindow)
	{
		sprintf(windowtitle, "Post.%d (Waiting, Page --- of ---, no file loaded)", post_count);
		openwindow();
	}

	if(argfile)
	{
		if(number_of_pages)
		{
			if (Options.PostOpts.from < 1) Options.PostOpts.from = 1;
			if (Options.PostOpts.to > number_of_pages) Options.PostOpts.to = number_of_pages;
			if (Options.PostOpts.from > Options.PostOpts.to) Options.PostOpts.from = Options.PostOpts.to;
			page_number = Options.PostOpts.from;
		}
		else Options.PostOpts.from = 1;
		if ((argprint || argiff) && Options.PostOpts.bandrendering)
		{
			if(Options.PostOpts.bandsize < Options.PostOpts.height)
			{
				if(number_of_pages == 0) bandrendering = FALSE;
				else bandrendering = TRUE;
			}
		}
	}
	sendmenu(PSACTCREATE, 0, 0, 0, NULL, NULL);
	Wait(1L << create_signal);
	if(createerror)
	{
		okmsg("subtask can't create activation!");
		errorende();
		return(20);
	}
	runstartupfiles();
	if(argfile)
	{
		sendmenu(PSACTFILE, number_of_pages, Options.PostOpts.from, Options.PostOpts.to, Options.lastfile, Options.lastdir);
	}

/* Execute menu commands */

	if (argwindow)
	{
		for (;;)
		{
			signals = ARexxSignal(RexxStuff);
			if(OutputWnd) signals |= 1L << OutputWnd->UserPort->mp_SigBit;
			signals |= 1L << mainport->mp_SigBit;
			rec_sig = Wait(signals);
			if(rec_sig == 1L << mainport->mp_SigBit)
			{
				while(msg = GetMsg(mainport))
				{
/* Check if action == PSACTAREXX and reply the ARexxMsg. So Arexx scripts	*
 * can be synchronised with the interpreter.											*/
					if(((struct PSmessage *) msg)->action == PSACTAREXX)
					{
						ReplyARexxMsg(RexxStuff,((struct PSmessage *) msg)->rmsg,0,retcode ? 5 : 0);
					}
					FreeMem(msg, sizeof(struct PSmessage));
				}
			}
			while(rmsg = GetARexxMsg(RexxStuff))
			{
				ProcessARexx();
			}
			if(OutputWnd)
			{
				while ((intmsg = (struct IntuiMessage *) GetMsg(OutputWnd->UserPort)))
				{
					switch (((struct IntuiMessage *) intmsg)->Class)
					{
					case IDCMP_MOUSEMOVE:
						idcmpupdate_ticks = 0;
						get_scrollers();
						do_blit();
						break;

					case IDCMP_GADGETDOWN:
						idcmpupdate_ticks = 0;
						do_gadgets(((struct Gadget *) intmsg->IAddress)->GadgetID, 1);
						break;

					case IDCMP_IDCMPUPDATE:
						idcmpupdate_ticks++;
						if(idcmpupdate_ticks < TICKS_TO_DELAY) break;
						do_gadgets(GetTagData(GA_ID, 0, (struct TagItem *) intmsg->IAddress), SCROLL_INC);
						break;

					case IDCMP_MENUVERIFY:
						setmenu();
						break;

					case IDCMP_SIZEVERIFY:
						blit_to_window = FALSE;
						break;

					case IDCMP_CLOSEWINDOW:
						Delay(10);
						if(!interactive && !startup)
						{
							SavePostOptions("ENV:Post", &Options);
							errorende();
							return(0);
						}
						break;

					case IDCMP_REFRESHWINDOW:
						BeginRefresh(OutputWnd);
						do_blit();
						EndRefresh(OutputWnd, TRUE);
						break;

					case IDCMP_ACTIVEWINDOW:
						SetTaskPri((struct Task *) rendertask, 0);
						break;

					case IDCMP_INACTIVEWINDOW:
						SetTaskPri((struct Task *) rendertask, -1);
						break;

					case IDCMP_NEWSIZE:
						winxsize = OutputWnd->Width - OutputWnd->BorderLeft - OutputWnd->BorderRight;
						winysize = OutputWnd->Height - OutputWnd->BorderTop-OutputWnd->BorderBottom;
						set_scrollers();
						do_blit();
						break;

					case IDCMP_MENUPICK:
						code = intmsg->Code;
						if (code != MENUNULL)
						{
							tempitem = ItemAddress(menu0, code);
							func = (void *) (GTMENUITEM_USERDATA( tempitem ));
							i = func();
						}
						break;

					case IDCMP_CHANGEWINDOW:
						if(OutputWnd->Flags & WFLG_ZOOMED)
						{
							Options.OutputWnd.WndZoomLeft		= OutputWnd->LeftEdge;
							Options.OutputWnd.WndZoomTop		= OutputWnd->TopEdge;
							Options.OutputWnd.WndZoomWidth	= winxsize + OutputWnd->BorderLeft + OutputWnd->BorderRight;
							Options.OutputWnd.WndZoomHeight	= winysize + OutputWnd->BorderTop + OutputWnd->BorderBottom;
						}
						else
						{
							Options.OutputWnd.WndLeft			= OutputWnd->LeftEdge;
							Options.OutputWnd.WndTop			= OutputWnd->TopEdge;
							Options.OutputWnd.WndWidth			= winxsize;
							Options.OutputWnd.WndHeight		= winysize;
						}
						break;

					case IDCMP_RAWKEY:
						switch(intmsg->Code & 0x7f)
						{
							case	CURSORUP:
								if ((intmsg->Qualifier & IEQUALIFIER_LSHIFT) ||
									(intmsg->Qualifier & IEQUALIFIER_RSHIFT))
								do_gadgets(GAD_UP, (9*winysize)/10);
								else if (intmsg->Qualifier & IEQUALIFIER_CONTROL)
									do_gadgets(GAD_UP, parm.page.ysize - winysize);
								else	do_gadgets(GAD_UP, 1);
								break;

							case	CURSORDOWN:
								if ((intmsg->Qualifier & IEQUALIFIER_LSHIFT) ||
									(intmsg->Qualifier & IEQUALIFIER_RSHIFT))
									do_gadgets(GAD_DOWN, (9*winysize)/10);
								else if (intmsg->Qualifier & IEQUALIFIER_CONTROL)
									do_gadgets(GAD_DOWN, parm.page.ysize - winysize);
								else	do_gadgets(GAD_DOWN, 1);
								break;

							case	CURSORLEFT:
								if ((intmsg->Qualifier & IEQUALIFIER_LSHIFT) ||
									(intmsg->Qualifier & IEQUALIFIER_RSHIFT))
									do_gadgets(GAD_LEFT, (9*winxsize)/10);
								else if (intmsg->Qualifier & IEQUALIFIER_CONTROL)
									do_gadgets(GAD_LEFT, parm.page.xsize - winxsize);
								else	do_gadgets(GAD_LEFT, 1);
								break;

							case	CURSORRIGHT:
								if ((intmsg->Qualifier & IEQUALIFIER_LSHIFT) ||
									(intmsg->Qualifier & IEQUALIFIER_RSHIFT))
									do_gadgets(GAD_RIGHT, (9*winxsize)/10);
								else if (intmsg->Qualifier & IEQUALIFIER_CONTROL)
									do_gadgets(GAD_RIGHT, parm.page.xsize - winxsize);
								else	do_gadgets(GAD_RIGHT, 1);
								break;

							default:
								break;
						}
						break;

					case IDCMP_VANILLAKEY:
						switch(intmsg->Code)
						{
							case	' ':
								if(winypos < parm.page.ysize - winysize)
									do_gadgets(GAD_DOWN, (9*winysize)/10);
								else
								{
									if(nextpage() == 0) do_gadgets(GAD_UP, parm.page.ysize - winysize);
								}
								break;

							case	13:
							case	'+':
								i = !nextpage();
								if((intmsg->Qualifier & IEQUALIFIER_NUMERICPAD) && i)
									do_gadgets(GAD_UP, parm.page.ysize - winysize);
								break;

							case	8:
							case	'-':
								i = !previouspage();
								if((intmsg->Qualifier & IEQUALIFIER_NUMERICPAD) && i)
									do_gadgets(GAD_DOWN, parm.page.ysize - winysize);
								break;

							default:
								break;
						}
						break;

						default:
						break;
					}
					if(intmsg) ReplyMsg((struct Message *) intmsg);
				}
			}
		}
	}
	sendmenu(PSACTWAIT, 0, 0, 0, NULL, NULL);
	Wait(1L << create_signal);
	errorende();
	return(0);
}

BPTR	oldwblock = NULL;

BOOL open_libs(void)
{
	BPTR	lock = NULL;

	GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 39);
	if(GfxBase) os_3 = TRUE;
	else GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 36);
	IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 36);
	AslBase = OpenLibrary("asl.library", 36);
	GadToolsBase = OpenLibrary("gadtools.library", 36);
	UtilityBase = OpenLibrary("utility.library", 36);
	DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 36);
	if (GfxBase == NULL || IntuitionBase == NULL || AslBase == NULL
		|| GadToolsBase == NULL || UtilityBase == NULL || DOSBase == NULL)
	{
		okmsg("Can't open libraries! You need OS 2.0!!!");
		return(FALSE);
	}
	PSbase = OpenLibrary("post.library", 17L);
	if (PSbase == NULL)
	{
		okmsg("Can't open post.library >= V17!!!");
		return(FALSE);
	}
	maintask = FindTask(NULL);
	create_signal = AllocSignal(-1);
	if(create_signal == -1)
	{
		okmsg("can't get create_signal!");
		return(FALSE);
	}
	GetCurrentDirName(startdir, 256);
	if (_WBenchMsg)
	{
		if (lock = Lock(startdir, ACCESS_READ))
		{
			oldwblock = CurrentDir(lock);
		}
		else
		{
			okmsg("can't get lock!");
			return(FALSE);
		}
	}
	insertbreakmain();
	SetExcept(~0, SIGBREAKF_CTRL_C);
	return(TRUE);
}

void close_libs(void)
{
	BPTR	lock;

	SetExcept(0, SIGBREAKF_CTRL_C);
	deletebreakmain();
	if (!_WBenchMsg) changedir(startdir);
	else
	{
		lock = CurrentDir(oldwblock);
		if (lock) UnLock(lock);
	}
	if (PSbase)  CloseLibrary((struct Library *) PSbase);
	if (GadToolsBase) CloseLibrary((struct Library *) GadToolsBase);
	if (AslBase) CloseLibrary((struct Library *) AslBase);
	if (GfxBase) CloseLibrary((struct Library *) GfxBase);
	if (DOSBase) CloseLibrary((struct Library *) DOSBase);
	if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase);
	if (UtilityBase) CloseLibrary(UtilityBase);
	if (create_signal != -1) FreeSignal(create_signal);
}

void errorende(void)
{
	struct Message *msg;

	if(rendertask)
	{
		if(renderport)
		{
			saveterminate();
			SetTaskPri((struct Task *) rendertask, 10);
			sendmenu(PSACTCLOSE, 0, 0, 0, NULL, NULL);
			Wait(1L << create_signal);
		}
	}
	while(msg = GetMsg(mainport))
	{
		if(((struct PSmessage *) msg)->action == PSACTAREXX)
		{
			ReplyARexxMsg(RexxStuff,((struct PSmessage *) msg)->rmsg,0,retcode);
		}
/*		sprintf(buffer, "action = %d", ((struct PSmessage *)msg)->action);
		okmsg(buffer);*/
		FreeMem(msg, sizeof(struct PSmessage));
	}
	if(rmsg) ReplyARexxMsg(RexxStuff, rmsg, 0, 0);
	while(rmsg = GetARexxMsg(RexxStuff)) ReplyARexxMsg(RexxStuff, rmsg, 0, 0); 
	FreeARexx(RexxStuff);
	if(pubscrcontext.ps_lock)
	{
		UnlockPubScreen(NULL, pubscrcontext.pubscreen);
		pubscrcontext.ps_lock = FALSE;
	}
	closewindow();
	if (custscreen)
	{
		while(!CloseScreen(custscreen)) okmsg("you have to close the visitor windows!");
		custscreen = NULL;
	}
	OpenWorkBench();
	delete_tempfiles();
	if(filerequester) FreeAslRequest(filerequester);
	if(fontrequester) FreeAslRequest(fontrequester);

	if (mainport)
	{
		DeletePort(mainport);
		mainport = NULL;
	}
	close_libs();
}

void	saveterminate(void)
{

	if(running)
	{
		if(number_of_pages == 0 || paused == 0) PSsignalint(arec, 2);
		if(paused)
		{
			Signal((struct Task *) rendertask, 1L << pause_signal);
			if (number_of_pages == 0) sendmenu(PSACTPAUSE, 0, 0, 0, NULL, NULL);
		}
		number_of_pages = 0;
		while (running) Delay(10);
	}
}

/* End of file "post.c" */
