/*////////////////////////////////////////////////////////////////////////
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:	onew.c (onew server)
Author:		Yutaka Sato <ysato@etl.go.jp>
Status:		public
Description:
History:
	ancient	created
=V2.0	930730	return kakutei keys if the buffers don't include non-ascii
=V2.0	930730	Control-U clears current input buffer if it's not empty
	
///////////////////////////////////////////////////////////////////////*/

#include <signal.h>
#include <ctype.h>
#include <stdio.h>
extern char *getenv();
#include "onew.h"

int on_via;
int onew_client_version = 1;

#define VER1	(onew_client_version == 1)
#define VER2	(onew_client_version == 2)

int ONEW_THRUSYMS_ON;

static Linebuff onew_buf;
static Mssgbuff onew_out;
static int idbx;
static clear_bufs(){
	onew_buf[0] = 0;
	onew_out[0] = 0;
	idbx = 0;
}
static int is_tty;
static int is_sock;
static FILE *logfp;

static put_client();


/*######################################################################*
 *	ONEW AS A ROMAJI/KANA/KANJI HENKAN SERVER PROCESS		*
 *######################################################################*/
static cdump(name)
	char *name;
{	int ch;
	int count,bytes;

	printf("unsigned char %s[] = {\n",name);

	count = 0;
	bytes = 0;
	while( (ch = getchar()) != EOF ){
		bytes++;
		printf("%3d,",ch);
		if( 20 <= ++count ){
			printf("\n");
			count = 0;
		}
	}
	printf("};\n");
	printf("int %s_SIZE = %d;\n",name,bytes);
}

main(ac,av)
	char *av[];
{	char *debug;
	int ch1,ch2;

	if( 2 <= ac ){
		if( strcmp(av[1],"-rktab") == 0 ){
			Onew_showrktab();
			exit(0);
		}
		if( strcmp(av[1],"-cdump") == 0 ){
			cdump(av[2]);
			exit(0);
		}
		if( strcmp(av[1],"-xrktab") == 0 ){
			Onew_extract_rktabs();
			exit(0);
		}
		if( strcmp(av[1],"-kkdic") == 0 ){
			Onew_kkdic();
			exit(0);
		}
	}

	ac = onew_on_via(ac,av);

	if( isatty(0) ){
		Onew_ttyIcanon(0);
		logfp = stderr;
	}else{
		Onew_notty();
		logfp = stdout;
	}
	is_tty = !on_via && isatty(1);

	signal(SIGINT,SIG_IGN);
	ONEW_MESSAGE(0,"[ROMKAN & KANAKAN FILTER] %s start.",Onew_version());
	if( debug = getenv("DEBUG_onew") )
		ONEW_DEBUG = atoi(debug);

/* keep Cntl('K') uninterpreted */
ONEW_KANA_TOGGLE = Cntl('Z');


	for(;;){
		ch1 = kgetc();
		if(ch1 == 0)
			continue;

		if( ch1 == 0xFF || ch1 == -1 )
			break;

		if( is_sock ){
			put_client(S_CHATTR,"+U");
			if( ch1 & 0x80 ){
				ch2 = kgetc();
				put_client(S_INPUT,"%c%c",ch1,ch2);
			}else	put_client(S_INPUT,"%c",ch1);
			put_client(S_CHATTR,"-U");
		}else
		if( is_tty ){
			if( ch1 & 0x80 ){
				ch2 = kgetc();
				Onew_fprintf(logfp,"%c%c",ch1,ch2);
			}else{
				fprintf(logfp,"%c",ch1);
			}
		}else
		{
			printf("%c",ch1);
			if( ch1 & 0x80 ){
				ch2 = kgetc();
				printf("%c",ch2);
			}
		}
		fflush(logfp);
	}
	if( isatty(0) )
		Onew_ttyIcanon(1);

	if( !is_tty && !is_sock )
		printf("\n");

	Onew_KK_freqsave();
}

static onew_xcom(){
	int ch;

	Onew_fprintf(stderr,"ONEW-COMMAND> ");
	ch = getchar();
	Onew_fprintf(stderr,"%c\n",ch);
}

ONEW_GETCHAR()
{	int ch;

	for(;;){
		ch = GetChar1();
		ouiTrace("onew_GETCHAR","(%x)",ch);

		if( ONEW_DEBUG )
			Onew_fprintf(stderr,"ONEW_GETCHAR: %x\n",ch);

		switch( ch ){
		    default:
			if( ch == Cntl('\\') )
				ch = Cntl('@');

			goto Break;

		    case CC_SYNC:
			set_is_sock();
			put_client(S_SYNC,"");
			ch = 0;
			break;

		    case CC_COMMAND:
			set_is_sock();
			switch( GetChar1() ){
			    case CCC_VERSION2:
				onew_client_version = 2;
				break;
			    case CCC_SYM_JIS:
				ONEW_THRUSYMS_ON = 0;
				break;
			    case CCC_SYM_ASCII:
				ONEW_THRUSYMS_ON = 1;
				break;
			}
			break;

		    case CC_XCOMMAND:
			set_is_sock();
			onew_xcom();
			break;
		}
	} Break:;
	return ch;
}

