dsI/bin/
dsI/extra/creremote/
dsI/extra/mingw/
dsI/extra/wolfpaw/
dsI/fluffos-2.7-ds2.018/
dsI/fluffos-2.7-ds2.018/ChangeLog.old/
dsI/fluffos-2.7-ds2.018/Win32/
dsI/fluffos-2.7-ds2.018/compat/
dsI/fluffos-2.7-ds2.018/compat/simuls/
dsI/fluffos-2.7-ds2.018/testsuite/
dsI/fluffos-2.7-ds2.018/testsuite/clone/
dsI/fluffos-2.7-ds2.018/testsuite/command/
dsI/fluffos-2.7-ds2.018/testsuite/data/
dsI/fluffos-2.7-ds2.018/testsuite/etc/
dsI/fluffos-2.7-ds2.018/testsuite/include/
dsI/fluffos-2.7-ds2.018/testsuite/inherit/
dsI/fluffos-2.7-ds2.018/testsuite/inherit/master/
dsI/fluffos-2.7-ds2.018/testsuite/log/
dsI/fluffos-2.7-ds2.018/testsuite/single/
dsI/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
dsI/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
dsI/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
dsI/fluffos-2.7-ds2.018/testsuite/u/
dsI/fluffos-2.7-ds2.018/tmp/
dsI/lib/cfg/
dsI/lib/cmds/common/
dsI/lib/cmds/creators/include/
dsI/lib/cmds/creators/include/SCCS/
dsI/lib/daemon/services/
dsI/lib/doc/
dsI/lib/domains/Ylsrim/
dsI/lib/domains/Ylsrim/adm/
dsI/lib/domains/Ylsrim/armour/
dsI/lib/domains/Ylsrim/broken/
dsI/lib/domains/Ylsrim/fish/
dsI/lib/domains/Ylsrim/meal/
dsI/lib/domains/Ylsrim/npc/
dsI/lib/domains/Ylsrim/virtual/
dsI/lib/domains/Ylsrim/weapon/
dsI/lib/domains/default/creator/
dsI/lib/domains/default/etc/
dsI/lib/domains/default/room/
dsI/lib/lib/comp/
dsI/lib/lib/lvs/
dsI/lib/lib/user/
dsI/lib/lib/virtual/
dsI/lib/obj/
dsI/lib/obj/include/
dsI/lib/realms/
dsI/lib/save/kills/a/
dsI/lib/save/kills/b/
dsI/lib/save/kills/f/
dsI/lib/save/kills/m/
dsI/lib/save/kills/q/
dsI/lib/save/kills/r/
dsI/lib/secure/cfg/
dsI/lib/secure/cfg/classes/
dsI/lib/secure/cfg/races/SCCS/
dsI/lib/secure/cmds/creators/include/
dsI/lib/secure/cmds/players/
dsI/lib/secure/cmds/players/include/
dsI/lib/secure/daemon/include/
dsI/lib/secure/lib/
dsI/lib/secure/lib/include/
dsI/lib/secure/lib/net/
dsI/lib/secure/lib/net/include/
dsI/lib/secure/lib/std/
dsI/lib/secure/obj/
dsI/lib/secure/obj/include/
dsI/lib/secure/save/
dsI/lib/spells/
dsI/lib/verbs/admins/include/
dsI/lib/verbs/common/
dsI/lib/verbs/common/include/
dsI/lib/verbs/creators/
dsI/lib/verbs/creators/include/
dsI/lib/verbs/players/include/SCCS/
dsI/lib/verbs/rooms/
dsI/lib/verbs/rooms/include/
dsI/lib/www/
dsI/v22.2b14/
dsI/win32/
/*    /lib/obj/post.c  
 *    from Foundation II  
 *    the user front end to the IIPS version 3.1  
 *    created by Descartes of Borg 940509  
 */  
  
#include <lib.h>    
#include <daemons.h>    
#include <iips.h>
#include "include/post.h"
    
inherit LIB_ITEM;    
    
static private int __Screen, __Lines, __NumLetters;   
static private int __Begin,__Current,__CommandLine,__FromMenu,__IncomingFlag;
static private string __Folder, __Owner, __CurrentMenu;    
static private mapping __Options, __TmpPost, __ChangedOptions;    
static private int *__Delete; 
static private string *__FwdRply;    
static private mapping *__BoxInfo, *__PostalOptions;    
    
void create() {    
    item::create();    
    SetKeyName("post box");    
    SetId( ({ "post box", "box", POSTAL_ID }) );    
    SetAdjectives( ({ "post", "a", "imaginary" }) );    
    SetShort("a post box");    
    SetLong("A post box.");    
    SetProperty("no steal", 1);    
    SetInvis(1);    
    SetMass(0);    
    SetValue(0);    
    SetPreventGet( (: Destruct :) );    
    SetPreventDrop( (: Destruct :) );    
    SetPreventPut( (: Destruct :) );    
    __PostalOptions = ({     
      ([ "key":"askcc", "value":({"N","Y"}), "desc":"Prompt for cc when "    
        "sending mail:" ]),     
      (["key":"quit", "value":({"N","Y"}), "desc":"Confirm quit from mail:"]),
      (["key":"metoo", "value":({"N","Y"}),"desc":"Send mail to yourself "
         "with you in alias:"]),
      (["key":"delete", "value":({"N","Y"}), "desc":"Confirm deletion of "    
        "letters:" ]),    
      (["key":"notify", "value":({"N","Y"}), "desc":"Notify me when new mail "    
        "is received:" ]),    
      ([ "key":"message", "value":"New mail has arrived from $N\n"    
        "Subject: $S", "desc":"Mail message when notify occurs:" ]),    
      ([ "key": "content", "value":({"message only", "header and message"}),    
        "desc":"Content of letters when reading mail:" ]),    
      ([ "key":"forward", "value":"none", "desc":"Address to forward "    
        "incoming mail to:" ]),    
      ([ "key":"sig file", "value":"none", "desc":"Signature file:" ]),    
      ([ "key":"commands", "value":({"N","Y"}), "desc":"Exclude command "    
        "listing from menus:" ]),    
      ([ "key":"read", "value":({"N","Y"}), "desc":"Read letter when you make "    
        "it current:" ])    
      });    
}    
    
void init() {    
    item::init();    
    if(this_player() != environment(this_object())) {    
        this_object()->eventDestruct();    
        return;    
    }    
    __Options = (mapping)OPTIONS_D->query_options(__Owner =
      (string)this_player()->GetKeyName());
    if(!(__Lines = to_int((string)this_player()->GetEnvVar("LINES"))))   
      __Lines = 24;   
    if(!(__Screen = to_int((string)this_player()->GetEnvVar("SCREEN"))))   
      __Screen = 80;    
    if((__NumLetters = __Lines - 10) < 0) __NumLetters = 5;   
}    
    
static private void restore_box(string folder) {    
    int x;    
    
    if(!pointerp(__BoxInfo=(mapping *)FOLDERS_D->query_box_info(__Owner, folder)))    
      __BoxInfo = ({});    
    __Folder = folder;    
    __TmpPost = ([]);    
    __Delete = allocate(x = sizeof(__BoxInfo));    
    if(!x) __Current = -1;    
    else __Current = 0;    
    __Begin = 0;    
}    
    
