/**
* This allows a piece of text to be placed into the players own
* line editor (which ever one they wish to use).
* <p>
* Expansion of the editor. We will now allow the player to use any
* of three different editors. One of them is the default (the old
* one) one of them is ed and the other I am going to write in a
* few secs....
* <p>
* cute line editor thing. Which even a player could use!
* @author Pinkfish
*/
#include "ed.h"
private nosave string *_lines;
private nosave mixed _end_func;
private nosave object _ed_ob = 0;
private nosave int _insertion_point;
private string editor;
private nosave string _filename;
private nosave mixed _in_editor;
private void main_bit(string str);
int set_editor(string name);
private void editor_do_quit(string str);
private void editor_loop(string str);
private void editor_insert(string str);
private void editor_delete(string str);
private void editor_modify(string str);
private void editor_check_quit(string str);
private void editor_modify2(string str, int range1, int range2);
private void editor_modify3(string str, int range1, int range2,
string modify_string);
protected void create() {
editor = "menu";
} /* create() */
/** @ignore yes */
protected void editor_commands() {
add_command("editor", "{menu|ed|command}", (: set_editor($4[0]) :) );
} /* edito_commands() */
/**
* Edit a string. This will edit the string or file name and then
* call the end function and end object at the end. It will pas in
* the string if the edit is successful, or 0 if it is not.
* @param str the string to edit
* @param end_f the function to call
* @param end_o the object to call it on (defaul: previous_object())
* @param fname a specific filename to edit
* @param extra an array of any parameters you need to carry into the end function
* @return 0 on failure.
*/
varargs int do_edit( string str, mixed end_f, object end_o, string fname,
mixed extra ) {
if( !end_f ) {
printf("Someone has stuffed up - there is no end function.\n");
return 0;
} else {
_end_func = end_f;
}
if( !end_o )
end_o = PO;
if( !str )
str = "";
if( !strlen(fname) )
_filename = TMP_FILE;
else
_filename = fname;
if( !functionp(end_f) ) {
if( extra )
_end_func = (: call_other( $(end_o), $(end_f), $1, $(extra) ) :);
else
_end_func = (: call_other( $(end_o), $(end_f), $1 ) :);
} else {
if( extra )
_end_func = (: evaluate( $(end_f), $1, $(extra) ) :);
else
_end_func = (: evaluate( $(end_f), $1 ) :);
}
switch( editor ) {
case "menu":
_lines = explode( str, "\n") - ({ 0 });
printf("Enter your text. Use ** on a line by itself to exit.\n");
_insertion_point = sizeof(_lines);
printf("%-2d] ", _insertion_point + 1 );
_in_editor = 1;
input_to( (: editor_loop :) );
return 1;
case "ed":
if( strlen(str) && _filename == TMP_FILE )
write_file( _filename, str );
_in_editor = 1;
ed(_filename, "editor_finish_ed", !creatorp(TO) );
return 1;
case "command":
_lines = explode(str, "\n") - ({ 0 });
printf("Enter your text. Use ** on a line by itself to exit or "
"~h for help.\n");
_insertion_point = sizeof(_lines);
printf("%-2d] ", _insertion_point + 1 );
_in_editor = 1;
input_to( (: editor_loop :) );
return 1;
}
} /* do_edit() */
/** @ignore yes */
private void main_bit( string str ) {
int i;
string s;
if( str != "") {
while( str[0] == ' ')
str = str[1..];
switch( str[0] ) {
case 'i':
case 'I':
printf("Insert before line: ");
input_to( (: editor_insert :) );
return;
case 'd':
case 'D':
printf("Delete (line no, or n..m ie 1..2): ");
input_to( (: editor_delete :) );
return;
case 'l':
case 'L':
if( !sizeof(_lines) ) {
main_bit("");
} else {
s = "";
for( i = 0; i < sizeof(_lines); i++ )
s += sprintf("%3d: %s\n", i + 1, _lines[i] );
TO->set_finish_func("end_of_edit_more");
TO->more_string(s);
}
return;
case 'm':
case 'M':
printf("Modify which line (line no, or n..m ie 1..2): ");
input_to( (: editor_modify :) );
return;
case 'c':
case 'C':
_insertion_point = sizeof(_lines);
printf("Okay, back into insertion mode. Use ** on a line "
"by itself to exit.\n%-2d] ", _insertion_point + 1 );
input_to( (: editor_loop :) );
return;
case 'e':
case 'E':
printf("Entering ed... Use \"q\" to quit, \"x\" to save and "
"quit, \"Q\" to quite without saving changes and \"h\" "
"for help.\n");
write_file( _filename, implode(_lines, "\n") );
ed( _filename, "editor_exit_ed", !creatorp(TO) );
return;
case 's':
case 'S':
printf("Quitting and saving.\n");
editor_do_quit( implode(_lines, "\n") );
return;
case 'q':
case 'Q':
printf("Are you sure you want to quit? (Y/N) ");
input_to( (: editor_check_quit :) );
return;
case 'h':
case 'H':
s = read_file(ED_HELP_FILE);
TO->set_finish_func("end_of_edit_more");
TO->more_string(s);
return;
default:
printf("I do not understand you. Try %s for help.\n",
( editor == "command" ? "~h" : "h" ) );
main_bit("");
return;
}
}
if( editor == "menu") {
printf( "%i lines - Choose from IDLMCESQ or H for help.", sizeof(_lines) );
input_to( (: main_bit :) );
} else {
printf("%-2d] ", _insertion_point + 1 );
input_to( (: editor_loop :) );
}
return;
} /* main_bit() */
/** @ignore yes */
void end_of_edit_more() {
TO->set_finish_func(0);
main_bit("");
} /* end_of_edit_more() */
/** @ignore yes */
private void editor_delete( string str ) {
int num1, num2, tmp;
if( sscanf(str, "%d..%d", num1, num2 ) == 2 ) {
if( num1 > num2 ) {
tmp = num1;
num1 = num2;
num2 = tmp;
}
if( num1 < 1 || num2 > sizeof(_lines) + 1 ) {
printf("Out of bounds.\n");
main_bit("");
}
printf("Deleting from line %d to line %d.\n", num1, num2 );
_lines = delete( _lines, num1 - 1, num2 - num1 + 1 );
printf("Okay.\n");
main_bit("");
return;
}
if( sscanf( str, "%d", num1 ) == 1 ) {
if( num1 < 1 || num1 > sizeof(_lines) ) {
printf("Line number out of range.\n");
main_bit("");
return;
}
printf("Deleting line %d.\n", num1 );
_lines = delete( _lines, num1 - 1, 1 );
printf("Okay.\n");
main_bit("");
return;
}
printf("Error: invalid data %s.\n", str );
main_bit("");
return;
} /* editor_delete() */
/** @ignore yes */
private void editor_insert( string str ) {
int num;
if( sscanf( str, "%d", num ) != 1 ) {
printf("Error: must be a number.\n");
main_bit("");
return;
}
if( num < 1 || num > sizeof(_lines) + 1 ) {
printf("Error: number out of bounds.\n");
main_bit("");
return;
}
_insertion_point = num - 1;
printf("Inserting before line %d. Entering insertion mode. Use ** on a "
"line by itself to exit\n%-2d] ", num, num );
input_to( (: editor_loop :) );
return;
} /* editor_insert() */
/** @ignore yes */
private void editor_loop( string str ) {
if( strlen(str) > 1 && str[0] == '~' && editor == "command") {
main_bit(str[1..]);
return;
}
if( str == "**") {
if( editor == "menu")
main_bit("");
else if( sizeof(_lines) )
editor_do_quit( implode( _lines, "\n") );
else
editor_do_quit(0);
return;
}
_lines = _lines[0.._insertion_point - 1] + ({ str }) +
_lines[_insertion_point..];
++_insertion_point;
printf("%-2d] ", _insertion_point + 1 );
input_to( (: editor_loop :) );
return;
} /* editor_loop() */
/** @ignore yes */
private void editor_modify( string str ) {
int num1, num2, tmp;
if( sscanf( str, "%d..%d", num1, num2 ) == 2 ) {
if( num1 > num2 ) {
tmp = num1;
num1 = num2;
num2 = tmp;
}
if( num1 < 1 || num2 > sizeof(_lines) + 1 ) {
printf("Error: number out of bounds.\n");
main_bit("");
}
printf("Modifying from line %d to line %d.\n", num1, num2 );
printf("Text to change? ");
input_to( (: editor_modify2 :), 0, num1, num2 );
return;
}
if( sscanf(str, "%d", num1 ) == 1 ) {
if( num1 < 1 || num1 > sizeof(_lines) + 1 ) {
printf("Error: line number out of range.\n");
main_bit("");
return;
}
printf("Modifying line %d.\n", num1 );
printf("Text to change? ");
input_to( (: editor_modify2 :), 0, num1, num1 );
return;
}
printf("Error: invalid data %s.\n", str );
main_bit("");
return;
} /* editor_modify() */
/** @ignore yes */
private void editor_modify2( string str, int range1, int range2 ) {
if( !strlen(str) ) {
printf("Aborting.\n");
main_bit("");
return;
}
printf("Change to: ");
input_to( (: editor_modify3 :), 0, range1, range2, str );
return;
} /* editor_modify2() */
/** @ignore yes */
private void editor_modify3( string str, int range1, int range2,
string modify_string ) {
int i, pos;
string s1, s2;
printf("Changing all occurrences of \"%s\" to \"%s\" from line %d to "
"line %d.\n", modify_string, str, range1, range2 );
for( i = range1 - 1; i < range2 && i < sizeof(_lines); i++ ) {
pos = strsrch( _lines[i], modify_string );
if( pos != -1 ) {
s1 = _lines[i][0..pos-1];
s1 += str;
s2 = _lines[i][pos + strlen(modify_string)..];
do {
pos = strsrch( s2, modify_string );
if( pos != -1 ) {
s1 += s2[0..pos-1];
s2 = s2[pos + strlen(modify_string)..];
}
} while( pos != -1 );
_lines[i] = s1 + s2;
printf("%3d: %s\n", i + 1, _lines[i] );
}
}
printf("Done.\n");
main_bit("");
return;
} /* editor_modify3() */
/** @ignore yes */
void editor_exit_ed() {
string str;
str = read_file(_filename);
if( file_size(_filename) >= 0 && !rm(_filename) )
log_file( LOG_FILE, "ed: couldn't rm %s\n", _filename );
_lines = explode("#" + str, "\n");
_lines[0] = _lines[0][1..];
main_bit("");
return;
} /* editor_exit_ed() */
/** @ignore yes */
void editor_finish_ed() {
string str;
str = read_file(_filename);
if( file_size(_filename) >= 0 && _filename == TMP_FILE &&
!rm(_filename) )
log_file( LOG_FILE, "ed: couldn't rm %s\n", _filename );
if( !str ) {
printf("Aborted.\n");
editor_do_quit(0);
return;
}
if( _filename == TMP_FILE )
editor_do_quit(str);
else
editor_do_quit(0);
return;
} /* editor_finish_ed() */
/** @ignore yes */
void editor_do_quit( string str ) {
_lines = ({ });
_in_editor = 0;
if( _ed_ob )
destruct(_ed_ob);
evaluate( _end_func, str );
} /* editor_do_quit() */
/** @ignore yes */
private void editor_check_quit( string str ) {
if( str != "" && str[0] != 'y' && str[0] != 'Y') {
printf("Returning to the editor.\n");
main_bit("");
return;
}
printf("Quitting.\n");
editor_do_quit(0);
return;
} /* editor_check_quit() */
/** @ignore yes */
int set_editor( string str ) {
editor = str;
printf("Editor set to %s.\n", str );
return 1;
} /* set_editor() */
/**
* This method will create the signature to append to whatever needs
* a signature.
* @return the players signature
*/
string append_signature() {
mapping sig;
string sigstr, *siglines;
int i, lines;
sig = TO->query_aliases();
if( siglines = sig[".signature"] ) {
sigstr = replace( FINGER_H->make_string(siglines),
({";", "\n", "%^", ""}) ) + "\n";
for( i = lines = 0; i < sizeof(sigstr) && lines < 4; i++ ) {
if( sigstr[i] == '\n')
lines++;
}
return "\n--\n" + sigstr[0..i-1] + "%^RESET%^";
}
return "";
} /* append_signature() */
/** @ignore yes */
void editor_check_do_quit() {
if( _in_editor ) {
// Force them to save the thingy they are editing.
printf("Saving what you are editing.\n");
if( editor != "ed")
editor_do_quit( implode( _lines, "\n") );
else
editor_finish_ed();
}
} /* editor_check_do_quit() */
/**
* This method will return the players current editor setting.
* @return the current editor setting.
*/
string query_editor() { return editor; }
/**
* This method returns the value of the in editor flag.
* It will return non-zero if the player is in an editor.
* @return non-zero in editor, 0 not in an editor
* @see set_in_editor()
*/
int query_in_editor() { return _in_editor; }
/**
* This method sets the current in editor flag.
* @param what the new value of the in editor flag
* @see query_in_editor()
*/
void set_in_editor( mixed what ) { _in_editor = what; }