very old code commited, ymmv
This commit is contained in:
3
Hexdiff/.gitignore
vendored
Normal file
3
Hexdiff/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
hexdiff
|
||||
|
||||
71
Hexdiff/Makefile
Normal file
71
Hexdiff/Makefile
Normal file
@@ -0,0 +1,71 @@
|
||||
#
|
||||
# VISUEL HEXDIFF
|
||||
# --------------
|
||||
#
|
||||
# old site : http://tboudet.free.fr/hexdiff/
|
||||
#
|
||||
|
||||
OU_LE_METTRE = /usr/local
|
||||
VERSION=0.0.50
|
||||
|
||||
TARNAME="hexdiff-$(VERSION).tar.gz"
|
||||
|
||||
all: hexdiff
|
||||
|
||||
#
|
||||
# if you define TRACE to a non zero value, you get a
|
||||
# lot of debugging trace on _stderr_
|
||||
#
|
||||
|
||||
COMP=gcc
|
||||
COPT=-g -DVERSION=\"$(VERSION)\" -DTRACE=0 -ansi
|
||||
LOPT=-lncurses
|
||||
|
||||
hexdiff.o: hexdiff.c Makefile hexdiff.h
|
||||
$(COMP) $(COPT) -Wall -O2 -c hexdiff.c
|
||||
|
||||
fonctions.o: fonctions.c Makefile hexdiff.h
|
||||
$(COMP) $(COPT) -Wall -O2 -c fonctions.c
|
||||
|
||||
parse_rc.o: parse_rc.c Makefile hexdiff.h
|
||||
$(COMP) $(COPT) -Wall -O2 -c parse_rc.c
|
||||
|
||||
fileinfo.o: fileinfo.c Makefile hexdiff.h
|
||||
$(COMP) $(COPT) -Wall -O2 -c fileinfo.c
|
||||
|
||||
sel_file.o: sel_file.c Makefile hexdiff.h
|
||||
$(COMP) $(COPT) -Wall -O2 -c sel_file.c
|
||||
|
||||
asciiview.o: asciiview.c Makefile hexdiff.h
|
||||
$(COMP) $(COPT) -Wall -O2 -c asciiview.c
|
||||
|
||||
OBJECTS=hexdiff.o fonctions.o fileinfo.o parse_rc.o sel_file.o \
|
||||
asciiview.o
|
||||
|
||||
hexdiff: Makefile $(OBJECTS)
|
||||
$(COMP) $(OBJECTS) -o $@ $(LOPT)
|
||||
|
||||
#
|
||||
# this install procedure is very crude.
|
||||
#
|
||||
install:
|
||||
cp hexdiff hexdiff.install
|
||||
strip hexdiff.install
|
||||
cp hexdiff.install $(OU_LE_METTRE)/bin/hexdiff
|
||||
rm hexdiff.install
|
||||
cp hexdiff.1 $(OU_LE_METTRE)/man/man1/hexdiff.1
|
||||
@echo "you can copy hexdiff.rc in your HOME as .hexdiffrc"
|
||||
|
||||
FILES=hexdiff.c hexdiff.1 Makefile README TODO BUGS fonctions.c CHANGES \
|
||||
hexdiff.h parse_rc.c hexdiff.rc fileinfo.c sel_file.c \
|
||||
asciiview.c memcheck.sh
|
||||
|
||||
tarball: $(FILES)
|
||||
@echo $(TARNAME)
|
||||
ls $^ > MANIFEST ; \
|
||||
( cd .. ; \
|
||||
tar zcvf $(TARNAME) `sed 's/^/HexDiff\//' HexDiff/MANIFEST` )
|
||||
date >> tarball
|
||||
|
||||
lines: $(FILES)
|
||||
wc $(FILES) | sort -n
|
||||
19
Hexdiff/README.md
Normal file
19
Hexdiff/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Hexdiff
|
||||
|
||||
Un truc en ncurses pour voir les différences entre deux fichiers binaires.
|
||||
|
||||
```
|
||||
look at:
|
||||
- the Makefile
|
||||
- the man page
|
||||
- the source code
|
||||
|
||||
old website:
|
||||
http://tboudet.free.fr/hexdiff/
|
||||
|
||||
installation:
|
||||
1) run make
|
||||
2) patch
|
||||
3) goto 1
|
||||
|
||||
```
|
||||
14
Hexdiff/TODO
Normal file
14
Hexdiff/TODO
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
add a '/' keystroke for searching a byte sequence in
|
||||
the current file.
|
||||
|
||||
drink a beer ? or, better, eat a Guinness ?
|
||||
|
||||
write a better english. write a better doc. write a
|
||||
better manpage. write a better code.
|
||||
|
||||
make a Slackware package. Mmmeee.
|
||||
|
||||
move the config file from $HOME/.hexdiffrc to
|
||||
$HOME/.tth/hexdiff.rc
|
||||
|
||||
202
Hexdiff/asciiview.c
Normal file
202
Hexdiff/asciiview.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
+----------------+
|
||||
| Ascii View |
|
||||
+----------------+
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hexdiff.h"
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
static void av_sauve_contexte(void)
|
||||
{ /* code to be defined ? */ }
|
||||
/*----------------------------------------------------------------*/
|
||||
static void av_restaure_contexte(void)
|
||||
{ /* code to be defined ? */ }
|
||||
/*----------------------------------------------------------------*/
|
||||
static char * ascii_name(int code)
|
||||
{
|
||||
static char static_buffer[20];
|
||||
|
||||
/* XXX this big switch must be audited.... */
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 0: return "NUL";
|
||||
case 1: return "SOH ^a";
|
||||
case 2: return "STX ^b";
|
||||
case 3: return "ETX ^c";
|
||||
case 4: return "EOT ^d";
|
||||
case 5: return "ENQ ^e";
|
||||
case 6: return "ACQ ^f";
|
||||
case 7: return "BEL ^g";
|
||||
case 8: return "BS ^h";
|
||||
case 9: return "HT ^i";
|
||||
case 10: return "LF ^j";
|
||||
case 11: return "VT ^k";
|
||||
case 12: return "FF ^l";
|
||||
case 13: return "CR ^m";
|
||||
case 14: return "SO ^n";
|
||||
case 15: return "SI ^o";
|
||||
case 16: return "DLE ^p";
|
||||
case 17: return "DC1 ^q";
|
||||
case 18: return "DC2 ^r";
|
||||
case 19: return "DC3 ^s";
|
||||
case 20: return "DC4 ^t";
|
||||
case 21: return "NAK ^u";
|
||||
case 22: return "SYN ^v";
|
||||
case 23: return "ETB ^w";
|
||||
case 24: return "CAN ^x";
|
||||
case 25: return "EM ^y";
|
||||
case 26: return "SUB ^z";
|
||||
case 27: return "ESC";
|
||||
case 28: return "FS ";
|
||||
case 29: return "GS ";
|
||||
case 30: return "RS ";
|
||||
case 31: return "US ";
|
||||
case 32: return "SPACE";
|
||||
case 127: return "DEL";
|
||||
}
|
||||
|
||||
if (code < 128)
|
||||
{
|
||||
sprintf(static_buffer, "'%c'", code);
|
||||
return static_buffer;
|
||||
}
|
||||
|
||||
/* may be for code > 127, we can put the "html" code &blabla; ? */
|
||||
|
||||
return "";
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
#define ASCV_I2LIG(idx) ((idx)>>6)
|
||||
#define ASCV_I2COL(idx) ((idx)&63)
|
||||
|
||||
static int av_affiche(Fichier *fic, WINDOW *pop, int clig, int ccol)
|
||||
{
|
||||
int foo, lig, col, car;
|
||||
char chaine[100];
|
||||
long depl;
|
||||
unsigned char octet;
|
||||
|
||||
wstandout(pop);
|
||||
for (foo=1; foo<65; foo++)
|
||||
mvwaddch(pop, 1, foo, ' ');
|
||||
mvwaddstr(pop, 1, 2, fic->nom);
|
||||
|
||||
depl = (clig*64)+ccol;
|
||||
octet = fic->buffer[depl];
|
||||
sprintf(chaine, "%7ld : %3d 0x%02x 0%03o",
|
||||
fic->offset+depl, octet, octet, octet);
|
||||
mvwaddstr(pop, 18, 1, chaine);
|
||||
mvwaddstr(pop, 18, 33, " ");
|
||||
mvwaddstr(pop, 18, 33, ascii_name(fic->buffer[depl]));
|
||||
wstandend(pop);
|
||||
|
||||
for (foo=0; foo<16*64; foo++)
|
||||
{
|
||||
lig = ASCV_I2LIG(foo);
|
||||
col = ASCV_I2COL(foo);
|
||||
car = fic->buffer[foo];
|
||||
car = is_printable(car) ? car : ' ';
|
||||
if (clig==lig && ccol==col)
|
||||
wstandout(pop);
|
||||
mvwaddch(pop, lig+2, col+1, car);
|
||||
if (clig==lig && ccol==col)
|
||||
wstandend(pop);
|
||||
}
|
||||
|
||||
/* put the cursor at the current location */
|
||||
/* this was a really bad idea for Xterm users, because
|
||||
* current pos char was written in "standout", and the
|
||||
* text cursor of xterm re-reverse it.
|
||||
* XXX wmove(pop, clig+2, ccol+1);
|
||||
*/
|
||||
wmove(pop,1,64);
|
||||
|
||||
wrefresh(pop);
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
/* new: 2004 Nov.
|
||||
* still in developement.
|
||||
*/
|
||||
int asciiview(void)
|
||||
{
|
||||
WINDOW * popup;
|
||||
int foo, key, flag_exit;
|
||||
int clig, ccol; /* position du curseur */
|
||||
Fichier * fic;
|
||||
|
||||
av_sauve_contexte();
|
||||
|
||||
popup = newwin(21, 66, 3, 5);
|
||||
bordure(popup);
|
||||
|
||||
wstandout(popup);
|
||||
for (foo=1; foo<65; foo++)
|
||||
mvwaddch(popup, 19, foo, ' ');
|
||||
mvwaddstr(popup, 19, 1, " 'Q' quit, <tab> see other file");
|
||||
for (foo=1; foo<65; foo++)
|
||||
mvwaddch(popup, 18, foo, ' ');
|
||||
wstandend(popup);
|
||||
wrefresh(popup);
|
||||
|
||||
flag_exit = 0;
|
||||
clig = ccol = 0;
|
||||
do
|
||||
{
|
||||
if (fenetre_active==0) fic = &f1;
|
||||
else fic = &f2;
|
||||
|
||||
av_affiche(fic, popup, clig, ccol);
|
||||
key = getch();
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case 'q': case 'Q':
|
||||
flag_exit = 1;
|
||||
break;
|
||||
case '\t':
|
||||
fenetre_active ^= 1;
|
||||
break;
|
||||
case KEY_UP:
|
||||
if (clig>0) clig--; break;
|
||||
case KEY_DOWN:
|
||||
if (clig<15) clig++; break;
|
||||
case KEY_LEFT:
|
||||
if (ccol>0) ccol--;
|
||||
else if (clig>0)
|
||||
{
|
||||
/* go to the previous line */
|
||||
ccol=63; clig--;
|
||||
}
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
if (ccol<63) ccol++;
|
||||
else if (clig<15)
|
||||
{
|
||||
/* go to the next line */
|
||||
ccol=0; clig++;
|
||||
}
|
||||
break;
|
||||
case KEY_HOME:
|
||||
ccol = clig = 0; break;
|
||||
case KEY_END:
|
||||
ccol = 63; clig = 15; break;
|
||||
default:
|
||||
flash();
|
||||
break;
|
||||
}
|
||||
|
||||
} while ( ! flag_exit );
|
||||
|
||||
delwin(popup);
|
||||
|
||||
av_restaure_contexte();
|
||||
return 42;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
138
Hexdiff/fileinfo.c
Normal file
138
Hexdiff/fileinfo.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
fileinfo.c
|
||||
----------
|
||||
|
||||
More infos --> http://tboudet.free.fr/hexdiff/
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "hexdiff.h"
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
/* private vars of this module */
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
/*
|
||||
* this func need more "configurability"
|
||||
*/
|
||||
static void prtime(time_t t, char *pstr)
|
||||
{
|
||||
struct tm *ptm;
|
||||
int foo;
|
||||
ptm = gmtime(&t);
|
||||
foo = strftime(pstr, 99, "%Y-%m-%d %H:%M:%S", ptm);
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
#define W_FILEINFO 48
|
||||
WINDOW * do_fileinfo(int fd, int ligne)
|
||||
{
|
||||
WINDOW * popup;
|
||||
int foo, lig, hpopup;
|
||||
struct stat stat_buf;
|
||||
char buffer[100];
|
||||
struct passwd *pass;
|
||||
struct group *grp;
|
||||
|
||||
if (config.ext_fileinfo) hpopup = 13;
|
||||
else hpopup = 12;
|
||||
|
||||
popup = newwin(hpopup, W_FILEINFO, ligne, 15);
|
||||
if ( popup==NULL ) return NULL;
|
||||
bordure(popup);
|
||||
|
||||
#if TRACE
|
||||
sprintf(buffer, " fileinfos fd %d ", fd);
|
||||
mvwaddstr(popup, 0, 10, buffer);
|
||||
#endif
|
||||
|
||||
foo = fstat(fd, &stat_buf);
|
||||
if (foo==0)
|
||||
{
|
||||
lig = 2;
|
||||
sprintf(buffer, "dev: %ld", (long)(stat_buf.st_dev));
|
||||
mvwaddstr(popup, lig, 2, buffer);
|
||||
sprintf(buffer, "inode: %ld", stat_buf.st_ino);
|
||||
mvwaddstr(popup, lig, 22, buffer);
|
||||
lig += 2;
|
||||
|
||||
sprintf(buffer, "uid: %d", stat_buf.st_uid);
|
||||
mvwaddstr(popup, lig, 2, buffer);
|
||||
sprintf(buffer, "gid: %d", stat_buf.st_gid);
|
||||
mvwaddstr(popup, lig, 22, buffer);
|
||||
if (config.ext_fileinfo)
|
||||
{
|
||||
lig++;
|
||||
|
||||
pass = getpwuid(stat_buf.st_uid);
|
||||
if (pass==NULL) strcpy(buffer, "unknow user");
|
||||
else sprintf(buffer, "user: %s", pass->pw_name);
|
||||
mvwaddstr(popup, lig, 2, buffer);
|
||||
|
||||
grp = getgrgid(stat_buf.st_gid);
|
||||
if (grp==NULL) strcpy(buffer, "unknow group");
|
||||
else sprintf(buffer, "group: %s", grp->gr_name);
|
||||
mvwaddstr(popup, lig, 22, buffer);
|
||||
}
|
||||
lig+=2;
|
||||
|
||||
/* Nov 2004: may be, here, we need a 'ls-like' display ,
|
||||
with "-rwxr-x---" look'n'feel ? */
|
||||
sprintf(buffer, "rwx: %05o", stat_buf.st_mode & 01777);
|
||||
mvwaddstr(popup, lig, 2, buffer);
|
||||
sprintf(buffer, "size: %ld", stat_buf.st_size);
|
||||
mvwaddstr(popup, lig, 22, buffer);
|
||||
lig+=2;
|
||||
|
||||
/* we don't display the atime, because, after all,
|
||||
hexdiff _is_ reading the file :) */
|
||||
prtime(stat_buf.st_mtime, buffer);
|
||||
mvwaddstr(popup, lig, 4, "mtime:");
|
||||
mvwaddstr(popup, lig, 14, buffer);
|
||||
lig++;
|
||||
|
||||
prtime(stat_buf.st_ctime, buffer);
|
||||
mvwaddstr(popup, lig, 4, "ctime:");
|
||||
mvwaddstr(popup, lig, 14, buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buffer, "fstat error = %d", foo);
|
||||
mvwaddstr(popup, 6, 2, buffer);
|
||||
}
|
||||
|
||||
wrefresh(popup);
|
||||
return popup;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
int fileinfo(int fd, int ligne)
|
||||
{
|
||||
WINDOW * pop;
|
||||
|
||||
pop = do_fileinfo(fd, ligne);
|
||||
getch();
|
||||
delwin(pop);
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
int double_fileinfo(int fd1, int ligne1, int fd2, int ligne2)
|
||||
{
|
||||
WINDOW * pop1, * pop2;
|
||||
|
||||
pop1 = do_fileinfo(fd1, ligne1);
|
||||
pop2 = do_fileinfo(fd2, ligne2);
|
||||
getch();
|
||||
delwin(pop1);
|
||||
delwin(pop2);
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
331
Hexdiff/fonctions.c
Normal file
331
Hexdiff/fonctions.c
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
fonctions.c
|
||||
-----------
|
||||
|
||||
Old site --> http://tboudet.free.fr/hexdiff/
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "hexdiff.h"
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
int is_printable(int octet)
|
||||
{
|
||||
if (config.show_8bits)
|
||||
return isprint(octet & 0x7f);
|
||||
|
||||
return isprint(octet);
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
int ouvre_fichier(char *nom)
|
||||
{
|
||||
int fd, foo;
|
||||
struct stat statbuf;
|
||||
Fichier *fichier;
|
||||
long offset;
|
||||
|
||||
if ( (fd=open(nom, O_RDONLY)) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fenetre_active==0)
|
||||
{
|
||||
fichier = &f1; offset = f2.offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
fichier = &f2; offset = f1.offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* close the old file
|
||||
*/
|
||||
close(fichier->fd);
|
||||
|
||||
/*
|
||||
* store information on newly open file
|
||||
*/
|
||||
strncpy(fichier->nom, nom, T_NOM);
|
||||
foo = fstat(fd, &statbuf);
|
||||
fichier->fd = fd;
|
||||
fichier->taille = statbuf.st_size;
|
||||
fichier->offset = offset;
|
||||
fichier->lus = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
void barre_inverse(char c, int ligne)
|
||||
{
|
||||
int foo;
|
||||
standout();
|
||||
for (foo=0; foo<80; foo++)
|
||||
mvaddch(ligne, foo, c);
|
||||
standend();
|
||||
/* refresh(); */
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
/* new 28 juillet 2007 */
|
||||
static int calcul_pourcent(Fichier *f)
|
||||
{
|
||||
float foo;
|
||||
if (f->taille < 16) return 0;
|
||||
foo = ((float)f->offset * 100.0) / (float)f->taille;
|
||||
return (int)foo;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
int
|
||||
ecrire_barres_fichiers(void)
|
||||
{
|
||||
char buffer[150];
|
||||
int pourcent;
|
||||
|
||||
barre_inverse(' ', BARRE_1);
|
||||
barre_inverse(' ', BARRE_2);
|
||||
|
||||
standout();
|
||||
|
||||
mvaddstr(BARRE_1, 0, fenetre_active ? " " : "**");
|
||||
mvaddstr(BARRE_1, 3, f1.nom);
|
||||
pourcent = calcul_pourcent(&f1);
|
||||
sprintf(buffer, "%8ld %8ld %3d%%", f1.taille, f1.offset, pourcent);
|
||||
/*sprintf(buffer, "%8ld %8ld %8ld", f1.taille, f1.offset, f1.lus);*/
|
||||
mvaddstr(BARRE_1, 52, buffer);
|
||||
|
||||
mvaddstr(BARRE_2, 0, fenetre_active ? "**" : " ");
|
||||
mvaddstr(BARRE_2, 3, f2.nom);
|
||||
pourcent = calcul_pourcent(&f2);
|
||||
sprintf(buffer, "%8ld %8ld %3d%%", f2.taille, f2.offset, pourcent);
|
||||
mvaddstr(BARRE_2, 52, buffer);
|
||||
|
||||
if (config.show_8bits) mvaddstr(0, 72, " 8bits ");
|
||||
else mvaddstr(0, 72, " 7bits ");
|
||||
if (config.offsets_in_hex) mvaddstr(0, 66, " hex ");
|
||||
else mvaddstr(0, 66, " dec ");
|
||||
standend();
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
int
|
||||
fond_ecran(void)
|
||||
{
|
||||
#if TRACE
|
||||
int foo;
|
||||
char buffer[200];
|
||||
#endif
|
||||
|
||||
barre_inverse(' ', 0);
|
||||
standout();
|
||||
mvaddstr(0, 2, " Visuel HexDiff v " VERSION " by tTh 2007 ");
|
||||
#if TRACE
|
||||
sprintf(buffer, " screen size %dx%d ", COLS, LINES);
|
||||
foo = strlen(buffer);
|
||||
mvaddstr(0, COLS-2-foo, buffer);
|
||||
#endif
|
||||
standend();
|
||||
refresh();
|
||||
|
||||
#if TRACE
|
||||
fprintf(stderr, "HAUT %3d\n", HAUT);
|
||||
fprintf(stderr, "HAUT_1 %3d BARRE_1 %3d\n", HAUT_1, BARRE_1);
|
||||
fprintf(stderr, "HAUT_2 %3d BARRE_2 %3d\n", HAUT_2, BARRE_2);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
void bordure(WINDOW * w)
|
||||
{
|
||||
if (config.nice_border)
|
||||
box(w, 0, 0);
|
||||
else
|
||||
wborder(w, '|', '|', '-', '-', '+', '+', '+', '+');
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
int ligne;
|
||||
char * texte;
|
||||
} ligne_aide;
|
||||
|
||||
ligne_aide lignes[] =
|
||||
{
|
||||
{ 2, "x q : quit now, 'tfatf'" },
|
||||
{ 4, "u j (U) : go up one (4) lines" },
|
||||
{ 5, "d k (D) : go down one (4) lines" },
|
||||
{ 6, "<spc> : go down one full page" },
|
||||
{ 7, "0 : back to begin of files" },
|
||||
{ 8, "$ : goto end of shortest file" },
|
||||
{ 9, "<tab> : toggle the active window" },
|
||||
{ 10, "g : input a new file offset" },
|
||||
/* { 11, "= : synchronize the two offsets" }, */
|
||||
{ 12, "H : 'toogle' hex/dec offset display" },
|
||||
{ 13, "7 8 : display control of bit 7" },
|
||||
{ 14, "i (I) : info about file(s)" },
|
||||
{ 15, "n : jump to the next difference" },
|
||||
{ 16, "^O : open new file in current win" },
|
||||
{ 17, "A : Ascii View (new feature :)" }
|
||||
};
|
||||
|
||||
#define NB_LIG (sizeof(lignes)/sizeof(ligne_aide))
|
||||
|
||||
#define L_POPUP 2
|
||||
#define C_POPUP 11
|
||||
|
||||
void popup_aide(void)
|
||||
{
|
||||
WINDOW * popup;
|
||||
int foo, bar, ligmax, largmax;
|
||||
|
||||
ligmax = largmax = 0;
|
||||
for (foo=0; foo<NB_LIG; foo++)
|
||||
{
|
||||
if ((bar=lignes[foo].ligne) > ligmax) ligmax = bar;
|
||||
if ((bar=strlen(lignes[foo].texte)) > largmax) largmax = bar;
|
||||
}
|
||||
|
||||
ligmax += 3;
|
||||
largmax += 7;
|
||||
popup = newwin(ligmax, largmax, L_POPUP, C_POPUP);
|
||||
bordure(popup);
|
||||
|
||||
for (foo=0; foo<NB_LIG; foo++)
|
||||
{
|
||||
mvwaddstr(popup, lignes[foo].ligne, 3, lignes[foo].texte);
|
||||
}
|
||||
|
||||
wrefresh(popup);
|
||||
getch();
|
||||
delwin(popup);
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
static char *about_texte[] =
|
||||
{
|
||||
"Visuel Hexdiff - version " VERSION,
|
||||
"(c) 2007 by Thierry [tth] Boudet",
|
||||
"http://tboudet.free.fr/hexdiff/",
|
||||
"send bugs reports: tontonth@free.fr",
|
||||
"binary build: " __DATE__ "/" __TIME__,
|
||||
};
|
||||
|
||||
void about(void)
|
||||
{
|
||||
WINDOW * popup;
|
||||
int nblignes = sizeof(about_texte) / sizeof(char *);
|
||||
int foo;
|
||||
|
||||
#if TRACE
|
||||
fprintf(stderr, "boite about: %d lignes\n", nblignes);
|
||||
#endif
|
||||
|
||||
popup = newwin((nblignes*2)+3, 43, L_POPUP, C_POPUP);
|
||||
bordure(popup);
|
||||
|
||||
for (foo=0; foo<nblignes; foo++)
|
||||
{
|
||||
#if TRACE
|
||||
fprintf(stderr, "%d '%s'\n", foo, about_texte[foo]);
|
||||
#endif
|
||||
mvwaddstr(popup, (foo*2)+2, 4, about_texte[foo]);
|
||||
}
|
||||
wrefresh(popup);
|
||||
getch();
|
||||
delwin(popup);
|
||||
/* pourquoi, quand je fait le 'delwin', ncurses
|
||||
ne rafraichit pas la zone qui etait masquee ?
|
||||
*/
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
void aide_cl(int flag)
|
||||
{
|
||||
int foo;
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
fputs("\tusage:\n", stderr);
|
||||
fputs("\t\thexdiff -h\n", stderr);
|
||||
fputs("\t\thexdiff -V\n", stderr);
|
||||
fputs("\t\thexdiff -X\n", stderr);
|
||||
fputs("\t\thexdiff file.A file.B\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fputs("\n", stderr);
|
||||
fputs("\t+------------------------------------------------+\n", stderr);
|
||||
fputs("\t| commandes clavier |\n", stderr);
|
||||
fputs("\t+------------------------------------------------+\n", stderr);
|
||||
for (foo=0; foo<NB_LIG; foo++)
|
||||
{
|
||||
fprintf(stderr, "\t| %-46s |\n", lignes[foo].texte);
|
||||
}
|
||||
fputs("\t+------------------------------------------------+\n", stderr);
|
||||
fputs("\t| Pour le reste: 'man hexdiff', hein... |\n", stderr);
|
||||
fputs("\t+------------------------------------------------+\n", stderr);
|
||||
fputs("\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
/*
|
||||
* cette fonction de saisie est codee a la "GRUIK" (aka "rache method")
|
||||
*/
|
||||
#define W_FEN_SL 40
|
||||
#define H_FEN_SL 5
|
||||
|
||||
long saisir_un_long(char *txt)
|
||||
{
|
||||
WINDOW * saisie;
|
||||
int l, c, foo;
|
||||
long valeur;
|
||||
|
||||
saisie = newwin(H_FEN_SL, W_FEN_SL, 5, 20);
|
||||
wstandout(saisie);
|
||||
|
||||
/*
|
||||
* la, je me demande pourquoi je suis oblige de 'poker' des espaces
|
||||
* au lieu d'appeler une fonction de base. par exemple, wclear() ne
|
||||
* semble pas prendre en compte le wstandout() ?
|
||||
*/
|
||||
for (l=0; l<H_FEN_SL; l++)
|
||||
for (c=0; c<W_FEN_SL; c++)
|
||||
mvwaddch(saisie, l, c, ' ');
|
||||
|
||||
bordure(saisie);
|
||||
|
||||
mvwaddstr(saisie, 2, 3, txt);
|
||||
wstandend(saisie);
|
||||
mvwaddstr(saisie, 2, 25, " ");
|
||||
wrefresh(saisie);
|
||||
|
||||
echo();
|
||||
foo = mvwscanw(saisie, 2, 25, "%ld", &valeur);
|
||||
noecho();
|
||||
|
||||
/* wrefresh(saisie); */
|
||||
delwin(saisie);
|
||||
if (foo == 1)
|
||||
return valeur;
|
||||
return -1;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
void version(void)
|
||||
{
|
||||
fprintf(stderr, "\nThis is 'hexdiff' v "VERSION", made by tontonTh in 2007\n");
|
||||
fprintf(stderr, "homepage: http://tboudet.free.fr/hexdiff/\n");
|
||||
#if TRACE
|
||||
fprintf(stderr, "Warning ! compiled with active TRACE !\n");
|
||||
#endif
|
||||
fputs("\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
129
Hexdiff/hexdiff.1
Normal file
129
Hexdiff/hexdiff.1
Normal file
@@ -0,0 +1,129 @@
|
||||
.TH HexDiff 1 "November 1905" "Divers Un*ces" "TontonTh tools"
|
||||
|
||||
.SH NAME
|
||||
hexdiff \- un 'visuel diff' pour les fichiers binaires
|
||||
|
||||
.SH SYNOPSIS
|
||||
\fBhexdiff\fP -V
|
||||
.br
|
||||
\fBhexdiff\fP -h|-?
|
||||
.br
|
||||
\fBhexdiff\fP file1 file2
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBhexdiff\fP a été crée pour faciliter le débuggage de routines d'écriture
|
||||
de fichiers images (PCX et BMP, comme par hasard). En comparant un fichier
|
||||
kimarche et un fichier que je fabrique, ça va aider :)
|
||||
.br
|
||||
\fBhexdiff\fP affiche, après le lancement, deux fenètres montrant un dump
|
||||
hexadécimal et ascii du début des deux fichiers. Deux barres d'état
|
||||
donnent le nom du fichier, sa taille et l'offset courant.
|
||||
La fenêtre courante est marquée par '**' à gauche de l'écran.
|
||||
A l'aide de diverses touches du clavier, vous pouvez vous déplacer
|
||||
simultanément dans les deux fichiers, et le dump vous montrera alors,
|
||||
en vidéo inverse, les octets qui sont différents entre les deux fichiers.
|
||||
Après, hein, c'est à vous d'interpréter...
|
||||
|
||||
.SH OPTIONS
|
||||
.B -V
|
||||
Pour connaitre la version du machin-bidule.
|
||||
.br
|
||||
.B -h | -?
|
||||
Ah, il y a un peu de l'aide. Bon à savoir.
|
||||
.br
|
||||
.B -X
|
||||
Help for debugging your ~/.hexdiffrc, or the rc file parser.
|
||||
|
||||
.SH KEYBOARD COMMANDS
|
||||
.B x q
|
||||
Quitte le programme. Parfois...
|
||||
.br
|
||||
.B u j U
|
||||
Remonte d'une ligne (de 16 octets), ou de quatre, dans les deux fichiers.
|
||||
.br
|
||||
.B d k D
|
||||
Descend d'une ou quatre lignes dans les deux fichiers.
|
||||
.br
|
||||
.B <space>
|
||||
Descend de plusieurs lignes dans les deux fichiers. Ce nombre étant calculé
|
||||
selon la taille de l'écran, je ne peux le révéler ici.
|
||||
.br
|
||||
.B 0 <home>
|
||||
Reprend au début des deux fichiers.
|
||||
.br
|
||||
.B $
|
||||
Vous emmène aux environs de juste avant la fin du plus petit des deux fichiers.
|
||||
.br
|
||||
.B g
|
||||
Propose de saisir un nouvel offset pour les deux fichiers. Attention, cette
|
||||
fonctions a été écrite à la 'Gruik' et n'est donc pas fiable.
|
||||
.br
|
||||
.B H
|
||||
Bascule l'affichage des offsets entre le décimal et l'hexadécimal. Le mode
|
||||
initial est configurable.
|
||||
.br
|
||||
.B i
|
||||
Affichage des informations 'fstat' sur le fichier sélectionné.
|
||||
.br
|
||||
.B I
|
||||
Affiche les mêmes informations, mais pour les deux fichiers simultanément.
|
||||
.br
|
||||
.B A
|
||||
Open the (currently) experimental AsciiViewer.
|
||||
Maybe coredump with no request. <tab> switch as usual.
|
||||
.br
|
||||
.B ^O
|
||||
Ouverture d'un nouveau fichier dans la fenêtre courante. Le "selecteur de
|
||||
fichier" est encore rudimentaire. Utiliser 'Q' pour annuler, <Enter> pour
|
||||
valider, et '?' pour l'aide.
|
||||
.br
|
||||
.B n
|
||||
Part à la recherche de la prochaine différence entre les deux fichiers.
|
||||
.br
|
||||
.B <tab>
|
||||
Change la fenètre active. Pour le moment, ça ne sert presque à rien.
|
||||
Ah, non, il parait que ça joue sur le contexte d'autres fonctions.
|
||||
Personne ne m'en a parlé, je ne suis au courant de rien, alors
|
||||
je --->[]
|
||||
.br
|
||||
.B ?
|
||||
"Popupe" une fenètre d'aide reprenant les principales commandes. Pour
|
||||
les autres commandes: un seul slogan, Utsl.
|
||||
|
||||
.SH CONFIG FILE
|
||||
Le fichier de configuration est
|
||||
.B .hexdiffrc
|
||||
et doit se trouver dans le
|
||||
.B $HOME
|
||||
de l'utilisateur.
|
||||
Une ligne commençant par un
|
||||
.B '#'
|
||||
est un commentaire. Les lignes vides sont ignorées. Pour plus de détails,
|
||||
consulter le fichier 'hexdiff.rc' qui devrait se trouver dans l'archive.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR diff (1),
|
||||
.BR cmp (1)
|
||||
|
||||
.SH BUGS
|
||||
Si vous redimensionnez votre xterm, \fBhexdiff\fP se prend un SIGWINCH,
|
||||
et s'en va probablement visiter le pays des Slashies. Dans la pratique,
|
||||
il en revient très vite.
|
||||
.br
|
||||
L'affichage en fin de fichier, si les tailles sont différentes, est
|
||||
parfois un peu déglingué. Mais je vais réparer ça.
|
||||
.br
|
||||
Cette page de man n'est pas synchrone avec la réalité virtuelle du code.
|
||||
Car le code évolue plus vite que la réalité. Parfois.
|
||||
|
||||
.SH AUTHOR
|
||||
Thierry Boudet aka
|
||||
.B tTh
|
||||
qui 'spleytise' avec vigueur ce petit programme depuis Mars 2002.
|
||||
Pour en savoir un peu plus sur ce logiciel:
|
||||
http://tboudet.free.fr/hexdiff/ et sur moi: http://tontonth.free.fr/plop/
|
||||
|
||||
.SH DEDICACE
|
||||
Ce logiciel est dédié aux kamarades trolleurs de l'équipe HardStory du
|
||||
CULTe, sans qui rien n'est pas faisable. <http://www.culte.org/>
|
||||
|
||||
394
Hexdiff/hexdiff.c
Normal file
394
Hexdiff/hexdiff.c
Normal file
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
99
Hexdiff/hexdiff.h
Normal file
99
Hexdiff/hexdiff.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* global .h file for hexdiff
|
||||
* --------------------------
|
||||
*/
|
||||
|
||||
#include <ncurses.h>
|
||||
|
||||
/* "#define VERSION" is now in the Makefile */
|
||||
|
||||
#define T_BUFF 4242
|
||||
#define T_NOM 360
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fd;
|
||||
long taille;
|
||||
long offset;
|
||||
long lus;
|
||||
char nom[T_NOM+1]; /* buffer overflow ? */
|
||||
unsigned char buffer[T_BUFF];
|
||||
} Fichier;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int nice_border;
|
||||
int show_8bits;
|
||||
char *language;
|
||||
int offsets_in_hex;
|
||||
int ext_fileinfo;
|
||||
int show_hidden;
|
||||
int sf_flag;
|
||||
int explique; /* not used */
|
||||
int zoom;
|
||||
int asciiview; /* not used */
|
||||
} configuration;
|
||||
|
||||
/*
|
||||
* declaration of globals vars
|
||||
*/
|
||||
|
||||
#ifdef MAIN
|
||||
#define EXTERN
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
EXTERN Fichier f1, f2;
|
||||
EXTERN int fenetre_active;
|
||||
EXTERN configuration config;
|
||||
|
||||
/*
|
||||
* macros de positionnement en hauteur
|
||||
*/
|
||||
#define HAUT ((LINES-3)/2)
|
||||
#define HAUT_1 1
|
||||
#define BARRE_1 (HAUT_1+HAUT)
|
||||
#define HAUT_2 (HAUT_1+(HAUT)+1)
|
||||
#define BARRE_2 (HAUT_2+HAUT)
|
||||
|
||||
/*
|
||||
* prototype des fonctions
|
||||
*/
|
||||
void barre_inverse(char c, int ligne);
|
||||
int ecrire_barres_fichiers(void);
|
||||
int fond_ecran(void);
|
||||
void about(void);
|
||||
void aide_cl(int flag);
|
||||
void bordure(WINDOW * w);
|
||||
void popup_aide(void);
|
||||
long saisir_un_long(char *txt);
|
||||
void version(void);
|
||||
int is_printable(int octet);
|
||||
int ouvre_fichier(char *nom);
|
||||
|
||||
/*
|
||||
* file parse_rc.c
|
||||
*/
|
||||
#define HEXDIFF_RC ".hexdiffrc"
|
||||
int init_configuration(void);
|
||||
int lire_configuration(int flag);
|
||||
|
||||
/*
|
||||
* file fileinfo.c
|
||||
*/
|
||||
int fileinfo(int fd, int ligne);
|
||||
int double_fileinfo(int, int, int, int);
|
||||
|
||||
/*
|
||||
* file sel_file.c
|
||||
*/
|
||||
int select_new_file(char *, int, int);
|
||||
int select_set_opt(int flg);
|
||||
|
||||
/*
|
||||
* file asciiview.c
|
||||
*/
|
||||
int asciiview(void);
|
||||
int octalview(void); /* not urgent */
|
||||
|
||||
31
Hexdiff/hexdiff.rc
Normal file
31
Hexdiff/hexdiff.rc
Normal file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# fichier de configuration pour Hexdiff
|
||||
# http://tboudet.free.fr/hexdiff/
|
||||
#
|
||||
|
||||
# enable (1) or disable (0) display of chars
|
||||
# with a code > 127. charset dependant.
|
||||
# you can toogle this flag with the 7 and 8 keys
|
||||
show_8bits 1
|
||||
|
||||
# enable or disable usage of semi-graphic chars
|
||||
# around the various popup windows.
|
||||
nice_border 0
|
||||
|
||||
# select decimal or hexa display of file offset.
|
||||
# the key 'H' switch interactively beetwen the two modes.
|
||||
offsets_in_hex 0
|
||||
# sorry, at this time, no octal offset display...
|
||||
|
||||
# if set to 1, display the id of user and group
|
||||
# in the fileinfo popup (access by 'i' or 'I' key
|
||||
ext_fileinfo 1
|
||||
|
||||
# those flags is not yet used...
|
||||
language fr
|
||||
asciiview 0
|
||||
|
||||
# is the file selector display hidden file ?
|
||||
show_hidden 0
|
||||
|
||||
|
||||
15
Hexdiff/memcheck.sh
Normal file
15
Hexdiff/memcheck.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# seek for memory leaks
|
||||
# ---------------------
|
||||
# you need a recent version of http://www.valgrind.org/
|
||||
#
|
||||
make hexdiff
|
||||
|
||||
rm valgr-plop*
|
||||
|
||||
valgrind --tool=memcheck --log-file=valgr-plop \
|
||||
--leak-check=yes --show-reachable=yes \
|
||||
./hexdiff hexdiff.o fonctions.o
|
||||
|
||||
259
Hexdiff/parse_rc.c
Normal file
259
Hexdiff/parse_rc.c
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
|
||||
HEXDIFF - lecture du fichier de configuration
|
||||
---------------------------------------------
|
||||
|
||||
Attention, programmation a la "Gruiik" !-)
|
||||
Il y a plein de GOTO dans cette fonction, mais je
|
||||
les daguisent habilement en fortranisme.
|
||||
-- tTh --
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* pour strtok */
|
||||
/* certaines mauvaises langues pratendent
|
||||
* que 'strtok' est obsolete, insecure et
|
||||
* pas elegant. moi, je veux bien, mais
|
||||
* alors,il faut me montrer par quoi le
|
||||
* remplacer...
|
||||
*/
|
||||
#include "hexdiff.h"
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
/*
|
||||
* positionner a des valeurs connues toutes les options de
|
||||
* configuration.
|
||||
*
|
||||
* 18juin2002: euh, on ne pourrait pas faire ce truc a la
|
||||
* declaration de la variable ?
|
||||
*/
|
||||
int
|
||||
init_configuration(void)
|
||||
{
|
||||
config.nice_border = 0;
|
||||
config.show_8bits = 0;
|
||||
config.language = "fr";
|
||||
config.offsets_in_hex = 0;
|
||||
config.ext_fileinfo = 0;
|
||||
config.show_hidden = 1;
|
||||
config.sf_flag = 0;
|
||||
config.explique = 0;
|
||||
config.zoom = 0;
|
||||
config.asciiview = 0;
|
||||
|
||||
return 51; /* have a Pastis ? */
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
#define DO_NICE_BORDER 1
|
||||
#define DO_LANGUAGE 2
|
||||
#define DO_SHOW_8BITS 3
|
||||
#define DO_OFFSET_HEX 4
|
||||
#define DO_EXT_FILEINFO 5
|
||||
#define DO_SHOW_HIDDEN 20
|
||||
#define DO_FS_FLAG 21
|
||||
#define DO_EXPLIQUE 24
|
||||
#define DO_START_ZOOM 25
|
||||
#define DO_ASCIIVIEW 26
|
||||
|
||||
#define FLAG 1
|
||||
#define TEXTE 2
|
||||
#define NOMBRE 3
|
||||
#define KEY_ALIAS 4
|
||||
|
||||
struct conf_var
|
||||
{
|
||||
char *nom;
|
||||
int code;
|
||||
int type;
|
||||
};
|
||||
|
||||
struct conf_var conf_vars[] =
|
||||
{
|
||||
{ "nice_border", DO_NICE_BORDER, FLAG },
|
||||
{ "language", DO_LANGUAGE, TEXTE },
|
||||
{ "show_8bits", DO_SHOW_8BITS, FLAG },
|
||||
{ "offsets_in_hex", DO_OFFSET_HEX, FLAG },
|
||||
{ "ext_fileinfo", DO_EXT_FILEINFO, FLAG },
|
||||
{ "show_hidden", DO_SHOW_HIDDEN, FLAG },
|
||||
{ "fs_flag", DO_FS_FLAG, NOMBRE },
|
||||
{ "explique", DO_EXPLIQUE, FLAG },
|
||||
{ "start_zoom", DO_START_ZOOM, FLAG },
|
||||
{ "asciiview", DO_ASCIIVIEW, NOMBRE }
|
||||
} ;
|
||||
|
||||
#define NB_TOKEN ( sizeof(conf_vars) / sizeof(struct conf_var) )
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
static int lookup_token(char *token)
|
||||
{
|
||||
int foo;
|
||||
|
||||
for (foo=0; foo<NB_TOKEN; foo++)
|
||||
if ( !strcmp(token, conf_vars[foo].nom) )
|
||||
return foo;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
#define LIGNE_RC 442
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
/*
|
||||
* If 'flag' is set to a non-zero value:
|
||||
* - the configfile name is set to './hexdiff.rc'
|
||||
* - parsing trace is displayed
|
||||
*/
|
||||
int
|
||||
lire_configuration(int flag)
|
||||
{
|
||||
FILE *fp;
|
||||
char ligne[LIGNE_RC+3];
|
||||
int line_number, foo;
|
||||
int numtok;
|
||||
char *machin, *valeur;
|
||||
char *delim = " \t=";
|
||||
char *home;
|
||||
|
||||
#if TRACE
|
||||
fprintf(stderr, "*** lecture fichier de conf, flag=%d\n", flag);
|
||||
#endif
|
||||
|
||||
if ( (home=getenv("HOME")) != NULL )
|
||||
{
|
||||
/*
|
||||
* XXX - WARNING BUFFER OVERFLOW HERE !!!
|
||||
*/
|
||||
foo = strlen(home) + strlen(HEXDIFF_RC);
|
||||
if (foo > LIGNE_RC)
|
||||
{
|
||||
fprintf(stderr, ".hexdiffrc buff overflow %d, bad $HOME ?\n",
|
||||
foo);
|
||||
exit(1);
|
||||
}
|
||||
strcpy(ligne, home); strcat(ligne, "/");
|
||||
strcat(ligne, HEXDIFF_RC);
|
||||
}
|
||||
else
|
||||
/*
|
||||
* oui, bon, c'est pas trop coherent, mais je ne
|
||||
* savais pas trop quoi faire en cas de 'homeless',
|
||||
* alors je me suis permis de supposer un contexte
|
||||
* msdos/djgpp ...
|
||||
*/
|
||||
{
|
||||
strcpy(ligne, "c:\\hexdiff.rc");
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
if (flag) /* we are in .rc debug context */
|
||||
{
|
||||
strcpy(ligne, "hexdiff.rc");
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( (fp = fopen(ligne, "r")) == NULL )
|
||||
{
|
||||
perror("hexdiff config file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
line_number = 1;
|
||||
|
||||
while ( fgets(ligne, LIGNE_RC, fp) != NULL )
|
||||
{
|
||||
/*
|
||||
* virer le caractere de fin de ligne (Gruiikage)
|
||||
*/
|
||||
foo=strlen(ligne);
|
||||
if (foo>0)
|
||||
ligne[foo-1] = '\0';
|
||||
#if TRACE
|
||||
fprintf(stderr, "%4d %4d : %s\n",
|
||||
line_number, foo, ligne);
|
||||
#endif
|
||||
line_number++;
|
||||
|
||||
/*
|
||||
* decomposition de la ligne en machins
|
||||
*/
|
||||
machin = strtok(ligne, delim);
|
||||
|
||||
if (machin == NULL) /* ya pas de token */
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( machin[0] == '#' ) /* c'est un commentaire */
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
numtok = lookup_token(machin);
|
||||
|
||||
if (flag)
|
||||
fprintf(stderr, "TOKEN = [%s] code=%d\n", machin, numtok);
|
||||
|
||||
if ( numtok < 0 ) { continue; }
|
||||
|
||||
valeur = strtok(NULL, delim); /* is strtok() usable in 2007 ? */
|
||||
|
||||
if ( valeur != NULL )
|
||||
{
|
||||
if (flag)
|
||||
fprintf(stderr, "VALUE = [%s]\n", valeur);
|
||||
|
||||
switch(conf_vars[numtok].code)
|
||||
{
|
||||
case DO_NICE_BORDER:
|
||||
config.nice_border = atoi(valeur);
|
||||
break;
|
||||
|
||||
case DO_SHOW_8BITS:
|
||||
config.show_8bits = atoi(valeur);
|
||||
break;
|
||||
|
||||
case DO_LANGUAGE:
|
||||
#if TRACE
|
||||
fprintf(stderr, "lang=%s\n", valeur);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case DO_OFFSET_HEX:
|
||||
config.offsets_in_hex = atoi(valeur);
|
||||
break;
|
||||
|
||||
case DO_EXT_FILEINFO:
|
||||
config.ext_fileinfo = atoi(valeur);
|
||||
break;
|
||||
|
||||
case DO_SHOW_HIDDEN:
|
||||
config.show_hidden = atoi(valeur);
|
||||
break;
|
||||
|
||||
case DO_FS_FLAG:
|
||||
break;
|
||||
|
||||
case DO_EXPLIQUE:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else /* valeur == NULL */
|
||||
{
|
||||
#if TRACE
|
||||
fprintf(stderr, "null value ?\n");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
return 42; /* thx for all the fishes, Douglas */
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
352
Hexdiff/sel_file.c
Normal file
352
Hexdiff/sel_file.c
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
sel_file.c
|
||||
----------
|
||||
|
||||
old site --> http://tboudet.free.fr/hexdiff/
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
/* nasty hack */
|
||||
char *strdup(char *);
|
||||
/* end of hack */
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "hexdiff.h"
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
/* private vars of this module */
|
||||
|
||||
typedef struct {
|
||||
long taille;
|
||||
char *nom;
|
||||
int idx;
|
||||
} FICH;
|
||||
|
||||
static FICH *liste;
|
||||
static int taille; /* taille de la liste */
|
||||
static int nombre; /* nbre d'entrees dans la liste */
|
||||
|
||||
#define TCHONK 42
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
static int teste_dirent(const struct dirent *de, struct stat *pstat)
|
||||
{
|
||||
int foo;
|
||||
|
||||
foo = stat(de->d_name, pstat);
|
||||
|
||||
if (S_ISDIR(pstat->st_mode))
|
||||
return 0;
|
||||
|
||||
if (config.show_hidden==0 && de->d_name[0]=='.')
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
static int compare_nom_asc(const void *pa, const void *pb)
|
||||
{
|
||||
return strcmp( ((FICH *)pa)->nom, ((FICH *)pb)->nom);
|
||||
}
|
||||
static int compare_nom_desc(const void *pa, const void *pb)
|
||||
{
|
||||
return strcmp( ((FICH *)pb)->nom, ((FICH *)pa)->nom);
|
||||
}
|
||||
static int compare_taille_asc(const void *pa, const void *pb)
|
||||
{
|
||||
return ((FICH *)pa)->taille - ((FICH *)pb)->taille;
|
||||
}
|
||||
static int compare_taille_desc(const void *pa, const void *pb)
|
||||
{
|
||||
return ((FICH *)pb)->taille - ((FICH *)pa)->taille;
|
||||
}
|
||||
static int compare_idx(const void *pa, const void *pb)
|
||||
{
|
||||
return ((FICH *)pa)->idx - ((FICH *)pb)->idx;
|
||||
}
|
||||
#define PAR_NOM_ASC 1
|
||||
#define PAR_NOM_DESC 2
|
||||
#define PAR_TAILLE_ASC 3
|
||||
#define PAR_TAILLE_DESC 4
|
||||
#define PAR_IDX 5
|
||||
#define PAR_PLOP 6
|
||||
static int trier_la_liste(int comment)
|
||||
{
|
||||
switch (comment)
|
||||
{
|
||||
case PAR_NOM_ASC:
|
||||
qsort(liste, nombre, sizeof(FICH), compare_nom_asc);
|
||||
break;
|
||||
case PAR_NOM_DESC:
|
||||
qsort(liste, nombre, sizeof(FICH), compare_nom_desc);
|
||||
break;
|
||||
case PAR_TAILLE_ASC:
|
||||
qsort(liste, nombre, sizeof(FICH), compare_taille_asc);
|
||||
break;
|
||||
case PAR_TAILLE_DESC:
|
||||
qsort(liste, nombre, sizeof(FICH), compare_taille_desc);
|
||||
break;
|
||||
case PAR_IDX:
|
||||
qsort(liste, nombre, sizeof(FICH), compare_idx);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
static int liste_fichiers(WINDOW *win, int flag)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
struct stat statbuf;
|
||||
int foo;
|
||||
|
||||
/*
|
||||
* initializing local vars, for list-of-files
|
||||
*/
|
||||
if ( NULL == (liste = malloc(TCHONK*sizeof(FICH))) )
|
||||
{
|
||||
wprintw(win, "no mem for file list");
|
||||
wrefresh(win);
|
||||
return 1;
|
||||
}
|
||||
taille = TCHONK;
|
||||
|
||||
dir = opendir(".");
|
||||
if (dir == NULL)
|
||||
{
|
||||
wprintw(win, "error on 'opendir'");
|
||||
wrefresh(win);
|
||||
return 1;
|
||||
}
|
||||
|
||||
nombre = 0;
|
||||
while ( (de=readdir(dir)) != NULL)
|
||||
{
|
||||
if ( ! teste_dirent(de, &statbuf) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* strdup is a 'non-portable' function ? */
|
||||
liste[nombre].nom = strdup(de->d_name);
|
||||
liste[nombre].taille = statbuf.st_size;
|
||||
liste[nombre].idx = nombre;
|
||||
nombre++;
|
||||
wrefresh(win);
|
||||
|
||||
/*
|
||||
* if needed, increase the size of the list
|
||||
*/
|
||||
if (nombre >= taille)
|
||||
{
|
||||
liste = realloc(liste, sizeof(FICH)*(taille+TCHONK));
|
||||
taille += TCHONK;
|
||||
}
|
||||
}
|
||||
|
||||
foo = closedir(dir);
|
||||
|
||||
return nombre;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
char *txt_aide_fs[] =
|
||||
{
|
||||
"\n WARNING !\n\n",
|
||||
" this file selector is a 'quick and dirty' hack\n",
|
||||
" and code was written with a 'Spleyt' spirit :)\n\n",
|
||||
"\n",
|
||||
" smart keys are:\n\n",
|
||||
" a -> sort by name ascending\n",
|
||||
" A -> sort by name reversing\n",
|
||||
" s -> sort by size\n",
|
||||
" S -> sort reverse by size\n",
|
||||
" n -> no sort\n",
|
||||
"",
|
||||
"sort by date is a work in progress..."
|
||||
};
|
||||
int help_on_file_selector(WINDOW *win, int flag)
|
||||
{
|
||||
int foo;
|
||||
|
||||
werase(win);
|
||||
for (foo=0; foo<(sizeof(txt_aide_fs)/sizeof(char *)); foo++)
|
||||
{
|
||||
wprintw(win, txt_aide_fs[foo]);
|
||||
wrefresh(win);
|
||||
}
|
||||
foo = getch();
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
/*
|
||||
* new, 2005 June: now, we get the max usable length for *nomfich.
|
||||
*/
|
||||
int select_new_file(char *nomfich, int t_nom, int flags)
|
||||
{
|
||||
int ligmax, largmax, affh, idx = -1;
|
||||
WINDOW *fen_1, *fen_2;
|
||||
int foo, first, curseur, flag_exit, key;
|
||||
char chaine[T_NOM];
|
||||
|
||||
/*
|
||||
* quick'n'dirty security check, need more work.
|
||||
*/
|
||||
if (t_nom > T_NOM)
|
||||
{
|
||||
fprintf(stderr, "\n%s:%d possible buffer overflow\n", __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ligmax = LINES-8; /* taille verticale de la popup */
|
||||
largmax = 62;
|
||||
|
||||
fen_1 = newwin(ligmax, largmax, 2, 12);
|
||||
bordure(fen_1); wrefresh(fen_1);
|
||||
|
||||
/*
|
||||
* first line of popup display active win number
|
||||
* and current win directory. as this time, we can't
|
||||
* select another directory ;-(
|
||||
*/
|
||||
wstandout(fen_1);
|
||||
for (foo=1; foo<largmax-1; foo++)
|
||||
{
|
||||
mvwaddch(fen_1, 1, foo, ' ');
|
||||
mvwaddch(fen_1, ligmax-2, foo, ' ');
|
||||
}
|
||||
/* XXX display the number of the active window
|
||||
XXX in this file selector.
|
||||
sprintf(chaine, "<%d>", fenetre_active);
|
||||
mvwaddstr(fen_1, 1, 2, chaine);
|
||||
*/
|
||||
|
||||
if (getcwd(chaine,99)!=NULL)
|
||||
mvwaddstr(fen_1, 1, 3, chaine);
|
||||
else
|
||||
mvwaddstr(fen_1, 1, 9, " can't get cwd, sorry... ");
|
||||
|
||||
mvwaddstr(fen_1, ligmax-2, 4, "'Q' to abort, <Enter> to select, '?' for help");
|
||||
wstandend(fen_1);
|
||||
wrefresh(fen_1);
|
||||
|
||||
/*
|
||||
* create a subwindow for the scrolling selector
|
||||
*/
|
||||
fen_2 = derwin(fen_1, ligmax-4, largmax-2, 2, 1);
|
||||
scrollok(fen_2, 1);
|
||||
|
||||
affh = ligmax-4; /* XXX need a valid value :) */
|
||||
|
||||
foo = liste_fichiers(fen_2, 0);
|
||||
#if TRACE
|
||||
wprintw(fen_2, "ret liste fichiers = %d\n", foo);
|
||||
wrefresh(fen_2);
|
||||
getch();
|
||||
#endif
|
||||
|
||||
trier_la_liste(PAR_NOM_ASC);
|
||||
|
||||
/*
|
||||
* now, the file list is built, so display the selector.
|
||||
*/
|
||||
first = curseur = 0;
|
||||
flag_exit = 0;
|
||||
|
||||
do
|
||||
{
|
||||
werase(fen_2);
|
||||
for (foo=0; foo<affh; foo++)
|
||||
{
|
||||
idx = foo+first;
|
||||
if (idx >= nombre)
|
||||
break;
|
||||
|
||||
if (curseur==foo) wstandout(fen_2);
|
||||
mvwprintw(fen_2, foo, 1, " %-46s %9ld ",
|
||||
liste[idx].nom, liste[idx].taille);
|
||||
if (curseur==foo) wstandend(fen_2);
|
||||
}
|
||||
wrefresh(fen_2);
|
||||
|
||||
#if TRACE
|
||||
mvwprintw(fen_1, 1, 2, "curs %3d first %3d ", curseur, first);
|
||||
wrefresh(fen_1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* user interaction
|
||||
*/
|
||||
key = getch();
|
||||
switch (key)
|
||||
{
|
||||
case KEY_UP:
|
||||
if (curseur) curseur--;
|
||||
else if (first>0) first--;
|
||||
break;
|
||||
|
||||
case KEY_DOWN:
|
||||
if ((curseur+first) >= (nombre-1)) break;
|
||||
|
||||
if (curseur < affh-1) curseur++;
|
||||
else if (first<(nombre-affh)) first++;
|
||||
break;
|
||||
|
||||
/* SORT operations */
|
||||
case 'a':
|
||||
trier_la_liste(PAR_NOM_ASC); break;
|
||||
case 'A':
|
||||
trier_la_liste(PAR_NOM_DESC); break;
|
||||
case 's':
|
||||
trier_la_liste(PAR_TAILLE_ASC); break;
|
||||
case 'S':
|
||||
trier_la_liste(PAR_TAILLE_DESC); break;
|
||||
|
||||
case '?':
|
||||
help_on_file_selector(fen_2, 0);
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
idx = curseur+first;
|
||||
flag_exit = 1;
|
||||
break;
|
||||
|
||||
case 'Q': flag_exit = -1; break;
|
||||
}
|
||||
} while ( ! flag_exit );
|
||||
|
||||
delwin(fen_1);
|
||||
|
||||
if (flag_exit == 1)
|
||||
{
|
||||
strcpy(nomfich, liste[idx].nom);
|
||||
}
|
||||
|
||||
/*
|
||||
* free the memory used by our list
|
||||
*/
|
||||
for (foo=0; foo<nombre; foo++)
|
||||
free(liste[foo].nom);
|
||||
free(liste);
|
||||
|
||||
return flag_exit==1;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
int select_set_opt(int flg)
|
||||
{
|
||||
#if TRACE
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
Reference in New Issue
Block a user