home *** CD-ROM | disk | FTP | other *** search
-
- {* ------------------------------------------------------------------------- *}
- {* S E C O N D L E V E L M E N U S
- {* ------------------------------------------------------------------------- *}
-
- procedure ExecuteEpilogue ; forward ;
-
- procedure SetDefaults ;
- {*
- * Set the default values for the CP/M and MS-DOS drive names. Upon
- * exit, the MS-DOS drive is assigned and installed!
- *}
- var
- NewDate: DateStrings ; { Today's date }
- Code : Char ; { Command character }
- const
- OSName : array[Oss] of string[ 6] =
- ( 'CP/M', 'MS-DOS' ) ;
- NameOfClass: array[FileClasses] of string[12] =
- ( 'Text file', 'Binary file', 'Ask per file' ) ;
- YesNo : array[Boolean] of string[ 3] =
- ( ' No', 'Yes' ) ;
-
- procedure ReadByte( var SomeByte: Byte ) ;
- {*
- * Read the (new) value for one of the padding characters.
- *}
- var
- NextChar: Char ; { Next character read }
-
- procedure ReadNextCharacter ;
- {*
- * Read and process one nibble (a four-bit quantity).
- *}
- var
- Found: Boolean ; { Legal character entered }
- begin
- repeat
- Read( Kbd, NextChar ) ;
- NextChar:= UpCase( NextChar ) ;
- Found:= (NextChar in ['0'..'9','A'..'F',^M]) ;
- if not Found then
- Write( ^G ) ;
- until Found ;
- Write( NextChar ) ;
- if NextChar<>^M then
- begin
- SomeByte:= (SomeByte shl 4) + Ord(NextChar) ;
- if NextChar<'A' then
- SomeByte:= SomeByte - Ord('0')
- else
- SomeByte:= SomeByte - Ord('A') + 10 ;
- end ; { of if }
- end ; { of ReadNextCharacter }
-
- begin
- Write( ^M^J'Enter hex character code : $' ) ;
- SomeByte:= 0 ;
- ReadNextCharacter ;
- if NextChar<>^M then
- ReadNextCharacter ;
- end ; { of ReadByte }
-
- procedure SetCpmOptions ;
- var
- Code: Char ; { Command code }
- begin
- repeat
- DisplayTitle( 'MS-DOS -> CP/M copy options' ) ;
- DisplayMenuHead ;
- WriteLn( ' <C> Copy file attributes = ', YesNo[CopyCpmFileAttr] ) ;
- WriteLn( ' <F> File type = ', NameOfClass[FileClass] ) ;
- WriteLn( ' <T> Text file pad char. = $', Hex(CpmTxtFillChar,2) ) ;
- WriteLn( ' <B> Binary file pad char.= $', Hex(CpmBinFillChar,2) ) ;
- DisplayMenuTail ;
- ReadCommand( Code ) ;
- case Code of
- 'B' : ReadByte( CpmBinFillChar ) ;
- 'C' : CopyCpmFileAttr:= not CopyCpmFileAttr ;
- 'F' : if FileClass=AskUser then
- FileClass:= TextFile
- else
- FileClass:= Succ( FileClass ) ;
- 'Q' : ;
- 'T' : ReadByte( CpmTxtFillChar ) ;
- else
- IllegalCommand ;
- end ; { of cases }
- until Code='Q' ;
- end ; { of SetCpmOptions }
-
- procedure SetMsdosOptions ;
- var
- Code: Char ; { Command code }
- begin
- repeat
- DisplayTitle( 'CP/M -> MS-DOS copy options' ) ;
- DisplayMenuHead ;
- WriteLn( ' <C> Copy file attributes = ', YesNo[CopyMsdosFileAttr] ) ;
- WriteLn( ' <P> Cluster pad character = $', Hex(MsdosFillChar,2) ) ;
- WriteLn( ' <F> File type = ', NameOfClass[FileClass] ) ;
- DisplayMenuTail ;
- ReadCommand( Code ) ;
- case Code of
- 'C' : CopyMsdosFileAttr:= not CopyMsdosFileAttr ;
- 'F' : if FileClass=AskUser then
- FileClass:= TextFile
- else
- FileClass:= Succ( FileClass ) ;
- 'P' : ReadByte( MsdosFillChar ) ;
- 'Q' : ;
- else
- IllegalCommand ;
- end ; { of cases }
- until Code='Q' ;
- end ; { of SetMsdosOptions }
-
- begin
- repeat
- DisplayTitle( 'Set default values' ) ;
- DisplayMenuHead ;
- WriteLn( ' <C> CP/M default drive/user = ',
- ExpandFileName(CpmDriveName,DU_Format):4 ) ;
- WriteLn( ' <M> MS-DOS drive = ',
- MsdosDriveName:3, ':' ) ;
- WriteLn( ' <S> Source drive = ',
- OSName[SourceOs] ) ;
- WriteLn ;
- WriteLn( ' <T> Today''s date = ', TodaysDate ) ;
- WriteLn( ' <D> Display disk parameters >' ) ;
- WriteLn( ' <A> CP/M -> MS-DOS copy options >' ) ;
- WriteLn( ' <B> MS-DOS -> CP/M copy options >' ) ;
- WriteLn ;
- Write ( ' <E> Exit from program' ) ;
- DisplayMenuTail ;
- ReadCommand( Code ) ;
- case Code of
- 'A' : SetMsdosOptions ;
- 'B' : SetCpmOptions ;
- 'C' : begin
- WriteLn ;
- SetCpmDrive ;
- end ; { of case C }
- 'D' : DisplayMsdosDiskParameters ;
- 'E' : begin
- ExecuteEpilogue ; { Clean up BIOS tables }
- UnInitFileNameUnit ; { Remove BDOS shell }
- Halt ;
- end ; { of case E }
- 'M' : begin
- WriteLn ;
- SetMsdosDrive ;
- end ; { of case M }
- 'Q' : if MsdosDriveName='?' then
- begin
- FlagError( 'SetD: MS-DOS drive unspecified' ) ;
- Code:= '?' ; { Inhibit termination of the loop }
- end ; { of case Q }
- 'S' : if SourceOS=Cpm then
- begin
- SourceOS := Msdos ;
- DestinationOS:= Cpm ;
- end
- else { if SourceOS=Msdos then }
- begin
- SourceOS := Cpm ;
- DestinationOS:= Msdos ;
- end ; { of if/case 'X' }
- 'T' : begin
- WriteLn ;
- Write( 'Enter date [yyyymmdd] : ' ) ;
- ReadLn( NewDate ) ;
- SetTodaysDate( NewDate ) ;
- end ; { of case 'T' }
- else
- IllegalCommand ;
- end ; { of case }
- ReportError ;
- until Code='Q' ;
- end ; { of SetDefaults }
-
- procedure EnterFileManager ;
- {*
- * Enter a line-oriented filemanager a la SWEEP. For a proper operation of
- * this procedure, the MS-DOS drive should be assigned (set). In other words,
- * the MsdosDriveName should not be '?'.
- *}
- type
- PathNames = string[40] ; { Description of path to source/destination }
- CommandCodes= ' '..'~' ; { Set of possible command codes }
- var
- AllowedCommands: set of CommandCodes ; { Currently allowed commands }
- PathName : array[OSs] of PathNames ; { Cpm & Msdos paths }
-
- NewHeader: Boolean ; { Display screen header (again) }
- NewLine : Boolean ; { Display file entry on a new line }
- Code : Char ; { Command code }
- I : Integer ; { Loop control variable }
-
- procedure AskFileClass ;
- begin
- if ReadYesNoAnswer( 'Text file' )='Y' then
- FileClass:= TextFile
- else
- FileClass:= BinaryFile ;
- end ; { of AskFileClass }
-
- procedure DeleteFile( OS: OSs ) ;
- begin
- if OS=Cpm then DeleteCpmFile
- else DeleteMsdosFile ;
- end ; { of DeleteFile }
-
- function GetFreeSpace( OS: OSs ) : Integer ;
- begin
- if OS=CPm then GetFreeSpace:= GetCpmFreeSpace
- else GetFreeSpace:= GetMsdosFreeSpace ;
- end ; { of GetFreeSpace }
-
- function LocateFile( OS: OSs ) : Boolean ;
- begin
- if OS=Cpm then LocateFile:= LocateCpmFile
- else LocateFile:= LocateMsdosFile ;
- end ; { of LocateFile }
-
- procedure ChangeMsdosPath ;
- {*
- * Change the MS-DOS path to the directory associated with the current
- * file entry.
- *}
- type
- NameString= string[11] ; { String to contain file name }
- var
- SubDirName: NameString ; { Name of (sub)directory }
-
- function Trim( SomeString: NameString ) : NameString ;
- {*
- * Remove the trailing spaces from a name.
- *}
- begin
- while (Length(SomeString)>0) and (SomeString[Length(SomeString)]=' ') do
- Delete( SomeString, Length(SomeString), 1 ) ;
- Trim:= SomeString ;
- end ; { of Trim }
-
- begin
- if LocateMsdosDirectory then
- begin
- {*
- * Save the number of the first cluster containing the FCB's of this
- * (sub)directory. A zero value indicates the root directory. Note that
- * the other Directory... variables are set at the initialisation of a
- * new search through the (sub)directory.
- *}
- DirectoryStartCls:= MsdosFcb^.Cluster ;
- {*
- * Update the name of the path to the current directory.
- *}
- SubDirName:= Trim( MsdosFcb^.FileName ) ;
- if SubDirName='.' then
- { do nothing }
- else
- if SubDirName='..' then
- DirectoryNesting:= Pred( DirectoryNesting )
- else
- begin
- DirectoryNesting:= Succ( DirectoryNesting ) ;
- if DirectoryNesting<=MsdosPathSize then
- MsdosPath[DirectoryNesting]:= SubDirName + '\' ;
- end { of else/else }
- end
- else
- FlagError( 'ChaMP: Can''t find directory ' + FileEntry^.Name ) ;
- end ; { of ChangeMsdosPath }
-
- procedure CopyFile ;
- {*
- * Copy one file from the source disk to the destination disk.
- *}
- var
- OrigFileClass: FileClasses ; { Original file class }
- begin
- if not IsFile then
- begin
- Write( 'Can''t copy it.' ) ;
- Exit ;
- end ; { of if }
- {*
- * Check if a file of that name already exeists on the destination disk. If
- * so, ask the user if that file can be destroyed. If not, exit immediatly.
- *}
- if LocateFile( DestinationOS ) then
- if not ErrorDetected then
- if ReadYesNoAnswer( 'Overwrite file' )='Y' then
- DeleteFile( DestinationOS )
- else
- Exit ;
- {*
- * See if there is enough room on the destination disk to copy the file.
- *}
- if not ErrorDetected then
- if FileEntry^.Size>GetFreeSpace(DestinationOS) then
- FlagError( ^H': Not enough space on destination disk' ) ;
- {*
- * Determine the type if file. This information is needed either to
- * determine the real end-of-file position (copy to MS-DOS) or to determine
- * padding of the last record (copy to CP/M).
- *}
- if not ErrorDetected then
- begin
- OrigFileClass:= FileClass ;
- if FileClass=AskUser then AskFileClass ;
-
- if SourceOS=Cpm then WriteMsdosFile { Finally, go copy the file }
- else ReadMsdosFile ;
-
- FileClass:= OrigFileClass ;
- end ; { of if }
-
- if not ErrorDetected then
- Write( 'Done.' )
- else
- BuildErrorTrace( 'CopF_' ) ;
- end ; { of CopyFile }
-
- procedure CopyTaggedFiles ;
- {*
- * Copy all the tagged files to the destination disk.
- *}
- begin
- FileEntry:= HeadFileList ;
- while FileEntry<>TailFileList do
- begin
- if FileEntry^.Mark then
- begin
- WriteLn ;
- Write ( 'Copying --> ', GetFileEntryName, ' : ' ) ;
- CopyFile ;
- if ErrorDetected then
- begin
- ReportError ;
- FileEntry:= TailFileList^.Prev ; { Terminate while loop }
- end
- else { if there is no error detected }
- begin
- FileEntry^.Mark:= False ;
- SizeTaggedFiles:= SizeTaggedFiles - FileEntry^.Size ;
- end ; { of else }
- end ; { of if }
- FileEntry:= FileEntry^.Next ;
- end ; { of while }
-
- FileEntry:= HeadFileList ;
- FileIndex:= 1 ;
- end ; { of CopyTaggedFiles }
-
- procedure DisplayFreeSpace ;
- {*
- * Display the free disk space on both the CP/M and the MS-DOS disk.
- *}
- begin
- WriteLn ;
- WriteLn( 'Free disk space on CP/M drive ', ExtractDisk(CpmDriveName),
- ': is ', GetCpmFreeSpace:4, ' KByte.' ) ;
- WriteLn( 'Free disk space on MS-DOS drive ', MsdosDriveName,
- ': is ', GetMsdosFreeSpace:4, ' KByte.' ) ;
- end ; { of displayFreeSpace }
-
- procedure DisplayHelp ;
- {*
- * Display a short summary of all the supported filemanager commands.
- *}
- begin
- WriteLn ; WriteLn ;
- WriteLn( ' < > Advance one file | <P> Change MS-DOS path' ) ;
- WriteLn( ' <B> Back one file | <Q> Quit' ) ;
- WriteLn( ' <C> Copy file | <S> Select MS-DOS drive' ) ;
- WriteLn( ' <D> Delete file | <T> Tag file' ) ;
- WriteLn( ' <E> Erase tagged files | <U> Untag file' ) ;
- WriteLn( ' <F> Show free disk space | <W> Wildcard tag' ) ;
- WriteLn( ' <L> Login CP/M drive | <X> Swap CP/M <-> MS-DOS' ) ;
- WriteLn( ' <M> Copy tagged files | <Z> Set defaults' ) ;
- WriteLn ;
- end ; { of DisplayHelp }
-
- procedure EraseFile ;
- {*
- * Erase (delete) the file associated with current filelist entry and
- * change the filelist to reflect this modification.
- *}
- begin { of EraseFile }
- {*
- * Only a file can be deleted. Exit if the entry is not a file.
- *}
- if not IsFile then
- begin
- Write( 'Can''t delete it.' ) ;
- Exit ;
- end ; { of if }
-
- if ReadYesNoAnswer( 'Delete' )='Y' then
- begin
- DeleteFile( SourceOS ) ;
- DeleteFileEntry ; { Adjusts SizeTaggedFiles too! }
- end
- else { do not delete this file after all }
- {*
- * Advance to the next file in the list. Thus, upon exit of this procedure,
- * the 'current' file entry is ALWAYS advanced, whether or not the file has
- * been deleted. The procedure EraseTaggedFiles needs this behaviour! Note
- * that only FILES can be tagged, thus if the 'IsFile' test at the beginning
- * of this procedure is negative, there is no need to advance to the next
- * file entry.
- *}
- AdvanceFileEntry ;
- end ; { of EraseFile }
-
- procedure EraseTaggedFiles ;
- {*
- * Erase (delete) all the tagged files. For each file the user must
- * acknowledge that the file must be deleted.
- *}
- begin
- FileEntry:= HeadFileList ;
- while FileEntry<>TailFileList do
- begin
- if FileEntry^.Mark then
- begin
- WriteLn ;
- Write ( 'Deleting --> ', GetFileEntryName, ' : ' ) ;
- EraseFile ;
- end
- else { the file entry is not marked }
- FileEntry:= FileEntry^.Next ;
- end ; { of while }
- FileEntry:= HeadFileList ;
- FileIndex:= 1 ;
- end ; { of EraseTaggedFiles }
-
- begin { of EnterFileManager }
- {*
- * Preset the control variables and build a file list from the directory on
- * the source drive. If an error is detected while reading the directory,
- * exit from the file manager.
- *}
- if SourceOS=Cpm then ReadCpmDirectory
- else ReadMsdosDirectory ;
- if ErrorDetected then
- begin
- ReportError ;
- Exit ;
- end ; { of if }
-
- (* SetWindow( 5, 24 ) ; { Define window for file manager } *)
- (* EnableWindow ; *)
- NewHeader:= True ;
- NewLine := True ;
- repeat
- CpmCurrentDrive:= Bdos( GetCurrentDrive ) ;
- {*
- * Display the header every time the CP/M drive/user selection or the MS-DOS
- * drive selection has changed. The header identifies the source and the
- * destination of any copy command. Note that in one of the WriteLn's the
- * assumption is hidden that the line width is 80 characters.
- *}
- if NewHeader then
- begin
- DisplayTitle( 'File Manager' ) ;
- PathName[Cpm ]:= 'CP/M, ' +
- ExpandFileName( CpmDriveName, DU_Format) ;
- PathName[Msdos]:= 'MS-DOS, ' + MsdosDriveName + ':' ;
- I:= 0 ;
- repeat
- PathName[Msdos]:= PathName[Msdos] + MsdosPath[I] ;
- I:= Succ( I ) ;
- until (I>DirectoryNesting) or (I>MsdosPathSize) ;
-
- WriteLn( 'Source = ', PathName[SourceOS],
- ' ':55-Length(PathName[Cpm])-Length(PathName[Msdos]),
- ' Destination = ', PathName[DestinationOS] ) ;
- NewHeader:= False ;
- end ; { of if }
- {*
- * Determine the set of allowed commands. If the filelist is empty, the file
- * operations are not allowed (as they are not sensible).
- *}
- AllowedCommands:=[' ','.','?','B','C','D','E','F', { All command codes }
- 'L','M','P','Q','S','T','U','W','X','Z'] ;
- if SizeFileList=0 then
- begin
- AllowedCommands:= ['?','F','L','Q','S','X','Z'] ;
- if NewLine then
- Write( ^M^J'No files. ' ) ;
- NewLine:= False ;
- end ; { of if }
- {*
- * Display the current file entry. Only in case of an erroneous command,
- * the file entry is not re-displayed.
- *}
- if NewLine then
- DisplayFileEntry ;
- NewLine:= True ;
- {*
- * Read the next command for the file manager from the keyboard device. All
- * non-printable characters are mapped onto the dot to make it visible.
- *}
- Read ( Kbd, Code ) ;
- if not (Code in [' '..'~']) then
- Code:= '.' ;
- Write( Code, ' ' ) ;
- Code:= UpCase( Code ) ;
- if Code in AllowedCommands then
- {*
- * Process the next file manager command.
- *}
- case Code of
- ' ',
- '.' : AdvanceFileEntry ;
- '?' : DisplayHelp ;
- 'B' : BackupFileEntry ;
- 'C' : CopyFile ;
- 'D' : EraseFile ;
- 'E' : EraseTaggedFiles ;
- 'F' : DisplayFreeSpace ;
- 'L' : begin
- SetCpmDrive ;
- if SourceOS=Cpm then
- ReadCpmDirectory ;
- NewHeader:= True ;
- end ; { of case 'L' }
- 'M' : CopyTaggedFiles ;
- 'P' : begin
- if IsDirectory { and SourceOS=Msdos } then
- begin
- ChangeMsdosPath ;
- ReadMsdosDirectory ;
- NewHeader:= True ;
- end { of if }
- else
- begin
- Write( ^G^H^H' '^H ) ;
- NewLine:= False ;
- end ; { of else }
- end ; { of case 'P' }
- 'Q' : ;
- 'S' : begin
- SetMsdosDrive ;
- if (SourceOS=Msdos) and (MsdosDriveName<>'?') then
- ReadMsdosDirectory ;
- NewHeader:= True ;
- end ; { of case 'S' }
- 'T' : begin
- TagFileEntry ;
- AdvanceFileEntry ;
- end ; { of case 'T' }
- 'U' : begin
- UntagFileEntry ;
- AdvanceFileEntry ;
- end ; { of case 'U' }
- 'W' : TagMultipleFileEntries ;
- 'X' : if SourceOS=Cpm then
- begin
- NewHeader := True ;
- SourceOS := Msdos ;
- DestinationOS:= Cpm ;
- ReadMsdosDirectory ;
- end
- else { if SourceOS=Msdos then }
- begin
- NewHeader := True ;
- SourceOS := Cpm ;
- DestinationOS:= Msdos ;
- ReadCpmDirectory ;
- end ; { of if/case 'X' }
- 'Z' : begin
- SetDefaults ;
- Newheader:= True ;
- end ; { of case 'Z' }
- end { of cases }
- {*
- * The command code is not supported or perhaps not allowed just now. Give
- * an audible error indication and wipe-out the command code on the screen.
- *}
- else
- begin
- Write( ^G^H^H' '^H ) ; { Remove illegal command code }
- NewLine:= False ; { Do not write a next line }
- end ; { of else }
- ReportError ;
- {*
- * If the command to select another MS-DOS drive failed, indicated by a '?'
- * for the name, the user MUST select another drive, until it succeeds.
- *}
- if MsdosDriveName='?' then
- begin
- SetDefaults ; { Force selection of another MS-DOS drive }
- NewHeader:= True ;
- end ; { of if }
- until Code='Q' ;
-
- (* DisableWindow ; *)
- end ; { of EnterFileManager }
-