A30 stuff

This commit is contained in:
mysticbbs 2013-03-23 11:22:51 -04:00
parent 504ec5afea
commit 76e9dcc96e
9 changed files with 243 additions and 71 deletions

View File

@ -98,11 +98,16 @@ Var
Form : TAnsiMenuForm; Form : TAnsiMenuForm;
Topic : String; Topic : String;
Links : LongInt; Links : LongInt;
OrigFN : String;
OrigPath : String;
Begin Begin
Topic := '|03(|09Message Base Edit|03) |01-|09> |15'; Topic := '|03(|09Message Base Edit|03) |01-|09> |15';
Box := TAnsiMenuBox.Create; Box := TAnsiMenuBox.Create;
Form := TAnsiMenuForm.Create; Form := TAnsiMenuForm.Create;
OrigFN := MBase.FileName;
OrigPath := Mbase.Path;
Box.Shadow := False; Box.Shadow := False;
Box.Header := ' Index ' + strI2S(MBase.Index) + ' '; Box.Header := ' Index ' + strI2S(MBase.Index) + ' ';
@ -167,6 +172,28 @@ Begin
MBase.NewsName := strReplace(MBase.NewsName, ' ', '.'); MBase.NewsName := strReplace(MBase.NewsName, ' ', '.');
If (MBase.FileName <> OrigFN) or (MBase.Path <> OrigPath) Then
If ShowMsgBox (1, 'Path/Filename changed. Rename? ') Then Begin
FileRename (OrigPath + OrigFN + '.lnk', MBase.Path + MBase.FileName + '.lnk');
FileRename (OrigPath + OrigFN + '.scn', MBase.Path + MBase.FileName + '.scn');
Case MBase.BaseType of
0 : Begin
FileRename (OrigPath + OrigFN + '.jhr', MBase.Path + MBase.FileName + '.jhr');
FileRename (OrigPath + OrigFN + '.jlr', MBase.Path + MBase.FileName + '.jlr');
FileRename (OrigPath + OrigFN + '.jdt', MBase.Path + MBase.FileName + '.jdt');
FileRename (OrigPath + OrigFN + '.jdx', MBase.Path + MBase.FileName + '.jdx');
End;
1 : Begin
FileRename (OrigPath + OrigFN + '.sqd', MBase.Path + MBase.FileName + '.sqd');
FileRename (OrigPath + OrigFN + '.sqi', MBase.Path + MBase.FileName + '.sqi');
FileRename (OrigPath + OrigFN + '.sql', MBase.Path + MBase.FileName + '.sql');
End;
End;
End;
Box.Close; Box.Close;
Form.Free; Form.Free;

View File

