Generic Large-Capacity Mail Recipient #14

Parent #45Owner #36Flags read, fertileSource RPG Core/rpgcore-patched.db

Aliases: Generic Large-Capacity Mail Recipient

43 verbs · 27 properties · 1 children

Verbs

VerbSpecFlagsDefinerLines
_genpropthis none thisrxd#1410
_makethis none thisrxd#147
_killthis none thisrxd#145
_getthis none thisrxd#141
_putthis none thisrxd#141
_ordthis none thisrxd#141
_makemsgthis none thisrxd#1410
_killmsgthis none thisrxd#145
_message_numthis none thisrxd#141
_message_datethis none thisrxd#141
_message_hdrthis none thisrxd#141
_message_textthis none thisrxd#141
_lt_msgnumthis none thisrxd#141
_lt_msgdatethis none thisrxd#141
receive_batchthis none thisrxd#1420
receive_messagethis none thisrxd#148
messages_in_seqthis none thisrxd#1420
display_seq_headersthis none thisrxd#1429
display_seq_fullthis none thisrxd#1422
list_rmmthis none thisrxd#1434
undo_rmmthis none thisrxd#1425
expunge_rmmthis none thisrxd#1414
rm_message_seqthis none thisrxd#1433
renumberthis none thisrxd#1457
length_all_msgsthis none thisrxd#141
length_num_lethis none thisrxd#141
length_date_lethis none thisrxd#141
exists_num_eqthis none thisrxd#141
new_message_numthis none thisrxd#1411
from_msg_seqthis none thisrxd#1427
%from_msg_seqthis none thisrxd#1429
to_msg_seqthis none thisrxd#1428
%to_msg_seqthis none thisrxd#1429
subject_msg_seqthis none thisrxd#1422
body_msg_seqthis none thisrxd#1430
date_sortthis none thisrxd#141
_fix_last_msg_datethis none thisrxd#142
__fixthis none thisrxd#1420
init_for_corethis none thisrxd#145
length_date_gtthis none thisrxd#146
_repairthis none thisrx#14146
repairthis none nonerd#1417
restore_fromthis none thisrxd#1466

Properties

PropertyDefinerFlagsOwnerValue
summary_uses_body#14rc#360
_mgr#14rc#36#13
mowner#14r#36#36
_genprop#14r#36""
moderator_notify#45rc#36<clear>
last_msg_date#45r#360
messages_going#45rc#36<clear>
moderated#45rc#36<clear>
moderator_forward#45rc#36<clear>
writers#45rc#36<clear>
readers#45rc#36<clear>
mail_notify#45r#36<clear>
mail_forward#45r#36<clear>
expire_period#45r#36<clear>
last_used_time#45r#36<clear>
messages#45rc#36<clear>
rmm_own_msgs#45rc#36<clear>
guests_can_send_here#45rc#36<clear>
messages_kept#45r#36<clear>
registered_email#45rc#36<clear>
email_validated#45rc#36<clear>
validation_password#45rc#36<clear>
key#1c#36<clear>
aliases#1r#36{"Generic Large-Capacity Mail Recipient"}
description#1rc#36
list of 41{"Generic Large Capacity Mail Recipient", "-------------------------------------", "Since any modifications to large lists entail copying the entire list over, operations on ordinary mail recipients having large numbers of messages, that actually change the content of .messages will take inordinately long. Thus we have this version which makes use of the $biglist package, scattering the messages onto numerous properties so that write operations involving only a few messages will not require recopying of the entire list.", "", "In nearly all respects it behaves as the ordinary Mail Recipient, except that it is faster for certain kinds of operations.", "", "Certain unimplemented verbs, like :date_sort(), and :messages() currently return E_VERBNF.", "", "To convert an existing $mail_recipient-child (call it #MR) into a $big_mail_recipient-child the basic procedure is", "", " ;;something.foo= #MR:messages();", " @rmm 1-$ from #MR", " @unrmm expunge", " @chparent #MR to $big_mail_recipient", " ;#MR:receive_batch(@something.foo);", "", "Reconstructing Damaged Big Mail Recipients", "------------------------------------------", "On rare occasions, the tree structure created by $biglist can be corrupted (this can happen on lists sufficiently large that a list-modification operation (e.g., @rmm, @renumber) runs out of ticks/seconds). In the vast majority of such cases, your messages are all still there; it's simply that the tree we use for finding/searching them is messed up.", "", "To recover messages from a damaged big mail recipient (#DBMR)", " --- read to the end before you start typing any commands ---", "", "create a fresh $big_mail_recipient (#NEWBMR) and then do the following:", "", " ;#NEWBMR:restore_from(#DBMR)", "", "When this finishes, #NEWBMR will contain all of the mail messages we were able to find. (note that this will include messages that you had deleted from #DBMR but not expunged). #NEWMBR should thenceforth be useable in place of #DBMR, however if #DBMR contains custom verbs and non-clear properties, these will also need to be copied over.", "", "Alternatively, one may do", "", " @copyobject #DBMR to #TEMPBMR", " ;#DBMR:restore_from(#TEMPBMR)", "", "to rebuild #DBMR in place. This, however, will take about twice as long.", "", "oooooooooooooooooooooooooooooooo", "WARNING!!! WARNING!!! WARNING!!!", "oooooooooooooooooooooooooooooooo", "", "Calling #OBJ:restore_from(...) COMPLETELY AND IRREVOCABLY REMOVES ALL MESSAGES from the object that it is run on (#OBJ); you MUST be sure to EITHER have made a copy of #OBJ OR be doing the restore to a DIFFERENT object."}
object_size#1r#36{40391, -1090650497}
html#1rc#36<clear>

