/*****************************************************************************/
/*                                                                           */
/*      asmail - AfterStep Mail                                              */
/*                                                                           */
/*      Copyright (c) 1996, 1997, 1998 Per Liden                             */
/*                                                                           */
/*  This program is free software; you can redistribute it and/or modify     */
/*  it under the terms of the GNU General Public License as published by     */
/*  the Free Software Foundation; either version 2 of the License, or        */
/*  (at your option) any later version.                                      */
/*                                                                           */
/*  This program is distributed in the hope that it will be useful,          */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
/*  GNU General Public License for more details.                             */
/*                                                                           */
/*  You should have received a copy of the GNU General Public License        */
/*  along with this program; if not, write to the Free Software              */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
/*                                                                           */
/*****************************************************************************/

/* Version ****************************************************************** */
#define VERSION "0.51"

/* Headers ****************************************************************** */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/xpm.h>
#include <X11/extensions/shape.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>

/* XPM struct and icons ***************************************************** */
typedef struct _XpmIcon {
    Pixmap pixmap;
    Pixmap mask;
    XpmAttributes attributes;
    struct XpmIcon *next;
} XpmIcon;

XpmIcon *NoMail, *OldMail, *NewMail, *Current;

#include "pixmaps/std/newmail.xpm"
#include "pixmaps/std/oldmail.xpm"
#include "pixmaps/std/nomail.xpm"
#include "pixmaps/std/newmail_s.xpm"
#include "pixmaps/std/oldmail_s.xpm"
#include "pixmaps/std/nomail_s.xpm"

/* Functions **************************************************************** */
int CheckMailBox(char **Mbox, int NumOfMbox);
int IsNewMail(char *Mbox);
int IsMail(char *Mbox);
int NoOfNewMail(char *Mbox);
int CheckTimeStamp(char **Mbox, int NumOfMbox);
int GetGStatus(void);
void CheckMailCallback(XtPointer XtP, XtIntervalId * XtI);
void Help(void);
void CreateWindow(int argc, char *argv[]);
void MakeSettings(int argc, char *argv[]);
void ParseCfgFile(FILE * File);
void StartLoop(void);
void GetXPM(int Shaped);
void LoadXPMFile(XpmIcon * Icon, char *XpmFile);
void XPMError(int Code, char *FileName);
void RedrawWindow(void);
void ButtonHandler(Widget W, XtPointer P, XEvent * E);
void ExposeHandler(Widget W, XtPointer P, XEvent * E);
void AnimCallback(XtPointer XtP, XtIntervalId * XtI);
Pixel GetColor(char *name);
void AddXpmToAnim(XpmIcon * Icon, XpmIcon * List, int ListNo);

/* Global stuff ************************************************************* */
#define DEFCFGFILE		"/.asmailrc"	/* Default configuration file */
#define DEFINTERVAL		5	/* Default interval 5 sec */
#define DEFANIMATIONSPEED	10	/* Default animationspeed 10 */
#define LEFTBUTTON		1	/* Left mousebutton id */
#define RIGHTBUTTON		3	/* Right mousebutton id */
#define MAXNUMOFMAILBOXES	256	/* Maximim number of mailboxes */
Display *Disp = 0;
Window Root;
char Execute[256] = "";
char NewMailExecute[256] = "";
char ExecuteOnUpdate[256] = "";
char *MailBoxes[MAXNUMOFMAILBOXES];
int NumOfMailBoxes = 0;
int ExecuteFlag = 0;
int NewMailExecuteFlag = 0;
int ExecuteOnUpdateFlag = 0;
int AlwaysNewMailExecute = 0;
int IsNew = 1;
int Interval = DEFINTERVAL;
int Beep = 1;
int Shape = 1;
int *NewMailCounter = 0;
int MailCounter = 0;
int TimeStampMode = 0;
int LockShape = 0;
int *IStatus = 0;
int *GStatus = 0;
int NumOfMsgX = 10;
int NumOfMsgY = 10;
int NumOfMsgMode = 0;
char NumOfMsgColor[50] = "WHITE";
XTextItem NumOfMsg;
GC WinGC;
Widget MainWin;
XtAppContext AsmailApp;
int AnimationSpeed[3] =
{DEFANIMATIONSPEED,
 DEFANIMATIONSPEED,
 DEFANIMATIONSPEED};
