Unit MKMsgAbs;       {Abstract Msg Object}

{$I-}
{$IFNDEF OS2}
{$V-,S-,F+,R-,X-,O+}
{$ENDIF}

Interface

Uses
  MKGlobT,
  Objects,
{$IFNDEF WIN32}
  DOS,
{$ENDIF}
  tMisc,
  tGlob;

Type
  AbsMsgObj = Object
    LastSoft, aDir, aHld, aImm, aLock : Boolean;
    C : PCollection;
    CurMsg : LongInt;
    Constructor Init; {Initialize}
    Destructor Done; Virtual; {Done}
    Procedure SetMsgPath (MP: String); Virtual; {Set msg path/other info}
    Function  OpenMsgBase: Word; Virtual; {Open the message base}
    Function  CloseMsgBase: Word; Virtual; {Close the message base}
    Function  CreateMsgBase (MaxMsg: Word; MaxDays: Word): Word; Virtual;
    {Create new message base}
    Function  MsgBaseExists: Boolean; Virtual; {Does msg base exist}
    Function  LockMsgBase: Boolean; Virtual; {Lock the message base}
    Function  UnLockMsgBase: Boolean; Virtual; {Unlock the message base}
    Procedure GetTotalMsgs; Virtual;
    Procedure SetDest (Var Addr: AddrType); Virtual; {Set Zone/Net/Node/Point for Dest}
    Procedure SetOrig (Var Addr: AddrType); Virtual; {Set Zone/Net/Node/Point for Orig}
    Procedure SetFrom (Name: String); Virtual; {Set message from}
    Procedure SetTo (Name: String); Virtual; {Set message to}
    Procedure SetSubj (Str: String); Virtual; {Set message subject}
    Procedure SetCost (SCost: Word); Virtual; {Set message cost}
    Procedure SetRefer (SRefer: LongInt); Virtual; {Set message reference}
    Procedure SetSeeAlso (SAlso: LongInt); Virtual; {Set message see also}
    Procedure SetDate (SDate: String); Virtual; {Set message date}
    Procedure SetTime (STime: String); Virtual; {Set message time}
    Procedure SetLocal (LS: Boolean); Virtual; {Set local status}
    Procedure SetRcvd (RS: Boolean); Virtual; {Set received status}
    Procedure SetPriv (PS: Boolean); Virtual; {Set priveledge vs public status}
    Procedure SetCrash (SS: Boolean); Virtual; {Set crash netmail status}
    Procedure SetKillSent (SS: Boolean); Virtual; {Set kill/sent netmail status}
    Procedure SetSent (SS: Boolean); Virtual; {Set sent netmail status}
    Procedure SetFAttach (SS: Boolean); Virtual; {Set file attach status}
    Procedure SetReqRct (SS: Boolean); Virtual; {Set request receipt status}
    Procedure SetReqAud (SS: Boolean); Virtual; {Set request audit status}
    Procedure SetRetRct (SS: Boolean); Virtual; {Set return receipt status}
    Procedure SetFileReq (SS: Boolean); Virtual; {Set file request status}
    Procedure SetHold (SS: Boolean); Virtual; {Set file hold status}
    Procedure SetDirect (SS: Boolean); Virtual; {Set file direct status}
    Procedure SetImmediate (SS: Boolean); Virtual; {Set immediate status}
    Procedure DoString (Str: String); Virtual; {Add string to message text}
    Procedure DoChar (CH: Char); Virtual; {Add character to message text}
    Procedure DoStringLn (Str: String); Virtual; {Add string and newline to msg text}
    Procedure DoKludgeLn (Str: String); Virtual; {Add ^A kludge line to msg}
    Function  WriteMsg: Word; Virtual; {Write msg to msg base}
    Function  ReWriteMsg: Word; Virtual; {Write msg to msg base}
    Function  GetChar: Char; Virtual; {Get msg text character}
    Function  EOM: Boolean; Virtual; {No more msg text}
    Function  GetString (MaxLen: Word): String; Virtual; {Get wordwrapped string}
    Function  GetNoKludgeStr (MaxLen: Word): String; Virtual; {Get ww str no ^A lines}
    Function  WasWrap: Boolean; Virtual; {Last line was soft wrapped no CR}
    Function  GetFrom: String; Virtual; {Get from name on current msg}
    Function  GetTo: String; Virtual; {Get to name on current msg}
    Function  GetSubj: String; Virtual; {Get subject on current msg}
    Function  GetCost: Word; Virtual; {Get cost of current msg}
    Function  GetDate: String; Virtual; {Get date of current msg}
    Function  GetTime: String; Virtual; {Get time of current msg}
    Function  GetRefer: LongInt; Virtual; {Get reply to of current msg}
    Function  GetSeeAlso: LongInt; Virtual; {Get see also of current msg}
    Function  GetNextSeeAlso: LongInt; Virtual;
    Procedure SetNextSeeAlso (SAlso: LongInt); Virtual;
    Function  GetMsgNum: LongInt; Virtual; {Get message number}
    Procedure GetOrig (Var Addr: AddrType); Virtual; {Get origin address}
    Procedure GetDest (Var Addr: AddrType); Virtual; {Get destination address}
    Function  IsLocal: Boolean; Virtual; {Is current msg local}
    Function  IsCrash: Boolean; Virtual; {Is current msg crash}
    Function  IsKillSent: Boolean; Virtual; {Is current msg kill sent}
    Function  IsSent: Boolean; Virtual; {Is current msg sent}
    Function  IsFAttach: Boolean; Virtual; {Is current msg file attach}
    Function  IsReqRct: Boolean; Virtual; {Is current msg request receipt}
    Function  IsReqAud: Boolean; Virtual; {Is current msg request audit}
    Function  IsRetRct: Boolean; Virtual; {Is current msg a return receipt}
    Function  IsFileReq: Boolean; Virtual; {Is current msg a file request}
    Function  IsRcvd: Boolean; Virtual; {Is current msg received}
    Function  IsPriv: Boolean; Virtual; {Is current msg priviledged/private}
    Function  IsDeleted: Boolean; Virtual; {Is current msg deleted}
    Function  IsEchoed: Boolean; Virtual; {Is current msg unmoved echomail msg}
    Function  IsDirect: Boolean; Virtual; {Is current msg local}
    Function  IsHold: Boolean; Virtual; {Is current msg local}
    Function  IsUns: Boolean; Virtual; {Is current msg unsent}
    Function  IsImmediate: Boolean; Virtual; {Is current msg immediate}
    Function  GetMsgLoc: LongInt; Virtual; {To allow reseeking to message}
    Procedure SetMsgLoc (ML: LongInt); Virtual; {Reseek to message}
    Procedure MsgStartUp; Virtual; {Do message set-up tasks}
    Procedure MsgTxtStartUp; Virtual; {Do message text start up tasks}
    Procedure StartNewMsg; Virtual; {Initialize for adding message}
    Procedure SeekFirst (MsgNum: LongInt); Virtual; {Start msg seek}
    Procedure SeekNext; Virtual; {Find next matching msg}
    Procedure SeekPrior; Virtual; {Prior msg}
    Function  SeekFound: Boolean; Virtual; {Msg was found}
    Procedure YoursFirst (Name: String; Handle: String); Virtual; {Seek your mail}
    Procedure YoursNext; Virtual; {Seek next your mail}
    Function  YoursFound: Boolean; Virtual; {Message found}
    Function  GetHighMsgNum: LongInt; Virtual; {Get highest msg number}
    Procedure SetMailType (MT: MsgMailType); Virtual; {Set message base type}
    Function  GetSubArea: Word; Virtual; {Get sub area number}
    Procedure ReWriteHdr; Virtual; {Rewrite msg header after changes}
    Procedure DeleteMsg (CarePos: Boolean); Virtual; {Delete current message}
    Procedure SetEcho (ES: Boolean); Virtual; {Set echo status}
    Function  NumberOfMsgs: LongInt; Virtual; {Number of messages}
    Function  GetLastRead (UNum: LongInt): LongInt; Virtual; {Get last read for user num}
    Procedure SetLastRead (UNum: LongInt; LR: LongInt); Virtual; {Set last read}
    Function  GetMsgDisplayNum: LongInt; Virtual; {Get msg number to display}
    Function  GetTxtPos: LongInt; Virtual; {Get indicator of msg text position}
    Procedure SetTxtPos (TP: LongInt); Virtual; {Set text position}
    Function  GetHighActiveMsgNum: LongInt; Virtual; {Get highest active msg num}
    Function  GetMsgNumRelative: LongInt; Virtual;
    Function  GetLowMsgNum: LongInt; Virtual;
    Procedure GetDestAddrSmart (Var Addr: AddrType);
    Procedure GetOrigAddrSmart (Var Addr: AddrType);
    Function Num2Relative (Nu: LongInt): LongInt; Virtual;
    Function Relative2Num (N: LongInt): LongInt; Virtual;
  End;

  AbsMsgPtr = ^AbsMsgObj;

