/*////////////////////////////////////////////////////////////////////////
Copyright (c) 1993 Electrotechnical Laboratry (ETL)

Permission to use, copy, modify, and distribute this material for any
purpose and without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies, and
that the name of ETL not be used in advertising or publicity pertaining
to this material without the specific, prior written permission of an
authorized representative of ETL.
ETL MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY OF THIS
MATERIAL FOR ANY PURPOSE.  IT IS PROVIDED "AS IS", WITHOUT ANY EXPRESS
OR IMPLIED WARRANTIES.
/////////////////////////////////////////////////////////////////////////
Content-Type:	program/C; charset=US-ASCII
Program:	onewclient.c
Author:		Yutaka Sato <ysato@etl.go.jp>
Status:		public
Description:
History:
=V2.0	930729	added putget_onew
///////////////////////////////////////////////////////////////////////*/

#include <signal.h>
#include "onew.h"

static int onew_DBG = 1;
static int onew_pid;
static int to_onew[2];
static int from_onew[2];
#define TO_ONEW		to_onew[1]
#define FROM_ONEW	from_onew[0]

onew_pipe(pipe)
	int pipe[];
{
	pipe[0] = FROM_ONEW;
	pipe[1] = TO_ONEW;
	return onew_pid;
}

static dbg_printf(form,a,b,c,d,e,f,g){
	if( onew_DBG )
	Onew_message(form,a,b,c,d,e,f,g);
}

static open_onew(){
	register int pid;
	char *command;

	if(onew_pid != 0)
		return;
	command = (char*)getenv("ONEW");

	pipe(to_onew);
	pipe(from_onew);

	onew_DBG = (int)getenv("DEBUG_onew");
	pid = fork();
	if( pid == 0 ){
		close(TO_ONEW);
		close(0); dup(to_onew[0]); close(to_onew[0]);
		close(FROM_ONEW);
		close(1); dup(from_onew[1]); close(from_onew[1]);
		if(command)
			system(command);
		else	execlp("onew","onew",0);
		_exit(-1);
	}
	close(to_onew[0]);
	close(from_onew[1]);
	dbg_printf(">>KANAKANP>> %d\n",pid);
	onew_pid = pid;
}
end_onew(){
	if( onew_pid ){
		close(to_onew[1]);
		close(from_onew[0]);
		onew_pid = 0;
	}
}

static int sigpipe_occured;
static void sigpipe(){
	sigpipe_occured = 1;
}

static int sent_msgno;
put_onew(ch)
	int ch;
{	char buf[10];
	int wc;
	void (*osignal)();
	void (*signal())();
	int rcode = 0;

	open_onew();
	sent_msgno++;

	if( ch & 0xFF00 ){
		wc = 2;
		buf[0] = 0x80|(ch >> 8);
		buf[1] = 0x80|(ch&0xFF);
	}else{
		wc = 1;
		buf[0] = ch;
	}

	osignal = signal(SIGPIPE,sigpipe);

	wc = write(TO_ONEW,buf,wc);
	signal(SIGPIPE,osignal);

	if( wc < 0 || sigpipe_occured ){
		Onew_message("Can't send to onew, DEAD?\n");
		sigpipe_occured = 0;
		rcode = -1;
	}
	dbg_printf(">>KANAKANP>> %x (%d)\n",ch,wc);
	Onew_dbglog("put> %x\n",ch);
	return rcode;
}

static int rcvd_msgno;
get_onew(line,wait_msec) unsigned char *line; {
	int ch,chi = 0;
	int omask;

	open_onew();
	dbg_printf("<<KANAKANP<< WAINITNG...\n");

	omask = sigblock(sigmask(SIGALRM));
	if( 0 < Onew_fd_input_ready(FROM_ONEW,wait_msec*1000) ){
		for(;;chi++ ){
			if( read(FROM_ONEW,&line[chi],1) <= 0 )
				break;
			ch =  line[chi];
			if( chi != 0 && ch == 0xFF )
				break;
			dbg_printf("<<KANAKANP<< %x  '%c'\n",ch,ch);
		}
	}
	sigsetmask(omask);

	line[chi] = 0;
	dbg_printf("<<KANAKANP<< GOT[%s]\n\n",line);
	Onew_dbglog("got> %02x %s\n",line[0],line+1);
	return chi;
}