char HelpMessage[] =
{
    "asmail - Version %s, by Per Liden (per@rsn.hk-r.se)\n"
    "usage:  asmail [file] [options ...] \n"
    "file:\n"
    "        configuration file to use (default ~/.asmailrc)\n"
    "options:\n"
    "        -geometry <geom>     geometry of asmail\n"
    "        -display  <disp>     specifies the display to use\n"
    "        -title    <string>   title string\n"
 "        -name     <string>   client instance, icon and title strings\n"
    "\n"};

/*****************************************************************************/
void main(int argc, char *argv[])
{
    CreateWindow(argc, argv);
    StartLoop();
}

/*****************************************************************************/
void Help()
{
    /* Print help message */
    fprintf(stderr, HelpMessage, VERSION);
    exit(1);
}

/****************************************************************************/
void MakeSettings(int argc, char *argv[])
{
    char CfgFile[256];
    FILE *File = 0;

    /* Get config file */
    if (argc == 1) {
	strcpy(CfgFile, (char *) getenv("HOME"));
	strcat(CfgFile, DEFCFGFILE);
    } else if (argc == 2) {
	/* Check if option */
	if (argv[1][0] == '-')
	    Help();
	else
	    strcpy(CfgFile, argv[1]);
    } else
	Help();


    /* Open config file */
    File = fopen(CfgFile, "r");
    if (File != NULL) {
	ParseCfgFile(File);
	fclose(File);
    } else
	fprintf(stderr, "asmail: '%s' not found, using default settings\n", CfgFile);


    /* Check interval */
    if (!Interval) {
	fprintf(stderr, "asmail: invalid update frequency specified, using default\n");
	Interval = DEFINTERVAL;	/* Use default */
    }
    /* Check animationspeed */
    if (!AnimationSpeed[0] || !AnimationSpeed[1] || !AnimationSpeed[2]) {
	fprintf(stderr, "asmail: invalid animationspeed specified, using default\n");
	AnimationSpeed[0] = DEFANIMATIONSPEED;	/* Use default */
	AnimationSpeed[1] = DEFANIMATIONSPEED;	/* Use default */
	AnimationSpeed[2] = DEFANIMATIONSPEED;	/* Use default */
    }
    AnimationSpeed[0] *= 100;
    AnimationSpeed[1] *= 100;
    AnimationSpeed[2] *= 100;

    /* If no MaiiFile option search for $MAIL */
    if (NumOfMailBoxes == 0) {
	if (getenv("MAIL") != NULL) {
	    NumOfMailBoxes = 1;
	    GStatus = (int *) calloc(NumOfMailBoxes, sizeof(int));
	    IStatus = (int *) calloc(NumOfMailBoxes, sizeof(int));
	    NewMailCounter = (int *) calloc(NumOfMailBoxes, sizeof(int));
	    MailBoxes[0] = (char *) calloc(strlen((char *) getenv("MAIL")) + 1, sizeof(char));
	    strcpy(MailBoxes[0], (char *) getenv("MAIL"));
	} else {
	    fprintf(stderr, "asmail: no mailfile specified\n");
	    exit(1);
	}
    }
    /* Check NumOfMsgMode */
    if (NumOfMsgMode < 0 || NumOfMsgMode > 3) {
	fprintf(stderr, "asmail: invalid NumOfMsgMode specified\n");
	NumOfMsgMode = 0;
    }
}

/****************************************************************************/
void AddXpmToAnim(XpmIcon * Icon, XpmIcon * List, int ListNo)
{
    static XpmIcon *First[3];
    static XpmIcon *Last[3];
    static Count[3] =
    {0, 0, 0};

    if (Count[ListNo] == 0) {
	switch (ListNo) {
	case 0:
	    NoMail = Icon;
	    break;
	case 1:
	    OldMail = Icon;
	    break;
	case 2:
	    NewMail = Icon;
	    break;
	}

	First[ListNo] = Icon;
	List = First[ListNo];
	List->next = (struct XpmIcon *) List;
	Last[ListNo] = First[ListNo];
	Count[ListNo]++;
    } else {
	Last[ListNo]->next = (struct XpmIcon *) Icon;
	Last[ListNo] = Icon;
	Last[ListNo]->next = (struct XpmIcon *) First[ListNo];
    }
}

