very old code commited, ymmv

This commit is contained in:
tTh
2022-11-24 14:37:21 +01:00
parent 4fa31cb790
commit c653852ee2
35 changed files with 4153 additions and 1 deletions

3
Hexdiff/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
hexdiff

71
Hexdiff/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}
/*----------------------------------------------------------------*/