/*
* $Id: wvclass.h 1.8 1997/03/18 19:30:04 dumoulin Exp $
 */

/*
 *
 *  WinVN C++ class definitions
 *
 */

#ifndef WVCLASS_H
#define WVCLASS_H

//#define WHEREAMI(s) TRACE3("TRACE %s: Executing %s, line %d\n", s, __FILE__, __LINE__)

//#define DEBUGMEMUSAGE  1 // detailed memory mgmt debug info
//#define DEBUGFREEALLOC 1

#define POOLBLOCKSIZE 16384


// C++ Implementation of aligned memory pool class of varying size

struct NewStruct
{
#ifdef DEBUGMEMUSAGE
  uint32 iSeqCtr;
#endif
  //int16 iUsedSize;
 // int16 iAllocSize;     // JD 1/7/97 16 bits too small
  UINT_PTR iAllocSize;	  //32 or 64bits
  UINT_PTR rootBlk;
}ALIGNED;

#ifdef __WATCOMC__
 void *operator new(UINT_PTR iReqSize);
 void *operator new [] (UINT_PTR iReqSize);
#ifdef _WIN32
 void *operator new(UINT_PTR ReqSize1, unsigned long lReqSize);
 void *operator new [] (UINT_PTR ReqSize1, unsigned long lReqSize);
#else
 void *operator new(UINT_PTR ReqSize1, unsigned long lReqSize);
 void *operator new [] (UINT_PTR ReqSize1, unsigned long lReqSize);
#endif
#endif

class WMemPool // 335
{
public:  // member functions
  WMemPool(uint32 uElementSize, unsigned uNumElements);
  inline void* AllocElement();
  inline void FreeElement(void*p);
  ~WMemPool();
private:
  void AllocBlock();

private:  // data
  unsigned m_uElmSize; // do not change the order of these
  unsigned m_uBlkSize; // two declarations (see constructor)
  struct MemPoolElement
  {
		MemPoolElement* next;
  }ALIGNED;
  struct MemPoolBlock
  {
    MemPoolBlock*next;
    MemPoolElement pe;
  }ALIGNED;
  MemPoolElement* m_FreeList;
  MemPoolBlock* m_pBlock;
}ALIGNED;


inline void* WMemPool::AllocElement()
{ 
#ifdef DEBUGFREEALLOC
    char * pch;
    char * p1;
#endif

    if(!m_FreeList)
    {
		AllocBlock();
    }

    MemPoolElement* pe = m_FreeList;
    if(pe)
    {
#ifdef DEBUGFREEALLOC
		pch = ((char *) pe + m_uElmSize );
		if (*pch != 'F' ) 
		{
			*pch = '\0';
			p1 = (char *)pe;
			p1 += sizeof(pe->next); 
			WVArgMessageBox (NULL, IDS_WVCLASS_ALLOC, IDS_WVCLASS_ERROR, MB_OK | MB_ICONHAND, p1);
		}
		*pch = 'U';
#endif

		m_FreeList = pe->next;
	}
	return pe;
}


inline void WMemPool::FreeElement(void*p)
{
#ifdef DEBUGFREEALLOC
	char * pch;
	char * p1;
#endif


  if(p)
  {
    
     MemPoolElement*pe = (MemPoolElement*)p;
#ifdef DEBUGFREEALLOC
     pch = ((char *) pe + m_uElmSize );
     if (*pch != 'U' ) 
	 {
		*pch = '\0';
		p1 = (char *)pe;
		p1 += sizeof(pe->next); 
		WVArgMessageBox (NULL, IDS_WVCLASS_FREE, IDS_WVCLASS_ERROR, MB_OK | MB_ICONHAND, p1);
		return; /* don't free twice because this breaks memory handling */
     }
     *pch = 'F';
#endif
     pe->next = m_FreeList;
     m_FreeList = pe;
 }
#ifdef DEBUGMEMUSAGE
  else
    DEBUG_BREAK;
#endif
}

class WVString
{
protected:
  char*m_data;
private:
  static WMemPool m_ClassPool;
public:
  WVString(const char*s=0, const uint32 uLen = 0);
  WVString(const WVString&rhs);
  WVString(const WVString&lhs, const WVString&rhs);
  ~WVString();
  void*operator new(UINT_PTR size);
  void operator delete(void*p);
  WVString& operator=(const WVString& rhs);
  WVString& operator=(const char* rhs);
  WVString& operator+=(const WVString& rhs);
  WVString& operator+=(const char* rhs);
  inline operator const char*()const  // (const char*) cast
  { return m_data;}
  
