/*

  This is a part of the Project Frontier's Source code.

  Copyright (C) 1997-98 Francis Gastellu
                    aka Lone Runner/Aegis

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
/**************************************************************************/
/******** VFS 1.0                                                  ********/
/********                                          Functions Body  ********/
/********     Virtual File System                                  ********/
/**************************************************************************/
#include "..\lang\vfs.h"
#include <stdio.h>
#include <process.h>
#include <string.h>
#include <alloc.h>
#include <share.h>
#include "..\lang\fortify.h"
#include "..\com\sharing.h"

char far copyright[] = "VFS 1.O þ Virtual File System þ (C)96 Lone Runner/AGS";

vfs_file *vfs_fopenread(char *fl, int mode)
{
FILE *__in;
vfs_file *buf;
char md[3] = "rX";
long l;

buf = (vfs_file *)farmalloc(sizeof(vfs_file)); //!
if (buf == NULL)
    return NULL;

if (mode == VFS_FILE_READBIN)
	md[1] = 'b';
else
	md[1] = 't';

if ((__in = fopen_share(fl, md, SH_DENYWR)) == NULL)
	{
    free(buf); //!
    return NULL;
    }

fseek(__in, 0, SEEK_END);
buf->size = ftell(__in);
buf->data = (char *)farmalloc(buf->size+1); //!
if (buf->data == NULL)
	{
    free(buf); //!
    fclose(__in);
    return NULL;
    }
buf->ptr = 0;
fseek(__in, 0, SEEK_SET);
l = buf->size;
fread(buf->data, l>>1, 2, __in);
l-=(l>>1) << 1;
if (l > 0)
	fread(buf->data+(buf->size-1), 1, 1, __in);

if (mode == VFS_FILE_READTXT)
	{
    unsigned char huge *p;
    long n, o;
    for (n=0,o=0,p=buf->data;n < buf->size;n++,o++,p++)
        if (*p == '\n')
        	n++;
	buf->size = o;
    }

fclose(__in);

buf->data = (char *)farrealloc(buf->data, buf->size+1); //!
if (buf->data == NULL)
	{
    free(buf); //!
    return NULL;
    }

strcpy(buf->filename, fl);
buf->mode = mode;

return buf;
}

void vfs_fread(void *ptr, size_t size, size_t n, vfs_file *buf)
{
size_t i,j;
unsigned char *_ptr = (unsigned char *)ptr;

for (j=0;j<n;j++)
	for (i=0;i<size;i++)
		{
	    _ptr[0] = buf->data[(long)buf->ptr];
	    _ptr++;
	    buf->ptr++;
	    }
}

void vfs_fseek(vfs_file *fl, long i, int whence)
{
switch (whence)
	{
    case SEEK_SET:
    	fl->ptr = i;
    	break;
    case SEEK_CUR:
    	fl->ptr += i;
        break;
    case SEEK_END:
    	fl->ptr = fl->size+i;
        break;
    }
}

unsigned long vfs_ftell(vfs_file *fl)
{
return fl->ptr;
}

void vfs_fclose(vfs_file *fl)
{
unsigned long l;

if (fl->mode == VFS_FILE_WRITEBIN || fl->mode == VFS_FILE_WRITETXT)
	{
	FILE *__out;
    char md[3]="wX";
    if (fl->mode == VFS_FILE_WRITEBIN)
    	md[1] = 'b';
    else
    	md[1] = 't';
	if ((__out = fopen_share(fl->filename, md, SH_DENYRW)) == NULL)
    	{
	    printf("VFS: Enable to create %s!\n", fl->filename);
		fcloseall();
		exit(1);
	    }
    l = fl->limit;
    fwrite(fl->data, fl->limit>>1, 2, __out);
    fl->limit-=(fl->limit>>1) << 1;
    if (fl->limit > 0)
	    fwrite(fl->data+(l-1), 1, 1, __out);
    fclose(__out);
    }

free(fl->data); //!
fl->ptr=0;
fl->size=0;
free(fl); //!
fl = NULL;
}

vfs_file *vfs_fopenwrite(char *fl, int mode)
{
FILE *__in;
vfs_file *buf;

buf = (vfs_file *)farmalloc(sizeof(vfs_file)); //!
if (buf == NULL)
    return NULL;

strcpy(buf->filename, fl);
buf->size = VFS_FILE_INC;
buf->data = (char *)farmalloc(buf->size+1); //!
if (buf->data == NULL)
	{
    free(buf); //!
    return NULL;
    }

buf->ptr = 0;
buf->mode = mode;
buf->limit=0;

return buf;
}

size_t vfs_fwrite(void *ptr, size_t size, size_t n, vfs_file *buf)
{

while (buf->ptr+size*n >= buf->size)
	{
	buf->data = (char *)farrealloc(buf->data, buf->size + VFS_FILE_INC); //!
    if (buf->data == NULL)
		{
        free(buf); //!
        return NULL;
	    }
    buf->size += VFS_FILE_INC;
    }

memcpy(buf->data+buf->ptr, ptr, size*n);

buf->ptr += size*n;
if (buf->limit < buf->ptr)
	buf->limit = buf->ptr;

return n;
}

void vfs_fputs(char *str, vfs_file *fl)
{
vfs_fwrite(str, strlen(str), 1, fl);
}

void vfs_fputc(char c, vfs_file *fl)
{
vfs_fwrite(&c, 1, 1, fl);
}

int vfs_feof(vfs_file *fl)
{
return (fl->ptr >= fl->/*true*/size);
}

char *vfs_fgets(char *dest, int n, vfs_file *fl)
{
unsigned char c=0;
char *p;
int l=0;

p = dest;
while (c != '\n' && l < n)
	{
	c = fl->data[fl->ptr];
    fl->ptr++;
    *p = c;
    p++;
    l++;
    }
*p=0;
return dest;
}

char vfs_fgetc(vfs_file *fl)
{
return fl->data[fl->ptr++];
}

vfs_file *vfs_outtoin(vfs_file *fl, int mode)
{
FILE *__in;
vfs_file *buf;
char md[3] = "rX";
long l;

buf = (vfs_file *)farmalloc(sizeof(vfs_file)); //!
if (buf == NULL)
    return NULL;

if (mode == VFS_FILE_READBIN)
	md[1] = 'b';
else
	md[1] = 't';

buf->data = fl->data;
buf->ptr = 0;
buf->size = fl->limit;

buf->data = (char *)farrealloc(buf->data, buf->size+1); //!

if (buf->data == NULL)
	{
    free(buf); //!
    return NULL;
    }

strcpy(buf->filename, fl->filename);
buf->mode = mode;

fl->ptr=0;
fl->size=0;
fl = NULL;

return buf;

}

