home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a065 / 1.img / TBEXS.EXE / TBEX26.PRG < prev    next >
Encoding:
Text File  |  1992-03-18  |  9.2 KB  |  370 lines

  1. // Tbex26.prg
  2. //
  3. // Program sequence using tbrowse object to browse a file. Assumes
  4. // all lines are terminated with CR / LF. 
  5. //
  6. // Compile with /a /m /n /w
  7. //
  8. // Link with Tbutils, Dict
  9.  
  10. #include "Fileio.ch"
  11. #include "Inkey.ch"
  12.  
  13. #define CR    Chr(13)
  14. #define LF    Chr(10)
  15. #define CRLF  CR + LF
  16.  
  17. // File's current position
  18. #define FTELL(nHandle)  Fseek(nHandle, 0, FS_RELATIVE)
  19.  
  20. MEMVAR getlist
  21.  
  22. #define K_SEARCH_FORWARD   K_F2
  23. #define K_SEARCH_BACKWARD  K_F3
  24. #define K_HIGHLIGHT        K_F4
  25.  
  26. // Pass file name as a parameter
  27.  
  28. FUNCTION Tbex26(cFname)
  29.  
  30. LOCAL oTbr, oTbc
  31. LOCAL lExitRequested := .F.
  32. LOCAL cSearcher, nSavefPos
  33. LOCAL aFileInfo
  34. LOCAL nKey
  35. LOCAL nLineOffset := 1
  36. LOCAL cHighlight
  37.  
  38.     SET SCOREBOARD OFF
  39.     CLEAR SCREEN
  40.     @ 23, 0 SAY "F2 - Search Forwards, F3 - Search Backwards, F4 - Highlight"
  41.  
  42.     @ 0,  0 TO 22, 79
  43.  
  44.     IF (aFileInfo := FileInit(cFname)) != NIL
  45.         oTbr := TBrowseNew(1, 1, 21, 78)
  46.         oTbc := TBColumnNew(, {|| Substr(CurLine(aFileInfo), nLineOffset) })
  47.         oTbc:colorBlock := {|cLine| ;
  48.                              iif(Empty(cHighlight), ;
  49.                                        {1, 2},     ;
  50.                                        iif(cHighLight $ cLine, ;
  51.                                            {2, 1}, {1, 2} ) ) }
  52.  
  53.         oTbc:width := 78
  54.         oTbr:addColumn(oTbc)
  55.  
  56.         oTbr:goTopBlock    := {| | GoFirst(aFileInfo) }
  57.         oTbr:goBottomBlock := {| | GoLast(aFileInfo)  }
  58.         oTbr:skipBlock     := {|n| FileSkip(n, aFileInfo) }
  59.  
  60.         DO WHILE !lExitRequested
  61.           FullStabilize(oTbr)
  62.  
  63.           nKey := inkey(0)
  64.           DO CASE
  65.             CASE nKey == K_ESC
  66.               lExitRequested := .T.
  67.  
  68.             CASE nKey == K_LEFT
  69.               IF nLineOffset > 1
  70.                 nLineOffset--
  71.                 oTbr:refreshall()
  72.               ENDIF
  73.  
  74.             CASE nKey == K_RIGHT
  75.               IF nLineOffset < len(CurLine(aFileInfo))
  76.                 nLineOffset++
  77.                 oTbr:refreshall()
  78.               ENDIF
  79.  
  80.             CASE nKey == K_HOME
  81.               nLineOffset := 1
  82.               oTbr:refreshall()
  83.  
  84.             CASE nKey == K_END
  85.               nLineOffset := Max(1, Len(CurLine(aFileInfo)) - ;
  86.                                         oTbc:width + 1)
  87.               oTbr:refreshAll()
  88.  
  89.             #define TAB_SIZE 10
  90.  
  91.             CASE nKey == K_TAB
  92.               IF nLineOffset <= Len(Curline(aFileInfo)) - TAB_SIZE
  93.                 nLineOffset += TAB_SIZE
  94.                 oTbr:refreshAll()
  95.               ENDIF
  96.  
  97.             CASE nKey == K_SH_TAB
  98.               nLineOffset = MAX(1, nLineOffset - TAB_SIZE)
  99.               oTbr:refreshall()
  100.  
  101.             CASE nKey == K_SEARCH_FORWARD
  102.               cSearcher := Space(20)
  103.               @ 24, 0
  104.               @ 24, 10 SAY "Enter Forward Search key" GET cSearcher
  105.               READ
  106.               @ 24, 0
  107.               IF FrwdSrch(Trim(cSearcher), aFileInfo)
  108.                 oTbr:refreshAll()
  109.               ELSE
  110.                 Alert("Not found", {"OK"}, "B/W, W/B")
  111.               ENDIF
  112.  
  113.             CASE nKey == K_SEARCH_BACKWARD
  114.               cSearcher := Space(20)
  115.               @ 24, 0
  116.               @ 24, 10 SAY "Enter Backward Search key" GET cSearcher
  117.               READ
  118.               @ 24, 0
  119.               IF BkwdSrch(Trim(cSearcher), aFileInfo)
  120.                 nSavefPos := FilePos(aFileInfo)
  121.                 oTbr:refreshAll()
  122.                 FullStabilize(oTbr)
  123.                 // Ensure same line selected
  124.                 DO WHILE FilePos(aFileInfo) != nSavefPos
  125.                   oTbr:up()
  126.                   FullStabilize(oTbr)
  127.                 ENDDO
  128.               ELSE
  129.                 Alert("Not found", {"OK"}, "B/W, W/B")
  130.               ENDIF
  131.  
  132.             CASE nKey == K_HIGHLIGHT
  133.               @ 24, 0
  134.               cHighLight := Space(20)
  135.               @ 24, 10 SAY "Enter highlight string" GET cHighlight
  136.               READ
  137.               @ 24, 0
  138.               IF Updated()
  139.                 oTbr:refreshAll()
  140.               ENDIF
  141.               cHighLight := Trim(cHighLight)
  142.  
  143.             OTHERWISE
  144.               IF StdMeth(nKey, oTbr)
  145.                 //  Handled as standard key
  146.               ELSE
  147.                 // Otherwise ignore
  148.               ENDIF
  149.           ENDCASE
  150.         ENDDO
  151.  
  152.         CLEAR SCREEN
  153.     ENDIF
  154.  
  155. RETURN NIL
  156.  
  157.  
  158. // File handling system
  159.  
  160. // Return the current line
  161.  
  162. #define FILE_LINE   1
  163. #define FILE_HANDLE 2
  164.  
  165. FUNCTION CurLine(aFileInfo)
  166.  
  167. RETURN aFileInfo[FILE_LINE]
  168.  
  169.  
  170. #define MAX_LINE_LEN 256
  171.  
  172. // Initialization routine - open file, and get first line
  173.  
  174. FUNCTION FileInit(cFname)
  175.  
  176. LOCAL aFileInfo := Array(2)
  177.  
  178.     IF (aFileInfo[FILE_HANDLE] := Fopen(cFname)) > 0
  179.       Fseek(aFileInfo[FILE_HANDLE], 0, FS_END)
  180.       GoFirst(aFileInfo)
  181.     ELSE
  182.       aFileInfo := NIL
  183.     ENDIF
  184.  
  185. RETURN aFileInfo
  186.  
  187.  
  188. // Read first line and store in aFileInfo element
  189.  
  190. FUNCTION GoFirst(aFileInfo)
  191.  
  192. LOCAL cLine
  193. LOCAL nHandle := aFileInfo[FILE_HANDLE]
  194.  
  195.     Fseek(nHandle, 0, FS_SET)
  196.     lFreadln(nHandle, @cline)
  197.     aFileInfo[FILE_LINE] := cLine
  198.     Fseek(nHandle, 0, FS_SET)
  199.  
  200. RETURN NIL
  201.  
  202.  
  203. // Read the next line from the file into "cBuffer". The routine
  204. // returns .T. if read, .F. otherwise (indicating EOF)
  205. // The caller must pass cBuffer by reference
  206.  
  207. FUNCTION lFreadln(nHandle, cBuffer)
  208.  
  209. LOCAL nEol, nRead, nSaveFpos
  210.  
  211.     cBuffer := Space(MAX_LINE_LEN)
  212.  
  213.     // First save current file pointer
  214.     nSaveFpos := FTELL(nHandle)
  215.     nRead := Fread(nHandle, @cBuffer, MAX_LINE_LEN)
  216.  
  217.     IF (nEol := At(CRLF, Substr(cBuffer, 1, nRead))) == 0
  218.         // Line overflow or eof
  219.         // cBuffer has the line we need
  220.     ELSE
  221.         // Copy up to eol
  222.         cBuffer := Substr(cBuffer, 1, nEol - 1)
  223.         // Position file pointer to next line
  224.         Fseek(nHandle, nSaveFpos + nEol + 1, FS_SET)
  225.     ENDIF
  226.  
  227. RETURN nRead != 0
  228.  
  229.  
  230. // Read last line in file and place in aFileInfo element
  231.  
  232. FUNCTION GoLast(aFileInfo)
  233.  
  234.     Fseek(aFileInfo[FILE_HANDLE], 0, FS_END)
  235.     lGoPrevLn(aFileInfo)
  236.  
  237. RETURN NIL
  238.  
  239.  
  240. // Skip n lines in the file. n can be positive or negative
  241.  
  242. FUNCTION FileSkip(n, aFileInfo)
  243.  
  244. LOCAL nSkipped := 0
  245.  
  246.     IF n > 0
  247.         DO WHILE nSkipped != n .AND. lGoNextLn(aFileInfo)
  248.             nSkipped++
  249.         ENDDO
  250.     ELSE
  251.         DO WHILE nSkipped != n .AND. lGoPrevLn(aFileInfo)
  252.             nSkipped--
  253.         ENDDO
  254.     ENDIF
  255.  
  256. RETURN nSkipped
  257.  
  258.  
  259. // Attempt to move to the next line in the file
  260. // Return .T. if successful, .F. otherwise
  261.  
  262. FUNCTION lGoNextLn(aFileInfo)
  263.  
  264. LOCAL nHandle := aFileInfo[FILE_HANDLE]
  265. LOCAL nSavePos := FTELL(nHandle), ;
  266.       cBuff := "", lMoved, nNewPos
  267.  
  268.     Fseek(nHandle, Len(aFileInfo[FILE_LINE]) + 2, FS_RELATIVE)
  269.     nNewPos := FTELL(nHandle)
  270.     IF lFreadLn(nHandle, @cBuff)
  271.         lMoved := .T.
  272.         aFileInfo[FILE_LINE] := cBuff
  273.         Fseek(nHandle, nNewPos, FS_SET)
  274.     ELSE
  275.         lMoved := .F.
  276.         Fseek(nHandle, nSavePos, FS_SET)
  277.     ENDIF
  278.  
  279. RETURN lMoved
  280.  
  281.  
  282. FUNCTION FilePos(aFileInfo)
  283.  
  284. RETURN FTELL(aFileInfo[FILE_HANDLE])
  285.  
  286.  
  287. // Return whether found or not - search forwards
  288. // If found, cLine is set to cuurent line and file pointer
  289. // is at its start
  290. // If not found, file pointer remains untouched
  291.  
  292. FUNCTION FrwdSrch(cString, aFileInfo)
  293.  
  294. LOCAL nHandle := aFileInfo[FILE_HANDLE]
  295. LOCAL lFound := .F.
  296. LOCAL nSavePos := FTELL(nHandle)
  297. LOCAL cSavecLine := aFileInfo[FILE_LINE]
  298.  
  299.     DO WHILE !lFound .AND. lGoNextLn(aFileInfo)
  300.       lFound := cString $ CurLine(aFileInfo)
  301.     ENDDO
  302.  
  303.     IF !lFound
  304.       Fseek(nHandle, nSavePos, FS_SET)
  305.       aFileInfo[FILE_LINE] := cSavecLine
  306.     ENDIF
  307.  
  308. RETURN lFound
  309.  
  310.  
  311. // Return whether found or not - search backwards
  312. // If found, cLine is set to current line and file pointer
  313. // is at its start
  314. // If not found, file pointer remains untouched
  315.  
  316. FUNCTION bkwdSrch(cString, aFileInfo)
  317.  
  318. LOCAL lFound := .F.
  319. LOCAL nHandle := aFileInfo[FILE_HANDLE]
  320. LOCAL nSavePos := FTELL(nHandle)
  321. LOCAL cSavecLine := aFileInfo[FILE_LINE]
  322.  
  323.     DO WHILE !lFound .AND. lGoPrevLn(aFileInfo)
  324.       lFound := cString $ CurLine(aFileInfo)
  325.     ENDDO
  326.  
  327.     IF !lFound
  328.       Fseek(nHandle, nSavePos, FS_SET)
  329.       aFileInfo[FILE_LINE] := cSavecLine
  330.     ENDIF
  331.  
  332. RETURN lFound
  333.  
  334.  
  335. FUNCTION lGoPrevLn(aFileInfo)
  336.  
  337. LOCAL nHandle := aFileInfo[FILE_HANDLE]
  338. LOCAL nOrigPos := FTELL(nHandle), nMaxRead, nNewPos, ;
  339.       lMoved, cBuff, nWhereCrLf, nPrev, cTemp
  340.  
  341.     IF nOrigPos == 0
  342.         lMoved := .F.
  343.     ELSE
  344.         lMoved := .T.
  345.         //  Check preceeding 2 chars for CR / LF
  346.         Fseek(nHandle, -2, FS_RELATIVE)
  347.         cTemp := space(2)
  348.         fread(nHandle, @cTemp, 2)
  349.         IF cTemp == CRLF
  350.             fseek(nHandle, -2, FS_RELATIVE)
  351.         ENDIF
  352.         nMaxRead := MIN(MAX_LINE_LEN, FTELL(nHandle))
  353.  
  354.         cBuff := Space(nMaxRead)
  355.         nNewPos := Fseek(nHandle, -nMaxRead, FS_RELATIVE)
  356.         Fread(nHandle, @cBuff, nMaxRead)
  357.         nWhereCrLf := rat(CRLF, cBuff)
  358.         IF nWhereCrLf == 0
  359.             nPrev := nNewPos
  360.             aFileInfo[FILE_LINE] := cBuff
  361.         ELSE
  362.             nPrev := nNewPos + nWhereCrLf + 1
  363.             aFileInfo[FILE_LINE] := Substr(cBuff, nWhereCrLf + 2)
  364.         ENDIF
  365.  
  366.         Fseek(nHandle, nPrev, FS_SET)
  367.     ENDIF
  368.  
  369. RETURN lMoved
  370.