/****************************************************************************/
void ParseCfgFile(FILE * File)
{
    char Buffer[256];
    int i;
    char c;
    XpmIcon *Icon;

    while (!feof(File)) {
	/* Read string */
	fscanf(File, "%s", Buffer);

	/* Comment */
	if (Buffer[0] == '#') {
	    /* Got to next line */
	    fgets(Buffer, 255, File);
	}
	/* NoBeep */
	else if (!strcasecmp(Buffer, "NoBeep")) {
	    Beep = 0;
	}
	/* NoShape */
	else if (!strcasecmp(Buffer, "NoShape")) {
	    Shape = 0;
	    GetXPM(0);
	}
	/* LockShape */
	else if (!strcasecmp(Buffer, "LockShape")) {
	    LockShape = 1;
	}
	/* MailFiles <...> */
	else if (!strcasecmp(Buffer, "MailFiles")) {
	    i = 0;
	    while (1) {
		fscanf(File, "%s", Buffer);
		/* End */
		if (!strcasecmp(Buffer, "End")) {
		    /* If no mailfiles specified */
		    if (i == 0) {
			fprintf(stderr, "asmail: no mailfiles specified in config");
			exit(1);
		    }
		    NumOfMailBoxes = i;
		    GStatus = (int *) calloc(NumOfMailBoxes, sizeof(int));
		    IStatus = (int *) calloc(NumOfMailBoxes, sizeof(int));
		    NewMailCounter = (int *) calloc(NumOfMailBoxes, sizeof(int));
		    break;
		}
		/* Mailfile */
		else {
		    /* Check maximin number of mailboxes */
		    if (i > MAXNUMOFMAILBOXES) {
			fprintf(stderr, "asmail: too many mailboxes specified");
			exit(1);
		    }
		    /* Check NumOfMsgMode */
		    else if (i > 1 && NumOfMsgMode != 0) {
			fprintf(stderr, "asmail: NumOfMsg can not be used if you have multiple mailboxes");
			NumOfMsgMode = 0;
		    }
		    /* Add mailbox */
		    MailBoxes[i] = (char *) calloc(strlen(Buffer) + 1, sizeof(char));
		    strcpy(MailBoxes[i], Buffer);
		    i++;
		}
	    }
	}
	/* Update <sec> */
	else if (!strcasecmp(Buffer, "Update")) {
	    fscanf(File, "%d ", &Interval);
	}
	/* Execute <program> */
	else if (!strcasecmp(Buffer, "Execute")) {
	    fgetc(File);
	    fgets(Execute, 255, File);
	    ExecuteFlag = 1;
	}
	/* ExecuteOnUpdate <program> */
	else if (!strcasecmp(Buffer, "ExecuteOnUpdate")) {
	    fgetc(File);
	    fgets(ExecuteOnUpdate, 255, File);
	    ExecuteOnUpdateFlag = 1;
	}
	/* NumOfMsgMode <mode> */
	else if (!strcasecmp(Buffer, "NumOfMsgMode")) {
	    /* Check NumOfMailBoxes */
	    if (NumOfMailBoxes > 1) {
		fprintf(stderr, "asmail: NumOfMsg can not be used if you have multiple mailboxes");
		NumOfMsgMode = 0;
	    }
	    fscanf(File, "%d ", &NumOfMsgMode);
	    NumOfMsg.chars = malloc(50);
	    NumOfMsg.font = XLoadFont(Disp, "-*-lucida-*-*-*-*-*-*-*-*-*-*-*-*");
	    NumOfMsg.delta = 1;
	}
	/* NumOfMsgPosition <x> <y> */
	else if (!strcasecmp(Buffer, "NumOfMsgPosition")) {
	    fscanf(File, "%d ", &NumOfMsgX);
	    fscanf(File, "%d ", &NumOfMsgY);
	}
	/* NumOfMsgFont <string> */
	else if (!strcasecmp(Buffer, "NumOfMsgFont")) {
	    fscanf(File, "%s ", &Buffer);
	    NumOfMsg.font = XLoadFont(Disp, Buffer);
	}
	/* NumOfMsgColor <string> */
	else if (!strcasecmp(Buffer, "NumOfMsgColor")) {
	    fscanf(File, "%s ", &Buffer);
	    strncpy(NumOfMsgColor, Buffer, 49);
	}
	/* NewMailExecute <program> */
	else if (!strcasecmp(Buffer, "NewMailExecute")) {
	    fgetc(File);
	    fgets(NewMailExecute, 255, File);
	    NewMailExecuteFlag = 1;
	}
	/* AlwaysNewMailExecute */
	else if (!strcasecmp(Buffer, "AlwaysNewMailExecute")) {
	    AlwaysNewMailExecute = 1;
	}
	/* TimeStampMode */
	else if (!strcasecmp(Buffer, "TimeStampMode")) {
	    TimeStampMode = 1;
	}
	/* AnimationSpeed <nomail> <oldmail <newmail> */
	else if (!strcasecmp(Buffer, "AnimationSpeed")) {
	    fscanf(File, "%d ", &AnimationSpeed[0]);
	    fscanf(File, "%d ", &AnimationSpeed[1]);
	    fscanf(File, "%d ", &AnimationSpeed[2]);
	}
	/* NoMail <...> */
	else if (!strcasecmp(Buffer, "NoMail")) {
	    free(NoMail);
	    while (1) {
		fscanf(File, "%s ", Buffer);
		if (!strcasecmp(Buffer, "End"))
		    break;
		Icon = (XpmIcon *) calloc(1, sizeof(XpmIcon));
		LoadXPMFile(Icon, Buffer);
		AddXpmToAnim(Icon, NoMail, 0);
	    }
	    Current = NoMail;
	}
	/* OldMail <...> */
	else if (!strcasecmp(Buffer, "OldMail")) {
	    free(OldMail);
	    while (1) {
		fscanf(File, "%s ", Buffer);
		if (!strcasecmp(Buffer, "End"))
		    break;
		Icon = (XpmIcon *) calloc(1, sizeof(XpmIcon));
		LoadXPMFile(Icon, Buffer);
		AddXpmToAnim(Icon, OldMail, 1);
	    }
	}
	/* NewMail <...> */
	else if (!strcasecmp(Buffer, "NewMail")) {
	    free(NewMail);
	    while (1) {
		fscanf(File, "%s ", Buffer);
		if (!strcasecmp(Buffer, "End"))
		    break;
		Icon = (XpmIcon *) calloc(1, sizeof(XpmIcon));
		LoadXPMFile(Icon, Buffer);
		AddXpmToAnim(Icon, NewMail, 2);
	    }
	}
	/* Unknown keyword */
	else {
	    for (i = 0, c = 0; i < strlen(Buffer); i++)
		c += isgraph(Buffer[i]);
	    if (c != 0)
		fprintf(stderr, "asmail: unknown keyword '%s'\n", Buffer);
	}
    }
}