static private void save_box() {    
    FOLDERS_D->delete_posts(__Owner, __Folder, __Delete);    
}    

static private void destruct_box(string str) {
    message("mail", str, this_player());
    this_object()->eventDestruct();
}
    
static private int valid_folder(string str) {    
    int i;

    if(str == "" || !str) return 0;    
    if(str[0] != '=' && str != "new") return 0;    
    i = strlen(str = lower_case(str));    
    while(i-- > 1) if(str[i] < 'a' || str[i] > 'z') return 0;    
    return 1;    
}    
     
static private int set_current(mixed val) {
    int i;

    if(intp(val)) __Current = val;
    else {
        i = sizeof(__BoxInfo);
        while(i--) {
            if(__BoxInfo[i]["id"] == val) {
                __Current = i;
                break;
            }
        }
    }
    if(__Current < __Begin) __Begin = __Current;
    else if(__Current >= __Begin+10) __Begin = __Current-9;
    return __Current;
}

void start_post(string str) {    
    string *args;
    int i, maxi;;

    if(str && str != "") {    
        maxi = sizeof(args = explode(str, " "));    
        if(args[0][0] == '-' && strlen(args[0]) == 2) {    
            switch(args[0][1]) {    
                case 'r':    
                    restore_box("new");    
                    index_cmd("");    
                    return;    
                case 'f':    
                    if(maxi < 2) {    
                        message("mail", "No folder named.", this_player());    
                        this_object()->eventDestruct();    
                        return;    
                    }    
                    else if(maxi>2 || (!valid_folder(args[1]) &&     
                      args[1] != "new")) {    
                        message("mail", "Illegal folder name.", this_player());    
                        this_object()->eventDestruct();    
                        return;    
                    }    
                    else {    
                        restore_box(args[1]);    
                        indices(0);    
                        return;    
                    }    
                case 'a':    
                    __CommandLine = 1;    
                    if(maxi < 2) index_cmd("a");    
                    else index_cmd(implode(args[1..maxi-1], " "));    
                    return;    
            }    
        }    
        __CommandLine = 1; 
        __TmpPost = ([]); 
        __FwdRply = 0;    
        send_letter(args);    
        return;    
    }    
    restore_box("new");
    indices(0);    
}    
    
static private void primary_prompt() {     
    message("prompt", "\nCommand: ", this_player());    
}    
    
static private void secondary_prompt() {    
    message("prompt", sprintf("\nCommand (%s for %s menu): ",   
      __CurrentMenu[0..0],  __CurrentMenu),    
      this_player());    
}    
  
varargs static private void postal_error(string str, string ind, mixed args) {
    message("mail", sprintf("\n%%^RED%%^%s", str), this_player());   
    primary_prompt();  
    if(args) input_to(sprintf("%s_cmd", (ind ? ind : __CurrentMenu)), args);  
    else input_to(sprintf("%s_cmd", (ind ? ind : __CurrentMenu)));  
  }  
  
varargs static private void postal_success(string str,string ind,mixed args) {
    message("mail", sprintf("\n%%^GREEN%%^%s", str), this_player());  
    secondary_prompt();  
    if(args) input_to(sprintf("%s_cmd", (ind ? ind : __CurrentMenu)), args);  
    else input_to(sprintf("%s_cmd", (ind ? ind : __CurrentMenu)));  
  }  
  
varargs static void indices(int x, string str) {    
    int i, maxi;    
    
    __CurrentMenu = "index";  
    if(str && str != "") {    
        index_cmd(str);    
        return;    
    }    
    __Begin = x;    
    __FromMenu = 1;    
    message("mail", "\n%^INITTERM%^Imaginary Intermud Postal Service "    
      "(IIPS) 3.1     Descartes of Borg 1993, 1994", this_player());    
    message("mail", sprintf("\n%%^CYAN%%^%s", center(sprintf("Folder is %s "
      "with %s.\n",__Folder,consolidate(maxi=sizeof(__BoxInfo),"one letter")),
      __Screen)), this_player());
    if(!maxi) __Current = -1;    
    else for(i=x; i<maxi && i < x+__NumLetters; i++)    
      message("mail", sprintf("%s%s) %s %s %s %s %s",    
        (__Current == i ? "%^YELLOW%^BOLD%^*" : " "),    
      ((i+1 > 99) ? (""+(i+1)) : ((i+1 > 9) ? (" "+(i+1)) : ("  "+(i+1)))),
        (__BoxInfo[i]["read"] ? " " : "N"),    
        (__Delete[i] ? "D" : " "),    
        arrange_string(capitalize(__BoxInfo[i]["from"]), 20),    
        arrange_string(postal_time(__BoxInfo[i]["date"]), 7),    
        arrange_string(__BoxInfo[i]["subject"], __Screen-40)), this_player());    
    index_menu();    
}    
    
varargs static void aliases(string str) {  
    __CurrentMenu = "alias";    
    if(str && str != "") {    
        alias_cmd(str);    
        return;    
    }    
    message("mail", "\n%^INITTERM%^Imaginary Intermud Postal Service "    
      "(IIPS) 3.1     Descartes of Borg 1993, 1994", this_player());    
    message("mail", sprintf("\n%%^CYAN%%^%s", center(sprintf("%s and "
      "Personal Alias Menu", mud_name()))), this_player());
    message("mail", sprintf("\n%s",    
      format_page(keys((mapping)OPTIONS_D->query_groups(__Owner) +    
      (mapping)LOCALPOST_D->query_mud_groups()),__Screen/20)),this_player());
    alias_menu();    
}    
    
varargs static void options(string str) {    
    string tmp;    
    int i, maxi;    
    
    __CurrentMenu = "option";  
    if(str && str != "") {    
        option_cmd(str);    
        return;    
    }    
    message("mail", "\n%^INITTERM%^Imaginary Intermud Postal Service "    
      "(IIPS) 3.1     Descartes of Borg 1993, 1994", this_player());    
    message("mail", sprintf("\n%%^CYAN%%^%s", center("IIPS 3.1 Options Menu\n",   
      __Screen)), this_player());    
    maxi = sizeof(__PostalOptions);    
    for(i=0; i<maxi; i++) {    
        if(pointerp(__PostalOptions[i]["value"]))    
          tmp = __PostalOptions[i]["value"][__Options[__PostalOptions[i]["key"]]];    
        else if(!(tmp = __Options[__PostalOptions[i]["key"]]))    
          tmp = __PostalOptions[i]["value"];    
        message("mail", sprintf("%s) %-45s %s", (i+1>9) ? (i+1)+"" :" "+(i+1),
          __PostalOptions[i]["desc"], tmp),    
          this_player());    
	}    
    option_menu();    
  }    
    
static private void help(string arg, string ind) {    
    if(!ind) ind = __CurrentMenu;    
    if(arg && arg != "") {    
        help_cmd(arg, ind);    
        return;    
      }    
    message("mail", "\n%^INITTERM%^Imaginary Intermud Postal Service "    
      "(IIPS) 3.1     Descartes of Borg 1993, 1994", this_player());    
    message("mail",sprintf("\n%%^CYAN%%^%s",center("IIPS 3.1 Help Menu",   
      __Screen)), this_player());    
    help_menu(ind);    
}    
    
