/*******************************************************************************/
/*			    Tiny Text Editor				       */
/*									       */
/*	     for  German and French  version				       */
/*									       */
/*	     Programmed by Y.Nishida   [ Nov.15, 1991 ]	 version 1.00	       */
/*	     Programmed by N.Okajima   [ Jan.17, 1992 ]	 version 1.50	       */
/*******************************************************************************/

#include    <stdio.h>
#include    <strings.h>
#include    <ctype.h>
#include    <jctype.h>
#include    "console.h"
#include    "editor.h"
#include    "moji_dot.h"


static char LineCutBuffer[MAXCOLUM] ;
static int  LineCutFlag = 0 ;

extern void  InsertMemory() ;
extern void  DeleteMemory() ;
extern void  DisplayNumber();
static void  FillMemory() ;
static int   GetIndentDepth() ;

/************************************************************************/
/*  Store character into the Text buffer				*/
/************************************************************************/

extern int StoreChar( code )
int  code ;
{
	unchar *txtptr ;
	int    pnt ;

	txtptr = &TextBuffer[CurrentLine][CurrentColum] ;

	if ( InsertFlag ) {
		while ( code < 0x100 ) {
			if ( (isprint((unchar)code) || (code>0xa0 && code<0x100)) && CurrentColum < MAXCOLUM-1 ) {
				InsertMemory( txtptr,MAXCOLUM-CurrentColum,1 ) ;
				*txtptr = code ;
				write( 1,txtptr++,ScreenWidth-CursorPosX-1 ) ;
				CursorForward() ;
			}
			code = InputChar() ;
		}
	}
	else {
		while ( code < 0x100 ) {
			if ( (isprint((unchar)code) || (code>0xa0 && code<0x100)) && CurrentColum < MAXCOLUM-1 ) {
				*txtptr = code ;
				write( 1,txtptr++,1 ) ;
				CursorForward() ;
			}
			code = InputChar() ;
		}
	}
	return ( code ) ;
}

/************************************************************************/
/*  Back space								*/
/************************************************************************/

extern int BackSpace( code )
int code ;
{
	int    cc,pnt ;
	unchar *txtptr ;

	cc     = code ;
	txtptr = &TextBuffer[CurrentLine][CurrentColum] ;

	while ( cc == code ) {
		if ( CurrentColum > 0 ) {
			CursorBackward() ;
			DeleteMemory( --txtptr,MAXCOLUM-CurrentColum,1 ) ;
			write( 1,txtptr,ScreenWidth-CursorPosX-1 ) ;
			Locate( CursorPosX,CursorPosY ) ;
		}
		cc = InputChar() ;
	}
	return ( cc ) ;
}

/************************************************************************/
/*  Delete character							*/
/************************************************************************/

extern int DeleteChar( code )
int  code ;
{
	int    cc,pnt ;
	unchar *txtptr ;

	cc     = code ;
	txtptr = &TextBuffer[CurrentLine][CurrentColum] ;

	while ( cc == code ) {
		DeleteMemory( txtptr,MAXCOLUM-CurrentColum,1 ) ;
		write( 1,txtptr,ScreenWidth-CursorPosX-1 ) ;
		Locate( CursorPosX,CursorPosY ) ;
		cc = InputChar() ;
	}
	return ( cc ) ;
}

/************************************************************************/
/*  Change insert mode flag						*/
/************************************************************************/

extern int InsertMode()
{
	if ( InsertFlag ) {
		InsertFlag = 0 ;
		Information[22] = 'O' ;
		Information[23] = 'W' ;
		Information[24] = 'T' ;
	}
	else {
		InsertFlag = 1 ;
		Information[22] = 'I' ;
		Information[23] = 'N' ;
		Information[24] = 'S' ;
	}
	Locate( 0,0 ) ;
	PrintMessage( Information ) ;
	Locate( CursorPosX,CursorPosY ) ;
	return ( InputChar()) ;
}

/************************************************************************/
/*  Erase line								*/
/************************************************************************/

extern int EraseLine()
{
	register unchar *txtptr ;
	register int	count ;

	txtptr = &TextBuffer[CurrentLine][CurrentColum] ;
	for ( count=CurrentColum ; count<MAXCOLUM ; count++ ) {
		*txtptr++ = ' ' ;
	}
	write( 1,"\033[K",3 ) ;
	return ( InputChar()) ;
}

/************************************************************************/
/*  Erase line all							*/
/************************************************************************/

extern int EraseLineAll()
{
	register unchar *txtptr ;
	register int	count ;

	memcpy( LineCutBuffer,&TextBuffer[CurrentLine][0],MAXCOLUM ) ;
	LineCutFlag = 1 ;

	txtptr = &TextBuffer[CurrentLine][0] ;
	for ( count=0 ; count<MAXCOLUM ; count++ ) {
		*txtptr++ = ' ' ;
	}
	write( 1,"\033[2K",4 ) ;
	return ( MoveTopLine()) ;
}

