/*     Bed a Binary EDitor for Linux and for Rxvt running under Linux.       */
/*     Copyright (C) 1998  Jaap Korthals Altes <jkaltes@hetnet.nl>      */
/*                                                                           */
/*     Bed 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.                                   */
/*                                                                           */
/*     Bed 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 bed; if not, write to the Free Software                    */
/*     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             */
/*                                                                           */
/* Sun Dec  6 18:34:27 1998                                                  */

/***
 *  v2  2000.09.20  Jim Blackson	rename truncate to truncatefile.
 */

#ifndef MEMORY_H
#define MEMORY_H
#include <features.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/param.h>
#include "defines.h"
#include "rbtree.h"
#include "offtypes.h"
#ifdef __FreeBSD__
#define NEEDS_BLOCKMODE 1
#endif
#ifdef BIOSDISK
#define NEEDS_BLOCKMODE 1
#endif
#ifdef  __cplusplus
extern "C" {
#endif
#ifdef HAS_REGEX_LIB
#ifdef HAVE_GNUREGEX_H
#include <gnuregex.h>
#else
#include <regex.h>
#endif
#else
#include "regex.h"
#endif

#ifdef  __cplusplus
}
#endif
#define DEBUG DEBUGGING
#include "debug.h"
#define regsearch(mem) (((mem)->lastforward>>2)&1)
#define forwardsearch(mem) (((mem)->lastforward&1)
#define casesearching(mem) (((mem)->lastforward>>1)&1)
#define BIGEST   LONG_MAX

#if !defined(HAS_PREAD) && defined(USETHREADS)
#include <semaphore.h>
#define DEFINEUSELSEEK sem_t lseeksem
#define DESTROYUSELSEEK  sem_destroy(&lseeksem)
#define INITUSELSEEK sem_init(&lseeksem,0,1)
#define STARTUSELSEEK sem_wait(&lseeksem)
#define	STOPUSELSEEK sem_post(&lseeksem)
#define	GSTOPUSELSEEK(memp) sem_post(&((memp)->lseeksem))
#else
#define	GSTOPUSELSEEK(memp)
#define DEFINEUSELSEEK 
#define DESTROYUSELSEEK  
#define INITUSELSEEK 
#define STARTUSELSEEK
#define STOPUSELSEEK 
#endif


extern int STBLOCKSIZE;


//#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
//#define DEBUG(x...)
#undef minnum
#undef maxnum
#define minnum( x,y) ((x)>(y)?(y):(x))
#define maxnum( een, twee) (((een)>(twee))?(een):(twee))
typedef char Flag;
#ifdef BIOSDISK
#include "biosdisk.h"
#endif
#ifndef _WIN32
typedef int BOOL ;
#endif
class Memory {
public:
#ifdef BIOSDISK
	Diskinfo *infodisk;	
#endif
private:
#ifdef NEEDS_BLOCKMODE
	int blockreadonly;
#endif
	public:
DEFINEUSELSEEK ;
int BLOCKSIZE;
	FILEHANDLE filehandle;
	int errors,readonly;
Treel *Memory::gettreel(BLOCKTYPE blockiter) ;
	 STATTYPE statdata;

	OFFTYPE filesize, diskfilesize;
	int lastforward;

	Flag mmapfailed;
	OFFTYPE searchpos;
      struct re_pattern_buffer *searchexpr;
      struct re_registers *searchregs;
	int tablebase[256];
	int *table;
	int searchlen;
	char *searchstr;