Ancestry

Ancestors (nearest first): #45 Generic Mail Recipient#1 Root Class

Children: #17 Player Creation Log

Call graph

calls n14_1 #14:_make n14_0 #14:_genprop n14_1->n14_0 n14_6 #14:_makemsg n14_6->n14_1 n14_7 #14:_killmsg n14_2 #14:_kill n14_7->n14_2 n14_14 #14:receive_batch n14_14->n14_6 n45_2 #45:is_writable_by n14_14->n45_2 n14_28 #14:new_message_num n14_14->n14_28 n56_7 #56:running_out_of_time n14_14->n56_7 n6_18 #6:tell n14_14->n6_18 n45_13 #45:ok n14_28->n45_13 n14_8 #14:_message_num n14_28->n14_8 n14_15 #14:receive_message n14_15->n14_6 n14_15->n45_2 n14_15->n14_28 n14_9 #14:_message_date n14_15->n14_9 n14_16 #14:messages_in_seq n14_16->n45_13 n14_16->n14_8 n14_11 #14:_message_text n14_16->n14_11 n14_17 #14:display_seq_headers n14_17->n6_18 n14_17->n45_13 n33_18 #33:contract n14_17->n33_18 n45_15 #45:parse_message_seq n14_17->n45_15 n33_2 #33:complement n14_17->n33_2 n14_24 #14:length_all_msgs n14_17->n14_24 n6_13 #6:linelen n14_17->n6_13 n20_71 #20:redirect_ansi n14_17->n20_71 n45_24 #45:msg_summary_line n14_17->n45_24 n14_24->n45_13 n14_18 #14:display_seq_full n14_18->n14_9 n14_18->n45_13 n14_18->n14_8 n14_18->n14_11 n45_33 #45:msg_full_text n14_18->n45_33 n14_19 #14:list_rmm n14_19->n6_18 n14_19->n45_13 n14_19->n14_8 n14_19->n20_71 n14_19->n45_24 n14_20 #14:undo_rmm n45_14 #45:ok_write n14_20->n45_14 n33_3 #33:union n14_20->n33_3 n33_17 #33:expand n14_20->n33_17 n14_36 #14:_fix_last_msg_date n14_20->n14_36 n14_21 #14:expunge_rmm n14_21->n45_14 n14_22 #14:rm_message_seq n14_22->n6_18 n14_22->n45_13 n14_22->n14_8 n14_22->n33_18 n14_22->n45_14 n14_22->n14_36 n45_19 #45:own_messages_filter n14_22->n45_19 n56_8 #56:suspend_if_needed n14_22->n56_8 n33_20 #33:intersection n14_22->n33_20 n33_4 #33:tostr n14_22->n33_4 n14_23 #14:renumber n14_23->n56_7 n14_23->n6_18 n14_23->n45_14 n14_23->n14_21 n14_25 #14:length_num_le n14_25->n45_13 n14_26 #14:length_date_le n14_26->n45_13 n14_27 #14:exists_num_eq n14_27->n45_13 n14_27->n14_8 n14_29 #14:from_msg_seq n14_29->n45_13 n33_0 #33:add n14_29->n33_0 n20_6 #20:english_list n14_29->n20_6 n55_4 #55:map_arg n14_29->n55_4 n14_30 #14:%from_msg_seq n14_30->n45_13 n14_30->n33_0 n14_30->n20_6 n14_30->n55_4 n14_31 #14:to_msg_seq n14_31->n45_13 n14_31->n33_0 n14_31->n20_6 n14_31->n55_4

Showing 48 of 68 verbs; 20 not shown.

Source

_genprop

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

Source

1gp = this._genprop;
2ngp = "";
3for i in [1..length(gp)]
4if (gp[i] != "z")
5ngp = (ngp + "bcdefghijklmnopqrstuvwxyz"[index("abcdefghijklmnopqrstuvwxy", gp[i])]) + gp[i + 1..length(gp)];
6return " " + (this._genprop = ngp);
7endif
8ngp = ngp + "a";
9endfor
10return " " + (this._genprop = ngp + "a");

_make

Spec this none thisFlags rxdOwner #2Definer #14

Referenced by

Source

1":_make(...) => new node with value {...}";
2if (!(caller in {this._mgr, this}))
3return E_PERM;
4endif
5prop = this:_genprop();
6`add_property(this, prop, args, {this.mowner, ""}) ! ANY';
7return prop;

_kill

Spec this none thisFlags rxdOwner #2Definer #14

Referenced by

Source

1":_kill(node) destroys the given node.";
2if (!(caller in {this, this._mgr}))
3return E_PERM;
4endif
5`delete_property(this, args[1]) ! ANY';