  //inline char operator[](int idx) const //         c = s[idx]; (rvalue/value)
  //{ return m_data[idx];}
  
  inline const char& operator[](int idx) const //  c = s[idx]; (rvalue/ref)
  { return idx >= 0 ? m_data[idx] : m_data[0];}
  
  inline char& operator[](int idx)      //         s[idx] = c; (lvalue)
  { return idx >= 0 ? m_data[idx] : m_data[0];}
  
  // unsigned Length() const;
  friend BOOL operator ==(const WVString& lhs, const WVString& rhs);
  friend BOOL operator !=(const WVString& lhs, const WVString& rhs);
  friend WVString operator+(const WVString& lhs, const WVString& rhs);
  friend WVString operator+(const WVString& lhs, const char* rhs);
  friend WVString operator+(const char* lhs, const WVString& rhs);

  char *MakeBuffer(UINT_PTR size);

protected:
  UINT_PTR AllocSize();
}ALIGNED;

#ifdef JAPANESE
#define stringwithsize(size)  new WVString("", size)
#endif

inline BOOL operator ==(const WVString& lhs, const WVString& rhs)
{ return strcmp(lhs.m_data, rhs.m_data) == 0;}

inline BOOL operator !=(const WVString& lhs, const WVString& rhs)
{ return !(lhs == rhs);}

inline WVString operator+(const WVString& lhs, const WVString& rhs)
{ return WVString(lhs, rhs);}

inline WVString operator+(const WVString& lhs, const char* rhs)
{ return WVString(lhs, WVString(rhs));}

inline WVString operator+(const char* lhs, const WVString& rhs)
{ return WVString(WVString(lhs), rhs);}

class WVSubjString : public WVString
{
public:
	WVSubjString(const char*s=0, const uint32 uLen = 0) : nFile(-1), nTotal(-1), 
			nGroup(-1), nGroupTotal(-1), bProcessed(false) ,WVString(s, uLen) {};

	const char *ParseFilename();
	int GetPart() { return nFile; };
	int GetTotal() { return nTotal; };
	int GetGroupPart() { return nGroup; };
	int GetGroupTotal() { return nGroupTotal; };

protected:

	int nFile;
	int nTotal;
	int nGroup;
	int nGroupTotal;
	bool bProcessed;
	WVString m_filename;
	
};


class WVPersBOOL  // persistent BOOL class
{
private:
  static WMemPool m_ClassPool;
protected:
  BOOL m_bModified;
  BOOL m_bDefault;
  WVString m_sSection;
  WVString m_sKey;
  BOOL m_bValue;
public:
  WVPersBOOL(const char*sGroup, const char*sSection, BOOL bDefault = FALSE);
  ~WVPersBOOL();
  void Clear() { m_bModified = FALSE; m_bValue = m_bDefault;  };
  inline void*operator new(UINT_PTR )
  { return m_ClassPool.AllocElement(); }
  inline void operator delete(void*p)
  { m_ClassPool.FreeElement(p); }
  WVPersBOOL& operator=(const WVPersBOOL& rhs);
  WVPersBOOL& operator=(const BOOL rhs);
  WVPersBOOL& operator|=(const BOOL rhs);
  WVPersBOOL& operator&=(const BOOL rhs);
  inline operator const BOOL()const  // const BOOL cast
  { return m_bValue;}
private:
  WVPersBOOL();             // not implemented
  WVPersBOOL(const char*s); // not implemented
}ALIGNED;


class WVHeaderData
{
private:
  static WMemPool m_ClassPool;
public:
  unsigned long iGroups;
  time_t date;
/* Ray Dunn:99/10: added datetime arg for date sorting */
  struct tm datetime;
  WVSubjString sSubject;
  WVString sFrom;
  WVString sEmail;
  WVString sMessage_id;
  WVString sBest_ref;
  WVString sFrob_ref_list;
  WVString sNewsgroups;
  WVString sNNTPPostHost;
public:
  WVHeaderData(unsigned long i=0, time_t t=0) : iGroups(i), date(t) {}
  inline void*operator new(UINT_PTR )
	{ return m_ClassPool.AllocElement(); }
  inline void operator delete(void*p)
	{ m_ClassPool.FreeElement(p); }
}ALIGNED;

/* the size of this struct *must* be a power of two for win16.  'huge' */
/* arrays require this. */
/* (4 4 4 2 1 1) => 16 */