@ -21,6 +21,7 @@ Type
CurX : Byte; CurX : Byte;
CurY : SmallInt; CurY : SmallInt;
CurAttr : Byte; CurAttr : Byte;
QuoteAttr : Byte;
CurLength : Byte; CurLength : Byte;
TopLine : LongInt; TopLine : LongInt;
CurLine : LongInt; CurLine : LongInt;
@ -101,6 +102,7 @@ Begin
CurLine := 1; CurLine := 1;
TopLine := 1; TopLine := 1;
CurAttr := 7; CurAttr := 7;
QuoteAttr := 9;
InsertMode := True; InsertMode := True;
DrawMode := False; DrawMode := False;
GlyphMode := False; GlyphMode := False;
@ -380,6 +382,7 @@ Begin
CurX := 1; CurX := 1;
CurY := 1; CurY := 1;
CurAttr := Session.io.ScreenInfo[1].A; CurAttr := Session.io.ScreenInfo[1].A;
QuoteAttr := Session.io.ScreenInfo[2].A;
FindLastLine; FindLastLine;
End; End;
@ -400,6 +403,7 @@ Begin
While TopLine + CurY - 1 > LastLine Do While TopLine + CurY - 1 > LastLine Do
Dec (CurY); Dec (CurY);
(*
If Not DrawMode Then Begin If Not DrawMode Then Begin
If (CurX > 1) and (CurX = CurLength + 1) Then If (CurX > 1) and (CurX = CurLength + 1) Then
CurAttr := ANSI.Data[CurLine][CurX - 1].Attr CurAttr := ANSI.Data[CurLine][CurX - 1].Attr
@ -408,7 +412,7 @@ Begin
If CurAttr = 0 Then CurAttr := 7; If CurAttr = 0 Then CurAttr := 7;
End; End;
*)
With TBBSCore(Owner).io Do Begin With TBBSCore(Owner).io Do Begin
AnsiGotoXY (WinX1 + CurX - 1, WinY1 + CurY - 1); AnsiGotoXY (WinX1 + CurX - 1, WinY1 + CurY - 1);
AnsiColor (CurAttr); AnsiColor (CurAttr);
@ -814,6 +818,7 @@ Begin
End; End;
SetLineText (CurLine, Text[NumLines]); SetLineText (CurLine, Text[NumLines]);
ANSI.SetLineColor (QuoteAttr, CurLine);
If CurY > WinSize Then If CurY > WinSize Then
ScrollDown(False); ScrollDown(False);
@ -896,15 +901,20 @@ Var
Var Var
Count : Byte; Count : Byte;
Begin Begin
Session.io.AnsiColor(11); // quote text color Session.io.AnsiColor (QuoteAttr);
For Count := 1 to QWinSize Do Begin For Count := 1 to QWinSize + 1 Do Begin
Session.io.AnsiGotoXY (WinX1, WinY1 + Count - 1); Session.io.AnsiGotoXY (WinX1, WinY1 + Count - 1);
If Count <= QWinSize Then
Session.io.BufAddStr(QWinData[Count]); Session.io.BufAddStr(QWinData[Count]);
Session.io.AnsiClrEOL; Session.io.AnsiClrEOL;
End; End;
End; End;
Var
Temp : Integer;
Begin Begin
Added := False; Added := False;
@ -913,9 +923,9 @@ Begin
If IoResult <> 0 Then Exit; If IoResult <> 0 Then Exit;
QuoteLines := 0;
NoMore := False; NoMore := False;
QWinDataPos := 0; QWinDataPos := 0;
QuoteLines := 0;
While Not Eof(InFile) Do Begin While Not Eof(InFile) Do Begin
Inc (QuoteLines); Inc (QuoteLines);
@ -926,10 +936,13 @@ Begin
Session.io.OutFile ('ansiquot', True, 0); Session.io.OutFile ('ansiquot', True, 0);
FillChar(QWinData, SizeOf(QWinData), 0); FillChar (QWinData, SizeOf(QWinData), 0);
QWinSize := Session.io.ScreenInfo[1].Y - WinY1 + 1; QWinSize := Session.io.ScreenInfo[1].Y - WinY1 + 1;
For Temp := CurLine - ((QWinSize DIV 2) + 1) To CurLine - 1 Do
If Temp >= 1 Then AddQuoteWin(GetLineText(Temp));
DrawQWin; DrawQWin;
UpdateWindow; UpdateWindow;
@ -1022,7 +1035,7 @@ Begin
InsertLine (CurLine); InsertLine (CurLine);
SetLineText (CurLine, QText[QuoteTopPage + QuoteCurLine]); SetLineText (CurLine, QText[QuoteTopPage + QuoteCurLine]);
ANSI.SetLineColor (11, CurLine); ANSI.SetLineColor (QuoteAttr, CurLine);
Inc (CurLine); Inc (CurLine);
Inc (CurY); Inc (CurY);
@ -1051,7 +1064,15 @@ Begin
Session.io.OutFull('|16'); Session.io.OutFull('|16');
// If (CurLine < mysMaxMsgLines) And Added Then Inc(CurLine); If CurLine < mysMaxMsgLines Then Begin
Inc (CurLine);
Inc (CurY);
InsertLine(CurLine);
If CurY > WinSize Then
ScrollDown(False);
End;
End; End;
Procedure TEditorANSI.Commands; Procedure TEditorANSI.Commands;

View File