_get

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1return (caller == this._mgr) ? `this.(args[1]) ! ANY' | E_PERM;

_put

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1return (caller == this._mgr) ? this.(args[1]) = listdelete(args, 1) | E_PERM;

_ord

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1return args[1][2..3];

_makemsg

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

Source

1":_makemsg(ord,msg) => leafnode for msg";
2"msg = $mail_agent:__convert_new(@args[2])";
3msg = args[2];
4if (caller != this)
5return E_PERM;
6elseif (h = "" in msg)
7return {this:_make(@msg[h + 1..$]), args[1], @msg[1..h - 1]};
8else
9return {0, args[1], @msg};
10endif

_killmsg

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1if (caller != this._mgr)
2return E_PERM;
3elseif (node = args[1][1])
4this:_kill(node);
5endif

_message_num

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

Source

1return args[2];

_message_date

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

Source

1return args[3];

_message_hdr

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

Source

1return args[3..$];

_message_text

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

Source

1return {@args[3..$], @args[1] ? {"", @this.(args[1])} | {}};

_lt_msgnum

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1return args[1] < args[2][1];

_lt_msgdate

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1return args[1] < args[2][2];

receive_batch

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1if (!this:is_writable_by(caller_perms()))
2return E_PERM;
3else
4new = this:new_message_num();
5msgtree = this.messages;
6for m in (args)
7msgtree = this._mgr:insert_last(msgtree, this:_makemsg(new, m[2]));
8new = new + 1;
9if ($command_utils:running_out_of_time())
10this.messages = msgtree;
11player:tell("... ", new);
12suspend(0);
13msgtree = this.messages;
14new = this:new_message_num();
15endif
16endfor
17this.messages = msgtree;
18this.last_used_time = time();
19return 1;
20endif

receive_message

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1if (!this:is_writable_by(caller_perms()))
2return E_PERM;
3else
4this.messages = this._mgr:insert_last(this.messages, msg = this:_makemsg(new = this:new_message_num(), args[1]));
5this.last_msg_date = this:_message_date(@msg);
6this.last_used_time = time();
7return new;
8endif

messages_in_seq

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1if (!this:ok(caller, caller_perms()))
2return E_PERM;
3elseif (typeof(seq = args[1]) != LIST)
4x = this._mgr:find_nth(this.messages, seq);
5return {this:_message_num(@x), this:_message_text(@x)};
6else
7msgs = {};
8while (seq)
9handle = this._mgr:start(this.messages, seq[1], seq[2] - 1);
10while (handle)
11for x in (handle[1])
12msgs = {@msgs, {this:_message_num(@x), this:_message_text(@x)}};
13endfor
14handle = this._mgr:next(@listdelete(handle, 1));
15(ticks_left() < 4000) && suspend(0);
16endwhile
17seq = seq[3..$];
18endwhile
19return msgs;
20endif

display_seq_headers

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

Source

1":display_seq_headers(msg_seq[,cur[,last_read_date]])";
2"This is the default header display routine.";
3"Prints a list of headers of messages on this to player.  msg_seq is the handle returned by this:parse_message_seq(...).  cur is the player's current message.  last_read_date is the date of the last of the already-read messages.";
4if (!this:ok(caller, caller_perms()))
5return E_PERM;
6endif
7getmsg = this.summary_uses_body ? "_message_text" | "_message_hdr";
8{seq, ?cur = 0, ?last_old = $maxint} = args;
9keep_seq = {@$seq_utils:contract(this:kept_msg_seq(), $seq_utils:complement(seq, 1, this:length_all_msgs())), $maxint};
10k = 1;
11mcount = 0;
12width = player:linelen();
13while (seq)
14handle = this._mgr:start(this.messages, seq[1], seq[2] - 1);
15while (handle)
16for x in (handle[1])
17(ticks_left() < 4000) && suspend(0);
18if (keep_seq[k] <= (mcount = mcount + 1))
19k = k + 1;
20endif
21annot = (x[3] > last_old) ? "+" | ((k % 2) ? " " | "=");
22line = tostr($string_utils:right(x[2], 5, (cur == x[2]) ? ">" | " "), ":", annot, " ", this:msg_summary_line(@this:(getmsg)(@x)));
23player:tell(line[1..min(width, $)]);
24endfor
25handle = this._mgr:next(@listdelete(handle, 1));
26endwhile
27seq = seq[3..$];
28endwhile
29player:tell("-----+");

display_seq_full

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1":display_seq_full(msg_seq[,preamble]) => {cur}";
2"This is the default message display routine.";
3"Prints the indicated messages on folder to player.  msg_seq is the handle returned by folder:parse_message_seq(...).  Returns the number of the final message in the sequence (to be the new current message number).";
4if (!this:ok(caller, caller_perms()))
5return E_PERM;
6endif
7{seq, ?preamble = ""} = args;
8cur = date = 0;
9while (seq)
10handle = this._mgr:start(this.messages, seq[1], seq[2] - 1);
11while (handle)
12for x in (handle[1])
13cur = this:_message_num(@x);
14date = this:_message_date(@x);
15player:display_message(preamble ? strsub(preamble, "%d", tostr(cur)) | {}, this:msg_full_text(@this:_message_text(@x)));
16endfor
17handle = this._mgr:next(@listdelete(handle, 1));
18(ticks_left() < 4000) && suspend(0);
19endwhile
20seq = seq[3..$];
21endwhile
22return {cur, date};

list_rmm

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1if (!this:ok(caller, caller_perms()))
2return E_PERM;
3endif
4len = 0;
5getmsg = this.summary_uses_body ? "_message_text" | "_message_hdr";
6going = this.messages_going;
7if (going && ((!going[1]) || (typeof(going[1][2]) == INT)))
8kept = {@going[1], $maxint};
9going = going[2];
10else
11kept = {$maxint};
12endif
13k = 1;
14mcount = 0;
15for s in (going)
16if (kept[k] <= (mcount = mcount + s[1]))
17k = k + 1;
18endif
19len = len + s[2][2];
20handle = this._mgr:start(s[2], 1, s[2][2]);
21while (handle)
22for x in (handle[1])
23if (kept[k] <= (mcount = mcount + 1))
24k = k + 1;
25endif
26player:tell($string_utils:right(this:_message_num(@x), 4), (k % 2) ? ":  " | ":= ", this:msg_summary_line(@this:(getmsg)(@x)));
27endfor
28handle = this._mgr:next(@listdelete(handle, 1));
29endwhile
30endfor
31if (len)
32player:tell("----+");
33endif
34return len;

undo_rmm

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1if (!this:ok_write(caller, caller_perms()))
2return E_PERM;
3endif
4msgtree = this.messages;
5seq = {};
6last = 0;
7"there are two possible formats here:";
8"OLD: {{n,msgs},{n,msgs},...}";
9"NEW: {kept_seq, {{n,msgs},{n,msgs},...}}";
10going = this.messages_going;
11if (going && ((!going[1]) || (typeof(going[1][2]) == INT)))
12kept = going[1];
13going = going[2];
14else
15kept = {};
16endif
17for s in (going)
18msgtree = this._mgr:insert_after(msgtree, s[2], last + s[1]);
19seq = {@seq, (last + s[1]) + 1, (last = (last + s[1]) + s[2][2]) + 1};
20endfor
21this.messages = msgtree;
22this.messages_going = {};
23this.messages_kept = $seq_utils:union(kept, $seq_utils:expand(this.messages_kept, seq));
24this:_fix_last_msg_date();
25return seq;

expunge_rmm

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

Source

1if (!this:ok_write(caller, caller_perms()))
2return E_PERM;
3endif
4len = 0;
5going = this.messages_going;
6if (going && ((!going[1]) || (typeof(going[1][2]) == INT)))
7going = going[2];
8endif
9for s in (going)
10len = len + s[2][2];
11this._mgr:kill(s[2], "_killmsg");
12endfor
13this.messages_going = {};
14return len;

rm_message_seq

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1seq = args[1];
2if (!(this:ok_write(caller, caller_perms()) || (this:ok(caller, caller_perms()) && (seq = this:own_messages_filter(caller_perms(), @args)))))
3return E_PERM;
4endif
5msgtree = this.messages;
6save = nums = {};
7onext = 1;
8rmmed = 0;
9for i in [1..length(seq) / 2]
10if ($command_utils:suspend_if_needed(0))
11player:tell("... rmm ", onext);
12suspend(0);
13endif
14start = seq[(2 * i) - 1];
15next = seq[2 * i];
16{msgtree, zmsgs} = this._mgr:extract_range(msgtree, start - rmmed, (next - 1) - rmmed);
17save = {@save, {start - onext, zmsgs}};
18nums = {@nums, this:_message_num(@this._mgr:find_nth(zmsgs, 1)), this:_message_num(@this._mgr:find_nth(zmsgs, zmsgs[2])) + 1};
19onext = next;
20rmmed = (rmmed + next) - start;
21endfor
22tmg = this.messages_going;
23save_kept = $seq_utils:intersection(this.messages_kept, seq);
24this.messages_kept = $seq_utils:contract(this.messages_kept, seq);
25this.messages_going = save_kept ? {save_kept, save} | save;
26fork (0)
27for s in (tmg)
28this._mgr:kill(s[2], "_killmsg");
29endfor
30endfork
31this.messages = msgtree;
32this:_fix_last_msg_date();
33return $seq_utils:tostr(nums);

renumber

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1":renumber([cur]) renumbers caller.messages, doing a suspend() if necessary.";
2"  => {number of messages,new cur}.";
3if (!this:ok_write(caller, caller_perms()))
4return E_PERM;
5endif
6{?cur = 0} = args;
7this:expunge_rmm();
8"... blow away @rmm'ed messages since there's no way to tell what their new numbers should be...";
9if (!(msgtree = this.messages))
10return {0, 0};
11endif
12if (cur)
13cur = this._mgr:find_ord(msgtree, cur - 1, "_lt_msgnum") + 1;
14endif
15while (1)
16"...find first out-of-sequence message...";
17n = 1;
18subtree = msgtree;
19if (msgtree[3][1] == 1)
20while ((node = this.(subtree[1]))[1])
21"...subtree[3][1]==n...";
22kids = node[2];
23n = n + subtree[2];
24i = length(kids);
25while ((n = n - kids[i][2]) != kids[i][3][1])
26i = i - 1;
27endwhile
28subtree = kids[i];
29endwhile
30leaves = node[2];
31n = ((firstn = n) + length(leaves)) - 1;
32while (n != leaves[(n - firstn) + 1][2])
33n = n - 1;
34endwhile
35n = n + 1;
36endif
37"... n == first out-of-sequence ...";
38"...renumber as many messages as we have time for...";
39while ((n <= msgtree[2]) && (!$command_utils:running_out_of_time()))
40msg = this._mgr:find_nth(msgtree, n);
41msgtree = this._mgr:set_nth(msgtree, n, listset(msg, n, 2));
42n = n + 1;
43endwhile
44this.messages = msgtree;
45if (n > msgtree[2])
46return {n - 1, cur};
47endif
48player:tell("...(renumbering to ", n - 1, ")");
49suspend(0);
50"...start over... may have received new mail, rmm'ed stuff, etc...";
51"...so who knows what's there now?...";
52if (this.messages_going)
53player:tell("Renumber aborted.");
54return;
55endif
56msgtree = this.messages;
57endwhile

length_all_msgs

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

Source

1return this:ok(caller, caller_perms()) ? this.messages ? this.messages[2] | 0 | E_PERM;

length_num_le

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1return this:ok(caller, caller_perms()) ? this._mgr:find_ord(this.messages, args[1], "_lt_msgnum") | E_PERM;

length_date_le

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1return this:ok(caller, caller_perms()) ? this._mgr:find_ord(this.messages, args[1], "_lt_msgdate") | E_PERM;

exists_num_eq

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1return this:ok(caller, caller_perms()) ? (i = this._mgr:find_ord(this.messages, args[1], "_lt_msgnum")) && ((this:_message_num(@this._mgr:find_nth(this.messages, i)) == args[1]) && i) | E_PERM;

new_message_num

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

Source

1if (this:ok(caller, caller_perms()))
2new = (msgtree = this.messages) ? this:_message_num(@this._mgr:find_nth(msgtree, msgtree[2])) + 1 | 1;
3if (rmsgs = this.messages_going)
4lbrm = rmsgs[$][2];
5return max(new, this:_message_num(@this._mgr:find_nth(lbrm, lbrm[2])) + 1);
6else
7return new;
8endif
9else
10return E_PERM;
11endif

from_msg_seq

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1":from_msg_seq(object or list)";
2" => msg_seq of messages from any of these senders";
3if (!this:ok(caller, caller_perms()))
4return E_PERM;
5elseif (!this.messages)
6return {};
7endif
8{plist, ?mask = {1, this.messages[2] + 1}} = args;
9if (typeof(plist) != LIST)
10plist = {plist};
11endif
12fseq = {};
13for m in [1..length(mask) / 2]
14handle = this._mgr:start(this.messages, i = mask[(2 * m) - 1], mask[2 * m] - 1);
15while (handle)
16for msg in (handle[1])
17fromline = msg[4];
18if (toobj(fromline[rindex(fromline, "(") + 1..rindex(fromline, ")") - 1]) in plist)
19fseq = $seq_utils:add(fseq, i, i);
20endif
21i = i + 1;
22(ticks_left() < 4000) && suspend(0);
23endfor
24handle = this._mgr:next(@listdelete(handle, 1));
25endwhile
26endfor
27return fseq || ("%f %<has> no messages from " + $string_utils:english_list($list_utils:map_arg(2, $string_utils, "pronoun_sub", "%n (%#)", plist), "no one", " or "));

%from_msg_seq

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1":%from_msg_seq(string or list of strings)";
2" => msg_seq of messages with one of these strings in the from line";
3if (!this:ok(caller, caller_perms()))
4return E_PERM;
5elseif (!this.messages)
6return {};
7endif
8{nlist, ?mask = {1, this.messages[2] + 1}} = args;
9if (typeof(nlist) != LIST)
10nlist = {nlist};
11endif
12fseq = {};
13for m in [1..length(mask) / 2]
14handle = this._mgr:start(this.messages, i = mask[(2 * m) - 1], mask[2 * m] - 1);
15while (handle)
16for msg in (handle[1])
17fromline = " " + msg[4];
18for n in (nlist)
19if (index(fromline, n))
20fseq = $seq_utils:add(fseq, i, i);
21endif
22endfor
23i = i + 1;
24(ticks_left() < 4000) && suspend(0);
25endfor
26handle = this._mgr:next(@listdelete(handle, 1));
27endwhile
28endfor
29return fseq || ("%f %<has> no messages from " + $string_utils:english_list($list_utils:map_arg($string_utils, "print", nlist), "no one", " or "));

to_msg_seq

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1":to_msg_seq(object or list) => msg_seq of messages to those people";
2if (!this:ok(caller, caller_perms()))
3return E_PERM;
4elseif (!this.messages)
5return {};
6endif
7{plist, ?mask = {1, this.messages[2] + 1}} = args;
8if (typeof(plist) != LIST)
9plist = {plist};
10endif
11seq = {};
12for m in [1..length(mask) / 2]
13handle = this._mgr:start(this.messages, i = mask[(2 * m) - 1], mask[2 * m] - 1);
14while (handle)
15for msg in (handle[1])
16toline = msg[5];
17for r in ($mail_agent:parse_address_field(toline))
18if (r in plist)
19seq = $seq_utils:add(seq, i, i);
20endif
21endfor
22i = i + 1;
23(ticks_left() < 4000) && suspend(0);
24endfor
25handle = this._mgr:next(@listdelete(handle, 1));
26endwhile
27endfor
28return seq || ("%f %<has> no messages to " + $string_utils:english_list($list_utils:map_arg(2, $string_utils, "pronoun_sub", "%n (%#)", plist), "no one", " or "));

%to_msg_seq

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1":%to_msg_seq(string or list of strings)";
2" => msg_seq of messages containing one of strings in the to line";
3if (!this:ok(caller, caller_perms()))
4return E_PERM;
5elseif (!this.messages)
6return {};
7endif
8{nlist, ?mask = {1, this.messages[2] + 1}} = args;
9if (typeof(nlist) != LIST)
10nlist = {nlist};
11endif
12seq = {};
13for m in [1..length(mask) / 2]
14handle = this._mgr:start(this.messages, i = mask[(2 * m) - 1], mask[2 * m] - 1);
15while (handle)
16for msg in (handle[1])
17toline = " " + msg[5];
18for n in (nlist)
19if (index(toline, n))
20seq = $seq_utils:add(seq, i, i);
21endif
22endfor
23i = i + 1;
24(ticks_left() < 4000) && suspend(0);
25endfor
26handle = this._mgr:next(@listdelete(handle, 1));
27endwhile
28endfor
29return seq || ("%f %<has> no messages to " + $string_utils:english_list($list_utils:map_arg($string_utils, "print", nlist), "no one", " or "));

subject_msg_seq

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1":subject_msg_seq(target) => msg_seq of messages with target in the Subject:";
2if (!this:ok(caller, caller_perms()))
3return E_PERM;
4elseif (!this.messages)
5return {};
6endif
7{target, ?mask = {1, this.messages[2] + 1}} = args;
8seq = {};
9for m in [1..length(mask) / 2]
10handle = this._mgr:start(this.messages, i = mask[(2 * m) - 1], mask[2 * m] - 1);
11while (handle)
12for msg in (handle[1])
13if (((subject = msg[6]) != " ") && index(subject, target))
14seq = $seq_utils:add(seq, i, i);
15endif
16i = i + 1;
17(ticks_left() < 4000) && suspend(0);
18endfor
19handle = this._mgr:next(@listdelete(handle, 1));
20endwhile
21endfor
22return seq || (("%f %<has> no messages with subjects containing `" + target) + "'");

