/*========================================================================*
 * TITLE:	XIOBIFF -- mail monitor for X
 * MODULE:	xiobiff.c
 * BY:		Ross C Linder	(c) 1994
 *
 * You may freely distribute and modify this code, Ethics dictate
 * that you would leave reference to me in the source code.
 *
 * NOTE: XIOBIFF was created for two reasons, one to play with a pixmap
 * and two to monitor both my incomming mail and the outgoing mail
 * queue.
 *
 * I needed this for a machine that uses smail over a slip link to show
 * me when I can terminate DIP. It simply looks for files in the input
 * directory waiting to be sent.
 *
 * Its simple, and it works for me. You can make it pretty by providing
 * new pixmaps in pixmap.h
 *========================================================================*/

static char id[]=

"@(#)xiobiff.h	$Revision: 1.1 $	$Date: 1994/12/23 17:19:25 $";


#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <pwd.h>
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include "/usr/X386/lib/xpm-include/xpm.h"	/* Whatch out for this ! */
#include "pixmaps.h"

#define UMAIL_DIR	"/usr/spool/mail/"	/* Remember "/" */
#define OUTM_DIR	"/usr/spool/smail/input"


typedef struct {
		Pixmap pixmap;
		Pixmap mask;
		XpmAttributes attributes;
		} XpmIcon;

/*====================== Some common stuff we need for X =================*/

Widget		toplevel;
Display		*disp;
Colormap	colormap;
XtAppContext	app_context;
XpmIcon		in, inout, out, none;

/*======================= Prototypes, well sort of :) ====================*/

void test_mail ();
void input_cb ();


/*========================================================================*
 * MAIN -- Init the Xt toolkit and get a toplevel window etc.
 *========================================================================*/

main (int argc, char *argv[])
{
Arg		args[5];
int		a, err;
XSizeHints	size_hints;
XpmColorSymbol	symbols[10];
XrmValue	val;


    toplevel = XtAppInitialize(&app_context, "xiobiff", NULL, 0,
					&argc, argv, NULL, NULL, 0);

    if (!toplevel) {
	perror ("Can't open display or init Xtoolkit");
	exit(1);
	}

    disp = XtDisplay (toplevel);
    colormap = XDefaultColormapOfScreen (XtScreen (toplevel));

    a = 0;
    XtSetArg (args[a], XtNwidth, 1); a++;
    XtSetArg (args[a], XtNheight, 1); a++;
    XtSetArg (args[a], XtNmappedWhenManaged, False); a++;
    XtSetArg (args[a], XtNinput, True); a++;
    XtSetValues (toplevel, args, a);

    XtRealizeWidget (toplevel);

    if (XpmCreatePixmapFromData (disp, XtWindow (toplevel), out_xpm,
		&out.pixmap, &out.mask,&out.attributes) != XpmSuccess) {
	perror ("Creating pixmap");
	exit (1);
	}

    if (XpmCreatePixmapFromData (disp, XtWindow (toplevel), inout_xpm,
		&inout.pixmap, &inout.mask,&inout.attributes) != XpmSuccess) {
	perror ("Creating pixmap");
	exit (1);
	}

    if (XpmCreatePixmapFromData (disp, XtWindow (toplevel), none_xpm,
		&none.pixmap, &none.mask,&none.attributes) != XpmSuccess) {
	perror ("Creating pixmap");
	exit (1);
	}

    if (XpmCreatePixmapFromData (disp, XtWindow (toplevel), in_xpm,
		&in.pixmap, &in.mask, &in.attributes) != XpmSuccess) {
	perror ("Creating pixmap");
	exit (1);
	}

    XtResizeWidget (toplevel, in.attributes.width, in.attributes.height, 1);

    /*==================== Set the pixmap to none 4 now ==================*/

    size_hints.flags = PMinSize;
    size_hints.min_height = none.attributes.height;
    size_hints.min_width = none.attributes.width;
    XSetWMNormalHints (disp, XtWindow (toplevel), &size_hints);

    XSetWindowBackgroundPixmap (disp, XtWindow (toplevel), none.pixmap);

    XtAddEventHandler (toplevel, ButtonPressMask | KeyPressMask,
				 ButtonPressMask | KeyPressMask,
			  (XtEventHandler) input_cb, NULL);

    XClearWindow (disp, XtWindow (toplevel));
    XMapWindow (disp, XtWindow (toplevel));

    XtAppAddTimeOut (app_context, 1000, test_mail, 0);	/* 1 sec first time */
    XtAppMainLoop (app_context);
}


