#include "prefs.h"
#include <proto/dos.h>
#include <proto/exec.h>


Prototype void sendmail(char *, char *);
Prototype void readmail(int, int);
Prototype void replymail(int,BOOL,BOOL);
Prototype void forwardmail(int,int);
Prototype void bouncemail(int,int);
Prototype BOOL writemail(char *,int,int);
Prototype void pipemail(int);
Prototype void editfile(char *);

void PagerCommand(char *);
int lines_len(long);



void
sendmail(char *To, char *Subject)
{
  FILE *fp;
  if (fp=fopen(MailTmp,"w")) {
    CreateHeader(fp,To,Subject);
    fclose(fp);
    editfile(MailTmp);
    send_off(MailTmp,NULL);
  }
  else
    status_msg("error: cannot open temporary file - mail not sent",100L);
}



int
lines_len(long charnum)
{
  if (charnum)
    return(((charnum+Win_Width-1)/Win_Width));
  else
    return(1);
}



int
chars_len(char *string)
{
  long len = 0L;
  while(*string) {
    len++;
    if(*string=='\n') {
      len--;
      while((len-1)%Win_Width)
        len++;
    }
    else if(*string=='\f')
      *string='¿';
    else if(*string=='\t')
      while(len%8)
        len++;
    string++;
  }
  return(len);
}



void HandleReturns(struct MailItem I)
{
  if ((!(I.Status & READ)) && (I.RR_To) && (ReturnReceipt)) {
    FILE *out;
    char String[MAX_LINELENGTH];

    if (!(out=fopen(MailTmp,"w"))) {
      status_msg("error: cannot open temporary file - receipt mail not sent",100L);
    }
    else {
      CreateHeader(out,I.RR_To,"received your mail");
      if (SendmailVersion==SM_FEULNER)
        fprintf(out,"From: Mail Delivery Subsystem <MAILER-DAEMON@%s%s>\n",HostName,DomainName);
      fprintf(out,"\nYour mail to   : %s\n",I.To);
      fprintf(out,"with Subject   : %s\n",I.Subject?I.Subject:"(none)");
      fprintf(out,"and Message-Id : %s\n",I.MessageID);
      fprintf(out,"\n ... has been received and read by ...\n\n");
      fprintf(out,"\t%s <%s@%s%s>\n\n",RealName,UserName,HostName,DomainName);
      fclose(out);

      putst("\n\n\033[1m Sending receipt message ... Wait ... \033[0m");
      if (SendmailVersion==SM_FEULNER)
        sprintf(String,"sendmail <%s",MailTmp);
      else if (SendmailVersion==SM_DILLON)
        sprintf(String,"sendmail <%s -f %s -R \"%s\"",MailTmp,"MAILER-DAEMON","Mail Delivery Subsystem");
      else if (SendmailVersion==SM_OTHER)
        sprintf(String,"sendmail <%s -f %s",MailTmp,"MAILER-DAEMON");
      Execute(String,NULL,NULL);
    }
  }

  if (((I.Status & READ)!=READ) && (I.RV_To) && (ReturnView)) {
    FILE *out;
    char String[MAX_LINELENGTH];

    if (!(out=fopen(MailTmp,"w"))) {
      status_msg("error: cannot open temporary file - receipt mail not sent",100L);
    }
    else {
      CreateHeader(out,I.RV_To,"read your mail");
      if (SendmailVersion==SM_FEULNER)
        fprintf(out,"From: Mail Delivery Subsystem <MAILER-DAEMON@%s%s>\n",HostName,DomainName);
      fprintf(out,"\nYour mail to   : %s\n",I.To);
      fprintf(out,"with Subject   : %s\n",I.Subject?I.Subject:"(none)");
      fprintf(out,"and Message-Id : %s\n",I.MessageID);
      fprintf(out,"\n ... has been received and read by ...\n\n");
      fprintf(out,"\t%s <%s@%s%s>\n\n",RealName,UserName,HostName,DomainName);
      fclose(out);

      putst("\n\n\033[1m Sending receipt message ... Wait ... \033[0m");
      if (SendmailVersion==SM_FEULNER)
        sprintf(String,"sendmail <%s",MailTmp);
      else if (SendmailVersion==SM_DILLON)
        sprintf(String,"sendmail <%s -f %s -R \"%s\"",MailTmp,"MAILER-DAEMON","Mail Delivery Subsystem");
      else if (SendmailVersion==SM_OTHER)
        sprintf(String,"sendmail <%s -f %s",MailTmp,"MAILER-DAEMON");
      Execute(String,NULL,NULL);
    }
  }
}



