//
// Ezycom function related class library
//

#define EZY110

#include "ezy.hpp"
#include "misc.h"
#include <dir.h>
#include <share.h>
#include <stdio.h>


void ezycom::ezycom(void)       // Constructor
    {
        node=0;
    }

void ezycom::~ezycom(void)      // Destructor
    {
        ;
    }

char *ezycom::whatdoing(int status, int wnode)
{
char what[60];
char userdoes[MAXFILEPATHLENGTH];
char *onlinedesc[]={
"Node Active        ",
"?                  ",
"Downloading        ",
"Uploading          ",
"Bimodem Transfer   ",
"Browsing Messages  ",
"External Door      ",
"Chatting with Sysop",
"Inactive           ",
"Logging In...      ",
"Waiting for Caller "
};

int ustream, length;

sprintf(userdoes,"%sUSERDOES.%d",ezydir, wnode);

if(!exists(userdoes))
{
    if (status > 7 && status < 208)
    {
        status-=8;
        sprintf(what, "Chatting (channel %d)", status);
    }
    else
        if(status > 207)
        {
        status-=245;
        sprintf(what, "%s", onlinedesc[status]);
        }
        else
            sprintf(what, "%s", onlinedesc[status]);

    return(what);
}

if((ustream=sopen(userdoes, O_RDONLY | O_TEXT, SH_DENYNO)) != NULL)
    {
    length=read(ustream, &what, 30);
    close(ustream);
    what[length]=0;  /* terminate string correctly */
    stripcr(what);
    return(what);
    }
return("Unable to Determine");
}

//
// Function: send_message      - Sends an online message
// Return values:
// 0 = Failed
// 1 = Successful
//
// SPECIAL variabe : tonode - if value is 256, message sent to all nodes with user
//      * not implemented *  online, if value is 257 Message sent to all nodes
//                           with user on that isn't up/downloading or in external
//                           door program
//


int ezycom::send_omessage(char fromuser[36], int fromnode, int tonode, char msg[81], int priv)
{
MultiMessageRecord multimsg;
char messnode[MAXFILEPATHLENGTH];
int stream;

sprintf(messnode, "%sMESSNODE.%d",config.MultiPath, tonode);
if((tonode == 0 || tonode >255) || (fromnode == 0 || fromnode > 255))
    return(0);

if((stream=sopen(messnode,O_CREAT|O_TRUNC|O_BINARY|O_WRONLY, SH_DENYNONE)) == NULL)
    return(0);

strcpy(fromuser, c_to_pas(fromuser));
strcpy(multimsg.From, fromuser);
multimsg.FromNode=fromnode;
strcpy(msg, c_to_pas(msg));
strcpy(multimsg.Message, msg);
multimsg.PrivateMsg=priv;
write(stream, &multimsg, sizeof(multimsg));
close(stream);
return(1);
}


// Fore and back in Hex please
char *ezycom::color2ezy(int fore, int back)
{
    char ec[3]; /* 2 byte string - ezycom color changer */
    sprintf(ec,"%1.1d%1.1d",back,fore);
    return(ec);
}

char *ezycom::useron(int wnode)
{
int stream;
OnlineRecord online;
char onlinebbs[MAXFILEPATHLENGTH];

sprintf(onlinebbs, "%sONLINE.BBS",config.MultiPath);
if((stream=sopen(onlinebbs, O_RDONLY | O_BINARY, SH_DENYNO)) == NULL)
    { return(NULL); }

if(wnode==0)
    lseek(stream,0L,SEEK_SET);
else
    lseek(stream, sizeof(online) * (wnode - 1), SEEK_SET);
read(stream, &online, sizeof(online));
close(stream);
strcpy(online.Name, pas_to_c(online.Name));
return(online.Name);
}


