/*
** The CLI Watcher - (c)1993-1994 Alex May
**
** Real ugly source but does the job ;)
**
** Shows usage of Pipes and other PL funcs.  Doesn't do the watcher
**    stuff but I'm not sure it's worth it being so small as it is...
*/

#include	"Headers.h"

struct	IntuitionBase	*IntuitionBase;
struct	Library			*PipelineBase;

struct	Window			*window;
struct	Screen			*scr;

struct	Process			*MyTask;

struct	MsgPort			*PipeMP;
struct	MsgPort			*Con_R_MP, *Con_W_MP;

struct	IOStdReq			*Con_R_IO, *Con_W_IO;

void		*Pipe_In = NULL, *Pipe_Out = NULL;

ULONG		Win_SB, Pipe_SB, Con_SB;
ULONG		Line;

struct	Message	*PRMsg;

char	title[80];
char	Buff[80];

UWORD		sx, sy, sw, sh;

int	OpenLibs( void )
{
	if( PipelineBase = OpenLibrary( "pipeline.library", 0 ) )
	{
		if( IntuitionBase = (struct IntuitionBase *)OpenLibrary( "intuition.library", 37 ) )
		{
			return( 1 );
		}
		else
		{
			PutStr( "Can't open the intuition.library\n" );
		}
		CloseLibrary( PipelineBase );
	}
	else
	{
		PutStr( "Can't open the pipeline.library\n" );
	}

	return( 0 );
}

void	CloseLibs( void )
{
	CloseLibrary( PipelineBase );
	CloseLibrary( (struct Library *)IntuitionBase );
}

int	OpenDisplay( int argc, char **argv )
{
	UWORD		i;

	sprintf( title, "Watching Line %ld", Line );

	if( !( scr = LockPubScreen( "PIPELINE" ) ) )
	{
		scr = LockPubScreen( NULL );
	}

	if( scr )
	{
		sx = NULL;
		sy = scr->BarHeight + 2;
		sw = scr->Width;
		sh = scr->Height - scr->BarHeight - 2;

		if( argc > 3 )
		{
			for( i = 2 ; i < argc ; i++ )
			{
				switch( i )
				{
					case 2: 
						sx = atoi( argv[2] );
						break;
					case 3: 
						sy = atoi( argv[3] );
						break;
					case 4: 
						sw = atoi( argv[4] );
						break;
					case 5: 
						sh = atoi( argv[5] );
						break;
				}
			}
		}

		if( window = OpenWindowTags( NULL, WA_Left, sx, WA_Top, sy,
													  WA_Width, sw, WA_Height, sh,
													  WA_PubScreen, scr,
													  WA_Title, title,
													  WA_Flags, WFLG_ACTIVATE | WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_SIZEBBOTTOM | WFLG_SMART_REFRESH,
													  WA_AutoAdjust, TRUE,
													  WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE,
													  WA_MinWidth, 50,
													  WA_MinHeight, 50,
													  TAG_DONE ) )
		{
			Win_SB = (1L << window->UserPort->mp_SigBit);
			UnlockPubScreen( NULL, scr );
			return( 1 );
		}
		else
		{
			PutStr( "Can't open the window\n" );
		}
		UnlockPubScreen( NULL, scr );
	}
	else
	{
		PutStr( "Can't lock the screen\n" );
	}

	return( 0 );
}

void	CloseDisplay( void )
{
	CloseWindow( window );
}

int	OpenPipes( void )
{
	UBYTE		buff[20];

	if( PipeMP = CreateMsgPort() )
	{
		PRMsg->mn_ReplyPort = PipeMP;
		PRMsg->mn_Length    = sizeof(struct Message);

		Pipe_SB = (1 << PipeMP->mp_SigBit );

		sprintf( buff, "LINE%ld_out", Line );

		if( Pipe_In = OpenPipe( buff, 8192, PIPE_READ ) )
		{
			sprintf( buff, "LINE%ld_in", Line );

			if( Pipe_Out = OpenPipe( buff, 8192, PIPE_WRITE ) )
			{
				RequestPipe( Pipe_In, PRMsg, PIPE_REQ_READ );
				return( 1 );
			}
			else
			{
				PutStr( "Can't open the write pipe\n" );
			}
			ClosePipe( Pipe_In, NULL );
		}
		else
		{
			PutStr( "Can't open the read Pipe\n" );
		}
		DeleteMsgPort( PipeMP );
	}
	else
	{
		PutStr( "Can't create a msgport\n" );
	}

	return( 0 );
}

void	ClosePipes( void )
{
	RequestPipe( Pipe_In, PRMsg, PIPE_REQ_ABORT );
	ClosePipe( Pipe_In, NULL );
	ClosePipe( Pipe_Out, NULL );
	DeletePort( PipeMP );
}

int	OpenMem( void )
{
	if( PRMsg = (struct Message *)AllocMem( sizeof(struct Message), MEMF_PUBLIC | MEMF_CLEAR ) )
	{
		return( 1 );
	}

	PutStr( "Out of memory\n" );

	return( 0 );
}

