/** << High C >> **************************************************************
**
**	ﾃｷｽﾄﾌｧｲﾙ表示ﾃｽﾄﾌﾟﾛｸﾞﾗﾑ(INT23h/INT24h処理を含む)
**
**	< History >
**	1991.03.06 : CREATE
**	1991.05.07 : CTRL+C,致命的ｴﾗｰ時の処理追加｡
**
**	< note > : TABS = 4
**
**	Programmed by Y.Hirata ( Nifty ID : NAB03321 )
**
******************************************************************************/

pragma	Off (Floating_point) ;

#include <stdio.h>
#include <dos.h>
#include <msdos.cf>
#include <egb.h>
#include <stdlib.h>
#include <string.h>
#include <fmc.h>
#include "hc.h"
#include "key.h"
#include <stdefs.h>
#include "doserror.h"

#define	GworkSize	1536						/*  ｸﾞﾗﾌｨｯｸ作業域のｻｲｽﾞ		*/
char	Gwork[GworkSize] ;						/*  ｸﾞﾗﾌｨｯｸ作業域			*/

typedef struct _LINEPTR {
	struct _LINEPTR	*next ;						/*  次の行ﾃﾞｰﾀﾎﾟｲﾝﾀ			*/
	struct _LINEPTR	*back ;						/*  前の行ﾃﾞｰﾀﾎﾟｲﾝﾀ			*/
	char	sp[1] ;								/*  行内の文字列ﾎﾟｲﾝﾀ		*/
} LINEPTR ;

/*******************************  致命的ｴﾗｰ処理  *****************************/
static int critical_handler( unsigned di,unsigned ax )
/*=============================================================================
**	致命的ｴﾗｰ処理をﾏｽｸする.
**
**	< INPUT  > : di ｴﾗｰｺｰﾄﾞ(下位1ﾊﾞｲﾄだけ有効)
**			   : ax 他のﾃﾞﾊﾞｲｽのｴﾗｰｺｰﾄﾞ
**	< OUTPUT > : なし
**	< RETURN > : 致命的ｴﾗｰに対する処置
=============================================================================*/
{
	register int	act ;
	int		errcode ;

/*
**	致命的ｴﾗｰ発生時のﾒｯｾｰｼﾞ表示
*/
	TEXT_cr() ;
	TEXT_color( C_HYELLOW ) ;
	/*  ｴﾗｰｺｰﾄﾞ表示	*/
	errcode = di & 0x00ff ;
	if ( errcode > NDOSerr_code_msg || errcode < 0 ) {
		errcode = NDOSerr_code_msg ;
		TEXT_printf( "ｴﾗｰｺｰﾄﾞ(%d): %s\n",
				(di&0x00ff),DOSerr_code_msg[errcode] ) ;
	} else {
		TEXT_printf( "ｴﾗｰｺｰﾄﾞ(%d): %s\n",
				errcode,DOSerr_code_msg[errcode] ) ;
	}
	TEXT_color( C_WHITE ) ;

	act = INT24_IGNORE ;
/*
**	致命的ｴﾗｰに対する処理を設定する
*/
	switch ( act ) {
	case INT24_RETRY :
	case INT24_ABORT :
	case INT24_FAIL :
		ax = ( ax & 0xFF00 ) + act ;
		break ;
	case INT24_IGNORE :
		ax = ( ax & 0xFF00 ) + INT24_FAIL ;
	}
	return( ax ) ;
}

/*********************************  初期化  **********************************/
void ginit()
{
	TEXT_init( Gwork,GworkSize ) ;		/* EGB 初期化						*/
	GRP_viewport( 0,0,1023,511 ) ;		/* View Port SET					*/
	GRP_writePage( 1 ) ;
	EGB_clearScreen( Gwork ) ;
	EGB_displayPage( Gwork,0,3 ) ;		/* Show page 0 & 1 : Priority 0		*/
	TEXT_cursor( FALSE ) ;				/* ｶｰｿﾙ非表示						*/
	TEXT_color( C_WHITE ) ;
	TEXTcrflg = TRUE ;
}

/*****************************  行ﾃﾞｰﾀ格納域確保  ****************************/
LINEPTR *linealloc( char *str )
{
	LINEPTR	*lp ;
	int		len ;

	len = strlen( str ) ;
	if ( len < 1 ) return( NULL ) ;

	lp = (LINEPTR *)malloc( len+sizeof(LINEPTR) ) ;
	if ( lp != NULL ) {
		lp->next = lp->back = NULL ;
		strcpy( lp->sp,str ) ;
	}

	return( lp ) ;
}

/*****************************  行ﾃﾞｰﾀ格納域開放  ****************************/
LINEPTR *linefree( LINEPTR *lp )
{
	LINEPTR	*next, *back ;

	next = lp->next ;
	back = lp->back ;
	if ( next != NULL ) next->back = back ;
	if ( back != NULL ) back->next = next ;
	free( lp ) ;

	return( next ) ;
}

/*****************************  行ﾃﾞｰﾀ格納域開放  ****************************/
LINEPTR *linefreeall( LINEPTR *lp )
{
	LINEPTR	*next, *back ;

	while ( lp != NULL ) {
		next = lp->next ;
		back = lp->back ;
		if ( next != NULL ) next->back = back ;
		if ( back != NULL ) back->next = next ;
		free( lp ) ;
		lp = next ;
	}

	return( next ) ;
}