int ezycom::statusof(int node)
{
int stream;
OnlineRecord online;
char onlinebbs[MAXFILEPATHLENGTH];
sprintf(onlinebbs, "%sONLINE.BBS",config.MultiPath);
if((stream=sopen(onlinebbs, O_RDONLY | O_BINARY, SH_DENYNO)) == NULL)
    { printf("\r\nş Error opening %s", onlinebbs); return(0); }

if(node==1)
    lseek(stream,0L,SEEK_SET);
else
    lseek(stream, sizeof(online) * (node - 1), SEEK_SET);
read(stream, &online, sizeof(online));
close(stream);
return(online.Status);
}

size_t ezycom::commafmt(char *buf , // Buffer for formatted string
                int bufsize,         // Size of buffer
                long N)              // Number to convert
{
        int len = 1, posn = 1, sign = 1;
        char *ptr = buf + bufsize - 1;

        if (2 > bufsize)
        {
ABORT:          *buf = '\0';
                return 0;
        }

        *ptr-- = '\0';
        --bufsize;
        if (0L > N)
        {
                sign = -1;
                N = -N;
        }

        for ( ; len <= bufsize; ++len, ++posn)
        {
                *ptr-- = (char)((N % 10L) + '0');
                if (0L == (N /= 10L))
                        break;
                if (0 == (posn % 3))
                {
                        *ptr-- = ',';
                        ++len;
                }
                if (len >= bufsize)
                        goto ABORT;
        }

        if (0 > sign)
        {
                if (0 == bufsize)
                        goto ABORT;
                *ptr-- = '-';
                ++len;
        }

        strcpy(buf, ++ptr);
        return (size_t)len;
}

// Convert a Pascal String to a 'C' String.
char * ezycom::pas_to_c(unsigned char *st)
{
    int i;
    char tempstr[256];

    for (i=0; i<*st; i++) tempstr[i] = st[i+1];
    tempstr[i] = '\0';
	return(strcpy(st, tempstr));
}

// Convert a 'C' string to a Pascal String
char * ezycom::c_to_pas(unsigned char *st)
{
    unsigned char i, len;
    unsigned char *p;

    len = i = strlen(st);
    p = st + i;

    do {
        *(p+1) = *p;
        p--;
    } while (i--);
    *st = len;
    return(st);
}