static private void index_menu() {    
    if(__Options["commands"]) {
        primary_prompt();
        input_to("index_cmd");
        return;
    }
    message("mail", "\n"+center("a)lias menu, c)hange folder, d)elete, "    
      "f)orward, h)elp, m)ail,", __Screen), this_player());    
    message("mail", center("n)ext letter, o)ptions menu, p)revious "    
      "letter, q)uit, Q)uit without saving,", __Screen), this_player());    
    message("mail", center("s)ave to folder, S)ave to file, "    
      "u)ndelete", __Screen), this_player());    
    message("mail", center("<return> to read selected letter", __Screen), 
      this_player());
    primary_prompt();
    input_to("index_cmd");    
  }    
    
static private void alias_menu() {    
    if(__Options["commands"]) {
        primary_prompt();
        input_to("alias_cmd");
        return;
    }
    message("mail", center("d)elete from an alias, e)nter into an alias, "    
      "h)elp, i)ndex menu, ", __Screen), this_player());    
    message("mail", center("l)ist an alias, m)ake an alias, o)ptions menu, "
      "q)uit, Q)uit without saving, ", __Screen), this_player());    
    message("mail", center("r)emove an alias", __Screen),this_player());    
    primary_prompt();    
    input_to("alias_cmd");    
  }    
    
static private void option_menu() {    
    if(__Options["commands"]) {
        primary_prompt();
        input_to("option_cmd");
        return;
    }
    message("mail", "\n"+center("Enter the number of an option to "    
      "change it.", __Screen), this_player());    
    message("mail", center("a)lias menu, h)elp, i)ndex menu, "    
      "q)uit, Q)uit without saving,", __Screen), this_player());    
    message("mail", center("s)ave option changes", __Screen), this_player()); 
    primary_prompt();    
    input_to("option_cmd");    
}    
    
static private void help_menu(string ind) {  
    int i, maxi;

    message("help", "\n\n\tEnter one of the following to visit "  
      "another menu:", this_player());  
    message("help", center("a)lias menu, i)ndex menu, o)ptions menu",  
      __Screen), this_player());  
    message("help", "\n\tOr enter one of the following for detailed help:",  
      this_player());    
    switch(ind) {  
        case "index":  
            message("help", center("c)hange folder, d)elete, f)orward, "  
              "m)ail letter, n)ext letter,", __Screen), this_player());  
            message("help", center("p)revious letter, q)uit, "  
              "Q)uit without saving, r)eply,", __Screen), this_player());  
            message("help", center("s)ave to folder, S)ave to file,",  
              __Screen), this_player());  
            message("help", center("x) help from another menu, y) detailed "  
              "IIPS user manual", __Screen), this_player());  
            break;  
	case "alias":  
            message("help", center("d)elete from an alias, e)nter into "  
              "an alias, m)ake an alias, q)uit,", __Screen), this_player());  
            message("help", center("Q)uit without saving, r)emove "  
              "an alias,", __Screen), this_player());  
            message("help", center("x) help from another menu, y) detailed "  
              "IIPS user manual", __Screen), this_player());  
            break;  
	case "option":  
            for(i=0, maxi = sizeof(__PostalOptions); i<maxi;i++)  
              message("help", center(sprintf("%d) %s", (i+1),   
                __PostalOptions[i]["desc"]), __Screen), this_player());   
            message("help", sprintf("\n%s",center("Also: q)uit, Q)uit without " 
              "saving, s)ave option changes,", __Screen)), this_player());  
            message("help", center("x) help from another menu, y) detailed "  
              "IIPS user manual", __Screen), this_player());  
            break;  
        default:   
            postal_error("Invalid postal menu.");  
            return;  
    }  
    primary_prompt();    
    input_to("help_cmd", ind);    
}  
    
static void index_cmd(string str) {    
    string cmd, args;    
    string *tmp;    
    int x;    
    
    __CurrentMenu = "index";    
    if(__IncomingFlag) {    
        __IncomingFlag = 0;  
        postal_error("New mail has arrived!\nCommand Ignored.");  
        return;    
    }    
    if(str == "" || !str) {    
        if(__Current < 0 || __Current >= sizeof(__BoxInfo)) {    
            postal_error("No current letter set.");  
            return;    
         }    
        if(__FromMenu) read_letter(__Current);    
        else if(set_current(__Current+1) < sizeof(__BoxInfo))
          read_letter(__Current);
        else read_letter(set_current(__Current - 1));
        return;    
      }    
    if(sscanf(str, "%d", x) && x) {
        if(x>0 && x <= sizeof(__BoxInfo)) {    
            if(__Options["read"]) read_letter(set_current(x-1));    
            else {    
                set_current(x-1);
		indices(__Begin);
	      }    
	  }    
        else postal_error("Invalid letter number.");  
        return;    
      }    
    if(!sizeof(tmp = explode(str, " "))) cmd = "";
    else cmd = tmp[0][0..0];
    if(sizeof(tmp) > 1) args = implode(tmp = tmp[1..sizeof(tmp)-1], " ");    
    else {
        args = "";
        tmp = ({});
    }
    switch(cmd) {    
        case "a": aliases(args); return;    
        case "c": change_folder(args); return;    
        case "d": case "u": delete_letter(cmd, args); return;    
        case "f": forward_letter(args, 0); return;    
        case "h": help(args, "index"); return;    
        case "i":     
            indices(__Current < __Begin+__NumLetters ? __Begin :    
              __Current-(__NumLetters-1), args);    
            return;    
        case "m": 
            __FwdRply = 0; 
            __TmpPost = ([]);  
            send_letter(tmp);  
            return;    
        case "n": index_cmd(""+(__Current+2)); return;    
        case "o": options(args); return;    
        case "p": index_cmd(""+(__Current)); return;    
        case "q": case "Q": quit_box(cmd); return;    
        case "r": reply(args); return;    
        case "s": case "S": save_letter(cmd, args); return;    
        default:  
            postal_error("Invalid postal command.");  
            return;    
    }    
}    
    
static void alias_cmd(string str) {    
    string cmd, args;    
    string *tmp;    
    
    __CurrentMenu = "alias";    
    if(str == "" || !str) {
        if(__CommandLine) destruct_box("Invalid alias command.");
        else postal_error("Invalid alias command.");  
        return;    
    }    
    cmd = (tmp = explode(str, " "))[0][0..0];    
    if(sizeof(tmp) > 1) args = implode(tmp[1..sizeof(tmp)-1], " ");    
    else args = "";    
    switch(cmd) {    
        case "a": aliases(args); return;
        case "d": case "e": alias_members(cmd, args); return;    
        case "m": case "r": alias_creation(cmd, args); return;    
        case "h": help(args, "alias"); return;    
        case "i":     
            indices(__Current < __Begin+__NumLetters ? __Begin :    
              __Current-(__NumLetters-1), args);    
            return;    
        case "l": list_alias(args); return;    
        case "o": options(args); return;    
        case "q": case "Q": quit_box(cmd); return;    
        case "s": aliases(args); return;    
        default: alias_cmd(0); return;    
    }    
}    
    
