[Back to FILES SWAG index]  [Back to Main SWAG index]  [Original]

{ File Viewer Object  }

uses Dos, Crt;

const
   PrintSet: set of $20..$7E = [ $20..$7E ];
   ExtenSet: set of $80..$FE = [ $80..$FE ];
   NoPrnSet: set of $09..$0D = [ $09, $0A, $0D ];

type
   CharType = ( Unknown, Ascii, Hex );
   DataBlock = array[1..256] of byte;
   Viewer = object
               XOrg, YOrg,
               LineLen, LineCnt, BlockCount : integer;
               FileName : string;
               FileType : CharType;
               procedure FileOpen( Fn : string;
                                   X1, Y1, X2, Y2 : integer );
               function  TestBlock( FileBlock : DataBlock;
                                    Count : integer ): CharType;
               procedure ListHex( FileBlock : DataBlock;
                                  Count, Ofs : integer );
               procedure ListAscii( FileBlock : DataBlock;
                                    Count : integer );
            end;

   Finder = object( Viewer )
               procedure Search( Fn, SearchStr : string;
                                 X1, Y1, X2, Y2 : integer );
            end;

procedure Finder.Search;
   var
      VF : file;   Result1, Result2 : word;
      BlkOfs, i, j, SearchLen : integer;
      SearchArray : array[1..128] of byte;
      EndFlag, BlkDone, SearchResult : boolean;
      FileBlock1, FileBlock2, ResultArray : DataBlock;
   begin
      BlockCount := 0;
      XOrg := X1;
      YOrg := Y1;
      LineLen := X2;
      LineCnt := Y2;
      FileType := Unknown;
      SearchLen := ord( SearchStr[0] );
      for i := 1 to Searchlen do
         SearchArray[i] := ord( SearchStr[i] );
      for i := 1 to sizeof( ResultArray ) do
         ResultArray[i] := $00;

      assign( VF, Fn );
      {$I-} reset( VF, 1 ); {$I+}
      if IOresult = 0 then
      begin
         EndFlag := false;
         BlkDone := false;
         SearchResult := false;
         BlockRead( VF, FileBlock2, sizeof( FileBlock2 ), Result2 );
         EndFlag := Result2 <> sizeof( FileBlock2 );
         repeat
            FileBlock1 := FileBlock2;
            Result1 := Result2;
            FileBlock2 := ResultArray;
            if not EndFlag then
            begin
               BlockRead( VF, FileBlock2, sizeof( FileBlock2 ), Result2 );
               inc( BlockCount );
               EndFlag := Result2 <> sizeof( FileBlock2 );
            end else BlkDone := True;
            for i := 1 to Result1 do
            begin
               if SearchArray[1] = FileBlock1[i] then
               begin
                  BlkOfs := i-1;
                  SearchResult := true;
                  for j := 1 to SearchLen do
                  begin
                     if i+j-1 <= Result1 then
                     begin
                        if SearchArray[j] = FileBlock1[i+j-1] then
                           ResultArray[j] := FileBlock1[i+j-1] else
                           begin
                              SearchResult := false;
                              j := SearchLen;
                           end;
                     end else
                        if SearchArray[j] = FileBlock2[i+j-257] then
                           ResultArray[j] := FileBlock2[i+j-257] else
                           begin
                              SearchResult := false;
                              j := SearchLen;
                           end;
                  end;
                  if SearchResult then
                  begin
                     for j := SearchLen+1 to sizeof( ResultArray ) do
                        if i+j-1 <= Result1
                           then ResultArray[j] := FileBlock1[i+j-1]
                           else ResultArray[j] := FileBlock2[i+j-257];
                     i := Result1;
                  end;
               end;
            end;
         until BlkDone or SearchResult;
         if SearchResult then
         begin
            writeln( 'Search string found in file block ', BlockCount,
               ' beginning at byte offset ', BlkOfs, ' ...' );
            writeln;
            if FileType = Unknown then
               FileType := TestBlock( ResultArray,
                                      sizeof( ResultArray ) );
            case FileType of
                 Hex : ListHex( ResultArray, sizeof( ResultArray ), BlkOfs );
               Ascii : ListAscii( ResultArray, sizeof( ResultArray ) );
            end;
         end else writeln( '"', SearchStr, '" not found in ', FN );
         close( VF );
         window( 1, 1, 80, 25 );
      end else writeln( Fn, ' invalid file name!' );
   end;

