
/*
 *	MAILCHK.C
 *
 *	DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
 *
 *      Check the mailbox and reports if new mail
 *      has arrived.
 *      
 *      Written by S. Laroche.  
 *    
 *      Usage:  mailchk -N(host) -q -d -t(time)
 *              -d:  Display old mail on startup, if it exists
 *              -q:  Quiet, don't display old mail on startup
 *              Default:  -d
 *
 *              -t:  (time) is the number of seconds between checks.
 *              Default:  40 seconds
 *
 *              -h:  help message
 *
 *      Arp.library is needed... (Version 39.1)
 *      File requester doesn't work, or at least, not with this code.
 */

#include <stdio.h>
#include <local/typedefs.h>
#include <arp/arpbase.h>
#include "/dnet/channel.h"
#include "/server/servers.h"
#include <local/deemu.h>

short Deemu[] = {
    DMSTRT, 0, 0,
    DMNW  , 0, 10, 2, 2, -80, 40, 0xFFFF,
    DMEND , 0, 0
};

#define DMNWOFF 4

ITEXT IText[] = {
    { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"View"           },
    { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"Print"          },
    { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"Delete"         },
    { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"Save"           },
    { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"Version"        },
    { 0, 1, JAM2, 0, 0, NULL, (ubyte *)"Remove"         }
};

ITEM Item[] = {
    { &Item[1], 0, 0, 100, 10, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&IText[0], NULL, 'v' },
    { &Item[2], 0,10, 100, 10, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&IText[1], NULL, 'p' },
    { &Item[3], 0,20, 100, 10, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&IText[2], NULL, 'd' },
    { &Item[4], 0,30, 100, 10, ITEMTEXT|COMMSEQ|HIGHCOMP, 0, (APTR)&IText[3], NULL, 's' },
    { &Item[5], 0,40, 100, 10, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0, (APTR)&IText[4], NULL},
    { NULL    , 0,50, 100, 10, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&IText[5], NULL, 'r' }
};

MENU Menu[] = {
    { NULL    , 0, 0, 100, 10+50, MENUENABLED, "MailChk", &Item[0] }
};

#define NA  0
#define MAILLENGTH 132

ubyte Title[128];

NW Nw = {
    0, 0, 320, 50, -1, -1,
    NEWSIZE|MENUPICK|CLOSEWINDOW|MOUSEBUTTONS,
    WINSTD|NOCAREREFRESH,
    NULL, NULL, Title, NULL, NULL,
    32, 18, -1, -1, WBENCHSCREEN
};

struct MailMsg {
  char msg[MAILLENGTH];
  struct MailMsg *next;
};

struct MailMsg *MailP=NULL;

WIN *Win = NULL;
RP  *Rp;

/* int Enable_Abort; */

long IntuitionBase;
long GfxBase;
long ArpBase;

main(ac,av)
char *av[];
{
    long chan = NULL;
    long numsecs = 40L;
    char firstrun = 1;
    char *host = NULL;

    ArpBase = (long)OpenLibrary(ArpName,39L);
    if (ArpBase == NULL) exit(1);
    {
      register short i;
      for (i = 1; i < ac; ++i) {
        if (strncmp(av[i],"-h",2) == 0) {
            Printf("MAILCHK - Stephane Laroche February 5, 1990\n");
            Printf("DNET    - (C) Matthew Dillon 1988\n");
            Printf("\nUsage:  -t(time) Interval between checks in seconds [DEFAULT = 40 seconds]\n");
            Printf("        -d Display mailbox on start-up [Default]\n");
            Printf("        -n Don't display mailbox on start-up\n");
            Printf("        -h This message...\n");
            exit(0);
        }
        if (strncmp(av[i], "-N", 2) == 0) {
            host = av[i]+2;                
            continue;               
        }
        if (strncmp(av[i],"-d",2) == 0) {
            firstrun = 1;
            continue;
        }
        if (strncmp(av[i],"-n",2) == 0) {
            firstrun = 0;
            continue;
        }
        if (strncmp(av[i],"-t",2) == 0) {
            numsecs = atoi(av[i]+2);
            continue;
        }
      }
    }


    Enable_Abort = 0;
    IntuitionBase = (long)OpenLibrary("intuition.library", 0);
    GfxBase = (long)OpenLibrary("graphics.library", 0);
    chan = DOpen(host, PORT_MAILCHK, 0, 0);
    if (chan == NULL) {
	Puts("no connect");
	goto fail;
    }
    InitDeemuNW(Deemu+DMNWOFF, &Nw);
    if (initmailserver(chan,numsecs,firstrun))
         checkmail(chan,numsecs);

fail:
    if (Win)
	CloseWindow(Win);
    if (chan)
	DClose(chan);
    if (IntuitionBase)
	CloseLibrary(IntuitionBase);
    if (GfxBase)
	CloseLibrary(GfxBase);
    if (ArpBase)
        CloseLibrary(ArpBase);
}

