/**---------------------------------------------------------------------
***	
***   file:      NewFormat.c
***
***   project:   Replacement for System:Format
***              Does NEVER format Harddisks
***
***         (c) 1991 Rainer Kowallik
***
***-------------------------------------------------------------------*/

#include <stdio.h>
#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <exec/devices.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <workbench/icon.h>

#include <devices/trackdisk.h>

#include <mdllib.h>

extern struct WBStartup *WBenchMsg;
extern struct IconBase *IconBase;

int   quick = 0;
int   MSDOS = 0;
int   noicons = 0;
int   act_track = 0;
char  diskname[80] = "Empty";
char  myname[80] = "NewFormat";

/* ---------------------------------------------
         User Callback functions
   --------------------------------------------- */

format_0()
{
char s[80];
FormatUnit(0);
}

format_1()
{
char s[80];
FormatUnit(1);
}

format_2()
{
char s[80];
FormatUnit(2);
}

format_3()
{
char s[80];
FormatUnit(2);
}

exitus()
{
close_gfx(my_window);
exit(0);
}
about()
{
char *s;
s = (char *) malloc(1500);
strcpy(s,"This Program was written to avoid unwanted\n");
strcat(s,"formatting of a Harddisk. It is inteded to\n");
strcat(s,"replace the usual system:format command.\n");
strcat(s,"NewFormat is transparent for command file calls !\n");
strcat(s,"You have to move the original system:format\n");
strcat(s,"to c:OLD_FORMAT and copy this programm to\n");
strcat(s,"system:FORMAT\n");
strcat(s,"Please set the Stacksize in the icon to 20000\n");
strcat(s,"If you really want to format your Harddisk\n");
strcat(s,"you may then use c:OLD_FORMAT instead.\n\n");
strcat(s,"This Programm is freely redistributable.\n");
strcat(s,"widley spreading is encouraged.\n\n");
strcat(s,"NewFormat Version 1.2 (C) Rainer Kowallik\n");
Help(s);
free(s);
}

reklame()
{
char *s;
s = (char *) malloc(1500);
strcpy(s,"other products from Rainer Kowallik:\n");
strcat(s,"  Public Domain:\n");
strcat(s,"MDL,  the Menu Description Language.\n");
strcat(s,"      Menu extension to the CShell and the\n");
strcat(s,"      SKShell\n");
strcat(s,"\n  On special Request:\n");
strcat(s,"LISE, the on Line Interactive Spectra Examination\n");
strcat(s,"      package (displaying and analysing time series\n");
strcat(s,"      and other two dimensional spectra)\n");
strcat(s,"      For Scientists only !\n");
Help(s);
strcpy(s,"\n  Commercial, under Devellopment:\n");
strcat(s,"MCAah, The Multi Channel Analyser for the Amiga Host\n");
strcat(s,"      The Software is allready used together with a\n");
strcat(s,"      patched IBM PC card. The pure Amiga card\n");
strcat(s,"      will be available at beginning of 1992\n\n");
strcat(s,"ADC,  A special Analog Digital Converter Card\n");
strcat(s,"      with Storage Oszilloscope functions.\n");
strcat(s,"      Hardware and Software are under Devellopment.\n");
Help(s);
strcpy(s,"\nAsk for more Information:\n");
strcat(s,"Rainer Kowallik  (Software)\n");
strcat(s,"Eisackstr. 14\n1000 Berlin 62\nGermany\n(030) 855 866 5\n");
strcat(s,"EAN: kowallik@vax.hmi.dbp.de\n");
strcat(s,"     S=KOWALLIK;OU=VAX;P=HMI;A=DBP;C=DE\n");
strcat(s,"or\n");
strcat(s,"Joern Ryba (Hardware)\n");
strcat(s,"Bambergerstr. 54\n1000 Berlin 30\nGermany\n(030)211 61 03\n");
Help(s);
free(s);
}

