//  ======================================================================
//               THIS IMPLEMENTATION WRITTEN BY KK - SPRING 1998
//  ======================================================================

#include "winplus.h"
#pragma  hdrstop
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

// =======================================================================

#define IBF_SHAREDPOOLSIZE      128 * 1024
static char lpSharedPool[IBF_SHAREDPOOLSIZE];

// =======================================================================

CInputBinaryFile::CInputBinaryFile(char *lpszPathName)
{
  ::strncpy(PathName,lpszPathName,_MAX_PATH);
  ::_splitpath(PathName,Drive,Dir,Name,Ext);
  dwPos=dwSize=dwFlags=0;
  lpFileBuffer=NULL;
  bLastError=TRUE;
  struct stat st;
  if(::stat(PathName,&st)==-1) return;
  dwSize=st.st_size;
  bLastError=FALSE;
};

CInputBinaryFile::~CInputBinaryFile()
{
  if(lpFileBuffer)
    if(lpFileBuffer!=lpSharedPool)
      free(lpFileBuffer);
}

void CInputBinaryFile::Preload(BOOL bUseSharedPool)
{
  bLastError=TRUE;
  lpFileBuffer=NULL;
  if(bUseSharedPool)
    if(dwSize<=IBF_SHAREDPOOLSIZE)
      lpFileBuffer = lpSharedPool;
  if(lpFileBuffer==NULL) lpFileBuffer=malloc(dwSize);
  if(lpFileBuffer==NULL) return;
  iHandle = ::open(PathName, O_RDONLY|O_BINARY);
  if(iHandle==-1) return;
  if(::read(iHandle,lpFileBuffer,dwSize)!=dwSize)
  {
    ::close(iHandle);
    return;
  }
  bLastError=FALSE;
  dwFlags|=FA_PREREAD;
  ::close(iHandle);
}

void CInputBinaryFile::seek(long lOffset, DWORD dwSeekType)
{
  switch(dwSeekType)
  {
    case SEEK_SET:
      dwPos=lOffset;
      break;
    case SEEK_CUR:
      dwPos+=lOffset;
      break;
    case SEEK_END:
      dwPos=dwSize+lOffset;
      break;
    default:
      bLastError=TRUE;
      return;
  }
  eof();
}

DWORD CInputBinaryFile::tell(void)
{
  bLastError=FALSE;
  return dwPos;
}

BOOL CInputBinaryFile::eof(void)
{
  if(dwPos>=dwSize)
  {
    dwPos=dwSize;
    bLastError=TRUE;
  }
  else
    bLastError=FALSE;
  return bLastError;
}

DWORD CInputBinaryFile::filesize(void)
{
  if(dwSize) bLastError=FALSE; else bLastError=TRUE;
  return dwSize;
}

DWORD CInputBinaryFile::read(void *lpBuffer, DWORD dwLength)
{
  if(eof()||(dwLength==0))
  {
    bLastError=TRUE;
    return 0;
  }
  if((dwLength+dwPos)>dwSize) dwLength=dwSize-dwPos;
  if(dwFlags&FA_PREREAD)
  {
    memcpy(lpBuffer,(char*)lpFileBuffer+dwPos, dwLength);
    dwPos+=dwLength;
    bLastError=FALSE;
  }
  else
  {
    iHandle = ::open(PathName,O_RDONLY|O_BINARY);
    if(iHandle!=-1)
    {
      ::lseek(iHandle,dwPos,SEEK_SET);
      DWORD dwL=::read(iHandle,lpBuffer,dwLength);
      if(dwL==dwLength)
      {
        dwPos+=dwLength;
        bLastError=FALSE;
      }
      else
      {
        bLastError=TRUE;
        dwLength=dwL;
      }
      ::close(iHandle);
    }
    else bLastError=TRUE;
  }
  return dwLength;
}

// =======================================================================

void CInputTextFile::SetWrapMode(int iWMode)
{
  if(iWMode)
  {
    dwFlags|=FA_WRAP;
  }
  else
  {
    dwFlags&=~(DWORD)FA_WRAP;
  }
  bLastError=FALSE;
}

UCHAR CInputTextFile::getch()
{
  UCHAR result;
  if(eof()) return 0;
  if(dwFlags&FA_PREREAD)
  {
    result=((UCHAR*)lpFileBuffer)[dwPos];
    dwPos++;
    bLastError=FALSE;
  }
  else
  {
    if(read(&result,1)==1)
      bLastError=FALSE;
    else
      bLastError=TRUE;
  }
  return result;
}

DWORD CInputTextFile::gets(char *lpszBuffer, DWORD dwLimit)
{
  DWORD count = 0, readed = 0;
  UCHAR ch;
  if(eof()) return 0;
  while(!eof())
  {
    if(count>=dwLimit)
    {
      readed=count;
      if(dwFlags&FA_WRAP)
      {
        while((!eof())&&(ch!=0x0D)) ch=getch();
        seek(1,SEEK_CUR);
      }
      lpszBuffer[count]=0;
      bLastError=FALSE;
      return readed;
    }
    ch=getch();
    if(ch==0x0D)
    {
      dwPos++; if(dwPos>dwSize) dwPos=dwSize;
      lpszBuffer[count]=0;
      bLastError=FALSE;
      return count;
    }
    else
    {
      lpszBuffer[count]=ch;
      count++;
    }
  }
  dwPos=dwSize;
  lpszBuffer[count]=0;
  bLastError=FALSE;
  return count;
}

DWORD CInputTextFile::scan(char *lpszBuffer, DWORD dwLimit)
{
  DWORD count = 0, readed = 0;
  UCHAR ch;
  if(eof()) return 0;
  while(!eof())
  {
    if(count>=dwLimit)
    {
      readed=count;
      if(dwFlags&FA_WRAP)
      {
        while((!eof())&&(ch!=0x0D)&&(ch!=0x20)) ch=getch();
        if(ch==0x0D) dwPos++;
      }
      lpszBuffer[count]=0;
      bLastError=FALSE;
      return readed;
    }
    ch = getch();
    if((ch==0x20)|(ch==0x0D))
    {
      if(ch==0x0D)
      {
        dwPos++;
        if(dwPos>dwSize) dwPos=dwSize;
      }
      lpszBuffer[count]=0;
      bLastError=FALSE;
      while((!eof())&&((ch==0x0D)||(ch==0x0A)||(ch==0x20))) ch=getch();
      if(!eof()) dwPos--;
      return count;
    }
    else
    {
      lpszBuffer[count]=ch;
      count++;
    }
  }
  dwPos=dwSize;
  lpszBuffer[count]=0;
  return count;
}