/****************************************************************************/
void CreateWindow(int argc, char *argv[])
{
    XSizeHints SizeHints;
    XWMHints WmHints;
    XGCValues gcv;
    unsigned long gcm;
    int Color;

    /* Create Main window */
    MainWin = XtAppInitialize(&AsmailApp, "asmail", NULL, 0, &argc, argv, NULL, NULL, 0);
    Disp = XtDisplay(MainWin);
    Root = RootWindow(Disp, DefaultScreen(Disp));

    /* Add eventhandlers */
    XtAddEventHandler(MainWin, ExposureMask, FALSE, (XtEventHandler) ExposeHandler, NULL);
    XtAddEventHandler(MainWin, ButtonPressMask, FALSE, (XtEventHandler) ButtonHandler, NULL);

    /* Get XPM data */
    GetXPM(1);

    /* Make settings */
    MakeSettings(argc, argv);

    /* Set window attributes */
    XtResizeWidget(MainWin, Current->attributes.width, Current->attributes.height, 1);
    XtRealizeWidget(MainWin);

    /* Create GC */
    gcm = GCForeground | GCBackground | GCGraphicsExposures;
    Color = GetColor(NumOfMsgColor);
    if (Color == 0)
	strcpy(NumOfMsgColor, "BLACK");
    gcv.foreground = Color;
    gcv.background = GetColor("WHITE");
    gcv.graphics_exposures = False;
    WinGC = XCreateGC(Disp, Root, gcm, &gcv);

    /* Map mainwindow */
    XtMapWidget(MainWin);
}