static void option_cmd(string str) {    
    string cmd, args;    
    string *tmp;    
    int x;    
    
    __CurrentMenu = "option";    
    if(str == "" || !str) {    
        postal_error("Invalid option command.");  
        return;    
    }    
    if(sscanf(str, "%d", x) && x) {
        change_option(x-1);    
        return;    
    }    
    cmd = (tmp = explode(str, " "))[0][0..0];    
    if(sizeof(tmp) > 1) args = implode(tmp[1..sizeof(tmp)-1], " ");    
    else args = "";    
    switch(cmd) {    
        case "a": aliases(args); return;    
        case "h": help(args, "option"); return;    
        case "i":     
            indices(__Current < __Begin+__NumLetters ? __Begin :    
              __Current-(__NumLetters-1), args);    
            return;    
        case "o": options(args); return;    
        case "q": case "Q": quit_box(cmd); return;    
        case "s": save_options(); return;    
        default: option_cmd(0); return;    
    }    
}    
    
static void help_cmd(string str, string ind) {    
    string tmp, file;  
    
    if(str == "" || !str) {    
        postal_error("Invalid help command.", "help", ind);  
        return;    
    }    
    switch(str = str[0..0]) {  
        case "a": aliases(""); return;
        case "i": indices(__Begin); return;
        case "o": options(""); return;
        case "q": case "Q": file = "quitting"; break;
    }
    if(!(tmp = read_file(DIR_POSTAL_HELP+"/"+file))) tmp = "Not found.\n";
    this_player()->eventPage(explode(tmp, "\n"), "help", (: end_help :)); 
}

void end_help() {
    secondary_prompt();
    input_to("help_cmd");
}

static private string postal_time(mixed val) {    
    string *parts;    
    string heure;    
    int x;    
    
    if(stringp(val) && x = to_int(val)) heure = ctime(time());    
    else if(stringp(val)) heure = val;    
    else heure = ctime(val);    
    parts = explode(replace_string(heure, "  ", " "), " ");    
    return sprintf("%s %s", parts[2], parts[1]);    
}    
    
static private string header(mapping borg) {    
    int x;

    return sprintf("%s from %%^GREEN%%^%s%%^RESET%%^\nTo: %s%s"    
      "Subject: %%^GREEN%%^%s",     
      (stringp(borg["date"]) ? ((x=to_int(borg["date"])) ? ctime(x) :     
        borg["date"]) : ctime(borg["date"])), capitalize(borg["from"]),    
      wrap(implode(borg["to"], ",  "), __Screen),    
      (sizeof(borg["cc"]) ? sprintf("Cc: %s",wrap(implode(borg["cc"], ",  "),
        __Screen)) : ""), borg["subject"]);    
}    
    
static void change_folder(string str) {    
    if(str == "" || !str) {    
        message("prompt", "Change to which folder? ", this_player());    
        input_to("get_folder");    
        return;    
      }    
    if(!valid_folder(str)) {    
        __FromMenu = 1;  
        postal_error("Invalid folder name.");  
        return;    
    }    
    if(!__Options["delete"] || member_array(1, __Delete) == -1)
      next_folder("", str);
    else {
        message("prompt", "Delete marked letters (default 'y')? ",
          this_player());
        input_to("next_folder", str);
    }
}

static void next_folder(string str, string folder) {
    if(str == "" || !str) str = "y";
    else str = (lower_case(str)[0..0]);
    if(str == "y") save_box();
    else if(str != "n") {
        message("prompt", "Invalid command.  Enter 'y' or 'n': ",this_player());
        input_to("next_folder");
    }
    restore_box(folder);    
    indices(__Begin);    
}    
    
static void get_folder(string str) {    
    if(str == "" || !str) {  
        __FromMenu = 1;  
        postal_error("Invalid folder name.");  
        return;    
    }    
    change_folder(str);    
}     
    
static private void delete_letter(string cmd, string args) {    
    int x, i, from, to, maxi;    
    
    if(args == "" || !args) {    
        from = __Current;    
        to = __Current;    
    }    
    else {
        sscanf(args, "%d-%d", from, to);
        if(!to) to = from-1;
        else to--;
        from--;
    }
    if(from > to || from < 0 || to >= sizeof(__BoxInfo)) {
        postal_error("Invalid letter range.");  
        return;    
    }        
    for(i= from; i < to+1; i++) {    
        if(cmd == "u" && !__Delete[i]) {    
            __FromMenu = 1;  
            postal_error(sprintf("Letter %d is not marked for deletion!",i+1));  
	}    
        else if(cmd == "d" && __Delete[i])  
          postal_error(sprintf("Letter %d is already marked for deletion!",i+1));  
        else if(!__BoxInfo[i]["read"] && cmd == "d" &&    
          !__Options["unread delete"]) {    
            message("mail", sprintf("\n%%^RED%%^Letter %d is still unread!",   
              i+1), this_player());  
            message("prompt","Delete it anyways (default n): ",this_player());   
            input_to("unread_delete", ({ i+1, to+1 }));    
            return;    
	}    
        else __Delete[i] = (cmd == "u" ? 0 : 1);    
    }    
    if(cmd == "d" && (args == "" || !args)) {    
        for(i=__Current, maxi = sizeof(__BoxInfo); i<maxi; i++) {    
            if(!__Delete[i]) {    
                set_current(i);
                if(!__FromMenu) {    
                    read_letter(__Current);   
                    return;    
		}    
                else {    
                    indices(__Current < __Begin+__NumLetters ? __Begin :    
                      __Current-(__NumLetters-1));    
                    return;    
		}    
	    }    
	}    
    }    
    if(__FromMenu) {    
        indices(__Current < __Begin+__NumLetters ? __Begin :    
          __Current-(__NumLetters-1));    
        return;    
    }  
    if(to == from) postal_success(sprintf("Letter %d %s",from+1,  
      (cmd == "d" ? "marked for deletion" : "undeleted")));    
    else postal_error(sprintf("Letters %d through %d %s.",    
      (from+1), (to+1), (cmd == "d" ? "marked for deletion" : "undeleted")));  
}    
    
static void unread_delete(string str, int *milk) {    
    if(str == "" || !str) str = "y";    
    else str = lower_case(str[0..0]);    
    if(str == "y") __Delete[milk[0]-1] = 1;    
    if(milk[0] < milk[1]) {    
        delete_letter("d", milk[0]+"-"+milk[1]);    
        return;    
      }    
    __FromMenu = 1;    
    secondary_prompt();    
    input_to("index_cmd");    
}    
   
static private void quit_box(string cmd) {   
    int i;   
   
    if(__Options["quit"]) {   
        message("prompt", "Do you really wish to quit (default 'n')? ",    
          this_player());   
        input_to("confirm_quit", cmd);   
        return;   
      }   
    really_quit(cmd);   
  }   
   
