forked from fuzzball-muck/fuzzball-muf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib-mail-MOSS1.1.muf
2305 lines (2189 loc) · 72.5 KB
/
lib-mail-MOSS1.1.muf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
@name MOSS1.0.muf=MOSS1.1.muf
@prog MOSS1.1.muf
1 10000 d
i
(
Mail Organization and Storage System <MOSS> 1.1 my Fre'ta @ FurryMUCK, etc etc
Copyright 1996 by Fre'ta <Steven Lang>
This code may be freely distributed!
If you make a change, please make some notice about it, like in the version
string, and give credit where credit is due. Also, if you think it is
something that might benefit <I know I mispelled that> others, please tell
me about it! I'm trying to design this to suit everything from the small
little garage MUCK to the big ones.
To install, just put this text into a program, and link a action to it!
Thats all! If you would like page #mail that uses the mailer, check for
the newest cmd-page, and enable LIBMAIL for the mail.
The security of this program is pretty good, it's impossible for a mortal to
forge mail <Since it's written on wizard only properties> and it's a pain
for wizzes to forge mail if encryption is on. Reading someone elses mail is
just as hard. Of course theres nothing to stop a wiz from copying the
encryption code out of this, but it's still a pain.
A wizbitted program can send a quick-mail message using the quick-mail
interface, however it will show up with the 'you quick-mail' stuff. Perhaps
in the future I will add code to allow programs to send messages and take
care of any displaying themselves.
)
( Config stuff.. If you don't want an option, comment out the line that )
( defines it, otherwise leave it defined, and add a value if needed )
( If it is something real long, a function would be recommended to save )
( space when compiled, however a function or a define will work )
( Define this to the maximum number mails can be forwarded to )
$def MAXFORWARD 5
( Define this to the max number someone can send a mail to )
$def MULTIMAX 30
( Define this to the maximum number of new messages a user can have )
$def INBOXSIZE 40
( Define this to the maximum number of saved messages before they get )
( marked to delete )
$def MAXSAVED 40
( Define this to how long until saved messages expire in seconds )
( 1 day is 86400 seconds, a week is 604800 seconds )
( A value like 86400 30 * for 30 days is a valid value )
$def EXPIRETIME 604800
( Define this to how long players have to do something when their saved )
( mailbox is full or a message is expired )
$def GRACETIME 86400
( If you want to limit message sizes, define this to either LINE for )
( limiting it to so many lines, or CHARACTER to limiting it to so many )
( characters )
$define MAILLIMIT CHARACTER $enddef
( And how many to limit it to )
$def MAILLIMITCOUNT 4096
( Maximum recursion for forward and alias evaluation before it gives up )
$def RECURSIONLIMIT 9
( Define this if you want messages to be encrypted )
$def ENCRYPTION
( Define this to a unique string with lotsa different chars - It's used to )
( generate the encryption keys, and can contain any kind of character the )
( MUCK would normally accept as input )
$def KEY "Put the string here"
( A program to call to convert any other form of mail to MOSS format )
( This program should take a dbref and an address, calling the address as )
( to from subject {mesg} sent read type )
( to is a space seperated list of dbrefs in int format, from is the dbref )
( it's from, subject is the string subject, {mesg} is a string range, sent )
( is a 'systime' of when it was sent, read is a 'systime of when it was read )
( and type is 0 for new or 1 for saved )
( For an example program, look for MOSS-convpmail the same place you found )
( this )
( $def CONVERT "$mailconvert" match )
( Just a few commands that determin if a player is a guest - Change to fit )
( your MUCK if needed )
( This needs to be defined, if you don't want to check guests just leave it )
( as 'pop 0' )
$def ISGUEST? name "Guest" stringpfx
( The prefix for alias props )
$def ALIASPROP "_page/alias/"
( Same, for the global aliases )
$def GLOBALALIASPROP "_page/galias/"
( Where to find global aliases, this should be set to a dbref for best results )
$def GLOBALALIASDBREF "page" match dup ok? if getlink then
( Converts a dbref to an ignored prop name )
$def IGNOREPROP "ignore#" swap int intostr strcat
( Where to find ignored props, again this should be set to a dbref )
$def IGNOREDBREF "page" match dup ok? if getlink then
( Prefix for page props, _page_ for older vers, _page/ for newer vers )
$def PAGEPROP "_page/"
( No user servicable parts beyond this point )
$def vernum 3
$def shortver "MOSS 1.1 by Fre'ta"
$def VERSION "Mail Organization and Storage System (MOSS) 1.1 by Fre'ta"
$def msgprep "** "
$def qmodemask 15
$def qheadermask 4
$def qnotheadermask 3
$def qpromptmask 2
$def qsavemask 1
( a *mesg* in a comment refers to to from subject {s}, being the compressed )
( list of dbrefs to send to, the person it's from, the subject, )
( and the message itself )
lvar lcount
lvar lines
lvar linelen
lvar wraplen
lvar editor
lvar lastkeynum
lvar lastkey
lvar runmode
( 0=update event, 1=interactive, 2=one-shot, 16+=quick )
( qflags: XXX )
( / \/ )
( Display \ )
( Header Display mode )
( prompt mode 00=No prompt and delete, 01=no prompt and save, 10=prompt )
: poprange ( {?} -- Pops a range - Also known as POPN )
begin dup while swap pop 1 - repeat pop
;
: pageproploc ( dbref -- dbref' )
dup "_proploc" getpropstr
dup if
dup "#" 1 strncmp not if
1 strcut swap pop
then
atoi dbref
dup ok? if
dup owner 3 pick
dbcmp if swap then
else swap
then pop
else pop
then
;
: askme2 ( -- s Reads from the user )
lines @ lcount !
begin
read
dup strip "\"" 1 strncmp not if
strip 1 strcut swap pop "<In the mailer> You say, \"" over
strcat "\"" strcat me @ swap notify
me @ name " says, \"" strcat swap strcat "\"" strcat
me @ location swap me @ swap 1 swap notify_exclude continue
then
dup strip ":" 1 strncmp not if
strip 1 strcut swap pop dup 1 strcut pop dup if
". ,':!?-" swap instr not if " " swap strcat then
then me @ name swap strcat
dup me @ location swap me @ swap 1 swap notify_exclude
"<In the mailer> " swap strcat me @ swap notify continue
then
dup until
;
: askme ( -- s Reads from the user and swallows .getlock )
begin askme2 dup ".getlock" strcmp until
;
: askmeraw ( -- s Reads from the yser and swallows .getlock, " and : allowed )
begin read dup ".getlock" strcmp until
;
: wrapsplit ( s1 i -- line1 line2 Splits a line at length, preserving words )
over strlen over >= over and if
over " " instr if
strcut swap dup " " rinstr dup if
1 - strcut 1 strcut swap pop rot strcat
else
pop strcat dup " " instr 1 - strcut 1 strcut swap pop
then exit then then
pop ""
;
: tellme ( s -- Tells the user )
wraplen @ wrapsplit dup if
swap tellme tellme exit
then pop
lcount @ dup 1 = if
pop me @ "_prefs/mail/expert" getpropstr if
" --- More ---"
else
" --- More [Yes/No/Continuous] ---"
then me @ swap notify askme
tolower dup "n" 1 strncmp not if
pop pop -2 lcount ! exit
then
"c" 1 strncmp not if -1 dup lcount ! else 1 then
then
dup -2 > if
me @ rot notify
else
swap pop
then
dup 1 > if
1 - lcount !
else
pop
then
;
: claimlock ( d -- i Tries to lock player d's mailbox, on falure returns the )
( PID with the current lock )
dup "@mail/lock" getprop dup if
dup ispid? if
over "@mail/lock/time" getprop #0 "_sys/startuptime" getprop > if
over me @ dbcmp if
"Attempting to claim lock from process " over intostr strcat tellme
over "@mail/lock/owner" getprop ".getlock" force 0 sleep
pop "@mail/lock" getprop dup if
"Unable to claim lock." tellme
else
pop me @ claimlock
then
exit
else
swap pop exit
then
else
pop "Removing stale lock." tellme
then
else
pop "Removing stale lock." tellme
then
dup "@mail/lock" remove_prop
else pop then
dup "@mail/lock" pid setprop
dup "@mail/lock/time" systime setprop
"@mail/lock/owner" me @ setprop 0
;
: killlock ( i -- i Kills the process associated with the lock, returning )
( 0 upon success or the PID of the locking process if a )
( different process has the lock )
me @ "@mail/lock" getprop over over = if
me @ "@mail/lock/owner" getprop "Killing process so " me @ name
" can access their mail" strcat strcat notify
pop kill pop me @ "@mail/lock" remove_prop
me @ claimlock
else
swap pop
dup not if pop me @ claimlock then
then
;
: clearlock ( d -- Clears the lock for d )
dup "@mail/lock" getprop pid = if "@mail/lock" remove_prop else pop then
;
: getmylock ( -- i Claims my lock, or returns 0 on falure )
me @ claimlock begin dup while
"Process " over intostr strcat
" has a lock on your mailbox, kill the process?" strcat tellme askme
tolower "y" 1 strncmp not if killlock else
"Mail command cancelled." me @ swap notify pop 0 exit
then
repeat pop 1
;
: instrcount ( s1 s2 -- Returns the number of occurences of s2 in s1 )
dup not if pop pop 0 exit then
swap dup strlen rot dup strlen 4 rotate rot "" swap subst strlen
rot swap - swap /
;
: cmdnum ( s1 s2 -- Returns the index of s2 in a space seperated list s1 )
" " swap tolower strip strcat swap " " swap tolower strip strcat swap
over over instr rot swap strcut rot instr if
pop 0 exit
then
" " instrcount
;
: initwrap ( -- Initializes word-wrap )
me @ "_prefs/mail/wrap" getpropstr dup if
atoi dup linelen ! wraplen !
else
pop 0 wraplen ! 78 linelen !
then
;
: initpaging ( -- Initializes paging )
me @ "_prefs/mail/paging" getpropstr atoi dup
lines ! lcount !
;
: getqflags ( -- i )
0
me @ "_prefs/mail/qreadmode" getpropstr dup if
"delete save prompt" swap cmdnum dup if 1 - then
+
else pop then
me @ "_prefs/mail/qheader" getpropstr dup if
"abbreviated full" swap cmdnum dup if 1 - 4 * then
+
else pop then
;
: init ( -- Initializes stuff )
"me" match me !
me @ player? not if
runmode @ if
"Sorry, only players may send mail." me @ swap notify 0
else -1 then runmode ! exit
then
me @ ISGUEST? if
runmode @ if
"Sorry, guests are not allowed to use mail." me @ swap notify 0
else -1 then runmode ! exit
then
0 lastkeynum !
runmode @ if
me @ "_prefs/mail/lastver" getpropstr atoi dup not if
pop "Welcome to " VERSION strcat tellme
"Setting up defaults in _prefs/mail..." tellme
me @ "_prefs/mail/qpre" "On %d, %n said:" setprop
me @ "_prefs/mail/qpfx" "> " setprop
me @ "_prefs/mail/qpost" " " setprop
me @ "_prefs/mail/repwrap" "78" setprop
me @ "_prefs/mail/lastver" vernum intostr setprop
"Use 'mail #options' to change the default settings." tellme
else
dup vernum = not if
"Mail has been upgraded to " SHORTVER strcat
", type 'mail #changes' for details." strcat tellme
dup 1 = if
pop 2 me @ "_prefs/mail/repwrap" "78" setprop
then
dup 2 = if
pop 3 me @ "_prefs/mail/qflags" over over getprop
rot rot remove_prop
atoi dup 3 bitand dup if
1 = if "save" else "prompt" then
me @ "_prefs/mail/qreadmode" rot setprop
else pop then
4 bitand if
me @ "_prefs/mail/qheader" "full" setprop
then
then
me @ "_prefs/mail/lastver" rot intostr setprop
else pop then
then
then
initpaging initwrap
"$lib/editor" match editor !
runmode @ 16 = if
runmode @ getqflags + runmode !
then
;
: showmenu ( s long short -- Displays a menu prompt )
me @ "_prefs/mail/expert" getpropstr tolower "y" 1 strncmp not if
": [" swap strcat "]" strcat swap pop strcat me @ swap notify
else
pop swap ": Please select a command by using at least the first letter."
strcat me @ swap notify
"Menu commands available: " swap strcat " H>elp" strcat me @ swap notify
then
;
: getname ( d -- s Gets the name checking for invalid name )
dup ok? not if
pop "*Toaded*" exit
then dup player? not if
pop "*Toaded*" exit
then name
;
: makespaces ( i -- s Makes spaces )
dup 20 > if
20 - makespaces 20 swap
else "" then
swap " " swap strcut pop strcat
;
: strpad ( s i -- s Pads s to i characters )
over strlen - makespaces strcat
;
: ignored ( d -- i If d is ignored, notify and return 1 )
IGNOREDBREF over IGNOREPROP getpropstr " " swap over strcat strcat
" #" me @ int intostr " " strcat strcat instr not if
pop 0 exit then
dup PAGEPROP "ignoremsg" strcat getpropstr dup if
"Ignore message from " 3 pick name strcat ": " strcat swap
else
pop dup name " is ignoring you"
then
strcat tellme
dup PAGEPROP "inform?" strcat getpropstr "yes" strcmp not if
me @ dup name swap " tried to mail you, but you are ignoring %o"
pronoun_sub strcat notify 1 exit
then
pop 1
;
: read_alias ( s -- s Reads alias named s )
me @ pageproploc over ALIASPROP swap strcat getpropstr dup if
swap pop exit then
pop GLOBALALIASDBREF dup ok? not if pop pop "" exit then
GLOBALALIASPROP rot strcat getpropstr
;
: refmatch ( s -- d Matches against a dref )
dup "#" 1 strncmp if pop #-1 exit then
1 strcut swap pop dup number? not if pop #-1 exit then
atoi dbref
;
: realname2ref ( s i i -- {d} Converts a name of a player or alias to )
( dbrefs, checking for recursion )
( The first i is the quiet flag, 0=quiet )
1 + dup RECURSIONLIMIT > if
"Alias recursion limit reached, ignored." tellme pop pop pop 0 exit then
3 pick not if pop pop pop 0 exit then
rot over if
dup "*" stringpfx not if
"*" over strcat match dup ok? not if
pop dup refmatch dup ok? if dup player? not if pop #-1 then then
then
dup ok? if
swap pop swap pop dup ISGUEST? if
pop if "Sorry, you may not send mail to guests." tellme then
0 exit
then swap pop dup ignored if pop 0 else 1 then exit
then pop
else
1 strcut swap pop
then
over if
dup read_alias dup not if
pop rot if
"Unknown player: " swap strcat tellme
else pop then
pop 0 exit then
swap pop
then
then
" " swap strcat
begin dup " (" instr dup while
strcut
dup ")" instr dup if
strcut swap pop strcat
else
pop pop
then
repeat pop
strip begin dup " " instr while " " " " subst repeat
" " explode 0 begin over while
rot 3 pick 3 pick + dup 5 + pick swap 4 + pick realname2ref
dup 2 + pick over + over 2 + put
begin dup while
swap over dup 4 + pick over dup 5 + pick swap - + + 2 + 0 swap -
rotate 1 -
repeat
pop swap 1 - swap
repeat
swap pop dup 2 + rotate pop dup 2 + rotate pop
;
: name2ref ( s -- {d} Converts a name of a player or alias to dbrefs )
strip dup not if pop 0 exit then 1 -1 realname2ref
;
: quietname2ref ( s -- {d} Converts a name to dbrefs quietly )
strip dup not if pop 0 exit then 0 -1 realname2ref
;
: refduppurge ( {d} -- {d} Purges duplicate dbrefs )
dup 2 + 0 swap - 0 swap rotate begin dup while
1 - swap
over begin dup while
1 - over over 5 + pick dbcmp if
rot 1 - rot rot dup 4 + rotate pop
then
repeat pop
over dup 4 + pick + 3 + 0 swap - rotate
dup dup 3 + pick 1 + swap 2 + put
repeat pop
;
: refcompress ( {d} -- s Turns a range of dbrefs to a string of dbrefs )
"" swap begin dup while
1 - rot int intostr " " swap strcat rot swap strcat swap
repeat pop strip
;
: nextcompref ( s -- s d Gets the next dbref in a compressed list )
dup " " instr dup not if pop "" swap atoi dbref exit then
strcut swap striptail atoi dbref
;
: getrecpt ( s -- s s Gets the real recepient/s of a forwarded mail and
returns everyone who can recieve it and everyone to
send it to )
0 swap begin dup while
nextcompref dup ok? if dup player? not if pop #-1 then then
dup ok? not if pop continue then
rot 1 + rot
repeat pop
dup not if
pop "" "" exit
then
refduppurge refcompress dup
0 swap begin
dup while
nextcompref dup 1
0 begin 1 +
dup RECURSIONLIMIT > if
pop poprange 1 break
then
0 0 begin
over 4 + pick over > while
over 5 + pick "_prefs/mail/forward" getpropstr quietname2ref
dup if
dup 2 + rotate over 3 + rotate rot + swap
over over + 5 + rotate pop
over 4 + pick 1 - 3 pick 4 + put
else
pop 1 +
then
repeat pop
dup not if
pop pop dup 2 + rotate pop break
then
dup 2 + rotate over 3 + rotate rot + swap
$ifdef MAXFORWARD
over MAXFORWARD > if
pop poprange 1 break
then
$endif
repeat
dup 2 + rotate over 3 + rotate rot + swap
repeat pop
refduppurge refcompress
;
: expand ( s -- s Expands a compressed reflist to a list of names )
"" begin
over while
swap nextcompref getname
over 4 pick and if
", " swap strcat
else
3 pick if
" and " swap strcat
then then
rot swap strcat
repeat
swap pop
;
: getkey2 ( d1 d2 -- s Gets the key for mail from d1 to d2 )
int swap int + dup lastkeynum @ = if
pop lastkey @ exit
then
dup lastkeynum !
"" lastkey !
begin
KEY dup strlen rot swap over over % 4 rotate swap strcut swap pop 1 strcut
pop lastkey @ strcat lastkey ! 2 / / dup while
repeat
pop lastkey @
;
: getkey1 ( d1 d2 i -- s Gets the key for mail from d1 to d2 with a length )
( of i, necessary due to a bug in encryption )
rot rot getkey2
begin over over strlen > while dup strcat
repeat swap strcut pop
;
$ifdef __version<Muck2.2fb5.46 $undef ENCRYPTION $endif
: writeprop ( d1 d2 p s -- Writes a line s from d1 to d2 to prop p )
$ifdef ENCRYPTION
$ifdef __version<Muck2.2fb5.48
4 rotate 4 pick 3 pick strlen getkey1 strencrypt "A" swap strcat
$else
4 rotate 4 pick getkey2 strencrypt "B" swap strcat
$endif
$else
4 rotate pop " " swap strcat
$endif
setprop
;
: getmailprop ( d1 d2 p -- s Reads a prop in message from d1 to d2 )
over swap getpropstr dup not if rot rot pop pop exit then
dup 1 strcut pop
" AB" swap instr dup if
dup 1 = if
pop 1 strcut swap pop rot rot pop pop exit
then
dup 2 = if
pop 1 strcut swap pop rot rot 3 pick strlen 2 - getkey1 strdecrypt exit
then
dup 3 = if
pop 1 strcut swap pop rot rot getkey2 strdecrypt exit
then
then
pop rot rot pop pop
;
: getpropref ( d p -- d Reads a dbref prop )
over swap getmailprop atoi dbref
;
: getpropint ( d p -- i Reads an int prop )
over swap getmailprop atoi
;
: writepropref ( d p d -- d Writes a dbref prop )
3 pick rot rot int intostr writeprop
;
: writepropint ( d p i -- d Writes an int prop )
3 pick rot rot intostr writeprop
;
: unreadcount ( d -- i Returns number of unread messages )
"@mail/newidx" getpropstr strlen 3 + 4 /
;
: savedcount ( d -- i Returns number of read messages )
"@mail/savedidx" getpropstr strlen 3 + 4 /
;
: indexcount ( i -- i Returns how many messages user has in mode i )
me @ swap if savedcount else unreadcount then
;
: writemesg ( *mesg* d1 d2 p -- Write a message *mesg* from player d1 to d2 )
( to prop p )
"#" strcat over over 6 pick intostr setprop "/" strcat
0 5 rotate
begin dup while
swap 1 + swap 1 - 5 pick 5 pick 5 pick 5 pick intostr strcat
4 pick 9 + rotate writeprop
repeat pop pop 3 pick 3 pick 3 pick "subject" strcat 7 rotate writeprop
over over "from" strcat 6 rotate writepropref
"to" strcat 4 rotate writeprop
;
: writetrans ( *mesg* ? d1 d2 p -- *mesg* ? Like writemesg but doesn't )
( clobber *mesg*, and ignores )
( the stack item after the message )
"#" strcat over over 7 pick intostr setprop "/" strcat
0 6 pick
begin dup while
swap 1 + swap 1 - 5 pick 5 pick 5 pick 5 pick intostr strcat
4 pick 11 + pick writeprop
repeat pop pop
3 pick 3 pick 3 pick "subject" strcat 8 pick 9 + pick writeprop
over over "from" strcat 7 pick 9 + pick writepropref
"to" strcat 5 pick 8 + pick writeprop
;
: getmesg ( prop d -- *mesg* time Reads a message in prop p on the user )
swap "#" strcat over over "/from" strcat getpropref
over "/to" strcat over 5 pick rot getmailprop -4 rotate
rot rot 3 pick
over "/subject" strcat over 5 pick rot getmailprop -4 rotate
3 pick 3 pick getpropstr atoi rot "/" strcat rot 4 rotate 4 pick
1 swap begin dup while
5 pick 3 pick intostr strcat 5 pick 5 pick rot getmailprop
-7 rotate 1 - swap 1 + swap
repeat pop pop swap pop swap "time" strcat getpropint
;
: getmesgprop ( d num mode -- prop Gets the prop for message num )
rot swap if "savedidx" else "newidx" then "@mail/" dup rot strcat rot swap
getpropstr rot 1 - 4 * strcut swap pop 4 strcut pop
striptail dup if strcat else pop pop "" then
;
: reindex ( d num mode newmode -- Reindexes a message as new mode )
( Here newmode 2 means deleted )
dup 2 = if pop "deleted" else if "savedidx" else "newidx" then then
"@mail/" swap strcat "@mail/" rot if "savedidx" else "newidx" then strcat
4 pick over getpropstr 4 rotate 1 - 4 * strcut 4 strcut over not if
pop pop pop pop pop pop exit then
rot swap strcat 5 pick 4 rotate rot setprop
3 pick 3 pick getpropstr " " over strlen 3 bitand 4 swap - 3 bitand
strcut pop strcat swap strcat setprop
;
: mytimestr ( i -- s Returns a formatted time string )
systime gmtoffset + over gmtoffset + - 86400 /
dup not if
pop "Today at"
else 1 = if
"Yesterday at"
else
"%a %b %e"
then
then over timefmt "%l:%M:%S%p" rot timefmt strip " " swap strcat strcat
;
: dumpmesg ( prop -- Dumps a message to the user )
"#" strcat me @ over getpropstr atoi swap "/" strcat
me @ over "from" strcat getpropref swap me @ over "time" strcat getpropint
"From: " 4 pick getname strcat 40 strpad
swap mytimestr strcat tellme
over over me @ swap "to" strcat getmailprop expand
"To : " swap strcat tellme
"Size: " 4 pick intostr strcat tellme
over over me @ swap "subject" strcat getmailprop dup if
"Subj: " swap strcat tellme
else pop then
" " tellme
rot 0 begin over lcount @ -2 > and while
1 + swap 1 - swap 4 pick me @ 5 pick 4 pick intostr strcat getmailprop
tellme
repeat pop pop pop pop
;
: quickdump ( prop -- Dumps a message in abbreviated format )
"#" strcat me @ over getpropstr atoi swap "/" strcat
me @ over "from" strcat getpropref swap me @ over "time" strcat getpropint
3 pick getname " (" strcat swap mytimestr strcat ") -- " strcat
3 pick me @ 4 pick "to" strcat getmailprop dup " " instr if
"(to " swap expand strcat ")" strcat else pop "" then
4 pick me @ 5 pick "subject" strcat getmailprop
dup "Page-mail" strcmp over "Quick-mail" strcmp and not over not or
7 pick 2 < and if
pop 4 rotate me @ 5 rotate "1" strcat getmailprop swap strcat
strcat tellme pop exit
then
swap strcat strcat tellme
rot 0 begin over over > while 1 +
4 pick me @ 5 pick 4 pick intostr strcat getmailprop tellme
repeat pop pop pop pop
;
: delmesg ( d prop -- Deletes a message prop on d )
"#" strcat remove_prop
;
: delmail ( d num mode -- Deletes a message and fill in the hole on d )
3 pick dup 4 pick 4 pick getmesgprop delmesg 2 reindex
;
: markread ( prop -- Marks a mailprop as read )
"#/read" strcat me @ over getpropstr if pop exit then
me @ swap systime writepropint
;
: markdel ( prop -- Marks a mailprop as deleted )
me @ swap "#/deleted" strcat "yes" setprop
;
: savemail ( num -- Saves a new mail )
me @ over 0 getmesgprop me @ swap "#/read" strcat systime writepropint
me @ swap 0 1 reindex
;
$ifndef CONVERT
$def checkmailbox
$else
: convertcall ( s d s {s} i i i -- Writes a message with the parameters )
( of *mesg* sent read type )
"sds{s}i3" checkargs
if "@mail/savedidx" else "@mail/newidx" then me @ over getpropstr
me @ "@mail/deleted" getpropstr dup if
4 strcut me @ "@mail/deleted" rot setprop striptail
else
pop me @ dup savedcount swap unreadcount + intostr
then
swap dup strlen 3 bitand " " 4 rot - 3 bitand strcut pop
3 pick strcat strcat me @ 4 rotate rot setprop
"@mail/" swap strcat me @ over "#/read" strcat 4 rotate dup if writepropint
else pop pop pop then
me @ over "#/time" strcat 4 rotate writepropint
over 4 + pick me @ rot writemesg
;
: checkmailbox ( -- Makes sure player's mailbox is all converted )
me @ "@mail/propver" getprop not if
"Please wait, converting your mailbox..." tellme
me @ 'convertcall CONVERT call
me @ "@mail/propver" 1 setprop
then
;
$endif
: getnewmesg ( d -- i Initilizes a new message on <player> and returns the )
( number )
dup "@mail/newidx" getpropstr dup strlen dup 4 / swap 3 bitand if 1 + then
dup 512 >= if
pop pop name "'s mailbox is full." strcat tellme 0 exit
then
$ifdef INBOXSIZE
3 pick "Truewizard" flag? not me @ "W" flag? not and if
INBOXSIZE over <= if
pop pop name "'s mailbox is full." strcat tellme 0 exit
then
then
$endif
3 pick "@mail/deleted" getpropstr dup if
4 strcut 5 pick "@mail/deleted" rot setprop striptail
else
pop 3 pick savedcount over + intostr
then
4 pick "@mail/" 3 pick strcat "#/time" strcat systime writepropint
rot dup strlen 3 bitand " " 4 rot - 3 bitand strcut pop strcat swap strcat
rot "@mail/newidx" rot setprop 1 +
;
: deliver ( *mesg* -- Delivers a message )
dup 4 + pick getrecpt swap expand "Sent to " swap strcat "." strcat tellme
begin
nextcompref
dup "You sense you have new mail from " me @ name strcat "." strcat notify
me @ swap dup getnewmesg dup if
over swap 0 getmesgprop 4 pick if
writetrans
else
4 rotate pop writemesg exit
then
else
"Your mailbox is full, mail lost" notify
pop dup not if
pop poprange pop pop pop exit
then
then
repeat
;
: editmail ( *mesg* i -- Edits and delivers a message from the user )
( i is the initial insertion point )
"< Entering message editor. To send your message enter '.send' >"
tellme
"< To abort this message enter '.abort' For further help enter '.h' >"
tellme
"< If you would like to say or pose, use \" to say or : to pose >"
tellme
"< To start a line with a . \" or :, use a . before it as in .. .\" or .: >"
tellme
me @ "@mail/postponed#" getpropstr not if
"< If you would like to postpone this message, enter '.postpone' >"
tellme
then
"end send abort postpone getlock" swap ".i"
begin
lines @ lcount !
begin editor @ "editorparse" call while askme repeat
tolower dup "getlock" strcmp if
dup "postpone" strcmp not if
me @ "@mail/postponed#" getpropstr if
"< Only one message may be postponed >" tellme pop
else
"< Message postponed, use resume to continue it >" tellme
pop pop pop pop pop pop
dup 4 + pick "" begin over while
swap nextcompref name " " strcat rot swap strcat
repeat swap pop over 4 + put
me @ dup "@mail/postponed" writemesg exit
then
else
"abort" strcmp if
pop pop pop
$ifdef MAILLIMIT
me @ "W" flag? not if
$ifdef MAILLIMIT=LINE
MAILLIMITCOUNT 4 pick < if
"Unable to send, message exceeds line limit of "
MAILLIMITCOUNT intostr strcat " lines" strcat tellme
".i" continue
then
$else $ifdef MAILLIMIT=CHARACTER
MAILLIMITCOUNT 0 5 pick begin dup while
dup 6 + pick strlen rot + swap 1 -
repeat pop < if
"Unable to send, message exceeds size limit of "
MAILLIMITCOUNT intostr strcat " characters" strcat
tellme ".i" continue
then
$else
$echo "Please define MAILLIMIT as either CHARACTER or LINE or undefine it"
$endif $endif
then
$endif
pop pop break
else
"Are you sure you want to abort, and lose the message?" tellme
askme 1 strcut pop tolower "y" strcmp not if
"< Message aborted >" tellme
pop pop pop pop pop begin dup while 1 - swap pop repeat
pop pop pop pop exit
then
"< Abort cancelled >" tellme
then then then
pop pop pop ""
repeat
deliver
;
: resume ( s -- Resume a postponed message )
pop me @ "@mail/postponed#" getpropstr not if
"No postponed message." tellme exit
then
"@mail/postponed" me @ getmesg me @ "@mail/postponed" delmesg pop
dup 4 + pick name2ref dup not if
"Nobody left to mail." tellme
pop poprange pop pop pop exit
then
$ifdef MULTIMAX
me @ "W" flag? not if
dup MULTIMAX > if
"Messages must be limited to a maximum of " MULTIMAX
intostr strcat " recipients." strcat tellme
poprange poprange pop pop pop exit
then
then
$endif
refcompress dup 3 pick 5 + put
expand "Resuming message to " swap strcat " about " strcat
over 3 + pick strcat tellme dup 1 + editmail
;
: my_pronoun_sub ( *mesg* time s -- *mesg time s Pronoun sub with %t, %d )
( %j and %w added )
"%%&" "%%" subst "%T" "%t" subst
"%l:%M:%S%p" 3 pick timefmt "%T" subst
"%D" "%d" subst "%a %b %e" 3 pick timefmt "%D" subst
"%W" "%w" subst 3 pick 6 + pick expand "%W" subst
"%J" "%j" subst 3 pick 4 + pick dup not if pop "something" then "%J" subst
"%%" "%%&" subst 3 pick 5 + pick swap pronoun_sub
;
: reply ( p -- Reply to a message in prop p )
me @ getmesg over if
me @ "_prefs/mail/repwrap" getpropstr atoi dup if
3 pick begin dup while
over over 5 + pick swap wrapsplit dup if
3 pick 5 + put -5 3 pick - rotate 4 rotate 1 + -4 rotate
else pop pop 1 - then
repeat pop
then pop
me @ "_prefs/mail/qpfx" getpropstr my_pronoun_sub
0 swap
begin over 5 pick < while
over 5 + pick over swap strcat 3 pick 5 + put swap 1 + swap
repeat pop pop
me @ "_prefs/mail/qpre" getpropstr my_pronoun_sub
3 pick -3 swap - rotate swap 1 + swap
me @ "_prefs/mail/qpost" getpropstr my_pronoun_sub
rot 1 + rot
then pop
dup if
"Include original message in reply?" tellme askme
tolower "y" 1 strncmp if
poprange 0
then
then
dup 4 + pick me @ int intostr strcmp if
"Reply to all recipients?" tellme askme
tolower "y" 1 strncmp not if
dup 4 + pick " " swap over strcat strcat
over 4 + pick int intostr " " swap over strcat strcat " " swap subst
" " me @ int intostr " " swap over strcat strcat subst
over 4 + pick int intostr strcat strip
else dup 3 + pick int intostr then
else dup 3 + pick int intostr then
"" begin over while swap nextcompref rot swap
dup ok? if dup player? not if pop #-1 then then
dup ok? if
dup ignored not if
int intostr " " strcat strcat
else pop then
else pop then
repeat swap pop dup not if
"Nobody left to mail." tellme pop poprange pop pop pop exit
then
$ifdef MULTIMAX
strip me @ "W" flag? not if
dup " " instrcount 1 + MULTIMAX > if
"Messages must be limited to a maximum of " MULTIMAX
intostr strcat " recipients." strcat tellme
pop poprange pop pop pop exit
then
then
$endif
over 4 + put
dup 2 + pick dup "Re: " 4 strncmp if
dup not if pop "Re: Your mail" else "Re: " swap strcat then
over 2 + put
else pop then
me @ over 3 + put