/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/


#define STREAM_LIB
#define LIBRARY
#define S_FILE_LIBRARY

#include	<stdlib.h>
#include	<fcntl.h>
#ifdef VA2
#include	<varargs.h>
#else
#include	<stdarg.h>
#endif
#include	<errno.h>

#include	"memory_debug.h"
#include	"utils.h"
#include	"stream.h"
#include	"task.h"

extern SEM stream_lock;

int s_close_terminal();
int s_write_terminal();
int s_read_terminal();
int s_vprintf_terminal();
int s_vprintf_cr_terminal();
int s_flush_terminal();
int s_vscanf_terminal();
int s_error();
STREAM * s_error_stream();

S_TABLE s_terminal_table = {
	'e',
	0,
	{0,0},
	0,
	s_error_stream,
	s_close_terminal,
	s_write_terminal,
	s_read_terminal,
	s_flush_terminal,
	s_error,
	s_error_stream,
	s_error
};


void
init_terminal_stream()
{
	insert_s_table(&s_terminal_table);
}

STREAM *
s_open_terminal(int (*prompt)())
{
STREAM * ret;
	ret = d_alloc(sizeof(S_TERMINAL));
	ret->h.tbl = &s_terminal_table;
	ret->terminal.inp = s_stdin;
	ret->terminal.out = s_stdout;
	ret->terminal.prompt = prompt;
	lock_task(stream_lock);
	_s_open(ret,O_RDWR);
	unlock_task(stream_lock,"s_open_terminal");
	(*prompt)(ret);
	return ret;
}

int
s_close_terminal(STREAM * s)
{
	(*s_file_table.close)(s->terminal.out);
	(*s_file_table.close)(s->terminal.inp);
	return 0;
}

int
s_write_terminal(STREAM * s,void * data,int len)
{
int i;
unsigned char k;
	for ( i = 0;  i < len;  i++ ) {
		k = *((char*)data+i);
		if ( k != '\n' && k < 32 )
			printf("[^%02x]",k);
		else
			putchar(k);
	}
	fflush(stdout);
	return len;
}

int
s_read_terminal(STREAM * s,void * data,int len)
{
int ret,p,q;
char * dp;

retry:
	ret = s_read(s->terminal.inp,data,len);
	if ( ret < 0 ) {
		if ( errno == EINTR ) {
			*(char*)data = C_CANCEL;
			return 1;
		}
		return ret;
	}
	dp = data;
	q = 0;
	for ( p = 0 ; p < ret ; p ++ )
		if ( dp[p] == '\n' ) {
			(s->terminal.prompt)(s,q);
			q = 0;
		}
		else	q ++;
	return ret;
}

/*
int
s_vprintf_terminal(STREAM * s,char * fmt,va_list p)
{	
	return (*s->terminal.out->h.tbl->vprintf)(s->terminal.out,fmt,p);
}

int
s_vprintf_cr_terminal(STREAM * s,char * fmt,va_list p)
{
	return (*s->terminal.out->h.tbl->vprintf_cr)(s->terminal.out,fmt,p);
}
*/

int
s_flush_terminal(STREAM * s)
{
	return s_flush(s->terminal.out);
}

int
s_set_prompt(STREAM * s,int (*prompt)())
{
	if ( s->h.tbl != &s_terminal_table )
		return -1;
	s->terminal.prompt = prompt;
	return 0;
}