typedef struct {
  TypDoc *ArtDoc;
  WVHeaderData *pHD;
  BIGINT number;		//article #
  unsigned int lines;
  unsigned int bytes;
  char SeenSelected;
  char thread_depth;
} ALIGNED TypHeader;


typedef TypHeader *header_p;


typedef struct LATESTSTRUCT {
  unsigned int lines;
  unsigned int bytes;
  unsigned int iGroups;
  WVString sFrom;
  WVString sEmail;
  WVString sSubject;
  WVString sMessage_id;
  WVString sNewsgroups;
  WVString sNNTPPostHost;
  WVString sXFace;
  WVString sFace;
  unsigned char cAddWrap;
} ALIGNED LATEST;


extern LATEST Latest;

// Action/Killfile constants
#define AA_NOACTION_MASK               1
#define AA_LT_MASK                     2
#define AA_EQ_MASK                     3
#define AA_GT_MASK                     4
#define AA_IS_MASK                     5
#define AA_CONTAINS_MASK               6
#define AA_PATTERN_MASK                7
#define AA_NOTPATTERN_MASK             8
#define AA_SELECT_MASK            0x1000
#define AA_KILL_MASK              0x2000
#define AA_MODULO                 0x0010

#define NO_ACTION                      1
#define MARK_SEEN_ART_LINES_BASE       1 * AA_MODULO  // 0x10/16
#define MARK_SEEN_ART_LINES_LT          MARK_SEEN_ART_LINES_BASE + AA_LT_MASK
#define MARK_SEEN_ART_LINES_EQ          MARK_SEEN_ART_LINES_BASE + AA_EQ_MASK
#define MARK_SEEN_ART_LINES_GT          MARK_SEEN_ART_LINES_BASE + AA_GT_MASK
#define MARK_SEEN_ART_GROUPS_BASE      2 * AA_MODULO  // 0x20/32
#define MARK_SEEN_ART_GROUPS_LT         MARK_SEEN_ART_GROUPS_BASE + AA_LT_MASK
#define MARK_SEEN_ART_GROUPS_EQ         MARK_SEEN_ART_GROUPS_BASE + AA_EQ_MASK
#define MARK_SEEN_ART_GROUPS_GT         MARK_SEEN_ART_GROUPS_BASE + AA_GT_MASK
#define MARK_SEEN_ART_FROM_BASE        3 * AA_MODULO  // 0x30/48
#define MARK_SEEN_ART_FROM_IS           MARK_SEEN_ART_FROM_BASE + AA_IS_MASK
#define MARK_SEEN_ART_FROM_CONTAINS     MARK_SEEN_ART_FROM_BASE + AA_CONTAINS_MASK
#define MARK_SEEN_ART_FROM_PATTERN      MARK_SEEN_ART_FROM_BASE + AA_PATTERN_MASK
#define MARK_SEEN_ART_FROM_NOTPATTERN      MARK_SEEN_ART_FROM_BASE + AA_NOTPATTERN_MASK
#define MARK_SEEN_ART_EMAIL_BASE       4 * AA_MODULO  // 0x40/64
#define MARK_SEEN_ART_EMAIL_IS          MARK_SEEN_ART_EMAIL_BASE + AA_IS_MASK
#define MARK_SEEN_ART_EMAIL_CONTAINS    MARK_SEEN_ART_EMAIL_BASE + AA_CONTAINS_MASK
#define MARK_SEEN_ART_EMAIL_PATTERN     MARK_SEEN_ART_EMAIL_BASE + AA_PATTERN_MASK
#define MARK_SEEN_ART_EMAIL_NOTPATTERN     MARK_SEEN_ART_EMAIL_BASE + AA_NOTPATTERN_MASK
#define MARK_SEEN_ART_SUBJ_BASE        5 * AA_MODULO  // 0x50/80
#define MARK_SEEN_ART_SUBJ_IS           MARK_SEEN_ART_SUBJ_BASE + AA_IS_MASK
#define MARK_SEEN_ART_SUBJ_CONTAINS     MARK_SEEN_ART_SUBJ_BASE + AA_CONTAINS_MASK
#define MARK_SEEN_ART_SUBJ_PATTERN     MARK_SEEN_ART_SUBJ_BASE +  AA_PATTERN_MASK
#define MARK_SEEN_ART_SUBJ_NOTPATTERN     MARK_SEEN_ART_SUBJ_BASE +  AA_NOTPATTERN_MASK
#define MARK_SEEN_ART_MSGID_BASE       6 * AA_MODULO  // 0x60/96
#define MARK_SEEN_ART_MSGID_IS          MARK_SEEN_ART_MSGID_BASE + AA_IS_MASK
#define MARK_SEEN_ART_MSGID_CONTAINS    MARK_SEEN_ART_MSGID_BASE + AA_CONTAINS_MASK
#define MARK_SEEN_ART_MSGID_PATTERN     MARK_SEEN_ART_MSGID_BASE + AA_PATTERN_MASK
#define MARK_SEEN_ART_MSGID_NOTPATTERN     MARK_SEEN_ART_MSGID_BASE + AA_NOTPATTERN_MASK
#define MARK_SEEN_ART_REF_BASE         7 * AA_MODULO  // 0x70/112
//#define MARK_SEEN_ART_REF_IS            MARK_SEEN_ART_REF_BASE + AA_IS_MASK
#define MARK_SEEN_ART_REF_CONTAINS      MARK_SEEN_ART_REF_BASE + AA_CONTAINS_MASK
#define MARK_SEEN_NGROUP_BASE          8 * AA_MODULO  // 0x80/128
//#define MARK_SEEN_NGROUP_IS             MARK_SEEN_NGROUP_BASE + AA_IS_MASK
#define MARK_SEEN_NGROUP_CONTAINS       MARK_SEEN_NGROUP_BASE + AA_CONTAINS_MASK

