/* 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); }