home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / PASCAL / MKMSG104 / MKMSGFID.PAS < prev    next >
Pascal/Delphi Source File  |  1994-01-09  |  36KB  |  1,463 lines

  1. Unit MKMsgFid;       {Fido *.Msg Unit}
  2.  
  3. {$I MKB.Def}
  4.  
  5. {
  6.      MKMsgFid - Copyright 1993 by Mark May - MK Software
  7.      You are free to use this code in your programs, however
  8.      it may not be included in Source/TPU function libraries
  9.      without my permission.
  10.  
  11.      Mythical Kingom Tech BBS (513)237-7737 HST/v32
  12.      FidoNet: 1:110/290
  13.      Rime: ->MYTHKING
  14.      You may also reach me at maym@dmapub.dma.org
  15. }
  16.  
  17.  
  18. {
  19.      Now handles message size only limited by disk space and
  20.      the maximum size of a longint, while using only a small
  21.      buffer for low memory usage with reasonable speed
  22. }
  23.  
  24. Interface
  25.  
  26. Uses MKGlobT, MKMsgAbs, MKFFile,
  27. {$IFDEF WINDOWS}
  28.   Strings, WinDos;
  29. {$ELSE}
  30.   Dos;
  31. {$ENDIF}
  32.  
  33.  
  34. Type FMsgType = Record
  35.   MsgFile: FFileObj;
  36.   TextCtr: LongInt;
  37.   MsgName: String[13];
  38.   TmpName: String[130];
  39.   TmpOpen: Boolean;
  40.   MsgOpen: Boolean;
  41.   Error: Word;
  42.   NetMailPath: String[128];
  43.   Dest: AddrType;
  44.   Orig: AddrType;
  45.   MsgStart: LongInt;
  46.   MsgEnd: LongInt;
  47.   MsgSize: LongInt;
  48.   DefaultZone: Word;
  49.   QDate: String[8];
  50.   QTime: String[5];
  51.   MsgDone: Boolean;
  52.   CurrMsg: LongInt;
  53.   SeekOver: Boolean;
  54.   {$IFDEF WINDOWS}
  55.   SR: TSearchRec;
  56.   {$ELSE}
  57.   SR: SearchRec;
  58.   {$ENDIF}
  59.   Name: String[35];
  60.   Handle: String[35];
  61.   End;
  62.  
  63.  
  64. Type FidoMsgObj = Object (AbsMsgObj)
  65.   FM: ^FMsgType;
  66.   Constructor Init;                      {Initialize FidoMsgOut}
  67.   Destructor Done; Virtual; {Done FidoMsgOut}
  68.   Procedure RemoveTmp; {remove temporary file}
  69.   Procedure PutLong(L: LongInt; Position: LongInt); {Put long into msg}
  70.   Procedure PutWord(W: Word; Position: LongInt);  {Put word into msg}
  71.   Procedure PutByte(B: Byte; Position: LongInt);  {Put byte into msg}
  72.   Function  GetByte(Position: LongInt): Byte; {Get byte from msg}
  73.   Procedure PutNullStr(St: String; Position: LongInt);  {Put string & null into msg}
  74.   Procedure SetMsgPath(St: String); Virtual; {Set netmail path}
  75.   Function  GetHighMsgNum: LongInt; Virtual; {Get highest netmail msg number in area}
  76.   Procedure SetDest(Var Addr: AddrType); Virtual; {Set Zone/Net/Node/Point for Dest}
  77.   Procedure SetOrig(Var Addr: AddrType); Virtual; {Set Zone/Net/Node/Point for Orig}
  78.   Procedure SetFrom(Name: String); Virtual; {Set message from}
  79.   Procedure SetTo(Name: String); Virtual; {Set message to}
  80.   Procedure SetSubj(Str: String); Virtual; {Set message subject}
  81.   Procedure SetCost(SCost: Word); Virtual; {Set message cost}
  82.   Procedure SetRefer(SRefer: LongInt); Virtual; {Set message reference}
  83.   Procedure SetSeeAlso(SAlso: LongInt); Virtual; {Set message see also}
  84.   Procedure SetDate(SDate: String); Virtual; {Set message date}
  85.   Procedure SetTime(STime: String); Virtual; {Set message time}
  86.   Procedure SetLocal(LS: Boolean); Virtual; {Set local status}
  87.   Procedure SetRcvd(RS: Boolean); Virtual; {Set received status}
  88.   Procedure SetPriv(PS: Boolean); Virtual; {Set priveledge vs public status}
  89.   Procedure SetCrash(SS: Boolean); Virtual; {Set crash netmail status}
  90.   Procedure SetKillSent(SS: Boolean); Virtual; {Set kill/sent netmail status}
  91.   Procedure SetSent(SS: Boolean); Virtual; {Set sent netmail status}
  92.   Procedure SetFAttach(SS: Boolean); Virtual; {Set file attach status}
  93.   Procedure SetReqRct(SS: Boolean); Virtual; {Set request receipt status}
  94.   Procedure SetReqAud(SS: Boolean); Virtual; {Set request audit status}
  95.   Procedure SetRetRct(SS: Boolean); Virtual; {Set return receipt status}
  96.   Procedure SetFileReq(SS: Boolean); Virtual; {Set file request status}
  97.   Procedure DoString(Str: String); Virtual; {Add string to message text}
  98.   Procedure DoChar(Ch: Char); Virtual; {Add character to message text}
  99.   Procedure DoStringLn(Str: String); Virtual; {Add string and newline to msg text}
  100.   Function  WriteMsg: Word; Virtual;
  101.   Procedure SetDefaultZone(DZ: Word); Virtual; {Set default zone to use}
  102.   Procedure LineStart; Virtual; {Internal use to skip LF, ^A}
  103.   Function  GetChar: Char; Virtual;
  104.   Procedure CheckZone(ZoneStr: String); Virtual;
  105.   Procedure CheckPoint(PointStr: String); Virtual;
  106.   Procedure CheckLine(TStr: String); Virtual;
  107.   Function  CvtDate: Boolean; Virtual;
  108.   Function  BufferWord(i: Word):Word; Virtual;
  109.   Function  BufferByte(i: Word):Byte; Virtual;
  110.   Function  BufferNullString(i: Word; Max: Word): String; Virtual;
  111.   Procedure MsgStartUp; Virtual; {set up msg for reading}
  112.   Function  EOM: Boolean; Virtual; {No more msg text}
  113.   Function  GetString(MaxLen: Word): String; Virtual; {Get wordwrapped string}
  114.   Function  WasWrap: Boolean; Virtual; {Last line was soft wrapped no CR}
  115.   Procedure SeekFirst(MsgNum: LongInt); Virtual; {Seek msg number}
  116.   Procedure SeekNext; Virtual; {Find next matching msg}
  117.   Procedure SeekPrior; Virtual; {Seek prior matching msg}
  118.   Function  GetFrom: String; Virtual; {Get from name on current msg}
  119.   Function  GetTo: String; Virtual; {Get to name on current msg}
  120.   Function  GetSubj: String; Virtual; {Get subject on current msg}
  121.   Function  GetCost: Word; Virtual; {Get cost of current msg}
  122.   Function  GetDate: String; Virtual; {Get date of current msg}
  123.   Function  GetTime: String; Virtual; {Get time of current msg}
  124.   Function  GetRefer: LongInt; Virtual; {Get reply to of current msg}
  125.   Function  GetSeeAlso: LongInt; Virtual; {Get see also of current msg}
  126.   Function  GetMsgNum: LongInt; Virtual; {Get message number}
  127.   Procedure GetOrig(Var Addr: AddrType); Virtual; {Get origin address}
  128.   Procedure GetDest(Var Addr: AddrType); Virtual; {Get destination address}
  129.   Function  IsLocal: Boolean; Virtual; {Is current msg local}
  130.   Function  IsCrash: Boolean; Virtual; {Is current msg crash}
  131.   Function  IsKillSent: Boolean; Virtual; {Is current msg kill sent}
  132.   Function  IsSent: Boolean; Virtual; {Is current msg sent}
  133.   Function  IsFAttach: Boolean; Virtual; {Is current msg file attach}
  134.   Function  IsReqRct: Boolean; Virtual; {Is current msg request receipt}
  135.   Function  IsReqAud: Boolean; Virtual; {Is current msg request audit}
  136.   Function  IsRetRct: Boolean; Virtual; {Is current msg a return receipt}
  137.   Function  IsFileReq: Boolean; Virtual; {Is current msg a file request}
  138.   Function  IsRcvd: Boolean; Virtual; {Is current msg received}
  139.   Function  IsPriv: Boolean; Virtual; {Is current msg priviledged/private}
  140.   Function  IsDeleted: Boolean; Virtual; {Is current msg deleted}
  141.   Function  IsEchoed: Boolean; Virtual; {Msg should be echoed}
  142.   Function  GetMsgLoc: LongInt; Virtual; {Msg location}
  143.   Procedure SetMsgLoc(ML: LongInt); Virtual; {Msg location}
  144.   Procedure YoursFirst(Name: String; Handle: String); Virtual; {Seek your mail}
  145.   Procedure YoursNext; Virtual; {Seek next your mail}
  146.   Function  YoursFound: Boolean; Virtual; {Message found}
  147.   Procedure StartNewMsg; Virtual;
  148.   Function  OpenMsgBase: Word; Virtual;
  149.   Function  CloseMsgBase: Word; Virtual;
  150.   Function  CreateMsgBase(MaxMsg: Word; MaxDays: Word): Word; Virtual;
  151.   Function  SeekFound: Boolean; Virtual;
  152.   Procedure SetMailType(MT: MsgMailType); Virtual; {Set message base type}
  153.   Function  GetSubArea: Word; Virtual; {Get sub area number}
  154.   Procedure ReWriteHdr; Virtual; {Rewrite msg header after changes}
  155.   Procedure DeleteMsg; Virtual; {Delete current message}
  156.   Function  NumberOfMsgs: LongInt; Virtual; {Number of messages}
  157.   Function  GetLastRead(UNum: LongInt): LongInt; Virtual; {Get last read for user num}
  158.   Procedure SetLastRead(UNum: LongInt; LR: LongInt); Virtual; {Set last read}
  159.   Procedure MsgTxtStartUp; Virtual; {Do message text start up tasks}
  160.   Function  GetTxtPos: LongInt; Virtual; {Get indicator of msg text position}
  161.   Procedure SetTxtPos(TP: LongInt); Virtual; {Set text position}
  162.   End;
  163.  
  164.  
  165. Type FidoMsgPtr = ^FidoMsgObj;
  166.  
  167. Function MonthStr(MoNo: Byte): String; {Return 3 char month name for month num}
  168. Function MonthNum(St: String):Word;
  169.  
  170.  
  171. Implementation
  172.  
  173. Uses MKFile, MKString, MKDos;
  174.  
  175.  
  176. Constructor FidoMsgObj.Init;
  177.   Begin
  178.   New(FM);
  179.   If FM = Nil Then
  180.     Begin
  181.     Fail;
  182.     Exit;
  183.     End;
  184.   FM^.NetMailPath := '';
  185.   FM^.TextCtr := 190;
  186.   FM^.Dest.Zone := 0;
  187.   FM^.Orig.Zone := 0;
  188.   FM^.SeekOver := False;
  189.   FM^.DefaultZone := 1;
  190.   FM^.MsgFile.Init(4000);
  191.   FM^.TmpOpen := False;
  192.   FM^.MsgOpen := False;
  193.   End;
  194.  
  195.  
  196. Destructor FidoMsgObj.Done;
  197.   Begin
  198.   If FM^.MsgOpen Then
  199.     If FM^.MsgFile.CloseFile Then;
  200.   If FM^.TmpOpen Then
  201.     Begin
  202.     RemoveTmp;
  203.     End;
  204.   FM^.MsgFile.Done;
  205.   Dispose(FM);
  206.   End;
  207.  
  208.  
  209. Procedure FidoMsgObj.RemoveTmp;
  210.   Var
  211.     TmpFile: File;
  212.  
  213.   Begin
  214.   If FM^.MsgFile.CloseFile Then;
  215.   Assign(TmpFile, FM^.TmpName);
  216.   Erase(TmpFile);
  217.   If IoResult <> 0 Then;
  218.   FM^.TmpOpen := False;
  219.   End;
  220.  
  221.  
  222. Procedure FidoMsgObj.PutLong(L: LongInt; Position: LongInt);
  223.   Var
  224.     i: Integer;
  225.  
  226.   Begin
  227.   If FM^.MsgFile.SeekFile(Position) Then
  228.     If FM^.MsgFile.BlkWrite(L, SizeOf(LongInt)) Then;
  229.   End;
  230.  
  231.  
  232. Procedure FidoMsgObj.PutWord(W: Word; Position: LongInt);
  233.   Begin
  234.   If FM^.MsgFile.SeekFile(Position) Then
  235.     If FM^.MsgFile.BlkWrite(W, SizeOf(Word)) Then;
  236.   End;
  237.  
  238.  
  239. Procedure FidoMsgObj.PutByte(B: Byte; Position: LongInt);
  240.   Begin
  241.   If FM^.MsgFile.SeekFile(Position) Then
  242.     If FM^.MsgFile.BlkWrite(B, SizeOf(Byte)) Then;
  243.   End;
  244.  
  245.  
  246. Function FidoMsgObj.GetByte(Position: LongInt): Byte;
  247.   Var
  248.     B: Byte;
  249.     NumRead: Word;
  250.  
  251.   Begin
  252.   If FM^.MsgFile.SeekFile(Position) Then
  253.     If FM^.MsgFile.BlkRead(B, SizeOf(Byte), NumRead) Then;
  254.   GetByte := b;
  255.   End;
  256.  
  257. Procedure FidoMsgObj.PutNullStr(St: String; Position: LongInt);
  258.   Var
  259.     i: Byte;
  260.  
  261.   Begin
  262.   i := 0;
  263.   If FM^.MsgFile.SeekFile(Position) Then
  264.     Begin
  265.     If FM^.MsgFile.BlkWrite(St[1], Length(St)) Then;
  266.     If FM^.MsgFile.BlkWrite(i, 1) Then;
  267.     End;
  268.   End;
  269.  
  270.  
  271. Procedure FidoMsgObj.SetMsgPath(St: String);
  272.   Begin
  273.   FM^.NetMailPath := Copy(St, 1, 110);
  274.   AddBackSlash(FM^.NetMailPath);
  275.   End;
  276.  
  277.  
  278. Function FidoMsgObj.GetHighMsgNum: LongInt;
  279.   Var
  280.   {$IFDEF WINDOWS}
  281.     SR: TSearchRec;
  282.     TStr: Array[0..128] of Char;
  283.   {$ELSE}
  284.     SR: SearchRec;
  285.   {$ENDIF}
  286.   TmpName: String[13];
  287.   TmpNum: Word;
  288.   Code: Word;
  289.   Highest: LongInt;
  290.  
  291.   Begin
  292.   Highest := 1;
  293.   {$IFDEF WINDOWS}
  294.   StrPCopy(TStr, FM^.NetMailPath + '*.MSG');
  295.   FindFirst(TStr, faReadOnly + faArchive, SR);
  296.   {$ELSE}
  297.   FindFirst(FM^.NetMailPath + '*.MSG', ReadOnly + Archive, SR);
  298.   {$ENDIF}
  299.   While DosError = 0 Do
  300.     Begin
  301.     {$IFDEF WINDOWS}
  302.     TmpName :=  StrPas(SR.Name);
  303.     {$ELSE}
  304.     TmpName := SR.Name;
  305.     {$ENDIF}
  306.     Val(Copy(TmpName, 1,  Pos('.', TmpName) - 1), TmpNum, Code);
  307.     If ((Code = 0) And (TmpNum > Highest)) Then
  308.       Highest := TmpNum;
  309.     FindNext(SR);
  310.     End;
  311.   GetHighMsgNum := Highest;
  312.   End;
  313.  
  314.  
  315. Function MonthStr(MoNo: Byte): String;
  316.   Begin
  317.   Case MoNo of
  318.     01: MonthStr := 'Jan';
  319.     02: MonthStr := 'Feb';
  320.     03: MonthStr := 'Mar';
  321.     04: MonthStr := 'Apr';
  322.     05: MonthStr := 'May';
  323.     06: MonthStr := 'Jun';
  324.     07: MonthStr := 'Jul';
  325.     08: MonthStr := 'Aug';
  326.     09: MonthStr := 'Sep';
  327.     10: MonthStr := 'Oct';
  328.     11: MonthStr := 'Nov';
  329.     12: MonthStr := 'Dec';
  330.     Else
  331.       MonthStr := '???';
  332.     End;
  333.   End;
  334.  
  335.  
  336. Procedure FidoMsgObj.SetDest(Var Addr: AddrType);
  337.   Var
  338.     TmpChr: Char;
  339.  
  340.   Begin
  341.   FM^.Dest := Addr;
  342.   PutWord(Addr.Net, 174);
  343.   PutWord(Addr.Node, 166);
  344.   If Addr.Point <> 0 Then
  345.     Begin
  346.     If ((FM^.TextCtr <> 190) And
  347.     (GetByte(FM^.TextCtr - 1) <> 13)) Then
  348.       DoChar(#13);
  349.     DoStringLn(#1 + 'TOPT ' + Long2Str(Addr.Point));
  350.     End;
  351.   If ((FM^.Orig.Zone <> 0)) Then
  352.     Begin
  353.     If ((FM^.TextCtr <> 190) And
  354.     (GetByte(FM^.TextCtr - 1) <> 13)) Then
  355.       DoChar(#13);
  356.     DoStringLn(#1 + 'INTL ' + AddrStr(FM^.Dest) + ' ' + AddrStr(FM^.Orig));
  357.     End;
  358.   End;
  359.  
  360.  
  361. Procedure FidoMsgObj.SetOrig(Var Addr: AddrType);
  362.   Begin
  363.   FM^.Orig := Addr;
  364.   PutWord(Addr.Net, 172);
  365.   PutWord(Addr.Node, 168);
  366.   If Addr.Point <> 0 Then
  367.     Begin
  368.     If ((FM^.TextCtr <> 190) And
  369.     (GetByte(FM^.TextCtr - 1) <> 13)) Then
  370.       DoChar(#13);
  371.     DoStringLn(#1 + 'FMPT ' + Long2Str(Addr.Point));
  372.     End;
  373.   If ((FM^.Dest.Zone <> 0)) Then
  374.     Begin
  375.     If ((FM^.TextCtr <> 190) And
  376.     (GetByte(FM^.TextCtr - 1) <> 13)) Then
  377.       DoChar(#13);
  378.     DoStringLn(#1 + 'INTL ' + AddrStr(FM^.Dest) + ' ' + AddrStr(FM^.Orig));
  379.     End;
  380.   End;
  381.  
  382.  
  383. Procedure FidoMsgObj.SetFrom(Name: String);
  384.   Begin
  385.   PutNullStr(Copy(Name, 1, 35),0);
  386.   End;
  387.  
  388.  
  389. Procedure FidoMsgObj.SetTo(Name: String);
  390.   Begin
  391.   PutNullStr(Copy(Name, 1, 35), 36);
  392.   End;
  393.  
  394.  
  395. Procedure FidoMsgObj.SetSubj(Str: String);
  396.   Begin
  397.   PutNullStr(Copy(Str, 1, 71), 72);
  398.   End;
  399.  
  400.  
  401. Procedure FidoMsgObj.SetCost(SCost: Word);
  402.   Begin
  403.   PutWord(SCost, 170);
  404.   End;
  405.  
  406.  
  407. Procedure FidoMsgObj.SetRefer(SRefer: LongInt);
  408.   Begin
  409.   PutWord(SRefer, 184);
  410.   End;
  411.  
  412.  
  413. Procedure FidoMsgObj.SetSeeAlso(SAlso: LongInt);
  414.   Begin
  415.   PutWord(SAlso, 188);
  416.   End;
  417.  
  418.  
  419. Procedure FidoMsgObj.SetDate(SDate: String);
  420.   Var
  421.     TempNum: Word;
  422.     Code: Word;
  423.     TmpStr: String[20];
  424.  
  425.   Begin
  426.   FM^.QDate := Copy(SDate,1,8);
  427.   Val(Copy(SDate,1,2),TempNum, Code);
  428.   TmpStr := Copy(SDate,4,2) + ' ' + MonthStr(TempNum) + ' ' +
  429.     Copy(SDate,7,2) + '  ';
  430.   For TempNum := 1 to 11 Do
  431.     PutByte(Ord(TmpStr[TempNum]), TempNum + 143);
  432.   End;
  433.  
  434.  
  435. Procedure FidoMsgObj.SetTime(STime: String);
  436.   Begin
  437.   FM^.QTime := Copy(STime,1,5);
  438.   PutNullStr(Copy(STime + ':00', 1, 8), 155);
  439.   End;
  440.  
  441.  
  442. Procedure FidoMsgObj.SetLocal(LS: Boolean);
  443.   Begin
  444.   If LS Then
  445.     PutByte(GetByte(187) or 1, 187)
  446.   Else
  447.     PutByte(GetByte(187) and (Not 1), 187);
  448.   End;
  449.  
  450.  
  451. Procedure FidoMsgObj.SetRcvd(RS: Boolean);
  452.   Begin
  453.   If RS Then
  454.     PutByte(GetByte(186) or 4, 186)
  455.   Else
  456.     PutByte(GetByte(186) and (not 4), 186);
  457.   End;
  458.  
  459.  
  460. Procedure FidoMsgObj.SetPriv(PS: Boolean);
  461.   Begin
  462.   If PS Then
  463.     PutByte(GetByte(186) or 1, 186)
  464.   Else
  465.     PutByte(GetByte(186) and (not 1), 186);
  466.   End;
  467.  
  468.  
  469. Procedure FidoMsgObj.SetCrash(SS: Boolean);
  470.   Begin
  471.   If SS Then
  472.     PutByte(GetByte(186) or 2, 186)
  473.   Else
  474.     PutByte(GetByte(186) and (not 2), 186);
  475.   End;
  476.  
  477.  
  478. Procedure FidoMsgObj.SetKillSent(SS: Boolean);
  479.   Begin
  480.   If SS Then
  481.     PutByte(GetByte(186) or 128, 186)
  482.   Else
  483.     PutByte(GetByte(186) and (Not 128), 186);
  484.   End;
  485.  
  486.  
  487. Procedure FidoMsgObj.SetSent(SS: Boolean);
  488.   Begin
  489.   If SS Then
  490.     PutByte(GetByte(186) or 8, 186)
  491.   Else
  492.     PutByte(GetByte(186) and (not 8), 186);
  493.   End;
  494.  
  495.  
  496. Procedure FidoMsgObj.SetFAttach(SS: Boolean);
  497.   Begin
  498.   If SS Then
  499.     PutByte(GetByte(186) or 16, 186)
  500.   Else
  501.     PutByte(GetByte(186) and (not 16), 186);
  502.   End;
  503.  
  504.  
  505. Procedure FidoMsgObj.SetReqRct(SS: Boolean);
  506.   Begin
  507.   If SS Then
  508.     PutByte(GetByte(187) or 16, 187)
  509.   Else
  510.     PutByte(GetByte(187) and (not 16), 187);
  511.   End;
  512.  
  513.  
  514. Procedure FidoMsgObj.SetReqAud(SS: Boolean);
  515.   Begin
  516.   If SS Then
  517.     PutByte(GetByte(187) or 64, 187)
  518.   Else
  519.     PutByte(GetByte(187) and (not 64), 187);
  520.   End;
  521.  
  522.  
  523. Procedure FidoMsgObj.SetRetRct(SS: Boolean);
  524.   Begin
  525.   If SS Then
  526.     PutByte(GetByte(187) or 32, 187)
  527.   Else
  528.     PutByte(GetByte(187) and (not 32), 187);
  529.   End;
  530.  
  531.  
  532. Procedure FidoMsgObj.SetFileReq(SS: Boolean);
  533.   Begin
  534.   If SS Then
  535.     PutByte(GetByte(187) or 8, 187)
  536.   Else
  537.     PutByte(GetByte(187) and (not 8), 187);
  538.   End;
  539.  
  540.  
  541. Procedure FidoMsgObj.DoString(Str: String);
  542.   Var
  543.     i: Word;
  544.  
  545.   Begin
  546.   i := 1;
  547.   While i <= Length(Str) Do
  548.     Begin
  549.     DoChar(Str[i]);
  550.     Inc(i);
  551.     End;
  552.   End;
  553.  
  554.  
  555. Procedure FidoMsgObj.DoChar(Ch: Char);
  556.   Begin
  557.   PutByte(Ord(Ch), FM^.TextCtr);
  558.   Inc(FM^.TextCtr);
  559.   End;
  560.  
  561.  
  562. Procedure FidoMsgObj.DoStringLn(Str: String);
  563.   Begin
  564.   DoString(Str);
  565.   DoChar(#13);
  566.   End;
  567.  
  568.  
  569. Function  FidoMsgObj.WriteMsg: Word;
  570.   Var
  571.     NetNum: Word;
  572.     TmpDate: LongInt;
  573.     {$IFDEF WINDOWS}
  574.     TmpDT: TDateTime;
  575.     {$ELSE}
  576.     TmpDT: DateTime;
  577.     {$ENDIF}
  578.     TmpFile: File;
  579.  
  580.   Begin
  581.   PutLong(GetDosDate, 180);
  582.   TmpDT.Year := Str2Long(Copy(FM^.QDate,7,2));
  583.   If TmpDT.Year > 79 Then
  584.     Inc(TmpDT.Year, 1900)
  585.   Else
  586.     Inc(TmpDT.Year, 2000);
  587.   TmpDT.Month := Str2Long(Copy(FM^.QDate,1,2));
  588.   TmpDT.Day := Str2Long(Copy(FM^.QDate,4,2));
  589.   TmpDt.Hour := Str2Long(Copy(FM^.QTime,1,2));
  590.   TmpDt.Min := Str2Long(Copy(FM^.QTime, 4,2));
  591.   TmpDt.Sec := 0;
  592.   PackTime(TmpDT, TmpDate);
  593.   PutLong(TmpDate, 176);
  594.   NetNum := GetHighMsgNum + 1;
  595.   If FM^.TmpOpen Then
  596.     Begin
  597.     If FM^.MsgFile.CloseFile Then
  598.       Begin
  599.       Assign(TmpFile, FM^.TmpName);
  600.       Rename(TmpFile, FM^.NetMailPath + Long2Str(NetNum) + '.Msg')
  601.       End;
  602.     End;
  603.   WriteMsg := IoResult;
  604.   FM^.CurrMsg := NetNum;
  605.   End;
  606.  
  607.  
  608. Procedure FidoMsgObj.SetDefaultZone(DZ: Word); {Set default zone to use}
  609.   Begin
  610.   FM^.DefaultZone := DZ;
  611.   End;
  612.  
  613.  
  614. Procedure FidoMsgObj.LineStart;
  615.   Begin
  616.   If GetByte(FM^.TextCtr) = 10 Then
  617.     Inc(FM^.TextCtr);
  618.   If GetByte(FM^.TextCtr) = 1 Then
  619.     Inc(FM^.TextCtr);
  620.   End;
  621.  
  622.  
  623. Function FidoMsgObj.GetChar: Char;
  624.   Begin
  625.   If ((FM^.TextCtr >= FM^.MsgSize) Or (GetByte(FM^.TextCtr) = 0)) Then
  626.     Begin
  627.     GetChar := #0;
  628.     FM^.MsgDone := True;
  629.     End
  630.   Else
  631.     Begin
  632.     GetChar := Chr(GetByte(FM^.TextCtr));
  633.     Inc(FM^.TextCtr);
  634.     End;
  635.   End;
  636.  
  637.  
  638. Procedure FidoMsgObj.CheckZone(ZoneStr: String);
  639.   Var
  640.     DestZoneStr: String;
  641.     Code: Word;
  642.  
  643.   Begin
  644.   If (Upper(Copy(ZoneStr,1,4)) = 'INTL') Then
  645.     Begin
  646.     DestZoneStr := ExtractWord(ZoneStr, 2);
  647.     DestZoneStr := StripBoth(DestZoneStr, ' ');
  648.     DestZoneStr := Copy(DestZoneStr, 1, Pos(':', DestZoneStr) - 1);
  649.     Val(DestZoneStr, FM^.Dest.Zone, Code);
  650.     DestZoneStr := ExtractWord(ZoneStr,3);
  651.     DestZoneStr := StripBoth(DestZoneStr, ' ');
  652.     DestZoneStr := Copy(DestZoneStr, 1, Pos(':', DestZoneStr) - 1);
  653.     Val(DestZoneStr, FM^.Orig.Zone, Code);
  654.     End;
  655.   End;
  656.  
  657.  
  658. Procedure FidoMsgObj.CheckPoint(PointStr: String);
  659.   Var
  660.     DestPointStr: String;
  661.     Code: Word;
  662.     Temp: Word;
  663.  
  664.   Begin
  665.   If (Upper(Copy(PointStr,1,4)) = 'TOPT') Then
  666.     Begin
  667.     DestPointStr := ExtractWord(PointStr, 2);
  668.     DestPointStr := StripBoth(DestPointStr, ' ');
  669.     Val(DestPointStr, Temp, Code);
  670.     If Code = 0 Then
  671.       FM^.Dest.Point := Temp;
  672.     End;
  673.   If (Upper(Copy(PointStr,1,4)) = 'FMPT') Then
  674.     Begin
  675.     DestPointStr := ExtractWord(PointStr, 2);
  676.     DestPointStr := StripBoth(DestPointStr, ' ');
  677.     Val(DestPointStr, Temp, Code);
  678.     If Code = 0 Then
  679.       FM^.Orig.Point := Temp;
  680.     End;
  681.   End;
  682.  
  683.  
  684. Function MonthNum(St: String):Word;
  685.   Begin
  686.   ST := Upper(St);
  687.   MonthNum := 0;
  688.   If St = 'JAN' Then MonthNum := 01;
  689.   If St = 'FEB' Then MonthNum := 02;
  690.   If St = 'MAR' Then MonthNum := 03;
  691.   If St = 'APR' Then MonthNum := 04;
  692.   If St = 'MAY' Then MonthNum := 05;
  693.   If St = 'JUN' Then MonthNum := 06;
  694.   If St = 'JUL' Then MonthNum := 07;
  695.   If St = 'AUG' Then MonthNum := 08;
  696.   If St = 'SEP' Then MonthNum := 09;
  697.   If St = 'OCT' Then MonthNum := 10;
  698.   If St = 'NOV' Then MonthNum := 11;
  699.   If St = 'DEC' Then MonthNum := 12;
  700.   End;
  701.  
  702.  
  703. Function FidoMsgObj.CvtDate: Boolean;
  704.   Var
  705.     MoNo: Word;
  706.     TmpStr: String;
  707.     i: Word;
  708.     MsgDt: String[25];
  709.  
  710.   Begin
  711.   MsgDt := BufferNullString(144, 20);
  712.   MsgDt := PadRight(MsgDt,' ', 20);
  713.   CvtDate := True;
  714.   If MsgDt[3] = ' ' Then
  715.     Begin {Fido or Opus}
  716.     If MsgDt[11] = ' ' Then
  717.       Begin {Fido DD MON YY  HH:MM:SSZ}
  718.       FM^.QTime := Copy (MsgDT,12,5);
  719.       TmpStr := Long2Str(MonthNum(Copy(MsgDt,4,3)));
  720.       If Length(TmpStr) = 1 Then
  721.         TmpStr := '0' + TmpStr;
  722.       FM^.QDate := TmpStr + '-' + Copy(MsgDT,1,2) + '-' + Copy (MsgDt,8,2);
  723.       End
  724.     Else
  725.       Begin {Opus DD MON YY HH:MM:SS}
  726.       FM^.QTime := Copy(MsgDT,11,5);
  727.       TmpStr := Long2Str(MonthNum(Copy(MsgDt,4,3)));
  728.       If Length(TmpStr) = 1 Then
  729.         TmpStr := '0' + TmpStr;
  730.       FM^.QDate := TmpStr + '-' + Copy(MsgDT,1,2) + '-' + Copy (MsgDt,8,2);
  731.       End;
  732.     End
  733.   Else
  734.     Begin
  735.     If MsgDT[4] = ' ' Then
  736.       Begin {SeaDog format DOW DD MON YY HH:MM}
  737.       FM^.QTime := Copy(MsgDT,15,5);
  738.       TmpStr := Long2Str(MonthNum(Copy(MsgDT,8,3)));
  739.       If Length(TmpStr) = 1 Then
  740.         TmpStr := '0' + TmpStr;
  741.       FM^.QDate := TmpStr + '-' + Copy(MsgDT,5,2) + '-' + Copy (MsgDt,12,2);
  742.       End
  743.     Else
  744.       Begin
  745.       If MsgDT[3] = '-' Then
  746.         Begin {Wierd format DD-MM-YYYY HH:MM:SS}
  747.         FM^.QTime := Copy(MsgDt,12,5);
  748.         FM^.QDate := Copy(MsgDt,4,3) + Copy (MsgDt,1,3) + Copy (MsgDt,9,2);
  749.         End
  750.       Else
  751.         Begin  {Bad Date}
  752.         CvtDate := False;
  753.         End;
  754.       End;
  755.     End;
  756.   For i := 1 to 5 Do
  757.     If FM^.QTime[i] = ' ' Then
  758.       FM^.QTime[i] := '0';
  759.   For i := 1 to 8 Do
  760.     If FM^.QDate[i] = ' ' Then
  761.       FM^.QDate[i] := '0';
  762.   If Length(FM^.QDate) <> 8 Then
  763.     CvtDate := False;
  764.   If Length(FM^.QTime) <> 5 Then
  765.     CvtDate := False;
  766.   End;
  767.  
  768.  
  769. Function FidoMsgObj.BufferWord(i: Word):Word;
  770.   Begin
  771.   BufferWord := BufferByte(i) + (BufferByte(i + 1) shl 8);
  772.   End;
  773.  
  774.  
  775. Function FidoMsgObj.BufferByte(i: Word):Byte;
  776.   Begin
  777.   BufferByte := GetByte(i);
  778.   End;
  779.  
  780.  
  781. Function FidoMsgObj.BufferNullString(i: Word; Max: Word): String;
  782.   Var
  783.     Ctr: Word;
  784.     CurrPos: Word;
  785.  
  786.   Begin
  787.   BufferNullString := '';
  788.   Ctr := i;
  789.   CurrPos := 0;
  790.   While ((CurrPos < Max) and (GetByte(Ctr) <> 0)) Do
  791.     Begin
  792.     Inc(CurrPos);
  793.     BufferNullString[CurrPos] := Chr(GetByte(Ctr));
  794.     Inc(Ctr);
  795.     End;
  796.   BufferNullString[0] := Chr(CurrPos);
  797.   End;
  798.  
  799.  
  800. Procedure FidoMsgObj.CheckLine(TStr: String);
  801.   Begin
  802.   If TStr[1] = #10 Then
  803.     TStr := Copy(TStr,2,255);
  804.   If TStr[1] = #01 Then
  805.     TStr := Copy(TStr,2,255);
  806.   CheckZone(TStr);
  807.   CheckPoint(TStr);
  808.   End;
  809.  
  810.  
  811. Procedure FidoMsgObj.MsgStartUp;
  812.   Var
  813.     TStr: String;
  814.     TmpChr: Char;
  815.     NumRead: Word;
  816.  
  817.   Begin
  818.   If FM^.MsgOpen Then
  819.     If FM^.MsgFile.CloseFile Then
  820.       FM^.MsgOpen := False;
  821.   If FM^.TmpOpen Then
  822.     RemoveTmp;
  823.   LastSoft := False;
  824.   If FileExist (FM^.NetMailPath + Long2Str(FM^.CurrMsg) + '.MSG') Then
  825.     FM^.Error := 0
  826.   Else
  827.     FM^.Error := 200;
  828.   If FM^.Error = 0 Then
  829.     Begin
  830.     If Not FM^.MsgFile.OpenFile(FM^.NetMailPath + Long2Str(FM^.CurrMsg) +
  831.     '.Msg',  fmReadWrite + fmDenyNone) Then FM^.Error := 1000;
  832.     End;
  833.   If FM^.Error = 0 Then
  834.     FM^.MsgOpen := True;
  835.   FM^.MsgDone := False;
  836.   FM^.MsgSize := FM^.MsgFile.RawSize;
  837.   FM^.MsgEnd := 0;
  838.   FM^.MsgStart := 190;
  839.   FM^.Dest.Zone := FM^.DefaultZone;
  840.   FM^.Dest.Point := 0;
  841.   FM^.Orig.Zone := FM^.DefaultZone;
  842.   FM^.Orig.Point := 0;
  843.   FM^.Orig.Net := BufferWord(172);
  844.   FM^.Orig.Node := BufferWord(168);
  845.   FM^.Dest.Net := BufferWord(174);
  846.   FM^.Dest.Node := BufferWord(166);
  847.   FM^.TextCtr := FM^.MsgStart;
  848.   If FM^.Error = 0 Then
  849.     Begin
  850.     If Not CvtDate Then
  851.       Begin
  852.       FM^.QDate := '09-06-89';
  853.       FM^.QTime := '19:76';
  854.       End;
  855.     TStr := GetString(128);
  856.     CheckLine(TStr);
  857.     If FM^.MsgFile.SeekFile(FM^.TextCtr) Then
  858.       If FM^.MsgFile.BlkRead(TmpChr, 1, NumRead) Then;
  859.     While ((FM^.MsgEnd = 0) and (FM^.TextCtr <= FM^.MsgSize)) Do
  860.       Begin
  861.       Case TmpChr Of
  862.         #0: FM^.MsgEnd := FM^.TextCtr;
  863.         #13: Begin
  864.           Inc(FM^.TextCtr);
  865.           TStr := GetString(128);
  866.           CheckLine(TStr);
  867.           If Length(TStr) > 0 Then
  868.             Dec(FM^.TextCtr);
  869.           End;
  870.         Else
  871.           Begin
  872.           Inc(FM^.TextCtr);
  873.           If FM^.MsgFile.BlkRead(TmpChr, 1, NumRead) Then;
  874.           End;
  875.         End;
  876.       End;
  877.     If FM^.MsgEnd = 0 Then
  878.       FM^.MsgEnd := FM^.MsgSize;
  879.     FM^.MsgSize := FM^.MsgEnd;
  880.     FM^.MsgStart := 190;
  881.     FM^.TextCtr := FM^.MsgStart;
  882.     FM^.MsgDone := False;
  883.     LastSoft := False;
  884.     End;
  885.   End;
  886.  
  887.  
  888. Procedure FidoMsgObj.MsgTxtStartUp;
  889.   Begin
  890.   FM^.MsgStart := 190;
  891.   FM^.TextCtr := FM^.MsgStart;
  892.   FM^.MsgDone := False;
  893.   LastSoft := False;
  894.   End;
  895.  
  896.  
  897. Function FidoMsgObj.GetString(MaxLen: Word): String;
  898.   Var
  899.     WPos: Word;
  900.     WLen: Byte;
  901.     StrDone: Boolean;
  902.     TxtOver: Boolean;
  903.     StartSoft: Boolean;
  904.     CurrLen: Word;
  905.     PPos: Word;
  906.     TmpCh: Char;
  907.  
  908.   Begin
  909.   StrDone := False;
  910.   CurrLen := 0;
  911.   PPos := FM^.TextCtr;
  912.   WPos := 0;
  913.   WLen := 0;
  914.   StartSoft := LastSoft;
  915.   LastSoft := True;
  916.   TmpCh := GetChar;
  917.   While ((Not StrDone) And (CurrLen < MaxLen) And (Not FM^.MsgDone)) Do
  918.     Begin
  919.     Case TmpCh of
  920.       #$00:;
  921.       #$0d: Begin
  922.             StrDone := True;
  923.             LastSoft := False;
  924.             End;
  925.       #$8d:;
  926.       #$0a:;
  927.       #$20: Begin
  928.             If ((CurrLen <> 0) or (Not StartSoft)) Then
  929.               Begin
  930.               Inc(CurrLen);
  931.               WLen := CurrLen;
  932.               GetString[CurrLen] := TmpCh;
  933.               WPos := FM^.TextCtr;
  934.               End
  935.             Else
  936.               StartSoft := False;
  937.             End;
  938.       Else
  939.         Begin
  940.         Inc(CurrLen);
  941.         GetString[CurrLen] := TmpCh;
  942.         End;
  943.       End;
  944.     If Not StrDone Then
  945.       TmpCh := GetChar;
  946.     End;
  947.   If StrDone Then
  948.     Begin
  949.     GetString[0] := Chr(CurrLen);
  950.     End
  951.   Else
  952.     If FM^.MsgDone Then
  953.       Begin
  954.       GetString[0] := Chr(CurrLen);
  955.       End
  956.     Else
  957.       Begin
  958.       If WLen = 0 Then
  959.         Begin
  960.         GetString[0] := Chr(CurrLen);
  961.         Dec(FM^.TextCtr);
  962.         End
  963.       Else
  964.         Begin
  965.         GetString[0] := Chr(WLen);
  966.         FM^.TextCtr := WPos;
  967.         End;
  968.       End;
  969.   End;
  970.  
  971.  
  972. Function FidoMsgObj.EOM: Boolean;
  973.   Begin
  974.   EOM := FM^.MsgDone;
  975.   End;
  976.  
  977.  
  978. Function FidoMsgObj.WasWrap: Boolean;
  979.   Begin
  980.   WasWrap := LastSoft;
  981.   End;
  982.  
  983.  
  984. Function FidoMsgObj.GetFrom: String; {Get from name on current msg}
  985.   Begin
  986.   GetFrom := BufferNullString(0, 35);
  987.   End;
  988.  
  989.  
  990. Function FidoMsgObj.GetTo: String; {Get to name on current msg}
  991.   Begin
  992.   GetTo := BufferNullString(36,35);
  993.   End;
  994.  
  995.  
  996. Function FidoMsgObj.GetSubj: String; {Get subject on current msg}
  997.   Begin
  998.   GetSubj := BufferNullString(72,71);
  999.   End;
  1000.  
  1001.  
  1002. Function FidoMsgObj.GetCost: Word; {Get cost of current msg}
  1003.   Begin
  1004.   GetCost := BufferWord(170);
  1005.   End;
  1006.  
  1007.  
  1008. Function FidoMsgObj.GetDate: String; {Get date of current msg}
  1009.   Begin
  1010.   GetDate := FM^.QDate;
  1011.   End;
  1012.  
  1013.  
  1014. Function FidoMsgObj.GetTime: String; {Get time of current msg}
  1015.   Begin
  1016.   GetTime := FM^.QTime;
  1017.   End;
  1018.  
  1019.  
  1020. Function FidoMsgObj.GetRefer: LongInt; {Get reply to of current msg}
  1021.   Begin
  1022.   GetRefer := BufferWord(184);
  1023.   End;
  1024.  
  1025.  
  1026. Function FidoMsgObj.GetSeeAlso: LongInt; {Get see also of current msg}
  1027.   Begin
  1028.   GetSeeAlso := BufferWord(188);
  1029.   End;
  1030.  
  1031.  
  1032. Function FidoMsgObj.GetMsgNum: LongInt; {Get message number}
  1033.   Begin
  1034.   GetMsgNum := FM^.CurrMsg;
  1035.   End;
  1036.  
  1037.  
  1038. Procedure FidoMsgObj.GetOrig(Var Addr: AddrType); {Get origin address}
  1039.   Begin
  1040.   Addr := FM^.Orig;
  1041.   End;
  1042.  
  1043.  
  1044. Procedure FidoMsgObj.GetDest(Var Addr: AddrType); {Get destination address}
  1045.   Begin
  1046.   Addr := FM^.Dest;
  1047.   End;
  1048.  
  1049.  
  1050. Function FidoMsgObj.IsLocal: Boolean; {Is current msg local}
  1051.   Begin
  1052.   IsLocal := ((GetByte(187) and 001) <> 0);
  1053.   End;
  1054.  
  1055.  
  1056. Function FidoMsgObj.IsCrash: Boolean; {Is current msg crash}
  1057.   Begin
  1058.   IsCrash := ((GetByte(186) and 002) <> 0);
  1059.   End;
  1060.  
  1061.  
  1062. Function FidoMsgObj.IsKillSent: Boolean; {Is current msg kill sent}
  1063.   Begin
  1064.   IsKillSent := ((GetByte(186) and 128) <> 0);
  1065.   End;
  1066.  
  1067.  
  1068. Function FidoMsgObj.IsSent: Boolean; {Is current msg sent}
  1069.   Begin
  1070.   IsSent := ((GetByte(186) and 008) <> 0);
  1071.   End;
  1072.  
  1073.  
  1074. Function FidoMsgObj.IsFAttach: Boolean; {Is current msg file attach}
  1075.   Begin
  1076.   IsFAttach := ((GetByte(186) and 016) <> 0);
  1077.   End;
  1078.  
  1079.  
  1080. Function FidoMsgObj.IsReqRct: Boolean; {Is current msg request receipt}
  1081.   Begin
  1082.   IsReqRct := ((GetByte(187) and 016) <> 0);
  1083.   End;
  1084.  
  1085.  
  1086. Function FidoMsgObj.IsReqAud: Boolean; {Is current msg request audit}
  1087.   Begin
  1088.   IsReqAud := ((GetByte(187) and 064) <> 0);
  1089.   End;
  1090.  
  1091.  
  1092. Function FidoMsgObj.IsRetRct: Boolean; {Is current msg a return receipt}
  1093.   Begin
  1094.   IsRetRct := ((GetByte(187) and 032) <> 0);
  1095.   End;
  1096.  
  1097.  
  1098. Function FidoMsgObj.IsFileReq: Boolean; {Is current msg a file request}
  1099.   Begin
  1100.   IsFileReq := ((GetByte(187) and 008) <> 0);
  1101.   End;
  1102.  
  1103.  
  1104. Function FidoMsgObj.IsRcvd: Boolean; {Is current msg received}
  1105.   Begin
  1106.   IsRcvd := ((GetByte(186) and 004) <> 0);
  1107.   End;
  1108.  
  1109.  
  1110. Function FidoMsgObj.IsPriv: Boolean; {Is current msg priviledged/private}
  1111.   Begin
  1112.   IsPriv := ((GetByte(186) and 001) <> 0);
  1113.   End;
  1114.  
  1115.  
  1116. Function FidoMsgObj.IsDeleted: Boolean; {Is current msg deleted}
  1117.   Begin
  1118.   IsDeleted := Not FileExist (FM^.NetMailPath + Long2Str(FM^.CurrMsg) + '.MSG');
  1119.   End;
  1120.  
  1121.  
  1122. Function FidoMsgObj.IsEchoed: Boolean; {Is current msg echoed}
  1123.   Begin
  1124.   IsEchoed := True;
  1125.   End;
  1126.  
  1127.  
  1128. Procedure FidoMsgObj.SeekFirst(MsgNum: LongInt); {Start msg seek}
  1129.   Begin
  1130.   FM^.CurrMsg := MsgNum - 1;
  1131.   SeekNext;
  1132.   End;
  1133.  
  1134.  
  1135. Procedure FidoMsgObj.SeekNext; {Find next matching msg}
  1136.   Var
  1137.     Code: Word;
  1138.     BestMatch: LongInt;
  1139.     CurrTry : LongInt;
  1140.     {$IFDEF WINDOWS}
  1141.       TStr: Array[0..128] of Char;
  1142.     {$ENDIF}
  1143.     MsgWasFound: Boolean;
  1144.  
  1145.   Begin
  1146.   CurrTry := 0;
  1147.   MsgWasFound := False;
  1148.   BestMatch := $7fffffff;
  1149.   Inc(FM^.CurrMsg);
  1150.   {$IFDEF WINDOWS}
  1151.   StrPCopy(TStr, FM^.NetMailPath + '*.MSG');
  1152.   FindFirst(TStr, faReadOnly + faArchive, FM^.SR);
  1153.   {$ELSE}
  1154.   FindFirst(FM^.NetMailPath + '*.MSG', ReadOnly + Archive, FM^.SR);
  1155.   {$ENDIF}
  1156.   While DosError = 0 Do
  1157.     Begin
  1158.     {$IFDEF WINDOWS}
  1159.       FM^.MsgName := StrPas(FM^.SR.Name);
  1160.     {$ELSE}
  1161.       FM^.MsgName := FM^.SR.Name;
  1162.     {$ENDIF}
  1163.     Val(Copy(FM^.MsgName, 1, Pos('.', FM^.MsgName) - 1), CurrTry, Code);
  1164.     If Code = 0 Then
  1165.       Begin
  1166.       If ((CurrTry >= FM^.CurrMsg) and (CurrTry < BestMatch)) Then
  1167.         Begin
  1168.         BestMatch := CurrTry;
  1169.         MsgWasFound := True;
  1170.         End;
  1171.       End;
  1172.     FindNext(FM^.SR);
  1173.     End;
  1174.   If MsgWasFound Then
  1175.     FM^.CurrMsg := BestMatch
  1176.   Else
  1177.     FM^.CurrMsg := 0;
  1178.   End;
  1179.  
  1180.  
  1181. Procedure FidoMsgObj.SeekPrior;
  1182.   Var
  1183.     Code: Word;
  1184.     BestMatch: LongInt;
  1185.     CurrTry : LongInt;
  1186.     {$IFDEF WINDOWS}
  1187.       TStr: Array[0..128] of Char;
  1188.     {$ENDIF}
  1189.     MsgWasFound: Boolean;
  1190.  
  1191.   Begin
  1192.   CurrTry := 0;
  1193.   MsgWasFound := False;
  1194.   BestMatch := 0;
  1195.   Dec(FM^.CurrMsg);
  1196.   {$IFDEF WINDOWS}
  1197.   StrPCopy(TStr, FM^.NetMailPath + '*.MSG');
  1198.   FindFirst(TStr, faReadOnly + faArchive, FM^.SR);
  1199.   {$ELSE}
  1200.   FindFirst(FM^.NetMailPath + '*.MSG', ReadOnly + Archive, FM^.SR);
  1201.   {$ENDIF}
  1202.   While DosError = 0 Do
  1203.     Begin
  1204.     {$IFDEF WINDOWS}
  1205.       FM^.MsgName := StrPas(FM^.SR.Name);
  1206.     {$ELSE}
  1207.       FM^.MsgName := FM^.SR.Name;
  1208.     {$ENDIF}
  1209.     Val(Copy(FM^.MsgName, 1, Pos('.', FM^.MsgName) - 1), CurrTry, Code);
  1210.     If Code = 0 Then
  1211.       Begin
  1212.       If ((CurrTry <= FM^.CurrMsg) and (CurrTry > BestMatch)) Then
  1213.         Begin
  1214.         BestMatch := CurrTry;
  1215.         MsgWasFound := True;
  1216.         End;
  1217.       End;
  1218.     FindNext(FM^.SR);
  1219.     End;
  1220.   If MsgWasFound Then
  1221.     FM^.CurrMsg := BestMatch
  1222.   Else
  1223.     FM^.CurrMsg := 0;
  1224.   End;
  1225.  
  1226.  
  1227. Function FidoMsgObj.SeekFound: Boolean;
  1228.   Begin
  1229.   SeekFound := FM^.CurrMsg <> 0;
  1230.   End;
  1231.  
  1232.  
  1233. Function FidoMsgObj.GetMsgLoc: LongInt; {Msg location}
  1234.   Begin
  1235.   GetMsgLoc := GetMsgNum;
  1236.   End;
  1237.  
  1238.  
  1239. Procedure FidoMsgObj.SetMsgLoc(ML: LongInt); {Msg location}
  1240.   Begin
  1241.   FM^.CurrMsg := ML;
  1242.   End;
  1243.  
  1244.  
  1245. Procedure FidoMsgObj.YoursFirst(Name: String; Handle: String);
  1246.   Begin
  1247.   FM^.Name := Upper(Name);
  1248.   FM^.Handle := Upper(Handle);
  1249.   FM^.CurrMsg := 0;
  1250.   YoursNext;
  1251.   End;
  1252.  
  1253.  
  1254. Procedure FidoMsgObj.YoursNext;
  1255.   Var
  1256.     FoundDone: Boolean;
  1257.  
  1258.   Begin
  1259.   FoundDone := False;
  1260.   SeekFirst(FM^.CurrMsg + 1);
  1261.   While ((FM^.CurrMsg <> 0) And (Not FoundDone)) Do
  1262.     Begin
  1263.     MsgStartUp;
  1264.     If ((Upper(GetTo) = FM^.Name) Or (Upper(GetTo) = FM^.Handle)) Then
  1265.       FoundDone := True;
  1266.     If IsRcvd Then FoundDone := False;
  1267.     If Not FoundDone Then
  1268.       SeekNext;
  1269.     If Not SeekFound Then
  1270.       FoundDone := True;
  1271.     End;
  1272.   End;
  1273.  
  1274.  
  1275. Function FidoMsgObj.YoursFound: Boolean;
  1276.   Begin
  1277.   YoursFound := SeekFound;
  1278.   End;
  1279.  
  1280.  
  1281. Procedure FidoMsgObj.StartNewMsg;
  1282.   Var
  1283.     Tmp: Array[0..189] of Char;
  1284.  
  1285.   Begin
  1286.   FM^.Error := 0;
  1287.   FM^.TextCtr := 190;
  1288.   FM^.Dest.Zone := 0;
  1289.   FM^.Orig.Zone := 0;
  1290.   FM^.Dest.Point := 0;
  1291.   FM^.Orig.Point := 0;
  1292.   If FM^.TmpOpen Then
  1293.     RemoveTmp
  1294.   Else
  1295.     Begin
  1296.     If FM^.MsgOpen Then
  1297.       Begin
  1298.       If FM^.MsgFile.CloseFile Then
  1299.         FM^.MsgOpen := False;
  1300.       End;
  1301.     End;
  1302.   FM^.TmpName := GetTempName(FM^.NetMailPath);
  1303.   If Length(FM^.TmpName) > 0 Then
  1304.     Begin
  1305.     If FM^.MsgFile.OpenFile(FM^.TmpName, fmReadWrite + fmDenyNone) Then
  1306.       Begin
  1307.       FM^.TmpOpen := True;
  1308.       End
  1309.     Else
  1310.       FM^.Error := 1002;
  1311.     End
  1312.   Else
  1313.     FM^.Error := 1001;
  1314.   If FM^.Error = 0 Then
  1315.     Begin
  1316.     FillChar(Tmp, SizeOf(Tmp), #0);
  1317.     If FM^.MsgFile.SeekFile(0) Then
  1318.       If FM^.MsgFile.BlkWrite(Tmp, SizeOf(Tmp)) Then;
  1319.     End;
  1320.   End;
  1321.  
  1322.  
  1323. Function FidoMsgObj.OpenMsgBase: Word;
  1324.   Begin
  1325.   OpenMsgBase := 0;
  1326.   End;
  1327.  
  1328.  
  1329. Function FidoMsgObj.CloseMsgBase: Word;
  1330.   Begin
  1331.   CloseMsgBase := 0;
  1332.   End;
  1333.  
  1334.  
  1335. Function FidoMsgObj.CreateMsgBase(MaxMsg: Word; MaxDays: Word): Word;
  1336.   Begin
  1337.   CreateMsgBase := 0;
  1338.   End;
  1339.  
  1340.  
  1341. Procedure FidoMsgObj.SetMailType(MT: MsgMailType);
  1342.   Begin
  1343.   End;
  1344.  
  1345.  
  1346. Function FidoMsgObj.GetSubArea: Word;
  1347.   Begin
  1348.   GetSubArea := 0;
  1349.   End;
  1350.  
  1351.  
  1352. Procedure FidoMsgObj.ReWriteHdr;
  1353.   Begin
  1354.   { Not needed, rewrite is automatic when updates are done }
  1355.   End;
  1356.  
  1357.  
  1358. Procedure FidoMsgObj.DeleteMsg;
  1359.   Var
  1360.     TmpFile: File;
  1361.  
  1362.   Begin
  1363.   If FM^.MsgOpen Then
  1364.     If FM^.MsgFile.CloseFile Then
  1365.       FM^.MsgOpen := False;
  1366.   Assign(TmpFile, FM^.NetMailPath + Long2Str(FM^.CurrMsg) + '.MSG');
  1367.   Erase(TmpFile);
  1368.   If IoResult <> 0 Then;
  1369.   End;
  1370.  
  1371.  
  1372. Function FidoMsgObj.NumberOfMsgs: LongInt;
  1373.   Var
  1374.   {$IFDEF WINDOWS}
  1375.     SR: TSearchRec;
  1376.     TStr: Array[0..128] of Char;
  1377.   {$ELSE}
  1378.     SR: SearchRec;
  1379.   {$ENDIF}
  1380.   TmpName: String[13];
  1381.   TmpNum: Word;
  1382.   Code: Word;
  1383.   Active: LongInt;
  1384.  
  1385.   Begin
  1386.   Active := 0;
  1387.   {$IFDEF WINDOWS}
  1388.   StrPCopy(TStr, FM^.NetMailPath + '*.MSG');
  1389.   FindFirst(TStr, faReadOnly + faArchive, SR);
  1390.   {$ELSE}
  1391.   FindFirst(FM^.NetMailPath + '*.MSG', ReadOnly + Archive, SR);
  1392.   {$ENDIF}
  1393.   While DosError = 0 Do
  1394.     Begin
  1395.     {$IFDEF WINDOWS}
  1396.     TmpName :=  StrPas(SR.Name);
  1397.     {$ELSE}
  1398.     TmpName := SR.Name;
  1399.     {$ENDIF}
  1400.     Val(Copy(TmpName, 1,  Pos('.', TmpName) -1), TmpNum, Code);
  1401.     If (Code = 0) Then
  1402.       Inc(Active);
  1403.     FindNext(SR);
  1404.     End;
  1405.   NumberOfMsgs := Active;
  1406.   End;
  1407.  
  1408.  
  1409. Function FidoMsgObj.GetLastRead(UNum: LongInt): LongInt;
  1410.   Var
  1411.     LRec: Word;
  1412.  
  1413.   Begin
  1414.   If ((UNum + 1) * SizeOf(LRec)) >
  1415.   SizeFile(FM^.NetMailPath + 'LastRead') Then
  1416.     GetLastRead := 0
  1417.   Else
  1418.     Begin
  1419.     If LoadFilePos(FM^.NetMailPath + 'LastRead', LRec, SizeOf(LRec),
  1420.     UNum * SizeOf(LRec)) = 0 Then
  1421.       GetLastRead := LRec
  1422.     Else
  1423.       GetLastRead := 0;
  1424.     End;
  1425.   End;
  1426.  
  1427.  
  1428. Procedure FidoMsgObj.SetLastRead(UNum: LongInt; LR: LongInt);
  1429.   Var
  1430.     LRec: Word;
  1431.     Status: Word;
  1432.  
  1433.   Begin
  1434.   If ((UNum + 1) * SizeOf(LRec)) >
  1435.   SizeFile(FM^.NetMailPath + 'LastRead') Then
  1436.     Begin
  1437.     Status := ExtendFile(FM^.NetMailPath + 'LastRead',
  1438.     (UNum + 1) * SizeOf(LRec));
  1439.     End;
  1440.   If LoadFilePos(FM^.NetMailPath + 'LastRead', LRec, SizeOf(LRec),
  1441.   UNum * SizeOf(LRec)) = 0 Then
  1442.     Begin
  1443.     LRec := LR;
  1444.     Status := SaveFilePos(FM^.NetMailPath + 'LastRead', LRec, SizeOf(LRec),
  1445.     UNum * SizeOf(LRec));
  1446.     End;
  1447.   End;
  1448.  
  1449.  
  1450. Function FidoMsgObj.GetTxtPos: LongInt;
  1451.   Begin
  1452.   GetTxtPos := FM^.TextCtr;
  1453.   End;
  1454.  
  1455.  
  1456. Procedure FidoMsgObj.SetTxtPos(TP: LongInt);
  1457.   Begin
  1458.   FM^.TextCtr := TP;
  1459.   End;
  1460.  
  1461.  
  1462. End.
  1463.