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

#include    <stdio.h>
#include    <strings.h>
#include    <ctype.h>
#include    <signal.h>
#include    "console.h"
#include    "editor.h"
#include    "command.h"

unchar TextBuffer[MAXLINE][MAXCOLUM] ;	/*  text buffer		       */
unchar CutBuffer[CUTLINE][MAXCOLUM] ;	/*  cut buffer		       */
unchar StringBuffer[MAXCOLUM] ;		/*  string input buffer	       */
char   FileName[256] ;			/*  edit file name	       */
char   Information[300] ;		/*  information buffer	       */
int    SignalMask ;

short  TabPoint[256] = {		/*  TAB point buffer	       */
		0,  8,	16, 24, 32, 40, 48, 56,
		64, 72, 80, 88, 96, 104,112,120,
		128,136,144,152,160,168,176,184,
		192,200,208,216,224,232,240,248,
} ;
int    TabCount	      = 32 ;		/*  Number of TAB points       */
int    AutoIndentFlag = 0 ;		/*  Auto indent flag	       */
int    InsertFlag     = 1 ;		/*  insert mode flag	       */
int    LineNumberFlag = 1 ;		/*  Line Number display flag   */

int    CutBufLength = 0 ;		/*  Line length of cut buffer  */

int    ScreenWidth  = 0 ;		/*  width of screen	       */
int    ScreenHeight = 0 ;		/*  height of screen	       */

int    CursorPosX  = 0 ;		/*  cursor position x	       */
int    CursorPosY  = 1 ;		/*  cursor position y	       */

int    MaximumLine  = 0 ;		/*  maximum line number	       */
int    CurrentHomeX = 0 ;		/*  current home line	       */
int    CurrentHomeY = 0 ;		/*  current home colum	       */

int    CurrentLine = 0 ;		/*  current line number	       */
int    CurrentColum = 0 ;		/*  current colum number       */

int    LatinFlag = 0 ;

static void EditMain() ;
static void ChangeScreenSize() ;

/************************************************************************/
/*  main routine of editor						*/
/************************************************************************/

void main( argc,argv )
int  argc ;
char **argv ;
{
	int cc ;

	if ( argc != 2 ) {
		puts( "Tiny screen editor (for German and French)  version 1.50" ) ;
		puts( "Usage: ee  <file name>" ) ;
		exit( 1 ) ;
	}
	strcpy( FileName,*++argv ) ;

	if (( MaximumLine = LoadTextFile( FileName )) == ERROR ) {
		printf( "%s :Cannot load Text file.\n", FileName ) ;
		exit( 1 ) ;
	}
	GetScreenSize( &ScreenWidth,&ScreenHeight ) ;
	if ( ScreenWidth < 25 && ScreenHeight < 4 ) {
		puts( "Screen size is too small." ) ;
		exit( 1 ) ;
	}
	signal( SIGWINCH,ChangeScreenSize ) ;
	SignalMask = sigblock( sigmask( SIGWINCH )) ;
	SetConsoleMode( CONSOLE_LOWMODE ) ;
	EditMain() ;
	SetConsoleMode( CONSOLE_RESET ) ;
}

/************************************************************************/
/*  Editor main								*/
/************************************************************************/

static void EditMain()
{
	int	code ;

	SetupEditor() ;
	DisplayAllScreen() ;
	Locate( CursorPosX,CursorPosY ) ;

	code = InputChar() ;

	while ( code >= 0 ) {
		if ( code == 0x200 ) {
			code = GotoLine() ;
		}
		else if ( code >= 0x100 ) {
			code = (*CommandProcess[code-0x100])( code ) ;
		}
		else {
			code = StoreChar( code ) ;
		}
	}
}

/************************************************************************/
/*  Exit editor ( save )						*/
/************************************************************************/

static int ExitEditor()
{
	int  res = -1 ;
	char backfile[256],debug[256] ;

	strcpy( backfile,FileName ) ;
	strcat( backfile,".BAK" ) ;
	rename( FileName,backfile ) ;

	PutStr( "\033[1;1H\033[K" ) ;
	PrintMessage( " Saving Now !!" ) ;

	WriteText( debug,0,MaximumLine+1 ) ;

	if ( SaveTextFile( FileName,0,MaximumLine+1 ) == ERROR ) {
		PutStr( "\033[1;1H\033[K" ) ;
		PrintMessage( "File save error." ) ;
		InputChar() ;
		PutStr( "\033[1;1H\033[K" ) ;
		PrintMessage( Information ) ;
		Locate( CursorPosX,CursorPosY ) ;
		res = InputChar() ;
	}
	else {
		PutStr( "\033[2J\033[1;1H" ) ;
		res = -1 ;
	}
	return ( res ) ;
}

/************************************************************************/
/*  Quit editor ( not save )						*/
/************************************************************************/

