/*
 *
 *  AM --- AmigaMail
 *  (C) 1991, 1992 by Christian Riede
 *
 *  AM is distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY.  No author or distributor accepts responsibility to anyone
 *  for the consequences of using it or for whether it serves any
 *  particular purpose or works at all, unless he says so in writing.
 *  Refer to the GNU General Public License, Version 1, for full details.
 *  
 *  Everyone is granted permission to copy, modify and redistribute AM,
 *  but only under the conditions described in the GNU General Public
 *  License, Version 1.  A copy of this license is supposed to have been 
 *  given to you along with AM so you can know your rights and responsi-
 *  bilities.  It should be in a file named COPYING.  Among other things,
 *  the copyright notice and this notice must be preserved on all copies.
 *
 *  
 *
 */

#include "amheader.h"
#include "paths.h"

/****************************************************/

#define AMIGAMAIL_VERSION "V1.19beta"
extern UBYTE *vers; /* every executable must have this */

/****************************************************/

#define PUBSCREENNAME "AmigaMail"

/* need at least 2.04 */
#define AM_LIBRARY_VERSION 37

/* Mailbox Nodetype */
#define AMNT_MAILBOX 123

/* SelectList NodeType */
#define AMNT_SELECT_LIST 124

/* NotifyPort List */
#define AMNT_NOTIFY_PORT_LIST 125

/* Addressbook */
#define AMNT_ADDRESSBOOK 126

/* comes into Mail->read */
#define MAIL_READ              1 /* mail has been read */
#define MAIL_ARCHIVE           2 /* archived mail from me */
#define MAIL_RRT               4 /* RRT has been requested */
#define MAIL_NEW               8 /* mail is new */

#define CTE_BASE64            0
#define CTE_QUOTED-PRINTABLE  1
#define CTE_8BIT              2
#define CTE_7BIT              3
#define CTE_BINARY            4

#define MAIL_FIELDLENGTH 512

/* length of config strings */
#define CONFIG_LENGTH 50


/* the gadgets in the main window */
#define LIST            1
#define SELECT          2
#define SHOW            3
#define SORT            4
#define ACTION          5


/* the name of the server's port */
#define SERVERNAME ((UBYTE *)"AM-Server")

/* client asks for service: */
#define ACT_DIE             0L /* kill server process */
#define ACT_LOCKCONTENTS    1L /* server loads contents file */
#define ACT_UNLOCKCONTENTS  2L /* server saves contents file if all clients have unlocked */
#define ACT_GETCONTENTS     3L /* get a list of items in mailbox */
#define ACT_MARK_READ       4L /* mark item as read */
#define ACT_ADD_ITEM        5L /* add a new item to mailbox */
#define ACT_DELETE_ITEM     6L /* delete item from mailbox */
#define ACT_NEW_SEQ         7L /* get new sequential */
#define ACT_NEW_MSGID       8L /* get new sequential */
#define ACT_NOTIFY_ON       9L /* notify client on changes to contents by other tasks */
#define ACT_NOTIFY_OFF     10L /* don't notify client any more */
#define ACT_VERSION        11L /* version of server */
#define ACT_MARK_UNREAD    12L /* mark item as unread */
#define ACT_MARK_OLD       13L /* mark item as old */

/* server notifies client */
#define NOTIFY_NEWITEM      1L /* a new item has bees added to mailbox */
#define NOTIFY_ITEM_DELETED 2L /* an item has been removed from mailbox */
#define NOTIFY_ITEM_CHANGED 3L /* an item has changed its attributes */

/* Send Flags */
#define SFLAGS_NONE       0L
#define SFLAGS_SEND       1L
#define SFLAGS_REPLY      2L
#define SFLAGS_FORWARD    4L
#define SFLAGS_MULTIMEDIA 8L
#define SFLAGS_QUOTE      16L
#define SFLAGS_GROUP      32L


#define MAXUSERS 256 /* maximum number of users */
#define USERLEN  20   /* maximum username length */