initmailserver(chan,numsecs,firstrun)

long chan, numsecs;
char firstrun;

{
  char init = 4;

    if ((DWrite(chan,&init,1) == 1) && (DWrite(chan,&numsecs,4) == 4)
         && (DWrite(chan,&firstrun,1) == 1)) return(1);
    return(0);

}
checkmail(chan,numsecs)

long chan, numsecs;

{
    long imask=0, dmask, mask;
    char notdone = 1, nowindow = 0;
    ULONG prsec = 0, prmic = 0;
    BYTE pos, oldpos = 0;

    dmask   = 1 << ((PORT *) chan)->mp_SigBit;
    imask   = 0;
    while (notdone) {
	mask = Wait(imask|dmask|SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_E);
	if (mask & SIGBREAKF_CTRL_C) {
	    notdone = 0; break; }
        if (mask & SIGBREAKF_CTRL_E)
            initmailserver(chan,numsecs,2);
	if (mask & imask) {
	    IMESS *im;
	    while (im = GetMsg(Win->UserPort)) {
		switch(im->Class) {
		case NEWSIZE: 
		    dispnewmail(pos,0,1);
		    break;
		case MOUSEBUTTONS:
		    if (im->Code == SELECTUP) {
		      if (DoubleClick(prsec,prmic,im->Seconds,im->Micros)
                          && pos == oldpos) {
			if (pos > 0) {
			    getmailmsg(chan,pos,0);
                        }
		      }
		      else {
			  prsec = im->Seconds;
			  prmic = im->Micros;
			    }
		      if (pos == 0) dispnewmail(0,oldpos,0);
                      else oldpos = pos;
		    }
		    else if (im->Code == SELECTDOWN) {
                             register short i=1; 
                             short temp;
  			     struct MailMsg *p = MailP;

  			     temp = (im->MouseY - Win->BorderTop) / Rp->TxHeight + 1;
  			     while ( i != temp && p != NULL) { 
    				i++;
    				p = p->next;
  			     }
  			     if (p == NULL) { oldpos = pos; pos = 0;}
                	     else { pos = temp;
                                    dispnewmail(pos,oldpos,0);
                                  }
			 }
		    break;
		case CLOSEWINDOW:
		    nowindow = 1;
		    break;
	        case MENUPICK:
		    switch((uword)((MENUNUM(im->Code)<<8)|ITEMNUM(im->Code))) {
		    case 0x0000:    /*	View 	*/
			getmailmsg(chan,pos,0);
                        break;
		    case 0x0001:    /*	Print	*/
                        getmailmsg(chan,pos,1);
                        break;
                    case 0x0002:    /*  Delete	*/
                        delmailmsg(chan,pos);
                        break;
                    case 0x0003:
                        getmailmsg(chan,pos,2);
                        break;
                    case 0x0004:
                        sprintf(Title, "MailChk V%s%s - S. Laroche 1990", VERSION, MAILCHK_VERSION); 
                        SetWindowTitles(Win,Title,-1);
                        break;
                    case 0x0005:
                        notdone = 0;
                        break;
                    }	
		}
                ReplyMsg(im);
	    }
	}
	if (mask & dmask) {
	    char len = 0;

	    if (DRead(chan, &len, 1) == 1) {
		if (len < sizeof(Title) && DRead(chan, Title, len) == len) {
		    Title[len-1] = 0;
		    if (strncmp(Title,"No mail",7) == 0) nowindow = 1;
		    else { if (strncmp(Title,"New mail",8) == 0) {
			       DisplayBeep(NULL);
			   }
			   if (Win == NULL) {
			       Win = OpenWindow(&Nw);
			       if (Win != NULL) {
				   Rp = Win->RPort;
                                   SetMenuStrip(Win,Menu);
				   imask   = 1 << Win->UserPort->mp_SigBit;
			       }
			   }
			   else WindowToFront(Win);
			   {
                            short temp=0;
                            char buf[25], buf2[9];

    			    getnewmail(chan,&temp);
                            if (temp > 1) strcpy(buf2,"messages");
                            else strcpy(buf2,"message");
			    sprintf(buf," (%d %s)",temp,buf2);
                            strcat(Title,buf);
			    dispnewmail(0,0,1);
                           }
			   if (Win != NULL) SetWindowTitles(Win, Title, -1);
                           else Puts(Title);
		    }
		}
	    }
	    else notdone = 0;
	}
	if (nowindow && Win) {
            ClearMenuStrip(Win);
	    CloseWindow(Win);
	    Win = NULL;
	    imask = 0;
	}
	nowindow = 0;
    }

    freemail(MailP);
    if (Win) {
        ClearMenuStrip(Win);
	CloseWindow(Win);
	Win = NULL;
    }
}

