home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
EDITORS
/
FTTEXT.ZIP
/
TEXTBROW.PRG
< prev
Wrap
Text File
|
1992-08-01
|
17KB
|
576 lines
#define TESTING
/* A file browser for essentially unlimited size text files.
Provided for Aquarium subscribers.
For use with the public domain library "Nanfor.lib" from CompuServe's
Nanforum, especially the FT_FText modules by Brice deGanahl. Note
that the current version of this library on Nanforum has a limitation
of 64K text files for these functions; a patched version is available
as "FTTxt2.zip".
Based upon original ideas, and possibly some remaining code fragements,
presented by Craig Yellick in "Clipper 5: A Developer's Guide",
copyright (c) 1991 M&T Books.
In particular started with:
Listing 25.14.
A file browser for small text files.
Author: Craig Yellick
Excerpted from "Clipper 5: A Developer's Guide"
Copyright (c) 1991 M&T Books
501 Galveston Drive
Redwood City, CA 94063-4728
(415) 366-3600
My conscience about copyrights will be clearer if you own that book when
you use this program. The book is well worth having anyway.
Implementation / modifications by Tim Meneely, Ira Emus, and Kathy Beaumont,
1992.
*/
//#define JERK // Use dispbegin/dispend to avoid showing refresh?
#define TAB_SPACES space(2) // Number of spaces to put in for a hor. tab
#command DEFAULT <param> TO <value> => ;
<param> := IF(<param> == NIL, <value>, <param>)
#include "inkey.ch"
#include "box.ch"
static cline:= ''
static lrec:= 0
static recno:= 0
static hoffset := 0
static pan_step:= 5 // "Smoothness" of panning: how many columns per press
static know_last:= .f.
// Long comment line, not at top of file |50 |60 |70 |80 |90 |100 |110 |120 |130 |140 |150
#ifdef TESTING
function Test(filename)
local colorspec := "w/n,n/w,b/w,w/b"
local color1, color2
/* For work on LCD screens
colorspec := "w/n,n/w,b/w,w/b"
*/
default filename to "textbrow.prg"
//setmode(50,132)
BrowText(filename,0,0,maxrow(),maxcol(),132,colorspec,.t.)
return nil
#endif // TESTING
/*
BrowText, a LARGE file text browser.
*/
function BrowText(filename,; // Name of file to browse
nTop, nLeft, nBottom, nRight,; // Browse window dimensions
maxwidth,; // Maximum width of line
colorspec,; // Colorspec string
lShowName; // Show file name?
)
local key
local txt
local col
local width
local block_:= {0,0}
local nSkipPage // how many lines to move for a PgUp/PgDn
local oldScreen := savescreen()
local oldCursor := set(_SET_CURSOR, .F.)
if filename = nil
//? "Must specify a file name."
return nil
endif
default nTop to 0
default nLeft to 0
default nBottom to maxrow()
default nRight to maxcol()
default maxwidth to 132
default lShowName to .t.
SET SCOREBOARD OFF // Hah! You shouldn't be using scoreboard anyway!
// Create the browse object.
txt:= TBrowseNew(nTop+1, nLeft+1, nBottom-2, nRight-1)
//──── Calculate the value of nSkipPage
nSkipPage := ((txt:nBottom-2) - (txt:nTop+1))
if colorspec <> NIL
txt:colorspec:= colorspec
else
txt:colorspec:= "w/n,n/w,b/w,w/b"
endif
FT_FUse(filename) // open text file
@ nTop,nLeft,nBottom,nRight BOX B_SINGLE_DOUBLE + " "
setpos(nBottom-1,nLeft)
dispout(padc(;
"Alt-S=Search, Alt-B=Block, Alt-U=Unmark, Alt-F=File, Alt-P=Printer",;
nRight-nLeft,chr(177) ) )
if lShowName
setpos(nTop, nLeft)
dispout(" File: " +trim(filename)+" ")
endif
setpos(nBottom, nLeft)
dispout(" Line: "+alltrim(str(recno))+" of "+alltrim(str(lrec))+" ")
// This line makes startup slow in big files
//lrec:= FT_FLastRec()
//know_last:= .t.
// Add columns to display lines of text.
width:= txt:nright-txt:nleft+1
col:=TBColumnNew(, {||substr(padr(TB_GetLine(),maxwidth),hoffset)} )
/*col:colorblock:= {||if(recno>=block_[1] .and. recno<=block_[2],;
{3,4},{1,2})}*/
col:colorblock:= {||if( ( recno>=block_[1] .and. recno<=block_[2] ) .or. ;
( recno<=block_[1] .and. recno>=block_[2] ) ,;
{3,4},{1,2})}
txt:addColumn(col)
// The data positioning blocks.
txt:goTopBlock:= { || FT_FGoTop() }
txt:goBottomBlock:= { || FT_FGoBot() }
txt:skipBlock:= { |n| TextPosition(n) }
// Display the window and process navigation keystrokes.
do while .t.
#ifdef JERK
dispbegin()
#endif
do while (.not. txt:stabilize()) .AND. nextkey() == 0
enddo
if block_[1] > 0
block_[2] := recno
endif
#ifdef JERK
dispend()
#endif
setpos(nBottom, nLeft)
dispout(padr("Line: "+alltrim(str(recno))+" of "+;
alltrim(str(lrec))+iif(know_last,"","+"),;
nRight-nLeft,chr(196)))
key:= inkey(0)
do case
case key == K_UP // Up one row
if block_[1] > 0 .and. block_[2] > block_[1]
//──── This reveals the current record in NON-marked color
--block_[2]
txt:refreshCurrent()
txt:stabilize()
endif
txt:up()
if block_[1] > 0
//──── We are in BLOCK mode, so have to pay attention
//──── to cleaning up the block markers.
do while !txt:stabilize()
enddo
block_[2] := recno
txt:refreshCurrent()
endif
case key == K_DOWN // Down one row
if block_[1] > 0 .and. block_[2] < block_[1]
++block_[2]
txt:refreshCurrent()
txt:stabilize()
endif
txt:down()
//──── more block dragging stuff
if block_[1] <> 0
txt:refreshCurrent()
txt:stabilize()
block_[2] := recno
endif
case key == K_LEFT // Left one column
hoffset:= max(hoffset -=pan_step,0)
txt:refreshall()
case key == K_RIGHT // Right one column
hoffset +=pan_step
txt:refreshall()
case key == K_PGUP // Up one page
//──── The following nonsense is to
//──── accommodate the unfortunate tendency of TBrowse not
//──── to move the highlighter to the top if it doesn't have
//──── to (known as the MoveHiLite() phenomenon... I'll go
//──── into more detail if you don't know what I'm talking
//──── about.)
if recno - nSkipPage <= 0
while recno > 1
txt:up()
txt:stabilize()
enddo
else
FT_FGoTo(recno - nSkipPage)
endif
if block_[1] > 0
block_[2] := FT_FRecno()
endif
txt:refreshall()
case key == K_PGDN // Down one page
if know_last
FT_FGoTo( min(recno + nSkipPage, lrec) )
else
FT_FGoTo( recno + nSkipPage )
if FT_FEOF()
FT_FGoto(recno)
while !FT_FEof()
FT_FSkip(1)
enddo
endif
endif
if block_[1] > 0
block_[2] := FT_FRecno()
endif
txt:refreshall()
case key == K_CTRL_PGUP // Up to the first record
txt:goTop()
if block_[1] > 0
block_[2] := FT_FRecno()
endif
case key == K_CTRL_PGDN // Down to the last record
txt:goBottom()
if block_[1] > 0
block_[2] := FT_FRecno()
endif
know_last:= .t.
case key == K_HOME // First visible column
hoffset:= 0
txt:refreshall()
case key == K_END // Last visible column
hoffset:= len(cline)-(txt:nRight-txt:nLeft)
txt:refreshall()
case key == K_CTRL_HOME // First column
hoffset:= 0
txt:refreshall()
case key == K_CTRL_END // Last column
hoffset:= len(cline)-(txt:nRight-txt:nLeft)
txt:refreshall()
case key == K_TAB // Pan to the right
hoffset += txt:nRight-txt:nLeft
txt:refreshall()
case key == K_SH_TAB // Pan to the left
hoffset:= max(hoffset -= txt:nRight-txt:nLeft,0)
txt:refreshall()
case key == K_ESC
exit
otherwise // Key not handled
HandleException(key,txt,block_)
endcase
enddo
ft_fuse() // close file
restscreen(,,,,oldScreen)
set(_SET_CURSOR, oldCursor)
return nil
// end of function BrowText(filename)
//-----------------------------------------------------------------------
function TextPosition(howMany)
local actual := howmany
local record := ft_frecno()
local numskipped
if ( -howmany ) > record // this solves a problem where ft_fskip()
ft_fgotop() // ignores the command to skip to -1.
else // I would have expected it to move as
ft_fskip( howmany) // far as possible, but it fooled me.
endif
recno := FT_FRecNo()
numskipped := recno - record
lrec:= max( lrec, recno )
cline:= FT_FReadLn()
if FT_FEof()
know_last:= .t.
endif
return (recno - record)
//-----------------------------------------------------------------------
static function HandleException(key,txt,block_)
local temp
do case
case key == K_ALT_S // Search
SrchText(txt)
case key == K_ALT_B
if (block_[1] == 0) .and. (block_[2] == 0)
block_[1] := block_[2] := recno
else
block_[1]:= recno
endif
if block_[1] > block_[2]
temp:= block_[1]
block_[1]:= block_[2]
block_[2]:= temp
endif
txt:refreshall()
case key == K_ALT_F //──── Output to a file
TxtOut(txt,block_,"F")
case key == K_ALT_P //──── Send to printer
TxtOut(txt,block_,"P")
case key == K_ALT_U //──── unmark block
block_[1] := block_[2] := 0
txt:refreshAll()
endcase
return NIL
// end static function HandleException(key,txt,block_)
//------------------------------------------------------------------------
static function SrchText(browse)
static SrchFor := ""
static NoCase := .t.
//static StartTop
static StartLine
local LineIn
local LineLong
local oldPos := FT_FRecNo() //──── mark our starting place
local getlist:= {}
local oldScreen:= savescreen(9,7,13,53)
local oldCursor := set(_SET_CURSOR,2) //──── turn the cursor on
local srchlength
//StartTop:= empty(SrchFor)
StartLine:= iif(empty(SrchFor),1,oldPos+1)
SrchFor:= padr(SrchFor,80) // 80 character max search string length
scroll(9,7,13,53)
@ 9, 7 to 13, 53
@ 10, 8 say "Search for: " get SrchFor picture "@S30K"
@ 11, 8 say "Case insensitive? " get NoCase
@ 12, 8 say "Start search on line number:" get StartLine picture "######"
//@ 12, 8 say "Start at top of file? " get StartTop
read
set(_SET_CURSOR, oldCursor) //──── turn cursor off again
if .not. empty(SrchFor)
SrchFor := iif(NoCase,upper(trim(SrchFor)),trim(SrchFor))
srchlength := len( SrchFor )-1
FT_FGoTo(StartLine)
/*if StartTop
FT_FGoTop()
else
// Don't search present line
FT_FSkip(1)
endif*/
LineLong:= ''
if NoCase
do while !(SrchFor $ (LineLong:= (right( linelong, SrchLength )+" "+upper(FT_FReadLn())))) ;
.and. !FT_FEof() ;
.and. inkey() == 0
@ 12,42 say ft_frecno()
FT_FSkip(1)
enddo
else
do while !(SrchFor, (LineLong:= (right( linelong, SrchLength )+" "+FT_FReadLn()))) ;
.and. !FT_FEof() ;
.and. inkey() == 0
@ 12,42 say ft_frecno()
FT_FSkip(1)
enddo
endif
endif
if !ft_feof()
browse:refreshAll()
else
tone(100,2)
lrec:= ft_frecno()
know_last:= .t.
FT_FGoTo(oldPos)
endif
restscreen(9,7,13,53,oldScreen)
return NIL
// end static function SrchText
//-----------------------------------------------------------------------
static function TxtOut(txt,block_,F_or_P)
local getlist:= {}, oldScreen, cOutfile:= space(30), nThisrec
local nTemp
default F_or_P to "F"
//──── KATHY 07/28/92: My "drag it around" stuff may leave the
//──── block anchors upside down.
if block_[2] < block_[1]
nTemp := block_[1]
block_[1] := block_[2]
block_[2] := ntemp
endif
if (block_[1] <= block_[2]) .and. (block_[2] > 0)
if F_or_P == "F"
oldScreen:= ;
savescreen(txt:nBottom-4,txt:nLeft+15,txt:nBottom-1,txt:nRight-15)
@ txt:nBottom-4,txt:nLeft+15,txt:nBottom-1,txt:nRight-15 box B_DOUBLE+" "
set cursor on
@ txt:nBottom-3,txt:nLeft +23 say "Copy marked text to where?"
@ txt:nBottom-2,txt:nLeft +20 get cOutfile picture '@!'
read
restscreen(txt:nBottom-4,txt:nLeft+15,txt:nBottom-1,txt:nRight-15,oldScreen)
set cursor off
if lastkey() != K_ESC
//──── if the file exists, append to the end
if file(cOutFile)
set printer to (cOutFile) additive
else
set printer to (cOutFile)
endif
endif
endif
DoPrnInit(.t.) // Send initialization codes to printer
FT_FGoto(block_[1])
nThisrec:= FT_Frecno()
set console off
set print on
while nThisrec >= block_[1] .and. nThisrec <= block_[2]
? FT_Freadln()
FT_FSkip(1)
nThisrec:= FT_Frecno()
enddo
DoPrnInit(.f.) // Send turn-off codes to printer
set print off
set console on
set printer to
//──── remove the highlights of the block
block_[1] := block_[2] := 0
txt:refreshAll()
else
NoBlock(txt)
endif
return NIL
// end static function TxtOut(txt,block_,F_or_P)
//------------------------------------------------------------------------
static function NoBlock(txt)
local oldScreen
tone(100,2) //──── THUD
oldScreen:= savescreen(txt:nBottom-4,txt:nLeft +15,;
txt:nBottom-1,txt:nRight -15)
@ txt:nBottom-4,txt:nLeft+15,txt:nBottom-1,txt:nRight-15 box B_DOUBLE+" "
@ txt:nBottom-3,txt:nLeft +25 say "Use Alt-B to Block Text!"
@ txt:nBottom-2,txt:nLeft +25 say " Press a key... "
inkey(0)
restscreen(txt:nBottom-4,txt:nLeft +15,;
txt:nBottom-1,txt:nRight -15,oldScreen)
return NIL
// end static function NoBlock
//------------------------------------------------------------------------
function TB_GetLine()
static ctrl_codes_:= {}
static codes_loaded:= .f.
local escpos, i
if !codes_loaded
ctrl_codes_:= LoadCodes()
codes_loaded:= .t.
endif
if chr(9) $ cline
// Expand any tabs
cline := strtran(cline,chr(9),TAB_SPACES)
endif
// Strip printer codes
for i:= 1 to len(ctrl_codes_)
if ctrl_codes_[i] $ cline
cline := strtran(cline, ctrl_codes_[i],"")
endif
next
// Or, for HP LaserJet only (no need to pass codes if you use this)
/*
do while ((escpos:= at(chr(27),cline)) > 0)
do while (.not. isupper(substr(cline,escpos,1))) .and. ;
(.not. substr(cline,escpos,1) == '@') .and. ;
(len(cline) >= escpos)
cline:= stuff(cline,escpos,1,"")
enddo
if (len(cline) >= escpos)
cline:= stuff(cline,escpos,1,"")
endif
enddo
*/
return cline
// end of TB_GetLine()
//-----------------------------------------------------------------------
static function LoadCodes()
/* This function should be customized to load the printer control
codes which you want to strip out. Anything in this array will
be purged while viewing (but not during other output).
The codes shown here are a few typical Laserjet codes; the more
general case would be to go back to whatever your application uses
to store its printer codes and to load the codes directly from there.
*/
return ;
{chr(27)+"&dD" ,;
chr(27)+"&k0S",;
chr(27)+"&l0O",;
chr(27)+"&d@" ,;
chr(27)+"(s0B",;
chr(27)+"(s3B",;
chr(27)+"(10U"}
// end static function LoadCodes()
//------------------------------------------------------------------------
static function DoPrnInit(Start)
/* dummy printer initialization routine. My systems have a function
to initialize the printer, including doing basic font setup; this
would call that.
I guess that the "best" way to ensure printouts chopped from the
middle of other printouts would work would be to search through
the _entire_ report file, looking for every hit on a printer code
and adding that printer code to a string to be sent to the printer -
and awesome concept, sending many, many "bold on - bold off"
sequences with all the text stripped out in between.
We need some creativity here, folks!
*/
return NIL
// end static function DoPrnInit(Start)
//------------------------------------------------------------------------
/* Version Control Data
Last update: Revision @#r on @#d at @#t
Revision History:
@#c
*/