aboutsummaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c704
1 files changed, 704 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..99ab651
--- /dev/null
+++ b/main.c
@@ -0,0 +1,704 @@
+#define MAJORVERSION 0
+#define MINORVERSION 6
+#define REVISION 5
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <string.h>
+#include <ncurses.h>
+#include "menu.h"
+#include "configfile.h"
+#include "machine_type.h"
+#include "input.h"
+#include "output.h"
+#include "buffers.h"
+#include "ui.h"
+#include "hexcalc.h"
+#include "search.h"
+#include "gpl.h"
+#include "markers.h"
+#include "correlation.h"
+
+void welcomescreen(char* argv0)
+{
+ fprintf(stderr,"*** DHEX %i.%i%i\n",MAJORVERSION,MINORVERSION,REVISION);
+ fprintf(stderr,"*** (C)opyleft 2011 by Thomas Dettbarn\n");
+ fprintf(stderr,"*** dettus@dettus.net (include DHEX somewhere in the subject)\n\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr,"(start it with %s -gpl to see the license)\n",argv0);
+ fprintf(stderr,"\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr,"This program is free software; you can redistribute it and/or modify\n");
+ fprintf(stderr,"it under the terms of the GNU General Public License as published by\n");
+ fprintf(stderr,"the Free Software Foundation; either version 2 of the License, or\n");
+ fprintf(stderr,"(at your option) any later version.\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr,"This program is distributed in the hope that it will be useful,\n");
+ fprintf(stderr,"but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
+ fprintf(stderr,"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
+ fprintf(stderr,"GNU General Public License for more details.\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr,"You should have received a copy of the GNU General Public License\n");
+ fprintf(stderr,"along with this program; if not, write to the Free Software\n");
+ fprintf(stderr,"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n");
+ fprintf(stderr," \n\n");
+}
+void helpscreen(char* argv0,int exitval)
+{
+ welcomescreen(argv0);
+ fprintf(stderr,"%s [Parameters]: General parameters\n",argv0);
+ fprintf(stderr," -h, -H, -? show this help\n");
+ fprintf(stderr," -v, -V show the version number %i.%i%i\n",MAJORVERSION,MINORVERSION,REVISION);
+ fprintf(stderr," -k, -K start the keyboard setup manually\n");
+ //fprintf(stderr," -x, -X start the hexcalc program (TODO)\n");
+ fprintf(stderr," -g, -G show the license\n");
+ fprintf(stderr," -f, -F [configfile] read the config from [configfile]\n");
+ fprintf(stderr," -m, -M [markerfile] read the bookmarks from [markerfile]\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr,"%s [Parameters] [Filename]: Edit a single file\n",argv0);
+ fprintf(stderr," -ob, -OB [x] set the cursor to [x] (binary)\n");
+ fprintf(stderr," -od, -OD [x] set the cursor to [x] (decimal)\n");
+ fprintf(stderr," -oh, -OH [x] set the cursor to [x] (hexadecimal)\n");
+ fprintf(stderr," -oo, -OO [x] set the cursor to [x] (octal)\n");
+ fprintf(stderr," -sa, -SA, -sab, -SAB [x] find the ascii string x in file (b=backwards)\n");
+ fprintf(stderr," -sh, -SH, -shb, -SHB [x] find the hex string x in file (b=backwards)\n");
+ fprintf(stderr," -r, -R [read searchlog] read the search positions from this searchlog\n");
+ fprintf(stderr," -w, -W [write searchlog] write the location of the occurances to this log\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr,"%s [Parameters] [Filename1] [Filename2]: Diff mode\n",argv0);
+ fprintf(stderr," -cd, -CD [x] correlate with the minimum difference\n");
+ fprintf(stderr," -cb, -CB, -cl, -CL correlate with the best/longest match\n");
+ fprintf(stderr," -o1b, -O1B [x] -o2b, -O2B [y] set the cursors to [x] and [y] (binary)\n");
+ fprintf(stderr," -o1d, -O1D [x] -o2d, -O2D [y] set the cursors to [x] and [y] (decimal)\n");
+ fprintf(stderr," -o1h, -O1H [x] -o2h, -O2H [y] set the cursors to [x] and [y] (hexadecimal)\n");
+ fprintf(stderr," -o1o, -O1O [x] -o2o, -O2O [y] set the cursors to [x] and [y] (octal)\n");
+ fprintf(stderr," -s1a, -s1ab [x] -s2a, -s2ab [y] find the ascii strings [x] and [y]\n");
+ fprintf(stderr," -s1h, -s1hb [x] -s2h, -s2hb [y] find the hex strings [x] and [y]\n");
+ fprintf(stderr," -r1 [searchlog1] -r2 [searchlog2] read the search positions from searchlogs\n");
+ fprintf(stderr," -w1 [searchlog1] -w2 [searchlog2] write the search positions to searchlogs\n");
+ //fprintf(stderr," -c, -C [corrlen] find the best correlation between the files (TODO)\n");
+ exit(exitval);
+}
+int parsecursorpos(tInt64* cursorpos1,tInt64* cursorpos2,char* lastopt,char* argv)
+{
+ int i;
+ int g;
+ int d;
+ char c;
+ tInt64 x=0;
+
+ g=16; // default: hex
+ if (lastopt[1]=='D' || lastopt[2]=='D') g=10; // -od: decimal
+ if (lastopt[1]=='d' || lastopt[2]=='d') g=10; // -od: decimal
+ if (lastopt[1]=='H' || lastopt[2]=='H') g=16; // -oh: hexadecimal
+ if (lastopt[1]=='h' || lastopt[2]=='h') g=16; // -oh: hexadecimal
+ if (lastopt[1]=='B' || lastopt[2]=='B') g=2; // -ob: binary
+ if (lastopt[1]=='b' || lastopt[2]=='b') g=2; // -ob: binary
+ if (lastopt[1]=='O' || lastopt[2]=='O') g=8; // -oo: octal
+ if (lastopt[1]=='o' || lastopt[2]=='o') g=8; // -oo: octal
+
+
+ for (i=0;i<strlen(argv);i++)
+ {
+ c=argv[i];
+ if (c>32)
+ {
+ x=x*g;
+ d=g;
+ if (c>='0' && c<='9') d=c-'0';
+ if (c>='a' && c<='f') d=c-'a'+10;
+ if (c>='A' && c<='F') d=c-'A'+10;
+
+ if (d>=g) return RETNOK;
+ x=x+d;
+ }
+ }
+ if (lastopt[1]=='1' || lastopt[2]=='1') *cursorpos1=x; // -o1: cursorpos1
+ else if (lastopt[1]=='2' || lastopt[2]=='2') *cursorpos2=x; // -o2: cursorpos2
+ else {
+ *cursorpos1=x; // -o: both
+ *cursorpos2=x; // -o: both
+ }
+ return RETOK;
+
+}
+int parsecommandlineoptions(int argc,char** argv,tInt64* cursorpos1,tInt64* cursorpos2,tBool* diffmode,int* filename1,int* filename2,tBool* keyboardsetupreq,char* markerfilename,char* configfile,tSearch* search1,tBool* gosearch1,tSearch* search2,tBool* gosearch2,tCorrelation* correlation,tBool* gocorr)
+{
+ int filenamecnt=0;
+ int i;
+ int retval=RETOK;
+ char lastopt[8];
+ tBool moreopts=1;
+
+ *gosearch1=0;
+ *gosearch2=0;
+ *gocorr=0;
+ memset(lastopt,0,8);
+ for (i=1;i<argc;i++)
+ {
+ if (argv[i][0]=='-' && moreopts)
+ {
+ memcpy(lastopt,&argv[i][1],8);
+ switch (lastopt[0]) // this is for parameters with just one part
+ {
+ case '-': lastopt[0]=0; // -- means: no more options
+ if (argv[i][2]) retval=RETNOK;
+ moreopts=0;
+ break;
+ case 'c': // searching for a correlation could be a two-parted search.
+ case 'C':
+ *gocorr=1;
+ if (lastopt[1]=='d' || lastopt[1]=='D') correlation->algorithm=CORR_MIN_DIFF; // min diff, this is two parted
+ else if (lastopt[1]=='b' || lastopt[1]=='B') {correlation->algorithm=CORR_BEST_MATCH;lastopt[0]=0;} // best match
+ else if (lastopt[1]=='l' || lastopt[1]=='L') {correlation->algorithm=CORR_LONGEST_MATCH;lastopt[0]=0;} // longest match
+ else {
+ fprintf(stderr,"unknown correlation algorithm. please provide -cb, -cd or -cl\n");
+ exit(1);
+ }
+
+ break;
+ case '?':
+ case 'H':
+ case 'h': helpscreen(argv[0],0); // print the helpscreen and be done with it
+ lastopt[0]=0;
+ break;
+ case 'g':
+ case 'G':
+ print_gpl(); // print the gpl and be done with it
+ exit(0);
+ lastopt[0]=0;
+ break;
+ case 'X':
+ case 'x': printf("TODO:hexcalc\n");
+ break;
+ case 'K':
+ case 'k':
+ *keyboardsetupreq=1;
+ lastopt[0]=0;
+ break;
+ case 'v':
+ case 'V':
+ printf("%i.%i%i\n",MAJORVERSION,MINORVERSION,REVISION);
+ exit(0);
+ break;
+ default:
+ break;
+
+ }
+ }
+ else if (lastopt[0]) // two-parted parameters
+ {
+ switch (lastopt[0])
+ {
+ case 'C':
+ case 'c':
+ correlation->start_mindiff=atoi(argv[i]);
+ break;
+ case 'F':
+ case 'f':
+ snprintf(configfile,512,"%s",argv[i]);
+ break;
+ case 'S':
+ case 's':
+ {
+ tInt8 stringtype=0; // 0=unknown, 1=ascii, 2=hex
+ tBool forward=1;
+ tSearch* search;
+ tBool* gosearch;
+ int j;
+
+ search=search1;
+ gosearch=gosearch1;
+ for (j=1;j<8 && lastopt[j];j++)
+ {
+ if (lastopt[j]=='a' || lastopt[j]=='A') stringtype=1;
+ if (lastopt[j]=='h' || lastopt[j]=='H') stringtype=2;
+ if (lastopt[j]=='b' || lastopt[j]=='B') forward=0;
+ if (lastopt[j]=='1')
+ {
+ search=search1;
+ gosearch=gosearch1;
+ }
+ if (lastopt[j]=='2')
+ {
+ search=search2;
+ gosearch=gosearch2;
+ }
+
+ }
+
+ *gosearch=1;
+ search->forwardnotbackward=!(lastopt[2]=='b' || lastopt[2]=='B');
+ if (stringtype==1)
+ {
+ memcpy(search->searchstring,argv[i],19);
+ search->searchlen=strlen(argv[i]);
+ if (search->searchlen>19) search->searchlen=19;
+ } else if (stringtype==2) {
+ int k=0;
+ int x=0;
+ search->searchlen=0;
+ for (j=0;j<strlen(argv[i]) && search->searchlen<19;j++)
+ {
+ int y;
+ y=-1;
+ x<<=4;
+ y=(argv[i][j]>='0' && argv[i][j]<='9')?argv[i][j]-'0':y;
+ y=(argv[i][j]>='a' && argv[i][j]<='f')?argv[i][j]-'a'+10:y;
+ y=(argv[i][j]>='A' && argv[i][j]<='F')?argv[i][j]-'A'+10:y;
+ if (y>=0)
+ {
+ x|=y;
+ if (k&1)
+ {
+ search->searchstring[search->searchlen++]=(x&0xff);
+ }
+ k++;
+ }
+ else if (argv[i][j]!=' ')
+ {
+ fprintf(stderr,"illegal character in hex searchstring.\n");
+ retval=RETNOK;
+ }
+ }
+ } else {
+ fprintf(stderr,"please select one of -sa or -sh\n");
+ retval=RETNOK;
+ }
+ }
+ break;
+ case 'r':
+ case 'R':
+ {
+ tSearch* search;
+ if (lastopt[1]=='2') search=search2; else search=search1;
+ memcpy(search->readlogfilename,argv[i],64);
+ search->readsearchlog=1;
+ }
+ break;
+ case 'w':
+ case 'W':
+ {
+ tSearch* search;
+ if (lastopt[1]=='2') search=search2; else search=search1;
+ memcpy(search->writelogfilename,argv[i],64);
+ search->writesearchlog=1;
+ }
+ break;
+ case 'O':
+ case 'o':
+ retval=parsecursorpos(cursorpos1,cursorpos2,lastopt,argv[i]);
+ break;
+ case 'm':
+ case 'M':
+ if (markerfilename) memcpy(markerfilename,argv[i],64);
+ break;
+ default:
+ retval=RETNOK;
+ break;
+ }
+ lastopt[0]=0;
+ }
+ else // no parameters, must be a filename
+ {
+ if (filenamecnt==0)
+ {
+ *filename1=i;
+ }
+ if (filenamecnt==1)
+ {
+ *filename2=i;
+ *diffmode=1;
+ }
+ filenamecnt++;
+ if (filenamecnt>2) retval=RETNOK;
+ }
+ }
+ return retval;
+}
+int main(int argc,char** argv)
+{
+// tBuffer buf1;
+// tBuffer buf2;
+ thHexCalc* hHexCalc=NULL;
+ tBuffer* buf1=NULL;
+ tBuffer* buf2=NULL;
+ tOutput* output=NULL;
+ tInt64 cursorpos1;
+ tInt64 firstpos1;
+ tInt64 cursorpos2;
+ tInt64 firstpos2;
+ tInt64 oldcursorpos1;
+ tInt64 oldfirstpos1;
+ tInt64 oldcursorpos2;
+ tInt64 oldfirstpos2;
+ tSearch search1;
+ tSearch search2;
+ tMarkers* markers;
+ tBool gosearch1=0;
+ tBool gosearch2=0;
+ tCorrelation correlation;
+ char markerfilename[64];
+
+ tUInt8 windowfield=0; // 0=hex field buffer 1, 1=ascii field buffer 1, 2=hex field buffer 2, 3=ascii field buffer 2
+ tBool diffmode=0;
+ tBool keyboardsetupreq;
+ tBool gocorr=0;
+ int retval;
+
+ int ch;
+ int filename1=-1;
+ int filename2=-1;
+ char* homedir;
+ char configfile[512];
+
+ memset(configfile,0,512);
+ memset(markerfilename,0,64);
+ markers=initmarkers();
+ output=malloc(sizeof(tOutput));
+ memset(output,0,sizeof(tOutput));
+ initcolors(output);
+ initkeytab(output);
+
+ keyboardsetupreq=0;
+ cursorpos1=0;
+ cursorpos2=0;
+ clearsearch(&search1);
+ clearsearch(&search2);
+ clear_correlation(&correlation);
+ if (parsecommandlineoptions(argc,argv,&cursorpos1,&cursorpos2,&diffmode,&filename1,&filename2,&keyboardsetupreq,markerfilename,configfile,&search1,&gosearch1,&search2,&gosearch2,&correlation,&gocorr)!=RETOK)
+ {
+ if (output)
+ {
+ if (output->pKeyTab) free(output->pKeyTab);
+ free(output);
+ }
+ if (markers) free(markers);
+ helpscreen(argv[0],0);
+ }
+ if (configfile[0]==0)
+ {
+ homedir=getenv("HOME");
+ if (homedir==NULL)
+ {
+ fprintf(stderr,"$HOME-variable not set. \n\n");
+ fprintf(stderr,"I'm sorry, but you'll have to provide a config-file by using\n");
+ fprintf(stderr,"%s -f /PATHTOCONFIGFILE/.dhexrc\n",argv[0]);
+ exit(1);
+ } else {
+ snprintf(configfile,512,"%s/.dhexrc",homedir);
+ }
+ }
+
+ if (markerfilename[0]) if (parsemarkerfile(markers,markerfilename)!=RETOK)
+ {
+ if (output)
+ {
+ if (output->pKeyTab) free(output->pKeyTab);
+ free(output);
+ }
+ if (markers) free(markers);
+ helpscreen(argv[0],0);
+
+ }
+
+ if (filename1==-1 || (filename2==-1 && diffmode)) helpscreen(argv[0],0);
+ retval=readconfigfile(output,configfile);
+ if (retval==1) // config file did not exists. creating one
+ {
+ tFptr f=fopen(configfile,"w");
+ if (!f)
+ {
+ welcomescreen(argv[0]);
+ fprintf(stderr,"config file %s did not exists, and i couldn't create it\n",configfile);
+ exit(1);
+ }
+ fprintf(f,"#DHEXCOLORSCHEME\n");
+ fprintf(f,"#VERSION 0\n");
+ fprintf(f,"#possible colors are: BLACK,RED,GREEN,YELLOW,BLUE,MAGENTA,CYAN,WHITE\n");
+ fprintf(f,"#possible extra flags are: UNDERLINE,REVERSE,BLINK,DIM,BOLD\n");
+ fprintf(f,"\n");
+ fprintf(f,"BRACKETS: FG=BLACK,BG=BLACK,BOLD\n");
+ fprintf(f,"HEXFIELD: FG=WHITE,BG=BLACK\n");
+ fprintf(f,"INPUT: FG=BLACK,BG=WHITE\n");
+ fprintf(f,"CURSOR: FG=WHITE,BG=BLACK\n");
+ fprintf(f,"TEXT: FG=LIGHTCYAN,BG=BLACK,BOLD\n");
+ fprintf(f,"MENU_NORMAL: FG=LIGHTBLUE,BG=BLACK\n");
+ fprintf(f,"MENU_HIGHLIGHT: FG=LIGHTBLUE,BG=BLUE\n");
+ fprintf(f,"MENU_HOTKEY: FG=CYAN,BG=BLACK\n");
+ fprintf(f,"MENU_HOTKEY_HI: FG=CYAN,BG=BLUE\n");
+ fprintf(f,"FRAME: FG=BLUE,BG=BLACK\n");
+ fprintf(f,"NORMAL_DIFF: FG=YELLOW,BG=BLACK,BOLD\n");
+ fprintf(f,"CURSOR_DIFF: FG=YELLOW,BG=WHITE,BOLD\n");
+ fprintf(f,"HEADLINE: FG=BLUE,BG=BLACK\n");
+ fprintf(f," \n");
+ fclose(f);
+ retval=2;
+ }
+ if (retval==2) keyboardsetupreq=1;
+
+ hHexCalc=malloc(sizeof(thHexCalc));
+ memset(hHexCalc,0,sizeof(thHexCalc));
+ buf1=malloc(sizeof(tBuffer));
+ memset(buf1,0,sizeof(tBuffer));
+ if (diffmode)
+ {
+ buf2=malloc(sizeof(tBuffer));
+ memset(buf2,0,sizeof(tBuffer));
+ }
+
+ if (openbuf(buf1,1,argv[filename1])!=RETOK)
+ {
+ fprintf(stderr,"error opening inputfile %s\n",argv[filename1]);
+ exit(1);
+ }
+ if (diffmode) if (openbuf(buf2,2,argv[filename2])!=RETOK)
+ {
+ fprintf(stderr,"error opening second inputfile %s\n",argv[filename2]);
+ exit(1);
+ }
+ if (gosearch1) searchfor(&search1,buf1,&cursorpos1,1);
+ if (gosearch2 && diffmode) searchfor(&search2,buf2,&cursorpos2,1);
+ if (gocorr && diffmode)
+ {
+ fprintf(stderr,"correlating...\n");
+ find_correlation(NULL,&correlation,buf1,buf2,&cursorpos1,&cursorpos2);
+ }
+ if (!(gosearch1 && search1.writesearchlog) || (diffmode && !(gosearch2 && search2.writesearchlog)))
+ {
+ output->win=initscr();
+ pairsinit(output);
+ noecho();
+ nodelay(output->win,1);
+ if (keyboardsetupreq) keyboardsetup(output,configfile);
+ readbuf(buf1,0);
+ firstpos1=cursorpos1;
+ firstpos2=cursorpos2;
+ ch=0;
+ while (ch!=KEYF10)
+ {
+ printmainmenu(output,diffmode);
+ if (diffmode)
+ printbufferdiff(output,buf1,buf2,cursorpos1,cursorpos2);
+ else
+ printbuffersingle(output,buf1,cursorpos1,firstpos1,windowfield);
+ ch=getkey((tKeyTab*)output->pKeyTab,1);
+
+#define MOVEMENTDEFINE(KEY,VIKEY,mvchar,mvline,mvpage) \
+ if (ch==KEY || (VIKEY && ch==VIKEY && windowfield==0)) \
+ { \
+ tInt32 err; \
+ oldfirstpos1=firstpos1; \
+ oldcursorpos1=cursorpos1; \
+ oldfirstpos2=firstpos2; \
+ oldcursorpos2=cursorpos2; \
+ \
+ err=movepositions(&cursorpos1,&firstpos1,buf1->bufsize,mvchar,mvline,mvpage,diffmode); \
+ \
+ if (diffmode) \
+ { \
+ movepositions(&cursorpos2,&firstpos2,buf2->bufsize,mvchar,mvline,mvpage,diffmode); \
+ err=((cursorpos1<0 && cursorpos2<0) || (cursorpos1>buf1->bufsize && cursorpos2>buf2->bufsize)); \
+ } \
+ if (err) \
+ { \
+ firstpos1=oldfirstpos1; \
+ cursorpos1=oldcursorpos1; \
+ firstpos2=oldfirstpos2; \
+ cursorpos2=oldcursorpos2; \
+ } \
+ }
+ MOVEMENTDEFINE(KEYRIGHT,'l' , 1, 0, 0);
+ MOVEMENTDEFINE(KEYLEFT,'h' ,-1, 0, 0);
+ MOVEMENTDEFINE(KEYDOWN,'j' , 0, 1, 0);
+ MOVEMENTDEFINE(KEYUP,'k' , 0,-1, 0);
+ MOVEMENTDEFINE(KEYPGDOWN,' ' , 0, 0, 1);
+ MOVEMENTDEFINE(KEYPGUP,0 , 0, 0,-1);
+
+#undef MOVEMENTDEFINE
+ if (ch==KEYHOME || (ch=='^' && windowfield==0))
+ {
+ if (diffmode)
+ {
+ tInt64 dmin,dmax;
+
+ dmin=MIN(cursorpos1,cursorpos2);
+ dmax=MAX(cursorpos1,cursorpos2);
+ if (dmin==0)
+ {
+ cursorpos1-=dmax;
+ cursorpos2-=dmax;
+ } else {
+ cursorpos1-=dmin;
+ cursorpos2-=dmin;
+ }
+ firstpos1=cursorpos1;
+ firstpos2=cursorpos2;
+
+ } else {
+ firstpos1=cursorpos1=0;
+ }
+ }
+ if (ch==KEYEND || (ch=='$' && windowfield==0))
+ {
+ if (diffmode)
+ {
+ tInt64 dmin,dmax;
+ dmin=MIN(buf1->bufsize-cursorpos1,buf2->bufsize-cursorpos2);
+ dmax=MAX(buf1->bufsize-cursorpos1,buf2->bufsize-cursorpos2);
+
+ if (dmin==0)
+ {
+
+ cursorpos2+=dmax;
+ cursorpos1+=dmax;
+ } else {
+ cursorpos1+=dmin;
+ cursorpos2+=dmin;
+ }
+ } else {
+ firstpos1=cursorpos1=buf1->bufsize;
+ }
+ }
+ if (ch==KEYTAB) {windowfield=(windowfield+1)&1;}
+ if ((ch==KEYF1 || (ch==':' && windowfield==0))&& !diffmode) {
+ if (gotomask(output,markers,&cursorpos1)==RETOK)
+ {
+ firstpos1=cursorpos1;
+ }
+ }
+ if ((ch==KEYF2 || ((ch=='/' || ch=='?') && (windowfield==0))) && !diffmode)
+ {
+ if (ch=='/') search1.forwardnotbackward=1; // / means forward
+ if (ch=='?') search1.forwardnotbackward=0; // ? means backward
+ searchmask(output,&search1,buf1,&cursorpos1);
+ firstpos1=cursorpos1;
+ }
+ if (ch==KEYF3 || ch==KEYF4 || (windowfield==0 && (ch=='n' || ch=='N')))
+ {
+ if (ch=='n') ch=KEYF3; // n=next
+ if (ch=='N') ch=KEYF4; // N=previous
+ if (diffmode)
+ {
+ tInt64 actcursorpos1=cursorpos1;
+ tInt64 actcursorpos2=cursorpos2;
+ tInt32 idx1,idx2;
+ tBool found;
+ tBool diffnotdiff;
+ tUInt64 minbufsize=(buf1->bufsize<buf2->bufsize)?buf1->bufsize:buf2->bufsize; // get the minimum of the filesizes
+ tUInt64 searchcnt=minbufsize;
+
+ oldcursorpos1=cursorpos1;
+ oldcursorpos2=cursorpos2;
+ actcursorpos1=actcursorpos1+((ch==KEYF3)?1:-1); // F3: next, F4:prev
+ actcursorpos2=actcursorpos2+((ch==KEYF3)?1:-1); // F3: next, F4:prev
+ found=(!minbufsize);
+ idx1=getbufferidx(buf1,actcursorpos1);
+ idx2=getbufferidx(buf2,actcursorpos2);
+ diffnotdiff=(buf1->data[idx1]!=buf2->data[idx2]); // if the cursor is on something which is a diff, look for the next time the values are the same
+ while (actcursorpos1!=oldcursorpos1 && actcursorpos2!=oldcursorpos2 && searchcnt && !found)
+ {
+ idx1=getbufferidx(buf1,actcursorpos1);
+ idx2=getbufferidx(buf2,actcursorpos2);
+ if ((buf1->data[idx1]!=buf2->data[idx2]) != diffnotdiff) found=1;
+ else {
+ actcursorpos1=actcursorpos1+((ch==KEYF3)?1:-1); // F3: next, F4:prev
+ actcursorpos2=actcursorpos2+((ch==KEYF3)?1:-1); // F3: next, F4:prev
+ }
+ if (actcursorpos1<0 || actcursorpos2<0)
+ {
+ actcursorpos1+=minbufsize; // start at the end of the smallest file
+ actcursorpos2+=minbufsize; // start at the end of the smallest file
+ }
+ if (actcursorpos1>=minbufsize && actcursorpos2>=minbufsize)
+ {
+ actcursorpos1-=minbufsize; // if you are at the end of the smallest file, start at the beginning
+ actcursorpos2-=minbufsize; // if you are at the end of the smallest file, start at the beginning
+ }
+ searchcnt--;
+ }
+ if (found)
+ {
+ cursorpos1=actcursorpos1;
+ cursorpos2=actcursorpos2;
+ }
+ }
+ else if (search1.occurancesfound)
+ {
+ searchfor(&search1,buf1,&cursorpos1,(ch==KEYF3)); // f3: next
+ firstpos1=cursorpos1;
+ }
+ }
+ if (ch==KEYF5) hexcalc(output,hHexCalc);
+ if (ch==KEYF6 && diffmode)
+ {
+ correlation.start_mindiff=MIN(buf1->bufsize,buf2->bufsize);
+ if (correlationmask(output,&correlation)==RETOK)
+ {
+ find_correlation(output,&correlation,buf1,buf2,&cursorpos1,&cursorpos2);
+ }
+ }
+ if ((ch==KEYF9 || (ch=='u' && windowfield==0)) && !diffmode)
+ {
+ if (buf1->changesnum)
+ {
+ if ((buf1->changes[buf1->changesnum].pos==(buf1->bufsize-1) && (buf1->filesize<=buf1->changes[buf1->changesnum].pos))) buf1->bufsize--; // if this was the last byte in the buffer, decrease its size
+ cursorpos1=buf1->changes[--buf1->changesnum].pos;
+ if (cursorpos1<firstpos1) firstpos1=cursorpos1;
+ if ((firstpos1+100)>cursorpos1) firstpos1=cursorpos1; // TODO: 100 depends on the size of the window
+ }
+
+ }
+ if (buf1->changesnum<CHANGEBUFSIZE-1 && !diffmode)
+ {
+ if (((ch>='0' && ch<='9') || (ch>='a' && ch<='f') || (ch>='A' && ch<='F')) && windowfield==0)
+ {
+ buf1->nexthex<<=4;
+ if (ch>='a') ch-=32;
+ buf1->nexthex|=((ch>='A')?(ch-'A'+10):(ch-'0'));
+ if (buf1->nibble)
+ {
+ if (cursorpos1==buf1->bufsize) buf1->bufsize++; // append the byte at the end
+ buf1->changes[buf1->changesnum].pos=cursorpos1;
+ buf1->changes[buf1->changesnum].after=buf1->nexthex;
+ buf1->changesnum++;
+ movepositions(&cursorpos1,&firstpos1,buf1->bufsize,1,0,0,diffmode);
+ }
+ buf1->nibble=!buf1->nibble;
+ buf1->changepos=cursorpos1;
+ } else buf1->nibble=0;
+ if (ch>=32 && ch<127 && windowfield==1)
+ {
+ if (cursorpos1==buf1->bufsize) buf1->bufsize++; // append the byte at the end
+ buf1->changes[buf1->changesnum].pos=cursorpos1;
+ buf1->changes[buf1->changesnum].after=ch;
+ buf1->changesnum++;
+ movepositions(&cursorpos1,&firstpos1,buf1->bufsize,1,0,0,diffmode);
+ }
+ }
+ if (ch==KEYF10)
+ {
+ if (buf1->changesnum) if (savedialog(output,buf1)!=RETOK)
+ {
+ ch=0;
+ }
+ }
+ }
+ if (output)
+ {
+ if (output->pKeyTab) free(output->pKeyTab);
+ free(output);
+ }
+ if (buf1) free(buf1);
+ if (buf2) free(buf2);
+ if (hHexCalc) free(hHexCalc);
+ if (markers) free(markers);
+ if (output->win) endwin();
+ welcomescreen(argv[0]);
+ } else {
+ if (gosearch1) fprintf(stderr,"%lli occurances found in %s\n",search1.occurancesfound,buf1->filename);
+ if (gosearch2) fprintf(stderr,"%lli occurances found in %s\n",search2.occurancesfound,buf2->filename);
+ }
+ return 0;
+}
+