#define MARK_SEEN_ART_HOST_BASE        9 * AA_MODULO // 0x90/144
#define MARK_SEEN_ART_HOST_IS			MARK_SEEN_ART_HOST_BASE + AA_IS_MASK
#define MARK_SEEN_ART_HOST_CONTAINS	    MARK_SEEN_ART_HOST_BASE + AA_CONTAINS_MASK
#define MARK_SEEN_ART_HOST_PATTERN      MARK_SEEN_ART_HOST_BASE + AA_PATTERN_MASK
#define MARK_SEEN_ART_HOST_NOTPATTERN      MARK_SEEN_ART_HOST_BASE + AA_NOTPATTERN_MASK

#define SELECT_ART_LINES_BASE           AA_SELECT_MASK + MARK_SEEN_ART_LINES_BASE
#define SELECT_ART_LINES_LT             AA_SELECT_MASK + MARK_SEEN_ART_LINES_LT
#define SELECT_ART_LINES_EQ             AA_SELECT_MASK + MARK_SEEN_ART_LINES_EQ
#define SELECT_ART_LINES_GT             AA_SELECT_MASK + MARK_SEEN_ART_LINES_GT
#define SELECT_ART_GROUPS_BASE          AA_SELECT_MASK + MARK_SEEN_ART_GROUPS_BASE
#define SELECT_ART_GROUPS_LT            AA_SELECT_MASK + MARK_SEEN_ART_GROUPS_LT
#define SELECT_ART_GROUPS_EQ            AA_SELECT_MASK + MARK_SEEN_ART_GROUPS_EQ
#define SELECT_ART_GROUPS_GT            AA_SELECT_MASK + MARK_SEEN_ART_GROUPS_GT
#define SELECT_ART_FROM_BASE            AA_SELECT_MASK + MARK_SEEN_ART_FROM_BASE
#define SELECT_ART_FROM_IS              AA_SELECT_MASK + MARK_SEEN_ART_FROM_IS
#define SELECT_ART_FROM_CONTAINS        AA_SELECT_MASK + MARK_SEEN_ART_FROM_CONTAINS
#define SELECT_ART_FROM_PATTERN         AA_SELECT_MASK + MARK_SEEN_ART_FROM_PATTERN
#define SELECT_ART_FROM_NOTPATTERN         AA_SELECT_MASK + MARK_SEEN_ART_FROM_NOTPATTERN
#define SELECT_ART_EMAIL_BASE           AA_SELECT_MASK + MARK_SEEN_ART_EMAIL_BASE
#define SELECT_ART_EMAIL_IS             AA_SELECT_MASK + MARK_SEEN_ART_EMAIL_IS
#define SELECT_ART_EMAIL_CONTAINS       AA_SELECT_MASK + MARK_SEEN_ART_EMAIL_CONTAINS
#define SELECT_ART_EMAIL_PATTERN        AA_SELECT_MASK + MARK_SEEN_ART_EMAIL_PATTERN
#define SELECT_ART_EMAIL_NOTPATTERN        AA_SELECT_MASK + MARK_SEEN_ART_EMAIL_NOTPATTERN
#define SELECT_ART_SUBJ_BASE            AA_SELECT_MASK + MARK_SEEN_ART_SUBJ_BASE
#define SELECT_ART_SUBJ_IS              AA_SELECT_MASK + MARK_SEEN_ART_SUBJ_IS
#define SELECT_ART_SUBJ_CONTAINS        AA_SELECT_MASK + MARK_SEEN_ART_SUBJ_CONTAINS
#define SELECT_ART_SUBJ_PATTERN         AA_SELECT_MASK + MARK_SEEN_ART_SUBJ_PATTERN
#define SELECT_ART_SUBJ_NOTPATTERN         AA_SELECT_MASK + MARK_SEEN_ART_SUBJ_NOTPATTERN
#define SELECT_ART_MSGID_BASE           AA_SELECT_MASK + MARK_SEEN_ART_MSGID_BASE
#define SELECT_ART_MSGID_IS             AA_SELECT_MASK + MARK_SEEN_ART_MSGID_IS
#define SELECT_ART_MSGID_CONTAINS       AA_SELECT_MASK + MARK_SEEN_ART_MSGID_CONTAINS
#define SELECT_ART_MSGID_PATTERN        AA_SELECT_MASK + MARK_SEEN_ART_MSGID_PATTERN
#define SELECT_ART_MSGID_NOTPATTERN        AA_SELECT_MASK + MARK_SEEN_ART_MSGID_NOTPATTERN
#define SELECT_ART_REF_BASE             AA_SELECT_MASK + MARK_SEEN_ART_REF_BASE
//#define SELECT_ART_REF_IS               AA_SELECT_MASK + MARK_SEEN_ART_REF_IS
#define SELECT_ART_REF_CONTAINS         AA_SELECT_MASK + MARK_SEEN_ART_REF_CONTAINS
#define SELECT_NGROUP_BASE              AA_SELECT_MASK + MARK_SEEN_NGROUP_BASE
//#define SELECT_NGROUP_IS                AA_SELECT_MASK + MARK_SEEN_NGROUP_IS
#define SELECT_NGROUP_CONTAINS          AA_SELECT_MASK + MARK_SEEN_NGROUP_CONTAINS