//
// int load_config(char *overidepath)
//
//  Loads config file, converting all strings to 'C' format,
//  and adding blackslashes to all paths that don't have them
//
// Returns  :
//      0 = Unsuccessful Loading config file (not found/located)
//      1 = Successful Loading of Config/Constant File
//      2 = Ezycom Environment variable set
//      3 = Unsuccessful Loading config file (*configfile was stuffed though)
//      4 = Corrupted Config file/unsuccessful reading config file
//              (*configfile was stuffed though)
//      5 = Unsuccessful Loading constant.ezy (not found/located)
//      6 = Unsuccessful Loading constant.ezy (*constantfile stuffed though)
//      7 = Corrupted Constant file/unsuccessful reading constant.ezy
//              (*constantfile was stuffed though)
//
//
//
int ezycom::load_config(char *overidepath)
{
    char configname[MAXFILEPATHLENGTH];
    int stream;
    int stream2;
    int counter;

if(overidepath == NULL)
{
    if(getenv("EZY") != NULL)
        {
        strcpy(ezydir,getenv("EZY"));
        fixslash(ezydir);
        }
    else
        return(2);
}
else
    {
    fixslash(overidepath);
    strcpy(ezydir,overidepath);
    }

if(node == 0)
    sprintf(configname, "%sCONFIG.EZY", ezydir);
else
    sprintf(configname, "%sCONFIG.%d", ezydir, node);

if (node==0)        // If there's no node set up, default to node 1
    node=1;

if(!exists(configname))
    return(0);
if((stream=sopen(configname, O_RDONLY | O_BINARY,SH_DENYNO)) == NULL)
    {
    strcpy(configfile, configname);
    return(3);
    }
if(read(stream, &config, sizeof(config)) != sizeof(config))
    {close(stream); strcpy(configfile,configname); return(4);}
close(stream);

strcpy(configfile,configname);
strcpy(config.Version, pas_to_c(config.Version));
strcpy(config.DefLanguage, pas_to_c(config.DefLanguage));
strcpy(config.LogPath, pas_to_c(config.LogPath));
strcpy(config.TextPath,pas_to_c(config.TextPath));
strcpy(config.MenuPath,pas_to_c(config.MenuPath));
fixslash(config.MenuPath);
strcpy(config.MnuRamPath, pas_to_c(config.MnuRamPath));
fixslash(config.MnuRamPath);
strcpy(config.NetmailPath, pas_to_c(config.NetmailPath));
fixslash(config.NetmailPath);
strcpy(config.NodelistPath,pas_to_c(config.NodelistPath));
fixslash(config.NodelistPath);
strcpy(config.MsgPath, pas_to_c(config.MsgPath));
fixslash(config.MsgPath);
strcpy(config.FilePath, pas_to_c(config.FilePath));
fixslash(config.FilePath);
strcpy(config.TempPath, pas_to_c(config.TempPath));
fixslash(config.TempPath);
strcpy(config.UserBasePath, pas_to_c(config.UserBasePath));
fixslash(config.UserBasePath);
strcpy(config.AvatarPath, pas_to_c(config.AvatarPath));
fixslash(config.AvatarPath);
strcpy(config.AscPath, pas_to_c(config.AscPath));
fixslash(config.AscPath);
strcpy(config.AscLowPath, pas_to_c(config.AscLowPath));
fixslash(config.AscLowPath);
strcpy(config.FileMaint, pas_to_c(config.FileMaint));
fixslash(config.FileMaint);
strcpy(config.FileAttachPath, pas_to_c(config.FileAttachPath));
fixslash(config.FileAttachPath);
strcpy(config.SoundPath, pas_to_c(config.SoundPath));
fixslash(config.SoundPath);
strcpy(config.FastIndexPath, pas_to_c(config.FastIndexPath));
fixslash(config.FastIndexPath);
strcpy(config.SystemPwd, pas_to_c(config.SystemPwd));
strcpy(config.SysopPwd, pas_to_c(config.SysopPwd));
strcpy(config.NewuserPwd, pas_to_c(config.NewuserPwd));
strcpy(config.TopMenu, pas_to_c(config.TopMenu));
strcpy(config.InboundMail, pas_to_c(config.InboundMail));
fixslash(config.InboundMail);
strcpy(config.OutboundMail, pas_to_c(config.OutboundMail));
fixslash(config.OutboundMail);
strcpy(config.UploadPath, pas_to_c(config.UploadPath));
fixslash(config.UploadPath);
strcpy(config.SwapFile, pas_to_c(config.SwapFile));
fixslash(config.SwapFile);
strcpy(config.MultiPath, pas_to_c(config.MultiPath));
fixslash(config.MultiPath);
strcpy(config.Brackets, pas_to_c(config.Brackets));
strcpy(config.PhoneFormat, pas_to_c(config.PhoneFormat));
strcpy(config.F7KeyLineTop, pas_to_c(config.F7KeyLineTop));
strcpy(config.F7KeyLineBot, pas_to_c(config.F7KeyLineBot));
strcpy(config.TopMenu, pas_to_c(config.TopMenu));
strcpy(config.QuoteString, pas_to_c(config.QuoteString));

for(counter=0;counter<10;counter++)
    {
    strcpy(config.AltF[counter], pas_to_c(config.AltF[counter]));
    strcpy(config.CtrlF[counter], pas_to_c(config.CtrlF[counter]));
    }

strcpy(config.LeftBracket, pas_to_c(config.LeftBracket));
strcpy(config.RightBracket, pas_to_c(config.RightBracket));
strcpy(config.EzyOvrPath, pas_to_c(config.EzyOvrPath));
strcpy(config.FileSecPath, pas_to_c(config.FileSecPath));
fixslash(config.FileSecPath);
strcpy(config.ExternalEditor, pas_to_c(config.ExternalEditor));
fixslash(config.ExternalEditor);
strcpy(config.DefaultOrigin, pas_to_c(config.DefaultOrigin));

sprintf(constantfile, "%sCONSTANT.EZY", ezydir);
if(!exists(constantfile))
    return(5);
if((stream2=sopen(constantfile, O_RDONLY | O_BINARY,SH_DENYNO)) == NULL)
    return(6);
if(read(stream2, &Constant, sizeof(Constant)) != sizeof(Constant))
    {close(stream2); return(7);}
close(stream2);
strcpy(Constant.Version, pas_to_c(Constant.Version));
strcpy(Constant.System, pas_to_c(Constant.System));
strcpy(Constant.SysopName, pas_to_c(Constant.SysopName));
strcpy(Constant.SysopAlias, pas_to_c(Constant.SysopAlias));
strcpy(Constant.SystemLocation, pas_to_c(Constant.SystemLocation));
strcpy(Constant.QWKFileName, pas_to_c(Constant.QWKFileName));
strcpy(Constant.QuoteString, pas_to_c(Constant.QuoteString));
return(1);
}

