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

/* The render task */

int	numofpages, page_counter, bandnumber = 0, totalbands;
BOOL	createerror;
char	file[256];
BPTR	outfh;

void __saveds SubTask(void)
{
	BPTR		oldlock, newlock;
	struct	PSmessage *msg;
	int		action, ende=FALSE;
	char		dummybuf[256], *status, *file2;
	BOOL		pause_bak, error=TRUE;

	insertbreak();
	SetExcept(~0, SIGBREAKF_CTRL_C);
	breakset = TRUE;
	insertftrap();
	ftrapset = TRUE;

	pause_signal = AllocSignal(-1);
	if(pause_signal == -1)
	{
		rendertask = NULL;
		return;
	}
	renderport = CreatePort(NULL, 0);
	Signal(maintask, 1L << create_signal);
	if (renderport == NULL)
	{
		FreeSignal(pause_signal);
		rendertask = NULL;
		return;
	}

	errfh=Output();

	while ( !ende )
	{
		WaitPort(renderport);
		while(msg = (struct PSmessage *) GetMsg(renderport))
		{
			action = msg->action;
			if (msg->file) strcpy(file, FilePart(msg->file));
			numofpages = msg->numofpages;
			running = TRUE;
			retcode = 0;
			errstr = NULL;
			switch (action)
			{
				case PSACTCREATE:
					if(arec) deleteactivation();
					if(argcon)
					{
						error=openconwin();
					}
					outfh=confh ? confh : errfh;
					if(error == FALSE || createactivation() == FALSE)
					{
						do
						{
							ReplyMsg((struct Message *) msg);
						} while(msg = (struct PSmessage *) GetMsg(renderport));
						createerror = TRUE;
						deleteactivation();
					}
					else
					{
						createerror = FALSE;
					}
					Signal(maintask, 1L << create_signal);
					totalbands = parm.page.yheight / parm.page.ysize;
					if(parm.page.yheight % parm.page.ysize) totalbands++;
					break;

				case PSACTCLEAR:
					PSdeleteact(arec);
					if(confh)
					{
						Close(confh);
						confh = NULL;
					}
					openconwin();
					parm.infh	= confh;
					parm.outfh	= confh;
					parm.errfh	= confh;
					arec = PScreateact(&parm);
					if (arec == 0 || (unsigned) arec <= errmax)
					{
						okmsg("error during initiation in PScreateact");
						do
						{
							ReplyMsg((struct Message *) msg);
						} while(msg = (struct PSmessage *) GetMsg(renderport));
						ende = TRUE;
						createerror = TRUE;
					}
					createerror = FALSE;
					Signal(maintask, 1L << create_signal);
					break;

				case PSACTAREXX:
					if(argwindow)
					{
						sprintf(windowtitle,
								"Post.%d (Running, Page --- of ---, Interpreting ARexx-Command)",
								post_count);
						if(OutputWnd) SetWindowTitles(OutputWnd, windowtitle, windowtitle);
					}
					arexx = TRUE;
					retcode = PSintstring(arec, msg->directory, -1, PSFLAGSTRING);
					arexx = FALSE;
					break;

				case PSACTSTARTUP:
				case PSACTFILE:
				case PSACTRUN:
				case PSACTFONT:
					if(action == PSACTSTARTUP)
					{
						pause_bak = pause;
						pause = FALSE;
						status = titlestart;
						startup = TRUE;
					}
					else
					{
						status = titlerunning;
						startup = FALSE;
					}
					if(msg->directory)
					{
						newlock = Lock(msg->directory, ACCESS_READ);
						if(newlock)
						{
							oldlock = CurrentDir(newlock);
							if(oldlock) UnLock(oldlock);
						}
					}
					if((argprint || argiff) && 
						(Options.PostOpts.bandrendering && !bandrendering) &&
						(action != PSACTSTARTUP) &&
						(Options.PostOpts.bandsize < Options.PostOpts.height))
							FPrintf(outfh, "file '%s' not conforming for band-rendering!\n", (ULONG) file);
					if(argwindow)
					{
						if(numofpages) sprintf(windowtitle, "Post.%d (%s, Page %3d of %3d, %s)", post_count, status, 1, numofpages, file);
						else  sprintf(windowtitle, "Post.%d (%s, Page --- of ---, %s)", post_count, status, file);
						if(OutputWnd) SetWindowTitles(OutputWnd, windowtitle, windowtitle);
					}
					page_counter = msg->from;
					iffseq = page_counter;
					if(msg->numofpages)
					{
						if (argverbose && !argwindow)
						{
							FPrintf(outfh, "interpreting prologue ... ");
							Flush(outfh);
						}
						sprintf(dummybuf, "%sPrologue%d.ps", Options.temppath, post_count);
						if (retcode = PSintstring(arec, dummybuf, -1, PSFLAGFILE|PSFLAGERASE))
						{
							break;
						}
						if (argverbose && !argwindow) FPrintf(outfh, "done.\n");
						if(argprint || argiff)
						{
							for (page_counter = msg->from; page_counter <= msg->to; page_counter++)
							{
								bandnumber = 0;
								if(argverbose)
								{
									FPrintf(outfh, "working on page %ld of file '%s', %ld page(s) left:\n", page_counter, (ULONG) file, msg->to - page_counter);
									FPrintf(outfh, " rendering band %ld of %ld ... ", 1, totalbands);
									Flush(outfh);
								}
								sprintf(dummybuf, "currentband 1 sub{setband (%sPage%04d_%d.ps) run} for 0 setband", Options.temppath, page_counter, post_count);
								if(retcode = PSintstring(arec, dummybuf, -1, PSFLAGSTRING|PSFLAGERASE))
								{
									break;
								}
							}
							if (argverbose)
							{
								FPrintf(outfh, "interpreting trailer ... ");
								Flush(outfh);
							}
							sprintf(dummybuf, "%sTrailer%d.ps", Options.temppath, post_count);
							retcode = PSintstring(arec, dummybuf, -1, PSFLAGFILE|PSFLAGERASE);
							if (argverbose) FPrintf(outfh, "done.\n");
						}
						else
						{
							sprintf(dummybuf, "%sPage%04d_%d.ps", Options.temppath, page_counter, post_count);
							retcode = PSintstring(arec, dummybuf, -1, PSFLAGFILE|PSFLAGERASE);
						}
					}
					else
					{
						page_counter = 1;
						if(argverbose && OutputWnd == NULL)
						{
							if(action == PSACTSTARTUP)
							{
								FPrintf(outfh, "running startup file '%s' ... ", (ULONG) file);
								Flush(outfh);
							}
							else
							{
								FPrintf(outfh, "rendering page %ld of file '%s' ... ", page_counter, (ULONG) file);
								Flush(outfh);
							}
						}
/* Versions of HWGPost.library >= 22.26 (Release Beta 6) create a separate	*
 * process. Therefore it is not possible, to change the current directory 	*
 * and the full path has to be specified.												*/
						if(PSbase->lib_Version == 22)
						{
							if(PSbase->lib_Revision >= 26) file2=msg->file;
							else file2=file;
						}
						else if (PSbase->lib_Version > 22) file2=msg->file;
						else file2=file;
						retcode = PSintstring(arec, file2, -1, action == PSACTRUN ?  PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE|PSFLAGSAVE : PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE);
						if(argverbose && OutputWnd == NULL)
						{
							if (action == PSACTSTARTUP) FPrintf(outfh, "done.\n");
							else if (!ioerror) FPrintf(outfh, "no more pages!\n");
						}
					}
					if(action == PSACTSTARTUP)
					{
						pause = pause_bak;
						startup = FALSE;
					}
					break;

				case PSACTINTER:
					interactive = TRUE;
					if(argwindow)
					{
						sprintf(windowtitle, "Post.%d (Running, Page --- of ---, Interactive)", post_count);
						if(OutputWnd) SetWindowTitles(OutputWnd, windowtitle, windowtitle);
					}
					retcode = PSintstring(arec, "%stdin", -1, PSFLAGFILE | PSFLAGCLEAR | PSFLAGERASE|PSFLAGSAVE|PSFLAGINTER);
					interactive = FALSE;
					break;

				case PSACTCLOSE:
					do
					{
						ReplyMsg((struct Message *) msg);
					} while(msg = (struct PSmessage *) GetMsg(renderport));
					ende = TRUE;
					break;

				case PSACTWAIT:
					Signal(maintask, 1L << create_signal);
					break;

				case PSACTPAUSE:
					if(numofpages)
					{
						page_counter = msg->from;
						if (page_counter <= numofpages)
						{
							if(argwindow)
							{
								sprintf(windowtitle, "Post.%d (%s, Page %3d of %3d, %s)", post_count, titlerunning, page_counter, numofpages, file);
								if(OutputWnd) SetWindowTitles(OutputWnd, windowtitle, windowtitle);
							}
							sprintf(dummybuf, "%spage%04d_%d.ps", Options.temppath, page_counter, post_count);
							retcode = PSintstring(arec, dummybuf, -1, PSFLAGFILE|PSFLAGERASE);
						}
						else
						{
							sprintf(dummybuf, "%sTrailer%d.ps", Options.temppath, post_count);
							retcode = PSintstring(arec, dummybuf, -1, PSFLAGFILE|PSFLAGERASE);
						}
					}
					break;

				default:
					break;
			}
			running = FALSE;
			if(argwindow)
			{
				sprintf(windowtitle, "Post.%d (Waiting, Page --- of ---, no file loaded)",	post_count);
				if(OutputWnd) SetWindowTitles(OutputWnd, windowtitle, windowtitle);
			}

			if(retcode) errstr = PSerrstr(arec, retcode);
			if(msg) ReplyMsg((struct Message *) msg);
		}
	}
	deleteactivation();
	Signal(maintask, 1L << create_signal);
	FreeSignal(pause_signal);
	DeletePort(renderport);
	if (breakset)
	{
		SetExcept(0, SIGBREAKF_CTRL_C);
		deletebreak();
		breakset = FALSE;
	}
	if (ftrapset)
	{
		deleteftrap();
		ftrapset = FALSE;
	}

	renderport = NULL;
	rendertask = NULL;
}