static private void really_quit(string cmd) {   
    int i;

    if(cmd == "Q") {   
        message("mail", "\nExiting from IIPS without saving deletions.",   
          this_player());   
        this_object()->eventDestruct();   
        return;   
      }   
    if(!__Options["delete"]) {   
        save_box();   
        message("mail", "\nExiting from IIPS.", this_player());   
        this_object()->eventDestruct();   
        return;   
      }   
    i = sizeof(__Delete);   
    while(i--) {   
        if(__Delete[i]) {   
            message("prompt", "Delete marked letters (default 'y')? ",   
              this_player());   
            input_to("confirm_delete");   
            return;   
	  }   
      }   
    message("mail", "\nExiting from IIPS.",   
      this_player());   
    this_object()->eventDestruct();   
  }   
   
static void confirm_quit(string str, string cmd) {   
    if(str == "" || !str) str = "n";   
    else str = lower_case(str)[0..0];   
    if(str == "y") {
        really_quit(cmd);
        return;
    }
    else if(str == "n") {   
        indices(__Current < __Begin+__NumLetters ? __Begin :   
          __Current - (__Lines-1));   
        return;   
      }   
    message("prompt", "Answer 'y' or 'n': ", this_player());   
    input_to("confirm_quit", cmd);   
  }   
   
static void confirm_delete(string str) {   
    if(str == "" || !str) str = "y";   
    else str = lower_case(str)[0..0];   
    if(str == "y") {   
        save_box();   
        message("mail", "\nExiting from IIPS.", this_player());   
        this_object()->eventDestruct();   
        return;   
      }   
    else if(str == "n") {   
        message("mail", "\nMarked letters will remain undeleted.\n"   
          "Exiting from IIPS.", this_player());   
        this_object()->eventDestruct();   
        return;   
      }   
    message("prompt", "Answer 'y' or 'n': ", this_player());   
    input_to("confirm_delete");   
  }   
   
static private void save_letter(string cmd, string args) {   
    string *tmp;   
    string folder;   
    int letter, i, maxi;   
   
    if(args && args != "") {   
        if(sizeof(tmp = explode(args, " ")) == 2) {   
            if(!sscanf(tmp[0], "%d", letter) || !letter) {
                sscanf(tmp[1], "%d", letter);
                folder = tmp[0];   
	      }   
            else folder = tmp[1];   
	  }   
        else if(!sscanf(args, "%d", letter) || !letter) folder = args;
        else folder = args;   
      }   
    else {   
        folder = 0;   
        letter = 0;   
      }   
    if(!letter) letter = __Current;   
    else letter--;   
    if(!folder) {   
        if(cmd == "S") message("prompt","Save to which file? ",this_player());   
        else message("prompt", sprintf("Save to which folder (default %s)? ",   
          sprintf("=%s", convert_name(__BoxInfo[letter]["from"]))),   
          this_player());   
        input_to("get_save_location", ({ letter, cmd }));   
        return;   
      }   
    if(cmd == "s") {   
        if(!valid_folder(folder)) {   
            postal_error("Invalid folder name.");  
            return;   
	}   
        FOLDERS_D->add_post(__Owner, folder, __BoxInfo[letter]);   
        message("mail", "\nLetter saved.", this_player());   
        set_current(letter);
        __Delete[__Current] = 1;   
    }   
    else if(cmd == "S") {   
        folder = absolute_path((string)this_player()->get_path(), folder);   
        if(!creatorp(this_player()) ||  
          !((int)master()->valid_write(folder, this_player()))) {   
            postal_error("Access denied.");  
            return;   
        }   
        write_file(folder,   
          (string)LETTERS_D->query_letter(__BoxInfo[letter]["id"]));   
        message("mail", sprintf("Letter saved to %s.", folder),    
          this_player());   
      set_current(letter);
        __Delete[__Current] = 1;   
      }   
    if(!__FromMenu)    
        for(i=__Current, maxi = sizeof(__BoxInfo); i<maxi; i++) {   
            if(!__Delete[i]) {   
                read_letter(__Current);   
                return;   
	      }   
	  }   
    secondary_prompt();
    input_to("index_cmd");
  }   
 
static void get_save_location(string str, mixed *vals) {   
    if(str == "" || !str) {   
        if(vals[1] == "s")   
          str = sprintf("=%s", convert_name(__BoxInfo[vals[0]]["from"]));   
        else {  
            postal_error("Invalid file name.");  
            return;   
        }   
    }   
    save_letter(vals[1], sprintf("%d %s", vals[0]+1, str));
}   
   
static private void read_letter(int x) {   
    string tmp;   
   
    if(__Options["content"])
      message("Nmail", sprintf("\n%%^INITTERM%%^Letter %d%s\n", (x+1),   
        (__Delete[x] ? " [DELETED]:" : ":")), this_player());   
    else message("Nmail", "\n%^INITTERM%^", this_player());
    if(__Options["content"]) tmp = header(__BoxInfo[x])+"\n";
    else tmp = "";
    tmp+=sprintf("\n%s\n",(string)LETTERS_D->query_letter(__BoxInfo[x]["id"]));   
    if(!__BoxInfo[x]["read"]) FOLDERS_D->mark_read(__Owner, __Folder, x);
    __BoxInfo[x]["read"] = 1;   
    this_player()->eventPage(explode(tmp, "\n"), "mail", (: end_read :));   
}   
   
void end_read() {   
    __FromMenu = 0;   
    secondary_prompt();   
    input_to("index_cmd");   
}      
       
static private void alias_members(string cmd, string args) {   
    string *members, *old_members;   
    string grp;
   
    if(args == "" || !args) {   
        message("prompt", sprintf("%s which alias? ",    
          (cmd == "e" ? "Enter into" : "Delete from")), this_player());   
        input_to("get_alias", cmd);   
        return;   
      }   
    if(sizeof(members = explode(args, " ")) == 1) {   
        message("prompt", sprintf("%s which members? ",    
          (cmd == "e" ? "Enter" : "Delete")), this_player());   
        input_to("get_members", ({ cmd, args }));   
        return;   
      }   
    if(!sizeof(members -= ({ grp =  members[0] }))) { 
        if(__CommandLine) destruct_box("Invalid alias member.");
        else postal_error("Invalid alias member.");  
        return;   
    }   
    if(user_exists(grp = lower_case(grp)) ||    
      (string *)LOCALPOST_D->query_mud_group(grp)) {   
        if(__CommandLine) destruct_box("Invalid alias.");
        else postal_error("Invalid alias.");  
        return;   
    }   
    if(!(old_members = (string *)OPTIONS_D->query_group(__Owner, grp))) {   
        if(__CommandLine) destruct_box("No such alias.");
        else postal_error(sprintf("No such alias %s.", grp));  
        return;   
    }   
    if(cmd == "e") members = distinct_array(members + old_members);   
    else if(!sizeof(members = old_members - members)) members = 0;   
    OPTIONS_D->set_group(__Owner, grp, members);   
    if(cmd == "d") {   
        if(!members)    
          message("mail", "\n%^GREEN%^All members deleted.", this_player());   
        else message("mail", "\n%^GREEN%^Members deleted from alias.",   
          this_player());   
      }   
    else message("mail", "\n%^GREEN%^Members entered into alias.",
      this_player());   
    if(__CommandLine) this_object()->eventDestruct();
    else {
        secondary_prompt();   
        input_to("alias_cmd");
    }   
  }   
       