install()
{
char s[256];
int i,n;
FILE *stream;
struct DiskObject *Lock;

  stream = fopen("c:OLD_FORMAT","r"); /* check if allready installed */
  if(stream != NULL) {
      fclose(stream);
      Help("I am allready installed\n");
      return(0);
  }
   about();
   if(!RequestYesNo("Continue to Install NewFormat ?")) return();
   FileCopy("System:FORMAT","c:OLD_FORMAT");
   FileCopy(myname,"c:FORMAT");
   FileCopy(myname,"System:FORMAT");
   Lock = GetDiskObject("system:format"); /* set stack size */
   Lock->do_StackSize = 20000;
   PutDiskObject("system:Format",Lock);
   FreeDiskObject(Lock);
   
}

remove_me()
{
char s[256];
int i,n;
FILE *stream;

  stream = fopen("c:OLD_FORMAT","r"); /* check if installed */
  if(stream == NULL) {
      fclose(stream);
      Help("I am not installed anyway\n");
      return(0);
  }

   if(!RequestYesNo("Continue to Remove NewFormat ?")) return();
   FileCopy("c:OLD_FORMAT","system:FORMAT");
   unlink("c:FORMAT");
   unlink("c:OLD_FORMAT");
}

FileCopy(f1,f2)
char *f1,*f2;
{
int fd1,fd2;
int n;
char s[1024];

   fd1 = open(f1,0,0);
   if(fd1 < 0) {
      sprintf(s,"could not read %s\naborting...\n");
      Help(s);
      return(0);
   }
   fd2 = creat(f2,0777);
   if(fd2 < 0) {
      SetProtection(f2,0);
      fd2 = creat(f2,0777);
   }
   if(fd2 < 0) {
      sprintf(s,"could not open %s\naborting...\n");
      Help(s);
      return(0);
   }
   n = 1;
   while(n > 0) {
      n = read(fd1,s,512);
      if(n > 0) write(fd2,s,n);
   }
   close(fd1);
   close(fd2);
}

