/*++
/* NAME
/*	desk 3
/* SUMMARY
/*	mail box display
/* PROJECT
/*	pc-mail
/* PACKAGE
/*	mailsh
/* SYNOPSIS
/*	#include "mailsh.h"
/*
/*	void desk()
/*
/*	int junk_desk()
/*
/*	char message[];
/*	char comment[];
/* DESCRIPTION
/*      Most functions in this module are invoked by the keyboard interpreter
/*      and are responsible for the mail box view of message summary lines.
/*
/*	desk() is the main entry point. It presents the user with a sorted
/*	display of message files and a list of commands to choose from.
/*
/*	patience() informs the user that an operation may take some time.
/*	It puts the 'one moment please..'  in the middle screen window.
/*	As a side effect, it sets the current pager file to none.
/*
/*	junk_desk() should be invoked when the number of files in the mail box
/*	may have changed. Always returns a zero value. This function
/*	should be called when a message is added to, or deleted from, the
/*	spool directory.
/*
/*	The strings "message" and "comment" hold path names of the currently
/*	selected message file, and its associated metafile (with message
/*	destination, origin or comments). These names are used by functions 
/*	that read, delete or otherwise manipulate message files.
/* FILES
/*      mail header files in the spool directory
/* SEE ALSO
/*      pager(3), pager(5), kbdinp(3)
/* DIAGNOSTICS
/*      If a selected mail message could not be found an error message
/*      is displayed instead.
/* BUGS
/*      Since a message can be accessed only if its metafile exists,
/*	a message is "lost" when for some reason the metafile is
/*	not available.
/* AUTHOR(S)
/*      W.Z. Venema
/*      Eindhoven University of Technology
/*      Department of Mathematics and Computer Science
/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
/* CREATION DATE
/*	Tue May 12 15:35:20 GMT+1:00 1987
/* LAST MODIFICATION
/*	Mon Apr  4 23:37:48 MET 1988
/* VERSION/RELEASE
/*	1.3
/*--*/

#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include "defs.h"
#include "mailsh.h"
#include "path.h"
#include "dir.h"
#include "pager.h"
#include "screen.h"
#include "status.h"
#include "window.h"

extern struct tm *localtime();          	/* std C library */

hidden void make_desk();			/* forward declarations */
hidden int pick_desk();
hidden int show_desk();
hidden void add_desk();

hidden File *deskfile = 0;			/* mail box pager file */
public char message[BUFSIZ];			/* path to message file */
public char comment[BUFSIZ];			/* path to comment file */
hidden int msgid;				/* message id */

/* description of the mail summary lines in the main screen */

typedef struct {
    char *category;		/* work, incoming, outgoing, ... */
    char *comtype;		/* from, to, ... */
    char *msgpfx;		/* message-file prefix */
    char *compfx;		/* meta-file prefix */
    int (*access)();		/* message access function */
} Summary;

hidden char makeletter[] = "(create a new message)";

hidden Summary summary[] = {
    "new",	makeletter,	EDTPFX,	COMPFX,	mail,	/* new mail */
    "Work",	"Name:",	EDTPFX,	COMPFX,	mail,	/* in preparation */
    "Out",	"To:",		MSGPFX,	XQTPFX,	mbox,	/* queued */
    "New",	"From:",	NEWPFX, HDRPFX, mbox,	/* new mail */
    "In",	"From:",	NEWPFX,	OLDPFX,	mbox,	/* old mail */
    0,							/* terminator */
};

hidden char dispfmt[] = "%-4s %5d  %s  %-5s %s";
hidden char scanfmt[] = "%s %d";

/* desk - main entry point for message manipulations */