/************************************************************************/
/*  Insert line								*/
/************************************************************************/

extern int InsertLine()
{
	register unchar *souptr,*desptr ;
	register int	count ;

	if ( MaximumLine >= MAXLINE-1 ) return ( InputChar()) ;

	souptr = &TextBuffer[MaximumLine  ][MAXCOLUM-1] ;
	desptr = &TextBuffer[MaximumLine+1][MAXCOLUM-1] ;
	count  = ( MaximumLine-CurrentLine+1 ) * MAXCOLUM ;
	MaximumLine++ ;
	while ( count-- ) {
		*desptr-- = *souptr-- ;
	}
	desptr = &TextBuffer[CurrentLine][0] ;
	for ( count=0 ; count<MAXCOLUM ; count++ ) {
		*desptr++ = ' ' ;
	}
	if ( CurrentHomeX == 0 ) {
		DisplayAfter() ;
		Locate( CursorPosX,CursorPosY ) ;
	}
	return ( MoveTopInsLine()) ;
}

/************************************************************************/
/*  Delete line								*/
/************************************************************************/

extern int DeleteLine()
{
	register unchar *souptr,*desptr ;
	register int	count,line,len ;
	int  pnt ;

	if ( CurrentLine == MaximumLine ) {
		if ( (len=GetLineLength( &TextBuffer[CurrentLine][MAXCOLUM] )) > 0 ) {
			 DeleteMemory(&TextBuffer[CurrentLine][0],len,len) ;
		}
	}

	else if ( MaximumLine > 0  && CurrentLine < MaximumLine) {
		memcpy( LineCutBuffer,&TextBuffer[CurrentLine][0],MAXCOLUM ) ;
		LineCutFlag = 1 ;
		desptr	    = &TextBuffer[CurrentLine  ][0] ;
		souptr	    = &TextBuffer[CurrentLine+1][0] ;
		count	    = ( MaximumLine-CurrentLine ) * MAXCOLUM ;
		MaximumLine-- ;

		if ( count > 0 ) {
			while ( count-- )  *desptr++ = *souptr++ ;
		}
		write( 1,"\033[1M",4 ) ;
		if (( line = CurrentHomeY+ScreenHeight-2 ) <= MaximumLine ) {
			Locate( 0,ScreenHeight-1 ) ;
			write( 1,(char *)&TextBuffer[line][CurrentHomeX],ScreenWidth-1 ) ;
		}
		Locate( CursorPosX,CursorPosY ) ;
	}
	return ( InputChar()) ;
}

/************************************************************************/
/*  Copy line buffer							*/
/************************************************************************/

extern int CopyLine()
{
	memcpy( LineCutBuffer,&TextBuffer[CurrentLine][0],MAXCOLUM ) ;
	LineCutFlag = 1 ;
	return ( InputChar()) ;
}

/************************************************************************/
/*  Paste deleted line							*/
/************************************************************************/

extern int PasteDeletedLine()
{
	register unchar *souptr,*desptr ;
	register int	count ;
	int  pnt ;
	char cc=' ' ;

	if ( MaximumLine < MAXLINE-1 && LineCutFlag ) {
		souptr = &TextBuffer[MaximumLine  ][MAXCOLUM-1] ;
		desptr = &TextBuffer[MaximumLine+1][MAXCOLUM-1] ;
		count  = ( MaximumLine-CurrentLine+1 ) * MAXCOLUM ;
		MaximumLine++ ;
		while ( count-- ) {
			*desptr-- = *souptr-- ;
		}
		memcpy( &TextBuffer[CurrentLine][0],LineCutBuffer,MAXCOLUM ) ;
		write( 1,"\033[1L",4 ) ;
		Locate( 0,CursorPosY ) ;

		write( 1,(char *)&TextBuffer[CurrentLine][CurrentHomeX],ScreenWidth-1 ) ;
		Locate( CursorPosX,CursorPosY ) ;
	}
	return ( InputChar()) ;
}

/************************************************************************/
/*  Carriage return							*/
/************************************************************************/

