/*     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                                                  */
#include "global.h"
BEDPLUGIN
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "../offtypes.h"
#include "index2table.h"
class Index2table;
class Editor {
public:
#include "faked.h"

iscalled(index2table)
//int Editor::gettableposition(int &length, int &startpos) ;
int Editor::startindex2table(Filter * (*func)(int fb,int sb,char *opts,ScreenPart *part=NULL)) ;
};
#define min(x,y) ((x)<(y)?(x):(y))
	Index2table::Index2table(int fbytes,int sbytes,int off,int len,int pbase): tableoffset(off),maxintable(len),ptrbase(pbase),Filter(fbytes,sbytes) {
		doedit=1;
	
		label=name=filtername(Index2table);
		}
	Index2table::Index2table(int fb,int sb,char *conv) : Filter(fb,sb) {
		doedit=1;
		label=name=filtername(Index2table);
		if(conv) {
			if(!sscanf(conv,"%d-%d-%d",&tableoffset,&maxintable,&ptrbase)) {
				sscanf(conv,"%d-%d",&tableoffset,&maxintable);
				ptrbase=0;
				}
			}
		}
	Index2table::Index2table(Index2table &rev): Filter(rev) {
		doedit=1;
		label=rev.label;
		tableoffset=rev.tableoffset;
		maxintable=rev.maxintable;
		ptrbase=rev.ptrbase;
		edit=rev.edit;
		}
	int Index2table::setpart(ScreenPart *p) {
		Filter::setpart(p);
		edit=p->editor;
		if(maxintable==LONG_MAX)
			maxintable=edit->filesize()-tableoffset;
		}
	char *Index2table::convstr(void) {
	#define convmax 80
		static char *conv=new char[convmax];
		snprintf(conv,convmax,"%d-%d-%d",tableoffset,maxintable,ptrbase);
		return conv;
		}
	Index2table::~Index2table() {
		}
	 Filter *Index2table::newone(void) {
		return new Index2table(*this);
		}
	 int Index2table::chbytes(int b) {
		edit=part->editor;
		bytesfile=b;
		return bytesscreen;
		}
	 int Index2table::chbytesback(int b) {
		edit=part->editor;
		bytesscreen=b;
		err=0;
		return bytesfile;
		}
#define min(x,y) ((x)<(y)?(x):(y))
	 int Index2table::fromfile(unsigned char *input,unsigned char *output) {
		if(edit) {
			long intable=*((long*)input)-ptrbase;
			char tmp[bytesscreen+1]; 
			memset(output,' ',bytesscreen);
			if(intable>=0&&intable<maxintable) {
				edit->getmem(	tableoffset +intable,(char *)tmp,bytesscreen);
				int len=min(strlen(tmp),bytesscreen);
				memcpy((char *)output,tmp,len);
				}
			}
		return bytesscreen;
		}
	 int Index2table::tofile(unsigned char *input,unsigned char *output) {
/* How do you know if it was intented to endup in the file instead of for
some other purpose like search 
WHen stop reading input? 
If you stop with space no space is possible inside label
if you don't stop you overwrite the next label
Some special stop character?
*/
		if(doedit&&edit) {
			long intable=*((long*)output)-ptrbase;
			if(intable>=0&&intable<maxintable) {
				int len=strcspn((char *)input," ");
				char tmp[len+1];
				memcpy(tmp,input,len);
				tmp[len]='\0';
				edit->putmem(	tableoffset +intable,(char *)tmp,min(bytesscreen,len+1));
				}
			}

		return bytesfile;
		}
	int  Index2table::equal(Filter *fil) {
		if(!Filter::equal(fil))
			return 0;
		if(tableoffset!=((Index2table *)fil)->tableoffset)
			return 0;
		if(maxintable!=((Index2table *)fil)->maxintable)
			return 0;
		if(edit!=((Index2table *)fil)->edit)
			return 0;
		return 1;
		}

