/* << High C V1.4 >> **********************************************************
**
**	ﾃｷｽﾄ表示ﾙｰﾁﾝ
**
**	☆ 640*480 16色ﾓｰﾄﾞ対応
**
**	1画面をﾃｷｽﾄ画面とみなして、ﾃｷｽﾄの表示を行う.
**
**	1991.03.02 : CREATE
**	1991.03.02 : FINISH
**
**	< History >
**	1991.03.02 : CREATE
**	1991.04.27 : 清書
**	1991.06.10 : ESCｼｰｹﾝｽ処理のﾊﾞｸﾞ修正.
**
**	< note > : TABS = 4
**
**	Programmed by Y.Hirata ( Nifty ID : NAB03321 )
**
******************************************************************************/

#include <stdio.h>
#include <dos.h>
#include <msdos.cf>
#include <string.h>
#include <stdlib.h>
#include <egb.h>
#include "hc.h"
#include "key.h"

/*=============================================================================
**	使用上の注意事項
**
**	1. 画面ﾓｰﾄﾞは、16色,480line(ﾓｰﾄﾞ3)に対応しています。それ以外のﾓｰﾄﾞでは
**	   正しく表示されません。
**
**	2. ここの関数群は、1画面しか考慮していません。2画面を使用する場合には、
**	   書き込みﾍﾟｰｼﾞに気を付ける必要があります。
**
**	3. TEXT_init()をあらかじめCALLしておく必要があります。
**	   TEXT_init()を使用する時には,GRP_init()は必要ありません｡
**
**	4. 文字ﾌｫﾝﾄは、標準体以外は使用できません。また、表示開始位置は X座標が
**	   8の倍数の場所に限ります.
**
**	5. ﾃｷｽﾄを表示しているﾍﾟｰｼﾞでは、EGB_displayStart()で表示開始位置を変更
**	   したり、EGB_clearScreen()を使用してはいけません。つまり画面上の表示
**	   をここの関数群以外の関数を使用して変更した場合には、ﾃｷｽﾄの表示位置が
**	   予期しないところになります。
**
**	6. 描画領域の設定は、仮想画面いっぱいとして下さい｡
**
**	7. ﾃｷｽﾄの書き込みﾍﾟｰｼﾞに対して、EGBﾗｲﾌﾞﾗﾘを使用する場合には、TEXT_pos()
**	   を使用して x,y の座標を変換した後にその値を使用して下さい｡
=============================================================================*/

/*
**	仮想画面上の表示開始位置のX値は、変更しないことを前提とする。
*/
struct _TEXT_POSITION {
	short	vx, vy ;		/*  仮想画面上表示開始位置	: 0〜31		*/
	short	dx, dy ;		/*  画面上のﾃｷｽﾄ表示位置	: 0〜29		*/
	short	px, py ;		/*  ﾃｷｽﾄ書き込み位置		: 0〜31		*/
} ;
static struct _TEXT_POSITION	TEXTpos = { 0,0, 0,0, 0,0 } ;

static char	TEXTcurdata[12] = {	1, 2,
						0xff, 0xff, 0xff, 0xff,
						0xff, 0xff, 0xff, 0xff,
						0xff,
						0xff
					} ;
static char	Cursorflg = FALSE ;					/*  ｶｰｿﾙ表示する？			*/

#define	MAXTABS		8							/*  最大TABｽﾍﾟｰｽ数			*/
int		TEXTtabs = 8 ;							/*  TABｽﾍﾟｰｽ				*/

char	TEXTctrl  = TRUE ;						/*  制御ｺｰﾄﾞの処理をする？	*/
char	TEXTcrflg = FALSE ;						/*  改行ﾏｰｸを表示する？		*/

int		TEXTfcolor = C_WHITE ;					/*  前景色					*/
int		TEXTbcolor = C_BLACK ;					/*  背景色					*/

extern int	VRAMfcolor ;						/*  VRAM描画用文字色		*/
extern int	VRAMbcolor ;						/*  VRAM描画用背景色		*/

/*  漢字の第１ﾊﾞｲﾄかのﾁｪｯｸ */
#define iskanji(c)  ((0x81 <= c && c <= 0x9F) || (0xE0 <= c && c <= 0xFC))

#define	INT_BEEP		0x9E					/*  BIOS割り込み番号		*/
#define	BEEP_TIME		18						/*  BEEP時間 x 10 ms		*/
#define	BEEP_COUNT		10						/*  19200 / ? Hz			*/

static uchar	TEXT_pal[16][3] = {
							/*    B   R   G : 上位 4ﾋﾞｯﾄ	*/
								  0,  0,  0,
								176,  0,  0,
								  0,176,  0,
								176,176,  0,
								  0,  0,176,
								176,  0,176,
								  0,176,176,
								176,176,176,
								 64, 64, 64,
								255,  0,  0,
								  0,255,  0,
								255,255,  0,
								  0,  0,255,
								255,  0,255,
								  0,255,255,
								255,255,255
						 } ;

int		ESC_color[8] = {	C_BLACK,C_RED,C_GREEN,C_YELLOW,
							C_BLUE,C_PURPLE,C_LIGHTBLUE,C_WHITE } ;

/********************  ﾃｷｽﾄﾗｲﾌﾞﾗﾘ & ｸﾞﾗﾌｨｯｸﾗｲﾌﾞﾗﾘの初期化  *******************/
int TEXT_init( char *egbwork,int size )
/*=============================================================================
**	ﾃｷｽﾄﾗｲﾌﾞﾗﾘとｸﾞﾗﾌｨｯｸﾗｲﾌﾞﾗﾘの初期化を行う.
**
**	< INPUT  > : EGB用作業域の先頭ｱﾄﾞﾚｽ
**			   : EGB用作業域のｻｲｽﾞ
**	< OUTPUT > : EGBﾗｲﾌﾞﾗﾘ用作業域
**	< RETURN > : ｴﾗｰ情報(EGB_init()に同じ)
=============================================================================*/
{
	char	para[132] ;
	int		c ;
	int		ret ;

	ret = GRP_init( egbwork,size ) ;
	DWORD( para+0 ) = 16 ;							/*  登録数	*/
	for ( c=0; c<16; c++ ) {
		DWORD( para+ 4+c*8 ) = c ;					/*  NUMBER	*/
		BYTE(  para+ 8+c*8 ) = TEXT_pal[c][0] ;		/*  BLUE	*/
		BYTE(  para+ 9+c*8 ) = TEXT_pal[c][1] ;		/*  RED		*/
		BYTE(  para+10+c*8 ) = TEXT_pal[c][2] ;		/*  GREEN	*/
		BYTE(  para+11+c*8 ) = 0 ;					/*  NULL	*/
	}
	EGB_palette( egbwork,0,para ) ;

	return( ret ) ;
}

