/* Do not remove the headers from this file! see /USAGE for more info. */
/*
** edit_ob.c
**
** Based on a text-entry facility by Rust.
** Transformed and rewritten by Deathblade on 8/23/94 to use the
** new input system facilities.
**
** Usage:
** new(EDIT_OB, EDIT_FILE, fname, func)
** or new(EDIT_OB, EDIT_TEXT, text, func)
**
** "func" will be evaluated when the editing is complete. One
** parameter will be passed, which will be zero if the editing
** was aborted for some reason. Otherwise, it will be a single
** string specifying the file name, or an array of strings
** holding the lines of text.
*/
#include <mudlib.h>
#include <playerflags.h>
#include <edit.h>
inherit M_ACCESS;
inherit M_INPUT;
#define HEADER \
"Begin typing your text. ~q to abort, . or ** to end, ~h for help.\n"+\
"-----------------------------------------------------------------\n"
private string* buf;
private int already_editing;
private string client_fname;
private function client_func;
private string tmp_fname()
{
return "/tmp/edit_ob." + this_user()->query_userid();
}
private string * read_strings(string fname, int messages)
{
int size;
size = file_size(fname);
if ( messages )
{
if ( size == -2 )
write("File is a directory. Ignoring.\n");
else if ( size == -1 )
write("File not found.\n");
else if ( size == 0 )
write("File is empty.\n");
else
write("Ok.\n");
}
if ( size <= 0 )
return ({ });
return explode(read_file(fname), "\n");
}
varargs private string build_string(int flag)
{
switch (sizeof(buf))
{
case 0:
return (flag & 1) ? "**No text!\n" : "";
default:
if (flag & 2)
return "[" + (sizeof(buf)-15) + " lines not displayed, please trim (~e)]\n" + implode(buf[<15..], "\n") + "\n";
/* WARNING - falls through */
case 1..20:
return implode(buf, "\n") + "\n";
}
}
private void end_edit(int aborted)
{
mixed arg;
if ( client_fname )
{
rm(client_fname);
if ( !aborted )
{
write_file(client_fname, build_string(1));
arg = client_fname;
}
}
else if ( !aborted )
arg = buf;
/*
** Clear up this information before dispatching the callback. The
** callback may want to push new modal handlers or something.
*/
if( !already_editing && this_body() )
this_body()->clear_flag(F_IN_EDIT);
modal_pop();
evaluate(client_func, arg);
destruct();
}
private nomask void end_ed()
{
string tmp_file;
tmp_file = tmp_fname();
buf = read_strings(tmp_file, 0);
rm(tmp_file);
write("Continue editing file.\n");
}
private void handle_escape(string str)
{
string tmp;
string tmp_file;
switch ( str[1] )
{
case 'q':
write("Edit aborted.\n");
end_edit(1);
return;
case 'r':
if(wizardp(this_user()))
buf += read_strings(evaluate_path(str[3..]), 1);
return;
case 'w':
if(wizardp(this_user()))
{
tmp = build_string();
if(!write_file(evaluate_path(str[3..]),tmp))
write("Unable to write to file.\n");
else
write("Ok.\n");
}
return;
case 'h':
write(
"Help for editor:\n. or **\t\texit editor\n~q\t\tabort edit.\n~h\t\tthis help.\n"+
"~e\t\tenter line by line editor.\n~p\t\tdisplay edit buffer.\n");
if(wizardp(this_user()))
write("~w <file>\twrite buffer to specified file.\n~r <file>\tread file into buffer.\n");
write("\n\n");
return;
case 'p':
write(build_string() + "\n");
return;
case 'e':
tmp_file = tmp_fname();
write_file(tmp_file, build_string());
new(ED_SESSION)->begin_editing(tmp_file, !this_user()->query_privilege(),
(: end_ed :));
return;
}
}
private nomask void parse_edit(mixed str)
{
if(str == -1)
destruct(this_object());
if ( str[0] == '~' )
{
handle_escape(str);
return;
}
if ( str == "." || str == "**" )
{
end_edit(0);
return;
}
buf += ({ str });
}
private void begin_edit(string *text, function continuation)
{
if(this_body())
{
if ( this_body()->test_flag(F_IN_EDIT) )
{
already_editing = 1;
write("Warning! You are already marked as editing.\n");
}
else
this_body()->set_flag(F_IN_EDIT);
}
buf = text ? text : ({ });
client_func = continuation;
write(HEADER + build_string(2));
modal_push((: parse_edit :), ""); /* empty prompt */
}
void create(int kind, mixed text, function continuation)
{
set_privilege(1);
switch ( kind )
{
case 0: // blueprint
return;
case EDIT_TEXT:
if ( stringp(text) )
text = explode(text, "\n");
break;
case EDIT_FILE:
client_fname = text;
text = read_strings(text, 0);
break;
default:
error("Bad argument 2 to new(EDIT_OB, ...)\n");
}
begin_edit(text, continuation);
}