extern int CarriageReturn()
{
	register unchar *souptr,*desptr ;
	register int	count ;

	if ( MaximumLine >= MAXLINE-1 ) return ( InputChar()) ;

	if ( InsertFlag || CurrentLine == MaximumLine ) {
		souptr = &TextBuffer[MaximumLine  ][MAXCOLUM-1] ;
		desptr = &TextBuffer[MaximumLine+1][MAXCOLUM-1] ;
		count  = ( MaximumLine-CurrentLine+1 ) * MAXCOLUM ;
		MaximumLine++ ;
		while ( count-- ) {
			*desptr-- = *souptr-- ;
		}
		desptr = &TextBuffer[CurrentLine][CurrentColum] ;
		for ( count=CurrentColum ; count<MAXCOLUM ; count++ ) {
			*desptr++ = ' ' ;
		}
		if ( CurrentColum > 0 ) {
			desptr = &TextBuffer[CurrentLine+1][0] ;
			souptr = &TextBuffer[CurrentLine+1][CurrentColum] ;
			for ( count=MAXCOLUM-CurrentColum ; count>0 ; count-- ) {
				*desptr++ = *souptr++ ;
			}
			for ( count=0 ; count<CurrentColum ; count++ ) {
				*desptr++ = ' ' ;
			}
		}
		if ( CurrentHomeX == 0 ) {
			DisplayAfter() ;
			Locate( CursorPosX,CursorPosY ) ;
		}
	}
	return ( ReturnCursor()) ;
}

/************************************************************************/
/*  Duplicate line							*/
/************************************************************************/

extern int DuplicateLine()
{
	register unchar *souptr,*desptr ;
	register int	count ;

	if ( MaximumLine >= MAXLINE-1 ) return ( InputChar()) ;

	souptr = &TextBuffer[MaximumLine  ][MAXCOLUM-1] ;
	desptr = &TextBuffer[MaximumLine+1][MAXCOLUM-1] ;
	count  = ( MaximumLine-CurrentLine+1 ) * MAXCOLUM ;
	MaximumLine++ ;
	while ( count-- ) {
		*desptr-- = *souptr-- ;
	}
	if ( CurrentHomeX == 0 ) {
		DisplayAfter() ;
		Locate( CursorPosX,CursorPosY ) ;
	}
	return ( InputChar()) ;
}

/************************************************************************/
/*  Adjust Indent							*/
/************************************************************************/

extern int AdjustIndent()
{
	unchar *txtptr ;
	int    count,indent,pnt ;
	char   cc=' ' ;

	txtptr = &TextBuffer[CurrentLine][0] ;

	if (( indent = GetIndentDepth( txtptr )) < MAXCOLUM ) {
		if ( indent < CurrentColum ) {
			count = CurrentColum - indent ;
			InsertMemory( txtptr,MAXCOLUM,count ) ;
			FillMemory( txtptr,count,' ' ) ;
			Locate( 0,CursorPosY ) ;
			write( 1,txtptr+CurrentHomeX,ScreenWidth-1 ) ;
			Locate( CursorPosX,CursorPosY ) ;
		}
		else if ( indent > CurrentColum ) {
			count = indent - CurrentColum ;
			DeleteMemory( txtptr,MAXCOLUM,count ) ;
			FillMemory( txtptr+(MAXCOLUM-count),count,' ' ) ;
			Locate( 0,CursorPosY ) ;
			write( 1,txtptr+CurrentHomeX,ScreenWidth-1 ) ;
			Locate( CursorPosX,CursorPosY ) ;
		}
	}
	return ( InputChar()) ;
}

/************************************************************************/
/*  Insert memory							*/
/************************************************************************/

extern void InsertMemory( txtptr,txtlen,inslen )
unchar *txtptr ;
int    txtlen,inslen ;
{
	register unchar *souptr,*desptr ;
	register int	cpycnt ;

	if (( cpycnt = txtlen - inslen ) > 0 ) {
		desptr = txtptr + txtlen ;
		souptr = desptr - inslen ;
		while ( cpycnt-- ) *--desptr = *--souptr ;
	}
}

/************************************************************************/
/*  Delete memory							*/
/************************************************************************/

extern void DeleteMemory( desptr,txtlen,inslen )
register unchar *desptr ;
int	 txtlen,inslen ;
{
	register unchar *souptr ;
	register int	cpycnt ;

	if (( cpycnt = txtlen - inslen ) > 0 ) {
		souptr = desptr + inslen ;
		while ( cpycnt-- ) *desptr++ = *souptr++ ;
	}
}

/************************************************************************/
/*  Fill memory								*/
/************************************************************************/

static void FillMemory( txtptr,count,data )
register unchar *txtptr ;
register count,data ;
{
	while ( count-- ) {
		*txtptr++ = data ;
	}
}

/************************************************************************/
/*  Get Indent depth							*/
/************************************************************************/

static int GetIndentDepth( txtptr )
register char *txtptr ;
{
	register int count ;

	for ( count=0 ; count<MAXCOLUM ; count++ ) {
		if ( *txtptr++ != ' ' ) break ;
	}
	return ( count ) ;
}