main(argc,argv)
unsigned int argc;
char *argv[];
{
int n,m,i;
FILE *stream, *tmp1;
char c,tempfile[80];
char mdlfile[80];
char s[256];
char **ToolArray, *Value;
struct DiskObject *Lock;
struct WBArg *Arg;
struct FileHandle *datei;

   if(argc > 0) {
      strcpy(myname,argv[0]);
      datei = (struct FileHandle *) Input(); /* check if called from a command file */
      if(!IsInteractive(datei)) { /* handle command file call */
         strcpy(s,"c:OLD_FORMAT ");
         for(i = 1; i < argc; i++) {
            if(lexcmp(argv[i],"DH0:") == 0) exit(0);
            strcat(s," "); strcat(s,argv[i]);
         }
         SysCall(s);
         exit(0);
      }
   } else {
      IconBase = (struct IconBase *) OpenLibrary("icon.library", 0L);
      Arg = WBenchMsg->sm_ArgList;
      CurrentDir(Arg->wa_Lock);
      strcpy(myname,Arg->wa_Name);
      if(WBenchMsg->sm_NumArgs > 1) {
         Arg++;
         UnLock(Arg->wa_Lock); /* Unlock Disk info */
         Arg->wa_Lock = 0;  /* Set Lock to 0 for cleanup after program */
         WBenchMsg->sm_NumArgs = 1;
      }
   }


/* --- window geometry and name */
  my_new_window = init_window(300,80,"NewFormat V1.2 (C) 1991 by RAKO",0,1);

/* ----- initializing menus and requesters */

   add_item(-1,-1,NEW_MENU,"project",0,0); 
      fn_number++;
   add_item(-1,-1,MENU,"Format DF0:",0,0); 
      fn_command[fn_number] = (void *)format_0;
      fn_number++;
   add_item(-1,-1,MENU,"Format DF1:",0,0); 
      fn_command[fn_number] = (void *)format_1;
      fn_number++;
   add_item(-1,-1,MENU,"Format DF2:",0,0); 
      fn_command[fn_number] = (void *)format_2;
      fn_number++;
   add_item(-1,-1,MENU,"Format DF3:",0,0); 
      fn_command[fn_number] = (void *)format_3;
      fn_number++;
   add_item(-1,-1,MENU,"Exit",0,0); 
      fn_command[fn_number] = (void *)exitus;
      fn_number++;
   add_item(-1,-1,NEW_MENU,"installation",0,0); 
      fn_number++;
   add_item(-1,-1,MENU,"Install NewFormat",0,0); 
      fn_command[fn_number] = (void *)install;
      fn_number++;
   add_item(-1,-1,MENU,"Remove NewFormat",0,0); 
      fn_command[fn_number] = (void *)remove_me;
      fn_number++;
   add_item(-1,-1,NEW_MENU,"help",0,0); 
      fn_number++;
   add_item(-1,-1,MENU,"about",0,0); 
      fn_command[fn_number] = (void *)about;
      fn_number++;
   add_item(-1,-1,MENU,"advertisement",0,0); 
      fn_command[fn_number] = (void *)reklame;
      fn_number++;

   add_item(150,15,TOGGLE,"Quick",0,0);
      var_value[fn_number] = &quick;
      fn_number++;

/*
   add_item(-1,-1,TOGGLE,"MS-DOS",0,0);
      var_value[fn_number] = &MSDOS;
      fn_number++;
*/

   add_item(-1,-1,TOGGLE,"No Icons",0,0);
      var_value[fn_number] = &noicons;
      fn_number++;

   add_item(-1,-1,STRING,"disk name",0,0);
      fn_command[fn_number] = (void *)dummy;
      var_value[fn_number] = &diskname;
      fn_number++;

   add_item(15,15,PUSH,"Format DF0:",0,100);
      fn_command[fn_number] = (void *)format_0;
      fn_number++;

   add_item(-1,-1,PUSH,"Format DF1:",0,0); 
      fn_command[fn_number] = (void *)format_1;
      fn_number++;

   add_item(-1,-1,PUSH,"Format DF2:",0,0); 
      fn_command[fn_number] = (void *)format_2;
      fn_number++;

   add_item(-1,-1,PUSH,"Format DF3:",0,0); 
      fn_command[fn_number] = (void *)format_3;
      fn_number++;

  my_window = (struct Window *) OpenWindow( my_new_window );
  SetMenuStrip( my_window, menu_bar );
  if(my_window == NULL)
  {
    close_gfx(NULL);
    exit();  
  }

  UpdateGadgets(my_window);
  fin_flg = FALSE;

  stream = fopen("c:OLD_FORMAT","r"); /* check if allready installed */
  if(stream == NULL) {
      install();
  } else {
      fclose(stream);
  }

  MainLoop(my_window);

  exit(0);
}

FormatUnit(unit)
int unit;
{
char s[256];
int i,n;

   sprintf(s,"c:OLD_FORMAT drive df%c: name %s",unit+48,diskname);
   if(noicons != 0) strcat(s," NOICONS");
   if(quick != 0) strcat(s," QUICK");
   SysCall(s);
}


