program MS_DOS_Kopierer;

const bufgr    = 28671;                     (* Datenpuffer *)
      fatgr    = 2047;                      (* FAT-Puffer  *)
      titel    = ^M^J'MS-DOS-Kopierer V1.0 vom 28.3.87'^M^J;
      befehle  = 'Befehle: Change, Dir, Erase, Help, New, Quit, Read';
      nofile   = 'No File';
      copying  = '- Copying :';
      diskfull = 'Error : Disk Full';

type tbuff     = array[0..1023] of byte;    (* Sektorpuffer *)
     string14  = string[14];
     anystring = string[255];
     format    = record
                   psize,clsize,dirstart,datstart,
                   reservsec,eintraege,sektoren,
                   fatsecs,secptrk,heads,maxclnum  : integer;
                   secpcl,fatzahl,medium           : byte;
                   end;

(* MS-DOS-Verwaltungsbezogene Variablen *)

var  fatbuf                                 : array[0..1,0..fatgr] of byte;
     datbuf                                 : array[0..bufgr] of byte;
     dirbuf                                 : tbuff;
     dirsec,diroff,bufcl                    : integer;

(* MS-DOS-Formatbezogene Variablen *)

     disk                                   : array[0..1] of format;

(* MS-DOS-Dateibezogene Variablen *)

     msname                                 : string14;
     startgruppe,datum,zeit                 : integer;
     datlength                              : real;

(* Variablen des Hauptprogramms und zur allgemeinen Verwaltung *)

     actdrv,logdrive,i                      : byte;
     drive                                  : array[0..1] of byte;
     befehl                                 : anystring;
     cmd                                    : char;
     suchname                               : string14;
     gefunden,exit,print                    : boolean;

{$I MSCOPY.IN0 }  (* Utilities                 *)
{$I MSCOPY.IN1 }  (* MS-DOS Diskette lesen     *)
{$I MSCOPY.IN2 }  (* MS-DOS Erase und Rename   *)

procedure conout(ch:char); external $339;
procedure lstout(ch:char); external $32F;

procedure co(ch:char);
begin
  conout(ch);
  lstout(ch);
  end;

(*********************************************************************
**                        H E L P                                   **
*********************************************************************)

procedure help;

  procedure waittaste;
  var ch : char;
  begin
    write('Beliebige Taste bet{tigen ');
    read(kbd,ch);
    write(^M,'':30);
    end;

begin
  writeln(titel,befehle);
  write(
^M^J'Befehle bestehen generell aus einem Buchstaben. Hinter dem Befehls-',
^M^J'buchstaben kann sofort ein Dateiname folgen, welcher aber auch durch',
^M^J'ein oder mehrere Leerzeichen vom Befehl getrennt sein oder ganz fehlen',
^M^J'darf. Es existieren folgende Befehle :'^M^J,
^M^J'C : CHANGENAME, besser bekannt als RENAME. Es werden zwei Dateinamen',
^M^J'    eingegeben, wovon der erste der Alte und der zweite der Neue ist.',
^M^J'    Fehlende Dateinamen werden explizit abgefragt. Wildcards sind in',
^M^J'    keinem der beiden Namen erlaubt.'^M^J,
^M^J'D : DIRECTORY, gibt die Directory der aktiven Diskette aus. Wildcards',
^M^J'    sind erlaubt, au~erdem kann durch Eingabe eines ''F'' unmittelbar',
^M^J'    nach dem Befehl die Option ''FULL'' gesetzt werden, welche f}r alle',
^M^J'    Files die Dateil{nge sowie Datum- und Zeiteintrag ausgibt. Wird',
^M^J'    kein Dateiname angegeben, so werden alle Files angezeigt.'^M^J,
^M^J'E : ERASE, l|scht das angegebene File. Wildcards sind erlaubt.'^M^J^J);
  waittaste;
  write(
  ^M'H : HELP, augenblicklich aktiver Programmteil.'^M^J,
^M^J'N : NEW, loggt neue (andere) MS-DOS-Diskette ein (FAT wird gelesen und',
^M^J'    logische Parameter werden gesetzt).'^M^J,
^M^J'P : PRINT, schaltet Printer-Echo an bzw. aus.'^M^J,
^M^J'Q : QUIT, Ausgang zum Betriebssystem CP/M.'^M^J,
^M^J'R : READ, Datei(en) von aktivem Drive lesen und nach dem anderen Drive',
^M^J'    schreiben. Wird kein Dateiname angegeben, wird der Dateiname explizit',
^M^J'    erfragt.'^M^J,
^M^J'd:  Angabe des nicht aktiven Drives, gefolgt von einem Doppelpunkt,',
^M^J'    schaltet auf dieses Drive um.'^M^J^J);
  end;

(*********************************************************************
**               H A U P T P R O G R A M M                          **
*********************************************************************)

begin
  print:=false;
  writeln(titel,befehle);
  repeat
    write(^M^J'1. MS-DOS-Laufwerk : ');
    readln(befehl);
    drive[0]:=ord(upcase(befehl[1]))-$41;
  until drive[0] in [0..3];
  repeat
    write('2. MS-DOS-Laufwerk : ');
    readln(befehl);
    drive[1]:=ord(upcase(befehl[1]))-$41;
  until (drive[1] in [0..3]) and not (drive[1]=drive[0]);
  writeln('Hinweis: phys. Disk-Parameter m}ssen korrekt gesetzt sein !'^M^J);
  logdrive:=BDOS(25);
  actdrv:=1; login;
  actdrv:=0; login;
  repeat
    repeat
      write('.',chr(drive[actdrv]+$41),'.>');
      readln(befehl);
    until length(befehl)>0;
    for i:=1 to length(befehl) do befehl[i]:=upcase(befehl[i]);
    cmd:=befehl[1];
    exit:=cmd='Q';
    if (length(befehl)=2) and (befehl[2]=':')
      and (ord(befehl[1])-$41=drive[1-actdrv])
      then actdrv:=1-actdrv
    else begin
      delete(befehl,1,1);
      while (length(befehl)>0) and (befehl[1]=' ') do delete(befehl,1,1);
      case cmd of
        'C' : rename;
        'D' : directory;
        'E' : erase;
        'H' : help;
        'N' : login;
        'P' : begin
                print:=not print;
                if print then conoutptr:=addr(co) else conoutptr:=$339;
                end;
        'Q' : ;
        'R' : readfile;
        else writeln(^G,cmd,'?');
        end;
      end;
  until exit;
  relog(logdrive);
  end.