void
readmail_ext(int Number,int full_header)
{
#define EXT_PAGER_WIDTH 80
    FILE *in,*out;
    int j,l;
    long r;
    struct MailItem I;
    char Text[MAX_LINELENGTH];

    if (Number<1 || Number>MaxArticle)
      return;

    I=*i_th(Number);

    sprintf(TBuffer,"\fExternal pager: %s, message: %d.\n",Pager,Number);
    outline();

    if (!(in=OpenHomeBox())) {
      status_msg("error: cannot open folder - mail not read",100L);
      return;
    }

    if (!(out=fopen(MailTmp,"w"))) {
      status_msg("error: cannot open mailfile - mail not read",100L);
      CloseHomeBox(in);
      return;
    }

    sprintf(Text,"Message %d/%d  From %.50s",Number,MaxArticle,I.FromName?I.FromName:I.From);
    while ((6+strlen(Text))<EXT_PAGER_WIDTH)  /* +6 (ctrl-chars, see above) -6 (length of date) */
      strcat(Text," ");
    strcat(Text,I.Date);
    fprintf(out,"%s\n\n",Text);

    if (I.Urgent)
      fprintf(out,"\n                    \033[1m (** This message is tagged Urgent **) \033[0m\n\n\n");

    if (full_header)
      j=I.ArtikelStart;
    else {
      j=I.TextStart;
      fprintf(out,"\033[1mFrom:\033[0m %s\n",I.From);
      if (I.To)
        fprintf(out,"\033[1mTo:\033[0m %s\n",I.To);
      if (I.Cc)
        fprintf(out,"\033[1mCc:\033[0m %s\n",I.Cc);
      if (I.Bcc)
        fprintf(out,"\033[1mBcc:\033[0m %s\n",I.Bcc);
      fprintf(out,"\033[1mSubject:\033[0m \033[7m%s\033[0m\n\n",I.Subject?I.Subject:"(none)");
    }

    if (ShowSig)
      l=I.ArtikelEnd;
    else
      l=I.SignatureStart;
    fseek(in,j,0);

    while(getline(in,Text,&r) && (r<=l)) {
      fprintf(out,"%s\n",Text);
    }

    CloseHomeBox(in);
    fclose(out);

    sprintf(Text,"%s %s",Pager,MailTmp);
    WorkbenchToFront();
    Execute(Text,NULL,NULL);
    ElmToFront();

    HandleReturns(I);
    i_th(Number)->Status |= READ;
}