static int QuitEditor()
{
	int  cc,res ;

	PutStr( "\033[1;1H\033[K" ) ;
	PrintMessage( "Do you really want to quit ? (y/n)" ) ;

	res = -2 ;
	while ( res == -2 ) {
		cc = InputChar() ;
		if ( cc == 'n' || cc == 'N' ) {
			PutStr( "\033[1;1H\033[K" ) ;
			PrintMessage( Information ) ;
			Locate( CursorPosX,CursorPosY ) ;
			res = InputChar() ;
		}
		else if ( cc == 'y' || cc == 'Y' ) {
			PutStr( "\033[2J\033[1;1H" ) ;
			res = -1 ;
		}
	}
	return ( res ) ;
}

/************************************************************************/
/*  Save file								*/
/************************************************************************/

static int SaveFile()
{
	char backfile[256] ;

	strcpy( backfile,FileName ) ;
	strcat( backfile,".BAK" ) ;
	rename( FileName,backfile ) ;

	PutStr( "\033[1;1H\033[K" ) ;
	PrintMessage( " Saving Now !!" ) ;
	Locate( CursorPosX,CursorPosY ) ;
	if ( SaveTextFile( FileName,0,MaximumLine+1 ) == ERROR ) {
		PutStr( "\033[1;1H\033[K" ) ;
		PrintMessage( "File save error." ) ;
		InputChar() ;
	}
	PutStr( "\033[1;1H\033[K" ) ;
	PrintMessage( Information ) ;
	Locate( CursorPosX,CursorPosY ) ;

	return ( InputChar()) ;
}

/************************************************************************/
/*  Change file name							*/
/************************************************************************/

static int ChangeFileName()
{
	int length ;

	PutStr( "\033[7m" ) ;
	PutStr( "\033[1;1H\033[KNew File Name:" ) ;
	length = InputString( 14,0 ) ;
	if ( 0 < length && length < 255 ) {
		strcpy( FileName,StringBuffer ) ;
		sprintf( Information+39,"%s", FileName ) ;
	}
	PutStr( "\033[1;1H\033[K" ) ;
	PrintMessage( Information ) ;
	PutStr( "\033[27m" ) ;
	Locate( CursorPosX,CursorPosY ) ;
	return ( InputChar()) ;
}

/************************************************************************/
/*  Marge file								*/
/************************************************************************/

static int MargeFile()
{
	static int  AllocMemory() ;
	static void FreeMemory() ;
	int  free_size,load_size ;

	PutStr( "\033[7m" ) ;
	PutStr( "\033[1;1H\033[KRead File Name:" ) ;
	if ( InputString( 15,0 ) > 0 ) {
		PutStr( "\033[27m" ) ;
		if (( free_size = AllocMemory( CurrentLine )) > 0 ) {
			load_size = MargeTextFile( StringBuffer,CurrentLine,free_size ) ;
			if ( load_size < 0 ) {
				PutStr( "\033[1;1H\033[K" ) ;
				if ( load_size == -1 ) PrintMessage( "Text buffer full." ) ;
						  else PrintMessage( "File not found." ) ;
				InputChar() ;
				FreeMemory( CurrentLine,free_size ) ;
			}
			else {
				FreeMemory( CurrentLine+load_size,free_size-load_size ) ;
				MaximumLine += load_size ;
			}
			DisplayAfter() ;
		}
		else {
			PutStr( "\033[1;1H\033[K" ) ;
			PrintMessage( "Text buffer full." ) ;
			InputChar() ;
		}
	}
	PutStr( "\033[1;1H\033[K" ) ;
	PrintMessage( Information ) ;
	Locate( CursorPosX,CursorPosY ) ;
	return ( InputChar()) ;
}

/************************************************************************/
/*  Allocate memory							*/
/************************************************************************/

static int AllocMemory( line )
int  line ;
{
	int	free_size ;
	register unchar *souptr,*desptr ;
	register int count ;

	free_size = MAXLINE - MaximumLine - 1 ;
	if ( free_size > 0 ) {
		souptr = &TextBuffer[MaximumLine][MAXCOLUM-1] ;
		desptr = &TextBuffer[MAXLINE-1	][MAXCOLUM-1] ;
		count  = ( MaximumLine - line + 1 ) * MAXCOLUM ;
		while ( count-- ) {
			*desptr-- = *souptr-- ;
		}
	}
	return ( free_size ) ;
}

/************************************************************************/
/*  Free memory								*/
/************************************************************************/

static void FreeMemory( line,size )
int  line,size ;
{
	register unchar *souptr,*desptr ;
	register int count ;

	if ( size > 0 ) {
		souptr = &TextBuffer[line+size][0] ;
		desptr = &TextBuffer[line     ][0] ;
		count  = ( MAXLINE - line - size ) * MAXCOLUM ;
		while ( count-- ) {
			*desptr++ = *souptr++ ;
		}
	}
}

/************************************************************************/
/*  Change Screen size							*/
/************************************************************************/

static void  ChangeScreenSize()
{
	GetScreenSize( &ScreenWidth,&ScreenHeight ) ;
	PutStr( "\033[2J" ) ;
	MoveCursorLine( CurrentLine,(ScreenHeight-1)/2 ) ;
	PutStr( "\033[1;1H" ) ;
	PrintMessage( Information ) ;
	Locate( CursorPosX,CursorPosY ) ;
}
