home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a065 / 1.img / TBPRGS.EXE / TB27.PRG < prev    next >
Encoding:
Text File  |  1992-03-09  |  9.9 KB  |  352 lines

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