#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include <fcntl.h>
#include <stat.h>
#include <exec/types.h>
#include <libraries/dosextens.h>

#include <devices/tpt.h>

#include <dlg/dlg.h>
#include <dlg/user.h>
#include <dlg/msg.h>
#include <dlg/input.h>
#include <dlg/menu.h>
#include <dlg/resman.h>
#include <dlg/log.h>
#include <dlg/file.h>
#include <dlg/misc.h>

#include <link/io.h>

#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/dlg.h>

#include <pragmas/dlg.h>

#include <private/Version.h>
#define  ObjRev "1"
const UBYTE version[]="\0$VER: MsgUsers " BUILDVER "." ObjRev " ©" COPYRIGHT " by Digerati Dreams "__AMIGADATE__;


void  main(int , char **);
int   HandleBuiltIn(UBYTE);
void _CXBRK(void);

void  AAdd_User(void);
BYTE  Get_UserName(char *);
BYTE  Area_Check(long);
BOOL  Area_Append(long);
void  UList_Area(void);
long  ADelete_User(char *, long);
void  ACopy_Users(void);
BOOL  EditUserArea(long, char *);
void  AA_Flags(struct Msg_Log *);


#define INSTACK RStruct.Command_Stack[0]
#define STK     RStruct.Command_Stack
#define HOT     UserDat.Hot_Keys

struct USER_DATA  UserDat;
struct Ram_File   RStruct;
struct Msg_Log    Log;
struct Msg_Area   Area;

char              Ext[4];
char              Overlay      =  FALSE;
char              MenuName[13] = "MSGU_Main";
char              exitflag     =  FALSE;

struct NewShortMenu Menu[8] = {{"Abort",1},
                               {"MSGU_Add",1},
                               {"MSGU_AreaCopy",1},
                               {"MSGU_Delete",1},
                               {"MSGU_Edit",1},
                               {"MSGU_Exit",1},
                               {"MSGU_List",1},
                               {"MSGU_ListArea",1}
                              };

BPTR               sout;
struct Library    *DLGBase = NULL;
struct LangStruct *ls;
char             **SA;

void main(int argc,char **argv)

{char *s;
 char *stack = NULL;

 sout = Output();
 if (!(DLGBase = OpenLibrary(DLGNAME, DLGVERSION)))  exit(5);

 while(--argc>0)
      {s = *++argv;
       if (*s++=='-')
          {while(*s)
                {switch(toupper(*s))
                       {case 'O': Overlay=TRUE;
                                  break;

                        case 'S': if (!--argc)  break;
                                  stack = *++argv;
                                  break;

                        case 'M': if (!--argc)  break;
                                  strncpy(MenuName,*++argv,12);
                                  MenuName[12] = 0;
                                  break;
                       }
                 s++;
                }
          }
      }


 if (GetDevName(Ext)==-1)              _CXBRK();
 if (!ReadUser(&RStruct,&UserDat,Ext))  _CXBRK();
 if (stack)                             InsertStack(STK, stack);

 if (!(ls = GetLang(Ext)))             _CXBRK();
 SA = ls->strings;


 WriteLog(SYSOP_CONFIG, RStruct.Name, Ext, SA[1415]);

 while(!exitflag)
      {Chk_Abort();

       if (MenuInput(MenuName,Ext,"MSGU",Menu,8,HandleBuiltIn,&UserDat,&RStruct,UserDat.Help_Level,NULL)==MENUNOTFOUND)
          _CXBRK();
      }

 _CXBRK();
}


int HandleBuiltIn(UBYTE cmd)

{SHORT  area;
 char   string[128];
 char   name  [40];
 struct USER_DATA TempUser;

 switch(cmd)
       {case 0:         /* Abort */
                exitflag = TRUE;
                break;

        case 1:         /* MSGU_Add */
                AAdd_User();
                break;

        case 2:         /* MSGU_AreaCopy */
                ACopy_Users();
                break;

        case 3:         /* MSGU_Delete */
                area = iinput(1,9999,0, SA[1416]);
                AFPrintf(NULL, sout, "\n\n");
                if (!area)  break;

                for(;;)
                   {if (Get_UserName(name))
                       {AFPrintf(&UserDat, sout, SA[1417]);
                        break;
                       }

                    if (ADelete_User(name, area))
                        AFPrintf(&UserDat, sout, SA[1418]);
                      else
                        AFPrintf(&UserDat, sout, SA[1419]);
                   }
                break;

        case 4:         /* MSGU_Edit */
                if (Get_UserName(name))
                   {AFPrintf(&UserDat, sout, SA[1420]);
                    break;
                   }
                EditUserArea(iinput(1,9999,0, SA[1421]),name);
                break;

        case 5:         /* MSGU_Exit */
               _CXBRK();
                break;
 
        case 6:         /* MSGU_ListArea */
                UList_Area();
                break;

        case 7:         /* MSGU_List */
                if (Get_UserName(name))
                   {AFPrintf(&UserDat, sout, SA[1420]);
                    break;
                   }

                ASPrintf(NULL, string, "USER:%s/User.data", name);
                UnderScore(string);
                GetFirstStruct(string, (char *)&TempUser, sizeof(TempUser));
                ListAreas(name, &TempUser, 0, 0);
                AFPrintf(NULL, sout, "\n");
                break;
       }

 return(TRUE);
}