/* dimensions of the addressbook window */
#define ABLeft    100L
#define ABTop     20L
#define ABWidth   500L
#define ABHeight1 180L /* for low screens  */
#define ABHeight2 360L /* for high screens */

#define ABS(x) (((x)>=0)?(x):(-x))

struct Address {
	struct Node Node;
	struct Node DisplayNode;
	char *Username;
	char *Realname;
	char *ReplyTo;
	int CTE;
};

struct Mail {
	struct Node m_Node;
	struct Node m_SelectNode;
	char DisplayText[160]; /* Text to Display in the LISTVIEW-Gadget */
	ULONG Number;
	char *From;
	char *To;
	char *Cc;
	char *ReplyTo;
	char *Subject;
	char *InReplyTo;
	char *MsgId;
	time_t Date;
	int read;
};

struct ContentsItem {
	ULONG Number;
	ULONG FromNumber,ToNumber,ReplyToNumber,CcNumber;
	ULONG SubjectNumber,InReplyToNumber;
	ULONG MsgIdNumber;
	time_t Date;
	int read;
};

struct AMMessage {
	struct Message AMMsg;
	ULONG Action;
	char *Username;
	char *MsgId;
	ULONG Number;
	struct MsgPort *NotifyPort;
	struct Mail *NewMail;
	struct List *Mailbox;
	char *Folder;
	int rc;
};

int ix_exec_entry (int argc, char **argv, char **environ, int *real_errno,
	int (*main)(int, char **, char **));

/*
 *
 *  The globally visible variables and
 *  prototypes for the exported functions
 *
 */

/* 
 *  action.c 
 */

void ActionRead(ULONG,struct List *); /* reentrant (freeze!)*/
void ActionSave(ULONG,struct List *); /* reentrant */
void ActionPrint(ULONG,struct List *); /* reentrant */
void ActionReply(ULONG,struct List *,ULONG); /* reentrant */
void ActionDelete(ULONG,struct List *); /* reentrant */
int ActionMove(ULONG,struct List *); /* reentrant */
void ActionAddAddress(ULONG,struct List *); /* reentrant */
void ActionForward(ULONG, struct List *,ULONG); /* reentrant */


/*
 *  address.c 
 */

/* the addressbook */
int AddAddress(struct List *,char *,char *,char *,int); /* reentrant */
void RemAddress(struct Address *); /* reentrant */
int ReadAddressBook(struct List *);  /* reentrant */
int WriteAddressBook(struct List *); /* reentrant */
void FreeAddressBook(struct List *); /* reentrant */

/*
 *  allocammsg.c 
 */

struct AMMessage *AllocAMMsg(void); /* reentrant */


/*
 *  am.c 
 */

/* some intuition stuff: */

/* the screen/public screen I am using */
extern struct Screen *Screen;
extern struct Screen *PubScreen;

/* the main window */
extern struct Window *Window;

/* global text attribute, font */
extern struct TextAttr TextAttr;
extern struct TextFont *TextFont;

extern USHORT *Stopwatch;

extern int WLeft,WTop,WWidth,WHeight;

/* current user- and realname */
extern char Username[];
extern char Realname[];

/* the mailbox */
extern struct List Mailbox;

/* the current folder */
extern char Folder[];

/* list of selected items */
extern struct List Selected;

extern void (*Show)(struct List *);
extern void (*Select)(struct List *,struct List *,
	void (*Sort)(struct List *,struct Mail *),void *extra);
extern void (*Sort)(struct List *,struct Mail *);

extern char SearchPattern[];

extern int LastSelected;

extern struct FileRequester *FReq;
extern struct FontRequester *FontReq;

/* number of running subprocesses */
extern int running;

void RefreshDisplay(
	void (*Select)(struct List *,struct List *,void (*)(struct List *,struct Mail *),void *),
	void (*Show)(struct List *),void (*Sort)(struct List *,struct Mail *),
	struct List *Mailbox, struct List *Selected,int select,void *extra); /* not reentrant */

