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

static char *version = "\0$VER: AmigaElm 1.11 (Fri, 13 Mar 1992 23:50:31 MET)";

void MainLoop(void);
int SendmailVersion  = 0;
int MaxArticle       = 0;
int StdFontSize      = 8;
int PagerFontSize    = 8;
int IntuiFontSize    = 8;
long MailBoxLaenge   = 0L;
long MailBoxDatum    = 0L;
long FileBufferSize  = 1024L;

char *FolderName     = NULL;
char *MailTmp        = NULL;
char *UserName       = NULL;
char *HostName       = NULL;
char *RealName       = NULL;
char *MailEditor     = NULL;
char *DomainName     = NULL;
char *PrefixString   = NULL;
char *SentArchive    = NULL;
char *ReceivedFolder = NULL;
char *ReplyIntro     = NULL;
char *ForwardIntro   = NULL;
char *ColorData      = NULL;
char *FileBuffer     = NULL;
char *TBuffer        = NULL;
char *StdFontName    = "topaz.font";
char *PagerFontName  = "topaz.font";
char *IntuiFontName  = "topaz.font";
char *Pager          = NULL;
char *PubScreenName  = NULL;
char *Shell          = "newshell";
char *PipeDefault;

struct MailItem *MailList = NULL;
struct AliasItem *AliasList = NULL;

BOOL ReturnView      = FALSE; /* do not support "Return-View-To:" */
BOOL ReturnReceipt   = FALSE; /* do not support "Return-Receipt-To:" */
BOOL WantView        = FALSE; /* do not use "Return-View-To:" in every mail */
BOOL WantReturn      = FALSE; /* do not use "Return-Receipt-To:" in every mail */
BOOL ShowHeader      = FALSE; /* show only certain header lines */
BOOL ShowSig         = FALSE; /* suppress signature (if introduced by "-- \n") */
BOOL AlwaysDelete    = TRUE;  /* delete messages marked for deletion on quick exit */
BOOL AlwaysKeep      = TRUE;  /* keep read mail in incoming mailbox on quick exit */
BOOL KeepBackup      = TRUE;  /* delete *.o files after successfully saving folder */
BOOL UseOwnScreen    = TRUE;  /* open elm window on workbench or own screen */
BOOL ShanghaiWindows = TRUE;  /* shanghai mode (hijack windows) */
BOOL ReverseSorting  = TRUE;  /* reverse sort order: newest mail first, oldest last */
BOOL WBToFront       = FALSE; /* pop workbench to front for editor etc. */
BOOL UseCmdClearKludge=FALSE; /* use the "Henning Schmiedehausen CMD_CLEAR kludge" */



#ifdef LATTICE
extern int _bufsiz;
#endif


void BreakExit(int sig)
{
  signal(SIGINT,SIG_IGN);
  clean_exit(20);
}