static put_client(command,form,a,b,c,d,e,f)
	char *command,*form;
{	Linebuff out,tmp;
	char *op;
	int ci,ch1,ch2;
	static int nmsg = 0;

	if( nmsg++ == 1 )
		put_client(S_MESSAGE,":[ROMKAN & KANAKAN FILTEDR] %s",
			Onew_version());

	op = (char*)out;
	sprintf(op,"%c%s",0xFF,command);
	op += strlen(op);

	sprintf(op,form,a,b,c,d,e,f);
	if( strcmp(command,S_INPUT) == 0 )
	if( VER1 )
	/* AND 1bytes character is INHIBITED */
	{
		ASCII_TO_JIS(op,tmp);
		strcpy(op,tmp);
	}
	op += strlen(op);

	sprintf(op,"%c",0xFF);

	if( ONEW_DEBUG ){
		fprintf(stderr,"%s: %-10s %8x %8x ",command,form,a,b,c,d,e,f);
		for( ci = 0; ch1 = out[ci]; ci++ ){ 
		  ch2 = out[ci+1];
		  if( ch1 & 0x80 && ch2 & 0x80 ){
			fprintf(stderr,"\033$B%c%c\033(B",ch1&0x7F,ch2&0x7F);
			ci++;
		  }else	fprintf(stderr,"[%2x]",ch1);
		}
		fprintf(stderr,"\n");
	}
	send_to_client(out);
}
static got_server(ch){
	if( ch == 0xFF ){
		/* do echo */
		ch = 0;
	}
	return ch;
}
static charlen(str)
	char *str;
{	int i,len,ch;

	len = 0;
	for( i = 0; ch = str[i]; i++ ){
		len++;
		if( (ch & 0x80) && str[i+1] )
			i++;
	}
	return len;
}

static int romkan_init_done;
kgetc(){
	int inch;

	if( romkan_init_done == 0 ){
		romkan_init_done = 1;
		Onew_RK_init();
		Onew_RK_cmode_set('h');
	}
	inch = Onew_romkan();
if( inch == ESC_CH )
if( is_tty ){
	if( OnewPeekchar(200) == EOF )
		inch = EOF;
}

if( inch == 0 ){}else

	if( inch == -1 ){
		/*fprintf(stderr,"*** EOF ***\n");*/
	}else
	if( idbx ){
	    switch( inch ){
		case 033:
		case Cntl('C'):
		case '\n':
		case '\r':
			idbx = 0;
			if( Onew_non_ascii(onew_buf) ){
				inch = 0;
			}
			break;

		case 0x7F:
		case '\b':
			if( 0 < idbx ){
				if( onew_buf[idbx-1] & 0x80 )
					idbx -= 2;
				else	idbx -= 1;
				onew_buf[idbx] = 0;
			}else	ONEW_BEEP(1);
			break;

		case Cntl('U'):
			if( is_tty )
			    Onew_fprintf(stderr,"\r");
			else
			if( is_sock ){
			    put_client(S_DELETE,"%d %d",
				strlen(onew_buf),charlen(onew_buf));
			    put_client(S_INPUT,"%s","");/* do delete */
			}
			clear_bufs();
			inch = 0;
			break;

		case Cntl('V'):
			inch = Onew_romkan();
			onew_buf[idbx++] = inch;
			break;

		default:
			if( 0x20 < inch && inch < 0x7F || inch & 0x80 )
				onew_buf[idbx++] = inch;
			else
			if( Onew_RK_imode() ){
				ONEW_MESSAGE(1,"[%x] %s",
					inch,"ONEW BUFFER IS NOT EMPTY.");
				ONEW_BEEP(2);
sleep(2);
				inch = 0;
			}else	onew_buf[idbx++] = inch;
			break;
	   }
	}else{
		if( Onew_RK_imode() ){
			if( 0x20 < inch && inch < 0x7F || inch & 0x80 ){
				onew_buf[idbx++] = inch;
			}
		}else{
/* 920923 */
if( !iscntrl(inch) )
			onew_buf[idbx++] = inch;
		}
	}
	onew_buf[idbx] = 0;
	return inch;
}
ONEW_KANAKAN(ch){
	char com;

	if( idbx ){
		if( is_sock ){
			put_client(S_DELETE,"%d %d",
				strlen(onew_buf),charlen(onew_buf));
		}
		com = Onew_kanakan(ch,onew_buf,0,idbx);

 		switch( com ){
			case Cntl('H'):
			case 0x7F:
				strcpy(onew_out,onew_buf);
				if( is_sock ){
					put_client(S_CHATTR,"%s","+U");
					put_client(S_INPUT,"%s",onew_out);
					put_client(S_CHATTR,"%s","-U");
				}
				break;

			default:
/*
				ONEW_KAKUTEI(com);
*/
				Onew_kakutei(com);
				break;
		}
		com = 0;
	}else{
		com = ch;
	}

	return com;
}

