PROGRAM NSAMP11;   { File-Handle Facilities Demonstration }

USES Crt, TPlus;

{ This program demonstrates the device independent I/O subroutines.}

TYPE IOArea = RECORD
                 Message : STRING [20];
                 Number  : INTEGER;
              END;


VAR Error   : INTEGER;       { Holds Status from each routine }
    Path    : String65;      { Holds path to the file }
    DirPath : String65;      { The directory to create and use for this test }
    FilePath : String65;     { The path to the file to be used for this test }
    CurPath : String65;      { Holds the current path in the test of CURDIR. }
    Attribute : INTEGER;     { Used in CREATEF to assign the new file attr.  }
    Access  : INTEGER;       { Defines the type of Access to the file.       }
    Handle  : INTEGER;       { When a file is opened using OPENF, an INTEGER }
                             { is returned. On all subsequent WRITEFs,READFs,}
                             { and CLOSEFs, the file is refered to by its    }
                             { INTEGER, in Handle. }
    DriveInt : INTEGER;      { Holds the Drive number. }
    DriveSt  : String65;     { Holds the current directory string returned. }
    Drive    : CHAR;
    Samp1Rec : IOArea;       { A RECORD used in some of the routine calls. }
    SampSize : WORD;         { The Number of bytes in the RECORD to read or  }
                             { write, can be less than what SIZEOF returns.  }
    Option : INTEGER;        { Used with change-file-Attributes procedure.   }


PROCEDURE Wait;

BEGIN
   WRITELN;
   WRITELN ('Press RETURN when ready.');
   PauseKb;
   ClearScnHome;
END;


