/* * Robocoder's Scrollback Shell * * Copyright 1995 by Anthon Pang, Omni Communications * PO Box 18121, RPO Kerrisdale * 2225 W 41st Avenue * Vancouver, BC * Canada V6M 4L3 * * Permission is granted to TMI-2 and Earth to distribute this with their * respective libs. * * Email: apang@mindlink.net * * Beware young adventurer...you are about to visit a realm not entirely * unlike your own. But many a skilled adventurer has walked this path. * It is long and winding, and danger lurks in every shadow. Be afraid, * for fear will guide you. * * Your adventure...begins now. */ #include <mudlib.h> #include <driver/origin.h> /* * simul_efun overrides */ #include "/adm/simul_efun/say.c" #include "/adm/simul_efun/tell_object.c" inherit OBJECT; /* * defaults to using LINES setting for size of scrollback buffer...but * you can override this with SCROLLSIZE env var */ #define DEFAULT_SCROLLBACK_SIZE 20 #define DEFAULT_LINES 20 int SCROLLSIZE; /* size */ /* * rely on mudlib to provide useful message classes...user must * have set SCROLLMASK env var to enable the filter; * example: setenv SCROLLMASK snoop|shout|gwiz|gtell */ #define DEFAULT_SCROLL_MASK "prompt|snoop" string *SCROLLMASK; /* mask */ object OWNER; /* authorized owner of this shell */ mapping SBUFS; /* scroll back buffers...a mapping of arrays */ void pager(string s, string *arr, int i); nomask static void initialize() { string tmp; OWNER = this_player(); SBUFS = ([ ]); SCROLLSIZE = OWNER->query_env("SCROLLSIZE"); if (stringp(SCROLLSIZE)) SCROLLSIZE = atoi(SCROLLSIZE); if (!SCROLLSIZE) { SCROLLSIZE = OWNER->query_env("LINES"); if (stringp(SCROLLSIZE)) SCROLLSIZE = atoi(SCROLLSIZE); if (!SCROLLSIZE) { SCROLLSIZE = DEFAULT_SCROLLBACK_SIZE; } } tmp = OWNER->query_env("SCROLLMASK"); if (!tmp || tmp == "") tmp = DEFAULT_SCROLL_MASK; tmp = replace_string(tmp, " ", ""); /* no spaces */ tmp = replace_string(tmp, ",", "|"); /* change commas to bar delims */ SCROLLMASK = explode(tmp, "|"); /* array of classes to ignore */ } void create() { if (origin() == ORIGIN_CALL_OTHER) return; set("id", ({ "shell", "sb", "scrollback" })); set("short", "A scrollback buffer"); set("long", "Robocoder's Scrollback Buffer\n"); set("prevent_drop", 1); initialize(); } mixed query_auto_load() { return 1; } int clean_up() { return 1; } /* * Personally, I don't mind add_action()'s...in this case, it means * I don't have to write separate command files */ void init() { if (environment() && this_player() == environment() && interactive(environment())) { add_action("sb", "sb"); add_action("help", "help"); } else { remove(); } } nomask int sb(string arg) { string *mapkeys; mixed *arr; int i; /* This seems silly, since it's called from this_player() * and this_player != this_object() --- Leto if (previous_object() != this_object()) { return 0; } */ if (!arg || arg == "") { /* display list of buffers */ mapkeys = keys(SBUFS); if (i = sizeof(mapkeys)) { tell_object(OWNER, "Scrollback Buffers:\n"); while (i--) { arr = SBUFS[mapkeys[i]]; tell_object(OWNER, sprintf("\t%s [%d]\n", mapkeys[i], arr[1] ? arr[0] - 2 : sizeof(arr) - 2)); } } else { tell_object(OWNER, "No scrollback buffers available.\n"); } } else if (arg == "-reset") { /* reset...using current env vars */ initialize(); tell_object(OWNER, "Scrollback Reset Complete.\n"); } else { /* display named buffer */ if (undefinedp(SBUFS[arg])) { write(sprintf("Buffer '%s' is empty.\n", arg)); } else { arr = SBUFS[arg]; if (arr[1]) pager("", arr[2..arr[0]-1], 0); else pager("", arr[arr[0]..<1] + arr[2..arr[0]-1], 0); } } return 1; } /* * use our own pager to prevent scrollback dump from being logged =) */ void pager(string s, string *arr, int i) { int l; if (s != "" && s[0] == '?') { tell_object(OWNER, @ENDHELP *** More (Jr.) *** ? - for help < - to go to beginning > - to go to end b - to go back to previous page y, CR - to display next page n, q, x - to quit ENDHELP ); } else { l = OWNER->query_env("LINES"); if (stringp(l)) l = atoi(l); if (!l) l = DEFAULT_LINES; if (s == "" || s[0] == 'y') { if (sizeof(arr) - i < l) l = sizeof(arr) - i; while (l--) tell_object(OWNER, arr[i++]); } else if (s[0] == '<') { i = 0; if (sizeof(arr) - i < l) l = sizeof(arr) - i; while (l--) tell_object(OWNER, arr[i++]); } else if (s[0] == 'b') { i -= l; if (i < 0) i = 0; if (sizeof(arr) - i < l) l = sizeof(arr) - i; while (l--) tell_object(OWNER, arr[i++]); } else if (s[0] == '>') { i = sizeof(arr) - l + 1; if (sizeof(arr) - i < l) l = sizeof(arr) - i; while (--l) tell_object(OWNER, arr[i++]); tell_object(OWNER, "(More) * End of File *\n"); input_to("pager", arr, i); return; } else if (s[0] == 'n' || s[0] == 'q' || s[0] == 'x') { return; } else { tell_object(OWNER, "(More) unrecognized command\n"); input_to("pager", arr, i); return; } } if (i != sizeof(arr)) { tell_object(OWNER, "(More): \n"); input_to("pager", arr, i); } } int receive_message(mixed Class, string msg) { mixed *arr; if (intp(Class)) Class = "" + Class; if (member_array(Class, SCROLLMASK) == -1) { /* * if not in filter list, save to buffer; * allocate buffer, if necessary... */ if (undefinedp(SBUFS[Class])) { SBUFS[Class] = arr = allocate(2 + SCROLLSIZE); arr[0] = 2; arr[1] = 1; /* not full */ } else { arr = SBUFS[Class]; } arr[arr[0]] = "> " + msg; /* * index manipulation */ if ((++arr[0]) == SCROLLSIZE + 2) { arr[0] = 2; arr[1] = 0; /* full */ } } tell_object(OWNER, msg); } int help(string s) { if (s == "sb" || s == "scrollback") { write( @ENDTEXT Robocoder's Scrollback Shell v1.0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Syntax: sb [<Class> | -reset] Description: The scrollback shell allows the user to maintain a history of received messages. It isn't a true scrollback buffer, because the history is simply piped back to the user via `more'. Arguments: -reset - reset shell <Class> - name or id of a message Class Environment variables: SCROLLSIZE - the maximum number of messages to keep in a buffer (this applies to all scrollback buffers) Example: setenv SCROLLSIZE 20 SCROLLMASK - a mask of buffers to filter out Example: setenv SCROLLMASK prompt|snoop|gwiz|gtell ENDTEXT ); return 1; } return 0; }