#define SELECT_ART_HOST_BASE            AA_SELECT_MASK + MARK_SEEN_ART_HOST_BASE
#define SELECT_ART_HOST_IS              AA_SELECT_MASK + MARK_SEEN_ART_HOST_IS
#define SELECT_ART_HOST_CONTAINS        AA_SELECT_MASK + MARK_SEEN_ART_HOST_CONTAINS
#define SELECT_ART_HOST_PATTERN         AA_SELECT_MASK + MARK_SEEN_ART_HOST_PATTERN
#define SELECT_ART_HOST_NOTPATTERN         AA_SELECT_MASK + MARK_SEEN_ART_HOST_NOTPATTERN

#define KILL_ART_LINES_LT               AA_KILL_MASK + MARK_SEEN_ART_LINES_LT      
#define KILL_ART_LINES_EQ               AA_KILL_MASK + MARK_SEEN_ART_LINES_EQ      
#define KILL_ART_LINES_GT               AA_KILL_MASK + MARK_SEEN_ART_LINES_GT
#define KILL_ART_GROUPS_BASE            AA_KILL_MASK + MARK_SEEN_ART_GROUPS_BASE
#define KILL_ART_GROUPS_LT              AA_KILL_MASK + MARK_SEEN_ART_GROUPS_LT     
#define KILL_ART_GROUPS_EQ              AA_KILL_MASK + MARK_SEEN_ART_GROUPS_EQ     
#define KILL_ART_GROUPS_GT              AA_KILL_MASK + MARK_SEEN_ART_GROUPS_GT
#define KILL_ART_FROM_IS                AA_KILL_MASK + MARK_SEEN_ART_FROM_IS       
#define KILL_ART_FROM_CONTAINS          AA_KILL_MASK + MARK_SEEN_ART_FROM_CONTAINS 
#define KILL_ART_FROM_PATTERN           AA_KILL_MASK + MARK_SEEN_ART_FROM_PATTERN
#define KILL_ART_FROM_NOTPATTERN           AA_KILL_MASK + MARK_SEEN_ART_FROM_NOTPATTERN
#define KILL_ART_EMAIL_IS               AA_KILL_MASK + MARK_SEEN_ART_EMAIL_IS         
#define KILL_ART_EMAIL_CONTAINS         AA_KILL_MASK + MARK_SEEN_ART_EMAIL_CONTAINS
#define KILL_ART_EMAIL_PATTERN          AA_KILL_MASK + MARK_SEEN_ART_EMAIL_PATTERN
#define KILL_ART_EMAIL_NOTPATTERN          AA_KILL_MASK + MARK_SEEN_ART_EMAIL_NOTPATTERN
#define KILL_ART_SUBJ_IS                AA_KILL_MASK + MARK_SEEN_ART_SUBJ_IS          
#define KILL_ART_SUBJ_CONTAINS          AA_KILL_MASK + MARK_SEEN_ART_SUBJ_CONTAINS
#define KILL_ART_SUBJ_PATTERN           AA_KILL_MASK + MARK_SEEN_ART_SUBJ_PATTERN 
#define KILL_ART_SUBJ_NOTPATTERN           AA_KILL_MASK + MARK_SEEN_ART_SUBJ_NOTPATTERN 
#define KILL_ART_MSGID_IS               AA_KILL_MASK + MARK_SEEN_ART_MSGID_IS       
#define KILL_ART_MSGID_CONTAINS         AA_KILL_MASK + MARK_SEEN_ART_MSGID_CONTAINS
#define KILL_ART_MSGID_PATTERN          AA_KILL_MASK + MARK_SEEN_ART_MSGID_PATTERN
#define KILL_ART_MSGID_NOTPATTERN          AA_KILL_MASK + MARK_SEEN_ART_MSGID_NOTPATTERN
#define KILL_ART_REF_CONTAINS           AA_KILL_MASK + MARK_SEEN_ART_REF_CONTAINS
#define KILL_NGROUP_CONTAINS            AA_KILL_MASK + MARK_SEEN_NGROUP_CONTAINS
#define KILL_NGROUP_BASE                AA_KILL_MASK + MARK_SEEN_NGROUP_BASE
#define KILL_ART_HOST_BASE              AA_KILL_MASK + MARK_SEEN_ART_HOST_BASE
#define KILL_ART_HOST_IS                AA_KILL_MASK + MARK_SEEN_ART_HOST_IS
#define KILL_ART_HOST_CONTAINS          AA_KILL_MASK + MARK_SEEN_ART_HOST_CONTAINS
#define KILL_ART_HOST_PATTERN           AA_KILL_MASK + MARK_SEEN_ART_HOST_PATTERN
#define KILL_ART_HOST_NOTPATTERN           AA_KILL_MASK + MARK_SEEN_ART_HOST_NOTPATTERN