/*========================================================================*
 * TEST_MAIL -- Test the users mailbox, and the outgoing directory
 *========================================================================*/

static	inflag = 0;		/* 1 if new mail arrived */
static	outflag = 0;		/* 1 if waiting for delivery */

void test_mail ()
{
static int	l_umt = 0;	/* last user mod time */
static int	l_usz = 0;	/* last user size */
int		osz = 0;	/* number of outgoing msg's pending */
struct dirent	*dp;
struct stat	st;
struct passwd	*pw;
DIR		*dirp;
char		*uname;
char		upath[256];

    if ((uname = getlogin ()) == NULL) {	/* who are we ? */
	pw = getpwuid (getuid ());
	if (!pw) {
	    perror ("Unknown user");
	    exit (1);
	    }
	uname = pw->pw_name;
	}

    strcpy (upath, UMAIL_DIR);
    strcat (upath, uname);

    /*================ Test the size and mod time of mailbox =============*/

    if (stat (upath, &st) != -1) {
	if (l_umt != st.st_mtime && l_usz != st.st_size) {
	    if (!inflag) {
		inflag |= 1;
		set_pixmaps ();		/* Times have changed */
		}
	    XBell (disp, 100);		/* and for the sleepy */
	    l_umt = st.st_mtime;
	    l_usz = st.st_size;
	    }
	}

    /*========== Count the no of messages pending for transfer ==========*/

    osz = 0;
    if ((dirp = opendir (OUTM_DIR)) != NULL) {
	while ((dp = readdir (dirp)) != NULL) {
	    if (dp->d_name[0] == '.')
		continue;

	    osz++;	/* Assume no sub-dirs ! */
	    }
	closedir (dirp);

	if (osz) {
	    if (!outflag) {
		outflag = 1;
		set_pixmaps ();		/* Come on George ! */
		}
	    }
	else {
	    if (outflag) {
		outflag = 0;
		set_pixmaps ();		/* At last ! */
		XBell (disp, 50);
		XBell (disp, 50);
		}
	    }
	}

    XtAppAddTimeOut (app_context, 10000, test_mail, 0);
}

/*========================================================================*
 * INPUT_CB -- Ack incoming mail, then reset flag & pixmap (by mouse click)
 *========================================================================*/

void input_cb ()
{
    if (inflag) {
	inflag = 0;
	set_pixmaps ();
	}
}

/*========================================================================*
 * SET_PIXMAPS -- Display the required pixmap based on the in & out flags
 *========================================================================*/

set_pixmaps ()
{
XpmIcon		*pm;
XSizeHints	size_hints;

    if (inflag && outflag)
	pm = &inout;
    else if (!inflag && outflag)
	pm = &out;
    else if (!inflag && !outflag)
	pm = &none;
    else
	pm = &in;

    size_hints.flags = PMinSize;
    size_hints.min_height = pm->attributes.height;
    size_hints.min_width = pm->attributes.width;
    XSetWMNormalHints (disp, XtWindow (toplevel), &size_hints);

    XSetWindowBackgroundPixmap (disp, XtWindow (toplevel), pm->pixmap);
    XClearWindow (disp, XtWindow (toplevel));
}

/*========================================================================*
 * $Log: xiobiff.c,v $
 * Revision 1.1  1994/12/23  17:19:25  ross
 * Initial revision
 *
 *========================================================================*/