static void get_alias(string str, string cmd) {   
    if(str == "" || !str) { 
        if(__CommandLine) destruct_box("Invalid alias name.");
        else postal_error("Invalid alias name.");  
        return;   
    }   
    alias_members(cmd, str);   
}   
   
static void get_members(string str, string *args) {   
    if(str == "" || !str) { 
        if(__CommandLine) destruct_box("Invalid alias members.");
        else postal_error("Invalid alias members.");  
        return;   
    }   
    alias_members(args[0], sprintf("%s %s", args[1], str));   
}   
   
static private void alias_creation(string cmd, string args) {  
    string *members;

    if(args == "" || !args) {  
        message("prompt", sprintf("Name of alias to %s: ",   
          (cmd == "m" ? "make" : "remove")), this_player());  
        input_to("get_alias_name", cmd);  
        return;  
    }  
    if(cmd == "m" && sizeof(members=explode(args=lower_case(args)," ")) == 1) {  
        message("prompt", "Enter members for the alias: ", this_player());  
        input_to("get_new_alias_members", ({ cmd, args }));  
        return;  
      }  
    else if(cmd == "m") members = members - ({ args = members[0] });  
    else members = 0;  
    if(cmd == "m" && (user_exists(args) || (mapping)LOCALPOST_D->query_mud_group(args))) {  
        if(__CommandLine) destruct_box("Invalid alias name.");
        else postal_error("Invalid alias name.");  
        return;  
    }  
    if(!((string *)OPTIONS_D->query_group(__Owner, args))) {  
        if(cmd == "r") { 
            if(__CommandLine) destruct_box("No such alias to remove.");
            else postal_error("No such alias to remove.");  
            return;  
	}  
    }  
    else if(cmd == "m") {  
        if(__CommandLine) destruct_box("Alias already exists.");
        else postal_error("That alias already exists.");  
        return;  
      }  
    OPTIONS_D->set_group(__Owner, args, members);  
    if(__CommandLine) 
      destruct_box(sprintf("Alias %s.", (cmd == "m" ? "made" : "removed")));
    else 
      postal_success(sprintf("Alias %s.", (cmd == "m" ? "made" : "removed")));
}           
  
static void get_alias_name(string str, string cmd) {  
    if(str == "" || !str) {
        if(__CommandLine) destruct_box("Invalid alias name.");
        else postal_error("Invalid alias name.");  
        return;  
    }  
    alias_creation(cmd, lower_case(str));  
}  
  
static void get_new_alias_members(string str, string *args) {  
    if(str == "" || !str) { 
        if(__CommandLine) destruct_box("Invalid alias members.");
        else postal_error("Invalid alias members.");  
        return;  
    }  
    alias_creation(args[0], sprintf("%s %s", args[1], lower_case(str)));  
}  
  
static private void list_alias(string str) {  
    string *who;  
  
    if(str == "" || !str) {
        if(__CommandLine) destruct_box("Invalid alias name.");
        else postal_error("Invalid alias name.");  
        return;  
    }  
    if(!(who = (string *)LOCALPOST_D->query_mud_group(str=lower_case(str)))) {  
        who = (string *)OPTIONS_D->query_group(__Owner, str);  
    }  
    if(!who) {
        if(__CommandLine) destruct_box("No such alias exists.");
        else postal_error("No such alias exists.");  
        return;  
    }  
    message("mail", "\n%^INITTERM%^"+center(sprintf("Alias: %s", str),  
      __Screen), this_player());  
    message("mail", "\n\n"+implode(who, ",   "), this_player());
    if(__CommandLine) this_object()->eventDestruct();
    else {
        secondary_prompt();  
        input_to("alias_cmd");
      }
}  
  
static private void save_options() {  
    string *cles;
    int i;

    if(!__ChangedOptions) {  
        postal_error("No options have changed.");  
        return;  
    }  
    i = sizeof(cles = keys(__ChangedOptions));
    while(i--) 
      OPTIONS_D->set_option(__Owner, cles[i], __ChangedOptions[cles[i]]);
    __Options = (mapping)OPTIONS_D->query_options(__Owner);  
    postal_success("New options now saved.");  
}  
  
static private void change_option(int x) {  
    if(pointerp(__PostalOptions[x]["value"])) {  
        message("mail", sprintf("%s\n\t0) %s\n\t1) %s", 
          __PostalOptions[x]["desc"],
        __PostalOptions[x]["value"][0], __PostalOptions[x]["value"][1]),  
        this_player());  
    }
    else message("mail", __PostalOptions[x]["desc"], this_player());  
    message("prompt", "Enter in a proper value: ", this_player());  
    input_to("really_change_option", 0, x);  
  }  
  
static void really_change_option(string str, int x) {  
    int y;

    if(!__ChangedOptions) __ChangedOptions = ([]);
    if(pointerp(__PostalOptions[x]["value"])) {  
        if((y=to_int(str)) != 0 && y != 1) {
            postal_error("Invalid value.  No option has changed.");  
            return;  
        }  
        __ChangedOptions[__PostalOptions[x]["key"]] = y;  
    }  
    else __ChangedOptions[__PostalOptions[x]["key"]] = (str == "" ? 0 : str);  
    postal_success("You must remember to save for this option to take effect.");  
}  
  
static private void reply(string str) {
    int x, i;

    if(str == "" || !str) x = __Current;
    else x = to_int(str)-1;
    if(x < 0 || x >= sizeof(__BoxInfo)) {
        postal_error("Invalid letter number for reply.");
        return;
      }
    set_current(x);
    __TmpPost = ([ "date":time(), "from": (string)this_player()->GetKeyName()]);
    if((__TmpPost["subject"] = __BoxInfo[x]["subject"])[0..2] != "Re:") 
      __TmpPost["subject"] = sprintf("Re: %s", __TmpPost["subject"]);
    message("prompt", "Include original text (default 'n'): ", this_player());
    input_to("get_reply_confirm");
  }

static void get_reply_confirm(string str) {
    if(str == "" || !str) str = "n";
    else str = lower_case(str)[0..0];
    if(str == "y") __FwdRply = ({ "r", query_reply_text() });
    else if(str != "n") {
        message("prompt", "Answer 'y' or 'n': ", this_player());
        input_to("get_reply_confirm");
        return;
      }
    else __FwdRply = 0;
    message("mail", sprintf("\n%s", center("Reply to: a)ll, c)c list and "
      "sender, s)ender only, t)o list and sender",__Screen)), this_player());
    message("prompt", "\nEnter choice (default 's'): ", this_player());
    input_to("get_reply_list");
}

static void get_reply_list(string str) {
    int i;

    if(str == "" || !str) str = "s";
    else str = lower_case(str)[0..0];
    __TmpPost["to"] = ({ convert_name(__BoxInfo[__Current]["from"]) });
    switch(str) {
        case "a": 
            __TmpPost["to"] += __BoxInfo[__Current]["to"];
            __TmpPost["cc"] = __BoxInfo[__Current]["cc"];
            break;
	case "c": __TmpPost["cc"] = __BoxInfo[i]["cc"]; break;
	case "s": __TmpPost["cc"] = ({}); break;
	case "t":
            __TmpPost["to"] += __BoxInfo[__Current]["to"];
            __TmpPost["cc"] = ({});
            break;
	default:
            message("prompt","Invalid choice.  Choose again: ", this_player());
            input_to("get_reply_list");
            return;
	  }
    if(!__Options["askcc"]) get_cc("");
    else {
        message("prompt", "Copies to: ", this_player());
        input_to("get_cc");
    }  
}

