//  This may look like C code, but it is really -*- C++ -*-

//  ------------------------------------------------------------------
//  The Goldware Library
//  Copyright (C) 1990-1999 Odinn Sorensen
//  Copyright (C) 1999-2000 Alexander S. Aganichev
//  ------------------------------------------------------------------
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Library General Public License for more details.
//
//  You should have received a copy of the GNU Library General Public
//  License along with this program; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
//  MA 02111-1307, USA
//  ------------------------------------------------------------------
//  $Id$
//  ------------------------------------------------------------------
//  JAM msgbase definitions and structures.
//  ------------------------------------------------------------------
//  This implementation is based on information in the document
//  JAM-001, revision 001, dated 93-07-01 and the associated example
//  "JAM API". Here is the JAM copyright notice:
//
//  "JAM(mbp) - Copyright 1993 Joaquim Homrighausen, Andrew Milner,
//                             Mats Birch, Mats Wallin.
//                             ALL RIGHTS RESERVED."
//  ------------------------------------------------------------------


//  ------------------------------------------------------------------
//  Only include once!

#ifndef __GM_JAMM_H
#define __GM_JAMM_H


//  ------------------------------------------------------------------

#include <gmoarea.h>


//  ------------------------------------------------------------------

#if defined(GOLD_CANPACK)
    #pragma pack(1)
#endif


//  ------------------------------------------------------------------
//  JAM constants

#define JAM_REVISION    1
#define JAM_SIGNATURE   "JAM\0"
#define JAM_MAXDATLEN   100


//  ------------------------------------------------------------------
//  Message status bits

#define JAMATTR_LOCAL       0x00000001L    // Msg created locally
#define JAMATTR_INTRANSIT   0x00000002L    // Msg is in-transit
#define JAMATTR_PRIVATE     0x00000004L    // Private
#define JAMATTR_READ        0x00000008L    // Read by addressee
#define JAMATTR_SENT        0x00000010L    // Sent to remote
#define JAMATTR_KILLSENT    0x00000020L    // Kill when sent
#define JAMATTR_ARCHIVESENT 0x00000040L    // Archive when sent
#define JAMATTR_HOLD        0x00000080L    // Hold for pick-up
#define JAMATTR_CRASH       0x00000100L    // Crash
#define JAMATTR_IMMEDIATE   0x00000200L    // Send Msg now, ignore restrictions
#define JAMATTR_DIRECT      0x00000400L    // Send directly to destination
#define JAMATTR_GATE        0x00000800L    // Send via gateway
#define JAMATTR_FILEREQUEST 0x00001000L    // File request
#define JAMATTR_FILEATTACH  0x00002000L    // File(s) attached to Msg
#define JAMATTR_TRUNCFILE   0x00004000L    // Truncate file(s) when sent
#define JAMATTR_KILLFILE    0x00008000L    // Delete file(s) when sent
#define JAMATTR_RECEIPTREQ  0x00010000L    // Return receipt requested
#define JAMATTR_CONFIRMREQ  0x00020000L    // Confirmation receipt requested
#define JAMATTR_ORPHAN      0x00040000L    // Unknown destination
#define JAMATTR_ENCRYPT     0x00080000L    // Msg text is encrypted
#define JAMATTR_COMPRESS    0x00100000L    // Msg text is compressed
#define JAMATTR_ESCAPED     0x00200000L    // Msg text is seven bit ASCII
#define JAMATTR_FPU         0x00400000L    // Force pickup
#define JAMATTR_TYPELOCAL   0x00800000L    // Msg is for local use only (not for export)
#define JAMATTR_TYPEECHO    0x01000000L    // Msg is for conference distribution
#define JAMATTR_TYPENET     0x02000000L    // Msg is direct network mail
#define JAMATTR_NODISP      0x20000000L    // Msg may not be displayed to user
#define JAMATTR_LOCKED      0x40000000L    // Msg is locked, no editing possible
#define JAMATTR_DELETED     0x80000000L    // Msg is deleted


//  ------------------------------------------------------------------
//  Message header subfield types