//
//  Get FSE user posting info
//
//      Returns :  1 upon success
//                 0 upon failure
//

int ezycom::get_msginfo(int wnode, FseRecord *msginfo)
{
    int stream;
    char minfopath[MAXFILEPATHLENGTH];
    sprintf(minfopath, "%sMSGINFO.%d", ezydir, wnode);
    if((stream=sopen(minfopath, O_RDONLY | O_BINARY, SH_DENYNO)) == NULL)
       return(0);
    read(stream, &msginfo, sizeof(msginfo));
    pas_to_c(msginfo->WhoFrom);
    pas_to_c(msginfo->WhoTo);
    pas_to_c(msginfo->Subject);
    close(stream);
    return(1);
}

void ezycom::fixslash(char *s)
{
     while(*s) s++;                      // Move to EOS
     if(*(--s) == '\\') return;          // If Ok return
    *(++s) = '\\';                       // Else Add Slash
    *(++s) = '\0';                       // Terminate String
}

int ezycom::get_sysinfo(SysInfoRecord *sysinfo)
{
    int stream;
    char sinfopath[MAXFILEPATHLENGTH];
    long bytesread = 0;

    sprintf(sinfopath, "%sSYSINFO.BBS", ezydir);
    if(!exists(sinfopath))
        return(0);
    if((stream=sopen(sinfopath, O_RDONLY | O_BINARY, SH_DENYNO)) == NULL)
        return(0);
    if(read(stream,&sysinfo,sizeof(sysinfotmp)) != sizeof(sysinfotmp))
        {
            close(stream);
            return(2);
        }
    close(stream);
    strcpy(sysinfo->LastCaller, pas_to_c(sysinfo->LastCaller));
    strcpy(sysinfo->LastAlias, pas_to_c(sysinfo->LastAlias));
    return(1);
}

//
//  Returns the number of nodes (as set in online.bbs)
//

int ezycom::num_nodes(void)
{
struct ffblk ffblk;
char onlinebbs[MAXFILEPATHLENGTH];

sprintf(onlinebbs, "%sONLINE.BBS", config.MultiPath);
findfirst(onlinebbs,&ffblk,0);
return( (int)(ffblk.ff_fsize/sizeof(onlinetmp)) );
// struct ffblk {
// char ff_reserved[21]; /* reserved by DOS */
//  char ff_attrib;       /* attribute found */
//  int  ff_ftime;        /* file time */
//  int  ff_fdate;        /* file date */
//  long ff_fsize;        /* file size */
//  char ff_name[13];     /* found file name */
// };
}

