perm filename EINIT.OLD[1,3] blob
sn#785648 filedate 1985-02-12 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00020 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00003 00002 ⊂ Description of this file:
C00004 00003 ⊂ REF Horizontal attach and copy
C00006 00004 ⊂ REF, DON Reverse a line, reverse an FMUNGE character
C00008 00005 ⊂ REF Word transposition
C00009 00006 ⊂ REF Find in a list of files
C00010 00007 ⊂ REF Saving a readonly page
C00011 00008 ⊂ REF Convert a directory to file names
C00012 00009 ⊂ REF, DON Caps to small and back
C00013 00010 ⊂ DON Wait for file to be free
C00015 00011 ⊂ DON, KS Quicksort the lines on a page
C00026 00012 ⊂ ROB, KS BURP an entire file
C00030 00013 ⊂ DON Save/restore modes
C00037 00014 ⊂ DON, JJW Reply to mail
C00092 00015 ⊂ DON Archive a message
C00095 00016 ⊂ DON Purge selected pages from a file, such as BBOARD
C00108 00017 ⊂ DON Find out the name of the file being edited
C00111 00018 ⊂ RSF Send newly added BBOARD messages to "OTHER-SU-BBOARDS".
C00118 00019 ⊂ RSF, DON Perform housekeeping after having done a BBOARD merge.
C00120 00020 ⊂ DON Skim BBOARD pages
C00126 ENDMK
C⊗;
⊗⊂ Description of this file:
This is the system library of E macros. Bug reports and (copiously commented)
additions should be sent to the current librarian via "MAIL EINIT", which will
forward appropriately.
All of the macros in this file can be used by loading the appropriate page with
the extended EXECUTE command. (None require user mods.) Thus, to get the
horizontal attachment and copying macros on the next page, one would type to E:
<control>xEXE [1,3](3)<carriage return>
When you load in a page of macros this way, you'll be told the name(s) of the
principal macro(s) brought in.
Have fun!
⊗⊃
⊗⊂ REF Horizontal attach and copy
These macros are for horizontal attachments. Calling the macro HA inserts
a mark in the line (a <vt>), and aborts. Resuming under another
character picks up everything from the original mark to that character,
and places it in the horizontal attachment buffer. Doing a further
"resume", or calling the macros HD or HAB will deposit that text in a line.
Doing a deposit at the end of a line unfortunately leaves you in line
insert mode.
HC will do a copy, rather than an attach. HSAVE will save your horizontal
attach buffer in the macro HD1. Invoking the macro HD will also deposit
your horizontal attach buffer.
⊗⊃
αXDEFINE HA⊗↔
αi⊗←αs⊗←αxabort⊗↔β⊗←α⊗↑β⊗↔αβuαs⊗←αdβ⊗↔αβa⊗↔αβe
β⊗αβiα⊗=⊗αs⊗←α⊗↔αaαxred hab⊗↔αβk
αβuαβuαβxjo⊗↔αs⊗←αd
αβxabort⊗↔αβzhd⊗↔
αβ⊗↓
αXDEFINE HD⊗↔
αβzhab⊗↔αβ⊗↓
αXDEFINE HC⊗↔
αi⊗←αs⊗≠αxabort⊗↔
β⊗↔αβuαs⊗←αdβ⊗↔αi⊗αiα⊗=⊗αs⊗←α⊗↔αβaαβxred hab⊗↔αβeα2αdα⊗=⊗↑⊗↑⊗↑αβuαβ3αβxjo⊗↔αβxabort⊗↔
αβzhd⊗↔
αβ⊗↓
αXDEFINE HSAVE⊗↔
αβxatt hab⊗↔αβxred hab1⊗↔αβk
αβ⊗↓
αXDEFINE HD1⊗↔
αβzhab1⊗↔αβ⊗↓
αxsay HA HC ⊗↔
⊗⊂ REF, DON Reverse a line, reverse an FMUNGE character
The macro REVERSe reverses the current "arrow" line. The line should
have at least two characters on it.
If you're anywhere on a page of an FMUNGE star-dot file, the macro
CHRREV will reverse the character on that page.
⊗⊃
αXDEFINE revup⊗↔
αβ-αβa⊗↔
αβ⊗↓
⊗⊂ Point the arrow at the line to be reversed ⊗⊃
αXDEFINE REVERS⊗↔
αβaαβ1αβxbreak 1⊗↔αxargument attsiz.⊗↔αxset revlng⊗↔
αxargument revlng⊗↔αβzrevup⊗↔αxargument revlng⊗↔αβu
αxargument revlng⊗↔αβxjoin⊗↔
αβ⊗↓
αXDEFINE chrrv1⊗↔
⊗↔αzrevers⊗↔
αβ⊗↓
αXDEFINE CHRREV⊗↔
αlαxnonempty⊗↔αβuαxset revlng=lines.⊗↔
αxargument line.⊗↔αxsubtract revlng⊗↔αxargument revlng⊗↔αzchrrv1⊗↔
αβ⊗↓
αxsay REVERS CHRREV ⊗↔
⊗⊂ REF Word transposition
Move the cursor under the first of two words in the MIDDLE of
a line to be transposed, then execute TRANSP.
⊗⊃
αXDEFINE TRANSP⊗↔
β⊗↔αs α β⊗↔αs α β⊗↔ ⊗; break the line around the two words
αβ-αβaαβuαβe ⊗; grab the second and move it up ahead of the first
αβuαβ3αβxjo⊗↔ ⊗; go up a line and re-patch the world
α⊗=αd ⊗; pick up last part of last line, leaving cursor in useful place
αβ⊗↓
αxsay TRANSP ⊗↔
⊗⊂ REF Find in a list of files
Do an extended FIND command to establish a search string. Then take the
cursor and point it to the first of a list of files (one to a line), and
execute FLFIND. The files will be searched in sequence until either the
next blank line in the list of names, or until the current string is
found.
⊗⊃
αXDEFINE FLFIND⊗↔
αxstopone⊗↔αxsilent⊗↔αxterse⊗↔
α∞αzflfnd1⊗↔
αxstopall⊗↔α-αxsilent⊗↔α-αxterse⊗↔
αβ⊗↓
αXDEFINE FLFND1⊗↔
αβ0αxnonempty⊗↔αxpoint /-r/2p/1l⊗↔
αzflfnd2⊗↔αh⊗↔
αβ⊗↓
αXDEFINE FLFND2⊗↔
αvαβ*
α2αxabort⊗↔
αβ⊗↓
αxsay FLFIND ⊗↔
⊗⊂ REF Saving a readonly page
It's often useful to be able to save the world (write out the in-core pages)
when in readonly mode, by leaving readonly mode, saving, and then returning.
This macro turns it into one command.
⊗⊃
αXDEFINE SAVE⊗↔
αXREADWRITE⊗↔αβ.αXREADONLY⊗↔
αβ⊗↓
αxSAY SAVE ⊗↔
⊗⊂ REF Convert a directory to file names
FIXFIL takes a page of directory information from WILD or DIR, and converts
it to a list of file names, one to a line. Useful for editing directories.
⊗⊃
αXDEFINE FFIL⊗↔
α6α .α3α [α3α β,α3α ]αK⊗↔⊗↔αβ⊗↓
αXDEFINE FIXFIL⊗↔
αβLαβxarg lines.⊗↔αβZFFIL⊗↔
αβLαF αβ\αβ∞⊗↔αβLαβ⊗↓
αxSAY FIXFIL ⊗↔
⊗⊂ REF, DON Caps to small and back
CTS changes a single capital letter to a small letter; STC does the inverse.
⊗⊃
αXDEFINE CTS⊗↔
αxsilent⊗↔αxterse⊗↔αxstopone⊗↔αβ9αβ6αxset ctsval⊗↔
αβ#αzctschk⊗↔α-αxterse⊗↔αxstopall⊗↔α-αxsilent⊗↔
αβ⊗↓
αXDEFINE STC⊗↔
αxsilent⊗↔αxterse⊗↔αxstopone⊗↔αβ6αβ4αxset ctsval⊗↔
αβ#αzctschk⊗↔α-αxterse⊗↔αxstopall⊗↔α-αxsilent⊗↔
αβ⊗↓
αXDEFINE CTSCHK⊗↔
αzctsck1⊗↔α
αβ⊗↓
αXDEFINE CTSCK1⊗↔
αβ6αβ4αβxiflt ascii.⊗↔αxset ctschr=ascii.⊗↔αβ3αβ2αxremainder ctschr⊗↔
αβ2αβ6αβxifge ctschr⊗↔αxifle ctschr⊗↔
αβxargument ctsval⊗↔αxadd ctschr⊗↔αβxcharacter ctschr⊗↔α⊗↑
αβ⊗↓
αxsay CTS STC ⊗↔
⊗⊂ DON Wait for file to be free
The OPEN macro will try once per second to open the file for writing. When
the file is no longer in use by other people it will succeed, at which point
it prints a message to that effect and breedles the terminal. At each
unsuccessful attempt it prints the list of people using the file; this
cannot be suppressed, so consider it a feature.
⊗⊃
αXDEFINE OPEN⊗↔
αxstopone⊗↔αxsilent⊗↔αxterse⊗↔α∞αzopen2⊗↔α-αxterse⊗↔α-αxsilent⊗↔αxstopall⊗↔
αβ⊗↓
αXDEFINE OPEN2⊗↔
αzopen3⊗↔α1αv
αβ⊗↓
αXDEFINE OPEN3⊗↔
αxopen⊗↔αxsay File now open for writing. ⊗↔αxbeep⊗↔α2αxabort⊗↔
αβ⊗↓
αxSAY OPEN ⊗↔
⊗⊂ DON, KS Quicksort the lines on a page
The macro QSORT takes all lines on the current page (which may be one
of several incore pages) and sorts them based on a collating sequence determined
by the QCHMAP macro. (The QCHMAP macro provided below simply maps lower-case
letters to their upper-case equivalents.) The field sorted on is the entire
line; someday there may be facilities for specifying character positions, but
it doesn't really seem worth it. Note: Lines which match on the first several
characters will be assumed equal and will be left unsorted (since the sort is
"stable", their relative order will be unchanged). You'll be told if this
happens.
QSORT is reasonably fast for small pages, say up to 100 lines or so.
Above that and the SSORT or MSORT program is probably your best bet. QSORT
should have no side effects ("marks" unchanged, modes restored, etc.).
QSORT updates the screen after each partitioning to give you something
to watch while it's working. If you don't want this (especially if you're
invoking QSORT from another macro and don't want to be bothered), execute the
QNOSHO macro before invoking QSORT.
⊗⊃
⊗⊂ First step is to separate any empty lines, to save special-case
testing in low-level routines. Then we start recursion via QSORT1.
⊗⊃
αXDEFINE QSORT⊗↔
αZENTRYX⊗↔α-αXUNDELETE⊗↔
αXSET QRAPID=RAPID.⊗↔α-αXMAXIMUM QRAPID⊗↔αβ0αXMINIMUM QRAPID⊗↔
αβ2αXMULTIPLY QRAPID⊗↔αXADD QRAPID⊗↔
αXRAPID⊗↔
α0αXSET QLEVEL⊗↔
αLβ⊗→β⊗↔α-αAα∞αZQEMPTY⊗↔⊗↔α-αPαEαβDαP
αZQSORT1⊗↔
αLα-αβD
αβXARGUMENT QRAPID⊗↔αXRAPID⊗↔
αZEXIT⊗↔
αβ⊗↓
⊗⊂ QEMPTY looks for an empty line and appends it onto the attach buffer.
We first back up so that (a) we'll find the second of two consecutive
blank lines and (b) we won't go to the next incore page (X EMPTY does
so if given at end of page).
⊗⊃
αXDEFINE QEMPTY⊗↔
αUαXEMPTY⊗↔α+αA
αβ⊗↓
⊗⊂ QSORT1 is the top recursive call; it sorts the current page based on the
first char of each line, and uses QEQUAL to subsort on equality. It returns
at once if there are fewer than 2 lines, else it uses the median line to
partition the other lines into 3 subpages and recurses.
⊗⊃
αXDEFINE QSORT1⊗↔
αXIFLT LINES.⊗↔
α∞αLβ⊗→α-αPβ⊗→
αXSET QVALUE←LINES.⊗↔α2αXDIVIDE QVALUE⊗↔
αXARGUMENT QVALUE⊗↔⊗↔
αZQSHOW⊗↔
αXARGUMENT ASCII.⊗↔αZQCHMAP⊗↔αXSET QVALUE⊗↔
αLαXARGUMENT LINES.⊗↔αZQSPLIT⊗↔
α-αPαZQSORT1⊗↔
αPαZQEQUAL⊗↔αLα-αβD
αPαZQSORT1⊗↔
αLα-αβD
αβ⊗↓
⊗⊂ QSPLIT compares the first char of the current line with QVALUE and moves
the line to the appropriate subpage.
⊗⊃
αXDEFINE QSPLIT⊗↔
αXARGUMENT ASCII.⊗↔αZQCHMAP⊗↔αXSET QVAL2⊗↔
⊗↔
αZQSPLT0⊗↔
αβ⊗↓
⊗⊂ QSPLT0 decides where to put the line above us, whose QLEVELth char is QVAL2.
⊗⊃
αXDEFINE QSPLT0⊗↔
αXARGUMENT QVAL2⊗↔αXIFNE QVALUE⊗↔
α-αAαXSET QLINE←LINE.⊗↔
αZQLESS⊗↔
αPα∞αLαE
α-αPαXARGUMENT QLINE⊗↔αL
αβ⊗↓
⊗⊂ QLESS moves the line above us to the previous page if QVAL2 < QVALUE, and
also aborts our caller (QSPLT0) if that's the case.
⊗⊃
αXDEFINE QLESS⊗↔
αXARGUMENT QVAL2⊗↔αXIFLT QVALUE⊗↔
αLαUαE
αPαXARGUMENT QLINE⊗↔αL
α2αXABORT⊗↔
αβ⊗↓
⊗⊂ QEQUAL is called to subsort a page on which all lines are, so far, equal.
It aborts at once if there's only one line, else it increments QLEVEL,
snarfs all lines which contain only QLEVEL chars (just as QSORT snarfed all
empty lines), and calls QSORT2 to sort the rest.
⊗⊃
αXDEFINE QEQUAL⊗↔
αXIFLT LINES.⊗↔
αXADD QLEVEL⊗↔
αLβ⊗→αCαUαXARGUMENT LINES.⊗↔αZQSNARF⊗↔α-αPαEαβDαP
αZQSORT2⊗↔
αLα-αβD
αXSUBTRACT QLEVEL⊗↔
αβ⊗↓
⊗⊂ QSNARF and QSNRF0 attaches the current line if it has only QLEVEL chars.
⊗⊃
αXDEFINE QSNARF⊗↔
αZQSNRF0⊗↔
⊗↔
αβ⊗↓
αXDEFINE QSNRF0⊗↔
αXARGUMENT QLEVEL⊗↔αXIFGE CHARS.⊗↔
α+αAαU
αβ⊗↓
⊗⊂ QSORT2 is the secondary recursive call; it sorts the current page based on
the QLEVELth char of each line, and uses QEQUAL to subsort on equality. It
returns at once if there are fewer than 2 lines, else it uses the median
line to partition the other lines into 3 subpages and recurses.
⊗⊃
αXDEFINE QSORT2⊗↔
αXIFLT LINES.⊗↔
αZQDEEP⊗↔
α∞αLβ⊗→α-αPβ⊗→
αXSET QVALUE←LINES.⊗↔α2αXDIVIDE QVALUE⊗↔
αXARGUMENT QVALUE⊗↔⊗↔
αZQSHOW⊗↔
αZQEVAL⊗↔
αLαXARGUMENT LINES.⊗↔αZQSPLT2⊗↔
α-αPαZQSORT2⊗↔
αPαZQEQUAL⊗↔αLα-αβD
αPαZQSORT2⊗↔
αLα-αβD
αβ⊗↓
⊗⊂ QDEEP tests whether we're getting too deep in recursion due to lines which
match on a long leading string. For now, if so, we leave the lines unsorted
and issue a warning.
⊗⊃
αXDEFINE QDEEP⊗↔
α2α0αXIFLE QLEVEL⊗↔
αXARGUMENT LINES.⊗↔αXSAY WARNING!! ⊗↔
αXARGUMENT QLEVEL⊗↔αXSAY lines match on their first ⊗↔
αβXSAY chars and are left unsorted.⊗↔
α2αXABORT⊗↔
αβ⊗↓
⊗⊂ QEVAL and QEVL0 figure out what the character is that's QLEVEL chars in on
the current line, and leaves us one the line below. It uses the line-editor
if possible, since it's faster, but if it won't fit it uses cruder methods.
The value is put into QVALUE.
⊗⊃
αXDEFINE QEVAL⊗↔
αZQEVL0⊗↔
αCα1αXBREAK 1⊗↔αXARGUMENT QLEVEL⊗↔αβKα∞αXJOIN⊗↔αE
αXARGUMENT ASCII.⊗↔αZQCHMAP⊗↔αXSET QVALUE⊗↔αβD
αβ⊗↓
αXDEFINE QEVL0⊗↔
αXLETEST⊗↔
αXARGUMENT QLEVEL⊗↔α αXARGUMENT ASCII.⊗↔αZQCHMAP⊗↔αXSET QVALUE⊗↔⊗↔
α2αXABORT⊗↔
αβ⊗↓
⊗⊂ QSPLT2 is like QSPLIT except it looks at the QLEVELth char.
⊗⊃
αXDEFINE QSPLT2⊗↔
αZQEVAL2⊗↔
αZQSPLT0⊗↔
αβ⊗↓
⊗⊂ QEVAL2 and QEVL02 are the same as QEVAL except the value goes into QVAL2.
⊗⊃
αXDEFINE QEVAL2⊗↔
αZQEVL02⊗↔
αCα1αXBREAK 1⊗↔αXARGUMENT QLEVEL⊗↔αβKα∞αXJOIN⊗↔αE
αXARGUMENT ASCII.⊗↔αZQCHMAP⊗↔αXSET QVAL2⊗↔αβD
αβ⊗↓
αXDEFINE QEVL02⊗↔
αXLETEST⊗↔
αXARGUMENT QLEVEL⊗↔α αXARGUMENT ASCII.⊗↔αZQCHMAP⊗↔αXSET QVAL2⊗↔⊗↔
α2αXABORT⊗↔
αβ⊗↓
⊗⊂ QCHMAP takes its argument (via the rep count) and maps it into a new value
based on the collating sequence desired. The result is returned by ending
QCHMAP with an ARGUMENT command. This particular version of QCHMAP simply
converts lower-case letters to upper-case. NOTE: Be sure to use doublebucky
on numeric arguments in QCHMAP, since it's called from the line editor.
⊗⊃
αXDEFINE QCHMAP⊗↔
α#αXSET QCHARX⊗↔
αβ1αβ2αβ3αXREMAINDER QCHARX⊗↔
αβ9αβ7αXDIVIDE QCHARX⊗↔
αβ-αβ3αβ2αXMULTIPLY QCHARX⊗↔
α#αXARGUMENT QCHARX⊗↔
αβ⊗↓
⊗⊂ QORDLT is used by QORDER to test for QCHAR1 being less than QCHAR2. If
so, we abort to QLESS, else we return.
⊗⊃
αXDEFINE QORDLT⊗↔
αXARGUMENT QCHAR1⊗↔αXIFLT QCHAR2⊗↔
α2αβD
α5αXABORT⊗↔
αβ⊗↓
⊗⊂ QSHOW just updates the screen. It's done in a macro so that QNOSHO can
turn it off (by making it do an altmode instead).
⊗⊃
αXDEFINE QSHOW⊗↔
αV
αβ⊗↓
αXDEFINE QSHOW0⊗↔
⊗≠
αβ⊗↓
αXDEFINE QNOSHO⊗↔
αXSET QSHOW←QSHOW0⊗↔
αβ⊗↓
αxsay QSORT ⊗↔
⊗⊂ And we'll be needing ENTRY/EXIT macros: ⊗⊃ αXEXECUTE EINIT.CMD[1,3](13)⊗↔
⊗⊂ ROB, KS BURP an entire file
(Original idea and simple minded implementation by ROB, all the niceness
by KS.)
(Sept 24, 1983 - Altered to reflect new block size (8 records/block). The word
"track" is no longer used in the typeout. - RSF)
The BELCH macro `burps' an entire file, using the /∞F file switching
trick. When finished, it announces the number of records in the file
before and after BELCHing, and the number of disk tracks thus freed.
Side effects: A jump is made to the directory page, and the page stack
will reflect that. Macros named BEFORE, AFTER, SAVED,
TRACKS, and SAYER are created (or altered).
⊗⊃
αXDEFINE BELCH⊗↔
α1αPα∞αL⊗↑⊗↑ ⊗; Go to directory page, ENDMK line
αCαβXBREAK 1⊗↔αβ1αβK ⊗; Flush "C" from record number
αβXBREAK 5⊗↔αβ-αβC ⊗; Flush other junk, move up
αXREDEFINE BEFORE⊗↔αβK ⊗; Define BEFORE as old total records
αβ1αβXSUBTRACT BEFORE⊗↔ ⊗; Flush leading zeros, adjust number
αε/∞F⊗↔ ⊗; BURP entire file
αCαβXBREAK 1⊗↔αβ1αβK ⊗; Flush "C" from record number
αβXBREAK 5⊗↔αβ-αβC ⊗; Flush other junk, move up
αXREDEFINE AFTER⊗↔αβK ⊗; Define AFTER as new total records
αβ1αβXSUBTRACT AFTER⊗↔ ⊗; Flush leading zeros, adjust number
αXSET SAVED←BEFORE⊗↔ ⊗; Calculate savings in records
αXARGUMENT AFTER⊗↔αXSUBTRACT SAVED⊗↔
αXSET TRACKS←BEFORE⊗↔ ⊗; Calculate track savings
αβ7αXADD TRACKS⊗↔
αβ8αXDIVIDE TRACKS⊗↔
αXSET TRKAFT←AFTER⊗↔
αβ7αXADD TRKAFT⊗↔
αβ8αXDIVIDE TRKAFT⊗↔
αXARGUMENT TRKAFT⊗↔αXSUBTRACT TRACKS⊗↔
αO ⊗; Go back where we were
αβI ⊗; Make a place to type
⊗α⊗βXSAY Before: αβZBEFORE⊗↔ ⊗; Type "αβXSAY Before:"&BEFORE
. After: αβZAFTER⊗↔ ⊗; Type ". After:"&AFTER
. Saved recs: αβZSAVED⊗↔ ⊗; Type ". Saved recs:"&SAVED
. (blocks: αβZTRACKS⊗↔)⊗⊗↔ ⊗; Type "("&TRACKS&" blocks)⊗↔"
αAαXREDEFINE SAYER⊗↔ ⊗; Now make a macro out of this
αEαXCANCEL⊗↔ ⊗; And cover our tracks
αZSAYER⊗↔ ⊗; Say it all
αβ⊗↓
αxsay BELCH ⊗↔
⊗⊂ DON Save/restore modes
ENTRY and EXIT save and restore states often modified by other macros.
Macro ENTRY saves the state of the CHECK, TERSE/VERBOSE, SILENT, UNDELETE, EXACT
and STOPHOW commands. Macro EXIT restores them to the values saved by ENTRY.
(EXIT works regardless of the state of the flags when called.) EXIT assumes
that the attach buffer is available for use; i.e., there's nothing in the attach
buffer and you're not in the line editor. If this isn't true when your macro
exits, then call EXIT1 at some point where it IS true; then call EXIT2 at the
end of your macro.
Note: Since the UNDELETE command (even with negative arg) is illegal in
the line editor, EXIT1 restores the UNDELETE setting. So be sure to wait till
the last minute to call EXIT1 if you think this'll affect you.
Macro ENTRYX is the same as ENTRY but also changes the modes to -CHECK,
TERSE, SILENT, -EXACT, and STOPONE. (It leaves the UNDELETE size alone since
you might be in the line editor.)
If a macro using ENTRY/EXIT in turn calls another macro that does so,
the "secondary" calls are ignored. (ENTRYX still sets modes as given above.)
Thus, when the second-level macro exits, it will not have restored the state in
use by the top-level one. Usually, however, the states set up by the two macros
will be compatible (especially if both use ENTRYX); if not, the top-level macro
should be careful to restore the state it wants when the other macro finishes.
This may get cleaned up someday using some sort of stack arrangement.
These macros use, as variables, the macros named ENTRYC, ENTRYT, ENTRYS,
ENTRYU, ENTRYE, and ENTRYH, respectively. ENTRYN is used to count the nesting
of ENTRY/EXIT calls to prevent second-level invocations destroying the data
saved at the top level. The macros also use EXITW to save the state of the W
flag so they can know whether to do a CANCEL, and for other temporary storage.
⊗⊃
αXDEFINE ENTRY⊗↔
αxset exitw=entryn⊗↔αxadd entryn⊗↔ ⊗; check nesting depth
αxminimum exitw⊗↔αβ0αxmaximum exitw⊗↔ ⊗; can't use IFEQ 0 since STOPHOW is sacred
αβxargument exitw⊗↔αxabort⊗↔
αxset entryc=check.⊗↔αβ0αxminimum entryc⊗↔α-αxmaximum entryc⊗↔
αβ2αxmultiply entryc⊗↔αxadd entryc⊗↔ ⊗; +1=check, else -1
αxset entryt=terse.⊗↔α-αxmaximum entryt⊗↔αxminimum entryt⊗↔
αβ2αxadd entryt⊗↔ ⊗; 1=terse, 2=normal, 3=verbose
αxset entrys=silent.⊗↔αβ0αxmaximum entrys⊗↔αxminimum entrys⊗↔
αβ2αxmultiply entrys⊗↔αxsubtract entrys⊗↔ ⊗; +1=silent, else -1
αxset entryu=undmax.⊗↔α-αxmultiply entryu⊗↔ ⊗; -size of undelete buffer
αxset entrye=exact.⊗↔αβ0αxmaximum entrye⊗↔α-αxminimum entrye⊗↔
αβ2αxmultiply entrye⊗↔αxsubtract entrye⊗↔ ⊗; +1=exact, else -1
αxset entryh=stopho.⊗↔αβ2αxadd entryh⊗↔ ⊗; 1=stopall, 2=stopzero, 3=stopone
αβ⊗↓
αXDEFINE ENTRYX⊗↔
αzentry⊗↔
αxterse⊗↔αxsilent⊗↔αxstopone⊗↔α-αxcheck⊗↔α-αxexact⊗↔
αβ⊗↓
αXDEFINE EXIT⊗↔
αzexit1⊗↔αzexit2⊗↔
αβ⊗↓
αXDEFINE EXIT1⊗↔
αxset exit2←exit2q⊗↔ ⊗; null EXIT2 macro in case ENTRYN > 1
αxsubtract entryn⊗↔αβ0αxmaximum entryn⊗↔αxset exitw=entryn⊗↔
αxminimum exitw⊗↔αβxargument exitw⊗↔αxabort⊗↔ ⊗; go away if not top-level
αxset exitw=wflag.⊗↔αxadd exitw⊗↔ ⊗; 1=page unchanged, else 2
αβxargument entryu⊗↔αxundelete⊗↔ ⊗; restore undelete size (can't wait for EXIT2)
α2αβ⊗↔ ⊗; create EXIT2 macro (eschew insert mode to defeat autowrite)
⊗α⊗βxargument entryc⊗⊗↔⊗αxcheck⊗⊗↔ ⊗; restore free-storage check mode
⊗α⊗βxargument entrye⊗⊗↔⊗αxexact⊗⊗↔ ⊗; restore exactness of searches
⊗α⊗βxargument entrys⊗⊗↔⊗αxsilent⊗⊗↔ ⊗; restore silence mode
⊗↔ ⊗; keep lines short to stifle E's echoing bug
⊗αxstop:=all=zero=one=αb:αβxargument entryh⊗↔αk=
αdαs=αk⊗↔⊗⊗↔ ⊗; restore stophow setting
:=⊗αxterse=⊗α-⊗αxterse=⊗αxverbose=αb:αβxargument entryt⊗↔αk=
αdαs=αk⊗↔⊗⊗↔ ⊗; restore terse/verbose mode
αβuαβ2αβaαxredefine exit2⊗↔αβk
α1αβ⊗↔ ⊗; create macro to do CANCEL if necessary (else altmode)
:=⊗αxcancel⊗⊗↔=⊗⊗≠=αb:αβxargument exitw⊗↔αk=αdαs=αk⊗↔
αβaαxredefine exitw⊗↔αβk ⊗; can reuse name EXITW for this
αzexitw⊗↔
αβ⊗↓
αXDEFINE EXIT2Q⊗↔
αx⊗↔
αβ⊗↓
αβ0αXSET ENTRYN⊗↔
αxsay ENTRY/EXIT ⊗↔
⊗⊂ DON, JJW Reply to mail
The REPLY macro makes it possible to send mail to whomever sent you a
particular piece of mail, without your having to type the network address or the
subject. You can also (optionally) include copies to all recipients of the
original message (optionally excluding "cc" recipients).
The basic operation of the macro is a three-step process. First, you
execute the REPLY macro. This sets up various headings based on the message on
the current page. (It's okay to have more than one in-core page, but results
are unspecified if there are multiple messages on one page.) The headings
should be self-explanatory. At the bottom of the page is the "reply text",
which is initially set up to be a line saying when the incoming message was sent
(if known) or received (if not). NOTE: If you have anything in the attach
buffer when you execute REPLY, the buffer set down as part of the reply text.
Having executed REPLY, you then edit the resulting template to add or
delete recipients and/or change the message text or subject. (Additional
recipients should be entered one per line with one of the prefaces "Also-To:"
or "Reply-cc:".) The only fields that must not be deleted entirely are the
"Replying-To" field (which must come first) and the "Reply-Text" field (which
must come last).
When you're done editing the message, you then type <control>% to
execute the % macro set up by REPLY (you're reminded of this by REPLY). This
sends the mail and restores the page to its original state.
If, after executing REPLY, you decide you don't really want to send
the reply at all, just do a CANCEL (or delete all the reply-related stuff).
To include all recipients of the original message on the mailing list
for the reply, execute the REPLY macro with an argument greater than 1. E.g.,
<control>2<control>ZREPLY<cr>. To include all but the "cc" recipients, give an
argument of "+", i.e., <control>+<control>ZREPLY<cr>. Doing either of these
also causes the initial reply-text to include the name of the original sender.
People listed as having received "ReSent" copies of the message are considered
to be "cc" recipients.
Notes on operation: REPLY makes a good try at parsing the more common
of the hairy contructs permitted under RFC822, the document defining network
mail protocols. Quoted strings, parenthesised comments, and broketed network
addresses are all handled correctly. If the recipient list of the original
message lacks some host-names, the host of the original sender is assumed (some
sites' mailers fail to put full network addresses for "local" addressees), or
the host of the first "ReSent-from" entry, if the original sender has no host
specified. Foreign distribution-list files will probably be parsed correctly,
but the mail command will fail, since you can't access such files from here.
Local distribution lists, file destinations (#<file> construct), and forwarding
names (such as BUG-xxxx) should work.
During the "editing" phase (after executing REPLY but before executing
"%" to send the mail), the following three macros may be useful (they are loaded
in along with REPLY): CCME adds a "Reply-cc" to yourself. TOLIST deletes the
"Replying-To" line and changes the next line from "Also-To" or "Reply-cc" into
the Replylng-To line (this is for when the original message was sent to a
distribution list by someone on that list, and you want to reply to the list
without shipping the original sender an extra copy). OLDMSG appends the entire
text of the original message (header and all) to the end of the Reply-Text,
indented and set off by lines of hyphens.
REPLY and % are a bit slow, though fast enough for small mailing lists.
The slowest part may well be loading them in with EXECUTE! If you use REPLY
frequently, but don't want to wait for it to be loaded in every time you execute
your personal EINIT file for something else, you may want to create a macro
(say, R) that EXECUTEs this page of EINIT[1,3] and then does
<control>#<control>ZREPLY<cr>. With a little more hackery you could rig the R
macro to suppress the EXECUTE command on later calls -- e.g., have R invoke R1
to do the EXECUTE, and then replace R1 with some sort of "no-op".
REPLY and % leave most modes, such as STOPHOW and TERSE, unchanged. The
parenthesis characters for the "(" and ")" commands are changed (if necessary)
to be the default of "real" parentheses. The search-stop-line (SSLINE) value is
cleared, and the defaults for the search/substitute commands are changed.
Various macro names are used for numeric values and other temporary storage, and
the % macro is of course overridden. The undelete buffer size is unchanged; the
undelete buffer is left holding the reply subject and message text, such that an
UNDELETE command retrieves them.
⊗⊃
αXDEFINE REPLY⊗↔
αZRENTRY⊗↔ ⊗; do our entry stuff (save modes, etc.)
αXSET REPLW=WFLAG.⊗↔ ⊗; remember whether W flag was on
αZREPL0⊗↔ ⊗; make sure blank line and no attach buffer
αβ#αZREPL1⊗↔ ⊗; put arg into REPARG for use by submacros
αXPAREN⊗↔ ⊗; make sure paren chars are "(" and ")"
αZRPMAIN⊗↔ ⊗; call main macro (this additional level
αZEXIT2⊗↔ ⊗; of nest makes aborting less noisy)
αβ⊗↓
αXDEFINE RENTRY⊗↔ ⊗; does entry stuff for REPLY and REPSND
⊗≠αZENTRYX⊗↔ ⊗; leave line-editor (if in), save modes
α-αXUNDELETE⊗↔ ⊗; speed things up a little more
αXSET REPLJC=CMAR.⊗↔αXSET REPLJL=LMAR.⊗↔αXSET REPLJR=RMAR.⊗↔ ⊗; JFILL info
αXSET REPLBK=BRKCOL.⊗↔αXSET REPDNT=INDENT.⊗↔ ⊗; BREAK and INDENT values (latter faked)
αβ⊗↓
αXDEFINE REXIT1⊗↔ ⊗; first stage of exit stuff (2nd is EXIT2)
αZEXIT1⊗↔
αXATTACH REPLJC⊗↔ ⊗; get a line to work with
αXJFILL REPLJC,REPLJL,REPLJR⊗↔ ⊗; restore justification parameters
αXINDENT REPDNT⊗↔ ⊗; restore indentation default
αXBREAK REPLBK⊗↔ ⊗; restore default break column
αβKαXSSLINE⊗↔ ⊗; discard junk line, clear search stop
αβ⊗↓
αXDEFINE RPMAIN⊗↔
αZREPL2⊗↔ ⊗; find sender
αZREPL3⊗↔ ⊗; find orig recipients if REPARG=+1 or >1
αZREPL4⊗↔ ⊗; find original cc names if REPARG > 1
αZREPL5⊗↔ ⊗; find subject
αZREPL6⊗↔ ⊗; put heading and preface on reply text
αZREPL7⊗↔ ⊗; set up macro % = REPSND
αZREXIT1⊗↔
αβ⊗↓
αXDEFINE REPLXX⊗↔ ⊗; error exit
αZREXIT1⊗↔
αXSET REPTMP=LINE.⊗↔
αXSTOPZERO⊗↔ ⊗; suppress error if no text to attach
αXARGUMENT REPLIN⊗↔αLα∞αβ!αA ⊗; restore attach buffer (if any)
αXSSLINE⊗↔
αXARGUMENT REPTMP⊗↔αL ⊗; now, where were we?
α-α1αXARGUMENT MDEPTH.⊗↔αXABORT⊗↔ ⊗; abort all but top level
αβ⊗↓
αXDEFINE REPL0⊗↔
α∞αLαXSET REPLIN=LINE.⊗↔ ⊗; go to bottom of incore page, save line #
α0αA ⊗; drop attach buffer, if any, as reply text
⊗↑α0αXNONEMPTY⊗↔⊗↔β⊗↔ ⊗; put in blank line if wasn't any
αXADD REPLIN⊗↔
αβ⊗↓
αXDEFINE REPL1⊗↔
αβ#αXSET REPARG⊗↔α2αXMULTIPLY REPARG⊗↔ ⊗; map 1 → 2, +1 → 3, >1 → >3
αZREPARG⊗↔α⊗→αXSET REPTMP=ASCII.⊗↔⊗≠ ⊗; enter line editor, then abort
α4α3αXIFEQ REPTMP⊗↔ ⊗; was first char of REPARG a "+"?
αXADD REPARG⊗↔ ⊗; if so, incr doubled value
αβ⊗↓
αXDEFINE REPL2⊗↔
αLαXEMPTY⊗↔α+α0αXSSLINE⊗↔ ⊗; searches stop before first blank line
αZREPL2A⊗↔ ⊗; look for right line in header
αZRFC822⊗↔ ⊗; parse RFC822 format, flush comments, etc.
αXARGUMENT REPLIN⊗↔αLαE ⊗; take copy of line down to bottom
αXADD REPLIN⊗↔ ⊗; old attach buffer now further down
⊗↔α1αβ⊗↔,αβUαXJOIN⊗↔ ⊗; put comma on the end
α1αXSIN⊗↔ ⊗; remove tabs (exist only if "∂" line)
αF,αβ\ ,⊗↔αXBREAK SRCHAR.⊗↔ ⊗; break ahead of first comma
⊗↔αβD⊗↑ ⊗; flush stuff from comma to end
α1αZREPNAM⊗↔ ⊗; parse what's left to form a name
α1αβ⊗↔⊗αI[In reply to message⊗α⊗β3⊗αXIFLE REPARG⊗⊗↔⊗αI from α⊗↔
α2αXREDEFINE REPFRM⊗↔αβD ⊗; save id of sender for "in reply to" text
αIReplying-To: α⊗↔ ⊗; add our special field name
αXSET REPLN2=LINE.⊗↔ ⊗; remember this position for REPLST
αβ⊗↓
αXDEFINE REPL2A⊗↔
αXSTOPZERO⊗↔αLαF⊗↓≡⊗↔Reply-To:⊗↓⊗↔⊗↔αXSET RPRPTO⊗↔ ⊗; flag name found on Reply-To line
αXSTOPONE⊗↔αXIFNE NFOUND.⊗↔ ⊗; exit if found!
αXSTOPZERO⊗↔⊗↑αF⊗↓≡⊗↔From:⊗↓⊗↔⊗↔α0αXSET RPRPTO⊗↔
αXSTOPONE⊗↔αXIFNE NFOUND.⊗↔
⊗↑α1α5αXIFNE ASCII.⊗↔ ⊗; see if top line starts with "∂"
αXSAY Sorry -- Can't find sender's name anywhere in header.⊗↔
αZREPLXX⊗↔ ⊗; abort
αβ⊗↓
αXDEFINE REPL3⊗↔
α3αXIFLE REPARG⊗↔ ⊗; do "also-to"s only if arg was +1 or >1
αXSET RPLSTF←REPL3F⊗↔αXSET RPLSTI←REPL3I⊗↔ ⊗; set up things for REPLST
α1αZREPLST⊗↔αXIFEQ REPTOP⊗↔ ⊗; REPTOP=1 iff no "to"s found
αβXSAY Warning -- Unable to find any "To" lines.⊗↔
αβ⊗↓
αXDEFINE REPL3F⊗↔
αF⊗↓≡⊗↔To:⊗↓⊗↔
αβ⊗↓
αXDEFINE REPL3I⊗↔
αIAlso-to: α⊗↔
αβ⊗↓
αXDEFINE REPL4⊗↔
α4αXIFLE REPARG⊗↔ ⊗; send to cc's only if arg was >1
αXSET RPLSTF←REPL4F⊗↔αXSET RPLSTI←REPL4I⊗↔ ⊗; set up things for REPLST
α1αZREPLST⊗↔αXSET RPLSTF←REPL4G⊗↔ ⊗; find "cc"s, set up for "ReSent-to"s
αXARGUMENT REPTOP⊗↔αZREPLST⊗↔αXIFEQ REPTOP⊗↔ ⊗; REPTOP=1 iff neither found
αβXSAY Warning -- Unable to find any "CC" lines.⊗↔
αβ⊗↓
αXDEFINE REPL4F⊗↔
αF⊗↓≡⊗↔cc:⊗↓⊗↔
αβ⊗↓
αXDEFINE REPL4G⊗↔
αF⊗↓≡⊗↔ReSent-To:⊗↓⊗↔
αβ⊗↓
αXDEFINE REPL4I⊗↔
αIReply-cc: α⊗↔
αβ⊗↓
αXDEFINE REPL5⊗↔
αXARGUMENT REPLN2⊗↔αXSSLINE⊗↔ ⊗; don't search reply text
αXSTOPZERO⊗↔⊗↔αLαF⊗↓≡⊗↔Subject:⊗↓⊗↔αXSTOPONE⊗↔ ⊗; look for RFC822 subject line
αXARGUMENT NFOUND.⊗↔αXCASE REPL5A REPL5B⊗↔
αXARGUMENT REPLIN⊗↔αLαE ⊗; take attached reply-subject down to our header
αXADD REPLIN⊗↔ ⊗; note movement downward of reply text
α+αXSSLINE⊗↔αFReply-Subject: re: re:αβ\Reply-Subject: re:⊗↔ ⊗; eschew redundant tautology
αβ⊗↓
αXDEFINE REPL5A⊗↔
αZREP5A0⊗↔ ⊗; try for "∂" line (aborts us if succeeds)
α1αβ⊗↔Reply-Subject: reply to messageαβA ⊗; couldn't find subject at all
αβ⊗↓
αXDEFINE REP5A0⊗↔
α1α5αXIFEQ ASCII.⊗↔ ⊗; check top line for "∂"
α+αXSSLINE⊗↔α2αF⊗=⊗↔ ⊗; does line include two tabs?
α+α1αXARGUMENT SRCHAR.⊗↔αXIFLT CHARS.⊗↔ ⊗; and does second tab have stuff after it?
αCαEαXSSLINE⊗↔αF⊗=αβ\ αβ2⊗↔ ⊗; a winner! copy it; tabs -> dbl-space
αXBREAK SRCHAR.⊗↔ ⊗; break between second pair of spaces
αβDα1αβ⊗↔Reply-Subject: re:α⊗↔αXJOIN⊗↔ ⊗; create our header line
αAαXTIN⊗↔αXSIN⊗↔ ⊗; flush trailing blanks
α2αXABORT⊗↔ ⊗; abort REPL5A
αβ⊗↓
αXDEFINE REPL5B⊗↔
⊗↔αCαEαFSubjectαβ\Reply-Subject: re⊗↔ ⊗; copy RFC822 subject line and make it ours
αA ⊗; pick it up
αβ⊗↓
αXDEFINE REPL6⊗↔
αXARGUMENT REPLIN⊗↔αLα3αβ⊗↔ ⊗; go to top of reply text and add header
⊗↔Reply-Text:⊗↔
α3αXADD REPLIN⊗↔ ⊗; that moved text down three lines
αZREPL6A⊗↔ ⊗; see if we can find date/time
αβD ⊗; delete junk line left by REP6A0 or REPL6A
αXARGUMENT REPLN2⊗↔αLαJ ⊗; go to top of reply headers and jump them
αXARGUMENT REPLIN⊗↔αL ⊗; move arrow to top of reply text
αβ⊗↓
αXDEFINE REPL6A⊗↔
αLαXARGUMENT REPLN2⊗↔αXSSLINE⊗↔ ⊗; don't search reply text
αXSTOPZERO⊗↔αF⊗↓≡⊗↔Date:⊗↓⊗↔αXSTOPONE⊗↔ ⊗; try to find RFC822 date line
αXARGUMENT NFOUND.⊗↔αXCASE REP6A0 REP6A1⊗↔
⊗; REP6A0 leaves us with attached date/time if found, else in line editor on junk line
⊗; REP6A1 always gives us attached date/time unless RFC822 aborts everything
⊗≠αXIFEQ ATTSIZ.⊗↔ ⊗; if nothing, abort; no big loss, so no error msg
αXARGUMENT REPLIN⊗↔αLαE ⊗; take it down to top of reply text
⊗↔β⊗↔α2αXADD REPLIN⊗↔ ⊗; separate it from reply text by blank line
α-αCαE ⊗; create junk line for REPL6 to delete
αβ⊗↓
αXDEFINE REP6A0⊗↔
αCαXJFILL 0,0,999⊗↔αE ⊗; copy line and flush tabs/multiple-spaces
α1α5αXIFEQ ASCII.⊗↔ ⊗; if top line is "∂", get its date/time
α1α6αXIFLE COLS.⊗↔ ⊗; line must have 16 cols if date/time there
αXBREAK 16⊗↔⊗↔αβD⊗↑ ⊗; flush rest of line
αDαβ4αβ8αXIFLE ASCII.⊗↔αβ5αβ7αXIFGE ASCII.⊗↔ ⊗; next char must be digit
αS αβ9αXIFEQ CHAR.⊗↔ ⊗; first "word" must be 9 chars ("dy-mon-yr")
α αβ4αβ8αXIFLE ASCII.⊗↔αβ5αβ7αXIFGE ASCII.⊗↔ ⊗; second "word" must start w/ digit
αS αβ1αβ4αXIFEQ CHAR.⊗↔ ⊗; second "word" must be 4 chars (time)
α⊗→αZREPFRM⊗↔αI rcvd α1α2α β:αS -PT.]αβA
αβ⊗↓
αXDEFINE REP6A1⊗↔
⊗↔α∞αZRFC822⊗↔ ⊗; move to "date" line, parse it (∞ = arg, not rep cnt)
αEα2αβ⊗↔ sent α⊗→αZREPFRM⊗↔α ⊗↔ ⊗; prepare enclosing text
.]αβA⊗↔αEα-α2αXJOIN⊗↔α1αXJFILL 0,0,999⊗↔ ⊗; combine preface and date
αXJOIN⊗↔αXSTOPZERO⊗↔α+αXSSLINE⊗↔αF..]αβ\.]αβ∞⊗↔αXSTOPONE⊗↔αA
αβ⊗↓
αXDEFINE REPL7⊗↔
αXSET %=REPSND⊗↔ ⊗; copy final-step macro to convenient name
αXSAY Type <control>% when ready to mail. ⊗↔
αβ⊗↓
αXDEFINE RFC822⊗↔
αZRFC1⊗↔ ⊗; handle "∂" lines specially
αCα∞αZRFC2⊗↔ ⊗; copy first line and all continuations
αEα+αXSSLINE⊗↔αXSTOPZERO⊗↔ ⊗; prepare to muck around on the one line
αF⊗=αβ\ αβ∞⊗↔ ⊗; all tabs become spaces
αXSTOPONE⊗↔⊗↑⊗↔αF:⊗↔ ⊗; find colon at end of header field name
αXBREAK SRCHAR.⊗↔ ⊗; break line so colon starts second line
αβDαF:αβ\⊗↔ ⊗; flush header name and colon
⊗⊂ now the tricky part: (1) notice quoted pairs (characters
delimited by "\") and alter them to simplify later parsing, (2)
flush parenthesised portions, which are comments, but watch out for
nesting and for quoted strings (quotes inside parens are comments;
parens in quotes are not!) (3) change special chars <space>,
<comma>, ":" and "@" in quotes to temporary chars that won't screw
up later parsing. main reason it's so tricky is we're not sure line
fits in line editor. ⊗⊃
β⊗↔α∞αZRFCX3⊗↔ ⊗; create "collecting" line; handle quoted pairs
⊗↑αXJOIN⊗↔ ⊗; done fixing quoted pairs
β⊗↔α∞αZRFC3⊗↔ ⊗; create "collecting" line; handle parens
⊗↑αXJOIN⊗↔ ⊗; done parsing comments
β⊗↔α∞αZRFC4⊗↔ ⊗; create new collecting line; handle quotes
⊗↑αXJOIN⊗↔ ⊗; done parsing quoted strings
β⊗↔α#αZRFC5⊗↔ ⊗; create new collecting line; handle colons
⊗↑αXJOIN⊗↔ ⊗; done parsing <comment>:<text>; format
αXSTOPZEROα+αXSSLINE⊗↔αFεαβ\αβ∞⊗↔ ⊗; flush all the "ε"s that got added
αXSTOPONE⊗↔αA ⊗; pick up final version
αβ⊗↓
αXDEFINE RFC1⊗↔
α1α5αXIFEQ ASCII.⊗↔ ⊗; see if this is a "∂" line
αCαEα⊗=⊗=α⊗→αS⊗=αRαK⊗↔αA ⊗; yes; copy it, flush subject field
α2αXABORT⊗↔ ⊗; abort RFC822
αβ⊗↓
αXDEFINE RFC2⊗↔
αZRFC2A⊗↔ ⊗; if next line starts with space or tab, add
α+αCαXJOIN⊗↔ ⊗; it to attach buffer and join with rest
αβ⊗↓
αXDEFINE RFC2A⊗↔
α3α2αXIFNE ASCII.⊗↔ ⊗; check for space
α9αXIFNE ASCII.⊗↔ ⊗; check for tab
α2αXABORT⊗↔ ⊗; neither found, abort RFC2
αβ⊗↓
αXDEFINE RFCX3⊗↔
α+αXSSLINE⊗↔αF\αβ\ε\⊗↔ ⊗; find "\", done if none
αXBREAK SRCHAR.⊗↔ ⊗; break ahead of "\"; "ε" ensures SRCHAR≠0
⊗↔αXBREAK 2⊗↔ ⊗; isolate "\" and following char
α+αXSSLINE⊗↔αXSTOPZERO⊗↔ ⊗; prepare for replacements
αF\"αβ\\""⊗↔ ⊗; duplicate quotation marks
αF\(αβ\\()⊗↔ ⊗; make quoted left paren in comments work
αF\)αβ\\)(⊗↔ ⊗; same for right paren
αXSTOPONE⊗↔α2⊗↑α3αXJOIN⊗↔ ⊗; join altered text to collecting line
⊗↔ ⊗; get back to working line
αβ⊗↓
αXDEFINE RFC3⊗↔
α+αXSSLINE⊗↔αF(αβ\ε(⊗↔ ⊗; find "(", done if none
αXBREAK SRCHAR.⊗↔ ⊗; break ahead of "("; "ε" ensures SRCHAR≠0
α+αXSSLINE⊗↔αXSTOPZERO⊗↔ ⊗; prepare to search up to "("
α∞αF"⊗↔αXSET REPTMP=NFOUND.⊗↔ ⊗; get number of quotes ahead of "("
αXSTOPONE⊗↔α2αXREMAINDER REPTMP⊗↔ ⊗; odd or even?
αXARGUMENT REPTMP⊗↔αXCASE RFC3A RFC3B⊗↔ ⊗; call subcase
αβ⊗↓
αXDEFINE RFC3A⊗↔
⊗↔αAαXSET REPTMP=LINE.⊗↔α∞αL ⊗; take line to bottom of page
α1αXBREAK 80⊗↔αE ⊗; break into bite-size chunks
αXSET REPTM2=LINE.⊗↔ ⊗; remember where first 80-char chunk is
αZRFC3A0⊗↔ ⊗; look for ")", return only if NOT found
αXSAY Sorry -- Couldn't find matching close parenthesis in above header line.⊗↔
αXARGUMENT REPTM2⊗↔αLα∞αβ!αβD ⊗; failed; clean up (∞! stops at pagemark)
αXARGUMENT REPTMP⊗↔αLα-α2αβD
αZREPLXX⊗↔
αβ⊗↓
αXDEFINE RFC3A0⊗↔
α) ⊗; find matching ")", abort if missing
αL⊗↔αDα⊗↔ ⊗; kill left to beginning of line, kill ")"
αXARGUMENT LINE.⊗↔αXSUBTRACT REPTM2⊗↔ ⊗; compute -# lines from "(" to here
αXARGUMENT REPTM2⊗↔αβD ⊗; delete all those lines
α∞αβ!αAα∞αXJOIN⊗↔ ⊗; pick up what's left (∞! stops at pagemark)
αXARGUMENT REPTMP⊗↔αLαE ⊗; put it back where we were
α-α2αXJOIN⊗↔ ⊗; join stuff left of "(" on collection line
⊗↔ ⊗; get back to working line
α2αXABORT⊗↔ ⊗; abort RFC3A
αβ⊗↓
αXDEFINE RFC3B⊗↔
⊗↔α+αXSSLINE⊗↔ ⊗; odd number of quotes, search for one more
αXSTOPZERO⊗↔αF"αβ\"ε⊗↔αXSTOPONE⊗↔ ⊗; handle failing search specially
α1αXARGUMENT NSUBST.⊗↔αZRFC3B0⊗↔ ⊗; REP3CY aborts if arg=1 (NSUBST=0)
αXBREAK SRCHAR.⊗↔ ⊗; break between " and ε
α2⊗↑α3αXJOIN⊗↔ ⊗; join through quote on collection line
⊗↔ ⊗; down to working line again
αβ⊗↓
αXDEFINE RFC3B0⊗↔
αXSET REPTMP⊗↔α#αXIFEQ REPTMP⊗↔ ⊗; abort if arg = 1
αXSAY Sorry -- Couldn't find matching quote in above header line.⊗↔
α2⊗↑α3αβD
αZREPLXX⊗↔
αβ⊗↓
αXDEFINE RFC4⊗↔
α+αXSSLINE⊗↔αF"αβ\ε"⊗↔ ⊗; find quote, done if none
αXBREAK SRCHAR.⊗↔ ⊗; break between quote and newly added "ε"
αXSTOPZERO⊗↔⊗↔α2αF"αβ\"ε⊗↔αXSTOPONE⊗↔ ⊗; find close quote (SSLINE still okay)
α1αXARGUMENT NSUBST.⊗↔αZRFC3B0⊗↔ ⊗; abort if couldn't find it
αXBREAK SRCHAR.⊗↔ ⊗; break between close quote and "ε"
α+αXSSLINE⊗↔αXSTOPZERO⊗↔ ⊗; prepare to change special chars (if any)
⊗↑⊗↔αF αβ\∧αβ∞⊗↔ ⊗; space becomes logical-and
⊗↑⊗↔αF,αβ\∨αβ∞⊗↔ ⊗; comma becomes logical-or
⊗↑⊗↔αF:αβ\∃αβ∞⊗↔ ⊗; colon becomes there-exists
⊗↑⊗↔αF@αβ\∀αβ∞⊗↔ ⊗; atsign becomes forall
αXSTOPONE⊗↔
α2⊗↑α3αXJOIN⊗↔ ⊗; join thru close-quote on collecting line
⊗↔ ⊗; back to the working line
αβ⊗↓
αXDEFINE RFC5⊗↔
α#αXIFLE CHARS.⊗↔α∞αZRFC5A⊗↔ ⊗; if arg=∞, parsing date; let colons be
αβ⊗↓
αXDEFINE RFC5A⊗↔
α+αXSSLINE⊗↔αF:αβ\εε⊗↔ ⊗; find colon, done if none, flush if there
αXBREAK SRCHAR.⊗↔ ⊗; break between the two newly-added "ε"s
αβ⊗↔,α⊗↔αXJOIN⊗↔α+αXSSLINE⊗↔ ⊗; make sure at least one comma before colon
αXSTOPZERO⊗↔α∞αF,⊗↔ ⊗; find last comma (if any) before colon
αXSTOPONE⊗↔αXARGUMENT NFOUND.⊗↔αF,αβ\,ε⊗↔
αXBREAK SRCHAR.⊗↔⊗↑⊗↔αF,αβ\⊗↔ ⊗; flush extra comma from front
⊗↑αXJOIN⊗↔⊗↔αβD ⊗; discard text between comma and incl colon
α+αXSSLINE⊗↔αF;αβ\εε⊗↔ ⊗; find matching semi (need not be present)
αXBREAK SRCHAR.⊗↔ ⊗; break ahead of where semi was
⊗↑αXJOIN⊗↔ ⊗; put intervening text on collecting line
⊗↔ ⊗; back to the working line
αβ⊗↓
αXDEFINE REPNAM⊗↔
⊗; if arg (rep cnt) > 1, allow any length local name and also quoted local names
⊗; if arg = 1, have REPNM6 save "@<host>" string for later use as default
α#αZREPNM0⊗↔ ⊗; assume RFC822 was called; parse a name
α#αZREPNM6⊗↔ ⊗; save hostname if #=1, else apply default
α+αXSSLINE⊗↔αZREPNM8⊗↔ ⊗; flush "@SAIL" and strip quotes if local
αXSTOPZERO⊗↔⊗↑⊗↔αF∧αβ\ αβ∞⊗↔ ⊗; change back special chars
⊗↑⊗↔αF∨αβ\,αβ∞⊗↔
⊗↑⊗↔αF∃αβ\:αβ∞⊗↔
⊗↑⊗↔αF≡∀αβ\@αβ∞⊗↔
⊗↑⊗↔αF\""αβ\\"αβ∞⊗↔ ⊗; restore quoted quote
⊗↑⊗↔αF\()αβ\\(αβ∞⊗↔ ⊗; and left paren
⊗↑⊗↔αF\)(αβ\\)αβ∞⊗↔ ⊗; and right paren
αXSTOPONE⊗↔
αβ⊗↓
αXDEFINE REPNM0⊗↔
⊗; REPNM1-5,7 abort REPNM0 if successful, else leave junk line (except ##4-5,7)
αZREPNM1⊗↔αβD⊗↑ ⊗; look for "<NAME at SITE>" or "<NAME @ SITE>"
αZREPNM2⊗↔αβD⊗↑ ⊗; look for "NAME at SITE"
αZREPNM3⊗↔αβD⊗↑ ⊗; look for "NAME @ SITE"
αZREPNM4⊗↔ ⊗; try first alph string after space/tab
α-αCαEα#αZREPNM6⊗↔αβD ⊗; if #=1, find out if ReSent-from exists
α#αXARGUMENT RPDFLT⊗↔αZREPNM5⊗↔ ⊗; try first string if alph or quoted & arg>1 or def host known
α#αZREPNM7⊗↔ ⊗; if name was on Reply-To, don't argue!
αXSAY Sorry -- Can't find a name in the above line.⊗↔
αZREPLXX⊗↔ ⊗; abort
αβ⊗↓
αXDEFINE REPNM1⊗↔
αCαEα+αXSSLINE⊗↔αF<αβ\ε<⊗↔ ⊗; look for "<", delete portion to left
αXBREAK SRCHAR.⊗↔αβDαF<αβ\⊗↔ ⊗; also delete the "<"; SSLINE still okay
αF>αβ\>ε⊗↔ ⊗; look for ">", delete portion to right
αXBREAK SRCHAR.⊗↔⊗↔αβD⊗↑αF>αβ\⊗↔
αXSTOPZERO⊗↔⊗↑⊗↔α+αXSSLINE⊗↔ ⊗; if " at " appears, replace with "@"
αF at αβ\@⊗↔αXSTOPONE⊗↔
αZREPNMX⊗↔ ⊗; parse stuff around "@"; return if failed
αβ⊗↓
αXDEFINE REPNM2⊗↔
αCαEα+αXSSLINE⊗↔αF at αβ\@⊗↔ ⊗; look for " at " and replace with "@"
αZREPNMX⊗↔ ⊗; parse stuff around "@"; return if failed
αβ⊗↓
αXDEFINE REPNM3⊗↔
αCαEαZREPNMX⊗↔ ⊗; look for "@" and parse it if found
αβ⊗↓
αXDEFINE REPNMX⊗↔ ⊗; parse name and site from around "@"
αXINDENT -9999⊗↔α1αXTIN⊗↔α1αXSIN⊗↔ ⊗; strip leading/trailing blanks
⊗↑⊗↔α+αXSSLINE⊗↔ ⊗; make sure search will work right
αF@⊗↔αXIFLE SRCHAR.⊗↔ ⊗; make sure SOMETHING to left of "@"!
α1αXARGUMENT SRCHAR.⊗↔αXIFLT CHARS.⊗↔ ⊗; and something to right
αXBREAK SRCHAR.⊗↔ ⊗; get name by itself
αAαXJFILL 0,0,1⊗↔ ⊗; break into separate words
α-αAα+αCαβK ⊗; save just the last word
αXBREAK 1⊗↔ ⊗; separate "@" (we know there's more)
⊗↔αAαXJFILL⊗↔ ⊗; get site by itself (first word after "@")
αXSET REPTMP⊗↔αXARGUMENT ATTSIZ.⊗↔αXSUBTRACT REPTMP⊗↔
αXARGUMENT REPTMP⊗↔αCα0αA ⊗; discard all but first, then put it down
⊗; (might have done α0αC to drop it, hence α0αA (= nop) instead of αE)
α2⊗↑α3αXJOIN⊗↔ ⊗; put it together again
αXSSLINE⊗↔αF@⊗↔ ⊗; get SRCHAR pointing to "@" for REPNMQ
α-αβD ⊗; delete original line
α3αXABORT⊗↔ ⊗; abort REPNM0
αβ⊗↓
αXDEFINE REPNM4⊗↔
αCαXJFILL 0,0,1⊗↔ ⊗; break into words
αXSET REPTMP=ATTSIZ.⊗↔ ⊗; save number of words
αEα∞αZRPNM4A⊗↔ ⊗; look at each line for SAIL prog name
αβ⊗↓
αXDEFINE RPNM4A⊗↔
αZRPNM4B⊗↔ ⊗; check one line, return if failed
α⊗↔αβDαXSUBTRACT REPTMP⊗↔ ⊗; keep REPTMP as number of lines left
αXIFLE REPTMP⊗↔ ⊗; give up if REPTMP hits (or is set to) 0
αβ⊗↓
αXDEFINE RPNM4B⊗↔
α6α5αXIFLE ASCII.⊗↔αXSET REPTM2=ASCII.⊗↔ ⊗; look for first line that
α3α2αXREMAINDER REPTM2⊗↔αXIFLE REPTM2⊗↔ ⊗; starts with alphabetic
α2α6αXIFGE REPTM2⊗↔
⊗↔α-α1αXARGUMENT REPTMP⊗↔αβD ⊗; got it; ignore remaining lines
⊗↑αXSET REPTMP⊗↔ ⊗; set REPTMP to abort RPNM4A if we fail
αXIFLT CHARS.⊗↔α4αXIFGT CHARS.⊗↔ ⊗; must be either 2 or 3 chars
α αβ6αβ5αXIFLE ASCII.⊗↔αXSET REPTM2=ASCII.⊗↔ ⊗; second char alpha?
αβ3αβ2αXREMAINDER REPTM2⊗↔αXIFLE REPTM2⊗↔αβ2αβ6αXIFGE REPTM2⊗↔
α⊗=α⊗↑αβ6αβ5αXIFLE ASCII.⊗↔αXSET REPTM2=ASCII.⊗↔ ⊗; last char alpha?
αβ3αβ2αXREMAINDER REPTM2⊗↔αXIFLE REPTM2⊗↔αβ2αβ6αXIFGE REPTM2⊗↔
α⊗↔α-αβDα4αXABORT⊗↔ ⊗; a winner! abort all the way up to REPNM0
αβ⊗↓
αXDEFINE REPNM5⊗↔
⊗; permit this case only on "to" or "cc" or if def host known due to "ReSent-from" line
α#αXSET REPTMP⊗↔α2αXIFLT REPTMP⊗↔
α-αCαXJFILL 0,0,1⊗↔ ⊗; break line into words
αXSET REPTMP=ATTSIZ.⊗↔ ⊗; save number of words
αE⊗↔α-α1αXARGUMENT REPTMP⊗↔αβD ⊗; delete all but the first word
⊗↑αZRPNM5A⊗↔ ⊗; check for quoted string (e.g., "#<file>")
α⊗↔αZRPNM5B⊗↔ ⊗; check for first-char = alph
αβD ⊗; no luck; flush line, let REPNM0 bitch
αβ⊗↓
αXDEFINE RPNM5A⊗↔
α3α4αXIFEQ ASCII.⊗↔ ⊗; make sure line starts with quote
α9α9αXIFGE CHARS.⊗↔ ⊗; local quoted names (#file, @file) always fairly short
α⊗=α⊗↑αβ3αβ4αXIFEQ ASCII.⊗↔ ⊗; make sure line ends with quote
α⊗↔α-αβDα3αXABORT⊗↔ ⊗; success! abort ourselves, REPNM5, and REPNM0
αβ⊗↓
αXDEFINE RPNM5B⊗↔
α6α5αXIFLE ASCII.⊗↔αXSET REPTM2=ASCII.⊗↔ ⊗; check for alph as in RPNM4B
α3α2αXREMAINDER REPTM2⊗↔αXIFLE REPTM2⊗↔α2α6αXIFGE REPTM2⊗↔ ⊗; allow lowercase
α-αβDα3αXABORT⊗↔ ⊗; alph it is, assume it's a forwarded name @SAIL
αβ⊗↓
αXDEFINE REPNM6⊗↔
⊗; if arg = 1, look for "@" and save hostname for later use as default
⊗; if arg > 1, look for "@" and if not found append default
α+αXSSLINE⊗↔α#αXSET REPTMP⊗↔α2αXMINIMUM REPTMP⊗↔
α-α1αXARGUMENT REPTMP⊗↔αXCASE RPNM6A RPNM6B⊗↔
αβ⊗↓
αXDEFINE RPNM6A⊗↔
αXSET RPDFLT⊗↔ ⊗; flag that no default known yet
αZRPNM6C⊗↔ ⊗; look for one on this line
αXSET REPTMP=LINE.⊗↔ ⊗; no luck, look for host ReSent-from
αCαEαLαXEMPTY⊗↔α+α0αXSSLINE⊗↔ ⊗; create junk line, restrict search to header
αLαXARGUMENT REPTMP⊗↔αZRPNM6D⊗↔ ⊗; RPNM6D might replace junk with new junk
αXARGUMENT REPTMP⊗↔αLαβD ⊗; whether or not that worked, we're through
αZRPNM6B⊗↔ ⊗; except we should apply ReSent-from host to this line, too!
αβ⊗↓
αXDEFINE RPNM6B⊗↔
αXIFNE RPDFLT⊗↔ ⊗; abort unless we know sender's host
α+αXSSLINE⊗↔αXSTOPZERO⊗↔⊗↔⊗↑αF@⊗↔ ⊗; look for "@" on this line
αXSTOPONE⊗↔αXIFNE NFOUND.⊗↔ ⊗; exit if found
⊗↔αXATTACH RPHOST⊗↔αE⊗↑αXJOIN⊗↔ ⊗; else append default host text
αβ⊗↓
αXDEFINE RPNM6C⊗↔
α+αXSSLINE⊗↔⊗↔⊗↑αF@⊗↔ ⊗; look for "@", abort if none
αXBREAK SRCHAR.⊗↔⊗↔ ⊗; break line ahead of "@"
α1αXREDEFINE RPHOST⊗↔⊗↑αXJOIN⊗↔ ⊗; save "@<host>" in handy macro, rejoin
αXADD RPDFLT⊗↔ ⊗; flag that default host is now known
α2αXABORT⊗↔ ⊗; abort RPNM6A (don't look for ReSent-from)
αβ⊗↓
αXDEFINE RPNM6D⊗↔
αF⊗↓≡⊗↔ReSent-From:⊗↓⊗↔⊗↔ ⊗; look for first remailer, abort if none
αZRFC822⊗↔α#αL⊗↔αEα-αβD ⊗; parse RFC format, replace junk line with this
α2αZREPNM0⊗↔ ⊗; parse for name, don't restore spec chars
α#αXSET REPTMP⊗↔ ⊗; REPTMP used by parsing macros
αZRPNM6C⊗↔ ⊗; see if it has "@host" for us
αβ⊗↓
αXDEFINE REPNM7⊗↔
α#αXIFEQ RPRPTO⊗↔ ⊗; looking for sender's name in Reply-To field?
⊗↑αXINDENT -9999⊗↔α1αXTIN⊗↔α1αXSIN⊗↔
α2αXABORT⊗↔ ⊗; well, look no further!
αβ⊗↓
αXDEFINE REPNM8⊗↔
αXSTOPZERO⊗↔ ⊗; flush local address (BEFORE restoring "@"s!)
⊗↑⊗↔αF@SU-AI.ARPAαβ\⊗↔
⊗↑⊗↔αF@SU-AIαβ\⊗↔
⊗↑⊗↔αF@SAILαβ\⊗↔
⊗↑⊗↔αF@⊗↔αXSTOPONE⊗↔αXIFNE NFOUND.⊗↔ ⊗; that's it unless no "@" now
α3αXIFLE CHARS.⊗↔ ⊗; first off, enough chars for quoted string?
α3α4αXIFEQ ASCII.⊗↔ ⊗; see if local name starts with quote
αXSTOPZERO⊗↔⊗↑⊗↔α∞αF"⊗↔ ⊗; yep, look for too many of them
αXARGUMENT NFOUND.⊗↔αβ* ⊗; now look for last on this line (at least 1!)
αXSTOPONE⊗↔α+α1αXARGUMENT SRCHAR.⊗↔αXIFEQ CHARS.⊗↔ ⊗; is last quote the last char?
αXBREAK SRCHAR.⊗↔αXBREAK 1⊗↔ ⊗; everything checks, discard quotes
αβD⊗↔αβD⊗↑α+αXSSLINE⊗↔
αβ⊗↓
αXDEFINE REPLST⊗↔
αXSET REPTOP⊗↔ ⊗; line from which to search, start at top
α∞αZRPLST1⊗↔ ⊗; process all the "to" or "cc" lines
α#αXMAXIMUM REPTOP⊗↔ ⊗; remember furthest we ever found a hit
αβ⊗↓
αXDEFINE RPLST1⊗↔
αXARGUMENT REPTOP⊗↔αL⊗↔⊗↑ ⊗; go to position of last line found
αXARGUMENT REPLN2⊗↔αXSSLINE⊗↔ ⊗; don't search original attached text
αZRPLSTF⊗↔ ⊗; look for appropriate header line
αXIFEQ NFOUND.⊗↔ ⊗; if none found, we're done
⊗↔αXSET REPTOP=LINE.⊗↔ ⊗; move down to actual line, save position
αZRFC822⊗↔ ⊗; pick up line, flush comments, etc.
αXARGUMENT REPLIN⊗↔αLαE ⊗; take it down to bottom
αXADD REPLIN⊗↔ ⊗; old attach buffer now further down
⊗↔α1αβ⊗↔,αβUαXJOIN⊗↔ ⊗; put comma on the end
α∞αZRPLST2⊗↔ ⊗; parse as many names as there are commas
αβDαXSUBTRACT REPLIN⊗↔ ⊗; delete whatever's left (probably null)
αβ⊗↓
αXDEFINE RPLST2⊗↔
α+αXSSLINE⊗↔αF,αβ\ ⊗↔αXBREAK SRCHAR.⊗↔ ⊗; break ahead of first comma
αZRPLS2A⊗↔ ⊗; process stuff ahead of comma
αβD ⊗; delete either blank line or junk line
αβ⊗↓
αXDEFINE RPLS2A⊗↔
α1αXTIN⊗↔α1αXSIN⊗↔ ⊗; get rid of trailing spaces
αXIFLE CHARS.⊗↔ ⊗; see if line had nothing but spaces
αXADD REPLIN⊗↔ ⊗; real text; account for BREAK in RPLST2
α2αZREPNAM⊗↔ ⊗; parse pre-comma text to form a name (2=arg, not rep cnt)
αZRPLSTI⊗↔ ⊗; add our special field name
αCαE ⊗; make a copy for RPLST2 to delete
αβ⊗↓
αXDEFINE REPSND⊗↔
αZRENTRY⊗↔
αZREPSN0⊗↔ ⊗; extra nesting level for quieter aborting
αZEXIT2⊗↔
αβ⊗↓
αXDEFINE REPLX2⊗↔ ⊗; error exit for REPSND
αXSSLINE⊗↔αZREXIT1⊗↔
α-α1αXARGUMENT MDEPTH.⊗↔αXABORT⊗↔
αβ⊗↓
αXDEFINE REPSN0⊗↔
αZREPSN1⊗↔ ⊗; find reply header; adjust REPLN2 & REPLIN if necessary
αZREPSN2⊗↔ ⊗; convert lines REPLN2 thru REPLIN-1 into mailing list
αZREPSN3⊗↔ ⊗; send the mail and clean up (leave reply text in undelete buf)
αβ⊗↓
αXDEFINE REPSN1⊗↔
αZRPSN1A⊗↔ ⊗; find "replying-to" line
⊗↔αXSET REPLN2=LINE.⊗↔ ⊗; remember its current position
αZRPSN1B⊗↔ ⊗; find "reply-text" line
⊗↔αXSET REPLIN=LINE.⊗↔ ⊗; remember it, too
αXARGUMENT REPLN2⊗↔αL ⊗; go to top of reply header
αXSET REPTMP=REPLIN⊗↔α1αXARGUMENT REPLN2⊗↔αXSUBTRACT REPTMP⊗↔
αXIFLE REPTMP⊗↔ ⊗; any lines between replying-to and reply-text?
αXARGUMENT REPTMP⊗↔αZRPSN1C⊗↔ ⊗; yes, check them for validity
αXARGUMENT REPLIN⊗↔αL ⊗; go to reply-text line
αXSTOPZERO⊗↔αXNONEMPTY⊗↔ ⊗; see if there's any text line after it
αXSTOPONE⊗↔αXARGUMENT LINE.⊗↔αXIFEQ REPLIN⊗↔ ⊗; return if there is
αβXSAY⊗↔αβXSAY Sorry -- No text found after "Reply-Text" line.⊗↔
αZREPLX2⊗↔
αβ⊗↓
αXDEFINE RPSN1A⊗↔
αXARGUMENT REPLN2⊗↔αL ⊗; go to approx loc of "replying-to" line
α+αXSSLINE⊗↔⊗↑ ⊗; first search just the one line
αXSTOPZERO⊗↔αF⊗↓≡⊗↔Replying-To:⊗↓⊗↔αXSTOPONE⊗↔
αXIFNE NFOUND.⊗↔ ⊗; exit if we found it
αXSTOPZERO⊗↔⊗↔αXEMPTY⊗↔ ⊗; try searching whole paragraph
α+α0αXSSLINE⊗↔α-αXEMPTY⊗↔αβ*
αXSTOPONE⊗↔αXIFNE NFOUND.⊗↔ ⊗; again exit if found
αLαXARGUMENT LINES.⊗↔αXSSLINE⊗↔ ⊗; search whole page
αXSTOPZERO⊗↔αβ*αXSTOPONE⊗↔αXIFNE NFOUND.⊗↔
αβXSAY⊗↔αβXSAY Sorry -- Can't find the "Replying-To" line.⊗↔
αZREPLX2⊗↔
αβ⊗↓
αXDEFINE RPSN1B⊗↔
α!⊗↔α+α2αXSSLINE⊗↔ ⊗; go to end of "replying-to" graf; check next line
αXSTOPZERO⊗↔αF⊗↓≡⊗↔Reply-Text:≡⊗↔⊗↓⊗↔αXSTOPONE⊗↔
αXIFNE NFOUND.⊗↔ ⊗; exit if found header
αXARGUMENT REPLN2⊗↔αL ⊗; else try from "replying-to" to end
αXARGUMENT LINES.⊗↔αXSSLINE⊗↔αXSTOPZERO⊗↔αβ*αXSTOPONE⊗↔αXIFNE NFOUND.⊗↔
αβXSAY⊗↔αβXSAY Sorry -- Can't find the "Reply-Text" line.⊗↔
αZREPLX2⊗↔
αβ⊗↓
αXDEFINE RPSN1C⊗↔
αZRPSN1D⊗↔ ⊗; want to be able to abort one iteration at a time
αβ⊗↓
αXDEFINE RPSN1D⊗↔
⊗↔α+αXSSLINE⊗↔⊗↑ ⊗; go to next line and restrict searches to it
αXSTOPZERO⊗↔αXSET REPTMP⊗↔ ⊗; flag saying whether any search won
αF⊗↓≡⊗↔Also-To:⊗↓⊗↔αXARGUMENT NFOUND.⊗↔αXADD REPTMP⊗↔
αF⊗↓≡⊗↔Reply-cc:⊗↓⊗↔αXARGUMENT NFOUND.⊗↔αXADD REPTMP⊗↔
αF⊗↓≡⊗↔Reply-Subject:⊗↓⊗↔αXARGUMENT NFOUND.⊗↔αXADD REPTMP⊗↔
⊗↔αXSTOPONE⊗↔αXIFEQ REPTMP⊗↔ ⊗; abort if any of the searches won
α0αXNONEMPTY⊗↔ ⊗; empty lines are also legal in the header
αβXSAY⊗↔αβXSAY Sorry -- This line doesn't seem to belong in the reply header.⊗↔
αZREPLX2⊗↔
αβ⊗↓
αXDEFINE REPSN2⊗↔
αXSET REPTMP⊗↔ ⊗; number of "name" lines initially = 1 (replying-to)
αXARGUMENT REPLIN⊗↔αXSSLINE⊗↔ ⊗; stop searches at reply text
αXSTOPZERO⊗↔αF⊗↓≡⊗↔Reply-cc:⊗↓⊗↔ ⊗; set up search string
α1αXARGUMENT REPLN2⊗↔αL ⊗; collect all the cc lines (if any)
αXSTOPONE⊗↔α∞αZRPSN2A⊗↔
αXARGUMENT ATTSIZ.⊗↔αXADD REPTMP⊗↔ ⊗; remember total # of names
α1αXARGUMENT REPLN2⊗↔αLα0αA ⊗; drop them just below replying-to
αZRPSN2B⊗↔ ⊗; add "/cc" to first one if any
αXSTOPZERO⊗↔αF⊗↓≡⊗↔Also-To:⊗↓⊗↔ ⊗; do it again for also-to's
α1αXARGUMENT REPLN2⊗↔αLαXSTOPONE⊗↔α∞αZRPSN2A⊗↔
αXARGUMENT ATTSIZ.⊗↔αXADD REPTMP⊗↔
α1αXARGUMENT REPLN2⊗↔αLα0αA ⊗; drop them between replying-to and reply-cc's
⊗↑αXARGUMENT REPTMP⊗↔αZRPSN2C⊗↔ ⊗; convert field name on each line to comma
αXARGUMENT REPLN2⊗↔αLαXARGUMENT REPTMP⊗↔αXJOIN⊗↔ ⊗; make one big line
α-α1αXARGUMENT REPTMP⊗↔αXSUBTRACT REPLIN⊗↔ ⊗; reply-text thereby moved
αF,αβ\MAIL ⊗↔ ⊗; so much for the name list
αZRPSN2D⊗↔ ⊗; take care of reply-subject (if any)
αXARGUMENT REPLIN⊗↔αLαXNONEMPTY⊗↔ ⊗; go to top of reply text (probably subject)
αXSET REPTMP=REPLN2⊗↔α-α1αXARGUMENT LINE.⊗↔αXSUBTRACT REPTMP⊗↔
αXARGUMENT REPTMP⊗↔αβD ⊗; delete all lines between MAIL command and top of text
⊗↑ ⊗; leave us sitting on MAIL command line
αβ⊗↓
αXDEFINE RPSN2A⊗↔
⊗↑αβ*⊗↔α+αA
αβ⊗↓
αXDEFINE RPSN2B⊗↔
αXIFLT REPTMP⊗↔ ⊗; were there any attached reply-cc lines?
⊗↔α1αβ⊗↔/ccαβUαXJOIN⊗↔ ⊗; yes; add "/cc" to the first one
αβ⊗↓
αXDEFINE RPSN2C⊗↔
αF:αβ\ ⊗↔αXBREAK SRCHAR.⊗↔αβD ⊗; break off and discard reply header
αXINDENT -9999⊗↔ ⊗; flush leading spaces from name
αXINDENT 1⊗↔αF αβ\,⊗↔ ⊗; add a comma at the front
⊗↔ ⊗; move on to the next name
αβ⊗↓
αXDEFINE RPSN2D⊗↔
αXARGUMENT REPLIN⊗↔αXSSLINE⊗↔ ⊗; search from name list to reply-text
αF⊗↓≡⊗↔Reply-Subject:⊗↓⊗↔ ⊗; try to find subject (if none, don't object)
⊗↔αF:αβ\ ⊗↔αXBREAK SRCHAR.⊗↔αβD ⊗; flush header name
αXINDENT -9999⊗↔αAαXSUBTRACT REPLIN⊗↔ ⊗; pick up subject (moves reply-text line)
αXARGUMENT REPLIN⊗↔αL ⊗; go to reply-text header
αXNONEMPTY⊗↔αE ⊗; put subject down at top of actual text
αXARGUMENT REPLN2⊗↔αLαFMAILαβ\MAIL/SUBJ⊗↔ ⊗; make MAIL use top text line as subject
αβ⊗↓
αXDEFINE REPSN3⊗↔
αFMAILαβ\⊗↔ ⊗; remove MAIL command from line
αZREXIT1⊗↔ ⊗; prepare to exit
α∞αβ!αAαXMAIL⊗↔ ⊗; pick up rest of page and mail it
αZRPSN3C⊗↔ ⊗; do a cancel if W flag was originally off
αβK ⊗; put text into undelete buffer
αβ⊗↓
αXDEFINE RPSN3C⊗↔
αXIFNE REPLW⊗↔αXCANCEL⊗↔ ⊗; undo everything if W flag was off when REPLY called
αβ⊗↓
αXDEFINE CCME⊗↔
αZRENTRY⊗↔
αZCCME0⊗↔ ⊗; extra nesting level for quieter aborting
αZEXIT2⊗↔
αβ⊗↓
αXDEFINE CCME0⊗↔
αXSET REPTMP=LINE.⊗↔ ⊗; remember where we were
αZRPSN1A⊗↔ ⊗; look for "replying-to" line
⊗↔⊗↔αβ⊗↔Reply-cc: .α⊗↔ ⊗; add cc-to-oneself
αXSET REPTM2=REPTMP⊗↔αXARGUMENT LINE.⊗↔αXDIVIDE REPTM2⊗↔ ⊗; is REPTMP≥LINE.?
αXMINIMUM REPTM2⊗↔αXARGUMENT REPTM2⊗↔αXADD REPTMP⊗↔ ⊗; if so, incr
αXARGUMENT REPTMP⊗↔αL ⊗; return to original line
αZREXIT1⊗↔
αβ⊗↓
αXDEFINE OLDMSG⊗↔
αZRENTRY⊗↔
αZOLDMS0⊗↔ ⊗; extra nesting level for quieter aborting
αZEXIT2⊗↔
αβ⊗↓
αXDEFINE OLDMS0⊗↔
αZRPSN1A⊗↔ ⊗; look for "replying-to" line
⊗↔⊗↔α-α∞αβ!αC ⊗; copy it & everything above (in incore page)
⊗; (include "replying-to" line to guarantee at least one line, else αβ! barfs)
αXINDENT S 2⊗↔αXSIN⊗↔ ⊗; indent by 2 and change tabs to spaces
α∞αLαEα1αβ⊗↔α7α0-α⊗→+⊗↔ ⊗; append to reply-text, put line across top
α∞αZOLDMS1⊗↔α7α0-α⊗→+α⊗↔ ⊗; put bar down left and line at bottom
α-αβD⊗↑αZOLDMS3⊗↔ ⊗; flush "replying-to" & blank above it (if any)
α∞αLαZREXIT1⊗↔ ⊗; leave cursur at bottom
αβ⊗↓
αXDEFINE OLDMS1⊗↔
αZOLDMS2⊗↔ ⊗; OLDMS2 handles empty lines
α0αXNONEMPTY⊗↔ ⊗; make sure we stop at incore pagemark
αF αβ\|⊗↔α1αXTIN⊗↔⊗↔ ⊗; if not empty, add spike and move on
αβ⊗↓
αXDEFINE OLDMS2⊗↔
α0αXEMPTY⊗↔ ⊗; note that end-of-page is not empty
α⊗↔ ⊗; create space for OLDMS1 to change
αβ⊗↓
αXDEFINE OLDMS3⊗↔
αXIFEQ CHARS.⊗↔αβD ⊗; delete line if contains only a "|"
αβ⊗↓
αXDEFINE TOLIST⊗↔
αZRENTRY⊗↔
αZTOLST0⊗↔ ⊗; extra nesting level for quieter aborting
αZEXIT2⊗↔
αβ⊗↓
αXDEFINE TOLST0⊗↔
αZRPSN1A⊗↔⊗↔⊗↔ ⊗; look for "replying-to", go to line after
αZTOLST1⊗↔ ⊗; change it to "replying-to"
α-αβD ⊗; flush old line
αZREXIT1⊗↔
αβ⊗↓
αXDEFINE TOLST1⊗↔
α+αXSSLINE⊗↔αXSTOPZERO⊗↔ ⊗; prepare for failing substitutions
αFAlso-To:αβ\Replying-To:⊗↔αXSTOPONE⊗↔αXIFNE NSUBST.⊗↔ ⊗; abort if okay
αXSTOPZERO⊗↔αFReply-cc:αβ\Replying-To:⊗↔αXSTOPONE⊗↔αXIFNE NSUBST.⊗↔
αβXSAY Sorry -- Line after "Replying-To" isn't an address line.⊗↔
⊗↑αZREPLX2⊗↔
αβ⊗↓
αxsay REPLY CCME TOLIST OLDMSG ⊗↔
⊗⊂ And we'll be needing ENTRY/EXIT macros: ⊗⊃ αXEXECUTE EINIT.CMD[1,3](13)⊗↔
⊗⊂ DON Archive a message
The ARCHIV macro moves the current message (as defined by the ∂ command) to an
archive file, creating the file if necessary. The archive file is written out
but is left open in a separate window. The message is deleted from the
original file only after it has been written out in the archive file.
To use, put the name of the archive file on the current line and execute ARCHIV.
The most likely way to do this is via a macro in your own EINIT file that does:
αβ⊗↔<filename>αZARCHIV⊗↔
The filename may include a /N switch if desired.
⊗⊃
αXDEFINE ARCHIV⊗↔
αXSTOPONE⊗↔αXTERSE⊗↔αXSILENT⊗↔
αZARCHV1⊗↔
α-αXSILENT⊗↔α-αXTERSE⊗↔αXSTOPALL⊗↔
αβ⊗↓
αXDEFINE ARCHV1⊗↔
αZARCHV2⊗↔
αβXSAY Sorry -- No file name found. Check ARCHIV documentation.⊗↔
αβD
αβ⊗↓
αXDEFINE ARCHV2⊗↔
αCαXIFEQ ATTSIZ.⊗↔αEαβ0αXNONEMPTY⊗↔
⊗↑αI ⊗αZARCHV5⊗⊗↔ α⊗= /C⊗⊗↔⊗αE
αAαXREDEFINE ARCHV4⊗↔αβK
αI ⊗απ⊗αε α⊗= /E⊗⊗↔⊗αXARGUMENT PAGES.⊗⊗↔⊗αP⊗α∞⊗αL⊗αXM⊗⊗↔⊗α⊗β2⊗αXABORT⊗⊗↔
αAαXREDEFINE ARCHV5⊗↔αβK
αZARCHV3⊗↔
αβXSAY Sorry -- No message text found.⊗↔
αβ2αXABORT⊗↔
αβ⊗↓
αXDEFINE ARCHV3⊗↔
α∂αCαXIFLE ATTSIZ.⊗↔αZARCHV4⊗↔
αβXSAY⊗↔αXARGUMENT LINES.⊗↔αXSAY⊗↔
αXARGUMENT PAGE.⊗↔αXSAY lines moved to page ⊗↔αXSAY .⊗↔
α.αG⊗↑α∂αβD
αβ3αXABORT⊗↔
αβ⊗↓
αxsay ARCHIV ⊗↔
⊗⊂ DON Purge selected pages from a file, such as BBOARD
This page contains three purge-related macros: PREPAR, ADJUST, and PURGE.
PREPAR is used to select pages to be purged and to prepare the page announcing
the upcoming purge. ADJUST is used to fix the page numbers listed in the
purge announcement if someone deletes some preceding pages. PURGE is used
to do the purge itself.
To prepare a purge, edit the file to be purged and execute the PREPAR macro.
It performs some initialisation, including setting up a few one-character
macros and reminding you of the functions of these latter macros. Then,
holding down the "control" buckybit, use: ≡ or ⊂ to include the current
page in the purge, ∩ to delete the current page immediately (e.g., if it
announces an event that is already past), and P to preserve a page. When
you've looked at all the pages, use the ∪ macro to set append the purge
announcement to the file. It also sets up a mail reminder telling you when
it's time to do the purge. (The date (actually, day of week) and time are
requested from you by the ∪ macro.)
If, before the purge takes place, someone deletes one or more pages from
the file such that the page numbers on the purge page are wrong, position
yourself at the first incorrect line on the purge page and execute ADJUST.
It decrements the page number on each line from there to the next blank
line. If more than one page has been deleted, you will have to reposition
yourself and do another ADJUST, until all the lines are correct again.
When the time comes to do the purge, go to the purge page and execute PURGE.
The first time it's executed, PURGE scans the current page for all lines
that look like E directory lines, collects them in a temporary window, and
sorts them. It then stops to let you look them over. When executed a
second time, it deletes the pages for which directory lines were gathered,
highest-numbered first. Before deleting each page, it verifies that the
current directory line from page 1 is the same as the one from the purge
list (except perhaps for the disk record number); if not, the page is
skipped. Before each page is deleted, you're shown the text from the
directory line along with the top line of the page, for a visual
double-check in case the automatic directory-line comparison fails; hit
ESCAPE-I if they don't match!! After deleting the selected pages, the
macro stops and shows you an account of what was done, pointing out how
many pages (if any) were spared due to directory-line mismatch. If you
like the results, hit ⊗Y to execute the macro a third time, whereupon it
will delete the auxiliary window and burp the file (using the BELCH macro
elsewhere in this CMD file).
You can control the amount of time that you have to type ESCAPE-I. Normally
the value of the numeric macro "PSHOW" is 1, meaning that the page will be
displayed for at least 1 second. If you're planning to not pay attention
anyway, then typing "α0αXSET PSHOW", which sets PSHOW to 0, will cause each
page to be displayed the minimum amount of time.
⊗⊃
αXDEFINE AUXWIN⊗↔
α⊗↔αXNDBBOARD⊗↔αI⊗απ⊗αε↓α2α $α⊗=↓.MSG[2,2]/C/Q⊗⊗↔αB↓α3α⊗↑αL$αβA
αXREDEFINE AUXOPN⊗↔αβKαβDαZAUXOPN⊗↔αG
αβ⊗↓
αXDEFINE PURGE⊗↔
αβ#αXSET PURGEX⊗↔ ⊗; discard repeat arg to guarantee 3-step execution
αβXARGUMENT PURGEV⊗↔αXCASE PURGE0 PURGE1 PURGE2⊗↔
αXADD PURGEV⊗↔αβ3αXREMAINDER PURGEV⊗↔
αβ⊗↓
αXDEFINE PURGE0⊗↔
αXREADWRITE⊗↔αXOPEN⊗↔α-αXAUTOBURP⊗↔αXTHISPAGE⊗↔
αXSTOPONE⊗↔αXSILENT⊗↔αXTERSE⊗↔α-αXCHECK⊗↔
αLαβ⊗↔PGαZAUXWIN⊗↔α∞αCαGαE
αXARGUMENT LINES.⊗↔αZPURG0A⊗↔
αXEXECUTE EINIT.CMD[1,3](11:12)⊗↔αZQNOSHO⊗↔αZQSORT⊗↔αβLα∞αZPURG0D⊗↔
αLαβ⊗↔⊗↔If you type ⊗⊗Y, the following pages will be deleted:⊗↔αβUαJ
αXSTOPALL⊗↔αXCHECK⊗↔α-αXTERSE⊗↔α-αXSILENT⊗↔
αβ⊗↓
αXDEFINE PURG0A⊗↔
αAα∞αβLαEαZPURG0B⊗↔α⊗↔α∞αβDαβL
αβ⊗↓
αXDEFINE PURG0B⊗↔
α6α7αXIFEQ ASCII.⊗↔α1α2αXIFLE CHARS.⊗↔αCαEαβ⊗↔⊗=XαβUαXJOIN⊗↔αXBREAK 16⊗↔
α αβ5αZPURG0C⊗↔αβ6αXIFEQ CHAR.⊗↔αβ3αβ2αXIFEQ ASCII.⊗↔
α αβ5αZPURG0C⊗↔αβ1αβ2αXIFEQ CHAR.⊗↔αβ9αXIFEQ ASCII.⊗↔
αK⊗↔α5α⊗↑αL⊗↔⊗↔αβD⊗↑αXJOIN⊗↔⊗↔
αβ⊗↓
αXDEFINE PURG0C⊗↔
αβ4αβ8αXIFLE ASCII.⊗↔αβ5αβ7αXIFGE ASCII.⊗↔α ⊗; Now you can see the <space>.
αβ⊗↓
αXDEFINE PURG0D⊗↔
αXBREAK 5⊗↔αβD⊗↔
αβ⊗↓
αXDEFINE PURGE1⊗↔
αXSTOPONE⊗↔αXSILENT⊗↔αXTERSE⊗↔α-αXCHECK⊗↔α3αXATTSET⊗↔α0αXSET PURGEZ⊗↔
α∞αLα∞αZPURG1A⊗↔
α8αXATTSET⊗↔αXSTOPALL⊗↔αXCHECK⊗↔α-αXTERSE⊗↔α-αXSILENT⊗↔
α-αβDαβ⊗↔αZPURGEZ⊗↔αβ2αXMINIMUM PURGEZ⊗↔
αXARGUMENT PURGEZ⊗↔αXCASE PURGZ0 PURGZ1 PURGZ2⊗↔α⊗↔α0α!⊗↔αJ
αβ⊗↓
αXDEFINE PURG1A⊗↔
⊗↑α0αXNONEMPTY⊗↔
αCαEαβ⊗↔⊗=⊗=⊗=αβUαXJOIN⊗↔αXBREAK 16⊗↔αK αDαβAαXTIN⊗↔αXREDEFINE PURGEX⊗↔αβK
αCα+αA⊗↑
αGαZPURG1B⊗↔αβKαG
α2αXMINIMUM PURGEX⊗↔αXADD PURGEX⊗↔
αβ⊗↔\/Deleted:/Can't delete page 1!/**SPARED**/α⊗→
αβXARGUMENT PURGEX⊗↔αK/αDαS/αK⊗↔⊗=α⊗↔αXJOIN⊗↔
αβ⊗↓
αXDEFINE PURG1B⊗↔
αXIFNE PURGEX⊗↔
αXADD PURGEZ⊗↔
α1αPα2αXARGUMENT PURGEX⊗↔αLα+αC
αXARGUMENT PURGEX⊗↔αβPα∞αLαE
α2αZPURG1D⊗↔
αXSET PURGEY=CHARS.⊗↔⊗↑
αXARGUMENT CHARS.⊗↔αXSUBTRACT PURGEY⊗↔
⊗↑α3αAα0αXIFEQ PURGEY⊗↔αE⊗↔
α-α1αXARGUMENT CHARS.⊗↔αZPURG1C⊗↔
⊗; look at one * to make sure rep count not 0, avoid second * lest BREAK fail
α2αβDα-αAα0αXIFEQ PURGEY⊗↔
α-α∞αEαXARGUMENT PSHOW⊗↔αVαEα∞α∂αA
α0αXSET PURGEX⊗↔
αXSUBTRACT PURGEZ⊗↔
αβ⊗↓
⊗⊂
PSHOW is used to decided how long the user has to type <esc>I. If you're going
off for coffee, then you might as well set it to 0 to save time.
⊗⊃
α1αXSET PSHOW⊗↔
αXDEFINE PURG1C⊗↔
αXSET PURGEY=ASCII.⊗↔αXBREAK 1⊗↔αβD⊗↔αXARGUMENT ASCII.⊗↔αXSUBTRACT PURGEY⊗↔
αXBREAK⊗↔αβD⊗↑α0αXIFEQ PURGEY⊗↔
αβ⊗↓
αXDEFINE PURG1D⊗↔
α2⊗↔αβ⊗↔ ⊗↔**αβ-αβ2αβAαXJOIN⊗↔ ⊗; make sure line is at least 17 columns
αXBREAK⊗↔ ⊗; most recent is BREAK 16 in PURG1A
αXTIN⊗↔αXSIN⊗↔αEαβDαXJOIN⊗↔
αβ⊗↓
αXDEFINE PURGZ0⊗↔
α⊗→No problems encountered; type ⊗⊗Y to delete this page and finish up.
αβ⊗↓
αXDEFINE PURGZ1⊗↔
page left undeleted due to directory-line mismatch; check the list⊗↔
below and, when satisfied, type ⊗⊗Y to delete this page and finish up.
αβ⊗↓
αXDEFINE PURGZ2⊗↔
pages left undeleted due to directory-line mismatches; check the list⊗↔
below and, when satisfied, type ⊗⊗Y to delete this page and finish up.
αβ⊗↓
αXDEFINE PURGE2⊗↔
αLα∞α∂αβDα1αXEXIT⊗↔
αβXSAY⊗↔α1α9αXAUTOBURP⊗↔αZBELCH⊗↔
αβ⊗↓
αβ0αXSET PURGEV⊗↔
αXDEFINE PREPAR⊗↔
α0αXSET PPRVAR⊗↔
αXEXECUTE EINIT.CMD[1,3](10)⊗↔αβXSAY macro loaded from EINIT[1,3]⊗↔
αXSET ≡=PPRMC1⊗↔αXSET ⊂=PPRMC1⊗↔
αXSET ∩=PPRMC2⊗↔
αXSET ∪=PPRMC3⊗↔
αβXSAY Use ≡ or ⊂ to include page, ∩ to delete page now, ∪ to send purge message.⊗↔
αβ⊗↓
αXDEFINE PPRMC1⊗↔
αZPPROPN⊗↔αXSET PPRVAR=PAGE.⊗↔α1αPα2αXARGUMENT PPRVAR⊗↔αLαC
αGαE⊗↔αGαOαP
αβ⊗↓
αXDEFINE PPRMC2⊗↔
αZPPROPN⊗↔αLα∞αβDαXDELETE⊗↔
αβ⊗↓
αXDEFINE PPRMC3⊗↔
αXMINIMUM PPRVAR⊗↔αβXARGUMENT PPRVAR⊗↔αβXCASE PPRM3B PPRM3A⊗↔
αβ⊗↓
αXDEFINE PPRM3A⊗↔
α0αXSET PPRVAR⊗↔
αXARGUMENT PAGES.⊗↔αPα∞αLαGα∂αβAαGαXMARK⊗↔αGα1αXEXIT⊗↔
αβ⊗↔
αβXSAY Type day of week, space, time of day, then hit control-∪ again.⊗↔
αβ⊗↓
αXDEFINE PPRM3B⊗↔
α⊗↔⊗↔αLα⊗=\,α⊗→αS,αDα⊗→αS\αK⊗↔αCαE
αI⊗αXREMIND/DATE=αS αI/TIME=αDα⊗= ./SUBJ Time for the BBOARD purge!⊗⊗↔
⊗α2⊗αXABORT⊗⊗↔αAαXREDEF PPRRMD⊗↔αβK
αLαIThe following pages will be purged on αS αI atα⊗=αI or so,⊗↔
unless someone objects before then.⊗↔α⊗↔
αLαXSUBJOB⊗↔αXLATTACH⊗↔
α0α=daytime⊗↔α0α=pp⊗↔
α+α6αXLRECEIVE⊗↔
α∞αXJOIN⊗↔αEα-αXSUBJOB⊗↔
αβ4αS 0αS-⊗B⊗BαL⊗↔β∂αS αβ2αDαS:αDαS αK,αDβ⊗Tα⊗T⊗B⊗TBBoard Purge⊗↔
αβ⊗↔Remember to check the purge-notice page for last-minute changes.αA
αXSILENT⊗↔αXTERSE⊗↔αXSTOPONE⊗↔α∞αZPPRM3C⊗↔αXSTOPALL⊗↔αβK
α1αPα∞αLα3⊗↑αCαOα∞αLαE⊗↔β⊗↔αβ.αXCLOSE⊗↔
α-αXTERSE⊗↔α-αXSILENT⊗↔
αβ⊗↓
αXDEFINE PPRM3C⊗↔
αZPPRRMD⊗↔
αβ⊗↓
αXDEFINE PPROPN⊗↔
αXMINIMUM PPRVAR⊗↔αXARGUMENT PPRVAR⊗↔αXCASE PPROP0 PPROP1⊗↔
αβ⊗↓
αXDEFINE PPROP0⊗↔
αXSAY ⊗↔
αZOPEN⊗↔
αLαβ⊗↔PPαZAUXWIN⊗↔
αβ⊗↓
αXDEFINE PPROP1⊗↔
⊗≠
αβ⊗↓
αXDEFINE ADJUST⊗↔
αXSTOPONE⊗↔α∞αZADJUS1⊗↔αXSTOPALL⊗↔
αβ⊗↓
αXDEFINE ADJUS1⊗↔
α0αXNONEMPTY⊗↔αXBREAK 7⊗↔⊗↔αXBREAK 5⊗↔αAαXREDEFINE ADJVAR⊗↔
α9α9α9α9α9αXADD ADJVAR⊗↔αβK⊗↑α⊗=αZADJVAR⊗↔α6α⊗↑αDα⊗↔αXJOIN⊗↔⊗↔
αβ⊗↓
αxARGUMENT PSHOW⊗↔αxsay PREPAR ADJUST PURGE PSHOW=⊗↔
⊗⊂ DON Find out the name of the file being edited
The NAME macro puts into the attach buffer a line containing the name of
the file currently being edited. The attach buffer is assumed to be empty
to begin with. No other significant side effects should occur; in particular,
the "W" flag in the header does not get set by executing this macro.
Leading and internal blanks in the filename are represented as underscores,
except that three leading blanks are converted to the ∂ notation.
⊗⊃
αXDEFINE NAME⊗↔
αXSILENT⊗↔αXTERSE⊗↔αXSUBJOB⊗↔αXLATTACH⊗↔αXSET NAMEWF=WFLAG.⊗↔αXTMPCOR⊗↔
α0α=tt w⊗↔α+α3αXLRECEIVE⊗↔ ⊗; ask for wholine, wait for output
α∞αXJOIN⊗↔αCαEpj ttyα4αDα3α αK⊗↔ ⊗; save for alias, form pj tty#
αβAα=αβKα+α3αXLRECEIVE⊗↔ ⊗; send that, wait for output
α1αβKα∞αXJOIN⊗↔αEαIr tmpcor;r ed#αK:α2αDαS αK⊗↔ ⊗; form tmpcor command
αβA⊗↑αE⊗↔α9α αI{}α⊗→αK(β{[α3α β,α3α β]}α⊗=αL}⊗↑αB{αDαL⊗↔⊗↔ ⊗; alias
α-α2αAαXJOIN⊗↔ ⊗; tack alias onto tmpcor name
α=αEα+α4αXLRECEIVE⊗↔ ⊗; send that, wait for output
α∞αXJOIN⊗↔αXBREAK 80⊗↔α+αAα1αEαβK ⊗; save up to 80 chars
⊗↑α3αDαS(αK⊗↔α⊗→ ⊗; extract first file name
α3α β∂α3αL_α⊗→αS∂∂α⊗=∂xxα⊗→αS∂αDαS∂αK⊗↔ ⊗; leading ___ becomes ∂
αβAαXARGUMENT NAMEWF⊗↔αXCASE NAMEW0 NAMEW1⊗↔ ⊗; CANCEL if appropriate
α-αXTERSE⊗↔α-αXSILENT⊗↔α-αXSUBJOB⊗↔
αβ⊗↓
αXDEFINE NAMEW0⊗↔
αXCANCEL⊗↔
αβ⊗↓
αXDEFINE NAMEW1⊗↔
⊗≠
αβ⊗↓
αxsay NAME ⊗↔
⊗⊂ RSF Send newly added BBOARD messages to "OTHER-SU-BBOARDS".
The OBBD macro can be used to conveniently forward appended BBOARD messages
to "OTHER-SU-BBOARDS". To use it, move the arrow to a line that begins
with a PPN (either 2 characters or 3) followed by " - ". (Note that the
PPN doesn't have to be yours, although it typically will be.) The attach
buffer should be empty to begin with. On executing the macro, the text on
this and the following lines will be mailed to OTHER-SU-BBOARDS.
In addition, the macro automatically does the following:
(i) The mail that it sends will have a subject line. This subject
is that of the first message that appears on the page (prefixed
by "re: "). The subject line will also indicate that the mail
came from SAIL's BBOARD.
(ii) It performs a αXNDBBOARD command (and deletes the old
header line).
(iii) It adds a note at the bottom of the page saying what lines have
been sent to OTHER-SU-BBOARDS.
The macro can fail for only three reasons (as far as I know):
(i) The arrow is not initially pointing to a line beginning
with "xy - " or "xyz - ". The macro uses this as a safety
check - it helps safeguard against accidentally forwarding
the wrong lines of text.
(ii) The first message on the page does not have a subject field
(either in the header line or in a separate "Subject:" line).
In this case you will be asked to add a subject to the header
line before resuming.
(iii) The first line on the page is not a message header.
In this case, you lose.
⊗⊃
αXDEFINE OBBD⊗↔
αXSILENT⊗↔αXTERSE⊗↔
αZOBB1⊗↔ ⊗; This extra level of nesting leads to cleaner error recovery.
α-αXSILENT⊗↔α-αXTERSE⊗↔
αβ⊗↓
αXDEFINE OBB1⊗↔
αZOBBCHK⊗↔ ⊗; Make sure that the arrow line is OK.
αXSET MSGLIN=LINE.⊗↔ ⊗; Remember this position.
αZOBBSUB⊗↔ ⊗; Find the subject.
αXARGUMENT MSGLIN⊗↔αL ⊗; Move the subject line back here.
α∞αAαXMAIL OTHER-SU-BBOARDS/SU⊗↔⊗; Actually send off the message.
αEαβD ⊗; Get rid of the subject line.
αXNDBBOARD⊗↔⊗↔αβD ⊗; Do αXNDBBOARD, etc.
αZOBBNOT⊗↔ ⊗; Add a notice at the bottom of the page.
αβ⊗↓
αXDEFINE OBBCHK⊗↔
αXSTOPONE⊗↔
α3α αZOBBHCH⊗↔ ⊗; Check for " - " starting from the 4th char.
α⊗↔α2α αZOBBHCH⊗↔ ⊗; If not, then check for " - " starting from the 3rd char.
α⊗↔αXSAY This line doesn't seem to begin with a PPN!⊗↔
αXBEEPME⊗↔α2αXABORT⊗↔ ⊗; Abort (to OBBD).
αβ⊗↓
αXDEFINE OBBHCH⊗↔
αβ3αβ2αXIFEQ ASCII.⊗↔ ⊗; Check for " ". (Note that we need the βs)
α αβ4αβ5αXIFEQ ASCII.⊗↔ ⊗; Check for "-".
α αβ3αβ2αXIFEQ ASCII.⊗↔ ⊗; Check for " ".
α⊗↔α2αXABORT⊗↔ ⊗; Success! Abort OBBCHK.
αβ⊗↓
αXDEFINE OBBSUB⊗↔ ⊗; Note: much of this was copied from DON's REPLY macro.
αLαXEMPTY⊗↔α+α0αXSSLINE⊗↔ ⊗; searches stop before first blank line
αXSTOPZERO⊗↔αLαF⊗↓≡⊗↔Subject:⊗↓⊗↔αXSTOPONE⊗↔ ⊗; look for RFC733 subject line
αXARGUMENT NFOUND.⊗↔αXCASE OBBS1 OBBS2⊗↔
αXSTOPZERO⊗↔α+αXSSLINE⊗↔αFre: re:αβ\re:⊗↔ ⊗; Delete redundant "re: " (if any).
α⊗= (from SAIL's BBOARD)
αA ⊗; Now grab onto the subject.
αβ⊗↓
αXDEFINE OBBS1⊗↔ ⊗; Looks for a subject in the header line.
αZOBBS1A⊗↔ ⊗; try for "∂" line (aborts OBBS1 if succeeds)
αL∂α⊗=⊗=αXSAY No subject found! Put one here, then go back and try again.⊗↔
αXBEEPME⊗↔αβ3αXABORT⊗↔ ⊗; Abort (to OBBD). (Note: it must be αβ3)
αβ⊗↓
αXDEFINE OBBS1A⊗↔
α1α5αXIFEQ ASCII.⊗↔ ⊗; check top line for "∂"
α+αXSSLINE⊗↔α2αF⊗=⊗↔ ⊗; does line include two tabs?
α+α1αXARGUMENT SRCHAR.⊗↔αXIFLT CHARS.⊗↔ ⊗; and does second tab have stuff after it?
αCαEαXSSLINE⊗↔αF⊗=αβ\ αβ2⊗↔ ⊗; a winner! copy it; tabs -> dbl-space
αXBREAK SRCHAR.⊗↔ ⊗; break between second pair of spaces
αβDα1αβ⊗↔re:α⊗↔αXJOIN⊗↔ ⊗; create our subject line
αAαXTIN⊗↔αXSIN⊗↔αE ⊗; flush trailing blanks
α2αXABORT⊗↔ ⊗; abort OBBS1
αβ⊗↓
αXDEFINE OBBS2⊗↔
⊗↔αCαEαFSubject:αβ\re:⊗↔⊗↑⊗↔ ⊗; copy RFC733 subject line and make it ours
αβ⊗↓
αXDEFINE OBBNOT⊗↔
αQαKα⊗=αKα αDα⊗=αLα⊗=⊗=α⊗→αSα⊗=αKα⊗↔αA ⊗; Isolate (and attach) your own PPN.
α∞αLαEαβ⊗↔α⊗↔⊗↔ ⊗; Take it to the bottom, and insert a blank line.
⊗; Now create the notice:
β[α⊗= - Forwarded to OTHER-SU-BBOARDS from line αZMSGLIN⊗↔]αβ⊗↔α⊗↔
αβ⊗↓
αXSAY OBBD ⊗↔
⊗⊂ RSF, DON Perform housekeeping after having done a BBOARD merge.
The MERGE macro can be used to do a αXNDBBOARD and write out the
page after you've merged two or more messages in BBOARD. Note that it is
no longer appropriate to add a message at the bottom explaining that there
has been a merge. (See NOTICE[UP,DOC]/288P.)
To use the macro, simply execute it anywhere on the page where
the merge took place. If there is text in the attach buffer (e.g., the
message(s) to be merged), it is appended to the page.
⊗⊃
αXDEFINE MERGE⊗↔
α∞αLα0αA ⊗; Drop attach buffer, if any.
αZBLANK1⊗↔ ⊗; Ensure exactly one blank line.
αXNDBBOARD⊗↔⊗↔αβD ⊗; Do αXNDBBOARD, etc.
α∞αLαZBLANK1⊗↔ ⊗; Ensure exactly one blank line at end.
αZWWRITE⊗↔ ⊗; Write without rippling
αβ⊗↓
αXDEFINE BLANK1⊗↔
αβ⊗↔⊗↔⊗↔xα⊗↔ ⊗; Insert two blank lines & known line.
α-αXNONEMPTY⊗↔α2⊗↔αFxαβDαβD ⊗; Delete "x" and all but one blank line.
αβ⊗↓
⊗; The WWRITE macro writes out the current page without rippling. (Suggested by YM)
αXDEFINE WWRITE⊗↔
αXSILENT⊗↔αXSTOPZERO⊗↔
α∞αXAPPEND⊗↔
αXTHISPAGE⊗↔
α-αXSILENT⊗↔αXSTOPALL⊗↔
αβ⊗↓
αXSAY MERGE ⊗↔
⊗⊂ DON Skim BBOARD pages
This page defines two macros, BBSKIM and BBGUN. BBSKIM lets you look at the
header lines of a large file (such as BBOARD) and select which pages you want
to look at. BBGUN temporarily deletes extraneous mail-header information from
a single page of a file.
When you execute BBSKIM anywhere except on page 1 of a file, the macro leaves
you on page 1 looking at the header lines of the pages of the file, starting
with the page you were on when you executed BBSKIM and continuing to the end.
The header lines are condensed to show just the page number and the subject
(defined to be the text following the last tab on the line; if there was no
subject field you get the sender's name instead). The macro instructs you to
delete all lines except the ones for pages you want to look at, then to type ⊗Y
to execute BBSKIM again. When you do so, it restores the directory page, puts
you at the top of the first page you wanted to see, and puts marks at the tops
of all the other pages you selected (up to a limit of 24 pages total).
The BBGUN macro deletes all extraneous header lines from wherever you are
through the end of the page. It finds these lines by looking for the string
"Subject: ", so it's possible it could delete too much in some weird cases.
Whenever it finds a Subject line, it deletes that paragraph (i.e., everything
between the nearest blank lines) except for the first header line (usually the
"∂" line). When BBGUN is done, it puts you back at the paragraph you were in
when you executed it. It also puts you into READONLY mode as protection against
making permanent changes to the file. You will have to do a αXCANCEL before
going to a different page.
⊗⊃
αXDEFINE BBSKIM⊗↔
αXSILENT⊗↔αXTERSE⊗↔α-αXCHECK⊗↔
αβ1αXSET BBPAGE⊗↔αXARGUMENT PAGE.⊗↔αXDIVIDE BBPAGE⊗↔
αXARGUMENT BBPAGE⊗↔αXCASE BBSKM0 BBSKM1⊗↔
αXCHECK⊗↔α-αXSILENT⊗↔α-αXTERSE⊗↔
αβ⊗↓
αXDEFINE BBSKM0⊗↔
αXSET BBRMOD=RMODE.⊗↔αXREADONLY⊗↔
αXSET BBPAGE=PAGE.⊗↔α1αPα2αXARGUMENT BBPAGE⊗↔αL
αXSET BBREPS=LINES.⊗↔α3αXARGUMENT BBPAGE⊗↔αXSUBTRACT BBREPS⊗↔
αXSTOPZERO⊗↔α-αXUNDELETE⊗↔αXARGUMENT BBREPS⊗↔αZBBSPLT⊗↔
α2αβDα2αXARGUMENT BBPAGE⊗↔αLα-α∞αβDαXTIN⊗↔
α-α5α0α0α0αXUNDELETE⊗↔αXSTOPALL⊗↔αXSSLINE⊗↔
αβXSAY Delete all uninteresting lines, then type ⊗⊗Y⊗↔
αβ⊗↓
αXDEFINE BBSPLT⊗↔
α+αXSSLINE⊗↔α∞αF⊗=⊗↔αXARGUMENT NFOUND.⊗↔αF⊗=αβ\>>$!>: ⊗↔α1αXSIN⊗↔
αF>$!>:⊗↔αXBREAK SRCHAR.⊗↔αXBREAK 9⊗↔αβDαXBREAK 3⊗↔⊗↔αβD
αXBREAK 4⊗↔αβD⊗↑αXJOIN⊗↔⊗↔
αβ⊗↓
αXDEFINE BBSKM1⊗↔
αβXSAY⊗↔αXSTOPONE⊗↔αZBBWARN⊗↔αLαXARGUMENT LINES.⊗↔αZBBMARK⊗↔
αLα⊗=α3⊗↑⊗α0⊗αXIFEQ BBRMOD⊗⊗↔⊗αXREADWRITE⊗⊗↔αβAα∞αLαE
αLα∞αXREDEFINE BBPAGE⊗↔αXCANCEL⊗↔αXZMARKS⊗↔αZBBPAGE⊗↔αXSTOPALL⊗↔
αβXSAY This is the first you wanted; get to others (if any) using ⊗αM⊗↔
αβ⊗↓
αXDEFINE BBWARN⊗↔
αβ2αβ4αXIFLT LINES.⊗↔αβ2αβ4αβLαXBREAK 3⊗↔α1αXREDEFINE BBPAGE⊗↔αXJOIN⊗↔⊗↔α∞αβD
αXARGUMENT BBPAGE⊗↔αβXSAY Limit is 24 pages. Re-execute BB when you reach page ⊗↔
αβ⊗↓
αXDEFINE BBMARK⊗↔
αXBREAK 3⊗↔β⊗αα β⊗αα β⊗αα ⊗αP⊗α⊗βM⊗↔αβD
αβ⊗↓
αXDEFINE BBGUN⊗↔
αXREADONLY⊗↔αXTERSE⊗↔αXSILENT⊗↔αXSTOPONE⊗↔α0α!⊗↔αXSET BBLINE=LINE.⊗↔
α∞αXTIN⊗↔α∞αZBBGUN2⊗↔αXARGUMENT BBLINE⊗↔αLαJαXSTOPALL⊗↔
α-αXSILENT⊗↔α-αXTERSE⊗↔
αβ⊗↓
αXDEFINE BBGUN2⊗↔
αFSubject:⊗↔α0α!α2⊗↔αβ!αβDαβD
αβ⊗↓
αxsay BBSKIM BBGUN ⊗↔