#define JAMSUB_OADDRESS               0
#define JAMSUB_DADDRESS               1
#define JAMSUB_SENDERNAME             2
#define JAMSUB_RECEIVERNAME           3
#define JAMSUB_MSGID                  4
#define JAMSUB_REPLYID                5
#define JAMSUB_SUBJECT                6
#define JAMSUB_PID                    7
#define JAMSUB_TRACE                  8
#define JAMSUB_ENCLOSEDFILE           9
#define JAMSUB_ENCLOSEDFILEWALIAS    10
#define JAMSUB_ENCLOSEDFREQ          11
#define JAMSUB_ENCLOSEDFILEWCARD     12
#define JAMSUB_ENCLOSEDINDIRECFILE   13
#define JAMSUB_EMBINDAT            1000
#define JAMSUB_FTSKLUDGE           2000
#define JAMSUB_SEENBY2D            2001
#define JAMSUB_PATH2D              2002
#define JAMSUB_FLAGS               2003
#define JAMSUB_TZUTCINFO           2004

#define JAMSUB_OADDRESS_LEN                      100
#define JAMSUB_DADDRESS_LEN                      100
#define JAMSUB_SENDERNAME_LEN                    100
#define JAMSUB_RECEIVERNAME_LEN                  100
#define JAMSUB_MSGID_LEN                         100
#define JAMSUB_REPLYID_LEN                       100
#define JAMSUB_SUBJECT_LEN                       100
#define JAMSUB_PID_LEN                            40
#define JAMSUB_TRACE_LEN               ((uint32_t)(-1))
#define JAMSUB_ENCLOSEDFILE_LEN        ((uint32_t)(-1))
#define JAMSUB_ENCLOSEDFILEWALIAS_LEN  ((uint32_t)(-1))
#define JAMSUB_ENCLOSEDFREQ_LEN        ((uint32_t)(-1))
#define JAMSUB_ENCLOSEDFILEWCARD_LEN   ((uint32_t)(-1))
#define JAMSUB_ENCLOSEDINDIRECFILE_LEN ((uint32_t)(-1))
#define JAMSUB_EMBINDAT_LEN            ((uint32_t)(-1))
#define JAMSUB_FTSKLUDGE_LEN                     255
#define JAMSUB_SEENBY2D_LEN            ((uint32_t)(-1))
#define JAMSUB_PATH2D_LEN              ((uint32_t)(-1))
#define JAMSUB_FLAGS_LEN               ((uint32_t)(-1))
#define JAMSUB_TZUTCINFO_LEN           ((uint32_t)(-1))


//  ------------------------------------------------------------------
//  .JHR file header

struct JamHdrInfo
{

    char    signature[4];     // <J><A><M> followed by <NUL>
    time32_t  datecreated;      // Creation date
    uint32_t   modcounter;       // Update counter
    uint32_t   activemsgs;       // Number of active (not deleted) msgs
    uint32_t   passwordcrc;      // CRC-32 of password to access
    uint32_t   basemsgnum;       // Lowest message number in index file
    uint32_t   highwatermark;    // Number of the last msg scanned
    byte    reserved[996];    // Reserved space
};


//  ------------------------------------------------------------------
//  .JHR message headers

struct JamHdr
{

    char    signature[4];   // <J><A><M> followed by <NUL>
    word    revision;       // Revision level of header
    word    reservedword;   // Reserved for future use
    uint32_t   subfieldlen;    // Length of subfields
    uint32_t   timesread;      // Number of times message read
    uint32_t   msgidcrc;       // CRC-32 of MSGID line
    uint32_t   replycrc;       // CRC-32 of REPLY line
    uint32_t   replyto;        // This msg is a reply to..
    uint32_t   reply1st;       // First reply to this msg
    uint32_t   replynext;      // Next msg in reply chain
    time32_t  datewritten;    // When msg was written
    time32_t  datereceived;   // When msg was read by recipient
    time32_t  dateprocessed;  // When msg was processed by tosser/scanner
    uint32_t   messagenumber;  // Message number (1-based)
    uint32_t   attribute;      // Msg attribute, see "Msg Attributes"
    uint32_t   attribute2;     // Reserved for future use
    uint32_t   offset;         // Offset of text in ????????.JDT file
    uint32_t   txtlen;         // Length of message text
    uint32_t   passwordcrc;    // CRC-32 of password to access message
    uint32_t   cost;           // Cost of message
};