Implementation

Constructor AbsMsgObj. Init;
Begin
End;

Destructor AbsMsgObj. Done;
Begin
End;

Procedure AbsMsgObj. SetMsgPath (MP: String);
Begin
End;

Function AbsMsgObj. OpenMsgBase: Word;
Begin
End;

Function AbsMsgObj. CloseMsgBase: Word;
Begin
End;

Function AbsMsgObj. LockMsgBase: Boolean;
Begin
End;

Function AbsMsgObj. UnLockMsgBase: Boolean;
Begin
End;

Procedure AbsMsgObj. SetDest (Var Addr: AddrType);
Begin
End;

Procedure AbsMsgObj. SetOrig (Var Addr: AddrType);
Begin
End;

Procedure AbsMsgObj. SetFrom (Name: String);
Begin
End;

Procedure AbsMsgObj. SetTo (Name: String);
Begin
End;

Procedure AbsMsgObj. SetSubj (Str: String);
Begin
End;

Procedure AbsMsgObj. SetCost (SCost: Word);
Begin
End;

Procedure AbsMsgObj. SetRefer (SRefer: LongInt);
Begin
End;

Procedure AbsMsgObj. SetSeeAlso (SAlso: LongInt);
Begin
End;

Procedure AbsMsgObj. SetDate (SDate: String);
Begin
End;

