home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a013 / 1.ddi / SOURCE.EXE / F_READTX.PRG < prev    next >
Encoding:
Text File  |  1991-01-25  |  7.5 KB  |  267 lines

  1. *****************************************************************
  2. FUNCTION READTEXT
  3. *****************************************************************
  4.  
  5. * Display a text file of any size in a window for reading
  6.  
  7. * Copyright(c) 1991 -- James Occhiogrosso
  8.  
  9. # include "inkey.ch"
  10. # include "box.ch"
  11. # define wind_rows  (bottom - top) - 1   // window rows
  12. # define wind_cols  (right - left) - 3   // window columns
  13.  
  14. LOCAL counter := 0, old_cursor := SETCURSOR(0), old_screen := ''
  15. PRIVATE text_array := {}, col_offset := 1, keypress := 0
  16. PARAMETERS text_file, top, left, bottom, right, start_line
  17.  
  18. * Initialize arguments not passed with defaults
  19.  
  20. top = IF(top = NIL, 0, top)
  21. left = IF(left = NIL, 0, left)
  22. bottom = IF(bottom = NIL, MAXROW(), bottom)
  23. right = IF(right = NIL, MAXCOL(), right)
  24. start_line = IF(start_line = NIL, 1, start_line)
  25.  
  26.  
  27. * If file cannot be opened, return
  28. IF (handle := FOPEN(text_file)) > 0
  29.  
  30.     * Save old screen and box text area
  31.     old_screen = SCRNSAVE(top, left, bottom, right)
  32.     @ top, left, bottom, right BOX B_SINGLE + SPACE(1)
  33.  
  34.     * Save end of file value
  35.     text_eof = FSEEK(handle, 0, 2)
  36.  
  37.     * Declare view array as number of window rows by 2 columns
  38.     * Columns: 1 = file pointer, 2 = line text
  39.     text_array := array(wind_rows,2)
  40.  
  41.     IF start_line > 1
  42.         FOR counter = 1 TO (start_line)
  43.             * Move file pointer to specified line
  44.             FREADLINE(handle)
  45.         NEXT
  46.     ENDIF
  47.  
  48.     * Load array and display initial window of lines
  49.     FILL_ARRAY()
  50.     DISP_ARRAY()
  51.  
  52.     * Process keys pressed and redisplay the array
  53.     PROCESS_KEY()
  54.  
  55.     * Restore old screen and close file
  56.     SCRNREST(old_screen)
  57.     FCLOSE(handle)
  58.  
  59. ENDIF
  60.  
  61.  
  62. SETCURSOR(old_cursor)
  63. RETURN NIL
  64.  
  65.  
  66. *****************************************************************
  67. STATIC FUNCTION PROCESS_KEY
  68. *****************************************************************
  69.  
  70. * Process keys for window movement
  71.  
  72. LOCAL buffer := SPACE(512), line_end := line_num := pointer := 0
  73.  
  74. DO WHILE keypress != K_ESC
  75.  
  76.     * If key is valid, process it
  77.  
  78.     IF  keypress = K_UP        .OR. keypress = K_DOWN  .OR. ;
  79.         keypress = K_HOME      .OR. keypress = K_END   .OR. ;
  80.         keypress = K_PGUP      .OR. keypress = K_PGDN  .OR. ;
  81.         keypress = K_LEFT      .OR. keypress = K_RIGHT .OR. ;
  82.         keypress = K_CTRL_LEFT .OR. keypress = K_CTRL_RIGHT ;
  83.         .OR. keypress = K_ENTER
  84.  
  85.         * Move up 1 line or 1 screen
  86.         IF keypress = K_UP .OR. keypress = K_PGUP
  87.  
  88.              IF text_array[1][1] != 0  // Top of file
  89.  
  90.                  * Move file pointer to top array line
  91.                  pointer = FSEEK(handle, text_array[1][1], 0)
  92.  
  93.                  * Back up file pointer (row or screen window)
  94.                  pointer = REWIND(handle, IF(keypress = K_UP, ;
  95.                            1, wind_rows), pointer)
  96.  
  97.                  * And reload array
  98.                  FILL_ARRAY()
  99.              ENDIF
  100.  
  101.         * Move down 1 line or 1 screen
  102.         ELSEIF keypress = K_DOWN .OR. keypress = K_PGDN
  103.  
  104.              * Test for end of file
  105.              IF FSEEK(handle,0,1) != text_eof
  106.  
  107.                  * If not EOF or BOF, reload array
  108.                  IF keypress = K_DOWN
  109.                      * Move pointer to second array element
  110.                      FSEEK(handle, text_array[2][1], 0)
  111.                  ENDIF
  112.  
  113.                  FILL_ARRAY()
  114.              ENDIF
  115.  
  116.         * Move to top of file
  117.         ELSEIF keypress = K_HOME
  118.              pointer = FSEEK(handle,0,0)
  119.              FILL_ARRAY()
  120.  
  121.         * Move to bottom of file
  122.         ELSEIF keypress = K_END
  123.              pointer = FSEEK(handle,0,2)
  124.              * Move pointer back one screen window
  125.              pointer = REWIND(handle, wind_rows, pointer)
  126.              FILL_ARRAY()
  127.  
  128.         * Scroll window 1 column right
  129.         ELSEIF keypress = K_RIGHT
  130.              col_offset := IF(col_offset < 512,++col_offset, 512)
  131.  
  132.         * Scroll window 1 column left
  133.         ELSEIF keypress = K_LEFT
  134.              col_offset := IF(col_offset > 1, --col_offset, 1)
  135.  
  136.         * Scroll window 8 columns right
  137.         ELSEIF keypress = K_CTRL_RIGHT
  138.              col_offset := IF(col_offset < 512,col_offset+8, 512)
  139.  
  140.         * Scroll window 8 columns left
  141.         ELSEIF keypress = K_CTRL_LEFT
  142.              col_offset := IF(col_offset > 8, col_offset-8, 1)
  143.  
  144.         * Reset window offset to first column
  145.         ELSEIF keypress = K_ENTER
  146.              col_offset := 1
  147.  
  148.         ENDIF
  149.  
  150.         * Redisplay array
  151.         keypress = DISP_ARRAY()
  152.  
  153.     ELSE
  154.         * Key is invalid, get another
  155.         keypress = INKEY(0)
  156.     ENDIF
  157. ENDDO
  158.  
  159. RETURN NIL
  160.  
  161.  
  162. *****************************************************************
  163. STATIC FUNCTION FILL_ARRAY
  164. *****************************************************************
  165.  
  166. * Load viewing array with pointer and text of each line
  167.  
  168. LOCAL counter := 1
  169.  
  170. FOR counter = 1 TO (wind_rows)
  171.      text_array[counter][1] := FSEEK(handle, 0, 1)
  172.      text_array[counter][2] := FREADLINE(handle)
  173.      IF FSEEK(handle, 0, 1) >= text_eof ; EXIT ; ENDIF
  174. NEXT
  175.  
  176. * If at EOF, fill balance of array with dummy values
  177. IF counter++ < wind_rows
  178.     FOR counter = counter TO wind_rows
  179.         text_array[counter][1] := text_eof
  180.         text_array[counter][2] := ''
  181.     NEXT
  182. ENDIF
  183.  
  184. RETURN NIL
  185.  
  186. *****************************************************************
  187. STATIC FUNCTION DISP_ARRAY
  188. *****************************************************************
  189.  
  190. * Display array. Return immediately if a key is pressed
  191.  
  192. LOCAL counter := 1, disp_string
  193.  
  194. * Clear keyboard buffer and window area
  195.  
  196. CLEAR TYPEAHEAD
  197. @ top+1, left+2 CLEAR TO bottom-1, right-2
  198.  
  199. * Display window lines until done or a key is pressed
  200. DO WHILE (keypress := INKEY()) = 0 .AND. counter <= wind_rows
  201.     * Display string and increment line counter
  202.     @ (top + counter), left + 2 SAY ;
  203.             SUBSTR(text_array[counter][2], col_offset, wind_cols)
  204.     counter++
  205.  
  206. ENDDO
  207.  
  208. RETURN keypress
  209.  
  210.  
  211. *****************************************************************
  212. STATIC FUNCTION REWIND (handle, num_lines, pointer)
  213. *****************************************************************
  214.  
  215. * Move file pointer back specified number of lines
  216.  
  217. LOCAL buffer := SPACE(512), first_line := .F.,  line_end := 0
  218.  
  219. DO WHILE num_lines > 0
  220.  
  221.     * Clear buffer
  222.     buffer := SPACE(512)
  223.  
  224.     IF pointer >= 514
  225.         * Move pointer back 514 bytes
  226.         FSEEK(handle, -514, 1)
  227.  
  228.         * Fill buffer without carriage return/line feed (CR/LF)
  229.         FREAD(handle, @buffer, 512)
  230.  
  231.     ELSE
  232.         * Move pointer to BOF and read remaining text
  233.         FSEEK(handle, -pointer, 1)
  234.         FREAD(handle, @buffer, pointer-2)
  235.  
  236.         * Set first line flag if no CR/LF in buffer
  237.         buffer = TRIM(buffer)
  238.         first_line := IF(AT(CHR(13)+CHR(10), buffer) > 0,.F.,.T.)
  239.     ENDIF
  240.  
  241.     * Look for previous CR/LF
  242.     DO WHILE (line_end := RAT(CHR(13)+CHR(10), buffer)) > 0 ;
  243.               .AND. num_lines > 0
  244.  
  245.         * Move pointer to end of previous line
  246.         pointer = FSEEK(handle, -(LEN(buffer)-(line_end-1)), 1)
  247.  
  248.         * Strip line from buffer and decrement number remaining
  249.         buffer = SUBSTR(buffer, 1, line_end - 1)
  250.         num_lines--
  251.     ENDDO
  252.  
  253.     IF ! first_line
  254.        * Move pointer to beginning of next line (skip CR/LF)
  255.        pointer = FSEEK(handle, 2, 1)
  256.     ELSE
  257.        * Reset pointer to BOF and exit
  258.        FSEEK(handle, 0, 0)
  259.        EXIT
  260.     ENDIF
  261.     
  262.  
  263. ENDDO
  264.  
  265. RETURN pointer
  266.  
  267.