/****************************************************************************/
void RedrawWindow(void)
{
    int GS = GetGStatus();

    /* Select icon */
    switch (GS) {
    case 0:
	Current = NoMail;
	break;
    case 1:
	Current = OldMail;
	break;
    case 2:
	Current = NewMail;
	break;
    }

    /* Shape window */
    if (Shape) {
	XShapeCombineMask(Disp, XtWindow(MainWin), ShapeBounding, 0, 0,
			  Current->mask, ShapeSet);
	if (LockShape)
	    Shape = 0;
    }
    /* Draw icon */
    XCopyArea(Disp, Current->pixmap, XtWindow(MainWin), WinGC, 0, 0,
	    Current->attributes.width, Current->attributes.height, 0, 0);

    /* Draw number of messages */
    if (GS && NumOfMsgMode) {
	/* Create string */
	switch (NumOfMsgMode) {
	case 1:
	    sprintf(NumOfMsg.chars, "%d/%d", NewMailCounter[0], MailCounter);
	    break;
	case 2:
	    sprintf(NumOfMsg.chars, "%d", NewMailCounter[0]);
	    break;
	case 3:
	    sprintf(NumOfMsg.chars, "%d", MailCounter);
	    break;
	}
	NumOfMsg.nchars = strlen(NumOfMsg.chars);
	XDrawText(Disp, XtWindow(MainWin), WinGC, NumOfMsgX, NumOfMsgY, &NumOfMsg, 1);
    }
}

/****************************************************************************/
void ButtonHandler(Widget W, XtPointer P, XEvent * E)
{
    int i;
    int Redraw = 0;

    /* Left button */
    if (E->xbutton.button == LEFTBUTTON && ExecuteFlag == 1)
	system(Execute);

    /* Right button */
    else if (E->xbutton.button == RIGHTBUTTON) {
	for (i = 0; i < NumOfMailBoxes; i++) {
	    if (GStatus[i] == 2) {
		if (TimeStampMode) {
		    GStatus[i] = 1;
		    IStatus[i] = 1;
		} else {
		    GStatus[i] = 1;
		    IStatus[i] = 3;
		    NewMailCounter[i] = NoOfNewMail(MailBoxes[i]);
		}
		Redraw++;
	    }
	}
    }
    if (Redraw)
	RedrawWindow();
}

/****************************************************************************/
void ExposeHandler(Widget W, XtPointer P, XEvent * E)
{
    if (E->xexpose.count == 0)
	RedrawWindow();
}


/****************************************************************************/
void StartLoop(void)
{
    /* Check mailbox at statup */
    if (CheckMailBox(MailBoxes, NumOfMailBoxes))
	RedrawWindow();

    /* Set timeout */
    XtAppAddTimeOut(AsmailApp, Interval * 1000,
		    (XtTimerCallbackProc) CheckMailCallback, NULL);

    /* Set animation timeout's */
    XtAppAddTimeOut(AsmailApp, AnimationSpeed[GetGStatus()],
		    (XtTimerCallbackProc) AnimCallback, NULL);

    /* Start looping */
    XFlush(Disp);
    XtAppMainLoop(AsmailApp);
}

/****************************************************************************/
void AnimCallback(XtPointer XtP, XtIntervalId * XtI)
{
    /* Change to next image */
    NoMail = (XpmIcon *) NoMail->next;
    OldMail = (XpmIcon *) OldMail->next;
    NewMail = (XpmIcon *) NewMail->next;

    /* Redraw */
    RedrawWindow();

    /* Set animation timeout */
    XtAppAddTimeOut(AsmailApp, AnimationSpeed[GetGStatus()],
		    (XtTimerCallbackProc) AnimCallback, NULL);
}

/****************************************************************************/
void CheckMailCallback(XtPointer XtP, XtIntervalId * XtI)
{
    /* Check if ExecuteOnUpdate */
    if (ExecuteOnUpdateFlag)
	system(ExecuteOnUpdate);

    /* Check mailbox */
    if (TimeStampMode && CheckTimeStamp(MailBoxes, NumOfMailBoxes))
	RedrawWindow();
    else {
	if (CheckMailBox(MailBoxes, NumOfMailBoxes))
	    RedrawWindow();
    }

    /* Set timeout */
    XtAppAddTimeOut(AsmailApp, Interval * 1000,
		    (XtTimerCallbackProc) CheckMailCallback, NULL);
}

