tmi2_fluffos_v2/
tmi2_fluffos_v2/bin/
tmi2_fluffos_v2/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/ChangeLog.old/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/Win32/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/simuls/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/clone/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/command/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/data/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/master/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/log/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/u/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/tmp/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/windows/
tmi2_fluffos_v2/lib/
tmi2_fluffos_v2/lib/adm/
tmi2_fluffos_v2/lib/adm/daemons/languages/
tmi2_fluffos_v2/lib/adm/daemons/network/I3/
tmi2_fluffos_v2/lib/adm/daemons/virtual/
tmi2_fluffos_v2/lib/adm/daemons/virtual/template/
tmi2_fluffos_v2/lib/adm/news/
tmi2_fluffos_v2/lib/adm/obj/
tmi2_fluffos_v2/lib/adm/obj/master/
tmi2_fluffos_v2/lib/adm/priv/
tmi2_fluffos_v2/lib/adm/shell/
tmi2_fluffos_v2/lib/adm/tmp/
tmi2_fluffos_v2/lib/cmds/
tmi2_fluffos_v2/lib/d/
tmi2_fluffos_v2/lib/d/Conf/
tmi2_fluffos_v2/lib/d/Conf/adm/
tmi2_fluffos_v2/lib/d/Conf/boards/
tmi2_fluffos_v2/lib/d/Conf/cmds/
tmi2_fluffos_v2/lib/d/Conf/data/
tmi2_fluffos_v2/lib/d/Conf/logs/
tmi2_fluffos_v2/lib/d/Conf/obj/
tmi2_fluffos_v2/lib/d/Conf/text/help/
tmi2_fluffos_v2/lib/d/Fooland/adm/
tmi2_fluffos_v2/lib/d/Fooland/data/
tmi2_fluffos_v2/lib/d/Fooland/data/attic/
tmi2_fluffos_v2/lib/d/Fooland/items/
tmi2_fluffos_v2/lib/d/TMI/
tmi2_fluffos_v2/lib/d/TMI/adm/
tmi2_fluffos_v2/lib/d/TMI/boards/
tmi2_fluffos_v2/lib/d/TMI/data/
tmi2_fluffos_v2/lib/d/TMI/rooms/
tmi2_fluffos_v2/lib/d/grid/
tmi2_fluffos_v2/lib/d/grid/adm/
tmi2_fluffos_v2/lib/d/grid/data/
tmi2_fluffos_v2/lib/d/std/
tmi2_fluffos_v2/lib/d/std/adm/
tmi2_fluffos_v2/lib/data/adm/
tmi2_fluffos_v2/lib/data/adm/daemons/
tmi2_fluffos_v2/lib/data/adm/daemons/doc_d/
tmi2_fluffos_v2/lib/data/adm/daemons/emoted/
tmi2_fluffos_v2/lib/data/adm/daemons/network/http/
tmi2_fluffos_v2/lib/data/adm/daemons/network/services/mail_q/
tmi2_fluffos_v2/lib/data/adm/daemons/network/smtp/
tmi2_fluffos_v2/lib/data/adm/daemons/news/archives/
tmi2_fluffos_v2/lib/data/attic/connection/
tmi2_fluffos_v2/lib/data/attic/user/
tmi2_fluffos_v2/lib/data/std/connection/b/
tmi2_fluffos_v2/lib/data/std/connection/l/
tmi2_fluffos_v2/lib/data/std/user/a/
tmi2_fluffos_v2/lib/data/std/user/b/
tmi2_fluffos_v2/lib/data/std/user/d/
tmi2_fluffos_v2/lib/data/std/user/f/
tmi2_fluffos_v2/lib/data/std/user/l/
tmi2_fluffos_v2/lib/data/std/user/x/
tmi2_fluffos_v2/lib/data/u/d/dm/working/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/smtp/
tmi2_fluffos_v2/lib/doc/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/interactive/
tmi2_fluffos_v2/lib/doc/driverdoc/concepts/
tmi2_fluffos_v2/lib/doc/driverdoc/driver/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/arrays/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/buffers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/compile/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/ed/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/filesystem/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/floats/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/functions/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/general/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/mappings/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/numbers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/parsing/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/constructs/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/preprocessor/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/types/
tmi2_fluffos_v2/lib/doc/driverdoc/platforms/
tmi2_fluffos_v2/lib/doc/mudlib/
tmi2_fluffos_v2/lib/ftp/
tmi2_fluffos_v2/lib/include/driver/
tmi2_fluffos_v2/lib/log/
tmi2_fluffos_v2/lib/log/driver/
tmi2_fluffos_v2/lib/obj/net/
tmi2_fluffos_v2/lib/obj/shells/
tmi2_fluffos_v2/lib/obj/tools/
tmi2_fluffos_v2/lib/std/adt/
tmi2_fluffos_v2/lib/std/board/
tmi2_fluffos_v2/lib/std/body/
tmi2_fluffos_v2/lib/std/fun/
tmi2_fluffos_v2/lib/std/living/
tmi2_fluffos_v2/lib/std/object/
tmi2_fluffos_v2/lib/std/shop/
tmi2_fluffos_v2/lib/std/socket/
tmi2_fluffos_v2/lib/std/user/
tmi2_fluffos_v2/lib/std/virtual/
tmi2_fluffos_v2/lib/student/
tmi2_fluffos_v2/lib/student/kalypso/
tmi2_fluffos_v2/lib/student/kalypso/armor/
tmi2_fluffos_v2/lib/student/kalypso/rooms/
tmi2_fluffos_v2/lib/student/kalypso/weapons/
tmi2_fluffos_v2/lib/u/l/leto/
tmi2_fluffos_v2/lib/u/l/leto/cmds/
tmi2_fluffos_v2/lib/www/errors/
tmi2_fluffos_v2/lib/www/gateways/
tmi2_fluffos_v2/lib/www/images/
tmi2_fluffos_v2/old/
tmi2_fluffos_v2/win32/
/*
 * 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;
}