body_msg_seq

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1":body_msg_seq(target) => msg_seq of messages with target in the body";
2if (!this:ok(caller, caller_perms()))
3return E_PERM;
4elseif (!this.messages)
5return {};
6endif
7{target, ?mask = {1, this.messages[2] + 1}} = args;
8seq = {};
9for m in [1..length(mask) / 2]
10handle = this._mgr:start(this.messages, i = mask[(2 * m) - 1], mask[2 * m] - 1);
11while (handle)
12for msg in (handle[1])
13if ((msg[1] && (body = this.(msg[1]))) && index(tostr(@body), target))
14seq = $seq_utils:add(seq, i, i);
15"Above saves ticks. Munges the whole message into one string and indexes it. Old code follows.";
16"l = length(body);";
17"while (!index(body[l], target) && (l = l - 1))";
18"ticks_left() < 4000 && suspend(0);";
19"endwhile";
20"if (l)";
21"seq = $seq_utils:add(seq, i, i);";
22"endif";
23endif
24i = i + 1;
25(ticks_left() < 4000) && suspend(0);
26endfor
27handle = this._mgr:next(@listdelete(handle, 1));
28endwhile
29endfor
30return seq || tostr("%f %<has> no messages containing `", target, "' in the body.");

date_sort

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1return E_VERBNF;

