typedef struct Event Event;
typedef struct Exec Exec;
typedef struct Message Message;
typedef struct Window Window;

enum
{
       STACK           = 8192,
       EVENTSIZE       = 256,
       NEVENT          = 5,
};

struct Event
{
       int     c1;
       int     c2;
       int     q0;
       int     q1;
       int     flag;
       int     nb;
       int     nr;
       char    b[EVENTSIZE*UTFmax+1];
       Rune    r[EVENTSIZE+1];
};

struct Window
{
       /* file descriptors */
       int             ctl;
       int             event;
       int             addr;
       int             data;
       Biobuf  *body;

       /* event input */
       char            buf[512];
       char            *bufp;
       int             nbuf;
       Event   e[NEVENT];

       int             id;
       int             open;
       Channel *cevent;
};

struct Message
{
       Window  *w;
       int             ctlfd;
       char            *name;
       char            *replyname;
       char            *replydigest;
       uchar   opened;
       uchar   dirty;
       uchar   isreply;
       uchar   deleted;
       uchar   writebackdel;
       uchar   tagposted;
       uchar   recursed;
       uchar   level;

       /* header info */
       char            *fromcolon;     /* from header file; all rest are from info file */
       char            *from;
       char            *to;
       char            *cc;
       char            *replyto;
       char            *date;
       char            *subject;
       char            *type;
       char            *disposition;
       char            *filename;
       char            *digest;
       char            *flags;

       Message *next;  /* next in this mailbox */
       Message *prev;  /* prev in this mailbox */
       Message *head;  /* first subpart */
       Message *tail;  /* last subpart */
};

enum
{
       NARGS           = 100,
       NARGCHAR        = 8*1024,
       EXECSTACK       = STACK+(NARGS+1)*sizeof(char*)+NARGCHAR
};

struct Exec
{
       char            *prog;
       char            **argv;
       int             p[2];   /* p[1] is write to program; p[0] set to prog fd 0*/
       int             q[2];   /* q[0] is read from program; q[1] set to prog fd 1 */
       Channel *sync;
};

extern  Window* newwindow(void);
extern  int             winopenfile(Window*, char*);
extern  void            winopenbody(Window*, int);
extern  void            winclosebody(Window*);
extern  void            wintagwrite(Window*, char*, int);
extern  void            winname(Window*, char*);
extern  void            winwriteevent(Window*, Event*);
extern  void            winread(Window*, uint, uint, char*);
extern  int             windel(Window*, int);
extern  void            wingetevent(Window*, Event*);
extern  void            wineventproc(void*);
extern  void            winwritebody(Window*, char*, int);
extern  void            winclean(Window*);
extern  int             winselect(Window*, char*, int);
extern  char*   winselection(Window*);
extern  int             winsetaddr(Window*, char*, int);
extern  char*   winreadbody(Window*, int*);
extern  void            windormant(Window*);
extern  void            winsetdump(Window*, char*, char*);

extern  void            readmbox(Message*, char*, char*);
extern  void            rewritembox(Window*, Message*);

extern  void            mkreply(Message*, char*, char*, Plumbattr*, char*);
extern  void            delreply(Message*);
extern  int             write2(int, int, char*, int, int);

extern  int             mesgadd(Message*, char*, Dir*, char*);
extern  void            mesgmenu(Window*, Message*);
extern  void            mesgmenuselect(Window*, Message*);
extern  void            mesgmenunew(Window*, Message*);
extern  void            mesgmenureflag(Window*, Message*);
extern  int             mesgopen(Message*, char*, char*, Message*, int, char*);
extern  void            mesgctl(void*);
extern  void            mesgsend(Message*);
extern  void            mesgdel(Message*, Message*);
extern  void            mesgmenudel(Window*, Message*, Message*);
extern  void            mesgmenumark(Window*, char*, char*);
extern  void            mesgmenumarkdel(Window*, Message*, Message*, int);
extern  Message*        mesglookup(Message*, char*, char*);
extern  Message*        mesglookupfile(Message*, char*, char*);
extern  void            mesgfreeparts(Message*);

extern  char*   readfile(char*, char*, int*);
extern  char*   readbody(char*, char*, int*);
extern  void            ctlprint(int, char*, ...);
extern  void*   emalloc(uint);
extern  void*   erealloc(void*, uint);
extern  char*   estrdup(char*);
extern  char*   estrstrdup(char*, char*);
extern  char*   egrow(char*, char*, char*);
extern  char*   eappend(char*, char*, char*);
extern  void            error(char*, ...);
extern  int             tokenizec(char*, char**, int, char*);
extern  void            execproc(void*);
extern  void            setflags(Message*, char *);

#pragma varargck        argpos  error   1
#pragma varargck        argpos  ctlprint        2

extern  Window  *wbox;
extern  Message mbox;
extern  Message replies;
extern  char            *fsname;
extern  int             plumbsendfd;
extern  int             plumbseemailfd;
extern  char            *home;
extern  char            *outgoing;
extern  char            *mailboxdir;
extern  char            *user;
extern  char            deleted[];
extern  int             wctlfd;
extern  int             shortmenu;
extern  int             altmenu;