void CloseMem( void )
{
	FreeMem( PRMsg, sizeof( struct Message ) );
}

int OpenConsole( void )
{
	if( Con_R_MP = CreateMsgPort() )
	{
		if( Con_W_MP = CreateMsgPort() )
		{
			if( Con_R_IO = (struct IOStdReq *)CreateExtIO( Con_R_MP, sizeof(struct IOStdReq) ) )
			{
				if( Con_W_IO = (struct IOStdReq *)CreateExtIO( Con_W_MP, sizeof(struct IOStdReq) ) )
				{
					Con_R_IO->io_Data   = window;
					Con_R_IO->io_Length = sizeof(struct Window);

					Con_W_IO->io_Data   = window;
					Con_W_IO->io_Length = sizeof(struct Window);
					
					if( !( OpenDevice( "console.device", CONU_CHARMAP, (struct IORequest *)Con_R_IO, CONFLAG_DEFAULT ) ) )
					{
						Con_W_IO->io_Device = Con_R_IO->io_Device;
						Con_W_IO->io_Unit   = Con_R_IO->io_Unit;

						Con_SB = (1L << Con_R_MP->mp_SigBit );

						return( 1 );
					}
					else
					{
						PutStr( "Can't open the console.device\n" );
					}
					DeleteExtIO( (struct IORequest *)Con_W_IO );
				}
				else
				{
					PutStr( "Can't create an IO\n" );
				}
				DeleteExtIO( (struct IORequest *)Con_R_IO );
			}
			else
			{
				PutStr( "Can't create an IO\n" );
			}
			DeleteMsgPort( Con_W_MP );
		}
		else
		{
			PutStr( "Can't open a msg port\n" );
		}
		DeleteMsgPort( Con_R_MP );
	}
	else
	{
		PutStr( "Can't open a msg port\n" );
	}

	return( 0 );
}

void CloseConsole( void )
{
	CloseDevice( (struct IORequest *)Con_R_IO );
	DeleteExtIO( (struct IORequest *)Con_W_IO );
	DeleteExtIO( (struct IORequest *)Con_R_IO );
	DeleteMsgPort( Con_W_MP );
	DeleteMsgPort( Con_R_MP );
}

void ConRead( void )
{
	Con_R_IO->io_Data    = Buff;
	Con_R_IO->io_Length  = 1;
	Con_R_IO->io_Command = CMD_READ;
	SendIO( (struct IORequest *)Con_R_IO );
}

void ProcessConMsg( void )
{
	struct	Message	*TheMsg;
	
	TheMsg = GetMsg( Con_R_MP );

	if( Con_R_IO->io_Actual )
	{
		if( (UBYTE)Buff[0] == (UBYTE)0x9B )
		{
			WritePipe( Pipe_Out, "[", 2 );
		}
		else
		{
			WritePipe( Pipe_Out, Con_R_IO->io_Data, Con_R_IO->io_Actual );
		}
	}

	ConRead();
}

void ProcessPipeMsg( void )
{
	struct	Message	*TheMsg;
	long		ready, skip;		
	char		*data;

	TheMsg = GetMsg( PipeMP );

	skip = NULL;

	while( ( ready = ReadPipe( Pipe_In, &data, skip ) ) > 0 )
	{
		if( ready > 256 )
			ready = 256;

		Con_W_IO->io_Data	   = data;
		Con_W_IO->io_Length  = ready;
		Con_W_IO->io_Command = CMD_WRITE;
		DoIO( (struct IORequest *)Con_W_IO );

		skip = ready;
	}

	RequestPipe( Pipe_In, PRMsg, PIPE_REQ_READ );
}
		
int main( int argc, char **argv )
{
	struct	IntuiMessage	*im;
	BOOL		Quit = FALSE;
	ULONG		Mask;

	if( argc < 2 )
	{
		Printf( "Usage: %s <Line Number>\n", argv[0] );
		return( 20 );
	}

	Line = atol( argv[1] );

	if( OpenLibs() )
	{
		if( OpenDisplay( argc, argv ) )
		{
			if( OpenConsole() )
			{
				if( OpenMem() )
				{
					if( OpenPipes() )
					{
						ConRead();
						KillMe( SIGBREAKF_CTRL_C );

						while( !Quit )
						{
							Mask = Wait( Win_SB | Pipe_SB | Con_SB | SIGBREAKF_CTRL_C );

							if( Mask & Win_SB )							
							{
								while( im = (struct IntuiMessage *)GetMsg( window->UserPort ) )
								{
									if( im->Class == IDCMP_CLOSEWINDOW )
										Quit = TRUE;
										
									ReplyMsg( (struct Message *)im );
								}
							}

							if( Mask & Pipe_SB )
							{
								ProcessPipeMsg();
							}
							
							if( Mask & Con_SB )
							{
								ProcessConMsg();
							}
							
							if( Mask & SIGBREAKF_CTRL_C )
							{
								Quit = TRUE;
							}
						}
						
						DontKillMe();

						ClosePipes();
					}
					CloseMem();
				}
				CloseConsole();
			}
			CloseDisplay();
		}
		CloseLibs();
	}

	return( NULL );
}
