/* * $Id$ */ /* * Harbour Project source code: * Text file browser class * * Copyright 1999 {list of individual authors and e-mail addresses} * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version, with one exception: * * The exception is that if you link the Harbour Runtime Library (HRL) * and/or the Harbour Virtual Machine (HVM) with other files to produce * an executable, this does not by itself cause the resulting executable * to be covered by the GNU General Public License. Your use of that * executable is in no way restricted on account of linking the HRL * and/or HVM code into it. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit * their web site at http://www.gnu.org/). * */ #include "hbclass.ch" #include "common.ch" #include "fileio.ch" #define MAX_LINE_LEN 256 #define FTELL( nHandle ) FSEEK( nHandle, 0, FS_RELATIVE ) CLASS TBrwText FROM TBrowse DATA cFileName // the name of the browsed file DATA nHandle // To hold the handle of the browsed file DATA nFileSize // bytes size of the browsed file DATA cLine // Currently selected text line DATA nLine METHOD New( nTop, nLeft, nBottom, nRight, cFileName, cColors ) METHOD GotoLine( nLine ) ENDCLASS METHOD New( nTop, nLeft, nBottom, nRight, cFileName, cColors ) CLASS TBrwText DEFAULT nTop TO 0 DEFAULT nLeft TO 0 DEFAULT nRight TO MaxCol() DEFAULT nBottom TO MaxRow() DEFAULT cColors TO SetColor() Super:New() ::nTop := nTop ::nLeft := nLeft ::nBottom := nBottom ::nRight := nRight ::ColorSpec := cColors ::cFileName := cFileName ::nHandle := FOpen( cFileName, FO_READ ) ::nFileSize := FSeek( ::nHandle, 0, FS_RELATIVE ) ::cLine := Space( ::nRight - ::nLeft - 2 ) ::nLine := 1 ::Autolite := .T. ::AddColumn( TbColumnNew( "", { || Alltrim( Str( ::nLine ) ) + ": " + ::cLine } ) ) ::GoTopBlock := {|| GoFirstLine( Self ) } ::GoBottomBlock := {|| GoLastLine( Self ) } ::SkipBlock := {| nLines | Skipper( Self, nLines ) } ::GoTop() return Self METHOD GotoLine( nLine ) CLASS TBrwText IF nLine > ::nLine DO WHILE ::nLine < nLine ::Down() ENDDO ::ForceStable() ELSE DO WHILE ::nLine > nLine ::Up() ENDDO ::ForceStable() ENDIF RETURN NIL STATIC FUNCTION GoFirstLine( oBrw ) LOCAL cLine FSeek( oBrw:nHandle, 0, FS_SET ) FReadLn( oBrw:nHandle, @cLine ) oBrw:cLine := cLine oBrw:nLine := 1 FSeek( oBrw:nHandle, 0, FS_SET ) RETURN NIL STATIC FUNCTION GoLastLine( oBrw ) LOCAL cLine := oBrw:cLine FSeek( oBrw:nHandle, -1, FS_END ) GoPrevLine( oBrw:nHandle, @cLine, oBrw:nFileSize ) oBrw:cLine := cLine RETURN NIL STATIC FUNCTION Skipper( oBrw, nLines ) LOCAL nSkipped := 0 LOCAL cLine := oBrw:cLine // Skip down IF nLines > 0 DO WHILE nSkipped != nLines .AND. GoNextLine( oBrw:nHandle, @cLine ) nSkipped++ ENDDO oBrw:cLine := cLine // Skip Up ELSE DO WHILE nSkipped != nLines .AND. GoPrevLine( oBrw:nHandle, @cLine, oBrw:nFileSize ) nSkipped-- ENDDO oBrw:cLine := cLine ENDIF oBrw:nLine += nSkipped RETURN nSkipped STATIC FUNCTION FReadLn( nHandle, cBuffer ) LOCAL nEOL // End Of Line Postion LOCAL nRead // Number of characters read LOCAL nSaveFPos // Saved File Postion cBuffer := Space( MAX_LINE_LEN ) // First save current file pointer nSaveFPos := FSeek( nHandle, 0, FS_RELATIVE ) nRead := FRead( nHandle, @cBuffer, MAX_LINE_LEN ) IF ( nEOL := At( Chr( 13 ) + Chr( 10 ), SubStr( cBuffer, 1, nRead ) ) ) == 0 .AND. ; ( nEOL := At( Chr( 10 ), SubStr( cBuffer, 1, nRead ) ) ) == 0 // Line overflow or eof // ::cLine has the line we need ELSE // Copy up to EOL cBuffer := SubStr( cBuffer, 1, nEOL - 1 ) // Position file pointer to next line FSeek( nHandle, nSaveFPos + nEOL + 1, FS_SET ) ENDIF RETURN nRead != 0 STATIC FUNCTION GoPrevLine( nHandle, cLine, nFileSize ) LOCAL nOrigPos // Original File Pointer Position LOCAL nMaxRead // Maximum Line Length LOCAL nNewPos // New File Pointer Position LOCAL lMoved // Pointer Moved LOCAL cBuff // Line buffer LOCAL nWhereCrLf // Position of CRLF LOCAL nPrev // Previous File Pointer Position // Save Original file position nOrigPos := FSEEK( nHandle, 0, FS_RELATIVE ) IF nOrigPos == 0 lMoved := FALSE ELSE lMoved := TRUE IF nOrigPos != nFileSize // Skip over preceeding CR / LF FSeek( nHandle, -2, FS_RELATIVE ) ENDIF nMaxRead := Min( MAX_LINE_LEN, FTELL( nHandle ) ) // Capture the line into a buffer, strip off the CRLF cBuff := Space( nMaxRead ) nNewPos := FSeek( nHandle, -nMaxRead, FS_RELATIVE ) FRead( nHandle, @cBuff, nMaxRead ) IF ( nWhereCrLf := RAt( Chr( 13 ) + Chr( 10 ), cBuff ) ) == 0 .AND. ; ( nWhereCrLf := RAt( Chr( 10 ), cBuff ) ) == 0 nPrev := nNewPos cLine := cBuff ELSE nPrev := nNewPos + nWhereCrLf + 1 cLine := SubStr( cBuff, nWhereCrLf + 2 ) ENDIF // Move to the beginning of the line FSeek( nHandle, nPrev, FS_SET ) ENDIF RETURN lMoved STATIC FUNCTION GoNextLine( nHandle, cLine ) LOCAL nSavePos // Save File pointer position LOCAL cBuff := "" // Line Buffer LOCAL lMoved // Pointer Moved LOCAL nNewPos // New File Pointer Position // Save the file pointer position nSavePos := FTELL( nHandle ) // Find the end of the current line FSeek( nHandle, Len( cLine ) + 2, FS_RELATIVE ) nNewPos := FTELL( nHandle ) // Read in the next line IF FReadLn( nHandle, @cBuff ) lMoved := .T. cLine := cBuff FSeek( nHandle, nNewPos, FS_SET ) ELSE lMoved := .F. FSeek( nHandle, nSavePos, FS_SET ) ENDIF RETURN lMoved