home *** CD-ROM | disk | FTP | other *** search
- // Tb27.prg
- //
- // Program sequence using tbrowse object to browse a file. Assumes
- // all lines are terminated with CR / LF
- //
- // Compile with /a /m /n /w
- //
- // Link with Tbutils, Dict
-
- #include "Fileio.ch"
- #include "Inkey.ch"
-
- #define CR Chr(13)
- #define LF Chr(10)
- #define CRLF CR + LF
-
- // File's current position
- #define FTELL(nHandle) Fseek(nHandle, 0, FS_RELATIVE)
-
- MEMVAR getlist
-
- #define K_SEARCH_FORWARD K_F2
- #define K_SEARCH_BACKWARD K_F3
-
- // Pass file name as a parameter
-
- FUNCTION Tb27(cFname)
-
- LOCAL oTbr, oTbc
- LOCAL lExitRequested := .F.
- LOCAL cSearcher, nSavefPos
- LOCAL aFileInfo
- LOCAL nKey
- LOCAL nLineOffset := 1
-
- SET SCOREBOARD OFF
- CLEAR SCREEN
- @ 23, 0 SAY "F2 - Search Forwards, F3 - Search Backwards"
-
- @ 0, 0 TO 22, 79
-
- IF (aFileInfo := FileInit(cFname)) != NIL
- oTbr := TBrowseNew(1, 1, 21, 78)
- oTbc := TBColumnNew(, {|| Substr(CurLine(aFileInfo), nLineOffset) })
-
- oTbc:width := 78
- oTbr:addColumn(oTbc)
-
- oTbr:goTopBlock := {| | GoFirst(aFileInfo) }
- oTbr:goBottomBlock := {| | GoLast(aFileInfo) }
- oTbr:skipBlock := {|n| FileSkip(n, aFileInfo) }
-
- DO WHILE !lExitRequested
- FullStabilize(oTbr)
-
- nKey := inkey(0)
- DO CASE
- CASE nKey == K_ESC
- lExitRequested := .T.
-
- CASE nKey == K_LEFT
- IF nLineOffset > 1
- nLineOffset--
- oTbr:refreshall()
- ENDIF
-
- CASE nKey == K_RIGHT
- IF nLineOffset < len(CurLine(aFileInfo))
- nLineOffset++
- oTbr:refreshall()
- ENDIF
-
- CASE nKey == K_HOME
- nLineOffset := 1
- oTbr:refreshall()
-
- CASE nKey == K_END
- nLineOffset := Max(1, Len(CurLine(aFileInfo)) - ;
- oTbc:width + 1)
- oTbr:refreshAll()
-
- #define TAB_SIZE 10
-
- CASE nKey == K_TAB
- IF nLineOffset <= Len(Curline(aFileInfo)) - TAB_SIZE
- nLineOffset += TAB_SIZE
- oTbr:refreshAll()
- ENDIF
-
- CASE nKey == K_SH_TAB
- nLineOffset = MAX(1, nLineOffset - TAB_SIZE)
- oTbr:refreshall()
-
- CASE nKey == K_SEARCH_FORWARD
- cSearcher := Space(20)
- @ 24, 0
- @ 24, 10 SAY "Enter Forward Search key" GET cSearcher
- READ
- @ 24, 0
- IF FrwdSrch(Trim(cSearcher), aFileInfo)
- oTbr:refreshAll()
- ELSE
- Alert("Not found", {"OK"}, "B/W, W/B")
- ENDIF
-
- CASE nKey == K_SEARCH_BACKWARD
- cSearcher := Space(20)
- @ 24, 0
- @ 24, 10 SAY "Enter Backward Search key" GET cSearcher
- READ
- @ 24, 0
- IF BkwdSrch(Trim(cSearcher), aFileInfo)
- nSavefPos := FilePos(aFileInfo)
- oTbr:refreshAll()
- FullStabilize(oTbr)
- // Ensure same line selected
- DO WHILE FilePos(aFileInfo) != nSavefPos
- oTbr:up()
- FullStabilize(oTbr)
- ENDDO
- ELSE
- Alert("Not found", {"OK"}, "B/W, W/B")
- ENDIF
-
- OTHERWISE
- IF StdMeth(nKey, oTbr)
- // Handled as standard key
- ELSE
- // Otherwise ignore
- ENDIF
- ENDCASE
- ENDDO
-
- CLEAR SCREEN
- ENDIF
-
- RETURN NIL
-
-
- // File handling system
-
- // Return the current line
-
- #define FILE_LINE 1
- #define FILE_HANDLE 2
-
- FUNCTION CurLine(aFileInfo)
-
- RETURN aFileInfo[FILE_LINE]
-
-
- #define MAX_LINE_LEN 256
-
- // Initialization routine - open file, and get first line
-
- FUNCTION FileInit(cFname)
-
- LOCAL aFileInfo := Array(2)
-
- IF (aFileInfo[FILE_HANDLE] := Fopen(cFname)) > 0
- Fseek(aFileInfo[FILE_HANDLE], 0, FS_END)
- GoFirst(aFileInfo)
- ELSE
- aFileInfo := NIL
- ENDIF
-
- RETURN aFileInfo
-
-
- // Read first line and store in aFileInfo element
-
- FUNCTION GoFirst(aFileInfo)
-
- LOCAL cLine
- LOCAL nHandle := aFileInfo[FILE_HANDLE]
-
- Fseek(nHandle, 0, FS_SET)
- lFreadln(nHandle, @cline)
- aFileInfo[FILE_LINE] := cLine
- Fseek(nHandle, 0, FS_SET)
-
- RETURN NIL
-
-
- // Read the next line from the file into "cBuffer". The routine
- // returns .T. if read, .F. otherwise (indicating EOF)
- // The caller must pass cBuffer by reference
-
- FUNCTION lFreadln(nHandle, cBuffer)
-
- LOCAL nEol, nRead, nSaveFpos
-
- cBuffer := Space(MAX_LINE_LEN)
-
- // First save current file pointer
- nSaveFpos := FTELL(nHandle)
- nRead := Fread(nHandle, @cBuffer, MAX_LINE_LEN)
-
- IF (nEol := At(CRLF, Substr(cBuffer, 1, nRead))) == 0
- // Line overflow or eof
- // cBuffer 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
-
-
- // Read last line in file and place in aFileInfo element
-
- FUNCTION GoLast(aFileInfo)
-
- Fseek(aFileInfo[FILE_HANDLE], 0, FS_END)
- lGoPrevLn(aFileInfo)
-
- RETURN NIL
-
-
- // Skip n lines in the file. n can be positive or negative
-
- FUNCTION FileSkip(n, aFileInfo)
-
- LOCAL nSkipped := 0
-
- IF n > 0
- DO WHILE nSkipped != n .AND. lGoNextLn(aFileInfo)
- nSkipped++
- ENDDO
- ELSE
- DO WHILE nSkipped != n .AND. lGoPrevLn(aFileInfo)
- nSkipped--
- ENDDO
- ENDIF
-
- RETURN nSkipped
-
-
- // Attempt to move to the next line in the file
- // Return .T. if successful, .F. otherwise
-
- FUNCTION lGoNextLn(aFileInfo)
-
- LOCAL nHandle := aFileInfo[FILE_HANDLE]
- LOCAL nSavePos := FTELL(nHandle), ;
- cBuff := "", lMoved, nNewPos
-
- Fseek(nHandle, Len(aFileInfo[FILE_LINE]) + 2, FS_RELATIVE)
- nNewPos := FTELL(nHandle)
- IF lFreadLn(nHandle, @cBuff)
- lMoved := .T.
- aFileInfo[FILE_LINE] := cBuff
- Fseek(nHandle, nNewPos, FS_SET)
- ELSE
- lMoved := .F.
- Fseek(nHandle, nSavePos, FS_SET)
- ENDIF
-
- RETURN lMoved
-
-
- FUNCTION FilePos(aFileInfo)
-
- RETURN FTELL(aFileInfo[FILE_HANDLE])
-
-
- // Return whether found or not - search forwards
- // If found, cLine is set to cuurent line and file pointer
- // is at its start
- // If not found, file pointer remains untouched
-
- FUNCTION FrwdSrch(cString, aFileInfo)
-
- LOCAL nHandle := aFileInfo[FILE_HANDLE]
- LOCAL lFound := .F.
- LOCAL nSavePos := FTELL(nHandle)
- LOCAL cSavecLine := aFileInfo[FILE_LINE]
-
- DO WHILE !lFound .AND. lGoNextLn(aFileInfo)
- lFound := cString $ CurLine(aFileInfo)
- ENDDO
-
- IF !lFound
- Fseek(nHandle, nSavePos, FS_SET)
- aFileInfo[FILE_LINE] := cSavecLine
- ENDIF
-
- RETURN lFound
-
-
- // Return whether found or not - search backwards
- // If found, cLine is set to current line and file pointer
- // is at its start
- // If not found, file pointer remains untouched
-
- FUNCTION bkwdSrch(cString, aFileInfo)
-
- LOCAL lFound := .F.
- LOCAL nHandle := aFileInfo[FILE_HANDLE]
- LOCAL nSavePos := FTELL(nHandle)
- LOCAL cSavecLine := aFileInfo[FILE_LINE]
-
- DO WHILE !lFound .AND. lGoPrevLn(aFileInfo)
- lFound := cString $ CurLine(aFileInfo)
- ENDDO
-
- IF !lFound
- Fseek(nHandle, nSavePos, FS_SET)
- aFileInfo[FILE_LINE] := cSavecLine
- ENDIF
-
- RETURN lFound
-
-
- FUNCTION lGoPrevLn(aFileInfo)
-
- LOCAL nHandle := aFileInfo[FILE_HANDLE]
- LOCAL nOrigPos := FTELL(nHandle), nMaxRead, nNewPos, ;
- lMoved, cBuff, nWhereCrLf, nPrev, cTemp
-
- IF nOrigPos == 0
- lMoved := .F.
- ELSE
- lMoved := .T.
- // Check preceeding 2 chars for CR / LF
- Fseek(nHandle, -2, FS_RELATIVE)
- cTemp := space(2)
- fread(nHandle, @cTemp, 2)
- IF cTemp == CRLF
- fseek(nHandle, -2, FS_RELATIVE)
- ENDIF
- nMaxRead := MIN(MAX_LINE_LEN, FTELL(nHandle))
-
- cBuff := Space(nMaxRead)
- nNewPos := Fseek(nHandle, -nMaxRead, FS_RELATIVE)
- Fread(nHandle, @cBuff, nMaxRead)
- nWhereCrLf := rat(CRLF, cBuff)
- IF nWhereCrLf == 0
- nPrev := nNewPos
- aFileInfo[FILE_LINE] := cBuff
- ELSE
- nPrev := nNewPos + nWhereCrLf + 1
- aFileInfo[FILE_LINE] := Substr(cBuff, nWhereCrLf + 2)
- ENDIF
-
- Fseek(nHandle, nPrev, FS_SET)
- ENDIF
-
- RETURN lMoved