typedef struct tag_ad
{
  int iAction;
  long int iParam;
  char *sParam;
} ALIGNED ACTIONDATA, FAR *LPACTIONDATA;


struct Node
{
  Node * Flink;
  Node * Blink;
  ACTIONDATA ad;
}ALIGNED;


// WVArticleAction - 'killfile' et al
class WVArticleAction
{
protected:
  Node *m_Head;
  Node *m_Tail;
  Node *m_Current;
  //char m_ProfSect[128];
  WVString m_sProfSect;
  WVPersBOOL *m_bNeedGroup;
  WVPersBOOL *m_bNeedNNTP;
  WVPersBOOL *m_bIgnoreGlobal;
private:
  static WMemPool m_ClassPool;
public:
  //WVArticleAction();
  WVArticleAction(const char*sGrp);
  WVArticleAction(const WVArticleAction& wv);
  WVArticleAction(WVArticleAction*wv);
  ~WVArticleAction();
  inline void*operator new(UINT_PTR )
  { return m_ClassPool.AllocElement(); }
  inline void operator delete(void*p)
  { m_ClassPool.FreeElement(p); }
  void SetIParam(int i);
  void SetParamText(const char*sP);
  void ResetCurrent(){m_Current = m_Head;};
  void ReadActions(/* const char*sGroup */);
  void WriteActions();
  Node*GetCurrent(){return m_Current;};
  void Append(int iA, long int iP, const char*sP);
  void DeleteNode(Node* pN);
  void DeleteAll();
  void GoToNext();
  void GoToPrev();
  void Switch(Node*nA, Node*nB);
  void Switchwith(WVArticleAction*nB);
  void ActOnArticles(TypGroup far *Group, header_p headers, BOOL bClear);
  BOOL NeedNgroupHeader();
  BOOL NeedNNTPHost();
  BOOL IgnoreGlobalFilter();
  void SetIgnoreGlobalFilter(BOOL bIgnore);
  void RemoveStoredNGroupValue();
  int GetCurrentIndex();
  int SetCurrentIndex(int ndex);
  int GetCount();
private:
  WVArticleAction& operator=(const WVArticleAction& rhs); // unimplemented
  WVArticleAction* operator&();                           // unimplemented
  const WVArticleAction* operator&() const;               // unimplemented
}ALIGNED;