/*
 *  Utility routines.	************************************************
 */

getnewmail(chan,count)

long chan;
register short *count;

{
  char len = 1;
  struct MailMsg *p;
  
  freemail(MailP);
  if (DWrite(chan, &len, 1) == 1 && DRead(chan, &len, 1) == 1) {
      while (len > 0) {   
        if (MailP) { 
            p->next = AllocMem(sizeof(*p),0);
            p = p->next;
        }
        else {
            MailP = AllocMem(sizeof(*p),0);
            p = MailP;
        }
        if (p == NULL) break;
        else p->next = NULL; 
        if (len < MAILLENGTH && (DRead(chan, p->msg, len) == len)) { 
            DRead(chan,&len,1);
            if (Win == NULL) p->msg[len-1] = 0;
            (*count)++;
        }
        else break;
        
      }
  }
}

dispnewmail(ONmsgno,OFFmsgno,flag)

BYTE ONmsgno, OFFmsgno, flag;

{
  char th, tb, tw;
  short y, Wh, Ww, WOx, WOy;
  int len;
  struct MailMsg *p;
  BYTE i=1;

  p = MailP;
  if (Win != NULL) {
      th = Rp->TxHeight;
      tb = Rp->TxBaseline;
      tw = Rp->TxWidth;
      y = Win->BorderTop;
      Ww = Win->Width - Win->BorderRight - Win->BorderLeft;
      Wh = Win->Height- Win->BorderTop - Win->BorderBottom;
      WOx = Win->BorderLeft;
      WOy = Win->BorderTop;
      if (flag) {
	  SetAPen(Rp, 0);
	  RectFill(Rp, WOx, WOy, Ww + WOx, Wh + WOy);
      }
  }
  while (p != NULL && ((Win == NULL) || ((y+tb) < Wh))) {
    short tl;

    if (! Win && flag) Puts(p->msg);
    else { if (flag || i == ONmsgno || i == OFFmsgno) {
               if (ONmsgno == i) {
                   SetBPen(Rp,2);
                   SetAPen(Rp,0);
               }
               else {
                   SetAPen(Rp,2);
                   SetBPen(Rp,0);
               } 
               len = strlen(p->msg);
	       tl = TextLength(Rp,p->msg,len);
	       if (tl > Ww) len = Ww / tw;
	       Move(Rp,Win->BorderLeft,y+tb);
	       Text(Rp,p->msg,len);
               if (ONmsgno == i) SetAPen(Rp,2);
               else if (OFFmsgno == i || flag) SetAPen(Rp,0);
	       RectFill(Rp,Rp->cp_x,y,Ww+WOx,y+th-1);
           }
 	   y += th;
	   i++;
    }
    p = p->next;
  }
}

delmailmsg(chan,msgno)

long chan;
BYTE msgno;

{
  register BYTE i=1;
  struct MailMsg *p = MailP;
  char dummy[32];
  BYTE dl = 3, ok;
  unsigned long stchar = 0,nochars;

  for (i=1; (i != msgno && p != NULL); i++) {
    getmailprm(p,&nochars,dummy);
    stchar += nochars;
    p = p->next;
  }
  if (p == NULL) return();
  getmailprm(p,&nochars,dummy);
   
  if ((DWrite(chan,&dl,1) == 1) &&
      (DWrite(chan,&stchar,4) == 4) &&
      (DWrite(chan,&nochars,4) == 4) &&
      (DRead(chan,&ok,1) == 1)) {
      if (ok) {
          freemail(MailP);
          strcpy(Title,"Delete successful, refreshing...");
          SetWindowTitles(Win,Title,-1);
          dispnewmail(0,0,1);
      }
  }
}

