Contributor: SWAG SUPPORT TEAM        

{$A+,B-,D+,E+,F-,G+,I+,L+,N-,O-,P-,Q-,R-,S-,T-,V-,X+,Y+}
{$M 16384,0,655360}

USES DOS,Crt;

   TYPE

   { Define action type MOVE or COPY }
   cTYPE = (cMOVE,cCOPY);

   { Define the special structure of a DOS Disk Transfer Area (DTA) }
   DTARec      =  RECORD
                     Filler   :  ARRAY [1..21] OF BYTE;
                     Attr     :  BYTE;
                     Time     :  WORD;
                     Date     :  WORD;
                     Size     :  LONGINT;
                     Name     :  STRING [12];
                  END {DtaRec};

VAR
    OK : Integer;
    IP,OP : PathStr;  { input,output file names }

   FUNCTION Copier (cWhat : cTYPE; VAR orig: STRING;VAR nName: STRING) : Integer;

   { Copy or Move file through DOS if not on same disk. Retain original date,
     time and size and delete the original on Move.  The beauty here is that
     we can move files across different drives.  Also, we can rename file if
     we choose.     If error, function returns error number }


      CONST bufsize = $C000;            { About 48 KB - 49152 }

      TYPE
       fileBuffer = ARRAY [1..bufsize] OF BYTE;

      VAR   Regs: registers;
            src,dst: INTEGER;
            bsize,osize: LONGINT;
            buffer : ^fileBuffer;
            DTABlk : DTARec;
            fError : BOOLEAN;

      FUNCTION CheckError(err : Integer) : BOOLEAN;
      BEGIN
      CheckError := (Err <> 0);
      fError     := (Err <> 0);
      Copier     := err;
      END;

      PROCEDURE delfile (VAR fName: STRING);

         VAR   Regs: registers;

         BEGIN
            WITH Regs do BEGIN
               ah := $43;             { Make file R/W for delete }
               al := 1;
               cx := 0;               { Normal file }
               ds := Seg(fName[1]);   { fName is the fully qualified }
               dx := Ofs(fName[1]);   { pathname of file, 0 terminated }
               MsDos (Regs);
               IF CheckError(Flags AND 1) THEN EXIT
               ELSE BEGIN
                  ah := $41;            { Delete file through fName }
                  { ds:dx stil valid from set-attributes }
                  MsDos (Regs);
                  IF CheckError(Flags AND 1) THEN EXIT;
                  END
               END
         END;

      BEGIN

         Copier := 0;  { Assume Success }
         FindFirst(Orig,Anyfile,SearchRec(DTABlk));
         IF CheckError(DosError) THEN EXIT;

         WITH Regs DO BEGIN
            ah := $3D;                  { Open existing file }
            al := 0;                    { Read-only }
            ds := Seg(orig[1]);         { Original filename (from) }
            dx := Ofs(orig[1]);
            MsDos (Regs);
            IF CheckError(Flags AND 1) THEN Exit
            ELSE BEGIN
               src := ax;               { Handle of the file }

               ah := $3C;               { Create a new file }
               cx := 0;                 { Start as normal file }
               ds := Seg(nName[1]);     { Pathname to move TO }
               dx := Ofs(nName[1]);
               MsDos (Regs);
               IF CheckError(Flags AND 1) THEN Exit
               ELSE
                  dst := ax
               END
            END;

         osize := DTABlk.size;       { Size of file, from "findfirst" }
         WHILE (osize > 0) AND NOT ferror DO BEGIN

            IF osize > bufsize THEN
               bsize := bufsize        { Too big for buffer, use buffer size }
            ELSE
               bsize := osize;

            IF BSize > MAXAVAIL THEN BSize := MAXAVAIL;

            GETMEM (buffer, BSize);    { Grap some HEAP memory }

            WITH Regs DO BEGIN
               ah := $3F;               { Read block from file }
               bx := src;
               cx := bsize;
               ds := Seg(buffer^);
               dx := Ofs(buffer^);
               MsDos (Regs);
               IF CheckError(Flags AND 1) THEN {}
               ELSE BEGIN
                  ah := $40;            { Write block to file }
                  bx := dst;
                  { cx and ds:dx still valid from Read }
                  MsDos (Regs);
                  IF CheckError(Flags AND 1) THEN {}
                  ELSE IF ax < bsize THEN
                     BEGIN
                     CheckError(98); { disk full }
                     END
                  ELSE
                     osize := osize - bsize
                  END;
               END;

            FREEMEM (buffer, BSize);   { Give back the memory }
            END;

         IF NOT ferror AND (cWHAT = cMOVE) THEN
         WITH Regs DO
            BEGIN
            ah := $57;                  { Adjust date and time of file }
            al := 1;                    { Set date }
            bx := dst;
            cx := DTABlk.time;          { Out of the "find" }
            dx := DTABlk.date;
            MsDos (Regs);
            CheckError(Flags AND 1);
            END;

         WITH Regs DO
            BEGIN
            ah := $3E;                  { Close all files, even with errors! }
            bx := src;
            MsDos (Regs);
            ferror := ferror OR ((flags AND 1) <> 0);
            ah := $3E;
            bx := dst;
            MsDos (Regs);
            ferror := ferror OR ((flags AND 1) <> 0)
            END;

         IF ferror THEN EXIT            { we had an error somewhere }
         ELSE WITH Regs DO
            BEGIN
            ah := $43;                  { Set correct attributes to new file }
            al := 1;                    { Change attributes }
            cx := DTABlk.attr;          { Attribute out of "find" }
            ds := Seg(nName[1]);
            dx := Ofs(nName[1]);
            MsDos (Regs);
            IF CheckError(Flags AND 1) THEN EXIT
            ELSE
               If (cWHAT = cMOVE) THEN DelFile (orig) { Now delete the original }
            END                                       { if we are moving file }
      END;

BEGIN
clrscr;
IP := 'queen1.PAS';
OP := 'd:\temp\queen1.pas';
OK := Copier(cCOPY,IP,OP);
WriteLn(OK);
END.