/* ....[@@@..[@@@..............[@.................. 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; }