FormatUnit__(unit)
int unit;
{
struct IOExtTD *DiskExtIO = 0L;
BYTE           *FormatData = 0l;
UWORD          i;
int            n;
char           s[1024];

   FormatData = (BYTE *) AllocMem(NUMSECS*TD_SECTOR, MEMF_CHIP | MEMF_CLEAR);
   if(FormatData == 0L) {
      Help("Not enough memory ?!\n");
      close_gfx(my_window);
      exit(0);
   }
   Open_A_Device("trackdisk.device",unit,&DiskExtIO, 0L,
                              (ULONG) (sizeof(struct IOExtTD)));

   DiskExtIO->iotd_Req.io_Length = 1L; /* motor on */
   Do_Command(DiskExtIO, TD_MOTOR);

   for(act_track = 0; act_track < 160; act_track++) {
      UpdateGadgets(my_window);
      for(i=0; i<(2*NUMSECS*TD_SECTOR); i+= 4) {
         FormatData[i]   = 'R';
         FormatData[i+1] = 'A';
         FormatData[i+2] = 'K';
         FormatData[i+3] = 'O';
      }
      DiskExtIO->iotd_Req.io_Offset = act_track * 512;
      Do_Command(DiskExtIO, TD_SEEK);
      n = DiskExtIO->iotd_Req.io_Error;
      if(n!=0) {
         sprintf(s,"Error %d on TD_SEEK\n",n);
         Help(s);
         break;
      }
      Do_Command(DiskExtIO,(UWORD)TD_CHANGENUM);
      DiskExtIO->iotd_Count = DiskExtIO->iotd_Req.io_Actual;
      DiskExtIO->iotd_Req.io_Data = (APTR) FormatData;
      DiskExtIO->iotd_Req.io_Length = (ULONG) (NUMSECS*TD_SECTOR);
      DiskExtIO->iotd_Req.io_Offset = 0L;
      Do_Command(DiskExtIO, TD_FORMAT);
      n = DiskExtIO->iotd_Req.io_Error;
      if(n!=0) {
         sprintf(s,"Error %d on TD_FORMAT\n",n);
         Help(s);
         break;
      }
   }
   DiskExtIO->iotd_Req.io_Length = 0L; /* motor off */
   Do_Command(DiskExtIO, TD_MOTOR);

   Close_A_Device(CloseDevice(DiskExtIO));
   FreeMem(FormatData, NUMSECS*TD_SECTOR);
}

APTR GetDeviceBlock(Size)
ULONG Size;
{
struct MsgPort *Device_Port = 0L;
APTR  Device_Request = 0L;

   Device_Port = (struct MsgPort *) CreatePort(0L, 0L);
   if(Device_Port == 0L) {
      Help("Couldn't get DEVICE PORT !\n");
      close_gfx(my_window);
      exit(0);
   }
   Device_Request = (APTR)CreateExtIO(Device_Port, Size);
   if (Device_Request == 0L) {
      DeletePort(Device_Port);
      Help("Couldn't get DEVICE BLOCK !\n");
      close_gfx(my_window);
      exit(0);
   }
   return(Device_Request);
}



Open_A_Device(Name, Unit, Device_Request, Flags, Size)
char * Name;
ULONG Unit;
APTR *Device_Request;
ULONG Flags, Size;
{
UWORD Error;

   if(Size != 0L) *Device_Request = (APTR) GetDeviceBlock(Size);
   Error = OpenDevice(Name, Unit, *Device_Request, Flags);
   if(Error != 0) {
      Help("Could not open device\n");
      close_gfx(my_window);
      exit(0);
   }
}

Close_A_Device(IORequest)
struct IORequest *IORequest;
{

   if(IORequest != 0) {
      if(IORequest->io_Message.mn_ReplyPort != 0L) 
            DeletePort(IORequest->io_Message.mn_ReplyPort);
      if(IORequest->io_Device != 0L) CloseDevice(IORequest);
      DeleteExtIO(IORequest);
   }
}

Do_Command(DeviceBlock, Command)
struct IORequest *DeviceBlock;
UWORD  Command;
{
   DeviceBlock->io_Command = Command;
   DoIO(DeviceBlock);
}

SysCall(str)
char *str;
{
int i,n,m;
struct FileHandle *input, *output;

input = (struct FileHandle *) Open("nil:",MODE_OLDFILE);
output = (struct FileHandle *) Open("con:50/50/300/30/NewFormat",MODE_NEWFILE);
   Execute(str,input,output);
Close(input);
Close(output);
}


/* ------------------------------------------------------
   compare two strings equating upper and lower case
   ------------------------------------------------------ */
lexcmp(str1,str2)
char  str1[],str2[];
{  char s1[256],s2[256];

   strcpy(s1,str1); strcpy(s2,str2);
   strupc(s1); strupc(s2);
   return(strcmp(s1,s2));
}


/* ---------------------------------------------
   convert string to upper case
   --------------------------------------------- */
strupc(str)
char  str[];
{  short  l,i;

   l=strlen(str);
   for(i=0; i < l; i++) str[i]=toupper(str[i]);
}

