home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
disk
/
misc
/
dcmp
/
source
/
source.lha
/
dcmp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-23
|
79KB
|
2,488 lines
/*--------------------------------------------------------------------------*
__
/ / $RCSfile dcmp.c,v $
____/ /______ _ _ ______ $Release 1.0$
/ __/ // ____// \_/ \ / __ / $Revision: 1.51 $
/ /_/ // /___ / /__/ // /_/ / $Date: 93/01/17 16:45:27 $
/_____//_____//_/ /_// ____/ $Author: tf $
/ / $State: Exp $
Revision 1.51 /_/
(c) Copyright 1992 Tobias Ferber, All Rights Reserved.
*--------------------------------------------------------------------------*/
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <exec/tasks.h>
#include <exec/io.h>
#include <intuition/intuitionbase.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <graphics/gfx.h>
#include <graphics/rastport.h>
/* for wbmain() */
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <workbench/icon.h>
#include <stdio.h>
/* system stuff */
static struct IntuitionBase *IntuitionBase;
static struct GfxBase *GfxBase;
static struct Window *Window;
static struct TextFont *TextFont;
static struct IntuiMessage *imsg;
static BOOL MenuFlag; /* SetMenuStrip() successfull? */
struct IconBase *IconBase; /* not always opened! */
/* stuff for the req.library */
#include <libraries/dosextens.h>
#include <libraries/reqbase.h>
struct ReqLib *ReqBase;
static struct Process *MyProcess;
static APTR OldWindowPtr;
/* stuff for the reqtools.library */
#include <libraries/reqtools.h>
#include <proto/reqtools.h>
struct ReqToolsBase *ReqToolsBase;
/* pre-declarations for cdglue.o */
BOOL a_Requester();
BOOL a_GetLongRequester();
VOID a_FileRequester();
int dos_rkcv(), dos_rkcvinit(), dos_rkcvexit(); /* ... rkcv.o */
int dcmp_Request();
/* nice.o */
extern struct Window *NiceOpenWindow();
extern void NiceCloseWindow();
extern UWORD NiceOpenSpeed, NiceCloseSpeed;
/*#include "crawl.h"*/
#include "strfn.h" /* string functions */
/* ---------------------------------------------------------------------- */
static char rcs_id[]="$Id: dcmp.c,v 1.51 93/01/17 16:45:27 tf Exp $";
#define BANNER "-- compare two disks block by block"
#define USAGE "USAGE: dcmp [-<options>] <DF0..3> [DF0..3]"
char *whoami; /* argv[0]: (who am I) */
#define DEF_LOGFILE "RAM:dcmp.log"
unsigned int language= 0L; /* 0 == ENGLISH */
#include "data.h" /* global structures (mainly intuition) */
#include "td_support.h" /* trackdisk support functions */
#include "intuisup.h" /* intuition support functions */
#include "pointer.h" /* mouse pointer support */
int dcmp_pointer= SMI_PREFS, busybee= SMI_BUSYBEE; /* (busy) mouse pointer image */
#define DEF_ATTEMPTS 2
#define MAX_ATTEMPTS 10
FILE *fp; /* file pointer for the logfile */
#define well_done 0L
#define warning 1L
#define error_state 2L
#define fatal_error 3L
#define depart 4L
#define lental (history>error_state)
#define danger (history>warning)
#define mark(x) history=x
int history= well_done; /* indicates program state */
/* flags for the options */
#define logfile_open (fp != (FILE *)NULL)
static BOOL write_logfile = FALSE, /* logfile creation desired */
write_icon = FALSE, /* icon creation for the logfile */
logdata_added = FALSE, /* logfile opened for `a'ppend */
be_quiet = FALSE, /* don't use printf(), puts()... */
display_window = FALSE, /* display data in the window */
ignore_errors = TRUE, /* don't break on errors */
deep_read = FALSE; /* don't read tracks twice */
/*
* I declare this deep_buffer pointer as global since it has to be freed
* outside of do_dcmp_stuff() in case of a ^C break.
* It is allocated in open_dcmp_stuff(), used in do_dcmp_stuff() and
* freed in close_dcmp_stuff().
*/
static ULONG *deep_buffer= (ULONG *)NULL;
#define CRSR_ON "\233\40\160\r"
#define CRSR_OFF "\233\60\40\160\r"
void _abort(void) /* DICE: set this in main() via onbreak(); */
{
printf("^C\n\n** BREAK\n" CRSR_ON);
mark(error_state);
wrap_up();
}
#include <stdarg.h>
void inform_user(const char *fmt, ...) /* ellipse declaration */
{ static char *answer[]= { "Resume", "Okay", "Continuer", "Continuare" };
va_list argp;
va_start(argp,fmt); /* name the last known argument */
if(!be_quiet)
{ fprintf(stderr, "\r%s: ",whoami);
vfprintf(stderr, fmt, argp);
fprintf(stderr, "\n");
}
else
{ char msg[1024]; /* information limited to 1K */
vsprintf(msg, fmt, argp);
a_Requester(msg,NULL,answer[language]);
}
va_end(argp); /* just to be sure... */
}
/* globals += */
static int unit_r = NOUNIT, /* first unit (read) */
unit_c = NOUNIT, /* second unit (compare) */
start_blk = FIRSTBLOCK, /* block to start with */
end_blk = LASTBLOCK, /* block to end with */
attempts = DEF_ATTEMPTS, /* #of retries to read */
ratt = 0, /* #of remaining attempts */
dblk = 0, /* #of differing blocks found */
dtrk = 0, /* ... tracks ... */
wtrk = 0, /* #of weak tracks found */
errcnt = 0; /* #of errors found */
/*
* If a block differs I will write its number into this array and check
* the results later.
*/
static int dblk_list[1760];
init_global_values()
{ int i;
for(i=0;i<=1759;dblk_list[i]=-1,i++)
;
ratt= attempts;
dblk= 0;
dtrk= 0;
wtrk= 0;
errcnt= 0;
}
/*
* cleanup procedures
*/
void close_window_stuff()
{
dos_rkcvexit();
if(Window)
{ if(MenuFlag) ClearMenuStrip(Window);
UnsetMouseImage(Window);
RestoreMouseColors(Window);
NiceCloseWindow(Window);
}
if(TextFont) CloseFont(TextFont);
if(ReqToolsBase) CloseLibrary(ReqToolsBase);
else if(ReqBase)
{ MyProcess->pr_WindowPtr=(struct Window *)OldWindowPtr;
CloseLibrary(ReqBase);
}
if(GfxBase) CloseLibrary(GfxBase);
if(IntuitionBase) CloseLibrary(IntuitionBase);
}
void close_logfile(void)
{ if(fp) fclose(fp);
fp= (FILE *)NULL; /* just to be sure... */
}
void close_dcmp_stuff(void)
{ if(deep_buffer)
{ FreeMem(deep_buffer, BYTES_PER_TRACK);
deep_buffer= (ULONG *)NULL; /* just to be sure */
}
if(unit_r != NOUNIT)
close_unit(unit_r);
if(unit_c != NOUNIT && unit_c != unit_r)
close_unit(unit_c);
}
/*
* close our stuff and exit()
*/
int wrap_up()
{ if(danger)
{ if(!be_quiet && history == fatal_error)
printf("\r%s: this was a fatal error, my friend!\n",whoami);
if(write_logfile && logfile_open)
fprintf(fp,"%s terminated abnormally.\n",whoami);
}
close_dcmp_stuff();
if(logfile_open) close_logfile();
if(display_window) close_window_stuff();
exit(danger?1:0);
}
#define DEFAULT_PEN 1L
#define DIFFER_PEN 2L
#define EQUAL_PEN 3L
/*
* draw_box() -- draw a hires box with double vertical lines
*/
void draw_box(rp,x,y,w,h,fpen)
struct RastPort *rp;
UWORD x,y,w,h;
int fpen;
{ int dpen; /* old detail pen */
Move(rp,x,y);
Draw(rp,x,y+h);
Draw(rp,x+w,y+h);
Draw(rp,x+w,y);
Draw(rp,x+1,y);
Draw(rp,x+1,y+h);
Move(rp,x+w-1,y+h);
Draw(rp,x+w-1,y);
if(w>4 && h>2)
{ dpen=rp->FgPen; /* save old APen */
SetAPen(rp,fpen);
RectFill(rp,x+2,y+1,x+w-2,y+h-1);
SetAPen(rp,dpen); /* resore it */
}
}
/*
* draw a grid (track display): x=left edge, y=top edge
*/
#define TRACKBOX_W 15L
#define TRACKBOX_H 8L
void draw_trackframe(rp, xpos, ypos, head)
struct RastPort *rp;
UWORD xpos, ypos;
int head;
{ UWORD x,y;
UWORD dx,dy;
static char nums[]= "0123456789", heads[]= "Head 0";
SetAPen(rp,DEFAULT_PEN); /* choose a color */
dx= xpos+TextFont->tf_XSize+5; /* xpos + width of textfont + dist. */
dy= ypos+TextFont->tf_YSize+1; /* ypos + height of textfont */
/* draw vertical lines */
for(x=0;x<=10;x++)
{ Move(rp, dx+(TRACKBOX_W*x), dy);
Draw(rp, dx+(TRACKBOX_W*x), dy+(TRACKBOX_H*8));
/*
* since pixels width is about half of their height, we
* will draw vertical lines doubled
*/
Move(rp, dx+1+(TRACKBOX_W*x), dy);
Draw(rp, dx+1+(TRACKBOX_W*x), dy+(TRACKBOX_H*8));
}
/* draw horizontal lines */
for(y=0;y<=8;y++)
{ Move(rp, dx, dy+(TRACKBOX_H*y));
Draw(rp, dx+(TRACKBOX_W*10), dy+(TRACKBOX_H*y));
}
/* add 3 boxes */
for(x=0;x<3;x++)
{ draw_box(rp, dx+(TRACKBOX_W*x), dy+(TRACKBOX_H*8),
TRACKBOX_W+1, TRACKBOX_H, 0L);
}
/* add numbers to the frame */
dx+= 5; /* add number centering distance */
dy= ypos+TextFont->tf_Baseline; /* ypos + fontbase correction */
for(x=0;x<=9;x++)
{ Move(rp, dx+(TRACKBOX_W*x),dy);
Text(rp, &nums[x],1L);
}
dx= xpos; /* xpos + centering distance */
dy+=TextFont->tf_YSize+2; /* add height of font, centering dist. */
for(y=0;y<=8;y++)
{ Move(rp, dx, dy+(TRACKBOX_H*y));
Text(rp, &nums[y],1L);
}
/* add head number */
dx= xpos+TextFont->tf_XSize+4+(TRACKBOX_W*5);
dy= ypos+TextFont->tf_YSize+3+(TRACKBOX_H*8)+TextFont->tf_Baseline;
heads[5]= (char)('0' + head);
Move(rp, dx, dy);
Text(rp, heads, strlen(heads));
}
/* changed on Thu Dec 10 02:49:45 1992 to fit in our GIMMEZEROZERO Window */
#define TFRAME_Y (14L-11L)
#define TFRAME0_X (10L-4L)
#define TFRAME1_X (186L-4L)
#define INFOBOX_X (366L-4L)
#define INFOBOX_Y (24L-11L) /* changed on Thu Dec 10 02:49:45 1992 */
#define INFOBOX_W 146L
#define INFOBOX_H 40L
#define EQUALBOX_X (INFOBOX_X+51)
#define DIFFERBOX_X (EQUALBOX_X+54)
#define EQDIFFBOX_Y (INFOBOX_Y-11L)
#define ABOUTBOX_X TFRAME0_X
#define ABOUTBOX_Y TFRAME_Y
#define ABOUTBOX_W 341L
#define ABOUTBOX_H 82L
/* globals += */
BOOL see_about= FALSE;
/*
* Delete the old track grids and overwrite them by empty ones.
* The RastPort is taken from Window->RPort!
*/
void new_trackframes(void)
{ struct RastPort *rp= Window->RPort;
SetAPen(rp,0L);
RectFill(rp, ABOUTBOX_X, ABOUTBOX_Y,
ABOUTBOX_X+ABOUTBOX_W, ABOUTBOX_Y+ABOUTBOX_H);
draw_trackframe(rp, TFRAME0_X, TFRAME_Y, 0L);
draw_trackframe(rp, TFRAME1_X, TFRAME_Y, 1L);
see_about= FALSE; /* EITHER trackframes OR about... */
}
/*
* who did it?
*/
void about()
{ struct RastPort *rp= Window->RPort;
static char *about_text[]= { "This version is HIGHLY EXPERIMENTAL!",
/*"This version of DCMP is SHAREWARE!",*/
"Tobias Ferber, Bismarckstraße 22",
"W-7570 Baden-Baden, GERMANY"
};
Window->Flags |= RMBTRAP; /* Is this allowed ? */
if(!see_about) /* I didn't want to write: if(see_about= !see_about) */
{ draw_3d(rp, ABOUTBOX_X, ABOUTBOX_Y, ABOUTBOX_W, ABOUTBOX_H, 0, POS_3D);
DrawImage(rp, &LogoImage, 100-4, 20-11);
SetDrMd(rp,JAM1);
SetAPen(rp,1L);
WaitBlit(); Move(rp,36-4,64-11); Text(rp,about_text[0],strlen(about_text[0]));
SetAPen(rp,2L);
WaitBlit(); Move(rp,34-4,63-11); Text(rp,about_text[0],strlen(about_text[0]));
SetAPen(rp,3L);
WaitBlit(); Move(rp,51-4,76-11); Text(rp,about_text[1],strlen(about_text[1]));
WaitBlit(); Move(rp,71-4,86-11); Text(rp,about_text[2],strlen(about_text[2]));
see_about= TRUE;
}
else new_trackframes(); /* sets see_about to FALSE */
Window->Flags &= ~RMBTRAP;
}
#define INFOTEXT_X (INFOBOX_X+98) /* 186 */
#define INFOTEXT_Y (INFOBOX_Y+11) /* 5 */
#define INFOTEXT_DY 11
set_iboxval(start, end, att, err, curr)
int start, end, att, err, curr;
{ char s[5];
struct RastPort *rp= Window->RPort;
SetAPen(rp,EQUAL_PEN);
SetDrMd(rp,JAM2);
if(start >= 0)
{ sprintf(s,"%02d",start);
Move(rp,INFOTEXT_X,INFOTEXT_Y);
Text(rp,s,strlen(s));
}
if(end >= 0)
{ sprintf(s,"%02d",end);
Move(rp,INFOTEXT_X+24,INFOTEXT_Y);
Text(rp,s,strlen(s));
}
if(att >= 0)
{ sprintf(s,"%02d",att);
Move(rp,INFOTEXT_X+8,INFOTEXT_Y+INFOTEXT_DY);
Text(rp,s,strlen(s));
}
if(err >= 0)
{ Move(rp,INFOTEXT_X+32,INFOTEXT_Y+INFOTEXT_DY);
Text(rp,(ignore_errors)?("i"):("b"),1L);
}
if(curr >= 0)
{ sprintf(s,"%03d",curr);
Move(rp,INFOTEXT_X+16,INFOTEXT_Y+2*INFOTEXT_DY);
Text(rp,s,strlen(s));
}
}
/*
* set_trackframe()
*/
void set_trackframe(trk, diff, ratt, oper)
int trk, diff, ratt;
char *oper;
{ UWORD i,dx,dy;
char s[6];
int cyl= trk/2; /* NUMHEADS=2 !!! (TRACKS_PER_CYLINDER) */
struct RastPort *rp= Window->RPort;
dx= TextFont->tf_XSize+5+(cyl%10)*TRACKBOX_W;
dy= TFRAME_Y+TextFont->tf_YSize+1+(cyl/10)*TRACKBOX_H;
if(trk%2 == 0) dx+= TFRAME0_X; /* head 0 */
else dx+= TFRAME1_X; /* head 1 */
if(diff<0) SetAPen(rp,0L);
else SetAPen(rp,(diff==0)?(EQUAL_PEN):(DIFFER_PEN));
RectFill(rp, dx+2, dy+1, dx+TRACKBOX_W-1, dy+TRACKBOX_H-1);
if(oper && *oper)
{ SetDrMd(rp,JAM1);
if(diff<0) SetAPen(rp,DEFAULT_PEN);
else SetAPen(rp,(diff==0)?(DIFFER_PEN):(EQUAL_PEN));
Move(rp, dx+4, dy+TextFont->tf_Baseline);
Text(rp, oper, strlen(oper));
}
set_iboxval(-1, -1, ratt, -1, trk);
}
/*
* open_window_stuff()
*/
void open_window_stuff(void)
{ struct RastPort *rp;
static char *err_msg[][]= {
{ "You need intuition.library V%ld+", /* 0 */
"You need graphics.library V%ld+", /* 1 */
"Unable to open window.", /* 2 */
"Unable to set menu strip.", /* 3 */
"Couldn't open %s {%ld}." /* 4 */
},
{ "Sie benötigen die Intuition.library in der Version %ld (oder neuer).",
"Ich kann die Graphics.library nicht öffnen.",
"Ich krieg das Fenster nicht auf!",
"Die Menüzeile weigert sich!",
"Ich kann den %s {%ld} nicht öffnen!",
},
{ "Vous avez besoin de l'intuition.library version %ld+",
"Je ne peux pas ouvrir la graphics.library.",
"Je ne peux pas ouvrir la fenêtre!",
"Le MenuStrip ne veut pas!",
"Je ne peux pas ouvrir le %s {%ld} !",
},
{ "Avete bisogno della Intuition.library nella versione %ld (o più recente).",
"Non posso aprire la graphics.library.",
"Non posso aprire la finestra!",
"La linea nel menu si rifiuta!",
"Non posso aprire il %s {%ld}",
}
};
IntuitionBase=(struct IntuitionBase *)
OpenLibrary("intuition.library",LIBRARY_VERSION);
if(!IntuitionBase)
{ inform_user(err_msg[language][0],LIBRARY_VERSION);
mark(fatal_error);
return;
}
GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",LIBRARY_VERSION);
if(!GfxBase)
{ inform_user(err_msg[language][1],LIBRARY_VERSION);
mark(fatal_error);
return;
}
/* init gadgets and menu */
{ int i;
init_DFxInfo(); /* get drive information */
/*
* I will use the unit counter `i' here instead of extracting
* the unit number from the text of the drive gadget. I think
* there is no need to do so, since I don't want to change the
* sequence DF0: DF1: DF2: DF3:
* If you want to do so then don't forget to change this in
* handle_gadget() also and simply replace check_DFxInfo(i) by
* check_DFxInfo(drive_gadget[i].GadgetText->IText[2]-'0'
*/
for(i=0;i<4;i++)
{ if(check_DFxInfo(i))
{ drive_gadget[i].Flags |= GADGDISABLED;
Items[language][15+i].Flags &= ~ITEMENABLED;
}
else if(i==unit_r || i==unit_c)
{ drive_gadget[i].Flags |= SELECTED;
Items[language][15+i].Flags |= CHECKED; /* DF0: ... DF3: */
}
}
}
if(deep_read)
{ hook_gadget.Flags |= SELECTED;
Items[language][9].Flags |= CHECKED; /* Verify tracks */
}
if(write_icon) Items[language][3].Flags |= CHECKED; /* Create logfile icon */
if(ignore_errors) Items[language][10].Flags |= CHECKED; /* Ignore errors */
/* the ibox letter will be updated further down... */
NewWindow.Title= rcs_id;
/*
* added on Thu Dec 10 03:10:53 1992, modified Sat Jan 23 13:04:50 1993
* The window size had initially been written for the 1.3 default values
* of Window->BorderLeft = 4,
* Window->BorderRight = 4,
* Window->BorderTop = 11 and
* Window->BorderBottom = 2
* So we have to adjust the width by the current l+r values - (4+4)
* and the height by the current t+b values - (8+2+1)
*/
{ struct Screen scr;
if(GetScreenData(&scr,sizeof(struct Screen),WBENCHSCREEN,NULL))
{ int hc= scr.WBorLeft + scr.WBorRight,
vc= scr.WBorTop + scr.WBorBottom + (scr.Font)->ta_YSize +1;
/* The title bar height of a window is calculated from the
* screen's WBorTop field, plus the font height, plus one
*/
NewWindow.Width += hc - 8; /* horizontal correction */
NewWindow.Height+= vc - 13; /* vertical correction */
if(Window=(struct Window *)NiceOpenWindow(&NewWindow))
{ hc= Window->BorderLeft + Window->BorderRight - hc;
vc= Window->BorderTop + Window->BorderBottom - vc;
/* Just to be sure having got the correct size: */
if(hc||vc)
{ BOOL done= FALSE; /* dcmp is waiting for a NEWSIZE message */
SizeWindow(Window, hc,vc);
while(!done)
{ Wait(1L<<Window->UserPort->mp_SigBit);
while(imsg=(struct IntuiMessage *)GetMsg(Window->UserPort))
{ done |= (imsg->Class == NEWSIZE);
ReplyMsg(imsg);
}
}
RefreshGadgets(Window->FirstGadget, Window, NULL);
RefreshWindowFrame(Window);
}
}
}
}
if(!Window)
{ inform_user(err_msg[language][2]);
mark(fatal_error);
return;
}
MenuFlag= SetMenuStrip(Window, MenuStrip[language]);
if(!MenuFlag) inform_user(err_msg[language][3]);
SaveMouseColors(Window); /* They might change with the pointer... */
SetMouseImage(Window, dcmp_pointer);
rp= Window->RPort;
TextFont=(struct TextFont *)OpenFont(&TextAttr);
if(!TextFont)
{ inform_user(err_msg[language][4],TextAttr.ta_Name,TextAttr.ta_YSize);
mark(fatal_error);
return;
}
SetFont(rp,TextFont);
new_trackframes();
draw_3dgb(rp, NewWindow.FirstGadget); /* We *must* use the NewWindow's GList
* here because we do not want to
* redraw the window's system gadgets...
*/
draw_3d(rp, INFOBOX_X,INFOBOX_Y,INFOBOX_W,INFOBOX_H, -1, POS_3D);
PrintIText(rp, &info_text[0], INFOBOX_X,INFOBOX_Y);
set_iboxval(start_blk / BLOCKS_PER_CYLINDER,
end_blk / BLOCKS_PER_CYLINDER,
attempts,
0, /* 0 => update `/i' or `/b' */
0 );
SetAPen(rp,DEFAULT_PEN);
draw_box(rp, EQUALBOX_X, EQDIFFBOX_Y,TRACKBOX_W+1,TRACKBOX_H,EQUAL_PEN);
draw_box(rp, DIFFERBOX_X,EQDIFFBOX_Y,TRACKBOX_W+1,TRACKBOX_H,DIFFER_PEN);
Window->Flags &= ~RMBTRAP; /* is this allowed ? */
ReqToolsBase=(struct ReqToolsBase *)OpenLibrary("reqtools.library", 37L);
if (!ReqToolsBase)
{ ReqBase=(struct ReqBase *)OpenLibrary("req.library",REQVERSION);
{ if(ReqBase)
{ MyProcess=(struct Process *)FindTask((char *)0L);
OldWindowPtr=MyProcess->pr_WindowPtr;
MyProcess->pr_WindowPtr=(APTR)Window;
}
}
}
if(dos_rkcvinit()) mark(error_state);
}
/*
* hide/show the logfile path
*
* I've slightly modified this code on Wed Oct 7 11:01:03 1992 to work with
* Kickstat V36+. It seems as if StringInfo.DispPos is ignored now... ?!
* So instead of scrolling the gadget contents I decided to copy the visible part
* of the filename into an `overlay_buffer' and display this buffer if the
* gadget is not active. If it is active, I'll re-link the logfile_name[].
*/
void hide_path()
{ char *s= string_info.Buffer;
static char overlay_buffer[26]; /* 24(25) visible characters */
int i=0, k=0;
SHORT pos= RemoveGadget(Window, &string_gadget);
while(s[i++])
if(s[i]=='/'||s[i]==':') k= i+1;
/*
* This is what we did under versions of Kickstart 1.3:
*
* string_info.DispPos= k;
* string_info.BufferPos= k;
*/
strncpy(overlay_buffer, &s[k], 25); /* now we have to copy the visible part */
overlay_buffer[25]= '\0'; /* string MUST (!) be null-terminated... */
string_info.Buffer= &overlay_buffer[0]; /* link our static buffer */
string_info.DispPos= 0; /* scroll to the first character */
string_info.BufferPos= 0; /* Kick 1.3 does NOT ignore this ! */
RefreshGList(&string_gadget, Window, NULL, 1L);
if(pos>=0) /* => we really removed the string_gadget */
AddGadget(Window, &overlay_gadget, pos);
/*Window->Flags &= ~RMBTRAP;*/ /* enable menu selections */
}
void show_path()
{ SHORT pos= RemoveGadget(Window, &overlay_gadget);
/*Window->Flags |= RMBTRAP;*/ /* disable menu selections */
string_info.DispPos= 0;
string_info.BufferPos= 0;
string_info.Buffer= logfile_name; /* re-link old string buffer */
RefreshGList(&string_gadget,Window, NULL, 1L);
if(pos>=0) /* => we really removed the overlay_gadget */
AddGadget(Window, &string_gadget, pos);
ActivateGadget(&string_gadget, Window, NULL);
while(imsg=(struct IntuiMessage *)GetMsg(Window->UserPort))
ReplyMsg(imsg); /* forget the waiting messages... */
}
/*
* Set the menu's CHECKED marks according to the global settings
*/
void update_menu()
{ int i;
if(write_icon) Items[language][3].Flags |= CHECKED;
else Items[language][3].Flags &= ~CHECKED;
if(deep_read) Items[language][9].Flags |= CHECKED;
else Items[language][9].Flags &= ~CHECKED;
if(ignore_errors) Items[language][10].Flags |= CHECKED;
else Items[language][10].Flags &= ~CHECKED;
for(i=0; i<4; i++)
{ if(!(drive_gadget[i].Flags & GADGDISABLED))
{ Items[language][15+i].Flags |= ITEMENABLED;
if((drive_gadget[i].Flags & SELECTED) == SELECTED)
Items[language][15+i].Flags |= CHECKED;
else Items[language][15+i].Flags &= ~CHECKED;
}
else Items[language][15+i].Flags &= ~ITEMENABLED;
}
for(i=0; i<5; i++) Items[language][29+i].Flags &= ~CHECKED;
Items[language][29+language].Flags |= CHECKED;
}
/*
* Refresh the dcmp device list and update the gadgets and menu items
*
* Note: There seems to be a bug in OffGadget() that makes the background
* of an active TOGGLESELECT boolean gadget disappear...
* This stuff will ghost the drive gadgets propperly
*/
void refresh_devicelist()
{ int i;
init_DFxInfo(); /* get drive information */
for(i=0; i<4; i++)
{ if(!check_DFxInfo(i))
{ on_3dg(&drive_gadget[i], Window);
Items[language][15+i].Flags |= ITEMENABLED;
}
else
{ set_gflags(&drive_gadget[i],Window,drive_gadget[i].Flags | GADGDISABLED);
Items[language][15+i].Flags &= ~ITEMENABLED;
}
}
}
void handle_gadget(struct Gadget *gadget)
{ static char *local_msg[][]= {
{ "Select a Logfile...", /* 0 */
"Too many drives specified.", "I see", /* 1,2 */
"No drive(s) specified.", "Continue", /* 3,4 */
},
{ "LogFile auswählen...",
"Sie haben zu viele Laufwerke ausgewählt!", "Stimmt",
"Wie, kein Laufwerk?!", "Oh!",
},
{ "Choisir LogFile...",
"Vous avez choisi trop de drives!", "Ça alors",
"Comment? Pas des drives?!", "Pardon",
},
{ "Scegliere LogFile...",
"Avete scelto troppi Floppies!", "Sì",
"Come, nessun Floppy?!", "Oh!",
},
};
if(gadget)
{ switch(gadget->GadgetID)
{ case LOGFILE_ID:
a_FileRequester(logfile_name, local_msg[language][0]);
strcpy(string_info.Buffer, logfile_name);
hide_path();
break;
case STRING_ID:
hide_path();
break;
case HOOK_ID:
deep_read= ((hook_gadget.Flags & SELECTED) == SELECTED);
case DRIVE0_ID: case DRIVE1_ID: case DRIVE2_ID: case DRIVE3_ID:
update_menu();
break;
case BEGIN_ID:
unit_r= unit_c= NOUNIT; /* reset units to `not specified' */
{ int i;
/*
* Here is where the counter i and the unit numbers on the
* gadgets must be equal... ( see open_window_stuff() )
*/
for(i=0;i<4 && !danger;i++)
{ if((drive_gadget[i].Flags & SELECTED) == SELECTED)
{ if(unit_r == NOUNIT) unit_r=i; /* get first unit */
else if(unit_c == NOUNIT) unit_c=i; /* get second unit */
else
{ a_Requester(local_msg[language][1],local_msg[language][2],NULL);
mark(error_state);
}
}
}
if(unit_r == NOUNIT && unit_c == NOUNIT)
{ a_Requester(local_msg[language][3],local_msg[language][4],NULL);
mark(error_state);
}
else if(unit_c == NOUNIT)
unit_c= unit_r; /* one unit -> verify disk */
}
write_logfile= (strlen(logfile_name) > 0);
if(!danger)
{ int i;
SHORT pos= RemoveGadget(Window, &begin_gadget);
begin_gadget.GadgetText= &gadget_text[7]; /* Stop! */
AddGadget(Window, &begin_gadget, pos);
RefreshGList(&begin_gadget, Window, NULL, 1L);
off_3dg(&hook_gadget, Window);
off_3dg(&logfile_gadget, Window);
off_3dg(&string_gadget, Window);
OffGadget(&overlay_gadget, Window, NULL);
/*
* I had a problem ghosting my drive gadgets via OffGadget()
* since it made the background color of the active TOGGLESELECT
* gadget disappear...
*/
for(i=0;i<4;i++)
{ if(!(drive_gadget[i].Flags & GADGDISABLED))
set_gflags(&drive_gadget[i],Window,
drive_gadget[i].Flags | GADGDISABLED);
}
Window->Flags |= RMBTRAP;
SetMouseImage(Window, busybee);
new_trackframes();
do_dcmp_stuff(); /* now go ! */
SetMouseImage(Window, dcmp_pointer);
Window->Flags &= ~RMBTRAP;
refresh_devicelist(); /* turn on drive gadgets */
OnGadget(&overlay_gadget, Window, NULL);
on_3dg(&string_gadget, Window);
on_3dg(&logfile_gadget, Window);
on_3dg(&hook_gadget, Window);
pos= RemoveGadget(Window, &begin_gadget);
begin_gadget.GadgetText= &gadget_text[1]; /* Begin Operation */
AddGadget(Window, &begin_gadget, pos);
RefreshGList(&begin_gadget, Window, NULL, 1L);
}
break;
}
}
}
/*
* Here we handle the RAWKEY events. A rawkey conversion has to be done
* before calling this procedure.
*/
void handle_keystroke(char key)
{ static char *local_msg[][]= {
{ "First Cylinder:", /* 0 */
"Illegal First Cylinder: %ld\n" /* 1 */
"#Cylinder sould be in [0..79]",
"Fine", /* 2 */
"Last Cylinder:", /* 3 */
"Illegal Last Cylinder: %ld\n" /* 4 */
"#Cylinder sould be in[0..79]",
"Ooops!", /* 5 */
"#of Attempts:", /* 6 */
"Illegal #of attempts: %ld\n" /* 7 */
"I think %ld attempts make noise enough!",
"So it is", /* 8 */
"No attempts means no reading.\n" /* 9 */
"Maybe the closing gadget can satisfy you?",
"Hmmm...", /* 10 */
"Illegal #of attempts: %ld\n" /* 11 */
"Think positive, try one of [1..%ld]",
"I will" /* 12 */
},
{ "Erster Cylinder:",
"Na nu? Den Cylinder %ld gibt es ja gar nicht!\n"
"Ihr Laufwerk kennt nur die Cylinder zwischen 0 und 79!",
"Ach so",
"Letzter Cylinder:",
"Ich kann doch nicht mit dem Cylinder %ld aufhören!\n"
"Es gibt nur die Cylinder von 0 bis 79!",
"Hoppla!",
"Leseversuche:",
"%ld Leseversuche sind zu viel!\n"
"Mit %ld Versuchen macht Ihr Laufwerk genug Krach!",
"Stimmt",
"Wenn sie mich nicht lesen lassen wollen,\n"
"sollten Sie vielleicht besser das Programm verlassen?",
"Ne, ne",
"Wie? %ld Leseversuche?\n"
"Wie wäre es mit einer Zahl zwischen 1 und %ld?",
"Tschuldigung"
},
{ "Premièr cylindre:",
"Ça alors, Le cylindre %ld n'existe pas!\n"
"Votre floppy ne connaît que des cylindres entre 0 et 79!",
"Bien",
"Dernier cylindre:",
"Je ne peux pas finir avec le cylindre %ld!\n"
"Il n'y a que les cylindres entre 0 et 79!",
"Olàlà!",
"#des essaies:",
"Trop d'essaies: %ld!\n"
"Avec %ld essaies votre floppy fait assez de bruit!",
"Croissant",
"Si vous ne voulez pas me laisser lire,\n"
"c'est peut-être mieux de quitter le programme?",
"Non, non",
"Quoi? %ld essaies?\n"
"Choisissez un numéro entre 1 et %ld?",
"Pardon"
},
{ "Primo cilindro:",
"Primo cilindro illegale: %ld\n"
"#Cilindro dovrebbe essere in [0..79]",
"Bene",
"Ultimo cilindro:",
"Ultimo cilindro illegale: %ld\n"
"#Cilindro dovrebbe essere in [0..79]",
"Oooh!",
"Tentativi di lettura:",
"# dei tentativi illegale: %ld\n"
"Penso che %ld fanno abbastamza rumore!",
"È proprio così!",
"Niente tentativi, niente lettura.\n"
"Vorreste forse uscire dal programma?",
"Hmmm...",
"# dei tentativi illegale: %ld\n"
"Siate ottimisti, provate uno di [1..%ld]",
"Lo saro"
}
};
switch(key)
{ case 'f': case 'F':
handle_gadget(&logfile_gadget);
break;
case 't': case 'T':
strcpy(logfile_name, DEF_LOGFILE);
show_path();
break;
case 'l': case 'L':
show_path();
break;
case 'b': case 'B': case 'g': case 'G':
handle_gadget(&begin_gadget);
break;
case 'q': case 'Q': case 'x': case 'X': case '\33': /* ESC */
mark(depart);
break;
case 'r': case 'R': case 'i': case 'I':
ignore_errors= !ignore_errors;
set_iboxval(-1,-1,-1,0,-1);
break;
case 'v': case 'V': case 'w': case 'W':
set_gflags(&hook_gadget, Window, hook_gadget.Flags ^ SELECTED);
deep_read= ((hook_gadget.Flags & SELECTED) == SELECTED);
break;
case '0': case '1': case '2': case '3':
{ int i= key-'0';
if(!(drive_gadget[i].Flags & GADGDISABLED))
set_gflags(&drive_gadget[i], Window, drive_gadget[i].Flags ^ SELECTED);
}
break;
case 's': case 'S':
{ long scyl; /* start cylinder */
do
{ scyl= start_blk/BLOCKS_PER_CYLINDER;
if(a_GetLongRequester(&scyl,local_msg[language][0],0L,79L))
{ if(0>scyl || scyl>79)
{ char response[256];
sprintf(response,local_msg[language][1],scyl);
a_Requester(response,local_msg[language][2],NULL);
}
else
{ start_blk= scyl * BLOCKS_PER_CYLINDER;
set_iboxval(scyl, -1, -1, -1, -1);
}
}
} while(0>scyl || scyl>79);
}
break;
case 'e': case 'E':
{ long ecyl; /* last cylinder */
do
{ ecyl= end_blk/BLOCKS_PER_CYLINDER;
if(a_GetLongRequester(&ecyl,local_msg[language][3],0L,79L))
{ if(0>ecyl || ecyl>79)
{ char response[256];
sprintf(response,local_msg[language][4],ecyl);
a_Requester(response,local_msg[language][5],NULL);
}
else
{ end_blk= (ecyl+1) * BLOCKS_PER_CYLINDER -1;
/* include the last SEC of this CYL */
set_iboxval(-1, ecyl, -1, -1, -1);
}
}
} while(0>ecyl || ecyl>79);
}
break;
case 'a': case 'A':
{ long atps;
do
{ atps= attempts;
if(a_GetLongRequester(&atps,local_msg[language][6],1L,MAX_ATTEMPTS))
{ char response[256];
if(atps>MAX_ATTEMPTS)
{ sprintf(response,local_msg[language][7],atps,MAX_ATTEMPTS);
a_Requester(response,local_msg[language][8],NULL);
}
else if(atps == 0)
{ sprintf(response,local_msg[language][9]);
a_Requester(response,local_msg[language][10],NULL);
}
else if(atps<0)
{ sprintf(response,local_msg[language][11],atps,MAX_ATTEMPTS);
a_Requester(response,local_msg[language][12],NULL);
}
else
{ attempts= atps;
set_iboxval(-1, -1, atps, -1, -1);
}
}
} while(1>atps || atps>MAX_ATTEMPTS);
}
break;
case '?': case '_': /* underscore == ? on the US keymap */
about();
break;
case 'd': case 'D': case ' ':
refresh_devicelist(); /* refresh dcmp device list via init_DFxInfo()
* and update the menu and gadgets
*/
break;
case 'h': case 'H':
dcmp_Request("You will have to register to use this function.",
"Fuck it!", "I will");
break;
case 'p':
FlipPointerX(Window);
break;
case 'P':
FlipPointerY(Window);
break;
case 'c': case 'C':
FlipPointerZ(Window);
break;
default:
DisplayBeep(Window->WScreen);
break;
}
}
/*
* Here the MENUPICK messages are handled. All selections in the menu
* are passed over to handle_keystroke(). If a MENUTOGGLE Item was changed
* we have to do a post processing to update the gadgets.
*/
void handle_menu(USHORT num)
{ struct MenuItem *item;
BOOL update= FALSE;
while(num != MENUNULL)
{ struct MenuItem *item= (struct MenuItem *)ItemAddress(MenuStrip[language], num);
USHORT menunum= MENUNUM(num),
itemnum= ITEMNUM(num),
subnum= SUBNUM(num);
switch(menunum)
{ case 0: /* Project */
switch(itemnum)
{ case 0: /* About */
handle_keystroke('?');
break;
case 2: /* Select Logfile */
handle_keystroke('f');
break;
case 3: /* Create logfile icon */
update= TRUE;
break;
case 5: /* Set first cylinder */
handle_keystroke('s');
break;
case 6: /* Set last cylinder */
handle_keystroke('e');
break;
case 7: /* Set #of attempts */
handle_keystroke('a');
break;
case 9: case 10: /* Verify tracks, Ignore Errors */
update= TRUE;
break;
case 12: /* Refresh device list */
handle_keystroke('d');
break;
case 14: /* Quit */
handle_keystroke('q');
break;
}
break;
case 1: /* Drives */
switch(itemnum)
{ case 0: case 1: case 2: case 3:
update= TRUE;
break;
}
break;
case 2: /* Information */
switch(itemnum)
{ case 4: /* Copyright */
dcmp_Request(info_msg[language][INFO_COPYRIGHT],
info_msg[language][INFO_COPYRIGHT+1],
info_msg[language][INFO_COPYRIGHT+2] );
break;
case 5: /* Distribution */
dcmp_Request(info_msg[language][INFO_DISTRIBUTION],
info_msg[language][INFO_DISTRIBUTION+1],
info_msg[language][INFO_DISTRIBUTION+2] );
break;
case 6: /* Credits */
switch(subnum)
{ case 0:
dcmp_Request(info_msg[language][INFO_IDEAS],
info_msg[language][INFO_IDEAS+1],
info_msg[language][INFO_IDEAS+2] );
break;
case 1:
dcmp_Request(info_msg[language][INFO_LIBRARIES],
info_msg[language][INFO_LIBRARIES+1],
info_msg[language][INFO_LIBRARIES+2] );
break;
case 2:
dcmp_Request(info_msg[language][INFO_COMPILER],
info_msg[language][INFO_COMPILER+1],
info_msg[language][INFO_COMPILER+2] );
break;
case 3:
dcmp_Request(info_msg[language][INFO_SUPPORT],
info_msg[language][INFO_SUPPORT+1],
info_msg[language][INFO_SUPPORT+2] );
break;
case 4:
dcmp_Request(info_msg[language][INFO_LANGUAGE],
info_msg[language][INFO_LANGUAGE+1],
info_msg[language][INFO_LANGUAGE+2] );
break;
case 5:
dcmp_Request(info_msg[language][INFO_TESTING],
info_msg[language][INFO_TESTING+1],
info_msg[language][INFO_TESTING+2] );
break;
}
break;
case 7: /* Versions */
dcmp_Request(info_msg[language][INFO_VERSIONS],
info_msg[language][INFO_VERSIONS+1],
info_msg[language][INFO_VERSIONS+2] );
break;
}
break;
case 3: /* Language */
update= TRUE;
break;
}
/*
printf("MENUNUM= %ld, ITEMNUM= %ld, SUBNUM= %ld\n",
MENUNUM(num), ITEMNUM(num), SUBNUM(num) );
printf("language= %ld\n",language);
*/
if(item->NextSelect != num)
num= item->NextSelect;
else num= MENUNULL;
}
/*
* Here we perform a post work on the CHECKED marks of the menu.
* We have to do so, because the `NextSelect' entry point in the
* MenuItem structure is not allowed to be equal to it's own ITEMNUM.
* (If it were, collecting the MENUPICK messages could become non-
* deterministic!)
*/
if(update) /* update settings according to the menu's CHECKED marks */
{ int i;
write_icon= ((Items[language][3].Flags & CHECKED) == CHECKED); /* no gadget for it */
deep_read= ((Items[language][9].Flags & CHECKED) == CHECKED);
set_gflags(&hook_gadget, Window,
deep_read ? (hook_gadget.Flags | SELECTED):
(hook_gadget.Flags & ~SELECTED) );
ignore_errors= ((Items[language][10].Flags & CHECKED) == CHECKED);
set_iboxval(-1, -1, -1, 0, -1); /* update `ignore errors' */
for(i=0; i<4; i++)
{ if(!(drive_gadget[i].Flags & GADGDISABLED)) /* => gadget NOT ghosted */
{ set_gflags(&drive_gadget[i], Window,
(Items[language][15+i].Flags & CHECKED)?(drive_gadget[i].Flags | SELECTED)
:(drive_gadget[i].Flags & ~SELECTED) );
}
}
for(i=0; i<5; i++)
{ if( ((Items[language][29+i].Flags & ITEMENABLED) == ITEMENABLED)
&& ((Items[language][29+i].Flags & CHECKED) == CHECKED) )
{ if (i != language)
{ language= i;
ClearMenuStrip(Window);
SetMenuStrip(Window, MenuStrip[language]);
update_menu();
}
}
}
}
}
void handle_window_stuff(void)
{ ULONG class;
USHORT code,qual;
APTR address;
hide_path();
while(!lental)
{ mark(well_done); /* loop as long as nothing lental happens */
Wait(1L<<Window->UserPort->mp_SigBit);
while(imsg=(struct IntuiMessage *)GetMsg(Window->UserPort))
{ class = imsg->Class;
code = imsg->Code;
qual = imsg->Qualifier;
address = imsg->IAddress;
ReplyMsg(imsg);
switch(class)
{ case CLOSEWINDOW:
mark(depart);
break;
case GADGETUP:
handle_gadget((struct Gadget *)address);
break;
case GADGETDOWN:
{ struct Gadget *gadget= (struct Gadget *)address;
if(gadget->GadgetID == OVERLAY_ID)
show_path();
else if(gadget->GadgetID!=STRING_ID)
hide_path();
break;
}
case MOUSEBUTTONS:
hide_path();
break;
case RAWKEY:
{ char buf[10];
if(code==95) /* rawkey code HELP */
handle_keystroke('h');
else if(dos_rkcv((int)code, (int)qual, &buf[0], 10))
handle_keystroke(buf[0]);
update_menu();
break;
}
case MENUPICK:
handle_menu(code);
break;
}
}
}
}
write_statistics(FILE *out, int full)
{ static char *local_msg[][]= {
{ "** Operation terminated abnormally!\n" /* 0 */
"result (so far): ",
"Verify", "error", "okay", /* 1,2,3 */
"total: ", /* 4 */
"track differs on", "tracks differ on", /* 5,6 */
"block", "blocks", /* 7,8 */
"no", "error", "errors", /* 9, 10, 11 */
", no ", "weak track", "weak tracks", /* 12, 13, 14 */
"found", /* 15 */
"Here is the complete list of differing blocks:", /* 16 */
" %4ld: Track #%03ld, Sector #%02ld\n", /* 17 */
"%4ld..%04ld: Track #%03ld, Sector #%02ld -- Track #%03ld, Sector #%02ld\n",
},
{ "*** Operation abgebrochen!\n"
"Bisher: ",
"Überprüfung", "negativ", "positiv",
"Insgesamt: ",
"unterschiedlicher Track auf",
"unterschiedliche Tracks auf",
"Block", "Blöcken",
"kein", "Fehler", "Fehler",
", keine ", "Weak-Track", "Weak-Tracks",
"gefunden",
"Hier ist die vollständige Liste der unterschiedlichen Blocks:",
" %4ld: Track #%03ld, Sektor #%02ld\n",
"%4ld..%04ld: Track #%03ld, Sektor #%02ld bis Track #%03ld, Sektor #%02ld\n",
},
{ "*** Opération interrompue!\n"
"Jusqu'à maintenant: ",
"Vérification", "negatif", "positif",
"Complètement: ",
"différent track sur",
"différents tracks sur",
"bloc", "blocs",
"pas", "d'erreur", "d'erreurs",
", pas de ", "Weak-Track", "Weak-Tracks",
"trouvés",
"Voilà la liste complète des blocs différents:",
" %4ld: track #%03ld, sector #%02ld\n",
"%4ld..%04ld: track #%03ld, sector #%02ld à track #%03ld, sector #%02ld\n",
},
{ "*** Operazione interrotta!\n"
"Fin adesso: ",
"Verificazione", "negativo", "positivo",
"Totale: ",
"Traccia differente su",
"Tracce differenti su",
"Blocco", "Blocchi",
"nessun", "errore", "errori",
", nessuni ", "Weak-Track", "Weak-Tracks",
"trovati", /* trovati ist plural, trovato ist 1zahl */
"Qui è la lista completa dei blocchi differenti:",
" %4ld: traccia #%03ld, settore #%02ld\n",
"%4ld..%04ld: traccia #%03ld, settore #%02ld -- traccia #%03ld, settore #%02ld\n",
},
};
if(danger) fprintf(out,local_msg[language][0]);
else
{ if(unit_r == unit_c)
{ fprintf(out,"%s %s: ",local_msg[language][1],
(wtrk>0 || errcnt>0)?(local_msg[language][2])
:(local_msg[language][3]) );
}
else fprintf(out,local_msg[language][4]);
}
if(unit_r != unit_c)
{ fprintf(out,"%ld %s %ld %s, ",dtrk,
(dtrk==1)?(local_msg[language][5])
:(local_msg[language][6]),
dblk,
(dblk==1)?(local_msg[language][7])
:(local_msg[language][8]) );
}
if(errcnt==0) fprintf(out,local_msg[language][9]); /* no */
else fprintf(out,"%ld",errcnt);
/*
* If we are taking italian, we say `nessun errore' instead of `nessuni errori'
*/
if(language==3)
{ fprintf(out," %s",(errcnt<=1)?(local_msg[3][10]) /* errore */
:(local_msg[3][11]) ); /* errori */
}
else
{ fprintf(out," %s",(errcnt==1)?(local_msg[language][10])
:(local_msg[language][11]) );
}
if(deep_read)
{ if(wtrk==0) fprintf(out,local_msg[language][12]);
else fprintf(out,", %ld ",wtrk);
fprintf(out, "%s.\n",(wtrk==1)?(local_msg[language][13])
:(local_msg[language][14]) );
}
else fprintf(out," %s.\n",local_msg[language][15]);
/* dblk can only be >0 if unit_r != unit_c... so: */
if(dblk>0 && full)
{ int s,e=0;
fprintf(out,"\n%s\n\n",local_msg[language][16]);
while(dblk_list[e]>=0 && e<=1759)
{ for(s=e;dblk_list[e]==dblk_list[e+1]-1 && e<=1759;e++)
;
if(s==e)
{ fprintf(out,local_msg[language][17], dblk_list[e],
dblk_list[e]/BLOCKS_PER_TRACK,
dblk_list[e]%BLOCKS_PER_TRACK);
}
else
{ fprintf(out,local_msg[language][18], dblk_list[s],
dblk_list[e],
dblk_list[s]/BLOCKS_PER_TRACK,
dblk_list[s]%BLOCKS_PER_TRACK,
dblk_list[e]/BLOCKS_PER_TRACK,
dblk_list[e]%BLOCKS_PER_TRACK);
}
e++;
}
}
}
/*
* open_logfile() opens the file `logfile_name'. If it already exists
* new data will be `a'ppended, otherwise a ne`w' file will be [created].
*/
#include <time.h>
void open_logfile()
{ static char *local_msg[][]= {
{ "created", /* 0 */
"This is %s\n", /* 1 */
"Verifying drive DF%ld: (%s)\n", /* 2 */
"deeply", "quickly", /* 3,4 */
"Compare drive DF%ld: with DF%ld:%s", /* 5 */
" w/ deep read\n", "\n", /* 6,7 */
"Warning: Not enough memory for weak data detection. Option ignored.\n",
"> Start: Track #%ld, Sector #%ld, Block #%ld\n", /* 9 */
"> End: Track #%ld, Sector #%ld, Block #%ld\n", /* 10 */
"Unable to open logfile.", /* 11 */
"No icon.library - Sorry, no icon" /* 12 */
},
{ "erstellt",
"LogFile von %s\n",
"Disk im Laufwerk %ld wird %s überprüft\n",
"genau", "gelesen und",
"Disk Vergleich DF%ld: mit DF%ld:%s",
" (mit Überprüfung)\n", "\n",
"Achtung: Nicht genug Speicher für die Überprüfung! Parameter ignoriert.\n",
"> Start: Track #%ld, Sektor #%ld, Block #%ld\n",
"> Ende: Track #%ld, Sektor #%ld, Block #%ld\n",
"Das LogFile konnte nicht geöffnet werden!",
"Keine Icon.library - Sorry, kein Icon"
},
{ "créé",
"LogFile de %s\n",
"Disque en floppy %ld est vérifié %s\n",
"exactement", "en lisant",
"Comparaisant les disques DF%ld: avec DF%ld:%s",
" (avec mit vérification)\n", "\n",
"Attention: Pas assez de memoire! Paramètre -v ignoré.\n",
"> Départ: track #%ld, sector #%ld, bloc #%ld\n",
"> Fin: track #%ld, sector #%ld, bloc #%ld\n",
"Le LogFile ne pouvait pas être ouvert!",
"Il n'y a pas d'icon.library - malheureusement pas d'icon"
},
{ "creato",
"Questo è il LogFile di %s\n",
"Disco nel floppy %ld viene letto %s\n",
"scrupolosamente", "ed verificato",
"Comparazione disco DF%ld: con DF%ld:%s",
" (riesaminando)\n", "\n",
"Attenzione: Non c'è abbastanza memoria disponibile per la verifica! Parameter ignorato.\n",
"> Inizio: traccia #%ld, settore #%ld, blocco #%ld\n",
"> Fine: traccia #%ld, settore #%ld, blocco #%ld\n",
"Il LogFile non poteva essere aperto!",
"Non c'è una Icon.library - Mi dispiace, nessuna icona"
}
};
if(write_icon)
{ IconBase= (struct IconBase *)OpenLibrary(ICONNAME,LIBRARY_VERSION);
if(IconBase)
{ PutDiskObject(logfile_name, &LogIcon);
CloseLibrary(IconBase);
}
else inform_user(local_msg[language][12]);
}
if(fp=fopen(logfile_name,"r")) /* check if logfile already exists */
{ fclose(fp);
if(fopen(logfile_name,"a")) /* reopen logfile for append */
{ long t;
time(&t); /* get #of seconds since 00:00:00 GMT Jan 1,1970 */
fprintf(fp,"\n@ %s\n",ctime(&t));
logdata_added= TRUE;
}
}
else /* file does *NOT* exist yet */
{ if(fp=fopen(logfile_name,"w")) /* create new file */
{ if(!be_quiet)
printf(" %s [%s]\n",logfile_name,local_msg[language][0]);
}
}
if(fp) /* okay, we opened this file somehow... */
{ write_logfile= TRUE;
fprintf(fp,local_msg[language][1],rcs_id);
if(unit_r == unit_c)
{ fprintf(fp,local_msg[language][2],unit_r,
(deep_read && deep_buffer)?(local_msg[language][3])
:(local_msg[language][4]) );
}
else
{ fprintf(fp,local_msg[language][5],unit_r,unit_c,
(deep_read && deep_buffer)?(local_msg[language][6])
:(local_msg[language][7]) );
}
if(deep_read &! deep_buffer) fprintf(fp,local_msg[language][8]);
fprintf(fp,local_msg[language][9], start_blk/BLOCKS_PER_TRACK,
start_blk%BLOCKS_PER_TRACK, start_blk);
fprintf(fp,local_msg[language][10],end_blk/BLOCKS_PER_TRACK,
end_blk%BLOCKS_PER_TRACK, end_blk);
}
else
{ inform_user(local_msg[language][11]);
write_logfile= FALSE;
mark(warning);
}
}
#define PORTNAME_R "dcmp_read.port"
#define PORTNAME_C "dcmp_compare.port"
#define PORTNAME_V "dcmp_verify.port"
/*
* open_dcmp_stuff() checks and opens the drive unit(s).
* returns FALSE in case of an error.
*/
int open_dcmp_stuff(void)
{ long err;
static char *local_msg[][]= {
{ "DF%ld: %s.", /* 0 */
"%s. Can't access DF%ld:", /* 1 */
"No disk present in unit %ld.", /* 2 */
"Not enough memory for weak data detection!", /* 3 */
},
{ "Laufwerk DF%ld: %s.",
"%s. Laufwerk %ld nicht ansprechbar!",
"Die Disk fehlt im Laufwerk %ld.",
"Zu wenig Speicher für die Überprüfung!",
},
{ "Floppy DF%ld: %s.",
"%s. Floppy %ld inaccessable!",
"Pas de disque en floppy %ld.",
"Pas assez de memorie pour la vérification!",
},
{ "DF%ld: %s.",
"%s. Floppy %ld non accesìbile!",
"Nel floppy %ld manca il disco.",
"Troppo poca memoria disponibile per la verifica!",
},
};
init_DFxInfo(); /* get drive information */
/* open unit_r */
if(err= check_DFxInfo(unit_r))
{ inform_user(local_msg[language][0], unit_r, dfxerr[language][err]);
return(FALSE);
}
if(unit_r != unit_c)
err= open_unit(unit_r,PORTNAME_R, BYTES_PER_TRACK);
else
err= open_unit(unit_r,PORTNAME_V, BYTES_PER_TRACK);
if(err)
{ inform_user(local_msg[language][1],ouerr[language][err],unit_r);
return(FALSE);
}
if(disk_state(unit_r) <= 0)
{ inform_user(local_msg[language][2],unit_r);
close_unit(unit_r);
return(FALSE);
}
/* open unit_c */
if(unit_r != unit_c)
{ if(err= check_DFxInfo(unit_c))
{ inform_user(local_msg[language][0], unit_c, dfxerr[language][err]);
close_unit(unit_r);
return(FALSE);
}
if(err= open_unit(unit_c, PORTNAME_C, BYTES_PER_TRACK))
{ inform_user(local_msg[language][1],ouerr[language][err],unit_c);
close_unit(unit_r);
return(FALSE);
}
if(disk_state(unit_c) <= 0)
{ inform_user(local_msg[language][2],unit_c);
close_dcmp_stuff();
return(FALSE);
}
}
/* allocate deep_buffer */
if(deep_read)
{ deep_buffer= (ULONG *)AllocMem(BYTES_PER_TRACK, MEMF_CHIP);
if(!deep_buffer)
inform_user(local_msg[language][3]);
}
return(TRUE);
}
/*
* dcmp_read() reads a track and handles the retries and the window stuff.
* If no buffer is given (buffer == NULL), the track will be
* read into DFxInfo[unit].Buffer.
* (-1) will be returned in case of an error.
*/
int dcmp_read(long unit, long trk, ULONG *buffer)
{ int err;
static char *local_msg[][]= {
{ "%s on DF%ld: track %ld, %ld %s failed.", /* 0 */
"Read error", /* 1 */
"attempt", "attempts", /* 2,3 */
"IO Error unit %ld: %s.", /* 4 */
},
{ "%s auf DF%ld: Track %ld, %ld %s fehlgeschlagen.",
"Lesefehler",
"Versuch", "Versuche",
"Ein-/Ausgabe Fehler auf Laufwerk %ld: %s.",
},
{ "%s sur DF%ld: track %ld, %ld %s.",
"Read error",
"essai raté", "essaies ratés",
"I/O Error sur floppy %ld: %s.",
},
{ "%s su DF%ld: traccia %ld, %ld %s.",
"Sbaglio di lettura",
"tentativo fallito", " tentativi falliti",
"IO errore su floppy %ld: %s.",
}
};
ratt=attempts;
if(!buffer) buffer= DFxInfo[unit].Buffer;
do /* the reading */
{ err= td_read(DFxInfo[unit].IOExtTD,
trk * BYTES_PER_TRACK,
BYTES_PER_TRACK,
buffer,
NULL );
if(err!=0) /* handle retries */
{ ratt--;
if(display_window)
set_trackframe(trk,-1,ratt,"e"); /* e == error */
}
} while(err!=0 && ratt>0);
if(err!=0) /* couldn't read this block */
{ char err_msg[128];
errcnt++;
if(err>0)
{ sprintf(err_msg,local_msg[language][0],
(20<=err && err<=35)?(tderr[language][err-20])
:(local_msg[language][1]),
unit,trk, attempts,
(attempts==1)?(local_msg[language][2])
:(local_msg[language][3]) );
}
else /* negative */
{ if(err<(-7)) err= -8; /* less than (-7) not known (yet) */
sprintf(err_msg,local_msg[language][4],unit,ioerr[language][-err]);
}
if(write_logfile && logfile_open)
fprintf(fp,"** %s\n",err_msg);
if(!ignore_errors) inform_user(err_msg);
else if(!be_quiet && !logfile_open)
printf("\r%s\n",err_msg);
return(-1);
} /* else */
return(0);
}
/*
* log_disktype() tries to get information about the disk in the given
* unit and writes them into the logfile.
*/
void log_disktype(unit)
{ static char *local_msg[][]= {
{ " disk in DF%ld:\n", /* 0 */
},
{ " Diskette im DF%ld:\n",
},
{ " disque dans DF%ld:\n",
},
{ " disco in DF%ld:\n",
}
};
if(fp)
{ switch(disk_type(unit))
{ case DRIVE3_5: fprintf(fp,"3.5\" ");
break;
case DRIVE5_25: fprintf(fp,"5.25\" ");
break;
case 3: fprintf(fp,"3.5\" w/ 150 RPM "); /* == DRIVE3_5_150RPM */
break;
}
if(read_block(unit, 0L) == 0)
{ long *t= DFxInfo[unit].Buffer; /* get disk type (dos.h) */
switch(*t)
{ case 'KICK': fprintf(fp,"Kickstart");
break;
case 'DOS\0': fprintf(fp,"DOS");
break;
case 'DOS\1': fprintf(fp,"FFS");
break;
case 'DOS\2': fprintf(fp,"INTER DOS");
break;
case 'DOS\3': fprintf(fp,"INTER FFS");
break;
case 'DOS\4': fprintf(fp,"FASTDIR DOS");
break;
case 'DOS\5': fprintf(fp,"FASTDIR FFS");
break;
case 'NDOS': fprintf(fp,"NDOS (not really DOS)");
break;
case 'MSD\0': fprintf(fp,"MS-DOS");
break;
default: fprintf(fp,"????");
break;
}
}
else fprintf(fp,"????");
fprintf(fp,local_msg[language][0],unit);
}
}
/*
* dcmp_check_brk() returns TRUE in case of a break
*/
BOOL dcmp_check_brk()
{ BOOL brk= FALSE; /* ... we have to collect all the messages */
while(imsg=(struct IntuiMessage *)GetMsg(Window->UserPort))
{ ULONG class = imsg->Class;
USHORT code = imsg->Code;
USHORT qual = imsg->Qualifier;
ReplyMsg(imsg);
switch(class)
{ case CLOSEWINDOW:
mark(depart);
brk= TRUE;
break;
case GADGETUP: /* can only be Stop! */
brk= TRUE;
break;
case RAWKEY:
{ char buf[10];
if(dos_rkcv((int)code,(int)qual, &buf[0], 10))
{ if(buf[0]=='t' || buf[0]=='T' || buf[0]==' ' || buf[0]=='\33')
brk= TRUE;
}
}
break;
}
}
return(brk);
}
/*
* dcmp_cmptrk() compares the two tracks (in buffer a and b) and returns
* TRUE if they are *NOT* equal,
* FALSE if they are equal.
*/
BOOL dcmp_cmptrk(ULONG *a, ULONG *b)
{ int l; /* long counter */
for(l=0; l<(BYTES_PER_TRACK/4); l++)
{ if(a[l] != b[l])
return(TRUE);
}
return(FALSE);
}
/*
* do_dcmp_stuff() (no comment)
*/
do_dcmp_stuff()
{ int st, /* track to start with (first to read) */
et, /* track to end with (last to read) */
so, /* first long to compare (on first track) */
eo, /* last long to compare (on last track) */
diff, /* #of differences on a track */
trk, /* track counter */
err, /* error state */
b; /* general counter */
ULONG *rb, /* read buffer */
*cb; /* compare buffer */
static char *weak_fmt[]=
{ "Warning: Weak data detected on DF%ld: track %ld.",
"Achtung: Schwache Magnetisierung auf DF%ld: Track %ld.",
"Attention: je ne sais pas?! %ld/%ld.",
"Attenzione: magnetizzazione debole su DF%ld: traccia %ld."
};
if(display_window) /* otherwise we already checked it */
{ if(start_blk>end_blk) /* -> swap start/end */
{ b= start_blk;
/* we should start on SEC 00 and end on SEC 10 ... */
start_blk= end_blk - (end_blk % BLOCKS_PER_CYLINDER);
end_blk= b - (b % BLOCKS_PER_CYLINDER)
+ (BLOCKS_PER_CYLINDER - 1);
set_iboxval(start_blk / BLOCKS_PER_CYLINDER,
end_blk / BLOCKS_PER_CYLINDER,
-1, -1, -1);
}
}
/* open drive unit(s) */
if(open_dcmp_stuff() == FALSE)
{ mark(error_state);
return;
}
/* open logfile */
if(write_logfile)
{ open_logfile();
if(logfile_open)
{ log_disktype(unit_r); /* write information about the disk type(s) */
if(unit_r != unit_c)
log_disktype(unit_c);
}
}
init_global_values();
rb= DFxInfo[unit_r].Buffer; /* read buffer */
if(unit_r != unit_c)
cb= DFxInfo[unit_c].Buffer; /* compare buffer */
else cb= (ULONG *)NULL;
st= start_blk/BLOCKS_PER_TRACK;
et= end_blk/BLOCKS_PER_TRACK;
so= (start_blk%BLOCKS_PER_TRACK) * (BYTES_PER_BLOCK/4);
eo= BYTES_PER_TRACK/4;
for(trk=st; trk<=et && !danger; trk++)
{
if(!be_quiet)
{ printf("\r%ld",trk);
fflush(stdout);
}
diff= 0; /* no differences (yet) */
/* read track into DFxInfo[unit_r].Buffer */
if(display_window) set_trackframe(trk,-1,ratt,"r");
err= dcmp_read(unit_r, trk, rb); /* read track into rb */
if(err)
{ if(!ignore_errors)
mark(error_state);
}
/* deep read for unit_r */
else if(deep_read && deep_buffer)
{ if(display_window && (unit_r == unit_c))
set_trackframe(trk,-1,ratt,"v");
do_command(DFxInfo[unit_r].IOExtTD, CMD_CLEAR);
/* force the current track to be re-read */
err= dcmp_read(unit_r, trk, deep_buffer);
if(err)
{ if(!ignore_errors)
mark(error_state);
}
else if(dcmp_cmptrk(rb, deep_buffer))
{ char weak_msg[128];
sprintf(weak_msg, weak_fmt[language], unit_r, trk);
if(write_logfile && logfile_open)
fprintf(fp,"** %s\n",weak_msg);
if(!be_quiet) printf("\r%s\n",weak_msg);
wtrk++; /* increase #of weak tracks */
if(display_window) /* w == weak */
{ set_trackframe(trk,(unit_r==unit_c)?(1):(-1),ratt,"w");
err++; /* don't change trackframe/compare */
}
}
}
if(!err && (unit_r != unit_c)) /* only if 00,ok,00,00 */
{
/* read track into DFxInfo[unit_c].Buffer */
if(display_window) set_trackframe(trk,-1,ratt,"c");
err= dcmp_read(unit_c, trk, cb); /* read track into rb */
if(err)
{ if(!ignore_errors)
mark(error_state);
}
/* deep read for unit_c */
else if(deep_read && deep_buffer)
{ do_command(DFxInfo[unit_c].IOExtTD, CMD_CLEAR);
/* force the current track to be re-read */
err= dcmp_read(unit_c, trk, deep_buffer);
if(err)
{ if(!ignore_errors)
mark(error_state);
}
else if(dcmp_cmptrk(cb, deep_buffer))
{ char weak_msg[128];
sprintf(weak_msg, weak_fmt[language], unit_c, trk);
if(write_logfile && logfile_open)
fprintf(fp,"** %s\n",weak_msg);
if(!be_quiet) printf("\r%s\n",weak_msg);
wtrk++; /* increase #of weak tracks */
if(display_window)
{ set_trackframe(trk,-1,ratt,"w"); /* w == weak */
err++;
}
}
}
if(!err) /* both tracks successfully read */
{ int lw; /* longword counter */
if(trk == et)
eo= (1+(end_blk%BLOCKS_PER_TRACK)) * (BYTES_PER_BLOCK/4);
/* maybe we are not to compare the last track fully... */
for(lw=so; lw<eo; lw++)
{ if(rb[lw] != cb[lw])
{ int sec= lw / (BYTES_PER_BLOCK/4); /* actual sector */
dblk_list[dblk]=(trk*BLOCKS_PER_TRACK)+sec;
dblk++; /* increase #of differing blocks found */
lw= (sec+1) * (BYTES_PER_BLOCK/4); /* seek to next block */
diff++; /* another difference on this track */
}
}
if(diff>0) dtrk++; /* increase #of differing tracks */
so=0; /* from now on we start comparing with the first long */
}
}
if(display_window) /* display the result in the trackframes */
{ if(err == 0) /* otherwise we already displayed it */
set_trackframe(trk,diff,ratt,NULL); /* NULL == ' ' */
if(dcmp_check_brk()) /* check the gadgets */
{ if(!danger)
mark(error_state); /* otherwise it might be lenthal... */
}
}
}
if(logfile_open)
{ if(write_logfile)
write_statistics(fp,1); /* 1 == full statistics */
close_logfile();
}
close_dcmp_stuff();
}
/*
* Information when started from CLI/Shell (How to use)
*/
static char *howtouse[]=
{ "\nLegal options are:\n",
"-t write transcript to `dcmp.log'",
"-l <LogFile> write extended transcript to `LogFile'",
"-i create project icon with logfile",
"-v verify tracks after read (detect weak data)",
"-w display information in a window",
"-a (-r) set #of attempts to read (retries)",
"-b break on (read) errors.",
"-sc <cylinder> start with cylinder #<cylinder> sector #0",
"-st <track> start with track #<track> sector #0",
"-ss <sector> start with sector #<sector>",
"-sb <block> start with block #<block>",
"-ec <cylinder> end with last cylinder #<cylinder> sector #0",
"-et <track> end with last track #<track> sector #0",
"-es <sector> end with last sector #<sector>",
"-eb <block> end with last block #<block>",
"\nALL THIS IS HIGHLY EXPERIMENTAL !!! TAKE GREAT CARE !!!",
"",
/* end of `how to use' */
};
/* --------------------------- P R I V A T E ------------------------------ */
#include <time.h>
void dcmp_private()
{ struct tm *lt;
long t;
static char *private_msg[][]= {
{ "Today is a very special day! It's the author's birthday !\n"
"So if you did not already make your greetings-card pop through\n"
"my letter-box yet then do so (hurry up)!"
,"happy","birthday",
"It seems as if your internal clock is not set correctly!\n"
"I strongly recommend to adjust this!"
,"","Oh, thanks!"
},
{ "Heute ist ein ganz besonderer Tag! Heute hat nämlich der\n"
"Autor von DCMP Geburtstag ! Wenn Sie mir also noch keine\n"
"Karte geschrieben haben, wird's jetzt aber höchste Zeit!"
,"Herzlichen", "Glückwunsch",
"Was ist denn mit Ihrer Uhr los? Das Datum geht nach!"
,"Oh, Mist", "Leck' mich",
},
{ "Aujourd'hui c'est un jour magnifique. C'est aujourd'hui que\n"
"l'auteur de DCMP a son jour d'anniversaire. Si vous n'avez\n"
"pas écrit de carte, dépêchez-vous!"
,"", "Bon anniversaire",
"Qu'est-ce qui se passe avec votre montre?\n"
"La date n'est pas correcte"
,"", "Chiure", /* <- Fliegendreck! */
},
{ "Oggi è festa! Sì, è il compleanno! (Pure l'autore del\n"
"programma sta invecchiando, poverino!) Se non avete ancora\n"
"mandato una cartolina, fatelo adesso per consolarlo\n"
,"","Tanti auguri!",
"Non funziona più l'orologio? Bisogna mettere a posto la data!\n"
,"", "Porca miseria!",
}
};
time(&t);
lt= localtime(&t);
if(lt->tm_year < 93)
dcmp_Request(private_msg[language][3],
private_msg[language][4],
private_msg[language][5] );
else if(lt->tm_mday == 27 && lt->tm_mon == 8) /* 27.09. */
dcmp_Request(private_msg[language][0],
private_msg[language][1],
private_msg[language][2] );
}
/* ------------------------------------------------------------------------ */
/*
* main()
*/
main(int argc, char *argv[])
{ char *arg; /* parsed argument */
int i; /* general counter */
BOOL do_about= FALSE; /* see about message in the window */
onbreak(_abort); /* this is DICE */
whoami=argv[0]; /* and this is me */
dcmp_private();
puts(rcs_id);
if(argc==2 && (argv[1][0]=='?'||argv[1][0]=='.'))
{ puts(BANNER);
puts(USAGE);
for(i=0;*howtouse[i];puts(howtouse[i++])); /* how to use */
exit(0);
}
/* parse args */
argc--;
argv++;
while(argc>0 && !danger)
{ arg=argv[0];
if(*arg=='-')
{ arg++;
switch(*arg)
{ case 'l': case 'L': case 'o': case 'O':
if(arg[1]) strcpy(logfile_name,arg+1);
else
{ argv++;
argc--;
strcpy(logfile_name,argv[0]);
}
write_logfile= TRUE;
break;
case 't': case 'T':
strcpy(logfile_name, DEF_LOGFILE);
write_logfile= TRUE;
break;
case 'i': case 'I':
write_icon= TRUE; /* note: no logfile -> no icon! */
break;
case 'v': case 'V': case 'd': case 'D':
deep_read= TRUE;
break;
case 'a': case 'A': case 'r': case 'R':
if(arg[1]) attempts=atoi(arg+1);
else
{ argv++;
argc--;
attempts=atoi(argv[0]);
}
if(0>=attempts||attempts>MAX_ATTEMPTS)
{ printf("Illegal #of attempts: %ld. Must be in [1..10].\n",attempts);
mark(error_state);
}
break;
case 's': case 'S':
switch(*++arg)
{ case 'b': case'B':
if(arg[1]) start_blk=atoi(arg+1);
else
{ argv++;
argc--;
start_blk=atoi(argv[0]);
}
if(start_blk<FIRSTBLOCK||start_blk>LASTBLOCK)
{ printf("Illegal block number: %ld. Must be in [0..1759].\n",start_blk);
mark(error_state);
}
break;
case 'c': case 'C':
if(arg[1]) i=atoi(arg+1);
else
{ argv++;
argc--;
i=atoi(argv[0]);
}
if(0<=i&&i<=79) start_blk=i*BLOCKS_PER_CYLINDER;
else
{ printf("Illegal cylinder number: %ld. Must be in [0..79].\n",i);
mark(error_state);
}
break;
case 't': case 'T':
if(arg[1]) i=atoi(arg+1);
else
{ argv++;
argc--;
i=atoi(argv[0]);
}
if(0<=i&&i<=159) start_blk=i*BLOCKS_PER_TRACK;
else
{ printf("Illegal track number: %ld. Must be in [0..159].\n",i);
mark(error_state);
}
break;
case 's': case 'S':
if(arg[1]) i=atoi(arg+1);
else
{ argv++;
argc--;
i=atoi(argv[0]);
}
if(0<=i&&i<=10)
{ i-= (start_blk%BLOCKS_PER_TRACK);
start_blk+=i;
}
else
{ printf("Illegal sector number: %ld. Must be in [0..10].\n",i);
mark(error_state);
}
break;
default:
printf("Illegal start option `-s%c'. Try -sc,-st,-sb,-ss\n",*arg);
mark(error_state);
}
break;
case 'e': case 'E':
switch(*++arg)
{ case 'b': case 'B':
if(arg[1]) end_blk=atoi(arg+1);
else
{ argv++;
argc--;
end_blk=atoi(argv[0]);
}
if(end_blk<FIRSTBLOCK||end_blk>LASTBLOCK)
{ printf("Illegal block number: %ld. Must be in [0..1759].\n",end_blk);
mark(error_state);
}
break;
case 'c': case 'C':
if(arg[1]) i=atoi(arg+1);
else
{ argv++;
argc--;
i=atoi(argv[0]);
}
if(0<=i&&i<=79) end_blk=i*BLOCKS_PER_CYLINDER;
else
{ printf("Illegal cylinder number: %ld. Must be in [0..79].\n",i);
mark(error_state);
}
break;
case 't': case 'T':
if(arg[1]) i=atoi(arg+1);
else
{ argv++;
argc--;
i=atoi(argv[0]);
}
if(0<=i&&i<=159) end_blk=i*BLOCKS_PER_TRACK;
else
{ printf("Illegal track number: %ld. Must be in [0..159].\n",i);
mark(error_state);
}
break;
case 's': case 'S':
if(arg[1]) i=atoi(arg+1);
else
{ argv++;
argc--;
i=atoi(argv[0]);
}
if(0<=i&&i<=10)
{ i-= (end_blk%BLOCKS_PER_TRACK);
end_blk+= i;
}
else
{ printf("Illegal sector number: %ld. Must be in [0..10].\n",i);
mark(error_state);
}
break;
default:
printf("Illegal end option `-e%c'. Try -ec,-et,-eb,-es\n",*arg);
mark(error_state);
}
break;
case 'w': case 'W':
display_window= TRUE;
break;
case 'b': case 'B':
ignore_errors= FALSE;
break;
case '?':
do_about= TRUE;
break;
default:
printf("Illegal option: -%s !\n",arg);
mark(error_state);
}
}
/*
* parse drive unit
*/
else if((arg[0]=='D'||arg[0]=='d')&&(arg[1]=='F'||arg[1]=='f'))
{ i=(int)(arg[2]-'0');
if(0>i||i>3)
{ puts("Illegal drive unit. Try DF0..DF3.");
mark(error_state);
}
else if(unit_r<0) unit_r=unit_c=i; /* one given unit# fills both */
else unit_c=i;
}
argc--;
argv++;
}
if(!danger && !display_window && unit_r<0 && unit_c<0)
{ puts("\rNo drive(s) specified.");
puts(USAGE); /* we need at least *one* unit# without window */
mark(error_state);
}
if(!danger)
{
if(start_blk > end_blk) /* -> swap start and end */
{ i=start_blk;
start_blk=end_blk;
end_blk=i;
}
if(!display_window)
{ printf(CRSR_OFF); /* no cursor! */
if(unit_r == unit_c)
{ printf("Checking Disk in DF%ld: (block %ld to %ld).\n",
unit_r,start_blk,end_blk);
}
else
{ printf("Comparing DF%ld: with DF%ld: (block %ld to %ld).\n",
unit_r,unit_c,start_blk,end_blk);
}
do_dcmp_stuff();
printf(CRSR_ON); /* cursor on! */
write_statistics(stdout,0); /* 0 = results only */
if(write_logfile)
{ printf("\rtranscript %s %s%s",
(logdata_added)?("appended to"):("written on"),
logfile_name,
(write_icon)?(" w/ icon\n"):("\n") );
}
}
else
{ open_window_stuff();
if(!danger)
{ be_quiet= TRUE; /* since we've got a window... */
if(do_about) about();
handle_window_stuff();
}
}
wrap_up();
}
}
/* legal ToolTypes are: */
#define TT_NAME "NAME"
#define TT_FIRSTCYL "FIRST CYL"
#define TT_LASTCYL "LAST CYL"
#define TT_ATTEMPTS "ATTEMPTS"
#define TT_LOGFILE "LOGFILE"
#define TT_LOGICON "LOGICON"
#define TT_DEFAULTTOOL "DEFAULT TOOL"
#define TT_IGNOREERRORS "IGNORE ERRORS"
#define TT_DEEPREAD "DEEP READ"
#define TT_LANGUAGE "LANGUAGE"
#define TT_MOUSEPOINTER "MOUSEPOINTER"
#define TT_BUSYBEE "WAITPOINTER"
wbmain(struct WBStartup *WBStartup)
{
static char *err_msg[][]= {
{ "Unable to open icon.library (hey, why?!)", "", "Oh shit!", /* 0,1,2 */
"Can't open dcmp's window stuff!", "", "Fuck it" /* 3,4,5 */
},
{ "Ich kann die icon.library nicht öffnen!", "", "Sowas Dummes",
"Das Fenster mag sich nicht öffnen lassen","","Schade"
},
{ "Pas d'icon.library!?", "", "Quoi?",
"Je ne peux pas ouvrir la fenêtre!", "", "Comment, pas?"
},
{ "Non posso aprire l'icon.library!", "", "Peccato",
"La finestra non si fa aprire","","Come, non aprire?"
},
};
be_quiet= TRUE; /* IMPORTANT!!! */
display_window= TRUE;
IconBase= (struct IconBase *)OpenLibrary(ICONNAME,LIBRARY_VERSION);
if(IconBase)
{ struct WBArg *wbarg= WBStartup->sm_ArgList;
struct DiskObject *icon;
whoami= wbarg->wa_Name;
CurrentDir(wbarg->wa_Lock);
icon= GetDiskObject(wbarg->wa_Name);
if(icon)
{ char *ttv, **tt= icon->do_ToolTypes;
/* --------------------------- P R I V A T E ------------------------------ */
ttv= FindToolType(tt, TT_NAME);
if(ttv)
{ if(MatchToolValue(ttv,"Mike")) /* Mike's settings */
{ unit_r= 0; unit_c= 0;
strcpy(logfile_name,DEF_LOGFILE); write_logfile= TRUE;
strcpy(DefaultTool,"c:MuchMore"); write_icon= TRUE;
start_blk= 0; end_blk= 1759; attempts= 2;
language=1; ignore_errors= TRUE; deep_read= TRUE;
}
else if(MatchToolValue(ttv,"Harald"))
{ dcmp_pointer= SMI_NONE;
busybee= SMI_STOPWATCH;
}
else if(MatchToolValue(ttv,"Tobias"))
{ dcmp_pointer= SMI_KLONDIKE;
busybee= SMI_SLEEPGLOVE;
}
else if(MatchToolValue(ttv,"Angela")) dcmp_pointer= SMI_NESSIE;
}
/* ------------------------------------------------------------------------ */
ttv= FindToolType(tt, TT_FIRSTCYL);
if(ttv)
{ int c= atoi(ttv);
if(c<0) c=0;
else if(c>79) c=79;
start_blk= c*BLOCKS_PER_CYLINDER;
}
ttv= FindToolType(tt, TT_LASTCYL);
if(ttv)
{ int c= atoi(ttv);
if(c<0) c=0;
else if(c>79) c=79;
end_blk= c*BLOCKS_PER_CYLINDER + BLOCKS_PER_CYLINDER -1;
}
ttv= FindToolType(tt, TT_ATTEMPTS);
if(ttv)
{ attempts= atoi(ttv);
if(attempts<1) attempts= 1;
else if(attempts>MAX_ATTEMPTS) attempts= MAX_ATTEMPTS;
}
ttv= FindToolType(tt, TT_LOGFILE);
if(ttv)
{ strcpy(logfile_name, ttv);
write_logfile= TRUE;
}
ttv= FindToolType(tt, TT_LOGICON);
if(ttv) write_icon= MatchToolValue(ttv,"ON");
ttv= FindToolType(tt, TT_DEFAULTTOOL);
if(ttv) strcpy(DefaultTool, ttv);
ttv= FindToolType(tt, TT_IGNOREERRORS);
if(ttv) ignore_errors= MatchToolValue(ttv,"ON");
ttv= FindToolType(tt, TT_DEEPREAD);
if(ttv) deep_read= MatchToolValue(ttv,"ON");
ttv= FindToolType(tt, TT_LANGUAGE);
if(ttv)
{ if(MatchToolValue(ttv,"ENGLISH")) language= 0;
else if(MatchToolValue(ttv,"ENGLISCH")) language= 0;
else if(MatchToolValue(ttv,"GERMAN")) language= 1;
else if(MatchToolValue(ttv,"DEUTSCH")) language= 1;
else if(MatchToolValue(ttv,"FRENCH")) language= 2;
else if(MatchToolValue(ttv,"FRANZÖSISCH")) language= 2;
else if(MatchToolValue(ttv,"FRANCAIS")) language= 2;
else if(MatchToolValue(ttv,"FRANÇAIS")) language= 2;
else if(MatchToolValue(ttv,"ITALIEN")) language= 3;
else if(MatchToolValue(ttv,"ITALIENISCH")) language= 3;
else if(MatchToolValue(ttv,"ITALIANO")) language= 3;
else if(MatchToolValue(ttv,"ASYL")) language= 3; /* not ready yet...*/
}
ttv= FindToolType(tt, TT_MOUSEPOINTER);
if(ttv)
{ if(MatchToolValue(ttv,"PREFSPOINTER")) dcmp_pointer= SMI_PREFS;
else if(MatchToolValue(ttv,"DEFAULT")) dcmp_pointer= SMI_NONE;
else if(MatchToolValue(ttv,"KLONDIKE")) dcmp_pointer= SMI_KLONDIKE;
else if(MatchToolValue(ttv,"NESSIE")) dcmp_pointer= SMI_NESSIE;
else if(MatchToolValue(ttv,"DOTTY")) dcmp_pointer= SMI_DOTTY;
else if(MatchToolValue(ttv,"STANDARD20")) dcmp_pointer=SMI_STANDARD20;
else if(MatchToolValue(ttv,"STANDARD2.0")) dcmp_pointer=SMI_STANDARD20;
else if(MatchToolValue(ttv,"CROSSHAIR")) dcmp_pointer=SMI_CROSSHAIR;
else if(MatchToolValue(ttv,"TINY")) dcmp_pointer=SMI_TINY;
}
ttv= FindToolType(tt, TT_BUSYBEE);
if(ttv)
{ if(MatchToolValue(ttv,"OFF")) busybee= SMI_NONE;
else if(MatchToolValue(ttv,"BUSYBEE")) busybee= SMI_BUSYBEE;
else if(MatchToolValue(ttv,"ZZBUBBLE")) busybee= SMI_ZZBUBBLE;
else if(MatchToolValue(ttv,"STOPWATCH")) busybee= SMI_STOPWATCH;
else if(MatchToolValue(ttv,"HOURGLASS")) busybee= SMI_HOURGLASS;
else if(MatchToolValue(ttv,"SLEEPGLOVE")) busybee= SMI_SLEEPGLOVE;
}
/* EXPERIMENTAL STUFF !!! */
ttv= FindToolType(tt, "NICEOPENSPEED");
if(ttv) { NiceOpenSpeed= atoi(ttv); if(NiceOpenSpeed > 20) NiceOpenSpeed= 20; }
ttv= FindToolType(tt, "NICECLOSESPEED");
if(ttv) { NiceCloseSpeed= atoi(ttv); if(NiceCloseSpeed > 20) NiceCloseSpeed= 20; }
FreeDiskObject(icon);
}
/* else (we got no icon) -> we were not started from Workbench */
CloseLibrary(IconBase);
}
else dcmp_Request(err_msg[language][0],err_msg[language][1],err_msg[language][2]);
dcmp_private();
open_window_stuff();
if(!danger) handle_window_stuff();
else dcmp_Request(err_msg[language][3],err_msg[language][4],err_msg[language][5]);
wrap_up();
}