_fix_last_msg_date

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

Source

1msgtree = this.messages;
2this.last_msg_date = (msgtree && this:_message_hdr(@this._mgr:find_nth(msgtree, msgtree[2]))[1]) || 0;

__fix

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1if (!this:ok_write(caller, caller_perms()))
2return E_PERM;
3endif
4{?doit = 0} = args;
5msgtree = this.messages;
6for n in [1..msgtree[2]]
7msg = this._mgr:find_nth(msgtree, n);
8msg = {@msg[1..2], @$mail_agent:__convert_new(@msg[3..$])};
9if (doit)
10msgtree = this._mgr:set_nth(msgtree, n, msg);
11endif
12if ($command_utils:running_out_of_time())
13suspend(0);
14if (this.messages != msgtree)
15player:notify("urk.  someone played with this folder.");
16return 0;
17endif
18endif
19endfor
20return 1;

init_for_core

Spec this none thisFlags rxdOwner #2Definer #14

Referenced by

Source

1if (caller_perms().wizard)
2pass();
3this._mgr = $biglist;
4this.mowner = $mail_recipient.owner;
5endif

length_date_gt

Spec this none thisFlags rxdOwner #36Definer #14

Referenced by

none

Source

1if (this:ok(caller, caller_perms()))
2date = args[1];
3return (this.last_msg_date <= date) ? 0 | (this.messages[2] - this._mgr:find_ord(this.messages, args[1], "_lt_msgdate"));
4else
5return E_PERM;
6endif

