/*     Bed a menu-driven multi dataformat binary editor for Linux            */
/*     Copyright (C) 1998 Jaap Korthals Altes <jkaltes@hetnet.nl>       */
/*                                                                           */
/*     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., 675 Mass Ave, Cambridge, MA 02139, USA.             */
/* Fri Dec  8 22:14:27 2000                                                  */
#ifndef  EDITOR_H
#define EDITOR_H
#include <features.h>
#define HAS_BOOL
#include "screen.h"
#ifdef USETHREADS
#include <pthread.h>

#ifdef HAS_SEMAPHORE
#include <semaphore.h>
#else
#define sem_init(x,y,z) pthread_mutex_init(x,NULL)
#define sem_wait(x) pthread_mutex_lock(x)
#define sem_post(x) pthread_mutex_unlock(x)
#define	sem_t pthread_mutex_t
#endif
#endif
#include "memory.h"
//#include "marks.h"
#include "type.h"
#include "myalloc.h"
#define MAXANT 256

const int maxmenus=30;
#define MAXUNDO 1000
struct undo {
	OFFTYPE pos;
	unsigned char *str;
	int len;
	};

class Filter ;
class ScreenPart;

class Empty;
class keylookup;

#ifdef USETHREADS
class Editor;
struct threadgegs {
	ScreenPart *part;
	Editor *ed;
	char *ant;
	int len;
	OFFTYPE pos;
	};
#endif

class Editor {

	public:
		WINDOW *editscreen;
		int fromtop,numberof;

int visualwidth,visualoffset,virtualwidth, visualunit;
// Declaraties
struct Menugeg {
	 char *name;
	 char *key;
	int (Editor::*proc)(void);
	};
//Static 
	static  int (Editor::*proc[])(void);
	static  char *procnames[];

	static  int (Editor::**dynproc)(void);
	static  char **dynprocnames;
	static int dynprocnr;

	static int procnr;
//DATA:
	Memory mem;
void Editor::enlargeparts(void);
	ScreenPart **parts;
	int maxparts;
	int nrparts;
	int mode;
//	enum {ASCII,HEX} mode;
	char *buffer;
	char *getbuf(void);
	int changed,modified;
	int edge,shownbufsize;
	OFFTYPE filepos ,lastgotopos;
	long editpos,oldpos,updated;
	int dofromfile;
	int commandmode;
	int allheight,Screenheight,Screenwidth,edittop;
	int shouldreinit;
int modechanged(void); 
	int nrx,nry;
	int getcols(void) ;
	int distribute(void) ;

	ScreenPart *searchpart;
#ifdef USETHREADS
	sem_t sema;
	pthread_t threadsearch;
	int threadrunning;
struct  threadgegs gegsthread;
	void stopthread(void); 
	int found;
#endif
#define MAXNUMSTR 12
/* Byte number procedures */
	int maxnum, numbase;
	char numstr[MAXNUMSTR];
	inline int startnum(void) {return 0;};
	int putnumbase(int base);
	void number(void);
	void numline(int y);

	int Editor::nrnumber(void);
	inline int top(void) {return 0;};

int resetnumbase(void) ;
/*
struct block {
	unsigned char *begin;
	int last,free,len,lowest;
	struct block *prev;
	};
*/
//struct block *now,*chunkbefore;


struct  undo undobuf[MAXUNDO];
int lastundo,redos,beginundo,undohalf;
void initundo(void) ;
void delundo(void) ;

unsigned char *Editor::expandchunk(unsigned char *ptr,int len,int oldlen) ;

inline struct undo *Editor::getnextundo(void) ;


int Editor::popundo(unsigned char **buf,OFFTYPE *pos) ;
int undoone(void) ;
int Editor::strtoundoer(OFFTYPE pos,int size) ;
int Editor::strtoundo(OFFTYPE pos,int size) ;
int Editor::addundo(OFFTYPE pos,unsigned char ch) ;
int Editor::undopos(void)  ;
int Editor::appendstrtoundo(OFFTYPE pos,char *str, int size) ;
int Editor::appendtoundo(OFFTYPE pos, int size) ;
int     Editor::extendtoundo(OFFTYPE oldsize);

int	Editor::extendtoundoonly(OFFTYPE oldsize) ;


//PROCEDURES

#undef prodefname
#define prodefname(name,pro)  int pro(void);
#undef prodef
#define prodef(pro)  int pro(void);
#include "procedures.h"
#undef prodef
	int proceskey(void);
int proceskeyonce(void) ;

	Editor(char *filename);
	~Editor() ;
	int reinit(void);
	int place(int);
//	int changechar(int pos,unsigned char ch);
inline int Editor::printchar(int pos) ;
	int changestr(int pos,unsigned char *str,int size);
	void doexit(void);
	void nocursor(void);
int Editor::fromfile(OFFTYPE pos);
	int fromfile(void) ;
	int geteditpos(void);
	int lowborder(void);