//extern WVArticleAction g_action;
extern WVArticleAction *g_pAction;


//under win64 the bitmap array uses 64bit storage
#if defined (_WIN64)
#define BMSIZE 64ui64
#define ALLBITS (0xFFFFFFFFFFFFFFFFui64)
#define UINT_MAX3264 ULLONG_MAX
#else  //under win32 we use 32bit storage
#define BMSIZE 32
#define ALLBITS 0xFFFFFFFFL
#define UINT_MAX3264 ULONG_MAX
#endif

class WVSeenDB
{
private:
  UBIGINT m_uLowVal, m_uHiVal;
  UBIGINT m_uLowBase, m_uHiBase;

  UINT_PTR *m_pBitmap;   

  static WMemPool m_ClassPool;

public:
  WVSeenDB(UBIGINT uLo, UBIGINT uHi, WVSeenDB*sdb = NULL);
  ~WVSeenDB()
  {
	if(m_pBitmap)
#ifdef _WIN32
    delete m_pBitmap;
#else
	_hfree(m_pBitmap);
#endif 
  }

  inline void*operator new(UINT_PTR )
  { return m_ClassPool.AllocElement(); }
  inline void operator delete(void*p)
  { m_ClassPool.FreeElement(p); }

  void CreateBitmap(UBIGINT uLo, UBIGINT uHi, BOOL bCompact = FALSE);
  void DestroyBitmap(void);
  void GetRange(TypRange& r);
  UBIGINT GetLowRange() const { return m_uLowVal; };
  UBIGINT GetHighRange() const { return m_uHiVal; };
  void MarkSeen(UBIGINT uArtIdx);
  void MarkSeen(UBIGINT uArtIdx1, UBIGINT uArtIdx2);
  void MarkAllSeen(UBIGINT uArtIdxHi);
  void MarkUnseen(UBIGINT uArtIdx);
  void MarkUnseen(UBIGINT uArtIdx1, UBIGINT uArtIdx2);

  BOOL WasSeen(UBIGINT uArtIdx);
  UBIGINT NumUnseen();
  UBIGINT HighestSeen();
  //uint32 LowestUnseen();
  UBIGINT NextSeen(UBIGINT uNext);
  UBIGINT NextUnseen(UBIGINT uNext = 0);
private:
  WVSeenDB(); // not implemented
}ALIGNED;

#define RangeOffset(nlen) (((nlen+sizeof(int))/sizeof(int))*sizeof(int)+sizeof(TypGroup))

#define CalcGroupLen(Group) (sizeof (TypLine) + RangeOffset (Group->NameLen) + sizeof (int))

/* in wvgroup.cpp    */

BOOL article_operation (TypDoc far * Doc, long artindex,BOOL (*art_fun) (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex));
 
BOOL selected_false (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);

BOOL error_false (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);

BOOL error_true (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);

BOOL preview_false (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);

BOOL preview_true (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);