void	__regargs blit(int, int);

void	__regargs blit(int y1, int y2)
{
	if(AttemptLockLayerRom(OutputWnd->WLayer))
	{
		BltBitMapRastPort(&bitmap, winxpos, y1, OutputWnd->RPort,
			winxbase, winybase + y1 - winypos, winxsize, y2 - y1, 0xC0);
		WaitBlit();
		UnlockLayerRom(OutputWnd->WLayer);
	}
}

/* Flush the page to the screen */

void __saveds __regargs flushpage(int y1, int y2)
{
	if (blit_to_window)
	{
		if (y1 < winypos) y1 = winypos;
		if (y2 < winypos) y2 = winypos;
		if (y1 > winypos + winysize) y1 = winypos + winysize;
		if (y2 > winypos + winysize) y2 = winypos + winysize;
		if (y2 > y1) blit(y1, y2);
	}
}

/* Copy the page to the output */

void __saveds __regargs copypage(int num)
{
	int	i;
	char	*action;

	ioerror = 0;
	if (argiff) action = "saving";
	if (argprint) action = "printing";
	if (numofpages == 0) page_counter++;
	bandnumber++;
	if (argverbose && !argwindow)
	{
		if(numofpages)
		{
			FPrintf(outfh, "done.\n  %s band %ld of %ld", (ULONG) action, bandnumber, totalbands);
		}
		else
		{
			FPrintf(outfh, "done.\n %s page %ld", (ULONG) action, page_counter - 1);
		}
		Flush(outfh);
	}
	if (argiff) iffpage(&output_bitmap);
	if (argprint)
	{
		SetTaskPri((struct Task *) rendertask, 0);
		if (bandrendering)
		{
			if(argverbose && !argwindow)
			{
				FPrintf(outfh, " ... ");
				Flush(outfh);
			}
			printpage(&output_bitmap);
		}
		else
		{
			for (i=0; i < num; i++)
			{
				if(argverbose && !argwindow)
				{
					FPrintf(outfh, " copy %ld of %ld ... ", i + 1, num);
					Flush(outfh);
				}
				printpage(&output_bitmap);
			}
		}
		SetTaskPri((struct Task *) rendertask, 0);
	}
	if (argverbose && !argwindow && !ioerror)
	{
		if(numofpages)
		{
			if(bandnumber == totalbands)
			{
				FPrintf(outfh, "done.\n");
			}
			else
			{
				FPrintf(outfh, "done.\n rendering band %ld of %ld ... ", bandnumber + 1, totalbands);
			}
		}
		else FPrintf(outfh, "done.\nrendering page %ld of file '%s' ... ", page_counter, (ULONG) file);
		Flush(outfh);
	}
	if (argwindow)
	{
		if (pause)
		{
			paused = TRUE;
			if(numofpages) sprintf(windowtitle, "Post.%d (%s, Page %3d of %3d, %s)", post_count, titlepaused, page_counter, numofpages, file);
			else if(interactive)  sprintf(windowtitle, "Post.%d (%s, Page --- of ---, Interactive)", post_count, titlepaused);
			else if(arexx) sprintf(windowtitle, "Post.%d (%s, Page --- of ---, Interpreting ARexx-Command)", post_count, titlepaused);
			else sprintf(windowtitle, "Post.%d (%s, Page --- of ---, %s)", post_count, titlepaused, file);
			if(OutputWnd) SetWindowTitles(OutputWnd, windowtitle, windowtitle);
			if(blit_to_window)
			{
					blit(winypos, winysize + winypos);
			}
			Wait(1L << pause_signal);
			if(argwindow && interactive)
			{
				sprintf(windowtitle, "Post.%d (Running, Page --- of ---, Interactive)", post_count);
				if(OutputWnd) SetWindowTitles(OutputWnd, windowtitle, windowtitle);
			}
			paused = FALSE;
		}
	}
	if (ioerror && ioerror != errinterrupt)
	{
		PSerror(arec, ioerror);
	}
}
