home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mksmvp10.zip / MKMSGEZY.PAS < prev    next >
Pascal/Delphi Source File  |  1997-09-27  |  29KB  |  1,111 lines

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