@ -26,7 +26,7 @@ Type
Function OpenMsgBase : Boolean; Virtual; {Open the message base} Function OpenMsgBase : Boolean; Virtual; {Open the message base}
Procedure CloseMsgBase; Virtual; {Close the message base} Procedure CloseMsgBase; Virtual; {Close the message base}
Function CreateMsgBase(MaxMsg: Word; MaxDays: Word): Boolean; Virtual; Function CreateMsgBase(MaxMsg: Word; MaxDays: Word): Boolean; Virtual;
Function MsgBaseExists: Boolean; Virtual; {Does msg base exist} // Function MsgBaseExists: Boolean; Virtual; {Does msg base exist}
Function LockMsgBase: Boolean; Virtual; {Lock the message base} Function LockMsgBase: Boolean; Virtual; {Lock the message base}
Function UnLockMsgBase: Boolean; Virtual; {Unlock the message base} Function UnLockMsgBase: Boolean; Virtual; {Unlock the message base}
Procedure SetDest (Addr: RecEchoMailAddr); Virtual; {Set Zone/Net/Node/Point for Dest} Procedure SetDest (Addr: RecEchoMailAddr); Virtual; {Set Zone/Net/Node/Point for Dest}
@ -513,9 +513,11 @@ Function TMsgBaseABS.CreateMsgBase(MaxMsg: Word; MaxDays: Word): Boolean;
Begin Begin
End; End;
(*
Function TMsgBaseABS.MsgBaseExists: Boolean; Function TMsgBaseABS.MsgBaseExists: Boolean;
Begin Begin
End; End;
*)
Procedure TMsgBaseABS.StartNewMsg; Procedure TMsgBaseABS.StartNewMsg;
Begin Begin

View File

@ -149,7 +149,7 @@ Type
Function OpenMsgBase: Boolean; Virtual; {Open message base} Function OpenMsgBase: Boolean; Virtual; {Open message base}
Procedure CloseMsgBase; Virtual; {Close message base} Procedure CloseMsgBase; Virtual; {Close message base}
Function CreateMsgBase(MaxMsg: Word; MaxDays: Word): Boolean; Virtual; Function CreateMsgBase(MaxMsg: Word; MaxDays: Word): Boolean; Virtual;
Function MsgBaseExists: Boolean; Virtual; // Function MsgBaseExists: Boolean; Virtual;
Procedure SetMsgPath(FN: String); Virtual; {Set filepath and name - no extension} Procedure SetMsgPath(FN: String); Virtual; {Set filepath and name - no extension}
Function SqdOpen: Boolean; Virtual; {Open squish data file} Function SqdOpen: Boolean; Virtual; {Open squish data file}
Function SqiOpen: Boolean; Virtual; {Open squish index file} Function SqiOpen: Boolean; Virtual; {Open squish index file}
@ -429,10 +429,10 @@ Begin
CreateMsgBase := False; CreateMsgBase := False;
End; End;
Function TMsgBaseSquish.MsgBaseExists: Boolean; //Function TMsgBaseSquish.MsgBaseExists: Boolean;
Begin //Begin
MsgBaseExists := FileExist(SqInfo^.FN + '.sqd'); // MsgBaseExists := FileExist(SqInfo^.FN + '.sqd');
End; //End;
Procedure TMsgBaseSquish.SqdClose; Procedure TMsgBaseSquish.SqdClose;
Begin Begin

View File