//  ------------------------------------------------------------------
//  .JHR subfield headers

struct JamSubFieldHdr
{

    word  loid;       // Field ID, 0-65535
    word  hiid;       // Reserved for future use
    uint32_t datlen;     // Length of buffer that follows
};


//  ------------------------------------------------------------------
//  .JHR subfields

struct JamSubField
{

    word  loid;         // Field ID, 0-65535
    word  hiid;         // Reserved for future use
    uint32_t datlen;       // Length of buffer that follows
    char  buffer[101];  // DATLEN bytes of data
};


//  ------------------------------------------------------------------
//  .JDX message index

struct JamIndex
{

    dword  usercrc;    // CRC-32 of destination username
    uint32_t  hdroffset;  // Offset of header in .JHR file
};


//  ------------------------------------------------------------------
//  .JLR lastread records

struct JamLast
{

    dword  usercrc;    // CRC-32 of user name (lowercase)
    dword  userid;     // Unique UserID
    dword  lastread;   // Last read message number
    dword  highread;   // Highest read message number
};


//  ------------------------------------------------------------------

#if defined(GOLD_CANPACK)
    #pragma pack()
#endif


//  ------------------------------------------------------------------

struct JamData
{
    int fhjhr;
    int fhjdt;
    int fhjdx;
    int fhjlr;
    int fhjhw;             // highwater if available
    int islocked;          // Area is locked?
    int timesposted;
    int32_t lastpos;          // Lastread position
    int32_t highwater;
    JamLast lastrec;       // .JLR Lastread record
    JamHdrInfo hdrinfo;    // .JHR Header info record
};


//  ------------------------------------------------------------------

struct JamWide
{
    dword usercrc;
    dword userid;
    int lookreplies;
    const char* jampath;
    int harddelete;
    int smapihw;
};


//  ------------------------------------------------------------------

class JamArea : public gmo_area
{

protected:

    JamData* data;
    JamWide* wide;

    int just_scanning;

    void data_open();
    void data_close();

    void open_area();

    void raw_open();
    void raw_close();

    void save_lastread();

    int test_open(const char* file);

    void raw_scan(int __keep_index, int __scanpm=false);

    int load_message(int __mode, gmsg* __msg, JamHdr& __hdr);

    void add_subfield(JamHdr& __hdr, byte*& __subfield, word __loid, word __hiid, char* __data, uint32_t maxlen);

    void save_message(int __mode, gmsg* __msg, JamHdr& __hdr);

public:

    JamArea()
    {
        wide = NULL;
        data = NULL;
        just_scanning = false;
    }
    virtual ~JamArea() {}

    virtual bool issoftdelete() const
    {
        return (wide != NULL) ? not wide->harddelete : true;
    }

    //  ----------------------------------------------------------------
    //  Messagebase member functions

    void open();
    void close();

    void suspend();
    void resume();

    void lock();
    void unlock();

    void scan();
    void scan_area();
    void scan_area_pm();

    int load_hdr(gmsg* msg);
    int load_msg(gmsg* msg);

    void save_hdr(int mode, gmsg* msg);
    void save_msg(int mode, gmsg* msg);

    void del_msg(gmsg* msg);

    void new_msgno(gmsg* msg);
    char* user_lookup(char* lookfor);
    int renumber();

    void update_timesread(gmsg* msg);

    Line* make_dump_msg(Line*& lin, gmsg* msg, char* lng_head);
};


//  ------------------------------------------------------------------

extern JamWide* jamwide;
extern JamData* jamdata;
extern int      jamdatano;


//  ------------------------------------------------------------------

char *jamstrlwr(char *str);


//  ------------------------------------------------------------------

#endif

//  ------------------------------------------------------------------

