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