/* -*- LPC -*- */
/*
* $Locker: $
* $Id: line_ed.c,v 1.23 2001/08/25 01:52:19 ceres Exp $
*/
#include "ed.h"
#include <player_handler.h>
/**
* 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
*/
/* September '97 - modified by Presto to allow players to use the 'magic'
* editor and to allow cres to use it as their default file
* editor. Also cleaned up the code a bit cos it was painful
* to look at. Is this file a bunch of crocky code or what?
*/
private nosave string *_lines;
private nosave mixed _end_func;
//private nosave object _end_object;
private nosave object _ed_ob = 0;
//private nosave mixed *_other;
private nosave int _insertion_point;
private string editor; /* The editor to use... */
private nosave string _filename;
private nosave int _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|magic|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(extra) {
_other = extra;
}
if ( !end_o ) {
_end_object = previous_object();
} else {
_end_object = end_o;
}
*/
if (!end_o) {
end_o = previous_object();
}
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", !this_object()->query_creator());
return 1;
case "magic":
if (strlen(str) && (_filename == TMP_FILE))
write_file(_filename, str);
_in_editor = 1;
_ed_ob = new(PRESTOS_ED, _filename, _filename != TMP_FILE);
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]);
this_object()->set_finish_func("end_of_edit_more");
this_object()->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", !this_object()->query_creator());
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);
this_object()->set_finish_func("end_of_edit_more");
this_object()->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(sizeof(_lines) +" lines - Choose from IDLMCESQ or H for help.");
input_to((: main_bit :));
}
else {
printf("%-2d] ", _insertion_point + 1);
input_to((: editor_loop :));
}
return;
} /* main_bit() */
/** @ignore yes */
void end_of_edit_more() {
this_object()->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) + 1))) {
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;
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++) {
_lines[i] = replace_string(_lines[i], modify_string, str);
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..];
/*
_lines[sizeof(_lines)-1] = _lines[sizeof(_lines)-1][0..
strlen(_lines[sizeof(_lines)-1])-2];
*/
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) {
//object prev_end_object;
_lines = ({ });
/*
if (str) str = replace(str, "@@", "@ @ ");
*/
if ((editor == "magic") && (_filename == TMP_FILE) &&
(file_size(_filename) >= 0) && !rm(_filename)) {
printf("magic: couldn't remove %s\n" , _filename);
str = 0;
}
_in_editor = 0;
/*
prev_end_object = _end_object;
_end_object = 0;
if (functionp(_end_func)) {
if(_other) {
evaluate(_end_func, str, _other);
} else {
evaluate(_end_func, str);
}
} else {
if(_other) {
call_other(prev_end_object, _end_func, str, _other);
} else {
call_other(prev_end_object, _end_func, str);
}
}
*/
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);
//_end_object = 0;
return;
} /* editor_check_quit() */
/** @ignore yes */
int set_editor(string str) {
/*
if ( member_array( str, ({ "magic", "menu", "command", "ed" }) ) == -1 ) {
notify_fail( "Your editor can be set to one of the following menu, "
"ed, command, and magic. Please do not set your editor "
"to ed unless you know what you are doing. The menu "
"editor is the default, the command editor is based on "
"using ~ escape characters and the magic editor is one "
"of Presto's concoctions.\n" );
return 0;
}
*/
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() {
return PLAYER_HANDLER->query_signature(this_object()->query_name());
} /* append_signature() */
/** @ignore yes */
void editor_check_do_quit() {
if (_in_editor) {
/* Force them to sve 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 true if the player is currently in the editor.
* @return 1 if the player is in the editor
*/
int query_in_editor() {
return _in_editor;
} /* query_in_editor() */