	OFFTYPE getfilepos(void);

/* Geometry */

int Editor::toborderpos(OFFTYPE pos) ;
	int Editor::toborder(OFFTYPE pos) ;
	inline int cols(void) { return nrx;};
	inline int rows(void) { return nry;};

	inline int x(void) { return (editpos%nrx);};
	inline int y(void) { return (editpos/nrx);};
	int writebuf(void);
	void cursorpos(void) ;
	inline void resetpos(void);
	int topos(OFFTYPE pos) ;
int Editor::pretopos(OFFTYPE pos);
	void putline(int y) ;
	int nomessage;
	inline void textovermessage(void);
	inline void restoremessageline(void);
	 void clearmessage(void) ;

	int getinput(const char question[],char *answer) ;
	int inputget(char *answer,const char *format,...) ;

#define NEXTFILE 888
#define PREVFILE 889
#define ASKFILE  890
#define LASTFILE 891
#define FIRSTFILE 891
#define FILENR	892
#define MAXFILES 60


int askmenufile(void) ;

	inline int switchcursor(void) ;
	int nextfast(void) ;

	int save(void);
	int Editor::saveaser(const char *ant) ;

	int extendfile(int len) ;



int Editor::toscreen(void) ;


OFFTYPE Editor::getmem(OFFTYPE pos,char *buf,OFFTYPE len);
OFFTYPE Editor::putmem(OFFTYPE pos,char *buf,OFFTYPE len);



	short searchbytes,searchgrens,indatatype;
	int openfile(const char *ant) ;
FILEHANDLE Editor::tmpopenfile(const char *ant) ;
	char *formatsearch,*searchdataname;

#define SEARCH_REGEX 4
#define SEARCH_FORWARD 1
#define SEARCH_CASE 2
#define SEARCH_BOUNDARY 8
int Editor::searchtype(int newtype) ;
	OFFTYPE dosearch(char *ant,int len);
	OFFTYPE dosearch(OFFTYPE pos, char *ant,int len) ;
	OFFTYPE dosearcher(char *ant,int len);
//	OFFTYPE dosearcher(OFFTYPE pos, char *ant,int len) ;
OFFTYPE Editor::dosearcher(ScreenPart *part,OFFTYPE pos, char *ant,int len) ;
	int searchregex(short yes);
	int searchforward(short yes);
	int searchcase(short yes) ;
	int searchonboundary(short yes) ;
	int searchedge(short yes);
//	int searchlist(char *ant,int len) ;
int Editor::searchlist(ScreenPart *part,char *ant, int len) ;
	int Editor::searcher(int askrepl);
#ifdef USETHREADS
//int Editor::searchlister(char *ant,int len,OFFTYPE pos) ;
int Editor::searchlister(ScreenPart *part,char *ant,int len,OFFTYPE pos) ;
#endif
	char *replacestr;
	int replacestrlen;
	int Editor::replacehere(OFFTYPE pos, char *str,int len  ) ;
	int Editor::replacer(char *rep,OFFTYPE foundpos);
//int Editor::replacer(ScreenPart *part,char *rep,OFFTYPE foundpos) ;

	int endedit(void);
	int closefile(void);

	int addbefore(DataType type,int to,int len,int order);
	inline int addafter(DataType type,int to,int len,int order) { return addbefore(type,to+1, len,order); }
 
	int tomode(DataType type,int len,int order) ;
	int Editor::tomodenr(int newmode) ;
//	int tomodeget(void) ;
 void editup(void) ;

	void filesup(void);



//	long digfrom(char *ant); to OFFTYPE??
	inline int maxedit(void) { return ((nrx)*(nry));}

	int screensize(void);
	 void memorize(void);


//	long selects[2];

	static	int	lensel;
	static char *selbuf;
	OFFTYPE other;
	int el;
int Editor::selected(OFFTYPE pos) ;

OFFTYPE Editor::getselregion(OFFTYPE *start) ;
int Editor::setmark(unsigned char *keys,int nr,OFFTYPE pos) ;

keylookup *marksptr;
/*
inline int defaultmark(void) {
	marx.defaultmark(editpos+filepos);
	return 0;
	};
*/
#undef getch
 int getch(void) ;


#define scrollon(x,y) scrollok(x,y)
inline void overline();
/*
inline int output(const char info[]) { }
*/
int output(const char info[]) ;
int message(char *format ...) ;
 int getkeyinput(char *format ...) ;