@ -13,7 +13,8 @@
; Many different configuration files can exist to perform any series of ; Many different configuration files can exist to perform any series of
; tasks supported by MUTIL, or a single configuration can be maintained that ; tasks supported by MUTIL, or a single configuration can be maintained that
; does everything. The minimum requirement is the General header with a ; does everything. The minimum requirement is the General header with a
; task enabled, and then the specific header for that task. ; task enabled, and then the specific header for that task that defines its
; options.
; ;
; Current abilities (enabled/disabled in the General header below): ; Current abilities (enabled/disabled in the General header below):
; ;
@ -22,7 +23,8 @@
; - Import Message Bases (by datafile analysis) ; - Import Message Bases (by datafile analysis)
; - Import FIDONET.NA into Message bases ; - Import FIDONET.NA into Message bases
; - Import FILEBONE.NA into File bases ; - Import FILEBONE.NA into File bases
; - Mass upload files to all file bases (with FILE_ID.DIZ import) ; - Mass upload files to all file bases (with FILE_ID.DIZ import and the
; ability to exclude files by filemask)
; - Generate Top 1 up to 99 Callers, Posters, Downloaders, Uploaders, PCR ; - Generate Top 1 up to 99 Callers, Posters, Downloaders, Uploaders, PCR
; Completely configurable output by using template files ; Completely configurable output by using template files
; - Import FILES.BBS into file bases ; - Import FILES.BBS into file bases
@ -63,13 +65,13 @@
Import_MessageBase = false Import_MessageBase = false
Import_FILEBONE.NA = false Import_FILEBONE.NA = false
Import_FILES.BBS = false Import_FILES.BBS = false
MassUpload = true MassUpload = false
GenerateTopLists = false GenerateTopLists = false
GenerateAllFiles = false GenerateAllFiles = false
PurgeMessageBases = false PurgeMessageBases = false
PostTextFiles = false PostTextFiles = false
PackMessageBases = false PackMessageBases = false
ImportEchoMail = false ImportEchoMail = true
ExportEchoMail = false ExportEchoMail = false
; ========================================================================== ; ==========================================================================
@ -287,6 +289,10 @@
top_pcr_namelen = 30 top_pcr_namelen = 30
top_pcr_datalen = 10 top_pcr_datalen = 10
; ==========================================================================
; ==========================================================================
; ==========================================================================
[GenerateAllFiles] [GenerateAllFiles]
; Generate all files list ; Generate all files list
@ -300,14 +306,26 @@
; header, footer, baseheader, basefooter, exclude bases, uploader optional ; header, footer, baseheader, basefooter, exclude bases, uploader optional
; uploader line, format list line 1st,2nd line, space between files? ; uploader line, format list line 1st,2nd line, space between files?
; ==========================================================================
; ==========================================================================
; ==========================================================================
[PurgeMessageBases] [PurgeMessageBases]
; No options for this function ; No options for this function
; ==========================================================================
; ==========================================================================
; ==========================================================================
[PackMessageBases] [PackMessageBases]
; No options for this function ; No options for this function
; ==========================================================================
; ==========================================================================
; ==========================================================================
[PostTextFiles] [PostTextFiles]
; Total number of text files to be posted. For each file there needs to ; Total number of text files to be posted. For each file there needs to
@ -341,6 +359,10 @@
file2_addr = 0:0/0 file2_addr = 0:0/0
file2_delfile = false file2_delfile = false
; ==========================================================================
; ==========================================================================
; ==========================================================================
[Import_MessageBase] [Import_MessageBase]
; This option scans the message base directory, and creates any messages ; This option scans the message base directory, and creates any messages
@ -363,6 +385,10 @@
max_msgs = 500 max_msgs = 500
max_msgs_age = 365 max_msgs_age = 365
; default base type when creating (if unknown) 0=jam 1=squish
base_format = 0
; network type (0=local, 1=echomail, 2=newsgroup 3=netmail) ; network type (0=local, 1=echomail, 2=newsgroup 3=netmail)
net_type = 1 net_type = 1
@ -376,6 +402,31 @@
new_scan = 1 new_scan = 1
qwk_scan = 1 qwk_scan = 1
; ==========================================================================
; ==========================================================================
; ==========================================================================
[ImportEchoMail] [ImportEchoMail]
; If you want to save duplicated / bad messages to a certain message
; base, then set this value to the *INDEX* of the message base (viewable
; at the top of the editor). Otherwise, set this value to -1 or leave it
; commented out and they will be ignored
dupe_msg_index = 5
; Set this value to true if you'd like to auto create message bases when
; an incoming message is found for an area that does not exist. MUTIL
; takes default values from the Import_MessageBase function and the system
; configuration, then uses attributes from the message itself in order to
; build a new message base profile.
auto_create = true
; ==========================================================================
; ==========================================================================
; ==========================================================================
[ExportEchoMail] [ExportEchoMail]
; no options for this area yet

View File