void
readmail(int Number,int full_header)
{
    FILE *fp;
    register int k;
    int j,l;
    long r = 0L;      /* position in file */
    long lines,dl;    /* lines of text, displayed lines */
    struct MailItem I;
    char Text[MAX_LINELENGTH];
    BOOL WrongKey;
    BOOL Quit;

    if (Pager) {
      readmail_ext(Number,full_header);
      return;
    }

    if (Number<1 || Number>MaxArticle)
      return;

    I=*i_th(Number);

display_page:

    if(!(fp=OpenHomeBox())) {
      status_msg("error: cannot open folder - mail not read",100L);
      return;
    }

    Quit = FALSE;
    k = 1;
    dl = 0;

    sprintf(TBuffer,"\f\033[0 pMessage %d/%d  From %.50s",Number,MaxArticle,I.FromName?I.FromName:I.From);
    while (strlen(TBuffer)<Win_Width)  /* +6 (ctrl-chars, see above) -6 (length of date) */
      strcat(TBuffer," ");
    strcat(TBuffer,I.Date);
    strcat(TBuffer,"\n\n");
    outline();
    k++;
    k++;

    if (I.Urgent) {
      putst("\n                    \033[1m (** This message is tagged Urgent **) \033[0m\n\n\n");
      k+=4;
    }

    if (full_header) {
      j=I.ArtikelStart;
      lines=I.TotalLines;
    }
    else {
      j=I.TextStart;
      lines=I.Lines;
      sprintf(TBuffer,"\033[1mFrom:\033[0m %.*s\n",Win_Width-7,I.From);
      outline();
      k++;
      if (I.To) {
        long len = chars_len(I.To)+4;
        sprintf(TBuffer,"\033[1mTo:\033[0m %s\n",I.To);
        outline();
        k+=lines_len(len);
      }
      if (I.Cc) {
        long len = chars_len(I.Cc)+4;
        sprintf(TBuffer,"\033[1mCc:\033[0m %s\n",I.Cc);
        outline();
        k+=lines_len(len);
      }
      if (I.Bcc) {
        long len = chars_len(I.Bcc)+5;
        sprintf(TBuffer,"\033[1mBcc:\033[0m %s\n",I.Bcc);
        outline();
        k+=lines_len(len);
      }
      sprintf(TBuffer,"\033[1mSubject:\033[0m \033[7m%.*s\033[0m\n\n",Win_Width-10,I.Subject?I.Subject:"(none)");
      outline();
      k+=2;
    }

    if (ShowSig)
      l=I.ArtikelEnd;
    else
      l=I.SignatureStart;
    fseek(fp,j,0);

    while(getline(fp,Text,&r) && (r<=l) && !Quit) {
        register long ll = chars_len(Text);  /* line length */
        k+=lines_len(ll);
        if (k/Win_Height) {
            fseek(fp,r,0);   /* re-position pointer, un-read last line */
            sprintf(TBuffer,"\n  \033[7;33;41m--\033[1mMore\033[0;7;33;41m(%d%%)--\033[0m  \033[3m [d)elete,f)orward,h)eader,m)ail,q)uit,g)roup r)eply] \033[0m",(dl*100)/lines);
            outline();
            Quit = TRUE;
            do {
              int c;
              flush_input();
              c = getch();
              WrongKey=FALSE;
              switch (c) {
                  case '^':
                      CloseHomeBox(fp);
                      goto display_page;
                      break;
                  case '\r':
                      k=Win_Height-lines_len(ll)-1;
                      putst("\r\033M\033[J");
                      Quit = FALSE;
                      break;
                  case ' ' :
                      k=2;
                      putst("\r\033M\033[J");
                      Quit = FALSE;
                      break;
                  case 'd':
                      CloseHomeBox(fp);
                      i_th(Number)->Status |= DELETED;
                      break;
                  case 'h':
                      CloseHomeBox(fp);
                      full_header=!full_header;
                      goto display_page;
                      break;
                  case 'f':
                  case 'F':
                      putst("\033[ p");   /* cursor on */
                      CloseHomeBox(fp);
                      PagerCommand("Forward");
                      forwardmail(Number,isupper(c));
                      break;
                  case 'm':
                      putst("\033[ p");   /* cursor on */
                      CloseHomeBox(fp);
                      PagerCommand("Mail");
                      sendmail("","");
                      break;
                  case 'g':
                  case 'G':
                      putst("\033[ p");   /* cursor on */
                      CloseHomeBox(fp);
                      PagerCommand("Group reply");
                      replymail(Number,isupper(c),TRUE);
                      break;
                  case 'r':
                  case 'R':
                      putst("\033[ p");   /* cursor on */
                      CloseHomeBox(fp);
                      PagerCommand("Reply to message");
                      replymail(Number,isupper(c),FALSE);
                      break;
                  case 'i' :
                  case 'q' :
                      CloseHomeBox(fp);
                      break;
                  default:
                      WrongKey=TRUE;
                      break;
              }
            } while(WrongKey);
        }
        else {
          sprintf(TBuffer,"%s\n",Text);
          outline();
          dl++;
        }
    }
    putst("\033[ p");   /* cursor on */

    if (Quit) {
      HandleReturns(I);
      i_th(Number)->Status |= READ;
      return;
    }

    CloseHomeBox(fp);

    putst("\n\033[1;7;33;41m  End of Message  \033[0m  \033[3m [d)elete,f)orward,h)eader,m)ail,q)uit,g)roup r)eply] \033[0m");

    do {
      int c;
      flush_input();
      c = getch();
      WrongKey=FALSE;
      switch (c) {
          case '^':
              goto display_page;
              break;
          case '\r':
          case ' ' :
          case 'i' :
          case 'q' :
              break;
          case 'd':
              i_th(Number)->Status |= DELETED;
              break;
          case 'h':
              full_header=!full_header;
              goto display_page;
              break;
          case 'f':
          case 'F':
              PagerCommand("Forward");
              forwardmail(Number,isupper(c));
              break;
          case 'm':
              PagerCommand("Mail");
              sendmail("","");
              break;
          case 'g':
          case 'G':
              PagerCommand("Group reply");
              replymail(Number,isupper(c),TRUE);
              break;
          case 'r':
          case 'R':
              PagerCommand("Reply to message");
              replymail(Number,isupper(c),FALSE);
              break;
          default:
              WrongKey=TRUE;
              break;
      }
    } while(WrongKey);

    HandleReturns(I);
    i_th(Number)->Status |= READ;
}



