
#define CBASE_TYPE_STRING		1
#define CBASE_TYPE_USTRING		32
#define CBASE_TYPE_INTEGER		2
#define CBASE_TYPE_UNSIGNED		4
#define CBASE_TYPE_STAMP		8
#define CBASE_TYPE_ID			16

#define CBASE_KEY_DUPLICATES		1
#define CBASE_KEY_MODIFIABLE		2
#define CBASE_KEY_SKIPNULL		4
#define CBASE_KEY_DESCENDING		8

struct CBaseHeader {
	ULONG	recsize;
	ULONG	pagesize;
	ULONG	nindex, flags;
	ULONG	n;

	ULONG	ffirst, flast;		// free
	ULONG	dfirst, dlast;		// data
	ULONG	dfree;			// data page with free space

	ULONG	stamp;
};

struct CBaseIndex {
	char	tag[12];
	USHORT	size;
	USHORT	flags;

	USHORT	seg_off[4];
	USHORT	seg_len[4];
	UBYTE	seg_type[4];
//
	ULONG	n, nunique;
	ULONG	start, top, bottom;

	ULONG	chain;			// chain for removal
};

struct RecLock {
	struct	RecLock *next, *prev;
	struct	RecLock *unext;

	struct	CBaseHandle *user;
	ULONG	record;
};

struct RecordHeader {
	ULONG	updated;
	ULONG	memo,memob,size;
};

struct PositionBlock {
	USHORT	i;		// index #

	ULONG	ipage, icheck;
	USHORT	b;
	UBYTE	key[128];

	ULONG	r;
	ULONG	dpage;
	USHORT	pi;

	struct	RecordHeader rh;

	ULONG	mpage, mpos, mpagepos;
};

struct PageHeader {
	ULONG	parent;		// index page
	ULONG	next,prev;	// index
	ULONG	nchain,pchain;	// index chain, all index records;
				// data chain, free space
	ULONG	bytes;		// index/memo page, # bytes
				// data page, 32 bits, which recs used?
	ULONG	updated;	// when this page changes
	ULONG	nx;

	USHORT	branch;		// index is a branch index?
};

struct TempPage {
	ULONG	address;
	ULONG	fileoffset;

	struct	TempPage *next;
};

struct MemPage {
	struct	MemPage *next, *prev;		//in bin
	struct	MemPage *rnext, *rprev;		//read order
	struct	MemPage *fnext, *fprev;		//belonging to one file
	struct	CBasePublic *file;
	struct	CBaseProcess *cb;
	ULONG	address;
	USHORT	users;

	UBYTE	trans, committed;

	struct	PageHeader *page, *page2;
};

#define CBase_Open		0
#define CBase_Close		1
#define CBase_Append		2
#define CBase_Update		3
#define CBase_Delete		4
#define CBase_GoTo		7
#define CBase_GetPosition	8
#define CBase_Top		9
#define CBase_Bottom		10
#define CBase_Next		11
#define CBase_Previous		12
#define CBase_Create		13
#define CBase_Status		14
#define CBase_Quit		15
#define CBase_Version		16
#define CBase_Unlock		17
#define CBase_Reset		18
#define CBase_SetProtect	19
#define CBase_ClearProtect	20
#define CBase_CreateIndex	21
#define CBase_DropIndex		22
#define CBase_UseIndex		23
#define CBase_Seek		24
#define CBase_SeekNear		25
#define CBase_SeekPercentage	32
#define CBase_FindPercentage	33
#define CBase_BeginTransaction	34
#define CBase_EndTransaction	35
#define CBase_AbortTransaction	36
#define CBase_MemoDelete	40
#define CBase_MemoAppend	41
#define CBase_MemoTop		42
#define CBase_MemoRead		43

#define CBase_Success					0
#define CBase_IOError					2
#define CBase_FileNotOpen				3
#define CBase_KeyNotFound				4
#define CBase_DuplicateKey				5
#define CBase_NotOrdered				6
#define CBase_InvalidPosition			8
#define CBase_EndOfFile					9
#define CBase_NonModifiableKey		10
#define CBase_FileNotFound				12
#define CBase_CloseError				17
#define CBase_DiskFull					18
#define CBase_NotLoaded					20
#define CBase_NotAllowed				41
#define CBase_InvalidAddress			43
#define CBase_AccessDenied				46
#define CBase_AlreadySet				50
#define CBase_MaxRejects				60
#define CBase_FormatError				62
#define CBase_FilterLimit				64
#define CBase_InvalidOffset			65
#define CBase_ConflictError			80
#define CBase_LockError					81			/* could not get exclusive lock */
#define CBase_UnLockError				82			/* could not unlock file - another user still has a lock */
#define CBase_LostPosition				83
#define CBase_FileInUse					85
#define CBase_ServerError				91
#define CBase_CommError    			96			/* CBaseInitialize was not called to open CBase */
#define CBase_NoMemory					101		/* memory allocation error */
#define CBase_NoDosLib					121		/* DOS.library could not be opened */
#define CBase_SmallCache				131      /* cache too small, must be 50k or larger */
#define CBase_UR_MisMatch				132   	/* cbase found the record but is linked to the wrong user */
#define CBase_MissingAddress			133   	/* no address specified */
#define CBase_NoPageError				141		/* could not "ObtainPage" */
#define CBase_NewPageError				142		/* could not "NewPage" */
#define CBase_NoPageMemory				143      /* could not allocate memory for page(s) */
#define CBase_NullPointer				153		/* expecting a non-null (data) pointer */
#define CBase_IXSeekError				161      /* index seek error */
#define CBase_NoFileHandle				171		/* no file handle specified (or file handle=0) */
#define CBase_DatabaseCorrupt       200		/* database is corrupt! */
#define CBase_DosErrors             500      /* anything above 500, subtract 500 from and get the dos error code */
#define CBase_Error						0xffffffff

