/*
	TOMCON2.C  by Y.Kurihara (Nif PDC01620)
		int 29h の割り込み処理部
*/

#include <string.h>
#include <jctype.h>
#include <dos.h>
#include <machine.h>
#include "tomcon.h"

int  x0 = X0;
int  y0 = Y0;
int  xl = XL;
int  yl = YL;
int  lx = 0;
int  ly = 0;
int  code1 = 0;
int  esc1 = 0;
int  reverse = -1;
int  fl_cur = 0;
int  md_cur = 1;

void ( far *save_int29 )( void );
void ( far *new_int29 )( void );

void putctl( int code )
{
	switch( code ) {
	case 0x07:	/* BEL */
	case 0x15:	/* NAK */
		break;
	case 0x08:	/* BS */
		if( lx == 0 && ly == 0 )  break;
		if( --lx < 0 ) {
			lx = xl - 1;
			ly--;
		}
		putank( ' ' );
		break;
	case 0x09:	/* TAB */
		do {
			int29( ' ' );
		} while( lx % 8 );
		break;
	case 0x0a:	/* LF */
		if( ++ly >= yl ) {
			ly = yl - 1;
			roll( y0,y0 + yl - 1 );
		}
		break;
	case 0x0b:	/* VT */
		lx = ly = 0;
		break;
	case 0x0c:	/* FF */
	case 0x16:	/* SYN */
		clr( y0,y0 + yl - 1 );
		lx = ly = 0;
		break;
	case 0x0d:	/* CR */
		lx = 0;
		break;
	case 0x1c:	/* FS */
		if( lx < xl - 1 )  lx++;
		break;
	case 0x1d:	/* GS */
		if( lx > 0 )  lx--;
		break;
	case 0x1e:	/* RS */
		if( ly > 0 )  ly--;
		break;
	case 0x1f:	/* VS */
		if( ly < yl - 1 )  ly++;
		break;
	default:
		int29( '^' );
		int29( code + '@' );
		break;
	}
}

void putesc( int code )
{
	static int para[10];
	static int count;
	static int save_lx;
	static int save_ly;

	if( esc1 == 1 ) {
		count = 0;
		para[0] = 0;
		para[1] = 0;
		switch( code ) {
		case '[':
			esc1 = 2;
			return;
		case '*':
			clr( y0,y0 + yl - 1 );
			lx = ly = 0;
			break;
		case 'Y':
			clr( y0 + ly + 1,y0 + yl - 1 );
		case 'T':
			save_lx = lx;
			do {
				putank( ' ' );
			} while( ++lx < xl );
			lx = save_lx;
			break;
		case 'E':
			lx = 0;
			roll2( y0 + ly,y0 + yl - 1 );
			break;
		case 'R':
			roll( y0 + ly,y0 + yl - 1 );
			break;
		}
		esc1 = 0;
		return;
	}

	if( isdigit( code ) ) {
		para[ count ] = para[ count ] * 10 + code - '0';
		return;
	} else if( code == ';' ) {
		count++;
		para[count] = 0;
		return;
	} else if( code == '>' ) {
		return;
	}

	switch( code ) {
	case 'H':
	case 'f':
		if( para[0] == 0 )  para[0] = 1;
		if( para[1] == 0 )  para[1] = 1;
		ly = para[0] - 1;
		lx = para[1] - 1;
		break;
	case 'A':
		if( para[0] == 0 )  para[0] = 1;
		ly -= para[0];
		break;
	case 'B':
		if( para[0] == 0 )  para[0] = 1;
		ly += para[0];
		break;
	case 'C':
		if( para[0] == 0 )  para[0] = 1;
		lx += para[0];
		break;
	case 'D':
		if( para[0] == 0 )  para[0] = 1;
		ly -= para[0];
		break;
	case 's':
		save_lx = lx;
		save_ly = ly;
		break;
	case 'u':
		lx = save_lx;
		ly = save_ly;
		break;
	case 'J':
		if( para[0] != 2 )  break;
		clr( y0,y0 + yl - 1 );
		lx = ly = 0;
		break;
	case 'K':
		if( para[0] != 0 )  break;
		save_lx = lx;
		do {
			putank( ' ' );
		} while( ++lx < xl );
		lx = save_lx;
		break;
	case 'm': {
		int i;
		for( i = 0; i <= count; i++ ) {
			if( para[i] == 0 ) reverse = -1;
			if( para[i] == 7 ) reverse = 0;
		}
		break; }
	case 'v':
		if( para[0] ==0 )  md_cur = 1;  else  md_cur = 0;
		break;
	case 'M':
		lx = 0;
		if( para[0] == 0 )  para[0] = 1;
		while( para[0]-- > 0 )  roll( y0 + ly,y0 + yl - 1 );
		break;
	case 'L':
		lx = 0;
		if( para[0] == 0 )  para[0] = 1;
		while( para[0]-- > 0 )  roll2( y0 + ly,y0 + yl - 1 );
		break;
	case 'l':
		if( para[0] == 5 )  md_cur = 1;
		break;
	case 'h':
		if( para[0] == 5 )  md_cur = 0;
		break;
	}
	if( lx < 0 )   lx = 0;
	if( lx >= xl ) lx = xl - 1;
	if( ly < 0 )   ly = 0;
	if( ly >= yl ) ly = yl - 1;
	esc1 = 0;
	return;
}

void int29( int code )			/* 一文字表示ルーチン */
{
	cur( 0 );
	code = code & 0xff;

	if( esc1 ) {
		putesc( code );
	} else if( code1 ) {			/* 漢字コード */
		if( lx + 2 > xl ) {
			lx = 0;
			putctl( 0x0a );
		}
		code = ( code1 << 8 )+ code;
		code = mstojis( code );
		putkan( code );
		lx += 2;
		code1 = 0;
	} else if( code == 0x1b ) {	/* エスケープコード */
		esc1 = 1;
	} else if( iskanji( code ) ) {	/* 漢字コードの1文字目 */
		code1 = code;
	} else if( code >= ' ' ) {	/* 半角文字 */
		if( lx + 1 > xl ) {
			lx = 0;
			putctl( 0x0a );
		}
		putank( code );
		lx++;
	} else {
		putctl( code );
	}

	cur( md_cur );
}

void set_int29()			/* INT 29H をフックする */
{
	static char lstack[512];
	struct SREGS seg;

	segread( &seg );
	new_ds = seg.ds;
	new_es = seg.es;
	new_ss = FP_SEG( lstack );
	new_sp = FP_OFF( lstack + 510 );
	new_int29 = _int29;

	save_int29 = _dos_getvect( 0x29 );
	_dos_setvect( 0x29,new_int29 );
}

void reset_int29()			/* INT 29H をもとに戻す */
{
	_dos_setvect( 0x29,save_int29 );
}