struct AliasItem *list_wo_own(char *str)
{
  struct AliasItem *list,*l;
  char *adr,*p,*e;

  list = AdrsToAList(str);

  if (adr=malloc(strlen(UserName)+strlen(HostName)+strlen(DomainName)+2)) {
    sprintf(adr,"%s@%s%s",UserName,HostName,DomainName);
    for (l=list; l; l=l->next) {
      if (p=strstr(l->alias,adr)) {
        e = p+strlen(adr);
        if ((p==l->alias && (*e==' ' || *e=='\t' || *e=='\0' || *e=='('))
             ||
            (p>l->alias && *(p-1)=='<' && *e=='>')
           ) {

          free(l->alias);
          l->alias = NULL;

        }
      }
    }
  }

  return(list);
}



void
replymail(int Number,BOOL full_header,BOOL group_reply)
{
    FILE *in,*out;
    char String[MAX_LINELENGTH];
    struct MailItem I;

    if (Number<1 || Number>MaxArticle)
      return;

    if (!(out=fopen(MailTmp,"w"))) {
      status_msg("error: cannot open temporary file - mail not sent",100L);
      return;
    }

    I=*i_th(Number);

    if (I.Subject==NULL || strlen(I.Subject)<1) {
      if (I.ReplyTo)
        CreateHeader(out,I.ReplyTo,"Re: your mail");
      else
        CreateHeader(out,I.From,"Re: your mail");
    }
    else if (strnicmp(I.Subject,"Re:",3)==0) {
      if (I.ReplyTo)
        CreateHeader(out,I.ReplyTo,I.Subject);
      else
        CreateHeader(out,I.From,I.Subject);
    }
    else {
      char *subj;
      if (subj=malloc(strlen(I.Subject)+5)) {    /* + "Re: \0" */
        strcpy(subj,"Re: ");
        strcat(subj,I.Subject);
        if (I.ReplyTo)
          CreateHeader(out,I.ReplyTo,subj);
        else
          CreateHeader(out,I.From,subj);
        free(subj);
      }
    }

    if (group_reply) {
      struct AliasItem *cc_list,*to_list,*l;
      BOOL erstes = TRUE;

      to_list = list_wo_own(I.To);
      cc_list = list_wo_own(I.Cc);

      for (l = cc_list; l; l = l->next) {
        if (l->alias) {
          fprintf(out,"%s%s",erstes?"Cc: ":",\n\t",l->alias);
          erstes = FALSE;
        }
      }

      for (l = to_list; l; l = l->next) {
        if (l->alias) {
          fprintf(out,"%s%s",erstes?"Cc: ":",\n\t",l->alias);
          erstes = FALSE;
        }
      }

/*
      if (I.Cc && I.To)
        fprintf(out,"Cc: %s,\n\t%s\n",I.Cc,I.To);
      else if (I.Cc)
        fprintf(out,"Cc: %s\n",I.Cc);
      else if (I.To)
        fprintf(out,"Cc: %s\n",I.To);
*/

      if (to_list || cc_list)
        fputc('\n',out);

      FreeAliasList(&cc_list);
      FreeAliasList(&to_list);
    }

/*
    else
      if (I.Cc)
        fprintf(out,"Cc: %s\n",I.Cc);

    if (I.Bcc)
      fprintf(out,"Bcc: %s\n",I.Bcc);
*/

    fprintf(out,"\n");

    do_introduction(out,ReplyIntro,&I);

    if((in=OpenHomeBox())==NULL) {
      status_msg("error: cannot open folder - mail not sent",100L);
      fclose(out);
      return;
    }
    else {
        long r;
        if (full_header)
          fseek(in,I.ArtikelStart,0);
        else
          fseek(in,I.TextStart,0);
        while(getline(in,String,&r) && (r<=I.ArtikelEnd)) {
          fprintf(out,"%s%s\n",PrefixString,String);
        }
        CloseHomeBox(in);
        fprintf(out,"\n");
    }
    fclose(out);
    editfile(MailTmp);
    if (send_off(MailTmp,I.MessageID)==1)
      i_th(Number)->Status |= ANSWERED;
}