#define CBASE_OPT_LOCK		1
#define CBASE_OPT_LOCK_MULTI	2
#define CBASE_OPT_EXTENDED	4
#define CBASE_OPT_KEYONLY	8
#define CBASE_OPT_FILTER	16

struct CBasePublic {
	struct	CBasePublic *next, *prev;

	struct	SignalSemaphore sem;
	struct	SignalSemaphore pagesem;
	struct	SignalSemaphore locksem;

	ULONG	updated;			//time of last update

	char	pathonly[84], path[83];
	char	exclusive;

	ULONG	users;				//number of users
	ULONG	pagesize, recsize;

	struct	CBaseProcess *process;
	struct	CBaseHandle  *first;
	struct	RecLock      *rlock;

	struct	MemPage	     *ffirst;		//all pages, this file

	ULONG	inpages, insize;
	struct	MemPage **pages;
//	struct	MemPage *wfirst;
	struct	MemPage *rfirst, *rlast;

	ULONG	logical0, physical0, end1, end2;	// end of file tracking

	struct	TempPage *tpage;

	ULONG	ncommitted, tsize;
	UBYTE	ta;
};

struct	CBaseProcess {
	struct	MsgPort mp;
	char	portName[24];

	struct	SignalSemaphore sem;

//	struct	CBaseProcess *next, *prev;
	struct	CBasePublic  *first;		// first assigned file

	ULONG	nbins, cachesize;

	ULONG	instances;
};

struct	CBaseHandle {
	BPTR	dh, th;

	struct	CBasePublic	*cp;
	struct	CBaseHandle	*next, *prev;
	struct	CBaseProcess	*cbb;
//	struct	MsgPort		*rp;

	struct	RecLock *rlock;

	struct	PositionBlock pb;

	UBYTE	ta;
};

struct	CBaseMessage {
	struct	Message m;

	struct	CBaseHandle *ah;

	UBYTE	*data, *key;
	ULONG	arg1, arg2;

	ULONG	request;
	ULONG	result;
};

#pragma libcall CBaseBase CBaseOpen		1e	0a9804
#pragma libcall CBaseBase CBaseClose		24	801
#pragma libcall CBaseBase CBaseAppend		2a	a9803
#pragma libcall CBaseBase CBaseUpdate		30	9802
#pragma libcall CBaseBase CBaseDelete		36	801
#pragma libcall CBaseBase CBaseGoTo		3c	0a9804
#pragma libcall CBaseBase CBaseGetPosition	42	9802
#pragma libcall CBaseBase CBaseTop		48	0a9804
#pragma libcall CBaseBase CBaseBottom		4e	0a9804
#pragma libcall CBaseBase CBaseNext		54	0a9804
#pragma libcall CBaseBase CBasePrevious		5a	0a9804
#pragma libcall CBaseBase CBaseCreate		60	09803
#pragma libcall CBaseBase CBaseStatus		66	9802
#pragma libcall CBaseBase CBaseQuit		6c	00
#pragma libcall CBaseBase CBaseVersion		72	801
#pragma libcall CBaseBase CBaseUnlock		78	801
#pragma libcall CBaseBase CBaseReset		7e	00
#pragma libcall CBaseBase CBaseSetProtect	84	09803
#pragma libcall CBaseBase CBaseClearProtect	8a	801
#pragma libcall CBaseBase CBaseCreateIndex	90	9802
#pragma libcall CBaseBase CBaseDropIndex	96	9802
#pragma libcall CBaseBase CBaseUseIndex		9c	9802
#pragma libcall CBaseBase CBaseSeek		a2	0a9804
#pragma libcall CBaseBase CBaseSeekNear		a8	0a9804
#pragma libcall CBaseBase CBaseSeekPercentage	ae	0a9804
#pragma libcall CBaseBase CBaseFindPercentage	b4	9802
#pragma libcall CBaseBase CBaseBeginTransaction	ba	801
#pragma libcall CBaseBase CBaseEndTransaction	c0	801
#pragma libcall CBaseBase CBaseAbortTransaction	c6	801
#pragma libcall CBaseBase CBaseMemoDelete	cc	801
#pragma libcall CBaseBase CBaseMemoAppend	d2	09803
#pragma libcall CBaseBase CBaseMemoTop		d8	801
#pragma libcall CBaseBase CBaseMemoRead		de	09803
#pragma libcall CBaseBase CBaseSave		e4	00
#pragma libcall CBaseBase CBaseInitialize	ea	801