//
//  Set the number of nodes through online.bbs
//      NOTE:  not possible to 'decrease' the number of nodes, only increase
//
//  Returns
//         -1   =  Nodes already set to that number
//          0   =  Failed
//          1   =  Success
//
//
int ezycom::set_nodes(int nodes)
{
if(nodes < num_nodes())
    return(0);
if(nodes == num_nodes())
    return(-1);
//
//  Add Code here to append empty records to online.bbs
//
return(1);
}

int ezycom::set_node(int wnode, OnlineRecord *online)
{
char onlinebbs[MAXFILEPATHLENGTH];
int stream;

sprintf(onlinebbs, "%sONLINE.BBS", config.MultiPath);
if((stream=sopen(onlinebbs, O_WRONLY | O_BINARY, SH_DENYNO)) == NULL)
   return(0);
lseek(stream,(long)(sizeof(onlinetmp)*(wnode-1)), SEEK_SET);
c_to_pas(online->Name);
c_to_pas(online->Alias);
c_to_pas(online->Location);
if(write(stream, online, sizeof(onlinetmp)) != sizeof(onlinetmp))
    {  close(stream);  return(0); }
close(stream);
return(1);
}

//
//  Load the specified node's online record into a structure
//
//  Returns True/False when successful/unsuccessful
//
int ezycom::load_node(int wnode, OnlineRecord *online)
{
char onlinebbs[MAXFILEPATHLENGTH];
int stream;

sprintf(onlinebbs, "%sONLINE.BBS", config.MultiPath);
if(!exists(onlinebbs))
    return(0);
if((stream=sopen(onlinebbs, O_RDONLY | O_BINARY, SH_DENYNO)) == NULL)
   return(0);
lseek(stream,(long)(sizeof(onlinetmp)*(wnode-1)), SEEK_SET);
if(read(stream, &onlinetmp, sizeof(onlinetmp)) != sizeof(onlinetmp))
    {
        close(stream);
        return(0);
    }
close(stream);

strcpy(online->Name, pas_to_c(onlinetmp.Name));
strcpy(online->Alias, pas_to_c(onlinetmp.Alias));
strcpy(online->Location, pas_to_c(onlinetmp.Location));
online->Status=onlinetmp.Status;
online->Attribute=onlinetmp.Attribute;
online->Baud=onlinetmp.Baud;
return(1);
}

//
//  Use multiple calls to receive multiple messages...
//
int ezycom::get_omessage(int wnode, MultiMessageRecord *msg)
{
MultiMessageRecord multimsgtmp;
char messnode[MAXFILEPATHLENGTH];
int stream;
long bytesread;
int x,y;
int num;

sprintf(messnode, "%sMESSNODE.%d",config.MultiPath, wnode);
if((stream=sopen(messnode,O_BINARY|O_RDONLY, SH_DENYRW)) == NULL)
    return(0);
if(read(stream, &multimsgtmp, sizeof(multimsgtmp)) != sizeof(multimsgtmp))
    { close(stream); return(0); }
strcpy(msg->From,pas_to_c(multimsgtmp.From));
strcpy(msg->Message,pas_to_c(multimsgtmp.Message));
msg->FromNode=multimsgtmp.FromNode;
msg->PrivateMsg=multimsgtmp.PrivateMsg;

num=(int)(filelength(stream)/sizeof(multimsgtmp));

if(num == 1)            // If only one record,
    goto eof;

printf("\r\nNum : %d\r\n",num);
for(x=1;;x++)
{
lseek(stream, (long)sizeof(multimsgtmp)*x, SEEK_SET);
if(read(stream, &multimsgtmp, sizeof(multimsgtmp)) != sizeof(multimsgtmp))
    goto eof;
lseek(stream,(long)(sizeof(multimsgtmp)*(x-1)), SEEK_SET);
write(stream, &multimsgtmp, sizeof(multimsgtmp));
}

eof:
chsize(stream, (num*sizeof(multimsgtmp)) - sizeof(multimsgtmp)   );
close(stream);
return(1);
}
