[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]