/* 
 *  client.c 
 */

/* the messageports for communication with the server */
extern struct MsgPort *ServerPort;

/* all reentrant */
struct AMMessage *AskServer(struct AMMessage *);
int KillServer(void);
int LockContents(char *folder);
int UnLockContents(char *folder);
int GetContents(struct List *Mailbox,char *folder);
struct Mail *AddItem(ULONG num,char *folder);
int MarkRead(ULONG num,char *folder);
int MarkUnread(ULONG num,char *folder);
int MarkOld(ULONG num,char *folder);
int DeleteItem(ULONG num,char *folder);
ULONG NewSeq(char *folder);
int NotifyOn(struct MsgPort *NotifyPort,char *folder);
int NotifyOff(struct MsgPort *NotifyPort,char *folder);
char *NewMsgId(char *);
int CmpVersion(void);



/*
 *  codes.c
 */

void to64(FILE *infile, FILE *outfile);
void from64(FILE *infile,FILE *outfile,char ** boundaries,int * boundaryct);
void lineto64(UBYTE *buf, int len, FILE *outfile);
void from64(FILE *infile,FILE *outfile,char ** boundaries,int * boundaryct);
void toqp(FILE *infile,FILE *outfile);
void linetoqp(UBYTE *Buf,int len,FILE *outfile);
void fromqp(FILE *infile,FILE * outfile,char **boundaries,int *boundaryct);
int PendingBoundary(char *s,char ** Boundaries,int * BoundaryCt);


/*
 *  cte.c
 */

extern char *ContentTransferEncoding[];
int CheckCTE(char *Username);


/*
 *  colorreq.c
 */

long colorreq(char *scrname, char *title, unsigned short initial_color);



/* 
 *  date.c 
 */

char *DateTime(time_t,char *); /* reentrant */
int ParseDate(char *,struct tm *); /* reentrant */
int ParseTimeZone(char *s,int *hoffset,int *voffset); /* reentrant */

/* 
 *  delete.c 
 */

int DeleteMail(struct Mail *,int); /* reentrant */

/* 
 *  editab.c 
 */

void EditAddressBook(void); /* reentrant */

/*
 *  findnode.c
 */

struct Node *findnode(struct List *list, unsigned short num);


/* 
 *  freecontents.c 
 */

void FreeMail(struct Mail *Mail); /* reentrant */
void FreeMailbox(struct List *Mailbox); /* reentrant */

/* 
 *  freeze.c 
 */

/* both pseudo-reentrant, but 2nd copy waits for first to finish */
void Freeze(FILE *in,FILE *out);
void Melt(FILE *in,FILE *out);

/* 
 *  getaddress.c 
 */


int GetAddress(char *To, char *Cc, char *Bcc, 
	char *Subject, char *ReplyTo, char *TmpFileName,int fieldlength);  /* reentrant */


/*
 *  getmail.c
 */

struct Mail *GetMail(ULONG num, struct List *Selected); /* reentrant */



/*
 *  getreplyto.c
 */

char *GetReplyTo(char *Username,char *Buffer,int len);



/* 
 *  os20stuff.c 
 */

int TwoGadRequest(struct Window *,char *,...); /* reentrant */
void SimpleRequest(struct Window *,char *,...); /* reentrant */

/*
 *  read.c
 */

void CallMetamail(char *Mailname,char *Action);
void ReadMail(void);
int notplain(char *s);


/* 
 *  readconfig.c 
 */

/* entries in UULIB:Config and AM's config file*/
extern char NodeName[];
extern char DomainName[];
extern char MailEditor[];
extern char RFilter[];
extern char AMPubScreen[];
extern ULONG AMDisplayID;
extern char TimeZone[];
extern int  LocalHOffset;
extern int  LocalMOffset;
extern char Signature[];
extern char ReplyTo[];
extern struct TextAttr AMFont;
extern UWORD AMColors[]; /* first word is number of colors loaded (max 4)*/
extern char AMFlags[];
extern int AMCTE;