public void desk()
{
    static Screen screen[] = {
	'C',	"Close",	0,      "Terminate the program",
	'F',	"File",		file,   "Mail a copy of an ordinary file",
	'N',	"Network",	call,   "Exchange mail with the network",
	'S',	"Setup",        setup,  "Set communications parameters",
	'A',	"Alias",	alias,	"Display the alias data base",
	'P',	"Print",	print,	"Print message-summary display",
	PGUP,	PgUp,		pu_pager,pageup,
	PGDN,	PgDn,		pd_pager,pagedn,
	UP,	"Up",           up_pager,csrup,
	DOWN,	"Down",         dn_pager,csrdn,
	ENTER,	"Enter",        pick_desk,"Select message at cursor",
	0,	0,		show_desk,
	"Select a message with cursor keys and press ENTER\n\
or select one of the commands in the top line."
    };

    kbdinp(screen);				/* and there they go... */
}

/* show_desk - create or refresh a display of the mail box */

hidden int show_desk()
{
    if (deskfile == 0) {			/* no mail box pager file */
	patience();				/* one moment please... */
	make_desk(deskfile = open_pager());	/* build mail box display */
    } else {					/* pager file exists */
	set_pager(deskfile);			/* select pager file */
    }
    ds_pager();					/* display it */
    return(0);					/* screen is ok */
}

/* make_desk - build pager file of summary lines */

hidden void make_desk(pp)
File *pp;
{
    register Summary *s = summary;

    /* display the "empty sheet of paper" line first */

    app_pager(pp,strcons(dispfmt,s->category,0,s->comtype,"",""));

    /* display summary lines for "New", "Work" and "Old" messages */

    for (s = summary+1; s->category; s++)
	add_desk(pp,s);

    /* sort summary lines in reverser order */

    sort_pager(pp,BACK_SORT);			/* sort mail box display */
}

/* pick_desk - user selected a message */

hidden int pick_desk()
{
    char type[BUFSIZ];
    register Summary *s;

    /* 
    * Read message type (in, out, work etc) and sequence number from 
    * summary line in the mail box display. Then call the appropriate
    * function to access that message.
    */

    type[0] = msgid = 0; 			/* initialize */
    scan_pager(deskfile,scanfmt,type,&msgid);	/* which message chosen? */
    if (msgid == 0)				/* new message? */
	msgid = newseqno();			/* choose new message id */

    for (s = summary; s->category; s++) {	/* try to recognize the */
	if (strcmp(s->category,type) == 0) {	/* message type */
	    strcpy(message,mesg_file(s->msgpfx,msgid)); /* msg file name */
	    strcpy(comment,meta_file(s->compfx,msgid)); /* metafile name */
	    return(CALL(s->access)(type,msgid));/* display the message */
	}
    }
    beep();					/* unrecognized message type */
    return(0);					/* nothing happened */
}

/* junk_desk - force rebuilding of mail box display */

public int junk_desk()
{
    if (deskfile) {
	close_pager(deskfile);			/* delete pager file */
	deskfile = 0;				/* say it's gone */
    }
    return(0);					/* in case one wants it */
}

/*
* add_desk() is invoked to build the main mail box menu screen.
* It searches the spool directory for metafiles of the
* specified type and writes their contents to the specified
* pager file, together with message type, message id and
* creation time of the corresponding message file.
*/

/* add_desk - append summaries with type in s to pager file in pp */

hidden void add_desk(pp,s)
File *pp;
register Summary *s;
{
    int prelen = strlen(s->msgpfx);		/* length of prefix */
    FILE *fp;					/* used to read summaries */
    char *f;					/* message file name */
    int dd;					/* dir search id */
    int msgno;					/* message number */
    struct stat st;				/* file information */

    for (dd = opendir(maildir); f = readdir(dd); /* void */) {
	if (!strncmp(s->msgpfx,f,prelen) && sscanf(f+prelen,"%d",&msgno)
	    && stat(mesg_file(s->msgpfx,msgno),&st) == 0
	    && (fp = fopen(meta_file(s->compfx,msgno),"r"))) {
	    char meta[BUFSIZ];			/* meta-file info */
	    fgets(meta,BUFSIZ,fp);		/* read meta info */
	    meta[strlen(meta)-1] = '\0';	/* chop off newline char */
	    app_pager(pp,strcons(dispfmt,s->category,msgno,
		tstamp(&st.st_mtime),s->comtype,meta));
	    fclose(fp);
	}
    }
    closedir(dd);				/* terminate file search */
}