static private string query_reply_text() {
    string tmp;

    tmp = (string)LETTERS_D->query_letter(__BoxInfo[__Current]["id"]);
    return sprintf("\n>%s\n", replace_string(tmp, "\n", "\n>"));
}

static private void forward_letter(string str, int flag) {
    string *args;
    int i, x;

    if(str == "" || !str) {
        message("prompt", "To: ", this_player());
        input_to("get_forward_list");
        return;
      }
    i = sizeof(args = explode(lower_case(str), " "));
    if(!flag) {
        while(i--) if(sscanf(args[i], "%d", x) && x) break;
        if(!x) x = __Current;
        else {
            x--;
            if( !i ) {
                if(sizeof(args) == 1) args = ({});
                else args = args[1..];
            }
            else if( i == sizeof(args)) {
                args = args[0..<2];
            }
            else if(sizeof(args) == 1)
              args = ({});
            else args = args[0..(i-1)] + args[(i+1)..];
        }
        if(x < 0 || x > sizeof(__BoxInfo)) {
            postal_error("Letter number is out of range.");
            return;
        }
        if(!sizeof(args)) {
            forward_letter(0, 1);
            return;
	  }
      }
    set_current(x);
    __TmpPost["to"] = args;
    if((__TmpPost["subject"]=__BoxInfo[__Current]["subject"])[0..4] !=
      "(fwd)") __TmpPost["subject"] = sprintf("(fwd) %s",__TmpPost["subject"]);
    __TmpPost["from"] = (string)this_player()->GetKeyName();
    __TmpPost["date"] = time();
    message("prompt", "Comment on original letter (default 'n')? ", 
      this_player());
    input_to("confirm_comments");
  }

static void get_forward_list(string str) {
    if(str == "" || !str) {
        message("prompt","Invalid recipients.  Abort forward (default 'y')? ",
          this_player());
        input_to("confirm_forward_abort");
        return;
      }
    else forward_letter(str, 1);
  }

static void confirm_comments(string str) {
    if(str == "" || !str) str = "n";
    else str = lower_case(str)[0..0];
    if(str == "y") __FwdRply = ({ "f", query_forward_text() });
    else if(str == "n") {
        __FwdRply = 0;
        __TmpPost["message"] = query_forward_text();
      }
    else {
        message("prompt", "Answer 'y' or 'n': ", this_player());
        input_to("confirm_comments");
        return;
    }
    if(!__Options["askcc"]) get_cc("");
    else {
        message("prompt", "Copies to: ", this_player());
        input_to("get_cc");
    }
}

static private string query_forward_text() {
    string tmp;

    tmp = (string)LETTERS_D->query_letter(__BoxInfo[__Current]["id"]);
    tmp = ">"+replace_string(tmp, "\n", "\n>");
    return sprintf("Original letter sent by %s %s:\n%s\n%s\n", 
      capitalize(__BoxInfo[__Current]["from"]), 
      postal_time(__BoxInfo[__Current]["date"]),
      center("---  ---    Begin Forwarded Text    ---  ---"), tmp);
  }
 
static void confirm_forward_abort(string str) {
    if(str == "" || !str) str = "y";
    else str = lower_case(str)[0..0];
    if(str == "y") {
        postal_error("Forward aborted.");
        return;
      }
    else if(str != "n") {
        message("prompt", "Answer 'y' or 'n': ", this_player());
        input_to("confirm_forward_abort");
        return;
      }
    message("prompt", "To: ", this_player());
    input_to("get_forward_list");
  }

static private void send_letter(string *args) { 
    string flag, tmp; 
    int j, i, maxi, x; 
 
    if(!args || !sizeof(args)) { 
        message("prompt", "To: ", this_player()); 
        input_to("get_to"); 
        return; 
      } 
    __FwdRply = 0;
    __TmpPost = ([ "from": (string)this_player()->GetKeyName(),"date":time()]);
    for(i=0, maxi = sizeof(args); i<maxi; i++) { 
        if(args[i] == "" || !args[i]) continue; 
        if(!flag && i < maxi-1 && args[i][0] == '-' && strlen(args[i]) > 1) { 
            if(member_array(args[i][1..1], ({"c","s","i"})) == -1)  
              continue; 
            else flag = args[i][1..1]; 
        } 
        else if(!flag && args[i][0] == '\\' && strlen(args[i]) > 1)  
          args[i] = args[i][1..strlen(args[1])-1];  
        else if(flag) { 
            if(args[i][0] != '\'') tmp = args[i]; 
            else if(args[i][x=strlen(args[i])-1] =='\'') tmp =args[i][1..x-1]; 
            else { 
                tmp = args[j=i][1..x]; 
                while(++j < maxi && args[j][x=strlen(args[j])-1] != '\'') 
                  if(x > 0) tmp += " "+args[j][0..x-1]; 
                if(args[j][x] == '\'' && x > 1) tmp += " "+args[j][0..x-1]; 
                i = j; 
	      } 
            switch(flag) { 
  	        case "c":  
                    if(!__TmpPost["cc"]) __TmpPost["cc"] = ({}); 
                    __TmpPost["cc"] += ({ convert_name(tmp) });  
                    break; 
                case "s": __TmpPost["subject"] = tmp; break; 
                case "i":  
                    tmp=absolute_path((string)this_player()->get_path(),tmp); 
                    if(sscanf(tmp,user_path(this_player())+"%s", flag) != 1 || 
                      !((int)master()->valid_read(tmp,this_player()))) { 
                        if(__CommandLine) { 
                            this_object()->eventDestruct(); 
                            return; 
			  } 
                        __TmpPost = ([]); 
                        postal_error("Access denied."); 
                        return; 
		    } 
                    if(!file_exists(tmp)) { 
                        if(__CommandLine) { 
                            this_object()->eventDestruct(); 
                            return; 
			  } 
                        __TmpPost = ([]); 
                        postal_error(sprintf("File %s does not exist.",tmp)); 
                        return; 
		      } 
                    if(!(__TmpPost["message"] = read_file(tmp))) 
                      __TmpPost["message"] = "EMPTY FILE"; 
                    break; 
		} 
            flag = 0; 
	  } 
        else {
            if(!__TmpPost["to"]) __TmpPost["to"] = ({ convert_name(args[i]) });
            else __TmpPost["to"] += ({ convert_name(args[i]) });
        }
    } 
    if(!__TmpPost["to"]) { 
        message("prompt", "To: ", this_player()); 
        input_to("get_to"); 
        return; 
    } 
    if(!__TmpPost["subject"]) { 
        message("prompt", "Subject: ", this_player()); 
        input_to("get_subject"); 
        return; 
    } 
    else message("mail", sprintf("Subject: %s", __TmpPost["subject"]), 
      this_player()); 
    if(!__TmpPost["cc"] && __Options["askcc"]) { 
        message("prompt", "Copies to: ", this_player()); 
        input_to("get_cc"); 
        return; 
      } 
    else if(!__TmpPost["cc"]) __TmpPost["cc"] = ({}); 
    if(!__TmpPost["message"]) get_cc("");
    else {
        __TmpPost["message"] = sprintf("%s%s", __TmpPost["message"],
          query_signature());
        confirm_send(); 
    } 
} 
 