	char *filename;
	Tree tree;
	int error(void) {return errors;}
	OFFTYPE size(void) {return filesize;}
	Memory(char *name);
	~Memory();

void openfile(void) ;
void init(char *name) ;
int reinit(char *name) ;

void Memory::endfile(void);
int reinit(void) ;
int empty(void) ;

int Memory::savenode(FILEHANDLE output, Treel *node) ;
	int saveall(void);
	int saveto(int handle);
	SIZE_T Memory::saveto(int handle,OFFTYPE beg,OFFTYPE len) ;
	int touched(void) ;
	SIZE_T Memory::getblock(BLOCKTYPE blocknr,char *buf) ;

SIZE_T Memory::mmapgetblock(BLOCKTYPE blocknr,char *buf) ;
	SIZE_T Memory::putblock(BLOCKTYPE blocknr,char *buf) ;
	SIZE_T Memory::getblockpiece(OFFTYPE beg,SIZE_T len,char *get) ;
	OFFTYPE Memory::getpart(OFFTYPE beg,OFFTYPE len,char *gegs) ;
SIZE_T Memory::putblockpiece(OFFTYPE  beg,SIZE_T len,char *get) ;
OFFTYPE Memory::putpart(OFFTYPE beg,OFFTYPE len,char *gegs) ;
void	setborder(OFFTYPE pos) ;
void Memory::extend(OFFTYPE newsize) ;
void Memory::truncatefile(OFFTYPE pos) ;			/* v2 */
//f c r

inline BLOCKTYPE blocksize(void) { return BLOCKSIZE;};
void Memory::initsearch( void) ;
OFFTYPE Memory::search(OFFTYPE beg,char *str,int len) ;
int Memory::setsearchgegs(OFFTYPE beg,char *str,int len) ;

	OFFTYPE Memory::nextsearch(void) ;

OFFTYPE Memory::backicaseregexsearch(OFFTYPE beg,char *str,int len) ;
OFFTYPE Memory::backregexsearch(OFFTYPE beg,char *str,int len) ;
OFFTYPE Memory::nextbackregexsearch(void) ;



OFFTYPE Memory::icaseregexsearch(OFFTYPE beg,char *str,int len) ;
OFFTYPE Memory::regexsearch(OFFTYPE beg,char *str,int len) ;
OFFTYPE Memory::nextforwardregexsearch(void) ;
OFFTYPE Memory::icasesearch(OFFTYPE beg,char *str,int len) ;
OFFTYPE Memory::nextforwardicasesearch(void) ;
OFFTYPE Memory::casesearch(OFFTYPE beg,char *str,int len) ;
OFFTYPE Memory::nextforwardsearch(void) ;
OFFTYPE Memory::backsearch(OFFTYPE beg,char *str,int len) ;
OFFTYPE Memory::nextbacksearch(void) ;
OFFTYPE Memory::backicasesearch(OFFTYPE beg,char *str,int len) ;
OFFTYPE Memory::nextbackicasesearch(void) ;


SIZE_T Memory::blockreadat(char *ptr,SIZE_T size,OFFTYPE offset) ;
inline	SIZE_T Memory::readat(char *ptr,SIZE_T size,OFFTYPE offset) ;

SIZE_T Memory::writeat(FILEHANDLE output,char *ptr,SIZE_T size,OFFTYPE offset) ;
int Memory::changed(void) ;
int Memory::changednode(Treel *node) ;
OFFTYPE Memory::exploresize(FILEHANDLE file,OFFTYPE begin=0, OFFTYPE end=MAXDISCSIZE) ;

#ifdef BIOSDISK
OFFTYPE Memory::getregistrysize(Diskinfo *infodisk,OFFTYPE &begin,OFFTYPE &end) ;
BOOL Memory::setregistrysize(Diskinfo *infodisk,OFFTYPE filesize);
#endif
inline BOOL sizehigher(OFFTYPE sizefile) ;
inline BOOL Memory::testsize(OFFTYPE sizetest);
inline BOOL Memory::checkfilesize(OFFTYPE filsize,OFFTYPE &begin,OFFTYPE &end) ;
OFFTYPE Memory::win32diskfilesize(FILEHANDLE filehandle) ;
	};


extern int tmpbuffer(char *name); 
extern SIZE_T writetofile(FILEHANDLE output,char *buf,SIZE_T nr);
#endif