/*
 *	returns TRUE if kakutei key should NOT be treated as normal input
 */
static pending_newline;
ONEW_KAKUTEI(key){
	int na;

	na = Onew_non_ascii(onew_buf) || Onew_non_ascii(onew_out);
	if( is_sock ){
		put_client(S_CONFIRM,"");
	}else
	if( is_tty ){
		if( onew_out[0] ){
			Onew_fprintf(stdout,"%s\n",onew_out);
			fflush(stdout);
			pending_newline = 0;
		}
	}else{
		printf("\n%s",onew_out);
	}
	clear_bufs();
	return na;
}

static int LAST_KH;
ONEW_DISP_KANAHALF(ch){
	if( is_sock ){
		if( ch == ' ' ){
			put_client(S_INPUT,"%s","");
		}else{
			put_client(S_INPUT,"%c%c",0x80|'#',0x80|ch);
			put_client(S_DELETE,"%d %d",2,1);
		}
	}else
	if( is_tty ){
		printf("%c\b",ch);
		fflush(stdout);
	}
	LAST_KH = ch;
}

set_is_sock(){
	if( is_sock == 0 ){
		is_sock = 1;
		if( LAST_KH )
			ONEW_DISP_KANAHALF(LAST_KH);
	}
}

ONEW_DISP_KANAKANB(so,left,current,right)
	char *left,*current,*right;
{	int bytes,chars;

	if( is_sock ){
		bytes = strlen(left) + strlen(current) + strlen(right);
		chars =charlen(left) +charlen(current) +charlen(right);

		if( *left ){
			put_client(S_CHATTR,"%s","+U");
			put_client(S_INPUT,"%s",left);
			put_client(S_CHATTR,"%s","-U");
		}
		if( *current ){
			put_client(S_CHATTR,"%s","+R");
			put_client(S_INPUT,"%s",current);
			put_client(S_CHATTR,"%s","-R");
		}
		if( *right ){
			put_client(S_CHATTR,"%s","+U");
			put_client(S_INPUT,"%s",right);
			put_client(S_CHATTR,"%s","-U");
		}
		put_client(S_DELETE,"%d %d",bytes,chars);
		if( VER1 ) put_client(S_MESSAGE,"%s%s%s%s%s",
			left,"\033[7m",current,"\033[m",right);
	}else
	if( is_tty ){
		Onew_fprintf(stderr,"\r%s%s%s%s%s",
			left,"\033[7m",current,"\033[m",right);
		Onew_fprintf(stderr,"\033[K\r");
		pending_newline = 1;
		fflush(stderr);
	}
	sprintf(onew_out,"%s%s%s",left,current,right);
	onew_out[strlen(onew_out)+1] = 0;
}
ONEW_BEEP(nsec){
	Onew_fprintf(stderr,"%c",7);
	fflush(stdout);
}
static int prev_modef;
ONEW_DISP_ROMKANMODE(cmode,chelp,modef)
	char *cmode,*chelp;
{
	if( modef == prev_modef )
		return;

	if( is_sock ){
	   if( VER2 )
		put_client(S_RKSTAT,"%s %s %s",cmode,chelp,Onew_version());
	   else	put_client(S_MESSAGE,"%s%s",cmode,chelp);
	}else
	if( is_tty ){
		if( pending_newline )
			Onew_fprintf(stderr,"\n");
		Onew_fprintf(stderr,"%s %s\n",cmode,chelp);
	}
	prev_modef = modef;
}

ONEW_MESSAGE(so,form,a,b,c,d)
	char *form;
	char *a,*b,*c,*d;
{	Mssgbuff msg;
	static int nmsg = 0;

	if( is_tty ){
		if( nmsg == 0 )
			Onew_fprintf(stderr,"Hit ESC to quit.\n");
			Onew_fprintf(stderr,"\r");
		if( so )Onew_fprintf(stderr,"\n\033[7m");
			Onew_fprintf(stderr,form,a,b,c,d);
		if( so )Onew_fprintf(stderr,"\033[m");
			Onew_fprintf(stderr,"\n");
	}else
	if( is_sock )
	{
		sprintf(msg,form,a,b,c,d);
		put_client(S_MESSAGE,":%s",msg);
	}
	nmsg++;
}

int TERMCAP_INIT = 1;
Tgetnum(id)
	char *id;
{
	if(strcmp(id,"li") == 0)
		return 24;
	else	return 80;
}


#ifndef VIA
onew_on_via(ac,av){ return ac; }
GetChar1(){
	int ch;

	ch = Onew_getchar(0,0);
	return ch;
}
send_to_client(out){
	printf("%s",out);
	fflush(stdout);
}
#else
#include "via+onew.c"
#endif


syntax highlighted by Code2HTML, v. 0.9.1