void main(int argc,char *argv[])
{
    char alt_folder[256];

    signal(SIGINT,BreakExit);
    _bufsiz = 10240;  /* speed up level 2 i/o a little bit */

    OpenReqToolsLib();

    if (!(MailTmp=malloc(32))) clean_exit(20);
    sprintf(MailTmp,"T:AmigaElm%ld.Txt",FindTask(NULL));

    if (!(TBuffer=malloc(10240))) {     /* large enough? */
      fprintf(stderr,"elm: cannot allocate memory for text buffer\n");
      clean_exit(20);
    }

    if (argc==3 && !strcmp(argv[1],"-f")) {
      if (strchr(argv[2],':') || strchr(argv[2],'/')) {
        strcpy(alt_folder,argv[2]);
      }
      else {
        FILE *fp;
        strcpy(alt_folder,UUMAIL);
        strcat(alt_folder,argv[2]);
        if (fp=fopen(alt_folder,"r")) {
          fclose(fp);
          UserName = strdup(argv[2]);
        }
        else {
          strcpy(alt_folder,argv[2]);
        }
      }
    }
    else {
      strcpy(alt_folder,"");
    }

    if (!get_config_entries())
      clean_exit(20);

    if (!(FileBuffer=malloc(FileBufferSize))) {
      fprintf(stderr,"elm: cannot allocate memory for file buffers\n");
      clean_exit(20);
    }

    if (!strlen(alt_folder)) {
      strcpy(alt_folder,UUMAIL);
      strcat(alt_folder,UserName);
    }

    ReadAliasList();

    if (argc==2)
      if (!strcmp(argv[1],"?") || !strcmp(argv[1],"-?") || !strcmp(argv[1],"-h") || !strcmp(argv[1],"-v"))
        Usage();     /* user requests for help text */
      else
        DirectSend(argv[1],"");

    if (argc==3 && !strcmp(argv[1],"-f")) {
/*
      if (UserName) free(UserName);
      UserName = strdup(argv[2]);
*/
    }
    else if (argc==4 && !strcmp(argv[1],"-s")) {
      DirectSend(argv[3],argv[2]);
    }
    else if (argc==4 && !strcmp(argv[2],"-s")) {
      DirectSend(argv[1],argv[3]);
    }
    else if (argc==1) {
    }
    else
      Usage();

    if (!SetFolderName(alt_folder)) {
      fprintf(stderr,"elm: cannot open folder\n");
      clean_exit(5);
    }

/*
    if ((MailBoxDatum=home_box_date())==-1L) {
      fprintf(stderr,"elm: cannot get date of folder\n");
      clean_exit(5);
    }
*/
    get_folder_data(&MailBoxLaenge,&MailBoxDatum);

    OpenTTY();

    if ((MailBoxLaenge=read_home_box())==0L) {
      fprintf(stderr,"elm: folder is empty\n");
      clean_exit(5);
    }

    MainLoop();
    clean_exit(0);
}