BEGIN
   SetColorsn(lightgray,black);
   ClearScnHome;
   WRITELN ('Welcome to the Turbo-Plus 5.0 File Handling Demonstration');
   WRITELN ('   In this demonstration the following Turbo-Plus routines');
   WRITELN ('   will be used.');
   WRITELN ('      CREATEF :  create a file.');
   WRITELN ('      OPENF   :  open a file.');
   WRITELN ('      READF   :  read a file.');
   WRITELN ('      WRITEF  :  write to a file.');
   WRITELN ('      CLOSEF  :  close a file.');
   WRITELN ('      CHANGEN :  change the Attributes of a file.');
   WRITELN ('      DELETEF :  delete a file.');
   WRITELN ('      MKDIRN  :  create a directory.');
   WRITELN ('      RMDIRN  :  delete a directory.');
   WRITELN ('      CHDIRN  :  change the current directory.');
   WRITELN ('      CURDIRN :  get the path to the current directory.');
   WRITELN ('      CURDISK :  get the letter of the current disk.');
   Wait;

   { This is an example on how to use MKDIRN.  MKDIRN performs }
   { the same function as the MKDIR command.  This call will   }
   { attempt to create the directory of your choice.           }
   WRITELN ('This is a test of the MKDIRN routine.  It will attempt to ');
   WRITELN ('create a directory.  Which directory would you like to   ');
   WRITELN ('create?');
   REPEAT
      READLN (DirPath);        { Get the path name for the new directory }

      {*********************}
       MKDIRN (DirPath, Error);   { Create the directory.      }
      {*********************}

      IF Error = 0 THEN
         WRITELN ('Directory ',DirPath,' Created')
      ELSE
         WRITELN ('Unable to create ', DirPath, ', try another name');
      WRITELN;
   UNTIL Error = 0;

   { This is an example on how to use CURDISK.  CURDISK returns}
   { the letter of the active disk Drive.                      }
   WRITELN ('This is a test of the CURDISK routine.  It will return the ');
   WRITELN ('letter of the current Drive.');
   Wait;

   {****************}
    CurDisk (Drive);            { The letter of the current Drive }
   {****************}

   WRITELN ('Current default Drive is ', Drive);
   WRITELN;


   { This is an example on how to use CURDIRN.  CURDIRN returns  }
   { the path to the current directory on a given Drive. (Each   }
   { Drive can have its own current directory.)  The second      }
   { parameter is the Drive letter.  It must be initialized with }
   { the Drive letter prior to the call.  A blank can be used    }
   { for the default Drive.                                      }
   WRITELN ('This is a test of the CURDIRN routine.  It will return the ');
   WRITELN ('path of the current directory on the default Drive.');
   Wait;
   Drive := ' ';               { Get the path to the current     }

   {*****************************}
    CURDIRN (Path, Drive, Error);  { get directory on the default Drive. }
   {*****************************}

   WRITELN ('Current default directory is: ',Path);
   WRITELN;

   { In this example CHDIR will be demonstrated.  The current  }
   { directory will be changed from what it is now (shown in   }
   { last example) to the directory created in the first step. }
   { CURDIR will be used to show the effect of CHDIR.          }
   WRITELN ('This is a test of the CHGDIRN routine.  It changes the current');
   WRITELN ('directory pointer just as the DOS CHGDIR (CD) command does. In');
   WRITELN ('this example the current directory will be changed from what');
   WRITELN ('it is now (shown in the last example) to the directory you  ');
   WRITELN ('created in the first example.  It will then be changed back.');
   Wait;

   {**********************}
    CHGDIRN (DirPath, Error);     { Change the directory.           }
   {**********************}

   IF Error <> 0  THEN            { Did it execute successfully?    }
     WRITELN ('CHGDIRN error is ',Error,'. Example terminated.')  { NO }
   ELSE                           { Yes: then continue.             }
     BEGIN
       CURDIRN (DirPath, Drive, Error);
       WRITELN ('The current directory has been changed to ', DirPath);
       CHGDIRN (Path, Error);      { Restore the current directory pointer }
       CURDIRN (Path, Drive, Error);
       WRITELN ('The current directory has been restored to ',Path);
     END;

   WRITELN;
   WRITELN ('Now we will go back into your temporary directory, to');
   WRITELN ('build a test file that shows off some of the other file');
   WRITELN ('functions available in TURBO-PLUS.');
   WRITELN;
   CHGDIRN (DirPath, Error);

   { This is an example on how to use CREATEF.  CREATEF creates}
   { a file then opens it.  CREATEF requires the path to the   }
   { file including the file name and a Attribute Number.  A   }
   { standard file has an Attribute of 0.  CREATEF returns an  }
   { INTEGER which must be used in all subsequent WRITEFs,     }
   { READFs, and the CLOSEF for the file.  CREATEF also returns}
   { a status code.                                            }
   WRITELN ('This is a test of the CREATEF routine.  CREATEF creates ');
   WRITELN ('a file and opens it with write Access.  What file would ');
   WRITELN ('you like to create?');
   REPEAT
      READLN (FilePath);          { Get the path to the file to be  }
      Attribute := 0;             { The standard file Attribute.    }

      {****************************************}
       CREATEF (FilePath, Attribute, Handle, Error); {create file}
      {****************************************}

      IF Error <> 0 THEN          { Did it execute successfully?    }
        BEGIN                     { No, try another file name.     }
          WRITELN ('CREATEF error is ',Error);
          WRITELN ('Since that did not work, try another file name.');
        END
      ELSE                        { Yes: Print the Handle.          }
        WRITELN ('File ',FilePath,' Created. Handle = ',Handle);
   UNTIL Error = 0;
   WRITELN;

   { To continue the example the file will be closed using     }
   { CLOSEF.  CLOSEF expects the Handle INTEGER to identify    }
   { the file.                                                 }
   WRITELN ('This is a test of the CLOSEF routine.  This test will close');
   WRITELN ('the file created in the last test.');
   Wait;

   {**********************}
    CLOSEF (Handle, Error);       { close file }
   {**********************}

   IF Error <> 0 THEN             { Did it execute successfully?    }
     WRITELN ('CLOSEF Error is ',Error)  { NO }
   ELSE                           { Yes: Print the good news.       }
     WRITELN ('File ',FilePath,' Handle ',Handle,' closed successfully.');
   WRITELN;

   { To continue the example the file will be opened with      }
   { OPENF.  OPENF requires the path to the file including     }
   { the file name.  It also requires an Access INTEGER.  The  }
   { Access Number indicates what type Access to the file is   }
   { desired.  OPENF returns a Handle INTEGER and a status     }
   { code.  Note that the Handle INTEGER is the same as when   }
   { the file was created with the CREATEF.                    }
   WRITELN ('This is a test of the OPENF routine.  It will attempt to');
   WRITELN ('open the file closed in the last test.  Notice that the');
   WRITELN ('Handle is the same as before.');
   Wait;
   Access := 2;                   { Request read/write Access.      }

   {*********************************}
    OPENF (FilePath, Access, Handle, Error);   { open file }
   {*********************************}

   IF Error <> 0 THEN             { Did it execute successfully?    }
      WRITELN ('OPENF error is ',Error) { NO }
   ELSE                           { Yes: Print the Handle.          }
      WRITELN ('File ',FilePath,' opened, its Handle is ',Handle);
   WRITELN;

   { This is an example of how to use WRITEF.  WRITEF writes   }
   { a RECORD to the file identified by the Handle INTEGER.    }
   { WRITEF expects a Handle INTEGER, a RECORD, the Number of  }
   { bytes to be written.  WRITEF returns a status.            }
   WRITELN ('This is a test of the WRITEF routine.  It will write a ');
   WRITELN ('RECORD to your test file.  The RECORD has an INTEGER 1 ');
   WRITELN ('and a STRING "sample1 RECORD"');
   Wait;

   Samp1Rec.Message := 'Sample1 RECORD';{ Fill in part of the test RECORD.}
   Samp1Rec.Number := 1;          { Fill in the other part.         }
   SampSize := SIZEOF (Samp1Rec); { Number of bytes to be written.  }

   {****************************************}
     WRITEF(Handle,Samp1Rec,SampSize,Error);         {write to file}
   {****************************************}

   IF Error <> 0  THEN            { Did it execute successfully?    }
     WRITELN ('WRITEF error is ',Error) { NO }
   ELSE                           { Yes: Print the good news.       }
     WRITELN ('WRITEF worked');
   WRITELN;

   { This is an example of how to use READF.  READF reads a    }
   { RECORD from the file identified by the Handle INTEGER.    }
   { READF expects a Handle INTEGER and the Number of bytes to }
   { be read.  READF returns a RECORD and a status.  In this   }
   { example the test file will be closed and reopened to      }
   { reposition at the first RECORD of the file.  (The one     }
   { written in the last example.)                             }
   WRITELN ('This is a test of the READF routine.  It will attempt to ');
   WRITELN ('read the RECORD written in the last test.  To reposition ');
   WRITELN ('at the first RECORD (the only one in this case) the file ');
   WRITELN ('will be closed then opened.');
   Wait;

   CLOSEF (Handle, Error);        { Reposition at first RECORD.     }
   OPENF (FilePath, Access, Handle, Error);

   {***************************************}
    READF (Handle, Samp1Rec, SampSize, Error); { read file }
   {***************************************}

   IF Error <> 0 THEN             { Did the RECORD get read?        }
     WRITELN ('read file error ',Error) { NO }
   ELSE                           { Yes: Print the fields in the    }
     BEGIN                        {      RECORD and its length.     }
       WRITELN ('The RECORD string is ',Samp1Rec.Message);
       WRITELN ('The RECORD integer is ',Samp1Rec.Number);
       WRITELN ('Record length is ',SampSize);
     END;
   WRITELN;

   { To continue this example, the next READF should give an   }
   { END of file status which is 99.                           }
   WRITELN ('This is another test of the READF routine.  In this test ');
   WRITELN ('another read will be done against the file.  It should   ');
   WRITELN ('give an END-OF-FILE status');
   Wait;

   READF (Handle, Samp1Rec, SampSize, Error);
   IF Error = 99 THEN             { Did it reach END of file?       }
     WRITELN ('End of file encountered, Error ',Error)  { YES ! }
   ELSE                           { No:  Print the error Number.    }
     WRITELN ('READF unexpected status is ',Error);
   WRITELN;

   { To conclude this example, the test file will be closed to }
   { prepare for following examples.                           }
   WRITELN ('To prepare for the following tests the test file is being');
   WRITELN ('closed.');
   Wait;

   {**********************}
    CLOSEF (Handle,Error);              {close file}
   {**********************}

   WRITELN;
   IF Error <> 0 THEN
     WRITELN ('CLOSEF error is ',Error)
   ELSE
     WRITELN ('File ',FilePath,' is closed.');
   WRITELN;

   { This is an example of how to use CHANGEN.  CHANGEN will be  }
   { used to change a files Attributes, examine them and then  }
   { change them back again }
   WRITELN ('This is a test of the CHANGEN routine.  It will change the');
   WRITELN ('Attributes of the file to hidden (2), then examine the Attributes,');
   WRITELN ('and then change them back to normal.');
   Wait;

   Option := 1;                   { change Option }
   Attribute := 2;

   {*************************************}
    CHANGEN (FilePath,Option,Attribute,Error);      {change files Attributes}
   {*************************************}

   Option := 0;                   { examine Attributes Option }
   CHANGEN (FilePath,Option,Attribute,Error);
   WRITELN;
   WRITELN ('The new Attribute for the file is ',Attribute);
   Option := 1;
   Attribute := 0;
   CHANGEN (FilePath, Option, Attribute, Error);
   WRITELN;
   WRITELN ('The files Attributes have been restored to normal');
   WRITELN;

   { What happens if you try to delete a directory with a file in it? }
   { We'll find out now. }
   WRITELN ('Now we will try to delete that subdirectory you made before.');
   WRITELN ('But it still has a file in it, so we should fail.');
   Wait;

   RMDIRN (DirPath, Error);
   IF Error <> 0 THEN
      WRITELN ('Removal failed, error code = ', Error)
   ELSE
      WRITELN ('How did that happen? No error encountered.');

   { This is an example on how to use DELETEF.  DELETEF expects}
   { the path including the filename of the file to be deleted.}
   { DELETEF returns a status.                                 }
   WRITELN ('This is a test of the DELETEF routine.  It will delete the ');
   WRITELN ('test file. ');
   Wait;

   {*********************}
    DELETEF (FilePath, Error);
   {*********************}

   IF Error <> 0 THEN             { Did the file get deleted?       }
      WRITELN ('DELETEF error is ',Error)  { NO }
   ELSE                           { Yes: Print the good news.       }
      WRITELN ('Deleted file ',FilePath,'.');
   WRITELN;


   { This is an example on how to use RMDIRN.  RMDIRN performs }
   { the same function as RMDIRN. It deletes directories.  The }
   { Drive is part of the path name.  In one of the earlier    }
   { examples directory samp1 was created.  In this example an }
   { attempt will be made to delete it.                        }

   { First, go back to the original directory }
   CHGDIRN (Path, Error);

   WRITELN ('This is a test of the RMDIRN routine.  It will attempt to ');
   WRITELN ('delete the directory you created in an earlier test again.');
   WRITELN ('It should succeed.');
   Wait;

   {*******************}
    RMDIRN (DirPath, Error);      { Delete the directory.           }
   {*******************}

   WRITELN;
   IF Error <> 0 THEN             { Did it execute successfully?    }
     WRITELN ('RMDIRN error is ',Error)  { NO }
   ELSE                           { Yes: Print the good news.       }
     WRITELN ('Directory ',DirPath,' removed');
   WRITELN;

   { To continue the example, an attempt will be made to delete}
   { the same directory.  This should demonstrate that the     }
   { Error will really contain a value when the function cannot}
   { be accomplished.                                          }
   WRITELN ('This is another test of the RMDIRN routine.  It will attempt');
   WRITELN ('to delete the same directory deleted in the previous test. ');
   WRITELN ('This time it should fail because the directory has already');
   WRITELN ('been removed.');
   Wait;

   RMDIRN (DirPath, Error);       { Delete the directory.           }
   IF Error = 0 THEN
      WRITELN ('Directory ',DirPath,' removed')  { THIS IS AN ERROR ! }
   ELSE
      WRITELN ('RMDIRN error is ',Error); { This error is expected }
   WRITELN;

   WRITELN ('That ends our demonstration.  As you can see, it is easy');
   WRITELN ('to create/modify/delete files and directories, using the');
   WRITELN ('exact same methods that DOS uses.  Please see the Turbo-');
   WRITELN ('Plus Users Manual for more information on these and some');
   WRITELN ('related routines (for example, the DUPHANDLE procedure).');
   WRITELN;
   WRITELN ('THANKS FOR WATCHING!');
END.
