/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@falcon.mercer.peachnet.edu 
MUD++ development mailing list    mudpp-list@spice.com
------------------------------------------------------------------------------
edittext.cc
*/

#include "string.h"
#include "llist.h"
#include "index.h"
#include "room.h"
#include "indexable.h"
#include "server.h"
#include "bit.h"
#include "edit.h"


// The edit object can be used like a char * for copy text from
// the object.
const String & TextEditor::asStr()
{
	output.clr();
	for( int i = 0; text[i]; i++ )
	{ 
		output += text[i];
	}

	return output;
}


// The edit object can be used like an array of strings by providing
// the [] index operator. Returns string at text[i]
const String & TextEditor::operator [] (int i)
{
   if( i >= 0 && i < MAX_LINES )
      return text[i];
   else return text[MAX_LINES]; // dummy string
}


// Show the edit buffer in line format.
const String & TextEditor::format()
{
	output.clr();
  
	for( int i=0; *text[i].chars(); i++ )
	{
		output << i+1 << "] " << text[i] << "\n\r"; 
	}
 
	return output;
}


// Clear the edit buffer out.
void TextEditor::clr()
{
   for( int i=0; i < MAX_LINES; i++ )
   { 
      text[i].clr();
   }
}


// Append a line onto the text.
void TextEditor::append( const char *str )
{
	text[current++] = str;
	lines++;
}

// Append a line onto the text.
void TextEditor::append( const String & str )
{
	text[current++] = str;
	lines++;
}


// Clear the line but do not delete.
// Can be undone.
void TextEditor::clrLine( int i )
{
	clipped = 1;
	clipboard[0] = text[i];
	text[i].clr();
}


// Insert a line at line i. All lines >= i are shifted down.
// Can be undone.
void TextEditor::insertLine( const String &, int )
{

}


// Delete line i and shift the text up.
// Can be undone.
void TextEditor::cutLine( int i )
{
	if( i > lines )
		return;

	// Discard the clipboard
	clipped = 0;
  
	for( int j = i; j < lines; j++ )
	{
		text[j] = text[j+1];	
	} 
	lines--;
}


// Replace line i with str.
// Can be undone.
void TextEditor::replaceLine( const String & str, int i )
{
	if( i >= MAX_LINES || i < 0 )
		return;

	clipped = 1;

	clipboard[0] = text[i];
	text[i] = str;
}


// Cut a block of text.
// Can be used to paste/copy sections of text.
// Can be undone.
void TextEditor::cutLines( int first, int last )
{
	if( first > last || first >= lines || last >= lines
		|| first < 0      || last < 0      )
		return;

	int i, j;

	clipped = last - first + 1;	
	for( i = first; i <= last; i++ )
		clipboard[i-first] = text[i];

	i = first;
	j = last+1;

	while( text[j] )
		text[i++] = text[j++];

	text[i].clr();
	lines -= (last - first);
}


// Paste the clipboard back into the text buffer at line i.
// Can be undone.
void TextEditor::pasteLines( int )
{

}


// Text editor master function. Called from main()
// Player must be in a edit state.
void TextEditor::command( String & arg )
{
	String arg1;
	String arg2;

	if( !arg )
		return;

	char buf[ BUF * 2 ];
	int line1;

	if( state == EDIT_APPEND )
	{
		if( arg[0] == '~' || arg[0] == '@' )
		{
			state = 0;
			return;
		}
		else if( arg[0] == '.' )
		{
			if( arg[1] == 'c' )
			{
				clr();
				pc->out( "\n\rBuffer cleared.\n\r" );
			}
			else
				pc->out( "\n\rUnknown dot command.\n\r" );
			return;
		}  

		append( arg );
		return;      
	}

	if( isdigit( arg[0] ) )
	{
		arg.startArgs();

		arg1 = arg.getArg();
		arg2 = arg.getArg();

		int line1 = arg1.asInt();

		if( line1 <= 0 )
		{
			pc->out( "\n\rInvalid line number.\n\r" );
			return;
		}

		if( !arg2 )
		{
			pc->out( text[line1-1] );
			return;
		} 
     
		replaceLine( arg2, line1-1 );
		return;
	}
 
	arg.startArgs();
	arg1 = arg.getArg();
	arg2 = arg.getArgRest();

	switch( tolower( arg[0] ) )
	{
		case  'a':
				state = TASK_EDIT_APPEND;
				return;
		case  'c':
				line1 = arg2.asInt();
				if( line1 <= 0 )
					pc->out( "\n\rUsage:    clear  <line #>\n\r" );
				else
					text[ line1-1 ].clr();
				return; 
		case  'h':
				pc->view( "../help/editor.hlp" );
				//pc->flush();
				return;
		case  's':
				pc->out( format() );
				return; 
		case  'q':
				state = state_last;
				return;
		default:
				return;
	}
}