// machine-dependent file routines

#include "Include.h"

#define FFBUFSIZE 1024

static BPTR fh;

static char ffinbuf[FFBUFSIZE];

static int eofflag;     /* end-of-file flag */

static short ffnext;
static short ffcount;
static short prev_c; // used to guess when to treat \r\n as single char


/// ffclose()
/*
** Close a file. Should look at the status in all systems.
 ***********************************************************************/
STD ffclose()
{
      Close(fh);
        return(FIOSUC);
}
//-

/// ffropen()
/*
** Open a file for reading.
**
** char    *fn;   filename
**
 ***********************************************************************/
STD ffropen(char *fn)
{
   if ((fh = Open(fn, MODE_OLDFILE)) == 0)
      return FIOFNF;
   ffnext = 0;
   ffcount = 0;
   prev_c = 0;
   eofflag = FALSE;
        return(FIOSUC);
}
//-

/// ffwopen()
/*
** Open a file for writing. Return TRUE if all is well, and FALSE on error
** (cannot create).
**
** char    *fn;   filename
** char *mode;    mode to open file for
**
 ***********************************************************************/
STD ffwopen(char *fn, char *mode)
{
// char xmode[6];    /* extended file open mode */

   if (*mode == 'w') {
      fh = Open(fn, MODE_NEWFILE);
   } else {
      fh = Open(fn, MODE_READWRITE);
      if (fh) {
         Seek(fh, 0, OFFSET_END);
      }
   }
   if (fh == 0) {
                mlwrite(TEXT155);
/*                      "Cannot open file for writing" */
                return(FIOERR);
        }
        return(FIOSUC);
}
//-

/// ffputline()
/*
** Write a line to the already opened file. The "buf" points to the buffer,
** and the "nbuf" is its length, less the free newline. Return the status.
** Check only at the newline.
**
** char    buf[];
** int nbuf;
**
 ***********************************************************************/
STD ffputline(char buf[], int nbuf)
{
   if (Write(fh, buf, nbuf) < 0 ||
       Write(fh, "\n", 1) < 0) {
                mlwrite(TEXT157);
/*                      "Write I/O error" */
                return(FIOERR);
   }
   
   return FIOSUC;
}
//-

/// ffgetc()
int ffgetc(void)
{
   if (ffnext == ffcount) {
      ffcount = Read(fh, ffinbuf, FFBUFSIZE);
      if (ffcount <= 0) {
         return EOF;
      }
      ffnext = 0;
   }
   return ffinbuf[ffnext++];
}
//-

/// ffgetline()
/*
** Read a line from a file, and store the bytes in the supplied buffer. The
** "nbuf" is the length of the buffer. Complain about long lines and lines
** at the end of the file that don't have a newline present. Check for I/O
** errors too. Return status.
 ***********************************************************************/
STD ffgetline(void)
{
        register int c;    /* current character read */
        register int i;    /* current index into fline */
// register char *tmpline; /* temp storage for expanding line */

   /* if we are at the end...return it */
   if (eofflag)
      return(FIOEOF);

   i = 0;

   // here is what i see:
   // messages end with \r\n
   // sometimes i see \n by itself
   // amigados files use \n by itself
   // file descriptions use \r by itself
   // messages quoted by turboread use \n by itself
   
   // added \r to read DLG file descriptions

   while (1) {
       // read until end of line
       while ((c = ffgetc()) != '\n' && c != EOF && c != '\r') {
      fline[i++] = c;
      if (i == FLINE_SIZE) {
          return FIOSUC;
      }
       }

       // kludge: if line is empty, check for \r\n sequence
       if (i == 0 && prev_c == '\r' && c == '\n') {
      // yes, this is \r\n, ignore \n
      continue;
       }
       // remember this line terminator for next line kludge
       prev_c = c;
       break;
   }
   /* dump any extra line terminators at the end */
   while (i > 0 && (fline[i-1] == 10 || fline[i-1] == 13))
      i--;

   /* test for any errors that may have occured */
        if (c == EOF) {
                if (i != 0)
         eofflag = TRUE;
      else
         return(FIOEOF);
        }

   /* terminate and decrypt the string */
        fline[i] = 0;
        return(FIOSUC);
}
//-