/********************************  座標の変換  *******************************/
void TEXT_pos( int *x,int *y )
/*=============================================================================
**	書き込みたい座標値をVRAMに対する座標値に変換する。
**
**	< INPUT  > : x,y
**	< OUTPUT > : なし
**	< RETURN > : なし
=============================================================================*/
{
	short	px, py ;

	px = TEXTpos.dx + TEXTpos.vx ;
	if ( px >= MAXVCOLM ) px -= MAXVCOLM ;
	*x = px * XCDOT ;
	py = TEXTpos.dy + TEXTpos.vy ;
	if ( py >= MAXVLINE ) py -= MAXVLINE ;
	*y = py * YCDOT ;
}

/****************************  制御ｺｰﾄﾞの処理選択  ***************************/
void TEXT_control( int sw )
/*=============================================================================
**	制御ｺｰﾄﾞの処理を選択する.
**
**	< INPUT  > : sw  真ならば制御ｺｰﾄﾞ処理をする.
**				     偽ならば制御ｺｰﾄﾞをそのまま表示する.
**	< OUTPUT > : なし
**	< RETURN > : なし
=============================================================================*/
{
	TEXTctrl = sw ;
}

/*******************************  ﾃｷｽﾄ色の設定  ******************************/
void TEXT_color( int col )
/*=============================================================================
**	文字色の指定を行う.
**
**	< INPUT  > : 色識別番号(0〜15)
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	既に書かれている文字には影響しません.
=============================================================================*/
{
	TEXTfcolor = col ;
	VRAMfcolor = TEXTfcolor ;
	VRAM_color( VRAMfcolor,VRAMbcolor ) ;
}

/*****************************  ﾃｷｽﾄ背景色の設定  ****************************/
void TEXT_backcolor( int col )
/*=============================================================================
**	背景色の指定を行う.
**
**	< INPUT  > : 色識別番号(0〜15)
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	画面ｽｸﾛｰﾙ時に、最下段を塗り潰す時の色となります.
**	また、画面消去時には、全画面がこの色で塗り潰されます.
=============================================================================*/
{
	TEXTbcolor = col ;
	VRAMbcolor = TEXTbcolor ;
	VRAM_color( VRAMfcolor,VRAMbcolor ) ;
}

/******************************  ｸﾞﾗﾌｨｯｸｶｰｿﾙ表示  ****************************/
void _TEXT_cursor( int x,int y )
/*=============================================================================
**	ｸﾞﾗﾌｨｯｸｶｰｿﾙ(ｱﾝﾀﾞｰﾗｲﾝ)を描く.
**
**	< INPUT  > : x,y 描く座標
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	　この関数で 描画ﾓｰﾄﾞ は GRP_writeMode() で設定された値に、面塗りﾓｰﾄﾞは
**	GRP_paintMode() で設定された値に変更されます.
**	(EGB_writeMode()やEGB_paintMode()を使用している場合には、注意して下さい)
**	また、前景色についても同様の注意が必要です。
**
**	ｶｰｿﾙは、XOR で描きます. 
**	ｶｰｿﾙを描いたら、同じ座標で再度この関数をCALLして消去して下さい.
**
**	☆この関数を直接CALLしないようにして下さい.
**	  (TEXT_locate()及びTEXT_cursor()を使用して下さい)
=============================================================================*/
{
	struct {
		unsigned int	adr ;
		short	ds ;
		short	x, y ;
	} pcur ;

	if ( !Cursorflg ) return ;

	pcur.adr = (unsigned int)TEXTcurdata ;
	pcur.ds  = getds() ;
	pcur.x   = x ;
	pcur.y   = y - 1 ;							/*  ｶｰｿﾙは縦2ﾄﾞｯﾄ			*/
	EGB_paintMode( GRPwork,0x02 ) ;
	EGB_writeMode( GRPwork,XOR ) ;
	EGB_color( GRPwork,0,C_HWHITE ) ;

	EGB_graphicCursor( GRPwork,0,(char *)&pcur ) ;

	if ( GRPpmode != 0x02 ) EGB_paintMode( GRPwork,GRPpmode ) ;
	if ( GRPwmode != XOR )  EGB_writeMode( GRPwork,GRPwmode ) ;
	if ( GRPfcolor != C_HWHITE ) EGB_color( GRPwork,0,GRPfcolor ) ;
}

/******************************  ｸﾞﾗﾌｨｯｸｶｰｿﾙ制御  ****************************/
void TEXT_cursor( int sw )
/*=============================================================================
**	ｶｰｿﾙのON/OFFを行う.
**
**	< INPUT  > : sw  真値ならばｶｰｿﾙ表示あり，偽値ならばｶｰｿﾙ表示なし
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	☆ 注意 ☆
**	　この関数で 描画ﾓｰﾄﾞ は GRP_writeMode() で設定された値に、面塗りﾓｰﾄﾞは
**	GRP_paintMode() で設定された値に変更されます.
**	(EGB_writeMode()やEGB_paintMode()を使用している場合には、注意して下さい)
**	また、前景色についても同様の注意が必要です。
=============================================================================*/
{
	if ( sw ) {							/*  ｶｰｿﾙ表示する	*/
		if ( !Cursorflg ) {
			Cursorflg = TRUE ;
			_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;/*表示*/
		}
	} else {							/*  ｶｰｿﾙ表示しない	*/
		if ( Cursorflg ) {
			_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;/*消去*/
			Cursorflg = FALSE ;
		}
	}
}

/*****************************  ﾃｷｽﾄ表示位置設定  ****************************/
void TEXT_locate( int row,int column )
/*=============================================================================
**	文字の表示位置の設定を行う.
**
**	< INPUT  > : row     1 〜 30 (行)
**			   : column  1 〜 80 (桁)
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	☆ 注意 ☆
**	　TEXT_cursor()と同様の注意が必要です。
=============================================================================*/
{
	if ( 1 > column || column > MAXCOLM ) return ;
	if ( -1 > row || row > MAXVLINE ) return ;

	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;

	TEXTpos.dx = column - 1 ;
	TEXTpos.px = TEXTpos.dx + TEXTpos.vx ;
	if ( TEXTpos.px >= MAXVCOLM ) TEXTpos.px -= MAXVCOLM ;
	TEXTpos.dy = row - 1 ;
	if ( TEXTpos.dy < 0 ) TEXTpos.dy += MAXVLINE ;
	if ( TEXTpos.dy >= MAXVLINE ) TEXTpos.dy -= MAXVLINE ;
	TEXTpos.py = TEXTpos.dy + TEXTpos.vy ;
	if ( TEXTpos.py >= MAXVLINE ) TEXTpos.py -= MAXVLINE ;

	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;
}