Procedure AbsMsgObj. SetTime (STime: String);
Begin
End;

Procedure AbsMsgObj. SetLocal (LS: Boolean);
Begin
End;

Procedure AbsMsgObj. SetRcvd (RS: Boolean);
Begin
End;

Procedure AbsMsgObj. SetPriv (PS: Boolean);
Begin
End;

Procedure AbsMsgObj. SetCrash (SS: Boolean);
Begin
End;

Procedure AbsMsgObj. SetImmediate (SS: Boolean);
Begin
  aImm := SS;
End;

Procedure AbsMsgObj. SetKillSent (SS: Boolean);
Begin
End;

Procedure AbsMsgObj. SetSent (SS: Boolean);
Begin
End;

Procedure AbsMsgObj. SetFAttach (SS: Boolean);
Begin
End;

Procedure AbsMsgObj. SetReqRct (SS: Boolean);
Begin
End;

Procedure AbsMsgObj. SetReqAud (SS: Boolean);
Begin
End;

Procedure AbsMsgObj. SetRetRct (SS: Boolean);
Begin
End;

Procedure AbsMsgObj. SetFileReq (SS: Boolean);
Begin
End;

Procedure AbsMsgObj. SetHold (SS: Boolean);
Begin
  aHld := SS;
End;

Procedure AbsMsgObj. SetDirect (SS: Boolean);
Begin
  aDir := SS;
End;

Procedure AbsMsgObj. DoString (Str: String);
Var
  i: Word;

Begin
  For i := 1 To Length (Str) Do DoChar (Str [i]);
End;

Procedure AbsMsgObj. DoChar (CH: Char);
Begin
End;

