subroutine gfits_open(file,status,error,overwrite)
  use gfits_dependencies_interfaces
  use gfits_interfaces, except_this=>gfits_open
  use gfits_buf
  use gbl_message
  use gbl_format
  !---------------------------------------------------------------------
  ! @ public
  ! FITS API routine
  !       Connect with a FITS file on disk.
  !---------------------------------------------------------------------
  character(len=*),  intent(in)    :: file       ! FITS file name
  character(len=*),  intent(in)    :: status     ! Read (IN) or Write (OUT) status
  logical,           intent(inout) :: error      ! Error flag
  logical, optional, intent(in)    :: overwrite  ! Overwrite in case of OUT status?
  ! Local
  character(len=*), parameter :: rname='OPEN'
  character(len=8), parameter :: defext='.fits'
  character(len=filename_length) :: name
  integer(kind=4) :: ier,recl,nc
  character(len=message_length) :: mess
  character(len=1) :: key
  !
  key = status(1:1)
  call sic_upper(key)
  !
  if (file(1:1).eq.'!') then  ! ???
    name = file(2:)
  else
    call sic_parse_file(file,' ',defext,name)
  endif
  !
  if (key.eq.'O' .and. present(overwrite) .and. overwrite) then
    nc = len_trim(name)
    if (gag_inquire(name,nc).eq.0)  call gag_filrm(name(1:nc))
  endif
  !
  if (dev_type.eq.disk) then
    ier = sic_getlun(unit)
    if (ier.ne.1) then
      error = .true.
      return
    endif
    !
    ! Open file with apropriate options
    recl = 720                 ! 2880 bytes = 720 words
    if (key.eq.'I') then
      open(unit=unit,file=name,status='OLD',recl=recl*facunf,  &
           form='UNFORMATTED',access='DIRECT',action='READ',iostat=ier)
    elseif (key.eq.'O') then
      open(unit=unit,file=name,status='NEW',recl=recl*facunf,  &
           form='UNFORMATTED',access='DIRECT',action='READWRITE',iostat=ier)
    else
      call gfits_message(seve%e,rname,'Programming error')
      error = .true.
      return
    endif
    if (ier.eq.0) then
      stdio = .true.
    else
      ! Try to recover
      call sic_frelun (unit)
      unit = 0
      call gfits_message(seve%e,rname,'Error opening '//name)
      call putios('E-OPEN,  ',ier)
      error = .true.
    endif
    !
  else
    write(mess,*) 'Unsupported device type ',dev_type
    call gfits_message(seve%e,rname,mess)
    error = .true.
    return
  endif
  !
  ! Read-write status?
  read = key.eq.'I'
  !
  ! Rewind the pointers to start of file
  call gfits_rewind_file(error)
  ! Current extension is Primary: starts at record 1
  hdurec = 1
  !
end subroutine gfits_open
!
subroutine gfits_close(error)
  use gfits_dependencies_interfaces
  use gfits_interfaces, except_this=>gfits_close
  use gfits_buf
  !---------------------------------------------------------------------
  ! @ public
  ! FITS API routine
  !       Disconnect from a FITS file, after flushing the data if needed
  !---------------------------------------------------------------------
  logical, intent(inout) :: error  ! Error flag
  ! Local
  logical :: error2
  !
  ! Ensure the following operations are correctly performed even in case
  ! of error recovery (i.e. entering here with error=.true.)
  error2 = .false.
  !
  ! First, dump current buffer
  if (.not.read) then
    call gfits_flush_data(error2)
    if (error2)  error = .true.
    if (error)  return
  endif
  !
  if (dev_type.eq.disk) then
    if (stdio) then
      close(unit=unit)
      call sic_frelun (unit)
    endif
    unit = 0
  endif
  !
end subroutine gfits_close
!
subroutine gfits_putrec(buff,error)
  use gfits_dependencies_interfaces
  use gfits_interfaces, except_this=>gfits_putrec
  use gfits_buf
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! Write one logical FITS record
  !---------------------------------------------------------------------
  integer(kind=1), intent(in)    :: buff(2880)  ! I/O buffer
  logical,         intent(inout) :: error       ! Error flag
  ! Local
  character(len=*), parameter :: rname='FITS'
  integer :: ier
  character(len=message_length) :: mess
  !
  if (dev_type.eq.disk) then
    write(unit=unit,iostat=ier,rec=irec) buff
    if (ier.ne.0) then
      call putios('E-FPUTREC  ',ier)
      error = .true.
      return
    endif
    irec = irec+1
  else
    write(mess,*) 'Unsupported device type ',dev_type
    call gfits_message(seve%e,rname,mess)
  endif
  !
end subroutine gfits_putrec
!
subroutine gfits_getrec(buff,error)
  use gfits_interfaces, except_this=>gfits_getrec
  !---------------------------------------------------------------------
  ! @ private
  ! Read one logical FITS record (verbose mode)
  !---------------------------------------------------------------------
  integer(kind=1), intent(out)   :: buff(2880)  ! I/O buffer
  logical,         intent(inout) :: error       ! Error flag
  ! Local
  logical :: eof  ! Unused
  !
  call fgetrec_sub(buff,error,eof,.false.)
  !
end subroutine gfits_getrec
!
subroutine fgetrecquiet(buff,error,eof)
  use gfits_interfaces, except_this=>fgetrecquiet
  !---------------------------------------------------------------------
  ! @ private
  ! Read one logical FITS record (quiet mode)
  !---------------------------------------------------------------------
  integer(kind=1), intent(out)   :: buff(2880)  ! I/O buffer
  logical,         intent(inout) :: error       ! Error flag
  logical,         intent(out)   :: eof         ! End of file flag
  !
  call fgetrec_sub(buff,error,eof,.true.)
  !
end subroutine fgetrecquiet
!
subroutine fgetrec_sub(buff,error,eof,quiet)
  use gfits_dependencies_interfaces
  use gfits_interfaces, except_this=>fgetrec_sub
  use gfits_buf
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! FITS  Internal routine
  !       Read one logical FITS record
  !---------------------------------------------------------------------
  integer(kind=1), intent(out)   :: buff(2880)  ! I/O buffer
  logical,         intent(inout) :: error       ! Error flag
  logical,         intent(out)   :: eof         ! End of file flag
  logical,         intent(in)    :: quiet       ! Verbosity flag
  ! Local
  integer :: ier
  character(len=message_length) :: mess
  !
  eof = .false.
  if (dev_type.eq.disk) then
    if (stdio) then            ! Normal fortran IO
      read(unit=unit,iostat=ier,rec=irec) buff
      ! Now Fortran-90 norm says IER < 0 is EOF.  
      if (ier.lt.0) then
        eof = .true.
        return
      elseif (ier.gt.0) then
        ! IF Quiet, Silently ignore the error and treat as EOF 
        if (quiet) then
          eof = .true.
        else
          write(mess,*) 'Irec ',irec
          call gfits_message(seve%e,'FGETREC',mess)
          call putios('E-FGETREC, IO error:  ',ier)
          error = .true.
        endif
        return
      endif
      irec = irec+1
    endif
  else
    write(mess,*) 'Unsupported device type: ',dev_type
    call gfits_message(seve%e,'FITS',mess)
  endif
end subroutine fgetrec_sub
!
subroutine gfits_skirec(nrec,error)
  use gildas_def
  use gfits_interfaces, except_this=>gfits_skirec
  use gfits_buf
  use gbl_message
  !---------------------------------------------------------------------
  ! @ public
  ! FITS  API routine
  !       Skips a (positive or negative) number of FITS logical records
  !---------------------------------------------------------------------
  integer(kind=record_length), intent(in)    :: nrec   ! Number of records to skip
  logical,                     intent(inout) :: error  ! Error flag
  ! Local
  integer(kind=record_length) :: i
  !
  if (.not.read) then
    call gfits_message(seve%e,'SKIP','Programming error. Not supported for '//  &
    'output')
    error = .true.
    return
  endif
  if (dev_type.eq.disk.and.stdio) then
    irec = irec+nrec
  else                         ! Should be optimised one day...
    do i=1,nrec
      call gfits_getrec(buffer,error)
    enddo
  endif
  return
  !
end subroutine gfits_skirec
!
subroutine gfits_getrecnum(irecnum)
  use gildas_def
  use gfits_interfaces, except_this=>gfits_getrecnum
  use gfits_buf
  !---------------------------------------------------------------------
  ! @ public
  ! FITS  API routine
  !       Returns the number of the present FITS 2880-bytes record.
  !---------------------------------------------------------------------
  integer(kind=record_length), intent(out) :: irecnum  ! Current record number
  irecnum = irec
end subroutine gfits_getrecnum
!
subroutine gfits_setrecnum(irecnum)
  use gildas_def
  use gfits_interfaces, except_this=>gfits_setrecnum
  use gfits_buf
  !---------------------------------------------------------------------
  ! @ public
  ! FITS  API Routine
  !       Sets the number of the FITS 2880-bytes record.
  !---------------------------------------------------------------------
  integer(kind=record_length), intent(in) :: irecnum  ! Current record number
  irec = irecnum
end subroutine gfits_setrecnum
!
subroutine gfits_getrecoffset(ioffset)
  use gfits_interfaces, except_this=>gfits_getrecoffset
  use gfits_buf
  !---------------------------------------------------------------------
  ! @ public
  ! FITS  API routine
  !       Returns the offset (in bytes) of the next data to be read
  !       inside the present 2880-bytes record.
  !---------------------------------------------------------------------
  integer(kind=4), intent(out) :: ioffset        ! Offset in current record
  ioffset = ib
end subroutine gfits_getrecoffset
!
subroutine gfits_setrecoffset(ioffset)
  use gfits_interfaces, except_this=>gfits_setrecoffset
  use gfits_buf
  !---------------------------------------------------------------------
  ! @ public
  ! FITS  API routine
  !       Sets the offset (in bytes) of the next data to be read inside
  !       the present 2880-bytes record.
  !---------------------------------------------------------------------
  integer(kind=4), intent(in) :: ioffset          ! Offset in current record
  ib = ioffset
end subroutine gfits_setrecoffset
!
subroutine gfits_getstdrec(error)
  use gfits_interfaces, except_this=>gfits_getstdrec
  use gfits_buf
  !---------------------------------------------------------------------
  ! @ public
  ! FITS  API routine
  !     Get the next buffer internally
  !     Only used by CLASS 3dfits.f90
  !---------------------------------------------------------------------
  logical, intent(inout) :: error  ! Error flag
  call gfits_getrec(buffer,error)
end subroutine gfits_getstdrec
!
subroutine fseefilepos()
  use gildas_def
  use gfits_interfaces, except_this=>fseefilepos
  use gfits_buf
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! Used while debugging.
  !---------------------------------------------------------------------
  character(len=*), parameter :: rname='FSEEFILEPOS'
  integer(kind=record_length) :: nextrec
  character(len=message_length) :: mess
  !
  inquire(unit=unit,nextrec=nextrec)
  write(mess,*) 'Nextrec = ',nextrec
  call gfits_message(seve%d,rname,mess)
  write(mess,*) 'IREC    = ',irec
  call gfits_message(seve%d,rname,mess)
  if (irec.eq.nextrec) then
    call gfits_message(seve%d,rname,'OK !')
  else
    call gfits_message(seve%d,rname,'There is a problem')
  endif
end subroutine fseefilepos
!
function gfits_iseof()
  use gfits_buf
  !---------------------------------------------------------------------
  ! @ public
  ! FITS API routine
  !     Tells if the FITS file has reached EOF
  !---------------------------------------------------------------------
  logical :: gfits_iseof                 ! intent(out)
  ! Local
  integer :: ier
  integer (kind=1) :: buff(2880)
  !
  ! call fSeeFilePos
  !
  ! Try to read the next buffer from the file.
  ! IREC contains the number of the next record to read.
  read(unit = unit,rec = irec,iostat = ier) buff
  if (ier.eq.0) then
    gfits_iseof = .false.
  else
    gfits_iseof = .true.
  endif
  !  call fSeeFilePos
end function gfits_iseof
!
subroutine gfits_rewind_file(error)
  use gfits_buf
  !---------------------------------------------------------------------
  ! @ public
  ! Rewind the pointers to start of file
  !---------------------------------------------------------------------
  logical, intent(inout) :: error
  !
  irec = 1
  if (read) then
    ib = 2880   ! Nothing left for read
  else
    ib = 0      ! Buffer is empty
  endif
  !
end subroutine gfits_rewind_file
!
subroutine gfits_rewind_hdu(error)
  use gfits_buf
  !---------------------------------------------------------------------
  ! @ public
  ! Rewind the pointers to start of current HDU
  !---------------------------------------------------------------------
  logical, intent(inout) :: error
  !
  irec = hdurec
  if (read) then
    ib = 2880   ! Nothing left for read
  else
    ib = 0      ! Buffer is empty
  endif
  !
end subroutine gfits_rewind_hdu