/*********************************  画面消去  ********************************/
void TEXT_cls( void )
/*=============================================================================
**	全画面消去を行う.
**
**	< INPUT  > : なし
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	TEXT_backcolor() で指定されている背景色で画面を塗り潰します.
**	文字表示位置が画面左上になります.
**
**	☆ 注意 ☆
**	　この関数で 描画ﾓｰﾄﾞ は GRP_writeMode() で設定された値に、面塗りﾓｰﾄﾞは
**	GRP_paintMode() で設定された値に変更されます.
**	(EGB_writeMode()やEGB_paintMode()を使用している場合には、注意して下さい)
**	また、前景色と背景色についても同様の注意が必要です。
=============================================================================*/
{
	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;

	EGB_color( GRPwork,1,TEXTbcolor ) ;
	EGB_clearScreen( GRPwork ) ;
	if ( GRPbcolor != TEXTbcolor ) EGB_color( GRPwork,1,GRPbcolor ) ;

	TEXTpos.vx = TEXTpos.vy = 0 ;
	TEXTpos.dx = TEXTpos.dy = 0 ;
	TEXTpos.px = TEXTpos.py = 0 ;
	EGB_displayStart( GRPwork,1,TEXTpos.vx*XCDOT,TEXTpos.vy*YCDOT ) ;

	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;
}

/********************************  ﾃｷｽﾄ表示  *********************************/
char _TEXT_gets( char *str )
/*=============================================================================
**	文字列内の制御ｺｰﾄﾞを展開し，一行以内の文字数にする.
**
**	< INPUT  > : str  文字列先頭ｱﾄﾞﾚｽ
**	< OUTPUT > : なし
**	< RETURN > : 文字列の終了のｺｰﾄﾞを返す. ('\n'または'\0')
**
**	'\n'かﾇﾙ文字に出会うまで, または一行内の最大文字数以内の文字列とする.
**	展開後の文字列の最後には,'\n'が含まれません.
=============================================================================*/
{
	char	buf[MAXCOLM+1] ;
	int		c, p, cc ;
	char	ret ;

	for ( p=0,c=0; c<MAXCOLM; c++ ) {
		if ( str[c] < ' ' ) {					/*  制御ｺｰﾄﾞ				*/
			if ( str[c] == '\0' ) {
				buf[p] = ret = str[c] ;
				break ;
			} else if ( str[c] == KCODE_ESC ) {		/*  esc			*/
				buf[p++] = str[c] ;
			} else if ( str[c] == '\t' ) {			/*  tab			*/
				for ( cc=0; cc<MAXTABS; cc++ ) {
					buf[p++] = ' ' ;
					if ( !(p % TEXTtabs) ) break ;
				}
			} else if ( str[c] == '\n' ) {			/*  cr+lf		*/
				buf[p] = '\0' ;
				ret = '\n' ;
				break ;
			} else {
				buf[p++] = str[c] ;
			}
		} else {								/*  制御ｺｰﾄﾞ以外			*/
			buf[p++] = str[c] ;
		}
		if ( p > MAXCOLM ) {
			buf[MAXCOLM] = ret = '\0' ;
			break ;
		}
	}
	strcpy( str,buf ) ;

	return( ret ) ;
}

/********************************  ﾃｷｽﾄ表示  *********************************/
void TEXT_puts( char *str )
/*=============================================================================
**	一行の文字列表示を行う.
**
**	< INPUT  > : str  文字列先頭ｱﾄﾞﾚｽ
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	'\n'かﾇﾙ文字に出会うまで, または一行内の最大文字数以内の文字列を表示する.
**	この関数では, 改行は行わない.
=============================================================================*/
{
	short	px, py ;
	char	buf[MAXCOLM+1] ;
	int		fcol ;
	char	endc ;

	/*  ｶｰｿﾙ制御	*/
	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;

	strcpy( buf,str ) ;
	endc = _TEXT_gets( buf ) ;
	px = TEXTpos.px * XCDOT ;						/* X Point	*/
	py = TEXTpos.py * YCDOT + YCDOT - 1 ;			/* Y Point	*/
	VRAM_putstr( px,py,buf ) ;					/*  文字表示				*/
	px = strlen( buf ) ;
	if ( endc == '\n' && TEXTcrflg ) {
		fcol = TEXTfcolor ;
		if ( fcol != C_YELLOW ) TEXT_color( C_YELLOW ) ;
		TEXTpos.px += px ;
		TEXT_putc( 0x1F ) ;
		TEXTpos.px ++ ;
		if ( fcol != C_YELLOW ) TEXT_color( fcol ) ;
		px ++ ;
	}

	/*  矩形塗り潰し	*/
	EGB_writeMode( GRPwork,PSET ) ;
	EGB_paintMode( GRPwork,0x20 ) ;
	EGB_color( GRPwork,2,TEXTbcolor ) ;			/*  背景色で塗り潰すため	*/
	GRP_box( px*XCDOT,TEXTpos.py*YCDOT,1023,py ) ;
	if ( GRPpcolor != TEXTbcolor ) EGB_color( GRPwork,2,GRPpcolor ) ;

	TEXTpos.dx += px ;
	TEXTpos.px += px ;
	if ( TEXTpos.px >= MAXVCOLM ) TEXTpos.px -= MAXVCOLM ;
	/*  ｶｰｿﾙ制御	*/
	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;
}

