KlugyTools/Hexdiff/hexdiff.c
2022-11-24 14:37:21 +01:00

395 lines
7.1 KiB
C

/*
Visuel Hexdiff
--------------
More infos --> http://tboudet.free.fr/hexdiff/
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#define MAIN
#include "hexdiff.h"
/*----------------------------------------------------------------*/
static void finish(int signal)
{
endwin(); exit(0);
}
/*----------------------------------------------------------------*/
int
affiche_les_dumps(void)
{
int foo, bar, idx, flag;
char buff[50];
char *format_offset;
memset(f1.buffer, 0, T_BUFF);
memset(f2.buffer, 0, T_BUFF);
/*
* lire les deux fichiers...
*/
lseek(f1.fd, f1.offset, SEEK_SET);
f1.lus = read(f1.fd, f1.buffer, T_BUFF);
lseek(f2.fd, f2.offset, SEEK_SET);
f2.lus = read(f2.fd, f2.buffer, T_BUFF);
ecrire_barres_fichiers();
/*
* afficher les offsets
*/
format_offset = config.offsets_in_hex ? "%08lx" : "%8ld";
for (foo=0; foo<HAUT; foo++)
{
move(HAUT_1+foo, 0); clrtoeol();
move(HAUT_2+foo, 0); clrtoeol();
sprintf(buff, format_offset, foo*16+f1.offset);
mvaddstr(HAUT_1+foo, 0, buff);
sprintf(buff, format_offset, foo*16+f2.offset);
mvaddstr(HAUT_2+foo, 0, buff);
}
/*
* afficher les octets
*/
for (foo=0; foo<HAUT; foo++)
{
for (bar=0; bar<16; bar++)
{
idx = foo*16 + bar;
/*
* il faut prendre en compte le cas ou la taille
* des fichiers n'est pas la meme, pour ne pas mettre
* en evidence les octets qui debordent.
*/
flag = f1.buffer[idx]!=f2.buffer[idx];
/*
* fenetre du haut
*/
if (flag && !fenetre_active) standout();
if (idx < f1.lus)
{
sprintf(buff, "%02x", f1.buffer[idx]);
mvaddstr(HAUT_1+foo, bar*3+11, buff);
if (is_printable(f1.buffer[idx]))
mvaddch(HAUT_1+foo, bar+62, f1.buffer[idx]);
else
mvaddch(HAUT_1+foo, bar+62, ' ');
}
if (flag && !fenetre_active) standend();
/*
* fenetre du bas
*/
if (flag && fenetre_active) standout();
if (idx < f2.lus)
{
sprintf(buff, "%02x", f2.buffer[idx]);
mvaddstr(HAUT_2+foo, bar*3+11, buff);
if (is_printable(f2.buffer[idx]))
mvaddch(HAUT_2+foo, bar+62, f2.buffer[idx]);
else
mvaddch(HAUT_2+foo, bar+62, ' ');
}
if (flag && fenetre_active) standend();
}
}
refresh();
return 0;
}
/*----------------------------------------------------------------*/
/*
* la boucle principale. tant qu'on a pas presse une touche
* kifaiquitter, on reste dedans.
*/
int
interactive(void)
{
int clef; /* la touche en question */
int flag_exit = 0; /* devient 1 si on doit quitter la boucle */
int pas_a_la_fin;
int foo;
long lfoo;
char chaine[T_NOM+1];
#if TRACE
char buff[100];
#endif
do
{
affiche_les_dumps();
pas_a_la_fin = (f1.offset<f1.taille) && (f2.offset<f2.taille);
clef = getch();
#if TRACE
sprintf(buff, "%c %04x %d ", clef, clef, pas_a_la_fin);
mvaddstr(0, 0, buff); refresh();
#endif
switch (clef)
{
case 'x': case 'q':
flag_exit = 1;
break;
case 'u': case 'j':
case KEY_UP:
if (f1.offset>15) f1.offset -= 16;
if (f2.offset>15) f2.offset -= 16;
break;
case 'U':
f1.offset -= 64;
if (f1.offset<0) f1.offset=0;
f2.offset -= 64;
if (f2.offset<0) f2.offset=0;
break;
case 'd': case 'k':
case KEY_DOWN:
if (pas_a_la_fin)
{
f1.offset += 16;
f2.offset += 16;
}
break;
case 'D':
if (pas_a_la_fin)
{
f1.offset += 64;
f2.offset += 64;
}
break;
case 'H':
config.offsets_in_hex ^= 1;
break;
case ' ':
case KEY_NPAGE:
if (pas_a_la_fin)
{
f1.offset += (HAUT-1)*16;
f2.offset += (HAUT-1)*16;
}
break;
case KEY_PPAGE:
lfoo = f1.offset - (HAUT-1)*16;
if (lfoo<0) lfoo = 0;
f1.offset = f2.offset = lfoo;
break;
case '0':
case KEY_HOME:
f1.offset = f2.offset = 0;
break;
case '7':
config.show_8bits = 0;
break;
case '8':
config.show_8bits = 1;
break;
case '$':
/* jump to the end of the smallest file */
lfoo = (f1.taille<f2.taille) ? f1.taille : f2.taille;
f1.offset = f2.offset = (lfoo-16) & 0xffffff0;
break;
case '=':
lfoo = (f1.offset<f2.offset) ? f1.offset : f2.offset;
f1.offset = f2.offset = lfoo & 0xffffff0;
break;
case 'g':
lfoo = saisir_un_long("nouvel offset");
if (lfoo != -1)
f1.offset = f2.offset = lfoo & 0xffffff0;
break;
case 'i':
if (fenetre_active == 0)
fileinfo(f1.fd, HAUT_1);
else
fileinfo(f2.fd, HAUT_2);
break;
case 'I':
double_fileinfo(f1.fd, HAUT_1, f2.fd, HAUT_2);
break;
case 'A':
/**** asciiview ****/
asciiview();
break;
/*
* a patch from Mark Glines:
* key 'n' search for the next difference
*/
case 'n': /* next */
for(lfoo = f1.offset + 16;
lfoo < f1.taille && (lfoo+f2.offset-f1.offset) < f2.taille;
lfoo += 16) {
char buf1[16], buf2[16];
int diff = f2.offset - f1.offset;
lseek(f1.fd, lfoo, SEEK_SET);
lseek(f2.fd, lfoo+diff, SEEK_SET);
if(read(f1.fd,buf1,16) == 16)
if(read(f2.fd,buf2,16) == 16)
if(memcmp(buf1,buf2,16)) {
f1.offset = lfoo;
f2.offset = lfoo + diff;
break;
}
}
break;
case '?':
popup_aide();
break;
case 'a':
about();
break;
case 0x0f: /* CTRL O */
foo = select_new_file(chaine, T_NOM, 0);
if (foo)
ouvre_fichier(chaine);
break;
case '\t': /* TAB */
fenetre_active ^= 1;
break;
case '\f': /* CTRL L */
wrefresh(curscr);
break;
case 'V': /* plugin viewers ? */
break;
default: /* this key was not used */
flash();
break;
}
} while ( ! flag_exit );
return 0;
}
/*----------------------------------------------------------------*/
/*
* HERE WE GO, FAST AND FURIOUS !
*/
int main(int argc, char *argv[])
{
int foo;
struct stat statbuf;
#if TRACE
fprintf(stderr, "\n------ trace de %s ------\n", argv[0]);
fflush(stderr);
#endif
if (argc == 1) aide_cl(0);
if (argc == 2)
{
if (!strcmp(argv[1], "-?") || !strcmp(argv[1], "-h"))
aide_cl(1);
if (!strcmp(argv[1], "-V")) version();
if (!strcmp(argv[1], "-X"))
{
foo = lire_configuration(1);
exit(0);
}
}
if (argc != 3) aide_cl(0);
/*
* initialisation des variables globales
*/
fenetre_active = 0;
/*
* on va essayer d'ouvrir les fichiers.
*/
if ( (f1.fd=open(argv[1], O_RDONLY)) < 0)
{
perror(argv[1]); exit(2);
}
else
{
strncpy(f1.nom, argv[1], T_NOM);
foo = fstat(f1.fd, &statbuf);
f1.taille = statbuf.st_size;
f1.offset = 0;
f1.lus = 0;
}
if ( (f2.fd=open(argv[2], O_RDONLY)) < 0)
{
perror(argv[2]); exit(2);
}
else
{
strncpy(f2.nom, argv[2], T_NOM);
foo = fstat(f2.fd, &statbuf);
f2.taille = statbuf.st_size;
f2.offset = 0;
f2.lus = 0;
}
/*
* si on arrive ici, c'est que les deux fichiers sont ouverts,
* donc on peut tenter de lire le fichier de configuration...
*/
foo = lire_configuration(0);
/*
* ... et ensuite, on peut passer en mode 'Vizzual'.
*/
initscr();
nonl(); cbreak(); noecho();
keypad(stdscr, TRUE); /* acces aux touches 'curseur' */
foo = fond_ecran();
interactive(); /* GOTO LOOP */
/*
* plop, on a fini, restaurer la console
*/
finish(0);
return 0;
}
/*----------------------------------------------------------------*/