static void get_to(string str) { 
    if(str == "" || !str) { 
        if(__CommandLine) { 
            this_object()->eventDestruct(); 
            return; 
	  } 
        postal_error("No recipients given.  Mail aborted."); 
        return; 
      } 
    send_letter(explode(str, " ")); 
  } 
 
static void get_subject(string str) { 
    string tmp; 
 
    if(str == "" || !str) { 
        message("prompt", "No subject given.  Continue (default 'n')? ", 
          this_player()); 
        input_to("confirm_subject"); 
        return; 
      } 
    __TmpPost["subject"] = str; 
    if(!__TmpPost["cc"] && __Options["askcc"]) { 
        message("prompt", "Copies to: ", this_player()); 
        input_to("get_cc"); 
        return; 
      } 
    else if(!__TmpPost["cc"]) __TmpPost["cc"] = ({}); 
    if(!__TmpPost["message"]) get_cc("");
    else {
        __TmpPost["message"] = sprintf("%s%s", __TmpPost["message"],
          query_signature());
        confirm_send(); 
    } 
  } 
 
static void confirm_subject(string str) { 
    if(str == "" || !str) str = "n"; 
    else str = lower_case(str)[0..0]; 
    if(str == "n") { 
        if(__CommandLine) { 
            this_object()->eventDestruct(); 
            return; 
	  } 
        __TmpPost = ([]); 
        postal_error("Mail aborted."); 
        return; 
      } 
    else if(str == "y") get_subject("[No Subject]"); 
    else { 
        message("prompt", "Answer 'y' or 'n': ", this_player()); 
        input_to("confirm_subject"); 
        return; 
      } 
  } 
 
static void get_cc(string str) { 
    string tmp; 
 
    if(!__TmpPost["cc"]) __TmpPost["cc"] = ({});
    if(str && str != "") __TmpPost["cc"] += explode(str, " ");
    if(__TmpPost["message"]) {
        __TmpPost["message"] = sprintf("%s%s", __TmpPost["message"],
          query_signature()); 
        confirm_send();
        return; 
      }
    if(file_exists(tmp = DIR_TMP+"/"+(string)this_player()->GetKeyName()))
      rm(tmp);
    if(!__FwdRply || __FwdRply[0] == "f") { 
        message("mail",sprintf("\n%%^INITTERM%%^%s", header(__TmpPost)), 
          this_player()); 
        this_player()->eventEdit(tmp, (: complete_send :));
        return; 
    } 
    write_file(tmp, __FwdRply[1]); 
    message("mail", sprintf("\n%%^INITTERM%%^%s", header(__TmpPost)),
      this_player());
    this_player()->eventEdit(tmp, (: complete_send :));
  } 
 
void complete_send() { 
    string str; 
 
    if( !(str = read_file(DIR_TMP "/" + (string)this_player()->GetKeyName())))
      str = "No message."; 
    if(__FwdRply && __FwdRply[0] == "f")
      str = sprintf("%s\n%s\n%s", str, __FwdRply[1], query_signature());
    else str = sprintf("%s%s", str, query_signature()); 
    __TmpPost["message"] = str;
    __FwdRply = 0;
    confirm_send(); 
} 
 
static private string query_signature() { 
    string tmp; 
 
    if(!__Options["sig file"]) return ""; 
    if(strsrch(__Options["sig file"], " ") != -1) 
      return sprintf("\n%s", __Options["sig file"]);     
    tmp = absolute_path(user_path((string)this_player()->GetKeyName()), 
      __Options["sig file"]); 
    if(!((int)master()->valid_read(tmp, this_player())) || !file_exists(tmp)) {
        return sprintf("\n%s", __Options["sig file"]); 
    } 
    return read_file(tmp); 
} 
 
static private void confirm_send() {
    message("mail", center("e)dit, f)orget, s)end", __Screen), this_player());
    message("prompt", "\nCommand (default 's'): ", this_player());
    input_to("handle_send_choice");
}

static void handle_send_choice(string str) {
    string tmp;

    if(str == "" || !str) str = "s";
    else str = lower_case(str)[0..0];
    switch(str) {
        case "s":
            notify_send((string *)LOCALPOST_D->send_post(copy(__TmpPost)));
            break;
        case "f":
            __TmpPost = ([]);
            postal_error("Mail aborted!");
            break;
        case "e":
            if(file_exists(tmp = sprintf("%s/%s.iips", DIR_TMP, 
              (string)this_player()->GetKeyName()))) rm(tmp);
            write_file(tmp, __TmpPost["message"]);
            map_delete(__TmpPost, "message");
            this_player()->eventEdit(tmp, (: complete_send :));
            break;
        default:
            message("prompt", "Invalid command.  Command: ", this_player());
            input_to("handle_send_choice");
            break;
    }
}

static private void notify_send(string *failures) { 
    string *arr; 
    string tmp; 
 
    if(!sizeof(failures)) 
      message("mail", "\n\t%^GREEN%^Mail successfully sent!", this_player()); 
    else { 
        message("mail", sprintf("\nFailed to send to: %s", 
          implode(failures, ",  ")), this_player()); 
        if(creatorp(this_player())) { 
            write_file(tmp=user_path((string)this_player()->GetKeyName())+"/dead.letter", 
              __TmpPost["message"]);
	  } 
        else write_file(tmp = sprintf("%s/%s.letter", DIR_TMP, 
          (string)this_player()->GetKeyName()), __TmpPost["message"]); 
        message("mail", sprintf("A copy of the letter was saved to %s", tmp), 
          this_player()); 
    } 
    if(sizeof(arr=distinct_array(__TmpPost["to"]+__TmpPost["cc"])-failures)) 
      message("mail", sprintf("Mail sent to: %s", implode(arr,",  ")), 
        this_player()); 
    if(__CommandLine) { 
        this_object()->eventDestruct(); 
        return; 
    } 
    secondary_prompt(); 
    input_to("index_cmd"); 
} 

void incoming_post() {
    mixed tmp;
    string id;
    int *delete;

    if(__Folder != "new") return;
    if(file_name(previous_object()) != FOLDERS_D) return;
    id = (__Current < 0 ? 0 : __BoxInfo[__Current]["id"]);
    delete =map_array(tmp=(mapping)FOLDERS_D->query_box_info(__Owner,"new"), 
      "order_box", this_object());
    __BoxInfo = copy(tmp);
    set_current(id);
    __Delete = copy(delete);
    __IncomingFlag = 1;
}

int order_box(mapping borg) {
    int i;

    i = sizeof(__BoxInfo);
    while(i--) if(__BoxInfo[i]["id"] == borg["id"]) return __Delete[i];
    return 0;
}