/************************************************************/
int CheckTimeStamp(char **Mbox, int NumOfMbox)
{
    struct stat St;
    int i;
    int Result = 0;
    int ExecFlag = 0;
    int BeepFlag = 0;

    if (NumOfMbox == 0)
	return 0;

    for (i = 0; i < NumOfMbox; i++) {
	/* Check if modified */
	if (!stat(Mbox[i], &St)) {
	    if (St.st_mtime >= St.st_atime) {
		/* Changed */
		if (IsNew) {
		    BeepFlag = 1;

		    if (IStatus[i] == 2 && AlwaysNewMailExecute && NewMailExecuteFlag)
			ExecFlag = 1;
		    else if (IStatus[i] != 2 && NewMailExecuteFlag)
			ExecFlag = 1;
		    IsNew = 0;
		    IStatus[i] = 2;
		    GStatus[i] = 2;
		}
		Result = 1;
	    }
	}
    }

    /* Beep and execute */
    if (BeepFlag && Beep)
	XBell(Disp, 0);
    if (ExecFlag)
	system(NewMailExecute);

    return Result;
}

/****************************************************************************/
int CheckMailBox(char **Mbox, int NumOfMbox)
{
    static int iCheckingMailbox = 0;
    int i;
    int Prev;
    int Result = 0;
    int BeepFlag = 0;
    int ExecFlag = 0;

    if (!iCheckingMailbox) {
	iCheckingMailbox = 1;
	for (i = 0; i < NumOfMbox; i++) {
	    Prev = GStatus[i];
/************************************************************/
	    if (IsMail(Mbox[i])) {
		if (IsNewMail(Mbox[i])) {
		    if (NoOfNewMail(Mbox[i]) > NewMailCounter[i]) {
			if (IsNew) {
			    if (IStatus[i] == 2 && AlwaysNewMailExecute && NewMailExecuteFlag)
				ExecFlag = 1;
			    else if (IStatus[i] != 2 && NewMailExecuteFlag)
				ExecFlag = 1;
			    BeepFlag = 1;
			    IsNew = 0;
			    NewMailCounter[i] = NoOfNewMail(Mbox[i]);
			}
			IStatus[i] = 2;
			GStatus[i] = 2;

		    } else {
			IsNew = 1;
			if (IStatus[i] == 3)
			    GStatus[i] = 1;
			else
			    GStatus[i] = 2;
		    }

		} else {
		    IsNew = 1;
		    IStatus[i] = 1;
		    GStatus[i] = 1;
		    NewMailCounter[i] = 0;
		}
	    } else {
		IsNew = 1;
		IStatus[i] = 0;
		GStatus[i] = 0;
		NewMailCounter[i] = 0;
	    }
/************************************************************/
	    iCheckingMailbox = 0;
	}
	Result |= (Prev != GStatus[i]);
    }
    /* Check for execute and beep */
    if (ExecFlag)
	system(NewMailExecute);
    if (Beep && BeepFlag)
	XBell(Disp, 0);

    return Result;
}

/****************************************************************************/
int NoOfNewMail(char *Mbox)
{
    FILE *MailFile = 0;
    char Buffer[30] = "";
    int NewMailn = 0;

    MailFile = fopen(Mbox, "r");

    if (MailFile == NULL)
	return 0;

    while (!feof(MailFile)) {
	fgets(Buffer, 29, MailFile);
	if (!strncmp(Buffer, "From ", 5))
	    NewMailn++;
	else if ((!strncmp(Buffer, "Status: RO", 10)) ||
		 (!strncmp(Buffer, "Status: OR", 10)))
	    NewMailn--;
    }
    fclose(MailFile);

    return NewMailn;
}

/****************************************************************************/
int IsNewMail(char *Mbox)
{
    FILE *MailFile = 0;
    char Buffer[30] = "";
    int WasStatus = 1;
    int NewMailn = 0;

    MailCounter = 0;
    MailFile = fopen(Mbox, "r");

    if (MailFile == NULL)
	return 0;

    while (!feof(MailFile)) {
	fgets(Buffer, 29, MailFile);
	if (!strncmp(Buffer, "From ", 5)) {
	    MailCounter++;
	    if (!WasStatus)
		NewMailn++;
	    WasStatus = 0;
	} else if ((!strncmp(Buffer, "Status: RO", 10)) ||
		   (!strncmp(Buffer, "Status: RO", 10)))
	    WasStatus = 1;
    }
    fclose(MailFile);

    return (NewMailn || !WasStatus);
}

/****************************************************************************/
int IsMail(char *Mbox)
{
    FILE *MailFile = 0;
    int Ret = 0;

    MailFile = fopen(Mbox, "r");
    if (MailFile == 0)
	Ret = 0;
    else {
	fgetc(MailFile);
	if (feof(MailFile))
	    Ret = 0;
	else
	    Ret = 1;

	fclose(MailFile);
    }

    return Ret;
}