procedure Viewer.FileOpen;
   var
      VF : file;      Ch : char;
      Result, CrtX, CrtY : word;
      EndFlag : boolean;
      FileBlock : DataBlock;
   begin
      BlockCount := 0;
      XOrg := X1;
      YOrg := Y1;
      LineLen := X2;
      LineCnt := Y2;
      FileType := Unknown;
      assign( VF, Fn );
      {$I-} reset( VF, 1 ); {$I+}
      if IOresult = 0 then
      begin
         window( X1, Y1, X1+X2-1, Y1+Y2-1 );
         writeln;
         EndFlag := false;
         repeat
            BlockRead( VF, FileBlock, sizeof( FileBlock ), Result );
            inc( BlockCount );
            EndFlag := Result <> sizeof( FileBlock );
            if FileType = Unknown then
               FileType := TestBlock( FileBlock, Result );
            case FileType of
                 Hex : ListHex( FileBlock, Result, 0 );
               Ascii : ListAscii( FileBlock, Result );
            end;
            if not EndFlag then
            begin
               CrtX := WhereX;    CrtY := WhereY;
               if WhereY = LineCnt then
               begin   writeln;
                       dec( CrtY );  end;
               gotoxy( 1, 1 );    clreol;
               write(' Viewing: ', FN );
               gotoxy( 1, LineCnt );   clreol;
               write(' Press (+) to continue, (Enter) to exit: ');
               Ch := ReadKey;     EndFlag := Ch <> '+';
               gotoxy( 1, LineCnt );   clreol;
               gotoxy( CrtX, CrtY );
            end;
         until EndFlag;
         close( VF );
         sound( 440 ); delay( 100 );
         sound( 220 ); delay( 100 ); nosound;
         window( 1, 1, 80, 25 );
      end else writeln( Fn, ' invalid file name!' );
   end;

function Viewer.TestBlock;
   var
      i : integer;
   begin
      FileType := Ascii;
      for i := 1 to Count do
         if not FileBlock[i] in NoPrnSet+PrintSet then
            FileType := Hex;
      TestBlock := FileType;
   end;

procedure Viewer.ListHex;
   const
      HexStr: string[16] = '0123456789ABCDEF';
   var
      i, j, k : integer;
   begin
      k := 1;
      repeat
         write(' ');
         j := (BlockCount-1) * sizeof( FileBlock ) + ( k - 1 ) + Ofs;
         for i := 3 downto 0 do
            write( HexStr[ j shr (i*4) AND $0F + 1 ] );
         write(': ');
         for i := 1 to 16 do
         begin
            if k <= Count then
               write( HexStr[ FileBlock[k] shr 4 + 1 ],
                      HexStr[ FileBlock[k] AND $0F + 1 ], ' ' )
               else write( '  ' );
            inc( k );
            if( i div 4 = i / 4 ) then write(' ');
         end;
         for i := k-16 to k-1 do
         if i <= Count then
            if FileBlock[i] in PrintSet+ExtenSet
               then write( chr( FileBlock[i] ) )
               else write('.');
         writeln;
      until k >= Count;
   end;

procedure Viewer.ListAscii;
   var
      i : integer;
   begin
      for i := 1 to Count do
      begin
         write( chr( FileBlock[i] ) );
         if WhereX > LineLen then writeln;
         if WhereY >= LineCnt then
         begin
            writeln;
            gotoxy( 1, LineCnt-1 );
         end;
      end;
   end;

{=============== end Viewer object ==============}

var
   FileFind : Finder;
begin
   clrscr;
   FileFind.Search( ParamStr(0),    { file to search }
                    'Press any key',           { search string  }
                    1, 1, 80, 25 );            { display window }
   gotoxy( 1, 25 );   clreol;
   write( 'Press any key to continue: ');
   while not KeyPressed do;
end.

[Back to FILES SWAG index]  [Back to Main SWAG index]  [Original]