home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / MKMSG102.ZIP / MKMSGEZY.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-08-15  |  28.1 KB  |  1,091 lines

  1. Unit MKMsgEZY;       {EZYCom Msg Unit}
  2.  
  3. {$I MKB.Def}
  4.  
  5. Interface
  6.  
  7. Uses MKGlobT, MKMsgAbs,
  8. {$IFDEF WINDOWS}
  9.   Strings, WinDos;
  10. {$ELSE}
  11.   Dos;
  12. {$ENDIF}
  13.  
  14. Const
  15.   MaxEzMsgAreas = 1024;
  16.  
  17. Type EZMsgHdrType = Record
  18.   ReplyTo: Word; {Message is reply to this number}
  19.   SeeAlso: Word; {Message has replies}
  20.   TxtStart: LongInt; {Text start position}
  21.   TxtLen: LongInt; {Length of msg text incl nul term}
  22.   DestAddr: AddrType; {Destination address}
  23.   OrigAddr: AddrType; {Origination address}
  24.   Cost: Word; {Message cost}
  25.   MsgAttr: Byte; {Message attribute - see constants}
  26.   NetAttr: Byte; {Netmail attribute - see constants}
  27.   ExtraAttr: Byte; {Future use}
  28.   Date: LongInt; {Date message was written}
  29.   RcvdDate: LongInt; {Date msg received bye MsgTo}
  30.   MsgTo: String[35]; {Message is intended for}
  31.   MsgFrom: String[35]; {Message was written by}
  32.   Subj: String[72]; {Message subject}
  33.   End;
  34.  
  35.  
  36. Const                                  {MsgHdr.MsgAttr}
  37.   ezDeleted =       1;                 {Message is deleted}
  38.   ezUnmovedNet =    2;                 {Unexported Netmail message}
  39.   ezRsvAttr =       4;
  40.   ezPriv =          8;                 {Message is private}
  41.   ezRcvd =         16;                 {Message is received}
  42.   ezUnmovedEcho =  32;                 {Unexported Echomail message}
  43.   ezLocal =        64;                 {"Locally" entered message}
  44.   ezNoKill =      128;
  45.  
  46.  
  47. Const                                  {MsgHdr.NetAttr}
  48.   ezKillSent =      1;                 {Delete after exporting}
  49.   ezSent =          2;                 {Msg has been sent}
  50.   ezFAttach =       4;                 {Msg has file attached}
  51.   ezCrash =         8;                 {Msg is crash}
  52.   ezFileReq =      16;                 {Msg is a file request}
  53.   ezReqRcpt =      32;                 {Msg is return receipt request}
  54.   ezRetAudit =     64;                 {Msg is a audit request}
  55.   ezRetRcpt =     128;                 {Msg is a return receipt}
  56.  
  57.  
  58. Const
  59.   EzMsgLen = 16000;
  60.  
  61. Type EZMsgType = Record
  62.   MsgHdrFile: File; { MsgH???.BBS }
  63.   MsgTxtFile: File; { MsgT???.BBS }
  64.   MsgTxtWFile: File;
  65.   MsgHdr: EzMsgHdrType;
  66.   TextCtr: LongInt;
  67.   MsgPath: String[128];
  68.   MsgAreaPath: String[128];
  69.   MsgArea: Word;
  70.   Error: Word;
  71.   MsgChars: Array[0..EZMsgLen] of Char;
  72.   MsgDone: Boolean;
  73.   CurrMsg: LongInt;
  74.   SeekOver: Boolean;
  75.   Name: String[35];
  76.   Handle: String[35];
  77.   MailType: MsgMailType;
  78.   Found: Boolean;
  79.   StrDate: String[8];
  80.   StrTime: String[5];
  81.   CRLast: Boolean;
  82.   End;
  83.  
  84.  
  85. Type EzyMsgObj = Object (AbsMsgObj)
  86.   EZM: ^EZMsgType;
  87.   Constructor Init; {Initialize}
  88.   Destructor Done; Virtual; {Done}
  89.   Procedure SetMsgPath(St: String); Virtual; {Set netmail path}
  90.   Function  GetHighMsgNum: LongInt; Virtual; {Get highest netmail msg number in area}
  91.   Procedure SetDest(Var Addr: AddrType); Virtual; {Set Zone/Net/Node/Point for Dest}
  92.   Procedure SetOrig(Var Addr: AddrType); Virtual; {Set Zone/Net/Node/Point for Orig}
  93.   Procedure SetFrom(Name: String); Virtual; {Set message from}
  94.   Procedure SetTo(Name: String); Virtual; {Set message to}
  95.   Procedure SetSubj(Str: String); Virtual; {Set message subject}
  96.   Procedure SetCost(SCost: Word); Virtual; {Set message cost}
  97.   Procedure SetRefer(SRefer: LongInt); Virtual; {Set message reference}
  98.   Procedure SetSeeAlso(SAlso: LongInt); Virtual; {Set message see also}
  99.   Procedure SetDate(SDate: String); Virtual; {Set message date}
  100.   Procedure SetTime(STime: String); Virtual; {Set message time}
  101.   Procedure SetLocal(LS: Boolean); Virtual; {Set local status}
  102.   Procedure SetRcvd(RS: Boolean); Virtual; {Set received status}
  103.   Procedure SetPriv(PS: Boolean); Virtual; {Set priveledge vs public status}
  104.   Procedure SetCrash(SS: Boolean); Virtual; {Set crash netmail status}
  105.   Procedure SetKillSent(SS: Boolean); Virtual; {Set kill/sent netmail status}
  106.   Procedure SetSent(SS: Boolean); Virtual; {Set sent netmail status}
  107.   Procedure SetFAttach(SS: Boolean); Virtual; {Set file attach status}
  108.   Procedure SetReqRct(SS: Boolean); Virtual; {Set request receipt status}
  109.   Procedure SetReqAud(SS: Boolean); Virtual; {Set request audit status}
  110.   Procedure SetRetRct(SS: Boolean); Virtual; {Set return receipt status}
  111.   Procedure SetFileReq(SS: Boolean); Virtual; {Set file request status}
  112.   Procedure SetEcho(ES: Boolean); Virtual; {Set echo status}
  113.   Procedure DoString(Str: String); Virtual; {Add string to message text}
  114.   Procedure DoChar(Ch: Char); Virtual; {Add character to message text}
  115.   Procedure DoStringLn(Str: String); Virtual; {Add string and newline to msg text}
  116.   Function  WriteMsg: Word; Virtual;
  117.   Function  GetChar: Char; Virtual;
  118.   Procedure MsgStartUp; Virtual; {set up msg for reading}
  119.   Function  EOM: Boolean; Virtual; {No more msg text}
  120.   Function  WasWrap: Boolean; Virtual; {Last line was soft wrapped no CR}
  121.   Procedure SeekFirst(MsgNum: LongInt); Virtual; {Seek msg number}
  122.   Procedure SeekNext; Virtual; {Find next matching msg}
  123.   Procedure SeekPrior; Virtual; {Seek prior matching msg}
  124.   Function  GetFrom: String; Virtual; {Get from name on current msg}
  125.   Function  GetTo: String; Virtual; {Get to name on current msg}
  126.   Function  GetSubj: String; Virtual; {Get subject on current msg}
  127.   Function  GetCost: Word; Virtual; {Get cost of current msg}
  128.   Function  GetDate: String; Virtual; {Get date of current msg}
  129.   Function  GetTime: String; Virtual; {Get time of current msg}
  130.   Function  GetRefer: LongInt; Virtual; {Get reply to of current msg}
  131.   Function  GetSeeAlso: LongInt; Virtual; {Get see also of current msg}
  132.   Function  GetMsgNum: LongInt; Virtual; {Get message number}
  133.   Procedure GetOrig(Var Addr: AddrType); Virtual; {Get origin address}
  134.   Procedure GetDest(Var Addr: AddrType); Virtual; {Get destination address}
  135.   Function  IsLocal: Boolean; Virtual; {Is current msg local}
  136.   Function  IsCrash: Boolean; Virtual; {Is current msg crash}
  137.   Function  IsKillSent: Boolean; Virtual; {Is current msg kill sent}
  138.   Function  IsSent: Boolean; Virtual; {Is current msg sent}
  139.   Function  IsFAttach: Boolean; Virtual; {Is current msg file attach}
  140.   Function  IsReqRct: Boolean; Virtual; {Is current msg request receipt}
  141.   Function  IsReqAud: Boolean; Virtual; {Is current msg request audit}
  142.   Function  IsRetRct: Boolean; Virtual; {Is current msg a return receipt}
  143.   Function  IsFileReq: Boolean; Virtual; {Is current msg a file request}
  144.   Function  IsRcvd: Boolean; Virtual; {Is current msg received}
  145.   Function  IsPriv: Boolean; Virtual; {Is current msg priviledged/private}
  146.   Function  IsDeleted: Boolean; Virtual; {Is current msg deleted}
  147.   Function  IsEchoed: Boolean; Virtual; {Msg should be echoed}
  148.   Function  GetMsgLoc: LongInt; Virtual; {Msg location}
  149.   Procedure SetMsgLoc(ML: LongInt); Virtual; {Msg location}
  150.   Procedure YoursFirst(Name: String; Handle: String); Virtual; {Seek your mail}
  151.   Procedure YoursNext; Virtual; {Seek next your mail}
  152.   Function  YoursFound: Boolean; Virtual; {Message found}
  153.   Procedure StartNewMsg; Virtual;
  154.   Function  OpenMsgBase: Word; Virtual;
  155.   Function  CloseMsgBase: Word; Virtual;
  156.   Function  CreateMsgBase(MaxMsg: Word; MaxDays: Word): Word; Virtual;
  157.   Function  SeekFound: Boolean; Virtual;
  158.   Procedure SetMailType(MT: MsgMailType); Virtual; {Set message base type}
  159.   Function  GetSubArea: Word; Virtual; {Get sub area number}
  160.   Procedure ReWriteHdr; Virtual; {Rewrite msg header after changes}
  161.   Procedure DeleteMsg; Virtual; {Delete current message}
  162.   Function  NumberOfMsgs: LongInt; Virtual; {Number of messages}
  163.   Function  GetLastRead(UNum: LongInt): LongInt; Virtual; {Get last read for user num}
  164.   Procedure SetLastRead(UNum: LongInt; LR: LongInt); Virtual; {Set last read}
  165.   Procedure MsgTxtStartUp; Virtual; {Do message text start up tasks}
  166.   Function  GetTxtPos: LongInt; Virtual; {Get indicator of msg text position}
  167.   Procedure SetTxtPos(TP: LongInt); Virtual; {Set text position}
  168.   Procedure SetMsgAttr(Mask: Word; St: Boolean); {Set msgattr}
  169.   Procedure SetNetAttr(Mask: Word; St: Boolean); {Set netattr}
  170.   End;
  171.  
  172.  
  173. Type EzyMsgPtr = ^EzyMsgObj;
  174.  
  175. Var
  176.   EzLastPath: String[128];
  177.   EzLastRecSize: Word;
  178.  
  179.  
  180. Implementation
  181.  
  182.  
  183. Uses MKFile, MKString, MKDos, Crc32;
  184.  
  185.  
  186. Constructor EzyMsgObj.Init;
  187.   Begin
  188.   New(Ezm);
  189.   If Ezm = Nil Then
  190.     Begin
  191.     Fail;
  192.     Exit;
  193.     End;
  194.   EZM^.MsgPath := '';
  195.   Ezm^.MsgAreaPath := '';
  196.   EZM^.MsgArea := 0;
  197.   EZM^.TextCtr := 0;
  198.   EZM^.SeekOver := False;
  199.   Ezm^.Error := 0;
  200.   End;
  201.  
  202.  
  203. Destructor EzyMsgObj.Done;
  204.   Begin
  205.   Dispose(Ezm);
  206.   End;
  207.  
  208.  
  209. Procedure EzyMsgObj.SetMsgPath(St: String);
  210.   Var
  211.     ANum: Word;
  212.  
  213.   Begin
  214.   EZM^.MsgPath := Copy(St, 5, 110);
  215.   AddBackSlash(EZM^.MsgPath);
  216.   EZM^.MsgArea := Str2Long(Copy(St,1,4));
  217.   ANum := ((EZM^.MsgArea - 1) Div 100) + 1;
  218.   Ezm^.MsgAreaPath := Ezm^.Msgpath + 'AREA' + Long2Str(ANum) +'\';
  219.   End;
  220.  
  221.  
  222. Function EzyMsgObj.GetHighMsgNum: LongInt;
  223.   Var
  224.     ANum: Word;
  225.  
  226.   Begin
  227.   GetHighMsgNum := SizeFile(Ezm^.MsgAreaPath + 'MsgH' +
  228.     PadLeft(Long2Str(Ezm^.MsgArea),'0',3) + '.BBS') Div SizeOf(EzMsgHdrType);
  229.   End;
  230.  
  231.  
  232. Procedure EzyMsgObj.SetDest(Var Addr: AddrType);
  233.   Begin
  234.   EZM^.MsgHdr.DestAddr := Addr;
  235.   End;
  236.  
  237.  
  238. Procedure EzyMsgObj.SetOrig(Var Addr: AddrType);
  239.   Begin
  240.   EZM^.MsgHdr.OrigAddr := Addr;
  241.   End;
  242.  
  243.  
  244. Procedure EzyMsgObj.SetFrom(Name: String);
  245.   Begin
  246.   EZM^.MsgHdr.MsgFrom := Name;
  247.   End;
  248.  
  249.  
  250. Procedure EzyMsgObj.SetTo(Name: String);
  251.   Begin
  252.   Ezm^.MsgHdr.MsgTo := Name;
  253.   End;
  254.  
  255.  
  256. Procedure EzyMsgObj.SetSubj(Str: String);
  257.   Begin
  258.   Ezm^.MsgHdr.Subj := Str;
  259.   End;
  260.  
  261.  
  262. Procedure EzyMsgObj.SetCost(SCost: Word);
  263.   Begin
  264.   Ezm^.MsgHdr.Cost := SCost;
  265.   End;
  266.  
  267.  
  268. Procedure EzyMsgObj.SetRefer(SRefer: LongInt);
  269.   Begin
  270.   Ezm^.MsgHdr.ReplyTo := SRefer and $ffff;
  271.   End;
  272.  
  273.  
  274. Procedure EzyMsgObj.SetSeeAlso(SAlso: LongInt);
  275.   Begin
  276.   Ezm^.MsgHdr.SeeAlso := SAlso and $ffff;
  277.   End;
  278.  
  279.  
  280. Procedure EzyMsgObj.SetDate(SDate: String);
  281.   Begin
  282.   Ezm^.StrDate := SDate;
  283.   End;
  284.  
  285.  
  286. Procedure EzyMsgObj.SetTime(STime: String);
  287.   Begin
  288.   Ezm^.StrTime := STime;
  289.   End;
  290.  
  291.  
  292. Procedure EzyMsgObj.SetMsgAttr(Mask: Word; St: Boolean); {Set msgattr}
  293.   Begin
  294.   If St Then
  295.     Ezm^.MsgHdr.MsgAttr := Ezm^.MsgHdr.MsgAttr or Mask
  296.   Else
  297.     Ezm^.MsgHdr.MsgAttr := Ezm^.MsgHdr.MsgAttr and (Not Mask);
  298.   End;
  299.  
  300.  
  301. Procedure EzyMsgObj.SetNetAttr(Mask: Word; St: Boolean); {Set netattr}
  302.   Begin
  303.   If St Then
  304.     Ezm^.MsgHdr.NetAttr := Ezm^.MsgHdr.NetAttr or Mask
  305.   Else
  306.     Ezm^.MsgHdr.NetAttr := Ezm^.MsgHdr.NetAttr and (not Mask);
  307.   End;
  308.  
  309.  
  310. Procedure EzyMsgObj.SetLocal(LS: Boolean);
  311.   Begin
  312.   SetMsgAttr(ezLocal, LS);
  313.   End;
  314.  
  315.  
  316. Procedure EzyMsgObj.SetRcvd(RS: Boolean);
  317.   Begin
  318.   SetMsgAttr(ezRcvd, RS);
  319.   End;
  320.  
  321.  
  322. Procedure EzyMsgObj.SetPriv(PS: Boolean);
  323.   Begin
  324.   SetMsgAttr(ezPriv, PS);
  325.   End;
  326.  
  327.  
  328. Procedure EzyMsgObj.SetCrash(SS: Boolean);
  329.   Begin
  330.   SetNetAttr(ezCrash, SS);
  331.   End;
  332.  
  333.  
  334. Procedure EzyMsgObj.SetKillSent(SS: Boolean);
  335.   Begin
  336.   SetNetAttr(ezKillSent, SS);
  337.   End;
  338.  
  339.  
  340. Procedure EzyMsgObj.SetSent(SS: Boolean);
  341.   Begin
  342.   SetNetAttr(ezSent, SS);
  343.   End;
  344.  
  345.  
  346. Procedure EzyMsgObj.SetFAttach(SS: Boolean);
  347.   Begin
  348.   SetNetAttr(ezFAttach, SS);
  349.   End;
  350.  
  351.  
  352. Procedure EzyMsgObj.SetReqRct(SS: Boolean);
  353.   Begin
  354.   SetNetAttr(ezReqRcpt, SS);
  355.   End;
  356.  
  357.  
  358. Procedure EzyMsgObj.SetReqAud(SS: Boolean);
  359.   Begin
  360.   End;
  361.  
  362.  
  363. Procedure EzyMsgObj.SetRetRct(SS: Boolean);
  364.   Begin
  365.   SetNetAttr(ezRetRcpt, SS);
  366.   End;
  367.  
  368.  
  369. Procedure EzyMsgObj.SetFileReq(SS: Boolean);
  370.   Begin
  371.   SetNetAttr(ezFileReq, SS);
  372.   End;
  373.  
  374.  
  375. Procedure EzyMsgObj.DoString(Str: String);
  376.   Var
  377.     i: Word;
  378.  
  379.   Begin
  380.   i := 1;
  381.   While i <= Length(Str) Do
  382.     Begin
  383.     DoChar(Str[i]);
  384.     Inc(i);
  385.     End;
  386.   End;
  387.  
  388.  
  389. Procedure EzyMsgObj.DoChar(Ch: Char);
  390.   Begin
  391.   If EZM^.TextCtr < SizeOf(EZM^.MsgChars) Then
  392.     Begin
  393.     Case(Ch) of
  394.       #13: Ezm^.CRLast := True;
  395.       #10:;
  396.       Else
  397.         Ezm^.CRLast := False;
  398.       End;
  399.     EZM^.MsgChars[EZM^.TextCtr] := Ch;
  400.     Inc(EZM^.TextCtr);
  401.     End;
  402.   End;
  403.  
  404.  
  405. Procedure EzyMsgObj.DoStringLn(Str: String);
  406.   Begin
  407.   DoString(Str);
  408.   DoChar(#13);
  409.   End;
  410.  
  411.  
  412. Function  EzyMsgObj.WriteMsg: Word;
  413.  
  414.   Type MsgFastAccessType = Record
  415.     CrcTo: LongInt;
  416.     Area: Word;
  417.     MsgNum: Word;
  418.     End;
  419.  
  420.   Var
  421.     {$IFDEF WINDOWS}
  422.     TmpDT: TDateTime;
  423.     {$ELSE}
  424.     TmpDT: DateTime;
  425.     {$ENDIF}
  426.     MsgFast: MsgFastAccessType; {MsgPath\MsgFast.Bbs}
  427.     MsgFastFile: File;
  428.     MsgExport: Boolean;
  429.     MsgExportFile: File;
  430.     MsgCount: Word;
  431.     MsgCountFile: File;
  432.     i: Word;
  433.     NumRead: Word;
  434.  
  435.   Begin
  436.   If Not Ezm^.CRLast Then
  437.     DoChar(#13);
  438.   DoChar(#0);
  439.   TmpDT.Year := Str2Long(Copy(Ezm^.StrDate,7,2));
  440.   If TmpDT.Year > 79 Then
  441.     Inc(TmpDT.Year, 1900)
  442.   Else
  443.     Inc(TmpDT.Year, 2000);
  444.   TmpDT.Month := Str2Long(Copy(Ezm^.StrDate,1,2));
  445.   TmpDT.Day := Str2Long(Copy(Ezm^.StrDate,4,2));
  446.   TmpDt.Hour := Str2Long(Copy(Ezm^.StrTime,1,2));
  447.   TmpDt.Min := Str2Long(Copy(Ezm^.StrTime, 4,2));
  448.   TmpDt.Sec := 0;
  449.   PackTime(TmpDT, Ezm^.MsgHdr.Date);
  450.   Ezm^.MsgHdr.RcvdDate := Ezm^.MsgHdr.Date;
  451.   FileMode := fmReadWrite + fmDenyWrite;
  452.   If shReset(Ezm^.MsgTxtWFile, 1) Then
  453.     Begin
  454.     Ezm^.MsgHdr.TxtStart := FileSize(Ezm^.MsgTxtWFile);
  455.     Seek(Ezm^.MsgTxtWFile, Ezm^.MsgHdr.TxtStart);
  456.     Ezm^.Error := IoResult;
  457.     Ezm^.MsgHdr.TxtLen := Ezm^.TextCtr;
  458.     If Ezm^.Error = 0 Then
  459.       Begin
  460.       BlockWrite(Ezm^.MsgTxtWFile, Ezm^.MsgChars, Ezm^.TextCtr);
  461.       Ezm^.Error := IoResult;
  462.       End;
  463.     If Ezm^.Error = 0 Then
  464.       Begin
  465.       Seek(Ezm^.MsgHdrFile, FileSize(Ezm^.MsgHdrFile));
  466.       Ezm^.Error := IoResult;
  467.       End;
  468.     If Ezm^.Error = 0 Then
  469.       Begin
  470.       BlockWrite(Ezm^.MsgHdrFile, Ezm^.MsgHdr, 1);
  471.       Ezm^.Error := IoResult;
  472.       Ezm^.CurrMsg := FileSize(Ezm^.MsgHdrFile);
  473.       End;
  474.     If ((Ezm^.Error = 0) and (Not IsRcvd)) Then
  475.       Begin
  476.       MsgFast.CrcTo := $ffffffff;
  477.       For i := 1 to Length(Ezm^.MsgHdr.MsgTo) Do
  478.         MsgFast.CrcTo := UpDC32(Ord(UpCase(Ezm^.MsgHdr.MsgTo[i])), MsgFast.CrcTo);
  479.       MsgFast.Area := Ezm^.MsgArea;
  480.       MsgFast.MsgNum := Ezm^.CurrMsg;
  481.       Assign(MsgFastFile, Ezm^.MsgPath + 'MsgFast.Bbs');
  482.       FileMode := fmReadWrite + fmDenyNone;
  483.       If shReset(MsgFastFile, SizeOf(MsgFastAccessType)) Then
  484.         Begin
  485.         Seek(MsgFastFile, FileSize(MsgFastFile));
  486.         If IoResult <> 0 Then;
  487.         BlockWrite(MsgFastFile, MsgFast, 1);
  488.         If IoResult <> 0 Then;
  489.         Close(MsgFastFile);
  490.         If IoResult <> 0 Then;
  491.         End;
  492.       End;
  493.     If ((Ezm^.Error = 0) and (IsEchoed)) Then
  494.       Begin
  495.       Assign(MsgExportFile, Ezm^.MsgPath + 'MsgExprt.Bbs');
  496.       FileMode := fmReadWrite + fmDenyNone;
  497.       If shReset(MsgExportFile, SizeOf(MsgExport)) Then
  498.         Begin
  499.         MsgExport := True;
  500.         Seek(MsgExportFile, Ezm^.MsgArea - 1);
  501.         If IoResult <> 0 Then;
  502.         BlockWrite(MsgExportFile, MsgExport, 1);
  503.         If IoResult <> 0 Then;
  504.         Close(MsgExportFile);
  505.         If IoResult <> 0 Then;
  506.         End;
  507.       End;
  508.     If Ezm^.Error = 0 Then
  509.       Begin
  510.       Assign(MsgCountFile, Ezm^.MsgPath + 'MsgCount.Bbs');
  511.       MsgCount := 0;
  512.       If shReset(MsgCountFile, SizeOf(MsgCount)) Then
  513.         Begin
  514.         Seek(MsgCountFile, Ezm^.MsgArea - 1);
  515.         If IoResult <> 0 Then;
  516.         BlockRead(MsgCountFile, MsgCount, 1, NumRead);
  517.         If IoResult <> 0 Then;
  518.         Inc(MsgCount);
  519.         Seek(MsgCountFile, Ezm^.MsgArea - 1);
  520.         If IoResult <> 0 Then;
  521.         BlockWrite(MsgCountFile, MsgCount, 1);
  522.         If IoResult <> 0 Then;
  523.         End;
  524.       End;
  525.     If Ezm^.Error = 0 Then
  526.       Begin
  527.       Close(Ezm^.MsgTxtWFile);
  528.       Ezm^.Error := IoResult;
  529.       End;
  530.     End
  531.   Else
  532.     Ezm^.Error := 5;
  533.   End;
  534.  
  535.  
  536. Function EzyMsgObj.GetChar: Char;
  537.   Begin
  538.   If ((EZM^.TextCtr >= EZM^.MsgHdr.TxtLen) Or (EZM^.MsgChars[EZM^.TextCtr] = #0)
  539.   Or(Ezm^.TextCtr >= EzMsgLen)) Then
  540.     Begin
  541.     GetChar := #0;
  542.     EZM^.MsgDone := True;
  543.     End
  544.   Else
  545.     Begin
  546.     GetChar := EZM^.MsgChars[EZM^.TextCtr];
  547.     Inc(EZM^.TextCtr);
  548.     End;
  549.   End;
  550.  
  551.  
  552. Procedure EzyMsgObj.MsgStartUp;
  553.   Var
  554.     NumRead: Word;
  555.  
  556.   Begin
  557.   If (Ezm^.CurrMsg > 0) and (Ezm^.CurrMsg <= FileSize(Ezm^.MsgHdrFile)) Then
  558.     Begin
  559.     LastSoft := False;
  560.     Ezm^.MsgDone := False;
  561.     Seek(Ezm^.MsgHdrFile, Ezm^.CurrMsg - 1);
  562.     Ezm^.Error := IoResult;
  563.     If Ezm^.Error = 0 Then
  564.       Begin
  565.       BlockRead(Ezm^.MsgHdrFile, Ezm^.MsgHdr, 1, NumRead);
  566.       Ezm^.Error := IoResult;
  567.       End;
  568.     End;
  569.   End;
  570.  
  571.  
  572. Procedure EzyMsgObj.MsgTxtStartUp;
  573.   Var
  574.     NumRead: Word;
  575.  
  576.   Begin
  577.   If ((Ezm^.MsgHdr.TxtStart >= 0) and (Ezm^.MsgHdr.TxtStart <=
  578.   FileSize(Ezm^.MsgTxtFile))) Then
  579.     Begin
  580.     Ezm^.Error := 0;
  581.     EZM^.TextCtr := 0;
  582.     EZM^.MsgDone := False;
  583.     FillChar(Ezm^.MsgChars, SizeOf(Ezm^.MsgChars), #0);
  584.     Seek(Ezm^.MsgTxtFile, Ezm^.Msghdr.TxtStart);
  585.     Ezm^.Error := IoResult;
  586.     If Ezm^.Error = 0 Then
  587.       Begin
  588.        If Ezm^.MsgHdr.TxtLen > EzMsgLen Then
  589.         BlockRead(Ezm^.MsgTxtFile, Ezm^.MsgChars, Ezm^.MsgHdr.TxtLen, NumRead)
  590.       Else
  591.         BlockRead(Ezm^.MsgTxtFile, Ezm^.MsgChars, EzMsgLen, NumRead);
  592.       Ezm^.Error := IoResult;
  593.       End;
  594.     LastSoft := False;
  595.     End
  596.   Else
  597.     Begin
  598.     Ezm^.Error := 400;
  599.     End;
  600.   End;
  601.  
  602.  
  603. Function EzyMsgObj.EOM: Boolean;
  604.   Begin
  605.   EOM := EZM^.MsgDone;
  606.   End;
  607.  
  608.  
  609. Function EzyMsgObj.WasWrap: Boolean;
  610.   Begin
  611.   WasWrap := LastSoft;
  612.   End;
  613.  
  614.  
  615. Function EzyMsgObj.GetFrom: String; {Get from name on current msg}
  616.   Begin
  617.   GetFrom := Ezm^.MsgHdr.MsgFrom;
  618.   End;
  619.  
  620.  
  621. Function EzyMsgObj.GetTo: String; {Get to name on current msg}
  622.   Begin
  623.   GetTo := Ezm^.MsgHdr.MsgTo;
  624.   End;
  625.  
  626.  
  627. Function EzyMsgObj.GetSubj: String; {Get subject on current msg}
  628.   Begin
  629.   GetSubj := Ezm^.MsgHdr.Subj;
  630.   End;
  631.  
  632.  
  633. Function EzyMsgObj.GetCost: Word; {Get cost of current msg}
  634.   Begin
  635.   GetCost := Ezm^.MsgHdr.Cost;
  636.   End;
  637.  
  638.  
  639. Function EzyMsgObj.GetDate: String; {Get date of current msg}
  640.   Begin
  641.   GetDate := DateStr(Ezm^.MsgHdr.Date);
  642.   End;
  643.  
  644.  
  645. Function EzyMsgObj.GetTime: String; {Get time of current msg}
  646.   Begin
  647.   GetTime := Copy(TimeStr(Ezm^.MsgHdr.Date),1, 5);
  648.   End;
  649.  
  650.  
  651. Function EzyMsgObj.GetRefer: LongInt; {Get reply to of current msg}
  652.   Begin
  653.   GetRefer := Ezm^.MsgHdr.ReplyTo;
  654.   End;
  655.  
  656.  
  657. Function EzyMsgObj.GetSeeAlso: LongInt; {Get see also of current msg}
  658.   Begin
  659.   GetSeeAlso := Ezm^.MsgHdr.SeeAlso;
  660.   End;
  661.  
  662.  
  663. Function EzyMsgObj.GetMsgNum: LongInt; {Get message number}
  664.   Begin
  665.   GetMsgNum := EZM^.CurrMsg;
  666.   End;
  667.  
  668.  
  669. Procedure EzyMsgObj.GetOrig(Var Addr: AddrType); {Get origin address}
  670.   Begin
  671.   Addr := EZM^.MsgHdr.OrigAddr;
  672.   End;
  673.  
  674.  
  675. Procedure EzyMsgObj.GetDest(Var Addr: AddrType); {Get destination address}
  676.   Begin
  677.   Addr := EZM^.MsgHdr.DestAddr;
  678.   End;
  679.  
  680.  
  681. Function EzyMsgObj.IsLocal: Boolean; {Is current msg local}
  682.   Begin
  683.   IsLocal := (Ezm^.MsgHdr.MsgAttr and ezLocal) <> 0;
  684.   End;
  685.  
  686.  
  687. Function EzyMsgObj.IsCrash: Boolean; {Is current msg crash}
  688.   Begin
  689.   IsCrash := (Ezm^.MsgHdr.NetAttr and ezCrash) <> 0;
  690.   End;
  691.  
  692.  
  693. Function EzyMsgObj.IsKillSent: Boolean; {Is current msg kill sent}
  694.   Begin
  695.   IsKillSent := (Ezm^.MsgHdr.NetAttr and ezKillSent) <> 0;
  696.   End;
  697.  
  698.  
  699. Function EzyMsgObj.IsSent: Boolean; {Is current msg sent}
  700.   Begin
  701.   IsSent := (Ezm^.MsgHdr.NetAttr and ezSent) <> 0;
  702.   End;
  703.  
  704.  
  705. Function EzyMsgObj.IsFAttach: Boolean; {Is current msg file attach}
  706.   Begin
  707.   IsFAttach := (Ezm^.MsgHdr.NetAttr and ezFAttach) <> 0;
  708.   End;
  709.  
  710.  
  711. Function EzyMsgObj.IsReqRct: Boolean; {Is current msg request receipt}
  712.   Begin
  713.   IsReqRct := (Ezm^.MsgHdr.NetAttr and ezReqRcpt) <> 0;
  714.   End;
  715.  
  716.  
  717. Function EzyMsgObj.IsReqAud: Boolean; {Is current msg request audit}
  718.   Begin
  719.   IsReqAud := False;
  720.   End;
  721.  
  722.  
  723. Function EzyMsgObj.IsRetRct: Boolean; {Is current msg a return receipt}
  724.   Begin
  725.   IsRetRct := (Ezm^.MsgHdr.NetAttr and ezRetRcpt) <> 0;
  726.   End;
  727.  
  728.  
  729. Function EzyMsgObj.IsFileReq: Boolean; {Is current msg a file request}
  730.   Begin
  731.   IsFileReq := (Ezm^.MsgHdr.NetAttr and ezFileReq) <> 0;
  732.   End;
  733.  
  734.  
  735. Function EzyMsgObj.IsRcvd: Boolean; {Is current msg received}
  736.   Begin
  737.   IsRcvd := (Ezm^.MsgHdr.MsgAttr and ezRcvd) <> 0;
  738.   End;
  739.  
  740.  
  741. Function EzyMsgObj.IsPriv: Boolean; {Is current msg priviledged/private}
  742.   Begin
  743.   IsPriv := (Ezm^.MsgHdr.MsgAttr and ezPriv) <> 0;
  744.   End;
  745.  
  746.  
  747. Function EzyMsgObj.IsDeleted: Boolean; {Is current msg deleted}
  748.   Begin
  749.   IsDeleted := (Ezm^.MsgHdr.MsgAttr and ezDeleted) <> 0;
  750.   End;
  751.  
  752.  
  753. Function EzyMsgObj.IsEchoed: Boolean; {Is current msg echoed}
  754.   Begin
  755.   Case EZM^.MailType of
  756.     mmtNormal: IsEchoed := False;
  757.     mmtNetMail: IsEchoed := (EZM^.MsgHdr.MsgAttr and ezUnMovedNet) <> 0;
  758.     mmtEchoMail: IsEchoed := (EZM^.MsgHdr.MsgAttr and ezUnMovedEcho) <> 0;
  759.     Else
  760.       IsEchoed := False;
  761.     End;
  762.   End;
  763.  
  764.  
  765. Procedure EzyMsgObj.SetEcho(ES: Boolean);
  766.   Begin
  767.   Case Ezm^.MailType of
  768.     mmtNetMail:
  769.       Begin
  770.       If ES Then
  771.         Ezm^.MsgHdr.MsgAttr := Ezm^.MsgHdr.MsgAttr or ezUnMovedNet
  772.       Else
  773.         Ezm^.MsgHdr.MsgAttr := Ezm^.MsgHdr.MsgAttr and (Not ezUnMovedNet);
  774.       End;
  775.     mmtEchoMail:
  776.       Begin
  777.       If ES Then
  778.         Ezm^.MsgHdr.MsgAttr := Ezm^.MsgHdr.MsgAttr or ezUnMovedEcho
  779.       Else
  780.         Ezm^.MsgHdr.MsgAttr := Ezm^.MsgHdr.MsgAttr and (Not ezUnMovedEcho);
  781.       End;
  782.     End;
  783.   End;
  784.  
  785.  
  786. Procedure EzyMsgObj.SeekFirst(MsgNum: LongInt); {Start msg seek}
  787.   Begin
  788.   EZM^.CurrMsg := MsgNum - 1;
  789.   SeekNext;
  790.   End;
  791.  
  792.  
  793. Procedure EzyMsgObj.SeekNext; {Find next matching msg}
  794.   Begin
  795.   Ezm^.Found := True;
  796.   If Ezm^.CurrMsg < FileSize(Ezm^.MsgHdrFile) Then
  797.     Inc(Ezm^.CurrMsg)
  798.   Else
  799.     Ezm^.Found := False;
  800.   End;
  801.  
  802.  
  803. Procedure EzyMsgObj.SeekPrior;
  804.   Begin
  805.   If Ezm^.CurrMsg > 0 Then
  806.     Begin
  807.     Dec(Ezm^.CurrMsg);
  808.     End;
  809.   If Ezm^.CurrMsg <= 0 Then
  810.     Ezm^.Found := False;
  811.   End;
  812.  
  813.  
  814. Function EzyMsgObj.SeekFound: Boolean;
  815.   Begin
  816.   SeekFound := EZM^.Found;
  817.   End;
  818.  
  819.  
  820. Function EzyMsgObj.GetMsgLoc: LongInt; {Msg location}
  821.   Begin
  822.   GetMsgLoc := GetMsgNum;
  823.   End;
  824.  
  825.  
  826. Procedure EzyMsgObj.SetMsgLoc(ML: LongInt); {Msg location}
  827.   Begin
  828.   EZM^.CurrMsg := ML;
  829.   End;
  830.  
  831.  
  832. Procedure EzyMsgObj.YoursFirst(Name: String; Handle: String);
  833.   Begin
  834.   EZM^.Name := Upper(Name);
  835.   EZM^.Handle := Upper(Handle);
  836.   EZM^.CurrMsg := 0;
  837.   YoursNext;
  838.   End;
  839.  
  840.  
  841. Procedure EzyMsgObj.YoursNext;
  842.   Var
  843.     FoundDone: Boolean;
  844.     MaxSize: LongInt;
  845.  
  846.   Begin
  847.   FoundDone := False;
  848.   MaxSize := GetHighMsgNum;
  849.   Inc(EZM^.CurrMsg);
  850.   SeekFirst(EZM^.CurrMsg);
  851.   While ((Ezm^.CurrMsg <= MaxSize) And (Not FoundDone)) Do
  852.     Begin
  853.     MsgStartUp;
  854.     If ((Upper(GetTo) = Ezm^.Name) Or (Upper(GetTo) = Ezm^.Handle)) Then
  855.       FoundDone := True;
  856.     If IsRcvd Then FoundDone := False;
  857.     If Not FoundDone Then
  858.       SeekNext;
  859.     If Not SeekFound Then
  860.       FoundDone := True;
  861.     End;
  862.   End;
  863.  
  864.  
  865. Function EzyMsgObj.YoursFound: Boolean;
  866.   Begin
  867.   YoursFound := SeekFound;
  868.   End;
  869.  
  870.  
  871. Procedure EzyMsgObj.StartNewMsg;
  872.   Begin
  873.   FillChar(EZM^.MsgChars, SizeOf(EZM^.MsgChars), #0);
  874.   FillChar(Ezm^.MsgHdr, SizeOf(Ezm^.MsgHdr), 0);
  875.   EZM^.TextCtr := 0;
  876.   End;
  877.  
  878.  
  879. Function EzyMsgObj.OpenMsgBase: Word;
  880.   Begin
  881.   Ezm^.Error := 0;
  882.   If Not FileExist(Ezm^.MsgAreaPath + 'MsgH' +
  883.   PadLeft(Long2Str(Ezm^.MsgArea),'0',3) + '.BBS') Then
  884.     CreateMsgBase(0,0);
  885.   Assign(Ezm^.MsgHdrFile, Ezm^.MsgAreaPath + 'MsgH' +
  886.     PadLeft(Long2Str(Ezm^.MsgArea),'0',3) + '.BBS');
  887.   Assign(Ezm^.MsgTxtFile, Ezm^.MsgAreaPath + 'MsgT' +
  888.     PadLeft(Long2Str(Ezm^.MsgArea),'0',3) + '.BBS');
  889.   Assign(Ezm^.MsgTxtWFile, Ezm^.MsgAreaPath + 'MsgT' +
  890.     PadLeft(Long2Str(Ezm^.MsgArea),'0',3) + '.BBS');
  891.   FileMode := fmReadWrite + fmDenyNone;
  892.   Reset(Ezm^.MsgHdrFile, SizeOf(Ezm^.MsgHdr));
  893.   Ezm^.Error := IoResult;
  894.   If Ezm^.Error = 0 Then
  895.     Begin
  896.     FileMode := fmReadOnly + fmDenyNone;
  897.     Reset(Ezm^.MsgTxtFile, 1);
  898.     Ezm^.Error := IoResult;
  899.     End;
  900.   If Ezm^.Error <> 0 Then
  901.     Begin
  902.     Close(Ezm^.MsgTxtFile);
  903.     If IoResult <> 0 Then;
  904.     Close(Ezm^.MsgHdrFile);
  905.     If IoResult <> 0 Then;
  906.     End;
  907.   OpenMsgBase := Ezm^.Error;
  908.   End;
  909.  
  910.  
  911. Function EzyMsgObj.CloseMsgBase: Word;
  912.   Begin
  913.   If IoResult <> 0 Then;
  914.   Close(Ezm^.MsgHdrFile);
  915.   If IoResult <> 0 Then;
  916.   Close(Ezm^.MsgTxtFile);
  917.   If IoResult <> 0 Then;
  918.   Close(Ezm^.MsgTxtWFile);
  919.   If IoResult <> 0 Then;
  920.   End;
  921.  
  922.  
  923. Function EzyMsgObj.CreateMsgBase(MaxMsg: Word; MaxDays: Word): Word;
  924.   Type MsgExportType = Array[1..MaxEzMsgAreas] of Boolean;
  925.   Type MsgCountType = Array[1..MaxEzMsgAreas] of Word;
  926.  
  927.   Var
  928.     HdrFile: File;
  929.     TxtFile: File;
  930.     TempFile: File;
  931.     MsgExport: MsgExportType;
  932.     MsgCount: MsgCountType;
  933.  
  934.   Begin
  935.   Assign(HdrFile, Ezm^.MsgAreaPath + 'MsgH' +
  936.     PadLeft(Long2Str(Ezm^.MsgArea),'0',3) + '.BBS');
  937.   Assign(TxtFile, Ezm^.MsgAreaPath + 'MsgT' +
  938.     PadLeft(Long2Str(Ezm^.MsgArea),'0',3) + '.BBS');
  939.   ReWrite(HdrFile);
  940.   Ezm^.Error := IoResult;
  941.   If Ezm^.Error = 0 Then
  942.     Begin
  943.     ReWrite(TxtFile);
  944.     Ezm^.Error := IoResult;
  945.     End;
  946.   Close(HdrFile);
  947.   If IoResult <> 0 Then;
  948.   Close(TxtFile);
  949.   If IoResult <> 0 Then;
  950.   If Not FileExist(Ezm^.MsgPath + 'MsgFast.Bbs') Then
  951.     Begin
  952.     Assign(TempFile, Ezm^.MsgPath + 'Msgfast.Bbs');
  953.     ReWrite(TempFile);
  954.     If IoResult <> 0 Then;
  955.     Close(TempFile);
  956.     If IoResult <> 0 Then;
  957.     End;
  958.   If Not FileExist(Ezm^.MsgPath + 'MsgExprt.Bbs') Then
  959.     Begin
  960.     FillChar(MsgExport, SizeOf(MsgExport), #0);
  961.     Assign(TempFile, Ezm^.Msgpath + 'MsgExprt.Bbs');
  962.     ReWrite(TempFile, SizeOf(MsgExport));
  963.     If IoResult <> 0 Then;
  964.     BlockWrite(TempFile, MsgExport, 1);
  965.     If IoResult <> 0 Then;
  966.     Close(TempFile);
  967.     If IoResult <> 0 Then;
  968.     End;
  969.   If Not FileExist(Ezm^.MsgPath + 'MsgCount.Bbs') Then
  970.     Begin
  971.     FillChar(MsgCount, SizeOf(MsgCount), #0);
  972.     Assign(TempFile, Ezm^.MsgPath + 'MsgCount.Bbs');
  973.     ReWrite(TempFile, SizeOf(MsgCount));
  974.     If IoResult <> 0 Then;
  975.     BlockWrite(TempFile, MsgCount, 1);
  976.     If IoResult <> 0 Then;
  977.     Close(TempFile);
  978.     If IoResult <> 0 Then;
  979.     End;
  980.   CreateMsgBase := Ezm^.Error;
  981.   End;
  982.  
  983.  
  984. Procedure EzyMsgObj.SetMailType(MT: MsgMailType);
  985.   Begin
  986.   Ezm^.MailType := MT;
  987.   End;
  988.  
  989.  
  990. Function EzyMsgObj.GetSubArea: Word;
  991.   Begin
  992.   GetSubArea := Ezm^.MsgArea;
  993.   End;
  994.  
  995.  
  996. Procedure EzyMsgObj.ReWriteHdr;
  997.   Begin
  998.   If ((Ezm^.CurrMsg > 0) and (Ezm^.CurrMsg <= FileSize(Ezm^.MsgHdrFile))) Then
  999.     Begin
  1000.     Seek(Ezm^.MsgHdrFile, Ezm^.CurrMsg - 1);
  1001.     Ezm^.Error := IoResult;
  1002.     If Ezm^.Error = 0 Then
  1003.       Begin
  1004.       BlockWrite(Ezm^.MsgHdrFile, Ezm^.MsgHdr, 1);
  1005.       Ezm^.Error := IoResult;
  1006.       End;
  1007.     End;
  1008.   End;
  1009.  
  1010.  
  1011. Procedure EzyMsgObj.DeleteMsg;
  1012.   Begin
  1013.   SetMsgAttr(ezDeleted, True);
  1014.   ReWriteHdr;
  1015.   End;
  1016.  
  1017.  
  1018. Function EzyMsgObj.NumberOfMsgs: LongInt;
  1019.   Begin
  1020.   NumberOfMsgs := FileSize(Ezm^.MsgHdrFile);
  1021.   End;
  1022.  
  1023.  
  1024.  
  1025. Function EzyMsgObj.GetLastRead(UNum: LongInt): LongInt;
  1026.   Var
  1027.     Count: LongInt;
  1028.     LFile: File;
  1029.     LR: Word;
  1030.     Position: LongInt;
  1031.  
  1032.   Begin
  1033.   LR := 0;
  1034.   Count := ((Ezm^.MsgArea - 1) Div 16) + 1; {number of combined info to skip}
  1035.   Inc(Count, (Ezm^.MsgArea - 1));  { point to current area}
  1036.   AddBackSlash(EzLastPath);
  1037.   Assign(LFile, EzLastPath + 'LastComb.Bbs');
  1038.   FileMode := fmReadOnly + fmDenyNone;
  1039.   Reset(LFile, 1);
  1040.   If IoResult <> 0 Then;
  1041.   Position := (UNum * EzLastRecSize) + (Count * 2);
  1042.   Seek(LFile, Position);
  1043.   If IoResult <> 0 Then;
  1044.   BlockRead(LFile, LR, 2);
  1045.   If IoResult <> 0 Then;
  1046.   Close(LFile);
  1047.   If IoResult <> 0 Then;
  1048.   GetLastRead := LR - 1;
  1049.   End;
  1050.  
  1051.  
  1052. Procedure EzyMsgObj.SetLastRead(UNum: LongInt; LR: LongInt);
  1053.   Var
  1054.     Count: LongInt;
  1055.     LFile: File;
  1056.     Position: LongInt;
  1057.     Tmp: Word;
  1058.  
  1059.   Begin
  1060.   Count := ((Ezm^.MsgArea - 1) Div 16) + 1; {number of combined info to skip}
  1061.   Inc(Count, (Ezm^.MsgArea - 1));  { point to current area}
  1062.   AddBackSlash(EzLastPath);
  1063.   Assign(LFile, EzLastPath + 'LastComb.Bbs');
  1064.   FileMode := fmReadWrite + fmDenyNone;
  1065.   Reset(LFile, 1);
  1066.   If IoResult <> 0 Then;
  1067.   Position := (UNum * EzLastRecSize) + (Count * 2);
  1068.   Seek(LFile, Position);
  1069.   If IoResult <> 0 Then;
  1070.   Tmp := LR + 1;
  1071.   BlockWrite(LFile, Tmp, 2);
  1072.   If IoResult <> 0 Then;
  1073.   Close(LFile);
  1074.   If IoResult <> 0 Then;
  1075.   End;
  1076.  
  1077.  
  1078. Function EzyMsgObj.GetTxtPos: LongInt;
  1079.   Begin
  1080.   GetTxtPos := EZM^.TextCtr;
  1081.   End;
  1082.  
  1083.  
  1084. Procedure EzyMsgObj.SetTxtPos(TP: LongInt);
  1085.   Begin
  1086.   EZM^.TextCtr := TP;
  1087.   End;
  1088.  
  1089.  
  1090. End.
  1091.