void
forwardmail(int Number,int full_header)
{
    FILE *in,*out;
    char String[MAX_LINELENGTH];
    char *subj;
    struct MailItem I;

    if (Number<1 || Number>MaxArticle)
      return;

    if (!(out=fopen(MailTmp,"w"))) {
      status_msg("error: cannot open temporary file - mail not sent",100L);
      return;
    }

    I=*i_th(Number);

    if (I.Subject==NULL || strlen(I.Subject)<1) {
      CreateHeader(out,"","forwarded mail");
    }
    else if (subj=malloc(strlen(I.Subject)+7)) {      /* + " (fwd)\0" */
      strcpy(subj,I.Subject);
      strcat(subj," (fwd)");
      CreateHeader(out,"",subj);
      free(subj);
    }
    else {
      CreateHeader(out,"","forwarded mail");
    }

    fprintf(out,"\n");

    do_introduction(out,ForwardIntro,&I);
    fprintf(out,"[-------------------- text of forwarded message follows --------------------]\n\n");

    if(!(in=OpenHomeBox())) {
      status_msg("error: cannot open folder - mail not sent",100L);
      fclose(out);
      return;
    }
    else {
        long r;
        if (full_header)
          fseek(in,I.ArtikelStart,0);
        else
          fseek(in,I.TextStart,0);
        while(getline(in,String,&r) && (r<=I.ArtikelEnd))
          fprintf(out,"%s\n",String);
        CloseHomeBox(in);
        fprintf(out,"\n");
    }

    fprintf(out,"[------------------------- end of forwarded message ------------------------]\n\n");
    fclose(out);

    editfile(MailTmp);
    if (send_off(MailTmp,NULL)==1)
      i_th(Number)->Status |= FORWARDED;
}



void
bouncemail(int Number,int full_header)
{
    FILE *in,*out;
    char String[MAX_LINELENGTH];
    char *subj;
    struct MailItem I;

    if (Number<1 || Number>MaxArticle)
      return;

    if (!(out=fopen(MailTmp,"w"))) {
      status_msg("error: cannot open temporary file - mail not sent",100L);
      return;
    }

    I=*i_th(Number);

    if (I.Subject==NULL || strlen(I.Subject)<1) {
      CreateHeader(out,"","bounced mail");
    }
    else if (subj=malloc(strlen(I.Subject)+10)) {      /* + " (bounce)\0" */
      strcpy(subj,I.Subject);
      strcat(subj," (bounce)");
      CreateHeader(out,"",subj);
      free(subj);
    }
    else {
      CreateHeader(out,"","bounced mail");
    }

    fprintf(out,"\n");

    do_introduction(out,ForwardIntro,&I);
    fprintf(out,"[-------------------- text of forwarded message follows --------------------]\n\n");

    if(!(in=OpenHomeBox())) {
      status_msg("error: cannot open folder - mail not sent",100L);
      fclose(out);
      return;
    }
    else {
        long r;
        if (full_header)
          fseek(in,I.ArtikelStart,0);
        else
          fseek(in,I.TextStart,0);
        while(getline(in,String,&r) && (r<=I.ArtikelEnd))
          fprintf(out,"%s\n",String);
        CloseHomeBox(in);
        fprintf(out,"\n");
    }

    fprintf(out,"[------------------------- end of forwarded message ------------------------]\n\n");
    fclose(out);

    editfile(MailTmp);
    if (send_off(MailTmp,NULL)==1)
      i_th(Number)->Status |= BOUNCED;

/*
    else {
        long r;
        fprintf(out,"On %s, %s wrote:\n\n",I.Date,I.From);
        fprintf(out,"[--------------------- text of bounced message follows ---------------------]\n\n");
        if (full_header)
          fseek(in,I.ArtikelStart,0);
        else
          fseek(in,I.TextStart,0);
        while(getline(in,String,&r) && (r<=I.ArtikelEnd)) {
          fprintf(out,"%s\n",String);
        }
        CloseHomeBox(in);
        fprintf(out,"\n");
    }
    fprintf(out,"[-------------------------- end of bounced message -------------------------]\n\n");
    fclose(out);
*/
}