_repair

Spec this none thisFlags rxOwner #2Definer #14

Referenced by

Source

1c = callers();
2if ((caller != this) && (!((((length(c) > 1) && (c[1][1] == $list_utils)) && (c[1][2] == "map_arg")) && (c[2][1] == this))))
3raise(E_PERM);
4endif
5(ticks_left() < 4000) && suspend(0);
6biglist = this;
7propname = args[1];
8if (!propname)
9bestlevel = -1;
10best = {};
11for prop in (properties(biglist))
12(ticks_left() < 4000) && suspend(0);
13if (index(prop, " ") == 1)
14val = biglist.(prop);
15if (typeof(val[1]) == INT)
16if (bestlevel < val[1])
17bestlevel = val[1];
18best = {prop};
19elseif (bestlevel == val[1])
20best = {@best, prop};
21endif
22endif
23endif
24endfor
25if (!best)
26player:notify("Can't find a root.");
27raise(E_INVARG);
28elseif (length(best) == 1)
29propname = best[1];
30else
31propname = best[1];
32val = biglist.(propname);
33for prop in (best[2..$])
34(ticks_left() < 4000) && suspend(0);
35val[2] = {@val[2], @biglist.(prop)[2]};
36endfor
37biglist.(propname) = val;
38"Now that the new value is safely stored, delete old values.";
39for prop in (best[2..$])
40(ticks_left() < 4000) && suspend(0);
41player:notify(tostr("Removing property ", toliteral(prop), ".  Its value, ", toliteral(biglist.(prop)), ", has been merged with property ", toliteral(propname), "."));
42delete_property(biglist, prop);
43endfor
44endif
45maxlevel = biglist.(propname)[1];
46player:notify(tostr("Maximum level is ", maxlevel, "."));
47items = $list_utils:make(maxlevel, {});
48"Arrgh.  Even after finding the root, some nodes might be detached!";
49player:notify("Checking for orphans...");
50for prop in (properties(biglist))
51(ticks_left() < 4000) && suspend(0);
52if (prop && (prop[1] == " "))
53val = biglist.(prop);
54if (((typeof(val) == LIST) && (typeof(level = val[1]) == INT)) && (level < maxlevel))
55items[level + 1] = {@items[level + 1], prop};
56endif
57endif
58endfor
59for prop in (properties(biglist))
60(ticks_left() < 4000) && suspend(0);
61if (prop && (prop[1] == " "))
62val = biglist.(prop);
63if (((typeof(val) == LIST) && (typeof(level = val[1]) == INT)) && (level > 0))
64for item in (val[2])
65items[level] = setremove(items[level], item[1]);
66endfor
67endif
68endif
69endfor
70player:notify(tostr("Orphans: ", toliteral(items)));
71backbone_prop = propname;
72level = maxlevel;
73while (level)
74backbone = biglist.(backbone_prop);
75lastkid = backbone_prop;
76for prop in (props = items[level])
77backbone[2] = {@backbone[2], {lastkid = prop, 0, {0, 0}}};
78endfor
79player:notify(tostr("Attaching ", nn = length(props), " propert", (nn == 1) ? "y" | "ies", " to property ", toliteral(backbone_prop), "..."));
80biglist.(backbone_prop) = backbone;
81backbone_prop = lastkid;
82level = level - 1;
83endwhile
84player:notify(tostr("Orphans repatriated."));
85endif
86toplevel = "(top level)";
87context = args[2] || toplevel;
88"This stuff is just paranoia in case something unexpected is in the data structure.  Normally there should be no blowouts here. --Minnie";
89if (typeof(propname) != STR)
90player:notify(tostr("Context=", context, " Prop Name=", toliteral(propname), " -- bad property name."));
91raise(E_INVARG);
92endif
93val = biglist.(propname);
94if (typeof(val) != LIST)
95player:notify(tostr("Context=", context, " Prop Name=", toliteral(propname), " -- contents invalid."));
96raise(E_INVARG);
97endif
98if (typeof(level = val[1]) != INT)
99player:notify(tostr("Context=", context, " Prop Name=", toliteral(propname), " -- contents invalid (bad first argument)."));
100raise(E_INVARG);
101endif
102"This is where the real work starts. --Minnie";
103"First check that the properties referred to really exist.  This must be done for all levels.";
104for item in (val[2])
105try
106biglist.(item[1]);
107except (E_PROPNF)
108player:notify(tostr("Item ", toliteral(item), " is invalid in property ", toliteral(propname), ".  It is being removed."));
109val[2] = setremove(val[2], item);
110continue item;
111endtry
112endfor
113"Next, only for upper levels, check that the message count for inferior levels is correct, but only after recursing into those levels and making repairs.";
114if (level > 0)
115new = $list_utils:map_arg(this, verb, $list_utils:slice(val[2]), propname);
116if (val[2] != new)
117player:notify(tostr("Changing ", toliteral(val[2]), " to ", toliteral(new), "."));
118val[2] = new;
119endif
120"Now that everything is correct, count size of inferiors.";
121endif
122"Bravely stuff the result back into place.";
123biglist.(propname) = val;
124"The result will be of the form:                               ";
125"  {propname, inferior_msgcount, {first_msgnum, first_time}}  ";
126if (level == 0)
127"Count the messages for message count.";
128"Use first message number and time for first_msgnum and first_time.";
129result = {propname, length(val[2]), val[2][1][2..3]};
130else
131"Use message count that is sum of inferior counts.";
132"Just propagate first node's first_msgnum and first_time upward literally.";
133n = 0;
134for subnode in (val[2])
135n = n + subnode[2];
136endfor
137result = {propname, n, val[2][1][3]};
138endif
139if (context == toplevel)
140if (result != biglist.messages)
141biglist.messages = result;
142player:notify(tostr("Property ", biglist, ".messages updated."));
143endif
144player:tell(biglist.messages[2], " messages repaired in ", $mail_agent:name(biglist), ".");
145endif
146return result;