int getmailmsg(chan,msgno,flag)

long chan;
BYTE msgno, flag;

{
  struct MailMsg *p = MailP;
  BYTE i, ok=0, hd = 2, l, start = 0;
  unsigned long stchar=0, nochars, len;
  long fh;
  ubyte *buf;
  char pname[128], vname[100], title[132], *tmp;
  int rcode = 1;
  struct NewShell *NS;
  struct FileRequester *FileReq;

  if (NS = AllocMem(sizeof(*NS)+4096,MEMF_CLEAR|MEMF_PUBLIC)) {
      NS->nsh_StackSize = 4000;
      NS->nsh_Control = BACKGROUND_SHELL;
  }
  else return(rcode);
  strcpy(vname,"DPIPE:Mail");
  switch (flag) {
    case 0:
      if ((tmp = GetDEnv("PAGER")) == NULL) {
          strcpy(pname,"sys:utilities/more");
      }
      else { strcpy(pname,tmp);
             free(tmp);
      }
      strcat(pname," ");
      strcat(pname,vname);
      strcpy(title,"Viewing ");
      start = 1;
      break;
    case 1:
      strcpy(vname,"PRT:");
      strcpy(title,"Printing ");
      break;
    case 2:
      { /*struct DefaultTracker *TR;*/

      strcpy(title,"Saving ...");
/*      FileReq = ArpAllocFreq(); 
      TR = LastTracker; 
      FileReq->fr_Hail = "MAILCHK:  Save to which file?"; 
      FileReq->fr_Dir = "MAIL:";
      FileReq->fr_Window = Win; 
      if (!(FileRequest(FileReq))) {             ->  Doesn't work... why?  
           FreeTrackedItem(TR);  return(rcode);}
      printf("vname= %s\n",vname);
      strcpy(vname,FileReq->fr_Dir);
      TackOn(vname,FileReq->fr_File); 
      FreeTrackedItem(TR); */
      return(rcode);
      } 
      break;
  }
  buf = (ubyte *) (NS + sizeof(*NS));
  l = strlen(title);
  for (i=1; (i != msgno && p != NULL); i++) {
    getmailprm(p,&nochars,title+l);
    stchar += nochars;
    p = p->next;
  }
  if (p == NULL) return(rcode);
  getmailprm(p,&nochars,title+l);
  if (flag == 0) {
      strcat(title," using ");
      strcat(title,pname);
  }
  SetWindowTitles(Win, title, -1);
  if (fh = Open(vname,1006)) {
      if (DWrite(chan, &hd, 1) == 1 && DWrite(chan, &stchar, 4) == 4
	  && DWrite(chan,&nochars,4) == 4) {
	  while (DRead(chan,&len,4) == 4 && len > 0) {
            if (DRead(chan,buf,len) == len) {
	        if (Write(fh,buf,len) != len) {
                    ok = 1;
		    DWrite(chan,&ok,1);
		    rcode = 0;
		    break;
		}
                if (start) {
                    if (ASyncRun(pname,0L,NS) < 0) {
                        ok = 1;
                        DWrite(chan,&ok,1);
                        rcode = 0;
                        break;
                    }
                    start = 0;
                }
	        DWrite(chan,&ok,1);
	    }
          }
      }
      Close(fh);
  }
  else {
	rcode = 0;
  }
  SetWindowTitles(Win,Title,-1);
  FreeMem(NS,sizeof(*NS)+4096);
  return(rcode);
}

getmailprm(p,nochars,title)

struct MailMsg *p;
unsigned long *nochars;
char *title;

{
  char *str;

  if (str = index(p->msg,'/')) {
      sscanf(++str,"%ld %s",nochars,title);
  }
  else *nochars = 0;
}

freemail(p)

struct MailMsg *p;

{
  while (p != NULL) {
    FreeMem(p,sizeof(*p));
    p = p->next;
  }
  MailP = NULL;
}