BOOL
writemail(char *Name,int mode,int Number)
/* Number: 0 - short, 1 - full, 2 - archive */
{
    FILE *fp,*in;
    char *name=NULL;
    struct MailItem I;
    long r;
    register int c;

    if (Number<1 || Number>MaxArticle || !Name || !strlen(Name))
      return(FALSE);

    I=*i_th(Number);

    if (Name[0]=='=' && Name[1]) {
      name = malloc(strlen(UUMAIL)+strlen(Name));
      strcpy(name,UUMAIL);
      strcat(name,&Name[1]);
    }

    if(!(fp=fopen(name?name:Name,"a"))) {
      status_msg("error: cannot open destination file - mail not saved",100L);
      if(name) free(name);
      return(FALSE);
    }

    if(!(in=OpenHomeBox())) {
      status_msg("error: cannot open folder - mail not saved",100L);
      fclose(fp);
      if(name) free(name);
      return(FALSE);
    }

    if ((mode==0)||(mode==2))       /* write to file or folder */
        r=I.TextStart;
    else
        r=I.ArtikelStart;
    if (mode==2) {
        fprintf(fp,"\nFrom %s (ARCHIVE)\n",I.From);
        fprintf(fp,"From: %s\n",I.From);
        fprintf(fp,"Date: %s\n",I.Date);
        fprintf(fp,"Subject: %s\n",I.Subject);
    }
    fseek(in,r,0);
    while (r<=I.ArtikelEnd) {
        c=getc(in);
        putc(c,fp);
        r++;
    }
    CloseHomeBox(in);
    fclose(fp);
    i_th(Number)->Status |= LOGGED;
    if(name) free(name);
    return(TRUE);
}



void
pipemail(int Number)
{
    FILE *in,*out;
    char exec[256];
/*
    BPTR fh;
*/
    struct MailItem I;

    if (Number<1 || Number>MaxArticle)
      return;

/*
    if (!(fh=Open("con:",MODE_NEWFILE))) {
      status_msg("error: cannot open i/o window - mail not sent",100L);
      return;
    }
*/

    if (!(out=fopen(MailTmp,"w"))) {
      status_msg("error: cannot open temporary file - mail not sent",100L);
/*
      Close(fh);
*/
      return;
    }

    I=*i_th(Number);

    if(!(in=OpenHomeBox())) {
      status_msg("error: cannot open folder - mail not sent",100L);
/*
      Close(fh);
*/
      fclose(out);
      return;
    }
    else {
      long r = I.ArtikelStart;
      char c;
      fseek(in,r,0);
      while (r<=I.ArtikelEnd) {
        c=getc(in);
        putc(c,out);
        r++;
      }
    }

    CloseHomeBox(in);
    fclose(out);

    sprintf(exec,PipeDefault,MailTmp);
    Execute(exec,NULL,NULL);
/*
    Delay(100L);
    Close(fh);
*/
    remove(MailTmp);
}



void PagerCommand(char *cmd_text)
{
  int i;
  sprintf(TBuffer,"\033[%d;1H\033[J",Win_Height-3);
  outline();
  putst("\033[1m");
  for(i=0;i<Win_Width;i++)
    TBuffer[i]='_';
  TBuffer[Win_Width]='\0';
  outline();
  putst("\033[0m");
  sprintf(TBuffer,"\033[%d;1HCommand: %s",Win_Height-1,cmd_text);
  outline();
}



void editfile(char *name)
{
  char *str;
  str=malloc(strlen(MailEditor)+strlen(name)+2);
  sprintf(str,"%s %s",MailEditor,name);
  WorkbenchToFront();
  Execute(str,NULL,NULL);
  ElmToFront();
  free(str);
}