repair

Spec this none noneFlags rdOwner #2Definer #14

Referenced by

none

Source

1"Syntax: repair <biglist>";
2"";
3"This tool makes a last-resort attempt to repair broken biglists (ones whose data structures are out of alignment due to an error such as \"out of ticks\" during some update operation leaving the b-tree in an inconsistent state).  This tool comes with no warranty of any kind.  You should only use it when you have no other choice, and you should make an attempt to @dump or fully copy or otherwise checkpoint your object before attempting to repair it so that you can recover from any failures this might produce.  This operation is NOT undoable.";
4if (!$perm_utils:controls(player, this))
5player:tell("You do not control that.");
6elseif (!$command_utils:yes_or_no("This tool can be used to repair some (but maybe not all) situations involving generic biglists that have had an error (usually \"out of ticks\") during an update operation and were left inconsistent.  Is this list really and truly broken in such a way?"))
7player:tell("No action taken.  PLEASE don't use this except in extreme cases.");
8elseif (!$command_utils:yes_or_no("Have you made a best effort to @dump or otherwise save the contents in case this make things worse?"))
9player:tell("No action taken.  PLEASE do any saving you can before proceeding.");
10elseif (!$command_utils:yes_or_no("This tool comes with no warranty of any kind.  Is this really your last resort and are you prepared to accept the consequences of utter failure?  There is no undoing the actions this takes.  Do you understand and accept the risks?"))
11player:tell("No action taken.  I'm not taking any responsibility for this failing.  It's gotta be your choice.");
12else
13player:tell("OK!  Going ahead with repair attempts...");
14this:_repair();
15player:tell("All done.  If this worked, you can thank Mickey.  If not, remember the promises you made above about accepting responsibility for failure.");
16endif
17"Last modified Fri Feb 16 08:36:27 1996 MST by Minnie (#123).";