/**************************  全画面スクロール  *******************************/
void TEXT_scroll( char *str )
/*=============================================================================
**	全画面1行ｽｸﾛｰﾙを行う.
**
**	< INPUT  > : 最下段に表示する文字列ﾎﾟｲﾝﾀ
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	strにNULLが指定された場合には,最下段はTEXT_backcolor()で指定された色で
**	塗り潰されます.
**
**	☆ 注意 ☆
**	　この関数で 描画ﾓｰﾄﾞ は GRP_writeMode() で設定された値に、面塗りﾓｰﾄﾞは
**	GRP_paintMode() で設定された値に変更されます.
**	(EGB_writeMode()やEGB_paintMode()を使用している場合には、注意して下さい)
**	また、前景色と面塗り色についても同様の注意が必要です。
=============================================================================*/
{
	short	ex, ey, dy ;
	char	buf[MAXCOLM+1] ;
	int		fcol ;
	char	endc ;

	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;
/*
**	UPｽｸﾛｰﾙした分だけ下の行を塗り潰す
*/
	EGB_writeMode( GRPwork,PSET ) ;
	EGB_paintMode( GRPwork,0x20 ) ;
	EGB_color( GRPwork,2,TEXTbcolor ) ;			/*  背景色で塗り潰すため	*/
	ey = TEXTpos.vy - ( MAXVLINE - MAXLINE ) ;
	if ( ey < 0 ) ey += MAXVLINE ;
	ex = 0 ;
	strcpy( buf,str ) ;
	endc = _TEXT_gets( buf ) ;
	if ( str != NULL ) {
		if ( TEXTctrl ) {
			dy = TEXTpos.dy ;
			TEXT_locate( MAXLINE+1,1 ) ;
			TEXT_printf( "%s",buf ) ;
			ex = strlen( buf ) ;
			if ( endc == '\n' && TEXTcrflg ) {
				fcol = TEXTfcolor ;
				if ( fcol != C_YELLOW ) TEXT_color( C_YELLOW ) ;
				_TEXT_putc( 0x1F ) ;
				ex ++ ;
				if ( fcol != C_YELLOW ) TEXT_color( fcol ) ;
			}
			TEXTpos.dy = dy ;
		} else {
			VRAM_putstr( ex,ey*YCDOT+YCDOT-1,buf ) ;
			ex = strlen( buf ) ;
		}
	}
	GRP_box( ex*XCDOT,ey*YCDOT,1023,ey*YCDOT+YCDOT-1 ) ;	/*  矩形塗り潰し*/
	if ( GRPpcolor != TEXTbcolor ) EGB_color( GRPwork,2,GRPpcolor ) ;
/*
**	仮想画面位置設定
*/
	TEXTpos.vy ++ ;
	if ( TEXTpos.vy >= MAXVLINE ) TEXTpos.vy = 0 ;
	EGB_displayStart( GRPwork,1,TEXTpos.vx*XCDOT,TEXTpos.vy*YCDOT ) ;
/*
**	ﾎﾟｼﾞｼｮﾝ再設定
*/
	TEXTpos.py = TEXTpos.dy + TEXTpos.vy ;
	if ( TEXTpos.py >= MAXVLINE ) TEXTpos.py -= MAXVLINE ;

	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;
}

/*************************  全画面逆スクロール  ******************************/
void TEXT_revscroll( char *str )
/*=============================================================================
**	全画面1行逆ｽｸﾛｰﾙを行う.
**
**	< INPUT  > : 最上段に表示する文字列ﾎﾟｲﾝﾀ
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	strにNULLが指定された場合には,最上段はTEXT_backcolor()で指定された色で
**	塗り潰されます.
**
**	☆ 注意 ☆
**	　TEXT_scroll()と同様の注意が必要です。
=============================================================================*/
{
	short	ex, ey, dy ;
	char	buf[MAXCOLM+1] ;
	int		fcol ;
	char	endc ;

	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;

/*
**	DOWNｽｸﾛｰﾙした分だけ下の行を塗り潰す
*/
	EGB_writeMode( GRPwork,PSET ) ;
	EGB_paintMode( GRPwork,0x20 ) ;
	EGB_color( GRPwork,2,TEXTbcolor ) ;			/*  背景色で塗り潰すため	*/
	ey = TEXTpos.vy - 1 ;
	if ( ey < 0 ) ey += MAXVLINE ;
	ex = 0 ;
	strcpy( buf,str ) ;
	endc = _TEXT_gets( buf ) ;
	if ( str != NULL ) {
		if ( TEXTctrl ) {
			dy = TEXTpos.dy ;
			TEXT_locate( 0,1 ) ;
			TEXT_printf( "%s",buf ) ;
			ex = strlen( buf ) ;
			if ( endc == '\n' && TEXTcrflg ) {
				fcol = TEXTfcolor ;
				if ( fcol != C_YELLOW ) TEXT_color( C_YELLOW ) ;
				_TEXT_putc( 0x1F ) ;
				ex ++ ;
				if ( fcol != C_YELLOW ) TEXT_color( fcol ) ;
			}
			TEXTpos.dy = dy ;
		} else {
			VRAM_putstr( ex,ey*YCDOT+YCDOT-1,buf ) ;
			ex = strlen( buf ) ;
		}
	}
	GRP_box( ex*XCDOT,ey*YCDOT,1023,ey*YCDOT+YCDOT-1 ) ;	/*  矩形塗り潰し*/
	if ( GRPpcolor != TEXTbcolor ) EGB_color( GRPwork,2,GRPpcolor ) ;
/*
**	仮想画面位置設定
*/
	TEXTpos.vy -- ;
	if ( TEXTpos.vy < 0 ) TEXTpos.vy = MAXVLINE - 1 ;
	EGB_displayStart( GRPwork,1,TEXTpos.vx*XCDOT,TEXTpos.vy*YCDOT ) ;
/*
**	ﾎﾟｼﾞｼｮﾝ再設定
*/
	TEXTpos.py = TEXTpos.dy + TEXTpos.vy ;
	if ( TEXTpos.py >= MAXVLINE ) TEXTpos.py -= MAXVLINE ;

	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;
}

/********************************  改行  *************************************/
void _TEXT_cr( int mark )
/*=============================================================================
**	改行を行う.
**
**	< INPUT  > : 改行ﾏｰｸ表示制御をするか？ ( 真値:する, 偽値:しない )
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	☆ 注意 ☆
**	　TEXT_scroll()と同様の注意が必要です。
=============================================================================*/
{
	int		fcol ;
	static char	crflg = FALSE ;

	if ( crflg ) return ;						/*  再帰呼出し不可			*/

	if ( TEXTcrflg && mark ) {
		if ( TEXTpos.dx >= MAXCOLM ) {
			if ( TEXTpos.dy == MAXLINE-1 ) {
				TEXT_scroll( NULL ) ;
			} else {
				TEXT_locate( TEXTpos.dy+2,1 ) ;
			}
		}
		fcol = TEXTfcolor ;
		if ( fcol != C_YELLOW ) TEXT_color( C_YELLOW ) ;
		crflg = TRUE ;
		TEXT_putc( 0x1F ) ;
		crflg = FALSE ;
		if ( fcol != C_YELLOW ) TEXT_color( fcol ) ;
	}

	if ( TEXTpos.dy == MAXLINE-1 ) {
		TEXT_scroll( NULL ) ;
	}

	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;

	TEXTpos.dy ++ ;
	if ( TEXTpos.dy >= MAXLINE ) TEXTpos.dy = MAXLINE -1 ;
	TEXTpos.py = TEXTpos.dy + TEXTpos.vy ;
	if ( TEXTpos.py >= MAXVLINE ) TEXTpos.py -= MAXVLINE ;

	TEXTpos.dx = 0 ;
	TEXTpos.px = TEXTpos.dx + TEXTpos.vx ;
	if ( TEXTpos.px >= MAXVCOLM ) TEXTpos.px -= MAXVCOLM ;

	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;
}