/************************************************************************/
/*  Change Auto TAB flag						*/
/************************************************************************/

extern int ChangeAutoIndent()
{
	AutoIndentFlag ^= 1 ;
	return ( InputChar()) ;
}

/************************************************************************/
/*  Change Latin character Input  flag					*/
/************************************************************************/

extern int ChangeLatin()
{
	LatinFlag ^= 1 ;
	return ( InputChar()) ;
}


/************************************************************************/
/*  Auto Indent								*/
/************************************************************************/

extern int AutoIndent( line )
int  line ;
{
	int  indent,old_home ;

	if ( line >= 0 ) {
		if (( indent = GetIndentDepth( &TextBuffer[line][0] )) < MAXCOLUM ) {
			CurrentColum = indent ;
			CursorPosX   = CurrentColum - CurrentHomeX ;
			old_home     = CurrentHomeX ;

			while ( CursorPosX > ScreenWidth-1 ) {
				CursorPosX   -= 8 ;
				CurrentHomeX += 8 ;
			}
			if ( CurrentHomeX != old_home )	 DisplayAllScreen() ;
		}
	}
}

/************************************************************************/
/*  Delete Word								*/
/************************************************************************/

extern int DeleteWord()
{
	unchar *txtptr ;
	int    len=0,pnt;
	char   cc=' ' ;

	txtptr = &TextBuffer[CurrentLine][CurrentColum] ;

	if ( GetLineLength(&TextBuffer[CurrentLine][MAXCOLUM]) == 0 )
		return ( InputChar() ) ;

	switch(*txtptr) {
		case ' ':
			while ( *txtptr == ' ' ) {
				len++ ;
				txtptr++ ;
				if ( txtptr == &TextBuffer[CurrentLine][MAXCOLUM] )
					return ( InputChar() ) ;
			}
			break ;
		default :
			while ( *txtptr != ' ' ) {
				len++ ;
				txtptr++ ;
			}
			break ;
	}

	if ( len > 64 ) {
		txtptr -= len ;
		while ( len-- ) {
			DeleteMemory(txtptr,MAXCOLUM-CurrentColum,1 ) ;
			write( 1,txtptr,ScreenWidth-CursorPosX-1 ) ;
			Locate( CursorPosX,CursorPosY ) ;
		}
	}
	else {
		DeleteMemory(txtptr-len,MAXCOLUM-CurrentColum,len ) ;
		write( 1,txtptr-len,ScreenWidth-CursorPosX-1 ) ;
		Locate( CursorPosX,CursorPosY ) ;
	}

	return ( InputChar() ) ;
}

/************************************************************************/
/*  Dot Count								*/
/************************************************************************/

extern int DotCount()
{
	unchar *txtptr ;
	char	infobuf[200];
	int    len,i,j,dtcnt,cc,errflg;

	errflg=0;
	dtcnt = 0;
	txtptr = &TextBuffer[CurrentLine][0] ;

	if ( (len=GetLineLength(&TextBuffer[CurrentLine][MAXCOLUM])) == 0 )
		return ( InputChar() ) ;

	for( i=0;i<len;i++ ) {
		if( *(txtptr+i)=='@' ) {
		    return ( InputChar() ) ;
		}
		else{
			for(j=0;j<MOJI_CNT;j++) {
				if ( *(txtptr+i)==moji_tbl[j] ) break ;
			}
			if( j<MOJI_CNT ) {
				dtcnt+=dot_tbl[j] ;
			}
			else {
				errflg=1;
				break;
			}
		}
	}
	
	if( errflg==0 ) {
		if( dtcnt > DOT_MAX ) {
			sprintf( infobuf," Line:%03d  Dot Count=%3d Dots   *** %3d Dots Over !! ***",
					 CurrentLine+1,dtcnt,dtcnt-DOT_MAX );
		}
		else {
			sprintf( infobuf," Line:%03d  Dot Count=%3d Dots",CurrentLine+1,dtcnt ) ;
		}
	}
	else {
		sprintf( infobuf," Line:%03d  Colum:%03d   '%c' ERROR !!",CurrentLine+1,i+1,*(txtptr+i) ) ;
	}


	PutStr( "\033[1;1H\033[K" ) ;
	PrintMessage( infobuf ) ;

	cc=InputChar();

	PutStr( "\033[1;1H\033[K" ) ;
	sprintf( Information+6,"%05d  COL:%03d",CurrentLine+1,CurrentColum+1 ) ;
	Information[20] = ' ' ;
	PrintMessage( Information ) ;
	Locate( CursorPosX,CursorPosY ) ;

	if( cc==0x104 || cc==0x105 || cc==0x113 || cc==0x118 ) return ( cc ) ;
	else return ( InputChar() ) ;
}