@ -68,6 +68,8 @@ Var
TotalNet : LongInt; TotalNet : LongInt;
TotalDupes : LongInt; TotalDupes : LongInt;
EchoNode : RecEchoMailNode; EchoNode : RecEchoMailNode;
DupeIndex : LongInt;
CreateBases : Boolean;
Procedure ImportNetMailpacket (ArcFN: String); Procedure ImportNetMailpacket (ArcFN: String);
Var Var
@ -114,6 +116,7 @@ Var
MBase : RecMessageBase; MBase : RecMessageBase;
Part : LongInt; Part : LongInt;
Whole : LongInt; Whole : LongInt;
Count : LongInt;
Begin Begin
FoundPKT := False; FoundPKT := False;
PKT := TPKTReader.Create; PKT := TPKTReader.Create;
@ -152,16 +155,87 @@ Var
If PKT.IsDuplicate Then Begin If PKT.IsDuplicate Then Begin
Log (3, '!', ' Duplicate message found in ' + PKT.MsgArea); Log (3, '!', ' Duplicate message found in ' + PKT.MsgArea);
If DupeIndex <> -1 Then Begin
CurTag := ''; // force next real msg to get mbase record
// TODO for speed:
// load dupe base first before all processsing
// add a way to not close/reopen if last was dupe (simple boolean)
If GetMBaseByIndex (DupeIndex, MBase) Then Begin
If MsgBase <> NIL Then Begin
MsgBase^.CloseMsgBase;
Dispose (MsgBase, Done);
MsgBase := NIL;
End;
MessageBaseOpen (MsgBase, MBase);
SavePKTMsgToBase (MsgBase, PKT, False);
End;
End;
Inc (TotalDupes); Inc (TotalDupes);
End Else Begin End Else Begin
If CurTag <> PKT.MsgArea Then Begin If CurTag <> PKT.MsgArea Then Begin
If Not GetMBaseByTag(PKT.MsgArea, MBase) Then Begin If Not GetMBaseByTag(PKT.MsgArea, MBase) Then Begin
Log (2, '!', ' Area ' + PKT.MsgArea + ' does not exist'); Log (2, '!', ' Area ' + PKT.MsgArea + ' does not exist');
// create base here optionally and do not CONTINUE fall If Not CreateBases then Continue;
// through to save message. or optionally move to badmsg
// or dupemsg base If FileExist(bbsConfig.MsgsPath + PKT.MsgArea + '.sqd') or
Continue; FileExist(bbsConfig.MsgsPath + PKT.MsgArea + '.jhr') Then Continue;
FillChar (MBase, SizeOf(MBase), #0);
MBase.Index := GenerateMBaseIndex;
MBase.Name := PKT.MsgArea;
MBase.QWKName := PKT.MsgArea;
MBase.NewsName := PKT.MsgArea;
MBase.FileName := PKT.MsgArea;
MBase.EchoTag := PKT.MsgArea;
MBase.Path := bbsConfig.MsgsPath;
MBase.NetType := 2;
MBase.ColQuote := bbsConfig.ColorQuote;
MBase.ColText := bbsConfig.ColorText;
MBase.ColTear := bbsConfig.ColorTear;
MBase.ColOrigin := bbsConfig.ColorOrigin;
MBase.ColKludge := bbsConfig.ColorKludge;
MBase.Origin := bbsConfig.Origin;
MBase.BaseType := INI.ReadInteger(Header_IMPORTMB, 'base_type', 0);
MBase.ListACS := INI.ReadString(Header_IMPORTMB, 'acs_list', '');
MBase.ReadACS := INI.ReadString(Header_IMPORTMB, 'acs_read', '');
MBase.PostACS := INI.ReadString(Header_IMPORTMB, 'acs_post', '');
MBase.NewsACS := INI.ReadString(Header_IMPORTMB, 'acs_news', '');
MBase.SysopACS := INI.ReadString(Header_IMPORTMB, 'acs_sysop', 's255');
MBase.Header := INI.ReadString(Header_IMPORTMB, 'header', 'msghead');
MBase.RTemplate := INI.ReadString(Header_IMPORTMB, 'read_template', 'ansimrd');
MBase.ITemplate := INI.ReadString(Header_IMPORTMB, 'index_template', 'ansimlst');
MBase.MaxMsgs := INI.ReadInteger(Header_IMPORTMB, 'max_msgs', 500);
MBase.MaxAge := INI.ReadInteger(Header_IMPORTMB, 'max_msgs_age', 365);
MBase.DefNScan := INI.ReadInteger(Header_IMPORTMB, 'new_scan', 1);
MBase.DefQScan := INI.ReadInteger(Header_IMPORTMB, 'qwk_scan', 1);
MBase.NetAddr := 1;
For Count := 1 to 30 Do
If bbsConfig.NetAddress[Count].Zone = PKT.PKTHeader.DestZone Then Begin
MBase.NetAddr := Count;
Break;
End;
If INI.ReadString(Header_IMPORTMB, 'use_autosig', '1') = '1' Then
MBase.Flags := MBase.Flags OR MBAutoSigs;
If INI.ReadString(Header_IMPORTMB, 'use_realname', '0') = '1' Then
MBase.Flags := MBase.Flags OR MBRealNames;
If INI.ReadString(Header_IMPORTMB, 'kill_kludge', '1') = '1' Then
MBase.Flags := MBase.Flags OR MBKillKludge;
// ADD DOWNLINK INFORMATION HERE INTO ECHONODES??
AddMessageBase(MBase);
End; End;
If MsgBase <> NIL Then Begin If MsgBase <> NIL Then Begin
@ -246,6 +320,11 @@ Begin
Exit; Exit;
End; End;
// read INI values
CreateBases := INI.ReadBoolean(Header_ECHOIMPORT, 'auto_create', False);
DupeIndex := INI.ReadInteger(Header_ECHOIMPORT, 'dupe_msg_index', -1);
FindFirst (bbsConfig.InboundPath + '*', AnyFile, DirInfo); FindFirst (bbsConfig.InboundPath + '*', AnyFile, DirInfo);
While DosError = 0 Do Begin While DosError = 0 Do Begin

View File

@ -87,47 +87,26 @@ Type
RecEchoMailExport = LongInt; RecEchoMailExport = LongInt;
(*
RecEchoMailOpts = Record
SysLocation : String[40];
SysFlags : String[40];
IncomingPath : String[mysMaxPathSize];
SIncomingPath : String[mysMaxPathSize];
OutboundPath : String[mysMaxPathSize];
NodeListPath : String[mysMaxPathSize];
ZoneMap : String[128];
FTPPort : Word;
BINKPPort : Word;
Res : Array[1..485] of Char;
End;
RecEchomailNodeFTP = Record
Host : String[60];
Login : String[30];
Password : String[30];
Directory : String[80];
End;
RecEchomailNodeBINKP = Record
Host : String[60];
TimeOut : Word;
BlockSize : Word;
Res : Array[1..10] of Byte;
End;
*)
RecEchoMailNode = Record RecEchoMailNode = Record
Index : LongInt; Index : LongInt;
Description : String[35]; Description : String[35];
Active : Boolean; Active : Boolean;
Address : RecEchoMailAddr; Address : RecEchoMailAddr;
Domain : String[8];
ArcType : String[4]; ArcType : String[4];
// InType : Byte; // 0=Disabled 1=FTP 2=BINKP 3=EMAIL 4=DIRECTORY MailType : Byte;
// OutType : Byte; // 0=Disabled 1=FTP 2=BINKP 3=EMAIL 4=DIRECTORY binkHost : String[60];
// FTPin : RecEchoMailNodeFTP; binkPort : Word;
// FTPout : RecEchoMailNodeFTP; binkTimeout : Word;
// BINKPin : RecEchoMailNodeBINKP; binkBlock : Word;
// BINKPout : RecEchoMailNodeBINKP; binkMD5 : Byte;
ftpOutHost : String[60];
ftpOutPort : Word;
ftpOutLogin : String[20];
ftpOutPass : String[20];
ftpInDir : String[60];
ftpOutDir : String[60];
ftpTimeOut : Word;
LastRecv : LongInt; LastRecv : LongInt;
LastSent : LongInt; LastSent : LongInt;
LastReset : LongInt; LastReset : LongInt;
@ -135,6 +114,7 @@ Type
InSize : Cardinal; InSize : Cardinal;
OutFiles : Cardinal; OutFiles : Cardinal;
OutSize : Cardinal; OutSize : Cardinal;
Res : Array[1..512] of Byte;
End; End;
RecSauceInfo = Packed Record RecSauceInfo = Packed Record

View File

@ -29,6 +29,7 @@ BUGS AND POSSIBLE ISSUES
FUTURE / IDEAS / WORK IN PROGRESS / NOTES FUTURE / IDEAS / WORK IN PROGRESS / NOTES
========================================= =========================================
- EXCLUDE from all files list. important.
- Reply to echomail via netmail. - Reply to echomail via netmail.
- Msgbase flag for AKA matching or just rewrite netmail all together. - Msgbase flag for AKA matching or just rewrite netmail all together.
- Amiga .readme and .TIC processing (similar) - Amiga .readme and .TIC processing (similar)

View File

@ -2944,5 +2944,16 @@
facilitate separation from regular text. The text will wrap and facilitate separation from regular text. The text will wrap and
reformat itself so no text should be lost. reformat itself so no text should be lost.
+ If you change message base's storage filename or path, Mystic will now ask
you if you want to physically rename them on disk too (and of course it
will rename them if you say yes).
+ MUTIL now has a full binkley-style echomail importer and exporter with a
bunch of features. It can autocreate new bases, perform unlimited dupe
checking, and store duplicate/badmsgs to name a few.
INSERT NEW SHIT HERE WHEN NOT DRUNK AND LAZY LOL
+ NEW FSE/BSO FTN TOSSER AND BINKP MAILER need to type up the changes + NEW FSE/BSO FTN TOSSER AND BINKP MAILER need to type up the changes
when done when done