/********************************  改行  *************************************/
void TEXT_cr( void )
/*=============================================================================
**	改行を行う.
**
**	< INPUT  > : なし
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	☆ 注意 ☆
**	　TEXT_scroll()と同様の注意が必要です。
=============================================================================*/
{
	_TEXT_cr( TEXTcrflg ) ;
}

/********************************  後退  *************************************/
void TEXT_bs( void )
/*=============================================================================
**	後退を行う.
**
**	< INPUT  > : なし
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	☆ 注意 ☆
**	　TEXT_putch()と同様の注意が必要です。
=============================================================================*/
{
	if ( TEXTpos.dx == 0 ) {
		if ( TEXTpos.dy > 0 ) {
			TEXT_locate( TEXTpos.dy,MAXCOLM ) ;
			TEXT_putch( ' ' ) ;
			TEXT_locate( TEXTpos.dy,MAXCOLM ) ;
		}
	} else {
		TEXT_locate( TEXTpos.dy+1,TEXTpos.dx ) ;
		TEXT_putch( ' ' ) ;
		TEXT_locate( TEXTpos.dy+1,TEXTpos.dx ) ;
	}
}

/******************************  ｶｰｿﾙ移動  ***********************************/
void TEXT_movecursor( char cursor )
/*=============================================================================
**	ｶｰｿﾙを移動する.
**
**	< INPUT  > : ｶｰｿﾙの向きを表すｷｰｺｰﾄﾞ
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	☆ 注意 ☆
**	　TEXT_cursor()と同様の注意が必要です。
=============================================================================*/
{
	switch ( cursor ) {
	case KCODE_UP :								/*  ↑			*/
		if ( TEXTpos.dy == 0 ) break ;
		TEXT_locate( TEXTpos.dy,TEXTpos.dx+1 ) ;
		break ;
	case KCODE_LEFT :							/*  ←			*/
		if ( TEXTpos.dx == 0 ) {
			if ( TEXTpos.dy > 0 ) {
				TEXT_locate( TEXTpos.dy,MAXCOLM ) ;
			}
		} else {
			TEXT_locate( TEXTpos.dy+1,TEXTpos.dx ) ;
		}
		break ;
	case KCODE_DOWN :							/*  ↓			*/
		if ( TEXTpos.dy == MAXLINE-1 ) break ;
		TEXT_locate( TEXTpos.dy+2,TEXTpos.dx+1 ) ;
		break ;
	case KCODE_RIGHT :							/*  →			*/
		if ( TEXTpos.dx == MAXCOLM-1 ) {
			if ( TEXTpos.dy < MAXLINE-1 ) {
				TEXT_locate( TEXTpos.dy+2,1 ) ;
			}
		} else {
			TEXT_locate( TEXTpos.dy+1,TEXTpos.dx+2 ) ;
		}
	}
}

/********************************  1文字表示  ********************************/
void _TEXT_putc( char c )
/*=============================================================================
**	一文字(1ﾊﾞｲﾄ)表示する. (制御ｺｰﾄﾞもそのまま表示する)
**
**	< INPUT  > : c  文字ｺｰﾄﾞ
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	ｴﾗｰﾁｪｯｸをしていないので,座標値の指定には気をつけること.
=============================================================================*/
{
	int		px, py, n ;
	static char	buf[3] = { 0,0,0 } ;
	static char	kanji = FALSE ;

	if ( iskanji(c) && !kanji ) {				/*  漢字					*/
		buf[0] = c ;
		kanji = TRUE ;
		return ;
	}

	if ( TEXTfcolor != VRAMfcolor || TEXTbcolor != VRAMbcolor )
		VRAM_color( TEXTfcolor,TEXTbcolor ) ;

	if ( kanji ) {
		n = 2 ;
		buf[1] = c ;
		buf[2] = '\0' ;
		kanji = FALSE ;
	} else {
		n = 1 ;
		buf[0] = c ;
		buf[1] = '\0' ;
	}

	px = TEXTpos.px * XCDOT ;						/* X Point	*/
	py = TEXTpos.py * YCDOT + YCDOT - 1 ;			/* Y Point	*/

	VRAM_putstr( px,py,buf ) ;					/*  文字表示				*/

	if ( TEXTfcolor != VRAMfcolor || TEXTbcolor != VRAMbcolor )
		VRAM_color( VRAMfcolor,VRAMbcolor ) ;

	TEXTpos.dx += n ;
	TEXTpos.px += n ;
}

/********************************  1文字表示  ********************************/
void TEXT_putc( char c )
/*=============================================================================
**	一文字(1ﾊﾞｲﾄ)表示する. (制御ｺｰﾄﾞもそのまま表示する)
**
**	< INPUT  > : c  文字ｺｰﾄﾞ
**	< OUTPUT > : なし
**	< RETURN > : なし
=============================================================================*/
{
	int		px, py, n ;
	static char	buf[3] = { 0,0,0 } ;
	static char	kanji = FALSE ;

	if ( iskanji(c) && !kanji ) {				/*  漢字					*/
		buf[0] = c ;
		kanji = TRUE ;
		return ;
	}

	/*  ｶｰｿﾙ制御	*/
	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;
	if ( TEXTfcolor != VRAMfcolor || TEXTbcolor != VRAMbcolor )
		VRAM_color( TEXTfcolor,TEXTbcolor ) ;

	if ( kanji ) {
		n = 2 ;
		buf[1] = c ;
		buf[2] = '\0' ;
		kanji = FALSE ;
	} else {
		n = 1 ;
		buf[0] = c ;
		buf[1] = '\0' ;
	}
	if ( TEXTpos.dx+n > MAXCOLM ) {
		_TEXT_cr( FALSE ) ;						/*  改行					*/
	}

	px = TEXTpos.px * XCDOT ;						/* X Point	*/
	py = TEXTpos.py * YCDOT + YCDOT - 1 ;			/* Y Point	*/

	VRAM_putstr( px,py,buf ) ;					/*  文字表示				*/

	if ( TEXTfcolor != VRAMfcolor || TEXTbcolor != VRAMbcolor )
		VRAM_color( VRAMfcolor,VRAMbcolor ) ;

	TEXTpos.dx += n ;
	TEXTpos.px += n ;
	if ( TEXTpos.px >= MAXVCOLM ) TEXTpos.px -= MAXVCOLM ;
	/*  ｶｰｿﾙ制御	*/
	_TEXT_cursor( TEXTpos.px*XCDOT,TEXTpos.py*YCDOT+YCDOT-1 ) ;
	if ( TEXTpos.dx >= MAXCOLM ) _TEXT_cr( FALSE ) ;
}