/****************************************************************************/
int GetGStatus(void)
{
    int i;
    int j = 0;

    /* Get highest GStatus */
    for (i = 0; i < NumOfMailBoxes; i++)
	if (j < GStatus[i])
	    j = GStatus[i];
    return j;
}

/****************************************************************************/
void GetXPM(int Shaped)
{
    /* Create default icons */
    NoMail = (XpmIcon *) calloc(1, sizeof(XpmIcon));
    OldMail = (XpmIcon *) calloc(1, sizeof(XpmIcon));
    NewMail = (XpmIcon *) calloc(1, sizeof(XpmIcon));

    if (Shaped) {
	/* Shaped */
	XPMError(XpmCreatePixmapFromData(Disp, Root,
					 nomail_s,
					 &NoMail->pixmap,
					 &NoMail->mask,
				   &NoMail->attributes), "nomale_s.xpm");
	XPMError(XpmCreatePixmapFromData(Disp, Root,
					 newmail_s,
					 &NewMail->pixmap,
					 &NewMail->mask,
				 &NewMail->attributes), "newmail_s.xpm");
	XPMError(XpmCreatePixmapFromData(Disp, Root,
					 oldmail_s,
					 &OldMail->pixmap,
					 &OldMail->mask,
				 &OldMail->attributes), "oldmail_s.xpm");
    } else {
	/* Normal */
	XPMError(XpmCreatePixmapFromData(Disp, Root,
					 nomail,
					 &NoMail->pixmap,
					 &NoMail->mask,
				     &NoMail->attributes), "nomail.xpm");
	XPMError(XpmCreatePixmapFromData(Disp, Root,
					 newmail,
					 &NewMail->pixmap,
					 &NewMail->mask,
				   &NewMail->attributes), "newmail.xpm");
	XPMError(XpmCreatePixmapFromData(Disp, Root,
					 oldmail,
					 &OldMail->pixmap,
					 &OldMail->mask,
				   &OldMail->attributes), "oldmail.xpm");
    }

    NoMail->next = (struct XpmIcon *) NoMail;
    OldMail->next = (struct XpmIcon *) OldMail;
    NewMail->next = (struct XpmIcon *) NewMail;

    /* Set startup-status to Nomail */
    Current = NoMail;
}

/****************************************************************************/
void LoadXPMFile(XpmIcon * Icon, char *XpmFile)
{
    XPMError(XpmReadFileToPixmap(Disp, Root,
				 XpmFile,
				 &Icon->pixmap,
				 &Icon->mask,
				 &Icon->attributes), XpmFile);

    /* Check if mask is ok */
    if (Icon->mask == 0) {
	fprintf(stderr, "asmail: '%s' does not have a transparent color\n", XpmFile);
	exit(1);
    }
}

/****************************************************************************/
void XPMError(int Code, char *FileName)
{
    switch (Code) {
    case XpmSuccess:
	break;
    case XpmColorError:
    case XpmColorFailed:
	fprintf(stderr, "asmail: not enough colors free for loading '%s'\n", FileName);
	break;
    case XpmOpenFailed:
	fprintf(stderr, "asmail: could not open '%s'\n", FileName);
	break;
    case XpmFileInvalid:
	fprintf(stderr, "asmail: invalid xpm '%s'\n", FileName);
	break;
    case XpmNoMemory:
	fprintf(stderr, "asmail: not enough memory free for loading '%s'\n", FileName);
	break;
    default:
	fprintf(stderr, "asmail: unknown error '%s'\n", FileName);
	break;
    }

    if (Code < 0)
	exit(1);
}

/****************************************************************************/
Pixel GetColor(char *ColorName)
{
    XColor Color;
    XWindowAttributes Attributes;

    XGetWindowAttributes(Disp, Root, &Attributes);
    Color.pixel = 0;

    if (!XParseColor(Disp, Attributes.colormap, ColorName, &Color))
	fprintf(stderr, "asmail: could not parse color '%s', using black\n", ColorName);
    else if (!XAllocColor(Disp, Attributes.colormap, &Color))
	fprintf(stderr, "asmail: could not allocate color '%s', using black\n", ColorName);

    return Color.pixel;
}

/* END OF FILE ************************************************************* */
