{ CP/M-80 directory program written in Turbo Pascal 2.0. Based loosely on wildcard.pas, author and compiler unknown. Accepts ambiguous file names and displays sorted directory. File sizes rounded to next 1k increment. Steve Fox - Albuquerque RCP/M (505)299-5974 Version 1.0 29 Mar 1985 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Revised 23 Apr 85 by : William L. Mabee, CRNA Followin attributes added Functions : Centered Dash ConstStr Procedures : PutItUp Changed Code to allow automatic display of logged DU directory will allow code to be included in Turbo Pascal Program or chaining from main turbo routine. Added prompt for which drive change source for your own system if you have more than two drives add something like ['A..P']; and change appropriate prompt. Added code to display total amount disk space used. Added header. } Program dir; label start; const columns = 4; fence = ' | '; header = 'File Ext Size File Ext Size File Ext Size File Ext Size'; type CharSet = set of char; FileName = string[14]; { d:filename.ext } str80 = string[80]; StrStd = string[127]; FilePtr = ^FileDescr; FileDescr = record fname: FileName; { Name of a matching file } fsize: integer; { Size of file } Next: FilePtr; { Points to next name on linked list } end; FileBlock = record case boolean of true: (drive: byte; { Byte code } fname: array[1..11] of char; { File name } extent, { Current extent } s1, s2, reccount: byte; { Used to compute file size } dn: array[16..31] of byte); false: (init: array[1..32] of byte); end; var CH : Char; entries: integer; { Count of directory entries } prototype: FileName; { Directory mask } first: FilePtr; { Start of linked list } searchblk: FileBlock; { Block for search } CtrPrg: File; Function ConstStr(C : Char; N : Integer) : Str80; var S : string[80]; begin if N < 0 then N := 0; S[0] := Chr(N); FillChar(S[1],N,C); ConstStr := S; end; Function Centered(TheString:Str80):Str80; begin Centered := ConstStr(' ',((80 - Length(TheString)) Div 2)) + TheString; end; Function Dash(Spaces : Integer) : Str80; var Column : Integer; Temp : Str80; begin Temp :=''; For Column := 1 to Spaces do begin Temp := Temp + '-'; Dash := Temp; end; end; Function Tab(Spaces : Integer) : Str80; var Column : Integer; Temp : Str80; begin Temp :=''; For Column := 1 to Spaces do begin Temp := Temp + '-'; Dash := Temp; end; end; Procedure Choice( Prompt : Str80; Term : CharSet; var TC : Char ); var Ch : Char; begin GotoXY(1,23); Write(Prompt); ClrEol; repeat Read(Kbd,Ch); TC := Upcase(Ch); if not (TC in Term) then write(^G); until TC in Term; Write(Ch); end; Procedure ClearFrame; var I : Integer; begin for I := 20 downto 3 do begin GotoXY(1,I + 1); ClrEol ; end; end; procedure GetMask(var prototype: FileName); { Get ambiguous file name and expand into directory mask (prototype) } var i, j: integer; line: StrStd; function trim(st: StrStd): StrStd; { Trim leading and trailing blanks } var i, j: integer; begin i := 1; j := length(st); while (st[i] = ' ') and (i <= j) do i := succ(i); while (st[j] = ' ') and (j >= i) do j := pred(j); trim := copy(st, i, j - i + 1) end; function pad(line: StrStd; i: integer): StrStd; { Pad line with spaces to length of i } begin while length(line) < i do line := line + ' '; pad := line end; begin repeat Choice('Directory for which drive ( A or B ) ? ',['A','B'],Ch); until Ch <> ''; ClearFrame; line := Ch+':*.*'; line := trim(line); for i := 1 to length(line) do line[i] := UpCase(line[i]); if line = '' then line := '*.*'; line := pad(line, 14); prototype := copy(line, 1, 14); FillChar(searchblk.init, 32, 0); with searchblk do begin if prototype[2] = ':' then begin drive := succ(ord(prototype[1]) - ord('A')); i := 3 end else begin drive := 0; i := 1 end; fname := ' '; j := 1; repeat begin if prototype[i] = '*' then while j <= 8 do begin fname[j] := '?'; j := succ(j) end else begin fname[j] := prototype[i]; j := succ(j) end end; i := succ(i) until (j > 8) or (prototype[i] = '.'); while (prototype[i] <> '.') and (prototype[i] <> ' ') do i := succ(i); i := succ(i); j := 9; repeat begin if prototype[i] = '*' then while j <= 11 do begin fname[j] := '?'; j := succ(j) end else begin fname[j] := prototype[i]; j := succ(j) end end; i := succ(i) until (j > 11) or (prototype[i] = '.'); extent := ord('?'); s1 := ord('?'); s2 := ord('?') end end; procedure ReadDir(prototype: filename; var entries: integer; var first: FilePtr); { Create an alphabetized list of files which match the prototype } const findfirst = 17; { BDOS function - search for first file } findnext = 18; { BDOS function - search for next file} setdma = 26; { BDOS function - set dma buffer address } fcb = $80; { Default dma buffer address } type dirblock = array [0..3] of FileBlock; fileblptr = ^FileBlock; var off: integer; { dir entry offset or end flag } fn: FileName; answerblk: dirblock; { block to receive file name } procedure insertfile(fn: FileName; fs: integer; var entries: integer; var first: FilePtr); { Insert a new file name in the alphabetic list } var f, { file name entry being created } this, previous: FilePtr; { followers for insertion } begin previous := nil; this := first; while (this <> nil) and (this^.fname < fn) do begin previous := this; this := this^.next end; if this^.fname <> fn then begin entries := succ(entries); new(f); f^.fname := fn; f^.fsize := fs; f^.next := this; if previous = nil then first := f else previous^.next := f end else if this^.fsize < fs then this^.fsize := fs end; begin { ReadDir } entries := 0; first := nil; BDOS(setdma, addr(answerblk)); off := BDOS(findfirst, addr(searchblk)); while off <> 255 do begin with answerblk[off] do if (ord(fname[10]) and $80) = 0 { Non-system? } then begin drive := 11; { File name length } move(drive, fn, 12); { File name } insert('.', fn, 9); insertfile(fn, reccount + (extent + (s2 shl 5)) shl 7, entries, first) end; off := BDOS(findnext, addr(searchblk)); end; BDOS(setdma, fcb) { Restore DMA buffer } end; procedure DispDir(entries: integer; first: FilePtr); { Display directory list } var i, size,totsize: integer; OldName: FilePtr; begin i := 0; totsize := 0; GotoXY(1,6); WriteLn(Header); WriteLn; while first <> nil do begin { Scan the whole list } size := first^.fsize shr 3; totsize := totsize + size; if 0 <> (first^.fsize mod 8) then size := succ(size); write(first^.fname, size:4, 'k'); i := succ(i); Oldname := first; first := first^.Next; { Go to next on chain } dispose(Oldname); { Reclaim space } if i < columns then write(fence) else begin writeln; i := 0 end end; WriteLn; WriteLn; write('Total number of Files : ',entries); writeln(' Using a total of : ',totsize,' K'); end; begin { main } ClrScr; GotoXY(1,1); Writeln(ConstStr('-',79)); WriteLn; Write(ConstStr('-',79)); GotoXY(1,2); Write(Centered('Disk Directory Routine')); GotoXY(1,22); Writeln(ConstStr('-',79)); WriteLn; Write(ConstStr('-',79)); start : clearFrame; GetMask(prototype); { Read mask } ReadDir(prototype, entries, first); { Read directory } DispDir(entries, first); { Display directory } repeat Choice('Do directory on another drive ( Y or N ) : ',['Y','N'],CH); if Ch = 'Y' then goto start; until Ch = 'N'; ClrScr; end.