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

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