registerfilterclass(Index2table) 



#include "../screen.h"
#include "../getfile.h"
int Editor::index2table(void) {
	ScreenPart *super=activemode(),*act;
	act=super->getsubpart();
	char offset[50]="";
	char length[50]="";
	char ptrbase[50]="";
	Index2table *ad=NULL;
for(int i=act->firstfilter;i<act->lastfilter;i++) {
	if(act->filters[i]->name==filtername(Index2table)) {
		ad=(Index2table*)act->filters[i];
		sprintf(offset,"%d",ad->tableoffset);
		sprintf(length,"%d",ad->maxintable);
		sprintf(ptrbase,"%d",ad->ptrbase);
		break;
		}
	}
int res=0;

  begindialog(11,40,5);
    mvwaddstr(takescr,1,2,"Labels at");
    linernrmax("File Off~set",offset,3,2,17,50);
    linernrmax("~Length",length,5,2,17,50);
    linernrmax("~Pointer base",ptrbase,7,2,17,50);
    oke(9,2);
    act("~Cancel",9,10);
  enddialog(res,res);
filesup();
switch(res) {
	case 0:;
	case 4: 
		return -1;
	}
	long taboff=strtol(offset,NULL,0);
	long tablen=strtol(length,NULL,0);
	long pbase=strtol(ptrbase,NULL,0);
	if(ad) {
			
		ad->tableoffset=taboff;
		ad->maxintable=tablen;
		ad->ptrbase=pbase;
		}
	else  {
		ScreenPart *super=activemode(),*act;
		act=super->getsubpart();
		ad=new Index2table(4,act->datbytes(),taboff,tablen,pbase);
		if(ad->error()) {
			delete ad;
			message("Error adding add");
			return -1;
			}
		addfilter(ad);
		}
	modechanged();
	super->calcsizes();
	toscreen();	
	return 0;
	}

sethelp(index2table,"index2table\n\nindex2table interprets the file content as long's (4 bytes)\nwhich are indexes in a table at some offset in the current file.\nInstead of the index number it displays the content of that table\nat that position. index2table is a filter that should be applied\nto a datatype appropriate for the data in the table. For this\npurpose this procedure asks to specify at what offset in the file\nthe labels start, with what index the table starts and table length.\nIndex2table is for example\nused to show the names of procedures in a symbol table.\nindex2table is then applied to multibyte ascii that shows\nthis label instead of the index.\ndynsym and symtab are sub classes of index2table.\nThey are used by misc/dynsym.bedda and misc/symtab.bedda.\nBecause of this use index2table was previously called symtable.") 
call(index2table)

/*
extern char *filtername(Section) ;
static char sectionnul[1]="";
class Section: public Index2table {
	public:	
	int setpart(ScreenPart *p) {
		Filter::setpart(p);
		edit=p->editor;
		tableoffset=edit->getsymposition(maxintable);
		}

	Section(int fb,int sb,char *conv=NULL,ScreenPart *p=NULL) : Index2table(fb,sb) {
		label=name=filtername(Section);
		if(part) {
			Filter::setpart(p);
			edit=part->editor;
			tableoffset=edit->getsymposition(maxintable);
			}
		else
			maxintable==LONG_MAX;
		}
	Section(Index2table &rev): Index2table(rev) {
		label=rev.label;
		maxintable==LONG_MAX;
		}
	char *convstr(void) {
		return sectionnul;
		}
	};
*/
int Editor::startindex2table(Filter *(*func)(int fb,int sb,char *opts,ScreenPart *part)) {
	ScreenPart *super=activemode(),*act;
	act=super->getsubpart();
	Filter *ad=func(4,15,"",act);
	if(!ad) {
		message("Could not create filter");
		beep();
		return -1;
		}
	if(ad->error()) {
		delete ad;
		message("Error adding add");
		return -1;
		}
	addfilter(ad);
	act->screenbytes(ad->bytesscreen);
	toscreen();	
	}