void SetGroupSelections (TypDoc * MyDoc, header_p headers, long newActive);
/* Ray Dunn:99/10: */
void ResortGroup(HWND hWnd);
/* Ray Dunn:99/10:End */
long search_headers (TypDoc far * HeaderDoc, header_p headers, long artindex, long num_headers);
void SaveSelectedArts (HWND hwnd, TypDoc far * Doc, header_p headers, long num_headers);
BOOL toggle_read_unread (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL toggle_selected (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL selected_true (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL seen_true (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL seen_false (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL mark_read_to_here (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL mark_read_all (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL mark_unread_all (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
/* Ray Dunn:99/10 */
BOOL mark_read_all_catchup (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
/* Ray Dunn:99/10:End */
BOOL mark_read_selected (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL mark_selected_read_articles (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL mark_selected_unread_articles (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL mark_deselected_read_articles (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL mark_deselected_unread_articles (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
BOOL SelectHeader (TypDoc far * Doc, header_p header, int value);

void SeverArticleParent(TypDoc *doc);
void setArticleFocus (HWND hWndArt);
long NewCursorToTextLine (int X, int Y, TypDoc far * DocPtr);
long AffectSelected (TypDoc far * Doc, int value, int compare);
long AffectSelectedOnScreen (TypDoc far * Doc, int value, int compare);
void InitiateReceiveArticle (TypDoc far * Doc, char far * articleId);
BOOL mark_unread_selected (TypDoc far * Doc, header_p headers, TypGroup * group, long artindex);
//void CloseGroupWnd (HWND hWnd, TypDoc far * ThisDoc);
void SetMenusForMultiArticleOperation (TypDoc far * DocPtr, int enable);

/* in file wvart.cpp */
long find_article_by_subject (TypHeader huge * headers, long artindex, long num_headers);
void view_article_by_message_id (TypDoc * Doc, char far * msg_id, long artindex);
void SetArticleRot13Mode (HWND hWnd, BOOL RotMode);
//BOOL GetArticleRot13Mode (HWND hWnd);
BOOL FindGroup(char * groupname, TypDoc  *DocPtr, TypBlock **BlockPtr, TypLine **LinePtr);
void mark_article_seen(TypDoc FAR * Doc, char * groupname, BIGINT artindex);
/* Ray Dunn:99/10 */
BOOL CloseArtWnd (HWND hWnd, TypDoc * ThisDoc);
void CloseArtWndSelectAnother (HWND hWnd, TypDoc * ThisDoc);
/* Ray Dunn:99/10:End */
void UpdateHighlightedText (TypDoc far * DocPtr, TextSelect far * PreviousPos);
void HighlightText (TypDoc far * DocPtrs);
void CopyTextToClipBoard (TypDoc FAR * DocPtr);

/* in file headarry.cpp */
header_p header_elt (header_p headers, long index);
header_p lock_headers (HANDLE header_handle, HANDLE thread_handle);
void unlock_headers (HANDLE header_handle, HANDLE thread_handle);
void free_headers (HANDLE header_handle, HANDLE thread_handle);
void sort_by_option(header_p h, thread_array t, BOOL tOk, long nL, HANDLE hHandle, HANDLE tHandle);
//void sort_by_threads (HANDLE header_handle, HANDLE thread_handle, long length);
void initialize_header_array (HANDLE header_handle, HANDLE thread_handle, long length);
void set_index_to_identity (HANDLE header_handle, HANDLE thread_handle, long length);
void shell_sort_index_array (header_p headers, thread_array index, long nElements,
                 int (*compare) (header_p headers, long elem1, long elem2));
long move_killed_headers (HANDLE header_handle, HANDLE thread_handle, long length);
long unkill_killed_headers (HANDLE header_handle, HANDLE thread_handle, long length);


//int compare_subject (header_p headers, long elem1, long elem2);
//int compare_date (header_p headers, long elem1, long elem2);
//int compare_lines (header_p headers, long elem1, long elem2);
//int compare_from (header_p headers, long elem1, long elem2);
//int compare_artnum (header_p headers, long elem1, long elem2);


typedef struct tag_ahd
{
    int iParam;
    char * sParam;
} ALIGNED ADDHDRDATA;

struct AHNode
{
    AHNode    * Flink;
    AHNode    * Blink;
    ADDHDRDATA  ahd;
}ALIGNED;

class WVAddHdr
{
protected:
  AHNode *m_Head;
  AHNode *m_Tail;
  AHNode *m_Current;
  WVString m_sProfSect;
private:
  static WMemPool m_ClassPool;
public:
  //WVAddHdr();
  WVAddHdr(const char*sGrp);
  WVAddHdr(const WVAddHdr& wv);
  WVAddHdr(WVAddHdr*wv);
  ~WVAddHdr();
  
  inline void*operator new(UINT_PTR )
  { return m_ClassPool.AllocElement(); }
  inline void operator delete(void*p)
  { m_ClassPool.FreeElement(p); }
  
  void SetIParam(int i);
  void SetParamText(const char*sP);
  BOOL GetParamText(char * sP);
  BOOL GetIParam(int *p);
  void ResetCurrent(){m_Current = m_Head;};
  void ReadAddHdr(/* const char*sGroup */);
  void WriteAddHdr();
  AHNode*GetCurrent(){return m_Current;};
  void Append(int i, const char*sP);
  void DeleteNode(AHNode* pN);
  void DeleteAll();
  void GoToNext();
  void GoToPrev();
  void Switch(AHNode*nA, AHNode*nB);
  void Switchwith(WVAddHdr*nB);
}ALIGNED;

extern WVAddHdr *g_pAddHdr;

#ifdef RFC1522

#include "wv1522.h"

#endif

#endif