 int Editor::showposition(void) ;



int gotonrwin(int nr) ;


void windel(void) ;



struct menuel {
	int key;
	int (Editor::*proc)(void);
	char *name;
	char *alt;
	char keypos;
	};
struct menu {
	WINDOW *win;
	int len,nu,key;
	struct menuel *el;
	char *name;
	char keypos;
	int maxname;
	int barpos;
	};
void editontop(void) ;

int showmenu(void) ;
static void selectmenu(struct menu *m,int dir) ;
static struct menu *menumk(int x,int el,struct Menugeg pro[], char *under) ;
static int Editor::menustructs(void) ;
static WINDOW *Editor::rewritemenu(struct Editor::menu *m) ;

static int Editor::deletemenu(int menunr) ;
static int Editor::deletemenuitem(int menunr,int pos) ;
static int Editor::addmenuitem(int menunr,char *name,int pos, int ( Editor::*proc)(void),int insert=0,char *keystr="") ;
static int Editor::addmenu(char *name,int menunr,int insert=0) ;

static struct menu *menulist[maxmenus];

static int menuiter,menunu;
//int addtobar(char *name) ;
static int Editor::addtobar(struct Editor::menu *m) ;
static int menus(void) ;
int Editor::fileok(void) ;
int Editor::saveinode(void) ;
int Editor::discard(void) ;
  OFFTYPE Editor::getpart(OFFTYPE begin, OFFTYPE len, char * buf); 
   OFFTYPE Editor::putpart(OFFTYPE begin, OFFTYPE len, char * buf);

OFFTYPE filesize(void);
void erefresh(void);

static int (Editor::*Editor::ineditproc[])(void);
static int (Editor::*Editor::inmenuproc[])(void);
int Editor::therepeat(int nr) ;
char *Editor::getfilename(char *buf);

int Editor::getselbuf(char **buf) ;
int Editor::putselbuf(char *buf,int len) ;

OFFTYPE Editor::getselect(void) ;
OFFTYPE Editor::setselect(OFFTYPE pos) ;

OFFTYPE Editor::posputbuf(OFFTYPE pos,char *buf,OFFTYPE len);
OFFTYPE Editor::putbuf(char *buf,OFFTYPE buflen);


void Editor::splitpos(OFFTYPE pos) ; 

int Editor::menuresized(void);
int Editor::getmode(DataType type,int len,int order) ;
int Editor::installpart(ScreenPart *sub) ;
int Editor::installpart(ScreenPart *sub,int separ) ;

int Editor::forcetruncate(void) ;
int Editor::filetruncate(OFFTYPE vanaf);
int Editor::savesel(const char *ant) ;
int Editor::saveshownname(const char *ant) ;
int Editor::readshownname(const char *ant) ;
//OFFTYPE formsearch(OFFTYPE from,char *ant,short len) ;
OFFTYPE Editor::formsearch(ScreenPart *datashown,OFFTYPE from,char *ant,short len) ;
OFFTYPE Editor::memnextsearch(void) ;
//OFFTYPE Editor::memnextsearch(ScreenPart *datashown) ;
//OFFTYPE Editor::memsearch(OFFTYPE pos,char *str,int len) ;
OFFTYPE Editor::memsearch(ScreenPart *part,OFFTYPE pos,char *str,int len) ;

//int Editor::nextsearching(ScreenPart *part) ;
ScreenPart *activemode(void) ;

int Editor::getanswer(const char *question,char *answ,int anslen,int ansroom=5) ;
int Editor::addtocontain(ScreenPart *part) ;
BLOCKTYPE blocksize(void);

int Editor::addfilter(Filter *fil) ;
int Editor::playmacrofile(const char *name) ;
int Editor::playmacro(char *buf,int len);

int Editor::savecontain(void) ;
int Editor::getsavedatahandler(char *question) ;
int Editor::savealldatatypes(void) ;
int Editor::loaddatatype(char *gegs,int endf,int addfield) ;
int Editor::proconname(char *str) ;
int Editor::configASCII(ScreenPart *sub,int kind);
int Editor::partconfig(ScreenPart *sub,int kind=1) ;
ScreenPart *Editor::replacepart(ScreenPart *part,int pos=-1) ;
int Editor::makevisible(ScreenPart *part,int pos) ;
OFFTYPE Editor::nextregexshown(ScreenPart *datashown);
int Editor::emptyconfig(Empty *emp,int kind) ;
private:
int ismessage;
int Editor::showmessage(void) ;
int Editor::realoutput(const char info[]) ;

OFFTYPE *previouspos;
int previouspositer, previousposhead;
public:
OFFTYPE getpreviouspos(void);
char justopened;
int Editor::insertshown(char *gegs, off_t endf) ;
#define mkmenunum(num) int Editor::menu##num##show(void);
#include "mkmenus.h"
#undef mkmenunum
};
#endif
