/*
....[@@@..[@@@..............[@.................. 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@hom.net
MUD++ development mailing list mudpp@van.ml.org
------------------------------------------------------------------------------
edittext.cc
*/
#include "config.h"
#include "string.h"
#include "llist.h"
#include "index.h"
#include "room.h"
#include "hash.h"
#include "server.h"
#include "bit.h"
#include "edit.h"
#include "pc.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; i < lines; i++ )
output << text[i] << "\r\n";
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; i < lines; i++ )
output << i+1 << "] " << text[i] << "\r\n";
return output;
}
// Clear the edit buffer out.
void TextEditor::clr()
{
for( int i=0; i < lines; i++ )
text[i].clr();
lines = 0;
current = 0;
}
// Append a line onto the text.
void TextEditor::append( const char *str )
{
text[current] = str;
text[current].rtrim();
current++;
lines++;
}
// Append a line onto the text.
void TextEditor::append( const String & str )
{
text[current] = str;
text[current].rtrim();
current++;
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.
// i is 1 - lines so subtract 1 before delete
void TextEditor::cutLine( int i )
{
if( i > lines )
return;
i--;
// 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( (bool)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( const String & arg )
{
String arg1;
String arg2;
if( !(bool)arg )
{
pc->out( "Null arg.\n\r" );
return;
}
int line1;
if( state == ED_TEXT_APPEND )
{
if( arg[0] == '~' || arg[0] == '@' )
{
state = 0;
setPrompt( "\n\rText Editor >" );
return;
}
else if( arg[0] == '.' )
{
if( arg[1] == 'c' )
{
clr();
pc->out( "\n\rBuffer cleared.\n\r" );
pc->out( format() );
}
else pc->out( "\n\rUnknown dot command.\n\r" );
return;
}
append( arg );
return;
}
if( isdigit( arg[0] ) )
{
arg.startArgs();
arg1 = arg.getArg();
arg2 = arg.getArgRest();
line1 = arg1.asInt();
if( line1 <= 0 || line1 > lines )
{
pc->out( "\n\rInvalid line number.\n\r" );
return;
}
if( !(bool)arg2 )
{
pc->out( text[line1-1] );
pc->out( "\n\r" );
return;
}
replaceLine( arg2, line1-1 );
return;
}
arg.startArgs();
arg1 = arg.getArg();
arg2 = arg.getArgRest();
switch( tolower( arg[0] ) )
{
case 'a':
pc->out( "Entering append mode.\n\r" );
pc->out( "Enter '~' or '@' on blank line to exit.\n\r" );
pc->out( format() );
state = TASK_EDIT_APPEND;
return;
case 'c':
line1 = arg2.asInt();
if( line1 <= 0 )
pc->out( "\n\rUsage: c <line #>\n\r" );
else
{
text[ line1-1 ].clr();
pc->out( "Line cleared.\n\r" );
}
return;
case 'd':
line1 = arg2.asInt();
if( line1 <= 0 )
pc->out( "\n\rUsage: d <line #>\n\r" );
else
{
cutLine( line1 );
pc->out( "Line cut.\n\r" );
}
return;
case '?':
case 'h':
pc->view( "../help/editor.hlp" );
return;
case 'l':
pc->out( format() );
return;
// Save and leave append
case 'x':
case 'q':
state = ED_DONE;
pc->out( format() );
pc->out( "Saving buffer.\n\r" );
return;
case '!':
state = ED_CANCEL;
pc->out( "Exiting without saving.\n\r" );
return;
default:
return;
}
}
const String & TextEditor::getPrompt()
{
if( state == ED_TEXT_APPEND )
{
prompt.clr();
prompt << ( current + 1 ) << "] ";
}
return prompt;
}