__asm __saveds ULONG CBaseOpen(
	register __a0 struct CBaseHandle **ah,
	register __a1 UBYTE *file,
	register __a2 UBYTE *key,
	register __d0 ULONG opts );
__asm __saveds ULONG CBaseClose(
	register __a0 struct CBaseHandle *ah );
__asm __saveds ULONG CBaseAppend(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data,
	register __a2 UBYTE *key );
__asm __saveds ULONG CBaseUpdate(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data );
__asm __saveds ULONG CBaseDelete(
	register __a0 struct CBaseHandle *ah );
__asm __saveds ULONG CBaseGoTo(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data,
	register __a2 UBYTE *key,
	register __d0 ULONG opts );
__asm __saveds ULONG CBaseGetPosition(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data );
__asm __saveds ULONG CBaseTop(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data,
	register __a2 UBYTE *key,
	register __d0 ULONG opts );
__asm __saveds ULONG CBaseBottom(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data,
	register __a2 UBYTE *key,
	register __d0 ULONG opts );
__asm __saveds ULONG CBaseNext(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data,
	register __a2 UBYTE *key,
	register __d0 ULONG opts );
__asm __saveds ULONG CBasePrevious(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data,
	register __a2 UBYTE *key,
	register __d0 ULONG opts );
__asm __saveds ULONG CBaseCreate(
	register __a0 UBYTE *data,
	register __a1 UBYTE *file,
	register __d0 ULONG opts );
__asm __saveds ULONG CBaseStatus(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data );
__asm __saveds ULONG CBaseQuit( void );
__asm __saveds ULONG CBaseVersion(
	register __a0 UBYTE *data );
__asm __saveds ULONG CBaseUnlock(
	register __a0 struct CBaseHandle *ah );
__asm __saveds ULONG CBaseReset( void );
__asm __saveds ULONG CBaseSetProtect(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *key,
	register __d0 ULONG opts );
__asm __saveds ULONG CBaseClearProtect(
	register __a0 struct CBaseHandle *ah );
__asm __saveds ULONG CBaseCreateIndex(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data );
__asm __saveds ULONG CBaseDropIndex(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *key );
__asm __saveds ULONG CBaseUseIndex(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *key );
__asm __saveds ULONG CBaseSeek(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data,
	register __a2 UBYTE *key,
	register __d0 ULONG opts );
__asm __saveds ULONG CBaseSeekNear(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data,
	register __a2 UBYTE *key,
	register __d0 ULONG opts );
__asm __saveds ULONG CBaseSeekPercentage(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data,
	register __a2 UBYTE *key,
	register __d0 ULONG opts );
__asm __saveds ULONG CBaseFindPercentage(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data );
__asm __saveds ULONG CBaseBeginTransaction(
	register __a0 struct CBaseHandle *ah );
__asm __saveds ULONG CBaseEndTransaction(
	register __a0 struct CBaseHandle *ah );
__asm __saveds ULONG CBaseAbortTransaction(
	register __a0 struct CBaseHandle *ah );
__asm __saveds ULONG CBaseMemoDelete(
	register __a0 struct CBaseHandle *ah );
__asm __saveds ULONG CBaseMemoAppend(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data,
	register __d0 ULONG len );
__asm __saveds ULONG CBaseMemoTop(
	register __a0 struct CBaseHandle *ah );
__asm __saveds ULONG CBaseMemoRead(
	register __a0 struct CBaseHandle *ah,
	register __a1 UBYTE *data,
	register __d0 ULONG len );
__asm __saveds ULONG CBaseSave( void );
__asm __saveds ULONG CBaseInitialize(
	register __a0 UBYTE *command );

#define CBASE_COMP_EQUAL	1
#define CBASE_COMP_GREATER	2
#define CBASE_COMP_LESS		4
#define CBASE_COMP_UNEQUAL	0

struct CBaseFilter {
	UBYTE	logic;		// 0=first, 1=AND, 2=OR
	UBYTE	type;		// CBASE_TYPE codes above

	USHORT	off;		// field start
	USHORT	len;		// field len

	UBYTE	op;		// CBASE_COMP codes above
	UBYTE	*constant;	// comparison constant
	USHORT	coff;		// or comparison field offset
};

struct CBaseField {
	USHORT	off;
	USHORT	len;
};

struct CBaseExtended {
	UBYTE	*data;			// array of records (or keys)
	USHORT	*recsize;		// array of record sizes
	ULONG	*address;		// array of physical record addresses

	USHORT	records;		// maximum # of records to return
	USHORT	datasize;		// maximum size of *data

	USHORT	rejects;		// maximum filtered records
	USHORT	nfilter;		// number of filter terms
	struct	CBaseFilter *filter;	// filter terms

	USHORT	nfields;		// number of field terms 0==Full record
	struct	CBaseField *field;	// field terms
};
