/* @(#) pf_io.c 96/12/23 1.12 */
/***************************************************************
** I/O subsystem for PForth based on 'C'
**
** Author: Phil Burk
** Copyright 1994 3DO, Phil Burk, Larry Polansky, Devid Rosenboom
**
** The pForth software code is dedicated to the public domain,
** and any third party may reproduce, distribute and modify
** the pForth software code or any derivative works thereof
** without any compensation or license.  The pForth software
** code is provided on an "as is" basis without any warranty
** of any kind, including, without limitation, the implied
** warranties of merchantability and fitness for a particular
** purpose and their equivalents under the laws of any jurisdiction.
**
****************************************************************
** 941004 PLB Extracted IO calls from pforth_main.c
***************************************************************/

#include "pf_all.h"

/***************************************************************
** Send single character to output stream.
*/
void ioEmit( char c )
{
	int32 Result;
	Result = sdTerminalOut(c);
	
	if( Result < 0 ) EXIT(1);
	if(c == '\n')
	{
		gCurrentTask->td_OUT = 0;
		sdTerminalFlush();
	}
	else
	{
		gCurrentTask->td_OUT++;
	}
}

void ioType( const char *s, int32 n )
{
	int32 i;

	for( i=0; i<n; i++)
	{
		ioEmit ( *s++ );
	}
}

/***************************************************************
** Return single character from input device, always keyboard.
*/
cell ioKey( void )
{
	return sdTerminalIn();
}

/**************************************************************
** Receive line from input stream.
** Return length, or -1 for EOF.
*/
#define BACKSPACE  (8)
cell ioAccept( char *Target, cell MaxLen, FileStream *stream )
{
	int32 c;
	int32 Len;
	char *p;

DBUGX(("ioAccept(0x%x, 0x%x, 0x%x)\n", Target, Len, stream ));
	p = Target;
	Len = MaxLen;
	while(Len > 0)
	{
		if( stream == PF_STDIN )
		{
			c = ioKey();
/* If KEY does not echo, then echo here. If using getchar(), KEY will echo. */
#ifndef PF_KEY_ECHOS
			ioEmit( c );
			if( c == '\r') ioEmit('\n'); /* Send LF after CR */
#endif
		}
		else
		{
			c = sdInputChar(stream);
		}
		switch(c)
		{
			case EOF:
				DBUG(("EOF\n"));
				return -1;
				break;
				
			case '\r':
			case '\n':
				*p++ = (char) c;
				DBUGX(("EOL\n"));
				goto gotline;
				break;
				
			case BACKSPACE:
				if( Len < MaxLen )  /* Don't go beyond beginning of line. */
				{
					EMIT(' ');
					EMIT(BACKSPACE);
					p--;
					Len++;
				}
				break;
				
			default:
				*p++ = (char) c;
				Len--;
				break;
		}
		
	}
gotline:
	*p = '\0';
		
	return pfCStringLength( Target );
}

#define UNIMPLEMENTED(name) { MSG(name); MSG("is unimplemented!\n"); }

#ifdef PF_NO_CHARIO
int  sdTerminalOut( char c )
{
	TOUCH(c);
	return 0;
}
int  sdTerminalIn( void )
{
	return -1;
}
int  sdTerminalFlush( void )
{
	return -1;
}
#endif

/***********************************************************************************/
#ifdef PF_NO_FILEIO

/* Provide stubs for standard file I/O */

FileStream *PF_STDIN;
FileStream *PF_STDOUT;

int32  sdInputChar( FileStream *stream )
{
	UNIMPLEMENTED("sdInputChar");
	TOUCH(stream);
	return -1;
}

FileStream *sdOpenFile( const char *FileName, const char *Mode )
{
	UNIMPLEMENTED("sdOpenFile");
	TOUCH(FileName);
	TOUCH(Mode);
	return NULL;
}
int32 sdFlushFile( FileStream * Stream  )
{
	TOUCH(Stream);
	return 0;
}
int32 sdReadFile( void *ptr, int32 Size, int32 nItems, FileStream * Stream  ) 
{ 
	UNIMPLEMENTED("sdReadFile");
	TOUCH(ptr);
	TOUCH(Size);
	TOUCH(nItems);
	TOUCH(Stream);
	return 0; 
}
int32 sdWriteFile( void *ptr, int32 Size, int32 nItems, FileStream * Stream  )
{ 
	UNIMPLEMENTED("sdWriteFile");
	TOUCH(ptr);
	TOUCH(Size);
	TOUCH(nItems);
	TOUCH(Stream);
	return 0; 
}
int32 sdSeekFile( FileStream * Stream, int32 Position, int32 Mode ) 
{ 
	UNIMPLEMENTED("sdSeekFile");
	TOUCH(Stream);
	TOUCH(Position);
	TOUCH(Mode);
	return 0; 
}
int32 sdTellFile( FileStream * Stream ) 
{ 
	UNIMPLEMENTED("sdTellFile");
	TOUCH(Stream);
	return 0; 
}
int32 sdCloseFile( FileStream * Stream ) 
{ 
	UNIMPLEMENTED("sdCloseFile");
	TOUCH(Stream);
	return 0; 
}
#endif