Procedure AbsMsgObj. DoStringLn (Str: String);
Begin
  DoString (Str);
  DoChar (#13);
End;

Procedure AbsMsgObj. DoKludgeLn (Str: String);
Begin
  If Str [1] <> #1 Then Str := #1 + Str;
  DoStringLn (Str);
End;

Function AbsMsgObj. WriteMsg: Word;
Begin
End;

Function AbsMsgObj. ReWriteMsg: Word;
Begin
End;

Function AbsMsgObj. GetChar: Char;
Begin
End;

Function AbsMsgObj. EOM: Boolean;
Begin
End;

Function AbsMsgObj. GetString (MaxLen: Word): String;
Var
  WPos, OldPos          : LongInt;
  WLen                  : Byte;
  StrDone, StartSoft    : Boolean;
  CurrLen               : Word;
  TmpCh                 : Char;
  Tmp                   : String;

Begin
  Tmp := '';
  If Not EOM Then
  Begin
    StrDone := False;
    CurrLen := 0;
    WPos := GetTxtPos;
    WLen := 0;
    StartSoft := LastSoft;
    LastSoft := True;
    OldPos := GetTxtPos;
    TmpCh := GetChar;

    While ((Not StrDone) And (CurrLen < MaxLen) And (Not EOM)) Do
    Begin
      Case TmpCh Of
        #$00:;
        #$0D: Begin
                StrDone := True;
                LastSoft := False;
              End;
        #$8D:;
        #$0a:;
        #$20: If ((CurrLen <> 0) Or (Not StartSoft)) Then
              Begin
                Inc (CurrLen);
                WLen := CurrLen;
                Tmp [CurrLen] := TmpCh;
                WPos := GetTxtPos;
              End Else
                StartSoft := False;
      Else
        Begin
          Inc (CurrLen);
          Tmp [CurrLen] := TmpCh;
        End;
      End;

      If Not StrDone Then
      Begin
        OldPos := GetTxtPos;
        TmpCh := GetChar;
      End;
    End;

    If StrDone Then SetLength (Tmp, CurrLen) Else
    If EOM Then SetLength (Tmp, CurrLen) Else
    Begin
      If WLen = 0 Then
      Begin
        SetLength (Tmp, CurrLen);
        SetTxtPos (OldPos);
      End Else
      Begin
        SetLength (Tmp, CurrLen);
        SetTxtPos (WPos);
      End;
    End;
  End;
  GetString := Tmp;
End;

Function AbsMsgObj. WasWrap: Boolean;
Begin
  WasWrap := LastSoft;
End;

Procedure AbsMsgObj. SeekFirst (MsgNum: LongInt);
Begin
End;

Procedure AbsMsgObj. SeekNext;
Begin
End;

Function AbsMsgObj. GetFrom: String;
Begin
End;

Function AbsMsgObj. GetTo: String;
Begin
End;

Function AbsMsgObj. GetSubj: String;
Begin
End;

Function AbsMsgObj. GetCost: Word;
Begin
End;

Function AbsMsgObj. GetDate: String;
Begin
End;

Function AbsMsgObj. GetTime: String;
Begin
End;

Function AbsMsgObj. GetRefer: LongInt;
Begin
End;

Function AbsMsgObj. GetSeeAlso: LongInt;
Begin
End;

Function AbsMsgObj. GetMsgNum: LongInt;
Begin
End;

Procedure AbsMsgObj. GetOrig (Var Addr: AddrType);
Begin
End;

Procedure AbsMsgObj. GetDest (Var Addr: AddrType);
Begin
End;

Function AbsMsgObj. IsLocal: Boolean;
Begin
End;

Function AbsMsgObj. IsCrash: Boolean;
Begin
End;

Function AbsMsgObj. IsKillSent: Boolean;
Begin
End;

Function AbsMsgObj. IsSent: Boolean;
Begin
End;

Function AbsMsgObj. IsFAttach: Boolean;
Begin
End;

Function AbsMsgObj. IsReqRct: Boolean;
Begin
End;

Function AbsMsgObj. IsReqAud: Boolean;
Begin
End;

Function AbsMsgObj. IsRetRct: Boolean;
Begin
End;

Function AbsMsgObj. IsFileReq: Boolean;
Begin
End;

Function AbsMsgObj. IsRcvd: Boolean;
Begin
End;

Function AbsMsgObj. IsPriv: Boolean;
Begin
End;

Function AbsMsgObj. IsDeleted: Boolean;
Begin
End;

Function AbsMsgObj. IsEchoed: Boolean;
Begin
End;

Function AbsMsgObj. IsHold: Boolean;
Begin
  IsHold := aHld;
End;

Function AbsMsgObj. IsDirect: Boolean;
Begin
  IsDirect := aDir;
End;

Function AbsMsgObj. IsUns: Boolean;
Begin
  IsUns := False;
End;

Function AbsMsgObj. IsImmediate: Boolean;
Begin
  IsImmediate := aImm;
End;

Function AbsMsgObj. GetMsgLoc: LongInt;
Begin
End;

Procedure AbsMsgObj. SetMsgLoc (ML: LongInt);
Begin
End;

Procedure AbsMsgObj. MsgStartUp;
Begin
End;

Procedure AbsMsgObj. MsgTxtStartUp;
Begin
End;

Procedure AbsMsgObj. YoursFirst (Name: String; Handle: String);
Begin
End;

Procedure AbsMsgObj. YoursNext;
Begin
End;

Function AbsMsgObj. YoursFound: Boolean;
Begin
End;

Function AbsMsgObj. CreateMsgBase (MaxMsg: Word; MaxDays: Word): Word;
Begin
End;

Function AbsMsgObj. MsgBaseExists: Boolean;
Begin
End;

Procedure AbsMsgObj. StartNewMsg;
Begin
  FillChar (aDir, 4, #0);
End;

Function AbsMsgObj. GetHighMsgNum: LongInt;
Begin
  If C^. Count > 0 Then GetHighMsgNum := LongInt (C^. At (C^. Count-1)) Else GetHighMsgNum := 0;
End;

Function AbsMsgObj. SeekFound: Boolean;
Begin
End;

Procedure AbsMsgObj. SetMailType (MT: MsgMailType);
Begin
End;

Function AbsMsgObj. GetSubArea: Word;
Begin
  GetSubArea := 0;
End;

Procedure AbsMsgObj. ReWriteHdr;
Begin
End;

Procedure AbsMsgObj. DeleteMsg (CarePos: Boolean);
Begin
End;

Procedure AbsMsgObj. SetEcho (ES: Boolean);
Begin
End;

Procedure AbsMsgObj. SeekPrior;
Begin
End;

Function AbsMsgObj. NumberOfMsgs: LongInt;
Begin
  NumberOfMsgs := C^. Count;
End;

Function AbsMsgObj. GetLastRead (UNum: LongInt): LongInt;
Begin
End;

Procedure AbsMsgObj. SetLastRead (UNum: LongInt; LR: LongInt);
Begin
End;

Function AbsMsgObj. GetMsgDisplayNum: LongInt;
Begin
  GetMsgDisplayNum := GetMsgNum;
End;

Function AbsMsgObj. GetTxtPos: LongInt;
Begin
  GetTxtPos := 0;
End;

Procedure AbsMsgObj. SetTxtPos (TP: LongInt);
Begin
End;

{SetNextSeeAlso provided by 2:201/623@FidoNet Jonas@iis.bbs.bad.se}

Procedure AbsMsgObj. SetNextSeeAlso (SAlso: LongInt);
Begin
End;

Function AbsMsgObj. GetNextSeeAlso: LongInt;
Begin
  GetNextSeeAlso := 0;
End;

Function  AbsMsgObj. GetNoKludgeStr (MaxLen: Word): String;
{From a suggestion by Johan Corstjens 2:281/610}
Var
  TmpStr        : String;

Begin
  TmpStr := GetString (MaxLen);
  While ((Length (TmpStr) > 0) And (TmpStr [1] = #1) And (Not EOM)) Do TmpStr := GetString (MaxLen);
  GetNoKludgeStr := TmpStr;
End;

Function AbsMsgObj. GetHighActiveMsgNum: LongInt;
Begin
  SeekFirst (GetHighMsgNum);
  If Not SeekFound Then SeekPrior;
  If SeekFound Then
    GetHighActiveMsgNum := GetMsgNum
  Else
    GetHighActiveMsgNum := 0;
End;

Function AbsMsgObj. GetMsgNumRelative: LongInt;
Begin
  GetMsgNumRelative := GetMsgNum;
End;

Function AbsMsgObj. GetLowMsgNum: LongInt;
Begin
  If C^. Count > 0 Then GetLowMsgNum := LongInt (C^. At (0)) Else GetLowMsgNum := 0;
End;

Procedure AbsMsgObj. GetTotalMsgs;
Begin
End;

Procedure AbsMsgObj. GetDestAddrSmart (Var Addr: AddrType);
Var
  TmpStr        : String [79];

Begin
  FillChar (Addr, SizeOf (Addr), #0);
  GetDest (Addr);

  MsgTxtStartUp;

  While Not EOM Do
  Begin
    TmpStr := GetString (79);

    If Copy (TmpStr, 1, 6) = #1'TOPT ' Then
    Begin
      Addr. Point := Str2Long (ExtractWord (2, Trim (TmpStr), [' ']));
      Exit;
    End;
  End;
End;

Procedure AbsMsgObj. GetOrigAddrSmart (Var Addr: AddrType);
Var
  TmpStr, S       : String [79];
  Found, AllFound : Boolean;
  oAddr           : AddrType;
  Point, k        : LongInt;

Begin
  FillChar (Addr, SizeOf (Addr), #0);
  FillChar (aDir, 4, #0);
  Found := False;
  AllFound := False;
  Point := 0;

  MsgTxtStartUp;

  While Not EOM Do
  Begin
    TmpStr := GetString (79);

    If Copy (TmpStr, 1, 7) = #1'FLAGS ' Then
    Begin
      TmpStr := Copy (TmpStr, 8, 255);
      For k := 1 To WordCount (TmpStr, [' ', ',']) Do
      Begin
        S := UpString (ExtractWord (k, TmpStr, [' ', ',']));
        aDir  := (S = 'DIR') or aDir;
        aHld  := (S = 'HLD') or aHld;
        aImm  := (S = 'IMM') or aImm;
        aLock := (S = 'LOK') or aLock;
      End;
      If AllFound Then Exit Else Continue;
    End Else
    If Not AllFound Then
    If Copy (TmpStr, 1, 6) = #1'INTL ' Then
    Begin
      ParseStrAddr (ExtractWord (3, Trim (TmpStr), [' ']), Addr);
      If Point <> 0 Then Addr. Point := Point;
      If Found Then AllFound := True;
      Found := True;
    End Else
    If Copy (TmpStr, 1, 6) = #1'FMPT ' Then
    Begin
      Point := Str2Long (ExtractWord (2, Trim (TmpStr), [' ']));
      Addr. Point := Point;
      If Found Then AllFound := True;
      Found := True;
    End Else
    If Copy (TmpStr, 1, 8) = #1'MSGID: ' Then
    Begin
      oAddr := Addr;
      ParseStrAddr (ExtractWord (2, Trim (TmpStr), [' ']), Addr);
      If (Addr. Zone = 0) And (Addr. Net = 0) And
         (Addr. Node = 0) And (Addr. Point = 0)
      Then Addr := oAddr
      Else AllFound := True;
    End Else
    If Copy (TmpStr, 1, 11) = ' * Origin: ' Then
    Begin
      TmpStr := ExtractWord (WordCount (TmpStr, ['(', ')']), TmpStr, ['(', ')']);
      If WordCount (TmpStr, [' ']) > 1 Then
        TmpStr := ExtractWord (WordCount (TmpStr, [' ']), TmpStr, [' ']);
      ParseStrAddr (Trim (TmpStr), Addr);
      AllFound := True;
    End;
  End;

  If Not AllFound Then GetOrig (Addr);
End;

Function AbsMsgObj. Num2Relative (Nu: LongInt): LongInt;
Const
  tNum : LongInt = 0;
  N : LongInt = 0;

Var
  pl : Pointer;

Function Matches (plz : Pointer): Boolean; Far;
Begin
  Inc (tNum);
  Matches := (plz <> nil) and (LongInt (plz) = N);
End;

Begin
  N := Nu;
  pl := nil; tNum := 0;
  pl := C^. FirstThat (@Matches);
  If pl <> nil Then Num2Relative := tNum Else Num2Relative := 0;
End;

Function AbsMsgObj. Relative2Num (N: LongInt): LongInt;
Begin
  If (N > 0) and (N <= C^. Count) Then N := LongInt (C^. At (N-1)) Else N := 0;
  Relative2Num := N;
End;

End.