/*
 *	the following is made originally for XIN
 */

#define ONEW_VATTR_MASK	0x7F000000
#define ONEW_VATTR_ON   0x7F000000
#define ONEW_VATTR_OFF  0x7E000000
#define ONEW_VATTR_CLR  0x7D000000

int ONEW_VA_ON	= 1;
int ONEW_VA_OFF	= 2;
int ONEW_VA_CLR	= 3;

onew_operator(ch,argp)
	int *argp;
{	int Attr;

	if( Attr = ch & ONEW_VATTR_MASK ){
		*argp = ch & 0xFFFFFF;
		if( Attr == ONEW_VATTR_ON  ) return ONEW_VA_ON;
		if( Attr == ONEW_VATTR_OFF ) return ONEW_VA_OFF;
		if( Attr == ONEW_VATTR_CLR ) return ONEW_VA_CLR;
	}
	return 0;
}
char*
onew_character(ch,buf)
	char *buf;
{
	if( ch & 0xFF00 ){
		buf[0] = ch >> 8;
		buf[1] = ch &  0xFF;
		buf[2] = 0;
	}else{
		if( ch == '\b' || ch == 0177 )
			sprintf(buf,"\b \b");
		else	sprintf(buf,"%c",ch);
	}
	return buf;
}

int ONEW_BS_BYTES;
static int onew_active;
putget_onew(inch,chis)
	int *chis;
{	unsigned char msg[128];
	static int predel;
	static int attred;
	int pdi,chi,chix,outx;
	int bytes,chars;

	if( onew_active == 0 ){
		put_onew(CC_COMMAND);
		put_onew(CCC_VERSION2);
		onew_active = 1;
	}
	put_onew(inch);
	put_onew(CC_SYNC);
	chix = 0;

	for(;;){
	    if( get_onew(msg,1000) <= 0 )
		continue;

	    switch( msg[1] ){
		case SC_INPUT:
		if( predel != 0 ){
			for(pdi = 0; pdi < predel; pdi++)
				chis[chix++] = '\b';
			predel = 0;
		}
		for( outx = 2; chi = msg[outx]; outx++ ){
			if( chi & 0x80 )
				chi = (msg[++outx]&0x7F) | ((chi&0x7F)<<8);
			chis[chix++] = chi;
		}
		break;
		case SC_CONFIRM:
			chis[chix++] = ONEW_VATTR_CLR | predel;
			predel = 0;
			break;

		case SC_DELETE: 
			if( ONEW_BS_BYTES ){
				sscanf(&msg[2],"%d",&bytes);
				predel += bytes;
			}else
			if(sscanf(&msg[2],"%d %d",&bytes,&chars) == 2)
				predel += chars;
			else	predel += bytes/2;
			break;

		case SC_SYNC:	  goto GOTCH;
		case SC_MESSAGE:  Onew_message("%s",&msg[2]); break;
		case SC_RKSTAT:   Onew_message("%s",&msg[2]); break;

		case SC_CHATTR:
			if( msg[2] == '+' )
				chis[chix++] = ONEW_VATTR_ON | msg[3];
			else	chis[chix++] = ONEW_VATTR_OFF| msg[3];
			break;
	    }
	}
GOTCH:
	chis[chix] = 0;
	return chix;
}
onew_symASCII(){
	put_onew(CC_COMMAND);
	put_onew(CCC_SYM_ASCII);
}


syntax highlighted by Code2HTML, v. 0.9.1