void
MainLoop(void)
{
#define String_Len 256
    register int Aktuell = 1;
    register int page = 0;
    int MsgPerPage = Win_Height - 9;
    struct MailItem *I;
    char c;
    char String[String_Len];
    BOOL Action;
    BOOL Quit=FALSE;
    BOOL RedisplayScreen=TRUE;
    BOOL RedisplayIndex=TRUE;
    BOOL RedisplayMenu=TRUE;
    BOOL RedisplayCmd=TRUE;
    BOOL Escape=FALSE;

    /* old settings:                  */
    /* Aktuell=MaxArticle;            */
    /* page=((Aktuell-1)/MsgPerPage); */

    sprintf(String,"          Mailbox is '%s' with %d messages [ELM %s]",
            FolderName,MaxArticle,VERSION);
    SetScreenTitle(String);

    while (!Quit) {

        Action=FALSE;

        if (folder_changed(MailBoxLaenge,MailBoxDatum)) {
          status_msg("Folder has changed. Resynchronizing...",0L);
          get_folder_data(&MailBoxLaenge,&MailBoxDatum);
          if (!read_home_box())
            clean_exit(5);
          if (!MailBoxLaenge || !MailBoxDatum)
            clean_exit(5);
          page = 0;
          Aktuell = 1;
          sprintf(TBuffer,"\033[%d;1H\033[J",Win_Height);
          outline();
          RedisplayIndex=TRUE;
          sprintf(String,"          Mailbox is '%s' with %d messages [ELM %s]",
                  FolderName,MaxArticle,VERSION);
          SetScreenTitle(String);
        }

        if (RedisplayScreen)
          putst("\f ");   /* extra space for character mapped console windows */

        if (RedisplayIndex)
          NewDisplayDirectory(page,MaxArticle,Aktuell,FULL,MsgPerPage);

        if (RedisplayMenu) {
          sprintf(TBuffer,"\033[%d;1H\033[J",Win_Height-5);
          outline();
          putst_center("!=shell, |=pipe, +, -, <, >, ?=help, <n>=set current to n");
          putch('\n');
          putst_center("c)hange folder, C)opy, d)elete, e)dit, f)orward, g)roup reply, G)oto last msg,");
          putch('\n');
          putst_center("m)ail, o)ptions, p)rint, q)uit, r)eply, s)ave, u)ndelete, w)rite, or e(x)it");
          RedisplayCmd=TRUE;
        }

        if (RedisplayCmd) {
          sprintf(TBuffer,"\033[%d;1H\033[J",Win_Height-1);
          outline();
          putst("Command: ");
        }
        else {
          sprintf(TBuffer,"\033[%d;10H\033[K",Win_Height-1);
          outline();
        }

        RedisplayScreen=FALSE;
        RedisplayIndex=FALSE;
        RedisplayMenu=FALSE;
        RedisplayCmd=FALSE;

        I = i_th(Aktuell);
        flush_input();

        do {
            int i;

            if (Escape)
              Escape=!Escape;
            else
              c=getch();

            i=c;
            switch (i) {
                case 0x1b:
                case 0x9b:
                    c=getch();
                    if (c=='?') {                   /* Help    */
                        getch();
                        c='v';
                    }
                    else if ((c=='A') || (c=='T'))  /* C up    */
                        c='-';
                    else if ((c=='B') || (c=='S'))  /* C down  */
                        c='+';
                    else if (c=='C')
                        c='>';                      /* C right */
                    else if (c=='D')
                        c='<';                      /* C left  */
                    else if (c==' ') {
                        c=getch();
                        if (c=='A')                 /* C right */
                            c='>';
                        else if (c=='@')            /* C left  */
                            c='<';
                    }
                    else
                        c='\0';
                    Escape=TRUE;
                    break;
                case '+':
                case 'j':
                    if (Aktuell<MaxArticle)
                      Aktuell++;
                    if (Aktuell>(page+1)*MsgPerPage) {
                      page++;
                      RedisplayIndex=TRUE;
                    }
                    else {
                      NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    }

                    Action=TRUE;
                    break;
                case '-':
                case 'k':
                    if (Aktuell>1)
                       Aktuell--;
                    if (Aktuell<=(page*MsgPerPage)) {
                      page--;
                      RedisplayIndex=TRUE;
                    }
                    else {
                      NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    }

                    Action=TRUE;
                    break;
                case '>':
                    if (((page+1)*MsgPerPage)<MaxArticle){
                        page++;
                        Aktuell=MsgPerPage*page +1 ;
                        RedisplayIndex=TRUE;
                    }
                    Action=TRUE;
                    break;
                case '<':
                    if(page>0) {
                        page--;
                        Aktuell=MsgPerPage*page +1 ;
                        RedisplayIndex=TRUE;
                    }
                    Action=TRUE;
                    break;
                case ' ' :
                case '\r':
                    putst("Display message");
                    SetPagerFont();
                    readmail(Aktuell,ShowHeader);
                    SetStdFont();
                    Action=TRUE;
                    RedisplayScreen=TRUE;
                    RedisplayIndex=TRUE;
                    RedisplayMenu=TRUE;
                    RedisplayCmd=TRUE;
                    break;
                case '\f':
                    putst("Redisplay");
                    Action=TRUE;
                    RedisplayScreen=TRUE;
                    RedisplayIndex=TRUE;
                    RedisplayMenu=TRUE;
                    RedisplayCmd=TRUE;
                    break;
                case '$':
                    putst("Resynchronize folder");
                    SaveFolder(FALSE,MailBoxLaenge,MailBoxDatum);
                    MailBoxLaenge = MailBoxDatum = 0L;
                    Action=TRUE;
                    RedisplayCmd=TRUE;
                    break;
                case '|':
                    putst("Pipe message to command");
                    pipemail(Aktuell);
                    Action=TRUE;
                    RedisplayCmd=TRUE;
                    break;
                case '/':
                    putst("Extra Shell");
                    if (Shell)
                      Execute(Shell,NULL,NULL);
                    else
                      status_msg("shell is undefined",100L);
                    Action=TRUE;
                    RedisplayCmd=TRUE;
                    break;
                case '!':
                    putst("Shell");
                    open_shell();
                    Action=TRUE;
                    RedisplayCmd=TRUE;
                    break;
                case 'b':
                case 'B':
                    putst("Bounce message");
                    bouncemail(Aktuell,isupper(c));
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case 'c':
                    putst("Change folder");
                    if (IsReqToolsOpen() || IsAslOpen()) {
                      if (IsAslOpen()?GetAslFRQ(UUMAIL,UserName,String):GetRTFRQ(UUMAIL,UserName,String)) {
/*
                      if (GetAslFRQ(UUMAIL,UserName,String)) {
*/
                        if (SetFolderName(String))
                          MailBoxLaenge = MailBoxDatum = 0L;
                        else
                          status_msg("cannot open folder - folder not changed",100L);
                      }
                    }
                    else {
                      putst("\nChange to which folder: ");
                      getst(String,50);
                      if (strlen(String)) {
                        char alt_folder[String_Len];
                        if (String[0]=='=' && String[1]) {
                          strcpy(alt_folder,UUMAIL);
                          strcat(alt_folder,&String[1]);
                        }
                        if (SetFolderName(alt_folder) || SetFolderName(String)) {
                          MailBoxLaenge = MailBoxDatum = 0L;
                        }
                        else {
                          status_msg("cannot open folder - folder not changed",100L);
                        }
                      }
                    }
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case 'C': {
                    char Folder[String_Len];
                    putst("Copy to folder");
                    strcpy(String,"");

                    if (IsReqToolsOpen()) {
                      if (GetRTString(String,String_Len-1,"Enter filename:")) {
                        sprintf(Folder,"%s%s",UUMAIL,String);
                        writemail(Folder,1,Aktuell);
                      }
                    }
                    else {
                      putst("\nCopy message to: ");
                      getst(String,60);
                      sprintf(Folder,"%s%s",UUMAIL,String);
                      writemail(Folder,1,Aktuell);
                    }
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                }
                case 'd':
                    I->Status |= DELETED;
                    Action=TRUE;
                    if (I->next && !(I->next->Status&DELETED)) {
                      /* goto next article if it's not deleted */
                      Escape=TRUE;
                      c='+';
                    }
                    else
                      NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    break;
                case 'e':
                    putst("Edit folder");
                    LockFile(FolderName);        /* lock folder   */
                    editfile(FolderName);        /* edit folder   */
                    UnLockFile(FolderName);      /* unlock folder */
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case 'E': {
                    char Folder[String_Len];
                    strcpy(String,"");
                    putst("Save to uumail:folders/<name>");

                    if (IsReqToolsOpen()) {
                      if (GetRTString(String,String_Len-1,"Enter filename:")) {
                        sprintf(Folder,"UUMAIL:Folders/%s",String);
                        writemail(Folder,2,Aktuell);
                      }
                    }
                    else {
                      putst("\nEnter <name>: ");
                      getst(String,60);
                      sprintf(Folder,"UUMAIL:Folders/%s",String);
                      writemail(Folder,2,Aktuell);
                    }
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                }
                case 'f':
                case 'F':
                    putst("Forward");
                    forwardmail(Aktuell,isupper(c));
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case '?':
                    putst("\f \n\n");   /* extra space for character mapped console windows */
                    putst_center_bold("Short Online Help");
                    putch('\n');
                    putst_center_bold("___________________");
                    putst("\033[7;1H <number> + <RETURN> : set pointer to message #<number>\n\n");
                    putst(" + : next message (j,cursor down)    - : previous message (k,cursor up)\n");
                    putst(" < : next page (cursor left)         > : previous page (cursor right)\n");
                    putst(" ! : shell                           | : pipe to command\n");
                    putst(" $ : resynchronize folder            ? : this page of information\n");
                    putst(" m : send off new message            b : bounce (remail) message\n");
                    putst(" r : reply to message                g : group reply\n");
                    putst(" f : forward message                 G : goto last message\n");
                    putst(" w : write text to file (no header)  s : save message to file (incl. header)\n");
                    putst(" C : copy to other user's folder     E : export message (archive)\n");
                    putst(" d : delete mail                     u : undelete mail\n");
                    putst(" o : change options                  p : send mail to printer\n");
                    putst(" c : change folder                   n : mark message as unread\n");
                    putst(" P : change color palette            / : user definable shell\n");
                    putst(" q : quit                            x : exit (no change)\n");
                    putst(" Q : Quick quit                      X : Quick exit\n");
                    putch('\n');
                    putst_center_bold("(press any key)");
                    flush_input();
                    c=getch();
                    RedisplayScreen=TRUE;
                    RedisplayIndex=TRUE;
                    RedisplayMenu=TRUE;
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case 'g':
                case 'G':
                    putst("Group reply");
                    replymail(Aktuell,isupper(c),TRUE);
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case '\007':  /* ctrl-g */
                    putst("Goto last message");
                    Aktuell=MaxArticle;
                    page=((Aktuell-1)/MsgPerPage);
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    Action=TRUE;
                    break;
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    putst("New Current Message");
                    putst("                Set current message to : ");
                    String[0]=c;
                    putch(c);
                    getst(&String[1],5);
                    sscanf(String,"%d",&i);
                    if ((i<=MaxArticle)&&(i>0)) {
                        Aktuell=i;
                        if (((i-1) / MsgPerPage)!=page)
                            page=((i-1)/MsgPerPage);
                    }
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    Action=TRUE;
                    break;
                case 'h':
                    putst("Message with headers...");
                    readmail(Aktuell,TRUE);
                    Action=TRUE;
                    RedisplayScreen=TRUE;
                    RedisplayIndex=TRUE;
                    RedisplayMenu=TRUE;
                    RedisplayCmd=TRUE;
                    break;
                case 'm':
                    putst("Mail");
                    sendmail("","");
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    Action=TRUE;
                    RedisplayCmd=TRUE;
                    break;
                case 'n':
                    I->Status &= (~READ);
                    Action=TRUE;
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    break;
                case 'o':
                    set_options();
                    RedisplayScreen=TRUE;
                    RedisplayIndex=TRUE;
                    RedisplayMenu=TRUE;
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case 'p':
                    putst("Print");
                    writemail("prt:",1,Aktuell);
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case 'P':
                    putst("Color Palette");
                    RTPalette();
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case 'Q':
                case 'q':
                    if (c=='q') {
                      putst("Quit");
                      SaveFolder(TRUE,MailBoxLaenge,MailBoxDatum);
                    }
                    else {
                      putst("Quick quit");
                      SaveFolder(FALSE,MailBoxLaenge,MailBoxDatum);
                    }
                    Quit=TRUE;
                    Action=TRUE;
                    break;
                case 'r':
                case 'R':
                    putst("Reply to message");
                    replymail(Aktuell,isupper(c),FALSE);
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case 's':
                    putst("Save to folder (incl. header)");
                    strcpy(String,"");
                    if (IsReqToolsOpen()) {
                      if (GetRTString(String,String_Len-1,"Enter filename:"))
                        writemail(String,1,Aktuell);
                    }
                    else {
                      putst("\nSave message to: ");
                      getst(String,60);
                      writemail(String,1,Aktuell);
                    }
/*
                    if (writemail(String,1,Aktuell))
                      I->Status |= DELETED;
*/
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case 'u':
                    I->Status &= (~DELETED);
                    Action=TRUE;
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    break;
                case 'v':
                    putst("Version");
                    AboutElmWindow();
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case 'w':
                    putst("Write to file (text only, no header)");
                    strcpy(String,"");
                    if (IsReqToolsOpen()) {
                      if (GetRTString(String,String_Len-1,"Enter filename:"))
                      writemail(String,0,Aktuell);
                    }
                    else {
                      putst("\nWrite message to: ");
                      getst(String,60);
                      writemail(String,0,Aktuell);
                    }
                    NewDisplayDirectory(page,MaxArticle,Aktuell,UPDATE,MsgPerPage);
                    RedisplayCmd=TRUE;
                    Action=TRUE;
                    break;
                case 'x':  {
                    char chr;
                    putst("Exit");
                    sprintf(TBuffer,"\033[%d;%dH\033[JReally quit without saving changes? (y/n) n\b",
                            Win_Height-1,Win_Width-46);
                    outline();
                    do {
                      flush_input();
                      chr=getch();
                      if (chr=='\r')
                        chr='n';
                  } while (chr!='y' && chr!='n');
                    if (chr=='y') {
                      putst("Yes.");
                      Delay(25L);  /* just a moment */
                      clean_exit(0);
                    }
                    else
                      putst("No.");
                    Delay(25L);  /* just a moment */
                    Action=TRUE;
                    break;
                }
                case 'X':
                    putst("Quick exit");
                    clean_exit(0);
                    break;
            }
        } while (!Action);
    }
}