int ReadConfig(char *s); /* reentrant */



/* 
 *  requeststring.c 
 */

int RequestString(char *Question,char *Answer,int Len);  /* reentrant */


/* 
 *  requestsearchstring.c 
 */

int RequestSearchString(char *);  /* reentrant */

/* 
 *  search.c 
 */

struct Mail *GetNum(struct List *Mailbox,ULONG num); /* reentrant */


/* 
 *  searchpattern.c 
 */

int SearchTextH(regexp *pat,struct Mail *Mail);  /* reentrant */
int SearchText(regexp *pat,struct Mail *Mail);  /* reentrant */

/* 
 *  select.c 
 */

/* all reentrant */
void DeselectAll(struct List *Selected);
void SelectAll(struct List *Mailbox, struct List *Selected,
	void (*Sort)(struct List *,struct Mail *),void *extra);
void SelectNew(struct List *Mailbox, struct List *Selected,
	void (*Sort)(struct List *,struct Mail *),void *extra);
void SelectFromMe(struct List *Mailbox, struct List *Selected,
	void (*Sort)(struct List *,struct Mail *),void *extra);
void SelectToMe(struct List *Mailbox, struct List *Selected,
	void (*Sort)(struct List *,struct Mail *),void *extra);
void SelectLastWeek(struct List *Mailbox, struct List *Selected,
	void (*Sort)(struct List *,struct Mail *),void *extra);
void SelectSearchTextH(struct List *Mailbox, struct List *Selected,
	void (*Sort)(struct List *,struct Mail *),void *extra);
void SelectSearchText(struct List *Mailbox, struct List *Selected,
	void (*Sort)(struct List *,struct Mail *),void *extra);

/* 
 *  send.c 
 */
#ifdef __GNUC__
void SendMail(void);
#else
void SendMail(int alen,char *arg);
#endif

/* pragma only for aztec */
/* instructions for GCC can be found in send.c */
#pragma regcall(SendMail(d0,a0))
#ifndef AZTEC_C
#ifndef __GNUC__
#error must provide pragmas for other compilers than Aztec or GCC !!!
#endif
#endif


/* 
 *  show.c 
 */

/* all reentrant */
void ShowSubject(struct List *Mailbox);
void ShowFrom(struct List *Mailbox);
void ShowTo(struct List *Mailbox);
void ShowAll(struct List *Mailbox);
void ShowDate(struct List *Mailbox);
void ShowMsgId(struct List *Mailbox);
char *GetRealname(char *s,char *t,int length);
char *GetUsername(char *s,char *t,int length);

/* 
 *  sort.c 
 */

/* all reentrant */
void InsertByNumber(struct List *Selected,struct Mail *Mail);
void InsertByFrom(struct List *Selected,struct Mail *Mail);
void InsertByTo(struct List *Selected,struct Mail *Mail);
void InsertBySubject(struct List *Selected,struct Mail *Mail);
void InsertByDate(struct List *Selected,struct Mail *Mail);
void InsertByInReplyTo(struct List *Selected,struct Mail *Mail);

/* 
 *  strip7.c 
 */

void strip7(FILE *in,FILE *out);
void linestrip7(UBYTE *Buf,int len,FILE *out);

/* 
 *  tags.c 
 */

/* tags for System() */
extern struct TagItem AMSystemTags[];

/* 
 *  uue.c
 */

void fromuue (FILE *infp,FILE *outfp,char **boundaries,int *ctptr);




/* 
 *  uuencode.c 
 */

void UUEncode(FILE *in,FILE *out); /* reentrant */
void UUDecode(FILE *in,FILE *out); /* reentrant */


/* 
 *  writeconfig.c 
 */

int WriteConfig(char *s); /* reentrant */

/* 
 *  writelog.c 
 */

void writelog(char *); /* reentrant */