/**********************************  BEEP  ***********************************/
void _TEXT_beep( int time,int count )
/*=============================================================================
**	指定された時間･周波数でBEEPを鳴らす.
**
**	< INPUT  > : time  - 時間   : 10ms 単位
**			   : count - ｶｳﾝﾀ数 : 基本周波数(19200Hz) / 周波数(Hz)
**	< OUTPUT > : なし
**	< RETURN > : なし
=============================================================================*/
{
	union	REGS	regs ;

	regs.h.ah = 0x03 ;
	regs.x.bx = time ;
	regs.x.dx = count ;
	int86( INT_BEEP,&regs,&regs ) ;
}

/**********************************  BEEP  ***********************************/
void TEXT_beep( void )
/*=============================================================================
**	BEEPを鳴らす.
**
**	< INPUT  > : なし
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**  time  - 時間   : 10ms 単位
**  count - ｶｳﾝﾀ数 : 基本周波数(19200Hz) / 周波数(Hz)
=============================================================================*/
{
	_TEXT_beep( BEEP_TIME,BEEP_COUNT ) ;
}

/********************************  行内消去  *********************************/
void TEXT_linecls( int mode )
/*=============================================================================
**	行内の文字を消去する.
**
**	< INPUT  > : 消去するﾓｰﾄﾞ(0〜2)
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	消去ﾓｰﾄﾞが 0〜2 以外の場合には何もしない.
=============================================================================*/
{
	int		cx, c ;

	cx = TEXTpos.dx ;
	switch ( mode ) {
	case 0 :							/*  ｶｰｿﾙ位置から行の終わりまで消去	*/
		TEXT_puts( " " ) ;
		break ;
	case 1 :							/*  行頭からｶｰｿﾙ位置まで消去		*/
		TEXT_locate( TEXTpos.dy+1,1 ) ;
		for ( c=0; c<cx; c++ ) TEXT_putc( ' ' ) ;
		break ;
	case 2 :							/*  ｶｰｿﾙ位置の行の消去				*/
		TEXT_locate( TEXTpos.dy+1,1 ) ;
		TEXT_puts( " " ) ;
	}
}

/********************************  ｱﾄﾘﾋﾞｭｰﾄ  *********************************/
void TEXT_escattr( int mode )
/*=============================================================================
**	ｴｽｹｰﾌﾟｼｰｹﾝｽによるｱﾄﾘﾋﾞｭｰﾄ設定を行う.
**
**	< INPUT  > : ﾓｰﾄﾞ
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	処理ﾓｰﾄﾞ以外は何もしない.
**	背景色は,画面全体でなく,文字の背景色とする.
=============================================================================*/
{
	int		col ;

	switch ( mode ) {
	case 0 :									/*  全てのｱﾄﾘﾋﾞｭｰﾄ解除		*/
		if ( TEXTfcolor != C_WHITE ) {
			TEXTfcolor = C_WHITE ;
			TEXT_color( TEXTfcolor ) ;
		}
		if ( TEXTbcolor != C_BLACK ) {
			TEXTbcolor = C_BLACK ;
			TEXT_backcolor( TEXTbcolor ) ;
		}
		break ;
	case 1 :									/*  高輝度					*/
		if ( TEXTfcolor < 8 ) {
			TEXT_color( TEXTfcolor+8 ) ;
		}
		break ;
	case 7 :									/*  ﾘﾊﾞｰｽ					*/
		col = TEXTfcolor ;
		TEXT_color( TEXTbcolor ) ;
		TEXT_backcolor( col ) ;
		break ;
	default :
		if ( mode >= 30 && mode <= 37 ) {			/*  文字色	*/
			col = ESC_color[mode-30] ;
			if ( TEXTfcolor > 7 ) col += 8 ;
			if ( TEXTfcolor != col ) {
				TEXT_color( col ) ;
			}
		} else if ( mode >= 40 && mode <= 47 ) {	/*  背景色	*/
			col = ESC_color[mode-40] ;
			if ( TEXTbcolor > 7 ) col += 8 ;
			if ( TEXTbcolor != col ) {
				TEXT_backcolor( col ) ;
			}
		}
	}
}