/********************************  行ﾃﾞｰﾀｾｯﾄ  ********************************/
LINEPTR *setline( FILE *fp,int *n )
{
	char	buf[MAXCOLM+1] ;
	LINEPTR	*top, *now, *wk ;
	int		nline ;

	nline = 0 ;
	top = linealloc( "TYPE.EXP : ESCｷｰで終了 : ↑↓でｽｸﾛｰﾙ. (SHIFT+で高速)     Programed by Y.Hirata\n" ) ;
	now = top ;
	nline ++ ;
	while ( fgets( buf,sizeof(buf),fp ) != NULL ) {
		wk = linealloc( buf ) ;
		if ( wk != NULL ) {
			if ( top->next == NULL ) {
				top->next = wk ;
				wk->back = top ;
			} else {
				now->next = wk ;
				wk->back = now ;
			}
			now = wk ;
			nline ++ ;
		}
	}
	wk = linealloc( "[EOF]" ) ;
	if ( wk != NULL ) {
		now->next = wk ;
		wk->back = now ;
		now = wk ;
		nline ++ ;
	}

	*n = nline ;
	return( top ) ;
}

/*****************************  ★ メイン ★  ********************************/
void main( int ac,char *av[] )
{
	FILE	*fp ;
	int		c ;
	int		err = FALSE ;
	LINEPTR	*top, *botm ;
	int		nowtop, nline ;
	char	matrix[16] ;

	ginit() ;								/* EGB 初期化				*/

	INT24_entry = critical_handler ;
	INT24_init() ;							/*  INT23h/INT24h設定		*/

	if ( ac > 1 ) {				/*  引数あり	*/
		if ( (fp=fopen( av[1],"r" )) == NULL ) {
			TEXT_printf( "can't open input file : %s\n",av[1] ) ;
			err = TRUE ;
		}
	} else {					/*  引数なし	*/
		TEXT_printf( "データファイル名を指定して下さい！\n" ) ;
		err = TRUE ;
	}

	if ( !err ) {
		TEXTtabs = 4 ;
		top = setline( fp,&nline ) ;
		botm = top ;
		TEXT_color( C_HGREEN ) ;
		for ( c=0; c<MAXLINE-1; c++ ) {
			if ( botm->next == NULL ) TEXT_color( C_GREEN ) ;
			TEXT_printf( "%s",botm->sp ) ;
			if ( botm->next == NULL || c == 0 ) TEXT_color( C_WHITE ) ;
			if ( botm->next == NULL ) break ;
			botm = botm->next ;
		}
		if ( nline >= MAXLINE ) {
			if ( botm->next == NULL ) TEXT_color( C_GREEN ) ;
			TEXT_puts( botm->sp ) ;
			if ( botm->next == NULL ) TEXT_color( C_WHITE ) ;
		}
		TEXT_locate( 1,1 ) ;
		TEXT_printf( "<%d line>",nline-2 ) ;
		if ( nline < MAXLINE ) {
			TEXT_locate( nline+1,1 ) ;
		} else {
			TEXT_locate( MAXLINE,1 ) ;
		}
		nowtop = 1 ;
		TEXT_printf( "\x1b[m" ) ;
		do {
			KYB_clrbuf() ;						/*  ﾊﾞｯﾌｧｸﾘｱ				*/
			KYB_matrix( matrix ) ;
			if ( KEY_test( matrix,KEY_UP ) ) {
				do {
					if ( nowtop > 1 && top->back != NULL ) {
						nowtop -- ;
						top  = top->back ;
						botm = botm->back ;
						if ( top->back == NULL ) TEXT_color( C_HGREEN ) ;
						TEXT_control( FALSE ) ;
						TEXT_revscroll( top->sp ) ;
						if ( top->back == NULL ) TEXT_color( C_WHITE ) ;
					}
					if ( !KEY_test( matrix,KEY_SHIFT ) )
						SOFT_timer( KEY_REPEAT ) ;
					KYB_clrbuf() ;				/*  ﾊﾞｯﾌｧｸﾘｱ				*/
					KYB_matrix( matrix ) ;
				} while ( KEY_test( matrix,KEY_UP ) ) ;
				SOFT_timer( KEY_WAIT ) ;
			} else if ( KEY_test( matrix,KEY_DOWN ) ) {
				do {
					if ( nowtop+MAXLINE-1 < nline && botm->next != NULL ) {
						nowtop ++ ;
						top  = top->next ;
						botm = botm->next ;
						if ( botm->next == NULL ) TEXT_color( C_GREEN ) ;
						TEXT_control( TRUE ) ;
						TEXT_scroll( botm->sp ) ;
						if ( botm->next == NULL ) TEXT_color( C_WHITE ) ;
					}
					if ( !KEY_test( matrix,KEY_SHIFT ) )
						SOFT_timer( KEY_REPEAT ) ;
					KYB_clrbuf() ;				/*  ﾊﾞｯﾌｧｸﾘｱ				*/
					KYB_matrix( matrix ) ;
				} while ( KEY_test( matrix,KEY_DOWN ) ) ;
				SOFT_timer( KEY_WAIT ) ;
			}
		} while ( !KEY_test( matrix,KEY_ESC ) ) ;
		KEY_break( KEY_ESC ) ;
		fclose( fp ) ;
	}

	KYB_clrbuf() ;								/*  ﾊﾞｯﾌｧｸﾘｱ				*/
	TEXT_color( C_HGREEN ) ;
	TEXT_printf( "\n何かキーを押して下さい. 終了します." ) ;
	while ( !KEY_hitchk() ) ;
	KYB_clrbuf() ;								/*  ﾊﾞｯﾌｧｸﾘｱ				*/
/*
**	ｺﾝｿｰﾙ画面に戻す
*/
	EGB_init( Gwork,GworkSize ) ;		 /*  ｺﾞﾐを消すため EGB 初期化		*/
	EGB_clearScreen( Gwork ) ;
	coninit() ;
}