void _CXBRK(void)

{WriteRam(&RStruct,Ext);

 if (!Overlay)  ChainProgram("DLG:Menu", Ext);
 CloseLibrary(DLGBase);

 exit(0);
}


void AAdd_User(void)

{SHORT area;

 area = iinput(1,9999,0, SA[1422]);
 AFPrintf(NULL, sout, "\n\n");
 if (!area)
    {AFPrintf(&UserDat, sout, SA[1420]);
     return;
    }

 if (!ReadArea(area, &Area, 0))
    {AFPrintf(&UserDat, sout, SA[1423]);
     return;
    }

 for(;;)
    {char retval;

     if ((retval=Get_UserName(Log.Name))==-1)
        {AFPrintf(&UserDat, sout, SA[1417]);
         return;
        }

     if (retval==1)  continue;
     if (!Area_Check(area))
        {AFPrintf(&UserDat, sout, SA[1424]);
         continue; 
        }

     Log.High_Mess =   0;
     Log.uflag     =   0;
     Log.dflag     =   0;
     Log.special   = TRUE;
     if (Area_Append(area))
         AFPrintf(&UserDat, sout, SA[1425]);
       else
         AFPrintf(&UserDat, sout, SA[1426]);
    }
}


BYTE Get_UserName(char *name)

{long  zflag;

 zflag = DLGInput(NULL,name,NULL,38,255,3, SA[1427]);
 AFPrintf(NULL, sout, "\n\n");
 if (!zflag)  return(-1);

 Upper(name);
 if (CheckUser(name) != 1)
    {AFPrintf(&UserDat, sout, SA[1428],name);
     return(1);
    }

 return(0);
}


BYTE Area_Check(long area)

{char filename[80];

 ASPrintf(NULL, filename,"MSG:%d/User.Msg",area);
 if (GetStruct(filename,(char *)&Log,sizeof(Log),36))
     return(1);

 return(0);
}  


BOOL Area_Append(long area)

{char filename[80];

 ASPrintf(NULL, filename,"MSG:%d/User.Msg",area);
 if (AddStruct(filename,(char *)&Log,sizeof(Log),36)==-1)
     return(FALSE);

 return(TRUE);
}


void UList_Area(void)

{SHORT area;
 int   fp;
 char  filename[80];

 area = iinput(1,9999,0, SA[1436]);
 AFPrintf(NULL, sout, "\n\n");
 if (!area)
    {AFPrintf(&UserDat, sout, SA[1420]);
     return;
    }

 if (!ReadArea(area, &Area, 0))
    {AFPrintf(&UserDat, sout, SA[1423]);
     return;
    }

 ASPrintf(NULL, filename,"MSG:%d/User.Msg", area);
 if ((fp = open(filename,O_RDONLY)) == EOF)
    {AFPrintf(&UserDat, sout, SA[1437]);
     return;
    }

 AFPrintf(&UserDat, sout, SA[1438]);
 AFPrintf(&UserDat, sout, SA[1439]);

 while(read(fp, &Log, sizeof(Log)) == sizeof(Log))
      {AFPrintf(&UserDat, sout, SA[1440], Log.Name, Log.High_Mess);
       AFPrintf(&UserDat, sout, SA[1441], (Log.dflag&Enter_Priv)?'E':'-',
                                         (Log.dflag&Kill_Priv)?'K':'-',
                                         (Log.dflag&Forward_Priv)?'F':'-',    
                                         (Log.dflag&Hurl_Priv)?'C':'-',
                                         (Log.dflag&Re_Edit)?'R':'-',
                                         (Log.dflag&Sysop_Access)?'S':'-');

       AFPrintf(&UserDat, sout, SA[1442], (Log.uflag&Enter_Priv)?'E':'-',
                                         (Log.uflag&Kill_Priv)?'K':'-',
                                         (Log.uflag&Forward_Priv)?'F':'-',    
                                         (Log.uflag&Hurl_Priv)?'C':'-',
                                         (Log.uflag&Re_Edit)?'R':'-',
                                         (Log.uflag&Sysop_Access)?'S':'-');
      }

 AFPrintf(&UserDat, sout, SA[1443]);
 close(fp);
 Pause();
}


long ADelete_User(char *name, long area)

{char filename[80];

 ASPrintf(NULL, filename, "MSG:%d/User.Msg", area);

 strcpy(Log.Name,name);
 Upper(Log.Name);

 return(DeleteStruct(filename, (char *)&Log, sizeof(Log), 36));
}