/********************************  ﾃｷｽﾄ表示  *********************************/
void _TEXT_putch( char c )
/*=============================================================================
**	一文字(ANK or 漢字)表示する. (TEXTctrlﾌﾗｸﾞによって制御ｺｰﾄﾞの処理を行う)
**	ESCｼｰｹﾝｽには対応しない.
**
**	< INPUT  > : str  文字列先頭ｱﾄﾞﾚｽ
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	TEXTctrlﾌﾗｸﾞは,TEXT_control()で指定する.
**	TEXT_putch()は,ESCｼｰｹﾝｽに対応.
=============================================================================*/
{
	int		lc ;

	if ( c < ' ' && TEXTctrl ) {				/*  制御ｺｰﾄﾞ				*/
		switch ( c ) {
		case '\n' :								/*  (cr+)lf		*/
			TEXT_cr() ;
			break ;
		case KCODE_CR :							/*  cr			*/
			TEXT_locate( TEXTpos.dy+1,1 ) ;
			break ;
#if 0
		/*  '\n'として扱う	*/
		case KCODE_LF :							/*  lf			*/
			if ( TEXTpos.dx >= MAXCOLM ) {
				if ( TEXTpos.dy == MAXLINE-1 ) {
					TEXT_scroll( NULL ) ;
				} else {
					TEXT_locate( TEXTpos.dy+2,TEXTpos.dx+1 ) ;
				}
			}
			break ;
#endif
		case KCODE_BS :							/*  back space	*/
			TEXT_bs() ;
			break ;
		case KCODE_UP :							/*  ↑			*/
		case KCODE_LEFT :						/*  ←			*/
		case KCODE_DOWN :						/*  ↓			*/
		case KCODE_RIGHT :						/*  →			*/
			TEXT_movecursor( c ) ;
			break ;
		case '\t' :								/*  tab			*/
			for ( lc=0; lc<MAXTABS; lc++ ) {
				TEXT_putc( ' ' ) ;
				if ( !(TEXTpos.dx % TEXTtabs) ) break ;
			}
			break ;
		case KCODE_BEEP :						/*  beep		*/
			TEXT_beep() ;
			break ;
		case KCODE_CLS :						/*  cls(^L)		*/
		case 0x16 :								/*  cls(^V)		*/
			TEXT_cls() ;
			break ;
		case KCODE_HOME :						/*  home		*/
			TEXT_locate( 1,1 ) ;
			break ;
		default :
			TEXT_putc( c ) ;
		}
	} else {									/*  制御ｺｰﾄﾞ以外			*/
		if ( !TEXTctrl ) {
			if ( c == '\t' ) {
				for ( lc=0; lc<MAXTABS; lc++ ) {
					TEXT_putc( ' ' ) ;
					if ( !(TEXTpos.dx % TEXTtabs) ) break ;
				}
			} else if ( c == '\n' ) {
				TEXT_cr() ;
			} else {
				TEXT_putc( c ) ;
			}
		} else {
			TEXT_putc( c ) ;
		}
	}
}

/********************************  ESCｼｰｹﾝｽ  *********************************/
int TEXT_esc( char c )
/*=============================================================================
**	ESCｼｰｹﾝｽ処理を行う.
**
**	< INPUT  > : 文字ｺｰﾄﾞ
**	< OUTPUT > : なし
**	< RETURN > : ESCｼｰｹﾝｽ中ならば 1 , ESCｼｰｹﾝｽ終了ならば 0 を返す.
=============================================================================*/
{
	static char	buf[128] ;
	static int	escon = FALSE ;
	static int	p = 0 ;
	int		lc ;								/*  ﾙｰﾌﾟｶｳﾝﾀ				*/
	int		s1, s2 ;							/*  ｾﾐｺﾛﾝの位置				*/
	char	tmp[11] ;							/*  atoi()用				*/
	int		cx, cy ;							/*  ｶｰｿﾙ位置保持用			*/

	if ( c == KCODE_ESC ) {
		if ( escon ) TEXT_putc( c ) ;
		escon = TRUE ;
		p = 0 ;
		buf[p++] = c ;
	} else if ( escon ) {
		if ( p == 1 && c != '[' ) {
			TEXT_putc( KCODE_ESC ) ;
			TEXT_putc( c ) ;
			escon = FALSE ;
		} else {
			switch ( c ) {
			case 'H' :							/*  locate		*/
			case 'f' :							/*  locate		*/
				if ( p == 2 ) buf[p++] = '1' ;	/*  ﾃﾞﾌｫﾙﾄ		*/
				buf[p] = '\0' ;
				s1 = s2 = 2 ;
				for ( lc=s2+1; lc<p; lc++ ) {
					if ( buf[lc] == ';' ) {
						s2 = lc ;
						buf[s2++] = '\0' ;		/*  ｾﾐｺﾛﾝの位置にﾇﾙをｾｯﾄ	*/
						if ( s2 == p ) {
							buf[p++] = '1' ;
							buf[p] = '\0' ;
						}
						break ;
					}
				}
				strcpy( tmp,buf+s1 ) ;
				cx = atoi( tmp ) ;
				strcpy( tmp,buf+s2 ) ;
				cy = atoi( tmp ) ;
				TEXT_locate( cy,cx ) ;
				p = 0 ;
				escon = FALSE ;
				break ;
			case 'm' :							/*  ｱﾄﾘﾋﾞｭｰﾄ	*/
				if ( p == 2 ) buf[p++] = '0' ;	/*  ﾃﾞﾌｫﾙﾄ		*/
				buf[p] = '\0' ;
				s1 = s2 = 2 ;
				for ( lc=s2+1; lc<p; lc++ ) {
					if ( buf[lc] == ';' ) {
						s2 = lc ;
						buf[s2++] = '\0' ;		/*  ｾﾐｺﾛﾝの位置にﾇﾙをｾｯﾄ	*/
						if ( s2 == p ) {
							buf[p++] = '0' ;
							buf[p] = '\0' ;
							strcpy( tmp,buf+s1 ) ;
							TEXT_escattr( atoi( tmp ) ) ;
							break ;
						}
						strcpy( tmp,buf+s1 ) ;
						TEXT_escattr( atoi( tmp ) ) ;
						s1 = s2 ;
					}
				}
				if ( lc >= p && s1 == s2 ) {	/*  ｾﾐｺﾛﾝがなかった時		*/
					strcpy( tmp,buf+s1 ) ;
					TEXT_escattr( atoi( tmp ) ) ;
				}
				p = 0 ;
				escon = FALSE ;
				break ;
			case 'J' :							/*  cls			*/
				if ( p == 2 ) buf[p++] = '0' ;	/*  ﾃﾞﾌｫﾙﾄ		*/
				buf[p] = '\0' ;
				strcpy( tmp,buf+2 ) ;
				s1 = atoi( tmp ) ;
				cx = TEXTpos.dx ;
				cy = TEXTpos.dy ;
				switch ( s1 ) {
				case 0 :				/*  ｶｰｿﾙ位置から画面の最後まで消去	*/
					TEXT_puts( " " ) ;
					for ( lc=TEXTpos.dy; lc<MAXLINE; lc++ ) {
						_TEXT_cr( FALSE ) ;
						TEXT_puts( " " ) ;
					}
					TEXT_locate( cy+1,cx+1 ) ;
					break ;
				case 1 :				/*  画面の先頭からｶｰｿﾙ位置まで消去	*/
					TEXT_locate( 1,1 ) ;
					TEXT_puts( " " ) ;
					for ( lc=1; lc<cy; lc++ ) {
						_TEXT_cr( FALSE ) ;
						TEXT_puts( " " ) ;
					}
					TEXT_locate( cy+1,1 ) ;
					for ( lc=0; lc<cx; lc++ ) TEXT_putc( ' ' ) ;
					TEXT_locate( cy+1,cx+1 ) ;
					break ;
				case 2 :				/*  画面全体を消去					*/
					TEXT_cls() ;
				}
				p = 0 ;
				escon = FALSE ;
				break ;
			case 'K' :							/*  erace row	*/
				if ( p == 2 ) buf[p++] = '0' ;	/*  ﾃﾞﾌｫﾙﾄ		*/
				buf[p] = '\0' ;
				strcpy( tmp,buf+2 ) ;
				lc = atoi( tmp ) ;
				cx = TEXTpos.dx ;
				cy = TEXTpos.dy ;
				TEXT_linecls( lc ) ;
				TEXT_locate( cy+1,cx+1 ) ;
				p = 0 ;
				escon = FALSE ;
				break ;
			case 'v' :							/*  ｶｰｿﾙ on/off	*/
				if ( p == 2 ) buf[p++] = '0' ;	/*  ﾃﾞﾌｫﾙﾄ		*/
				buf[p] = '\0' ;
				strcpy( tmp,buf+2 ) ;
				lc = atoi( tmp ) ;
				switch ( lc ) {
				case 0 :						/*  ｶｰｿﾙ表示	*/
					TEXT_cursor( TRUE ) ;
					break ;
				case 1 :						/*  ｶｰｿﾙ非表示	*/
					TEXT_cursor( FALSE ) ;
				}
				p = 0 ;
				escon = FALSE ;
				break ;
			case 'A' :							/*  上へ移動(行のみ)	*/
			case 'B' :							/*  下へ移動(行のみ)	*/
			case 'C' :							/*  右へ移動(桁のみ)	*/
			case 'D' :							/*  左へ移動(桁のみ)	*/
				if ( p == 2 ) buf[p++] = '1' ;	/*  ﾃﾞﾌｫﾙﾄ		*/
				buf[p] = '\0' ;
				strcpy( tmp,buf+2 ) ;
				lc = atoi( tmp ) ;
				cx = TEXTpos.dx ;
				cy = TEXTpos.dy ;
				if ( c == 'A' ) {
					cy -= lc ;
					if ( cy < 0 ) cy = 0 ;
				} else if ( c == 'B' ) {
					cy += lc ;
					if ( cy >= MAXLINE ) cy = MAXLINE - 1 ;
				} else if ( c == 'C' ) {
					cx += lc ;
					if ( cx >= MAXCOLM ) cx = MAXCOLM - 1 ;
				} else if ( c == 'D' ) {
					cx -= lc ;
					if ( cx < 0 ) cx = 0 ;
				}
				TEXT_locate( cy+1,cx+1 ) ;
				p = 0 ;
				escon = FALSE ;
				break ;
			case 'n' :							/*  ｷｰﾊﾞｯﾌｧ内にCPR挿入	*/
			case 'R' :							/*  ｶｰｿﾙ位置の通知		*/
			case 's' :							/*  現在のｶｰｿﾙ位置を保持*/
			case 'u' :							/*  SCPｼｰｹﾝｽのｶｰｿﾙ位置に移動*/
			case 'h' :							/*  画面表示ﾓｰﾄﾞの設定	*/
			case 'I' :							/*  画面表示ﾓｰﾄﾞの設定	*/
			case 'p' :							/*  画面表示ﾓｰﾄﾞの設定	*/
			default :
				if ( ( '0' > c || c > '9' ) && c != '[' && c != ';' &&
						c != '=' && c != '?' ) {
					for ( lc=0; lc<p; lc++ ) _TEXT_putch( buf[lc] ) ;
					escon = FALSE ;
					p = 0 ;
				} else {
					buf[p++] = c ;
				}
			}
		}
	} else {
		TEXT_putc( c ) ;
	}
	if ( p == 128 ) {
		for ( lc=0; lc<p; lc++ ) _TEXT_putch( buf[lc] ) ;
		escon = FALSE ;
		p = 0 ;
	}

	return( escon ) ;
}