restore_from

Spec this none thisFlags rxdOwner #2Definer #14

Referenced by

none

Source

1":restore_from(OLD_MAIL_RECIPIENT, LOST_STRING)";
2"This clears all biglist properties from this object, then";
3"scans the properties of OLD_MAIL_RECIPIENT, which must be a descendant";
4"of $big_mail_recipient, looking for those corresponding to mail messages,";
5"and then rebuilds the message tree entirely from scratch.";
6"";
7"No attempt is made to preserve the original tree structure.";
8"The live/deleted state of any given message is lost;";
9"all messages, including formerly rmm-ed ones, are restored to .messages";
10"";
11"In the (unlikely) event that message-body properties have been lost, the";
12"affected messages are given a one-line body consisting of LOST_STRING";
13"";
14{old, ?lost_body = "###BODY-LOST###"} = args;
15if (!($perm_utils:controls(caller_perms(), this) && $perm_utils:controls(caller_perms(), old)))
16raise(E_PERM);
17elseif (!$object_utils:isa(old, $big_mail_recipient))
18raise(E_TYPE, "First argument must be a $big_mail_recipient.");
19elseif (typeof(lost_body) != STR)
20raise(E_TYPE, "Second argument, if given, must be a string.");
21endif
22mgr = this._mgr;
23"...";
24"... destroy everything...";
25for p in (properties(this))
26delete_property(this, p);
27endfor
28this.messages = this.messages_going = {};
29"...";
30"... look at all properties...";
31msgcount = lostcount = 0;
32for p in (properties(old))
33if (index(p, " ") == 1)
34pvalue = old.(p);
35"... ignore everything except level-0 nodes...";
36if (pvalue[1..min(1, $)] == {0})
37for msg in (pvalue[2])
38if ((ticks_left() < 6000) || (seconds_left() < 2))
39player:tell("...", msgcount, " copied.");
40suspend(0);
41endif
42try
43body = old.(msg[1]);
44except e (E_PROPNF)
45body = {lost_body};
46lostcount = lostcount + 1;
47endtry
48msg[1] = this:_make(@body);
49msgtree = mgr:insert_last(this.messages, msg);
50msgcount = msgcount + 1;
51n = mgr:find_ord(msgtree, this:_message_num(@msg), "_lt_msgnum");
52if (n < msgcount)
53{msgtree, singleton} = mgr:extract_range(msgtree, msgcount, msgcount);
54msgtree = mgr:insert_after(msgtree, singleton, n);
55endif
56this.messages = msgtree;
57endfor
58endif
59endif
60endfor
61player:tell(msgcount, " messages installed on ", this.name, "(", this, ")");
62if (lostcount)
63player:tell(lostcount, " messages have missing bodies (indicated by ", toliteral(lost_body), ").");
64else
65player:tell("No message bodies were missing.");
66endif