void ACopy_Users(void)

{SHORT area1;
 SHORT area2;
 int   fp;
 char  filename[80];

 if ((area1 = iinput(1,9999,0, SA[1444])) == 0)
    {AFPrintf(&UserDat, sout, SA[1445]);
     return;
    }
 AFPrintf(NULL, sout, "\n\n");

 if ((area2 = iinput(1,9999,0, SA[1446])) == 0)
    {AFPrintf(&UserDat, sout, SA[1445]);
     return;
    }
 AFPrintf(NULL, sout, "\n\n");

 ASPrintf(NULL, filename,"MSG:%d/User.Msg",area1);
 if ((fp = open(filename,O_RDONLY)) == EOF)
    {AFPrintf(&UserDat, sout, SA[1447]);
     return;
    }

 while(read(fp,&Log,sizeof(Log)) == sizeof(Log))
      {AFPrintf(&UserDat, sout, SA[1448], Log.Name);
       Log.High_Mess = 0;
       Log.special   = 1;

       Area_Append(area2);
       AFPrintf(&UserDat, sout, SA[1449]);
      }
 close(fp);

 AFPrintf(NULL, sout, "\n");
}


BOOL EditUserArea(long area, char *name)

{char filename[80];

 AFPrintf(NULL, sout, "\n\n");
 if (!ReadArea(area, &Area, 0))  return(1);

 ASPrintf(NULL,filename,"MSG:%d/User.Msg",area);

 strcpy(Log.Name, name);
 Upper(Log.Name);

 if (GetStruct(filename,(char *)&Log,sizeof(Log),36))
    {AFPrintf(&UserDat, sout, SA[1450]);
     return(FALSE);
    }

 AA_Flags(&Log);

 if (AddStruct(filename,(char *)&Log,sizeof(Log),36)==-1)
    {AFPrintf(&UserDat, sout, SA[1451]);
     return(FALSE);
    }

 return(TRUE);
}


void AA_Flags(struct Msg_Log *log)

{char inp[2];

 AFPrintf(&UserDat, sout, SA[1429]);

 DLGInput(NULL,inp,NULL,1,1,1, SA[1430]);
 if(inp[0]=='-') {log->dflag |=  Enter_Priv; log->uflag &= ~Enter_Priv;}
 if(inp[0]=='+') {log->uflag |=  Enter_Priv; log->dflag &= ~Enter_Priv;}
 if(inp[0]== 0 ) {log->dflag &= ~Enter_Priv; log->uflag &= ~Enter_Priv;}

 DLGInput(NULL,inp,NULL,1,1,1, SA[1431]);
 if(inp[0]=='-') {log->dflag |=  Kill_Priv; log->uflag &= ~Kill_Priv;}
 if(inp[0]=='+') {log->uflag |=  Kill_Priv; log->dflag &= ~Kill_Priv;}
 if(inp[0]== 0 ) {log->dflag &= ~Kill_Priv; log->uflag &= ~Kill_Priv;}

 DLGInput(NULL,inp,NULL,1,1,1, SA[1432]);
 if(inp[0]=='-') {log->dflag |=  Forward_Priv; log->uflag &= ~Forward_Priv;}
 if(inp[0]=='+') {log->uflag |=  Forward_Priv; log->dflag &= ~Forward_Priv;}
 if(inp[0]== 0 ) {log->dflag &= ~Forward_Priv; log->uflag &= ~Forward_Priv;}

 DLGInput(NULL,inp,NULL,1,1,1, SA[1433]);
 if(inp[0]=='-') {log->dflag |=  Hurl_Priv; log->uflag &= ~Hurl_Priv;}
 if(inp[0]=='+') {log->uflag |=  Hurl_Priv; log->dflag &= ~Hurl_Priv;}
 if(inp[0]== 0 ) {log->dflag &= ~Hurl_Priv; log->uflag &= ~Hurl_Priv;}

 DLGInput(NULL,inp,NULL,1,1,1, SA[1434]);
 if(inp[0]=='-') {log->dflag |=  Re_Edit; log->uflag &= ~Re_Edit;}
 if(inp[0]=='+') {log->uflag |=  Re_Edit; log->dflag &= ~Re_Edit;}
 if(inp[0]== 0 ) {log->dflag &= ~Re_Edit; log->uflag &= ~Re_Edit;}

 DLGInput(NULL,inp,NULL,1,1,1, SA[1435]);
 if(inp[0]=='-') {log->dflag |=  Sysop_Access; log->uflag &= ~Sysop_Access;}
 if(inp[0]=='+') {log->uflag |=  Sysop_Access; log->dflag &= ~Sysop_Access;}
 if(inp[0]== 0 ) {log->dflag &= ~Sysop_Access; log->uflag &= ~Sysop_Access;}

 AFPrintf(NULL, sout, "\n\n");
}