/********************************  ﾃｷｽﾄ表示  *********************************/
void TEXT_putch( char c )
/*=============================================================================
**	一文字(ANK or 漢字)表示する. (TEXTctrlﾌﾗｸﾞによって制御ｺｰﾄﾞの処理を行う)
**
**	< INPUT  > : str  文字列先頭ｱﾄﾞﾚｽ
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	TEXTctrlﾌﾗｸﾞは,TEXT_control()で指定する.
=============================================================================*/
{
	static int	escon = FALSE ;

	if ( escon || c == KCODE_ESC ) {
		escon = TEXT_esc( c ) ;
	} else {
		_TEXT_putch( c ) ;
	}
}

/********************************  ﾃｷｽﾄ表示  *********************************/
void TEXT_putstr( char *str )
/*=============================================================================
**	文字列表示を行う.
**
**	< INPUT  > : str  文字列先頭ｱﾄﾞﾚｽ
**	< OUTPUT > : なし
**	< RETURN > : なし
**
**	☆ 注意 ☆
**	　TEXT_putch()と同様の注意が必要です。
=============================================================================*/
{
	int		sl ;
	int		c ;

	sl = strlen( str ) ;
	for ( c=0; c<sl; c++ ) {
		if ( *(str+c) == '\0' ) break ;
		if ( iskanji(*(str+c)) ) {					/*  漢字				*/
			if ( TEXTpos.dx+2 > MAXCOLM ) {
				_TEXT_cr( FALSE ) ;					/*  改行				*/
			}
			TEXT_putch( *(str+c) ) ;
			c ++ ;
			TEXT_putch( *(str+c) ) ;
		} else {									/*  漢字以外			*/
			TEXT_putch( *(str+c) ) ;
		}
	}
}

/*****************************  書式付ﾃｷｽﾄ表示  ******************************/
int TEXT_printf( char *str,... )
/*=============================================================================
**	printf()のように文字列の表示を行う.
**
**	< INPUT  > : str  文字列
**			   : ...  文字列内の書式制御文字列に対する引数
**	< OUTPUT > : なし
**	< RETURN > : 表示した文字列の長さ(ﾊﾞｲﾄ)
**
**	☆ 注意 ☆
**	　文字列の長さは、127文字以内です。
=============================================================================*/
{
	char	buf[128] ;
	va_list	argptr ;
	int		ret ;

	va_start( argptr,str ) ;
	ret = vsprintf( buf,str,argptr ) ;
	TEXT_putstr( buf ) ;
	va_end( argptr ) ;

	return( ret ) ;
}

