FUNCTION txt_read, InFile, data, $
        approx_recl = approx_recl   , $
        range_recl  = range_recl    , $
        recl        = recl          , $
        nrec        = nrec          , $
        silent      = silent        , $
        delete      = delete        , $
        test        = test
    @compile_opt.pro        ; On error, return to caller

InitVar, silent , 0
InitVar, delete , /key
InitVar, test   , /key

status = 0

IF NOT IsType(InFile,/string) THEN BEGIN
    gzipped = 0
    InFile = '<no file>'
    hide = InFile
    errormessage = 'file name is not defined, or is not a char string'
    goto, EARLY_RETURN
ENDIF

fi = (file_search(InFile))[0]

; If file found then unzip if necessary.
; If file not found try adding .gz extension.

gzipped = gunzip_file(InFile+(['','.gz'])[fi EQ ''], rawfile, check=fi EQ '',isgz=isgz)
CASE gzipped OF
0: IF isgz THEN fi = ''
1: fi = rawfile
ENDCASE

nrec = -1
hide = hide_env(InFile)

IF fi EQ '' THEN BEGIN
    errormessage = 'file not found or unzip error'
    goto, EARLY_RETURN
ENDIF

openr, /get_lun, iu, fi, delete=delete, error=i ; Open file read only
IF i NE 0 THEN BEGIN
    errormessage = !error_state.msg             ; Open error
    goto, EARLY_RETURN
ENDIF

on_ioerror, IOERROR                     ; Establish error handler

crec = ''
IF test THEN BEGIN
    readf, iu, crec
    approx_recl = strlen(crec)
    point_lun, iu, 0
ENDIF

CASE IsType(approx_recl,/defined) OF
0: BEGIN
    nrec = 0L
    WHILE NOT eof(iu) DO BEGIN
        readf, iu, crec
        nrec = nrec+1
    ENDWHILE
    point_lun, iu, 0
    IF nrec LE 0 THEN errormessage = 'empty file'
END
1: BEGIN
    nrec = GuessRecs(iu, approx_recl, range_recl, recl=recl)
    IF nrec LE 0 THEN errormessage = 'unable to guess record length'
END
ENDCASE

IF nrec GT 0 THEN BEGIN             ; If succesful ...
    data = strarr(nrec)
    readf, iu, data                 ; Read file
    status = 1                      ; File read: set status to success
ENDIF

on_ioerror, NULL                    ; Cancel error handler

EARLY_RETURN:                       ; Return before ioerror handler is established

IF IsType(iu, /defined) THEN free_lun, iu

CASE status OF
0: BEGIN
    IF silent LE 1 THEN message, /info, hide+', '+errormessage
    destroyvar, data
END
1: BEGIN    
    IF silent LE 0 THEN BEGIN
        CASE n_elements(recl) OF
        0: message, /info, hide
        1: message, /info, hide+' ('+strcompress(recl,/rem)+' bytes)'
        ENDCASE
    ENDIF
END
ENDCASE

IF gzipped THEN i = do_file(/delete, rawfile, silent=silent)

RETURN, status

IOERROR:                            ; I/O error label

free_lun, iu
on_ioerror, NULL

status =  0
destroyvar, data

errormessage = hide+', '+!error_state.msg
IF silent LE 1 THEN message, /info, errormessage

IF gzipped THEN i = do_file(/delete, rawfile, silent=silent)

RETURN, status  &  END