module imbfits_column_types
  use gbl_message
  use gkernel_types
  use cfitsio_api
  use imbfits_file_type
  !
  public :: imbfits_read_column
  public :: imbfits_dump_column
  private
  !
  interface imbfits_read_column
    module procedure imbfits_read_logi_1d
    module procedure imbfits_read_inte_1d
    module procedure imbfits_read_real_1d
    module procedure imbfits_read_dble_1d
    module procedure imbfits_read_char_1d
    module procedure imbfits_read_dble_2d_into_1d
  end interface imbfits_read_column
  !
  interface imbfits_dump_column
    module procedure imbfits_dump_inte_1d
    module procedure imbfits_dump_real_1d
    module procedure imbfits_dump_dble_1d
    module procedure imbfits_dump_char_1d
    module procedure imbfits_dump_logi_1d
  end interface imbfits_dump_column
  !
contains
  !
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  ! Reading routines (1D)
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !
  subroutine imbfits_read_logi_1d(caller,file,key,n,logi,error)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    character(len=*),     intent(in)    :: caller
    type(imbfits_file_t), intent(in)    :: file
    character(len=*),     intent(in)    :: key
    integer(kind=4),      intent(in)    :: n
    type(fits_logi_1d_t), intent(inout) :: logi    ! INOUT: keep allocation status
    logical,              intent(inout) :: error
    ! Local
    character(len=*), parameter :: rname='IMBFITS>READ>LOGI>1D'
    integer(kind=4) :: colnum,status
    character(len=message_length) :: mess
    character(len=10) :: tkey,tval
    character(len=comment_length) :: tcomm
    !
    call imbfits_message(seve%t,rname,'Welcome')
    !
    if (file%unit.eq.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Input file not opened')
      error = .true.
      return
    endif
    !
    ! Allocations
    call reallocate_fits_logi_1d(key,n,logi,error)
    if (error)  return
    !
    ! Get column number
    status = 0
    call ftgcno(file%unit,.false.,logi%key,colnum,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Error while searching for column '''//trim(key)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    !
    ! Get corresponding TFORM
    tkey = 'TFORM'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,tcomm,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    if (tval.ne.'L' .and. tval.ne.'1L') then
      write(mess,'(A,A,A,A,A)')  &
            'Attempt to read column ''',trim(key),''' (type ',trim(tval),') in a logical*4 vector'
      call imbfits_message(seve%w,rname,mess)
    endif
    !
    ! Get corresponding TTYPE so that we get its comment
    tkey = 'TTYPE'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,logi%comment,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    !
    ! Read the column data
    if (n.eq.0)  return  ! No data, nothing more to do
    call ftgcl(file%unit,colnum,1,1,n,logi%val,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      write(mess,'(A,I0,A,A,A,I0)')  &
            'Error while reading column #',colnum,' (',trim(key),'), row #',1
      call imbfits_message(seve%e,rname,mess)
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
  end subroutine imbfits_read_logi_1d
  !
  subroutine imbfits_read_inte_1d(caller,file,key,n,inte,error)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    character(len=*),     intent(in)    :: caller
    type(imbfits_file_t), intent(in)    :: file
    character(len=*),     intent(in)    :: key
    integer(kind=4),      intent(in)    :: n
    type(fits_inte_1d_t), intent(inout) :: inte    ! INOUT: keep allocation status
    logical,              intent(inout) :: error
    ! Local
    character(len=*), parameter :: rname='IMBFITS>READ>INTE>1D'
    integer(kind=4) :: colnum,status
    logical :: anynull
    character(len=message_length) :: mess
    character(len=10) :: tkey,tval
    character(len=comment_length) :: tcomm
    !
    call imbfits_message(seve%t,rname,'Welcome')
    !
    if (file%unit.eq.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Input file not opened')
      error = .true.
      return
    endif
    !
    ! Allocations
    call reallocate_fits_inte_1d(key,n,inte,error)
    if (error)  return
    !
    ! Get column number
    status = 0
    call ftgcno(file%unit,.false.,inte%key,colnum,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Error while searching for column '''//trim(key)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    !
    ! Get corresponding TFORM
    tkey = 'TFORM'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,tcomm,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    if (tval.ne.'J' .and. tval.ne.'1J') then
      write(mess,'(A,A,A,A,A)')  &
            'Attempt to read column ',trim(key),' (type ',trim(tval),') in an integer*4 vector'
      call imbfits_message(seve%w,rname,mess)
    endif
    !
    ! Get corresponding TTYPE so that we get its comment
    tkey = 'TTYPE'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,inte%comment,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    !
    ! Read the column data
    if (n.eq.0)  return  ! No data, nothing more to do
    anynull = .false.
    call ftgcvj(file%unit,colnum,1,1,n,-1,inte%val,anynull,status)
    if (anynull .or. status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      write(mess,'(A,I0,A,A,A,I0)')  &
            'Error while reading column #',colnum,' (',trim(key),'), row #',1
      call imbfits_message(seve%e,rname,mess)
      if (anynull) then
        call imbfits_message(seve%e,rname,'Some null values found')
      else
        call cfitsio_errormsg(status)
      endif
      error = .true.
      return
    endif
  end subroutine imbfits_read_inte_1d
  !
  subroutine imbfits_read_real_1d(caller,file,key,n,real,error)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    character(len=*),     intent(in)    :: caller
    type(imbfits_file_t), intent(in)    :: file
    character(len=*),     intent(in)    :: key
    integer(kind=4),      intent(in)    :: n
    type(fits_real_1d_t), intent(inout) :: real    ! INOUT: keep allocation status
    logical,              intent(inout) :: error
    ! Local
    character(len=*), parameter :: rname='IMBFITS>READ>REAL>1D'
    integer(kind=4) :: colnum,status
    logical :: anynull
    character(len=message_length) :: mess
    character(len=10) :: tkey,tval
    character(len=comment_length) :: tcomm
    !
    call imbfits_message(seve%t,rname,'Welcome')
    !
    if (file%unit.eq.0) then
      call imbfits_message(seve%e,rname,'Input file not opened')
      error = .true.
      return
    endif
    !
    ! Allocations
    call reallocate_fits_real_1d(key,n,real,error)
    if (error)  return
    !
    ! Get column number
    status = 0
    call ftgcno(file%unit,.false.,real%key,colnum,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Error while searching for column '''//trim(key)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    !
    ! Get corresponding TFORM
    tkey = 'TFORM'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,tcomm,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    if (tval.ne.'E' .and. tval.ne.'1E') then
      write(mess,'(A,A,A,A,A)')  &
            'Attempt to read column ',trim(key),' (type ',trim(tval),') in a real*4 vector'
      call imbfits_message(seve%w,rname,mess)
    endif
    !
    ! Get corresponding TTYPE so that we get its comment
    tkey = 'TTYPE'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,real%comment,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    !
    ! Read the column data
    if (n.eq.0)  return  ! No data, nothing more to do
    anynull = .false.
    call ftgcve(file%unit,colnum,1,1,n,-1.e0,real%val,anynull,status)
    if (anynull .or. status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      write(mess,'(A,I0,A,A,A,I0)')  &
      'Error while reading column #',colnum,' (',trim(key),'), row #',1
      call imbfits_message(seve%e,rname,mess)
      if (anynull) then
        call imbfits_message(seve%e,rname,'Some null values found')
      else
        call cfitsio_errormsg(status)
      endif
      error = .true.
      return
    endif
  end subroutine imbfits_read_real_1d
  !
  subroutine imbfits_read_dble_1d(caller,file,key,n,dble,error)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    character(len=*),     intent(in)    :: caller
    type(imbfits_file_t), intent(in)    :: file
    character(len=*),     intent(in)    :: key
    integer(kind=4),      intent(in)    :: n
    type(fits_dble_1d_t), intent(inout) :: dble    ! INOUT: keep allocation status
    logical,              intent(inout) :: error
    ! Local
    character(len=*), parameter :: rname='IMBFITS>READ>DBLE>1D'
    integer(kind=4) :: colnum,status
    logical :: anynull
    character(len=message_length) :: mess
    character(len=10) :: tkey,tval
    character(len=comment_length) :: tcomm
    !
    call imbfits_message(seve%t,rname,'Welcome')
    !
    if (file%unit.eq.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Input file not opened')
      error = .true.
      return
    endif
    !
    ! Allocations
    call reallocate_fits_dble_1d(key,n,dble,error)
    if (error)  return
    !
    ! Get column number
    status = 0
    call ftgcno(file%unit,.false.,dble%key,colnum,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Error while searching for column '''//trim(key)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    !
    ! Get corresponding TFORM
    tkey = 'TFORM'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,tcomm,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    if (tval.ne.'D' .and. tval.ne.'1D') then
      write(mess,'(A,A,A,A,A)')  &
            'Attempt to read column ',trim(key),' (type ',trim(tval),') in a real*8 vector'
      call imbfits_message(seve%w,rname,mess)
    endif
    !
    ! Get corresponding TTYPE so that we get its comment
    tkey = 'TTYPE'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,dble%comment,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    !
    ! Read the column data
    if (n.eq.0)  return  ! No data, nothing more to do
    anynull = .false.
    call ftgcvd(file%unit,colnum,1,1,n,-1.d0,dble%val,anynull,status)
    if (anynull .or. status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      write(mess,'(A,I0,A,A,A,I0)')  &
            'Error while reading column #',colnum,' (',trim(key),'), row #',1
      call imbfits_message(seve%e,rname,mess)
      if (anynull) then
        call imbfits_message(seve%e,rname,'Some null values found')
      else
        call cfitsio_errormsg(status)
      endif
      error = .true.
      return
    endif
  end subroutine imbfits_read_dble_1d
  !
  subroutine imbfits_read_char_1d(caller,file,key,n,char,error,default)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    character(len=*),     intent(in)           :: caller
    type(imbfits_file_t), intent(in)           :: file
    character(len=*),     intent(in)           :: key
    integer(kind=4),      intent(in)           :: n
    type(fits_char_1d_t), intent(inout)        :: char    ! INOUT: keep allocation status
    logical,              intent(inout)        :: error
    character(len=*),     intent(in), optional :: default  ! If absent column or NULL values in column
    ! Local
    character(len=*), parameter :: rname='IMBFITS>READ>CHAR>1D'
    integer(kind=4) :: colnum,status,nc
    logical :: anynull
    character(len=message_length) :: mess
    character(len=10) :: tkey,tval
    character(len=comment_length) :: tcomm
    character(len=char1d_length) :: defstring
    !
    call imbfits_message(seve%t,rname,'Welcome')
    !
    if (file%unit.eq.0) then
      call imbfits_message(seve%e,rname,'Input file not opened')
      error = .true.
      return
    endif
    !
    ! Allocations
    call reallocate_fits_char_1d(key,n,char,error)
    if (error)  return
    !
    ! Get column number
    status = 0
    call ftgcno(file%unit,.false.,char%key,colnum,status)
    if (status.gt.0) then
      ! Error, probably no such column
      if (present(default)) then
        char%val(:) = default
        char%comment = 'WARNING! Column not found in table'
        return
        else
        call imbfits_message(seve%e,caller,'Error')
        call imbfits_message(seve%e,rname,'Error while searching for column '''//trim(key)//'''')
        call cfitsio_errormsg(status)
        error = .true.
        return
      endif
    endif
    !
    ! Get corresponding TFORM
    tkey = 'TFORM'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,tcomm,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    nc = len_trim(tval)
    if (tval(nc:nc).ne.'A') then
      write(mess,'(A,A,A,A,A)')  &
            'Attempt to read column ',trim(key),' (type ',trim(tval),') in a character vector'
      call imbfits_message(seve%w,rname,mess)
    endif
    !
    ! Get corresponding TTYPE so that we get its comment
    tkey = 'TTYPE'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,char%comment,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    !
    ! Read the column data
    if (n.eq.0)  return  ! No data, nothing more to do
    if (present(default)) then
        defstring = default
    else
        defstring = 'NULL'
    endif
    anynull = .false.
    call ftgcvs(file%unit,colnum,1,1,n,defstring,char%val,anynull,status)
    if (anynull .or. status.gt.0) then
      if (status.eq.0 .and. anynull .and. present(default)) then
        ! Caller gave a default in case of undefined values. Not an error
        continue
      else
        call imbfits_message(seve%e,caller,'Error')
        write(mess,'(A,I0,A,A,A,I0)')  &
              'Error while reading column #',colnum,' (',trim(key),'), row #',1
        call imbfits_message(seve%e,rname,mess)
        if (anynull) then
          call imbfits_message(seve%e,rname,'Some null values found')
        else
          call cfitsio_errormsg(status)
        endif
        error = .true.
        return
      endif
    endif
  end subroutine imbfits_read_char_1d
  !
  subroutine imbfits_read_dble_2d_into_1d(caller,file,key,nrow,ncol,dble,error)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    character(len=*),     intent(in)    :: caller
    type(imbfits_file_t), intent(in)    :: file
    character(len=*),     intent(in)    :: key
    integer(kind=4),      intent(in)    :: nrow
    integer(kind=4),      intent(in)    :: ncol
    type(fits_dble_1d_t), intent(inout) :: dble    ! INOUT: keep allocation status
    logical,              intent(inout) :: error
    ! Local
    character(len=*), parameter :: rname='IMBFITS>READ>DBLE>2D>INTO>1D'
    integer(kind=4) :: colnum,status,nelem
    logical :: anynull
    character(len=message_length) :: mess
    character(len=10) :: tkey,tval
    character(len=comment_length) :: tcomm
    !
    call imbfits_message(seve%t,rname,'Welcome')
    !
    ! *** JP Next block should be factorized
    if (file%unit.eq.0) then
      call imbfits_message(seve%e,rname,'Input file not opened')
      error = .true.
      return
    endif
    !
    ! Allocations
    call reallocate_fits_dble_1d(key,nrow*ncol,dble,error)
    if (error)  return
    !
    ! *** JP Next two blocks should be factorized
    ! Get column number
    status = 0
    call ftgcno(file%unit,.false.,dble%key,colnum,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Error while searching for column '''//trim(key)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    !
    ! Get corresponding TFORM
    tkey = 'TFORM'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,tcomm,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    ! ZZZ Some clever check here!
    !   if (tval.ne.'E') then
    !     write(mess,'(A,A,A,A,A)')  &
    !       'Attempt to read column ',trim(key),' (type ',trim(tval),') in a real*8 array'
    !     call imbfits_message(seve%w,rname,mess)
    !   endif
    !
    ! Get corresponding TTYPE so that we get its comment
    tkey = 'TTYPE'
    write(tkey(6:7),'(I0)')  colnum
    call ftgkys(file%unit,tkey,tval,dble%comment,status)
    if (status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      call imbfits_message(seve%e,rname,'Some error reading '''//trim(tkey)//'''')
      call cfitsio_errormsg(status)
      error = .true.
      return
    endif
    !
    nelem = nrow*ncol
    anynull = .false.
    call ftgcvd(file%unit,colnum,1,1,nelem,-1.d0,dble%val,anynull,status)
    ! *** JP Next block could be factorized
    if (anynull .or. status.gt.0) then
      call imbfits_message(seve%e,caller,'Error')
      write(mess,'(A,I0,A,A,A,I0)')  &
            'Error while reading column #',colnum,' (',trim(key),'), row #',1
      call imbfits_message(seve%e,rname,mess)
      if (anynull) then
        call imbfits_message(seve%e,rname,'Some null values found')
      else
        call cfitsio_errormsg(status)
      endif
      error = .true.
      return
    endif
  end subroutine imbfits_read_dble_2d_into_1d
  !
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  ! Dumping routines (1D)
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !
  subroutine imbfits_dump_inte_1d(inte,olun,error,full)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    type(fits_inte_1d_t), intent(in)    :: inte
    integer(kind=4),      intent(in)    :: olun   ! Output LUN
    logical,              intent(inout) :: error
    logical, optional,    intent(in)    :: full   ! Full output (all values)?
    ! Local
    character(len=key_length) :: key
    logical :: dofull
    !
    if (present(full)) then
      dofull = full
    else
      dofull = .false.
    endif
    key = inte%key
    call sic_upper(key)
    if (.not.associated(inte%val)) then
      write(olun,100)  key,trim(inte%comment)
    elseif (dofull) then
      write(olun,'(4A,I0)')  &
        trim(key),' (',trim(inte%comment),') is an integer column of dimensions ',inte%n
      call i4_type(inte%n,inte%val)
    elseif (inte%n.ge.3) then
      write(olun,103)  key,inte%val(1),inte%val(inte%n),trim(inte%comment)
    elseif (inte%n.eq.2) then
      write(olun,102)  key,inte%val(1:2),trim(inte%comment)
    else  ! 1 value
      write(olun,101)  key,inte%val(1),trim(inte%comment)
    endif
    !
    100 format(A8,' (I4) = NO DATA ASSOCIATED!',              T64,'/ ',A)
    101 format(A8,' (I4) =',1(1X,I14),                        T64,'/ ',A)
    102 format(A8,' (I4) =',2(1X,I14),                        T64,'/ ',A)
    103 format(A8,' (I4) =',1(1X,I14),'      ...     ',1X,I14,T64,'/ ',A)
  end subroutine imbfits_dump_inte_1d
  !
  subroutine imbfits_dump_real_1d(real,olun,error,full)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    type(fits_real_1d_t), intent(in)    :: real
    integer(kind=4),      intent(in)    :: olun   ! Output LUN
    logical,              intent(inout) :: error
    logical, optional,    intent(in)    :: full   ! Full output (all values)?
    ! Local
    character(len=key_length) :: key
    logical :: dofull
    !
    if (present(full)) then
      dofull = full
    else
      dofull = .false.
    endif
    key = real%key
    call sic_upper(key)
    if (.not.associated(real%val)) then
      write(olun,100)  key,trim(real%comment)
    elseif (dofull) then
      write(olun,'(4A,I0)')  &
        trim(key),' (',trim(real%comment),') is a real column of dimensions ',real%n
      call r4_type(real%n,real%val)
    elseif (real%n.ge.3) then
      write(olun,103)  key,real%val(1),real%val(real%n),trim(real%comment)
    elseif (real%n.eq.2) then
      write(olun,102)  key,real%val(1:2),trim(real%comment)
    else
      write(olun,101)  key,real%val(1),trim(real%comment)
    endif
    !
    ! Single precision floats: precision is 7.22 decimal digits
    100 format(A8,' (R4) = NO DATA ASSOCIATED!',                         T64,'/ ',A)
    101 format(A8,' (R4) =',1(1X,1PG14.7),                               T64,'/ ',A)
    102 format(A8,' (R4) =',2(1X,1PG14.7),                               T64,'/ ',A)
    103 format(A8,' (R4) =',1(1X,1PG14.7),'      ...     ',1(1X,1PG14.7),T64,'/ ',A)
  end subroutine imbfits_dump_real_1d
  !
  subroutine imbfits_dump_dble_1d(dble,olun,error,full)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    type(fits_dble_1d_t), intent(in)    :: dble
    integer(kind=4),      intent(in)    :: olun   ! Output LUN
    logical,              intent(inout) :: error
    logical, optional,    intent(in)    :: full   ! Full output (all values)?
    ! Local
    character(len=key_length) :: key
    logical :: dofull
    !
    if (present(full)) then
      dofull = full
    else
      dofull = .false.
    endif
    key = dble%key
    call sic_upper(key)
    if (.not.associated(dble%val)) then
      write(olun,100)  key,trim(dble%comment)
    elseif (dofull) then
      write(olun,'(4A,I0)')  &
        trim(key),' (',trim(dble%comment),') is a double column of dimensions ',dble%n
      call r8_type(dble%n,dble%val)
    elseif (dble%n.ge.3) then
      write(olun,103)  key,dble%val(1),dble%val(dble%n),trim(dble%comment)
    elseif (dble%n.eq.2) then
      write(olun,102)  key,dble%val(1:2),trim(dble%comment)
    else
      write(olun,101)  key,dble%val(1),trim(dble%comment)
    endif
    !
    ! Double precision floats: precision is 15.95 decimal digits (using
    ! more than 15 digits can make appear roundoff problems because of
    ! precision is not exactly 16).
    100 format(A8,' (R8) = NO DATA ASSOCIATED!',                  T64,'/ ',A)
    101 format(A8,' (R8) =',1(1X,1PG22.15),                       T64,'/ ',A)
    102 format(A8,' (R8) =',2(1X,1PG22.15),                       T64,'/ ',A)
    103 format(A8,' (R8) =',1(1X,1PG22.15),' ... ',1(1X,1PG22.15),T64,'/ ',A)
  end subroutine imbfits_dump_dble_1d
  !
  subroutine imbfits_dump_char_1d(char,olun,error,full)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    type(fits_char_1d_t), intent(in)    :: char
    integer(kind=4),      intent(in)    :: olun   ! Output LUN
    logical,              intent(inout) :: error
    logical, optional,    intent(in)    :: full   ! Full output (all values)?
    ! Local
    character(len=key_length) :: key
    logical :: dofull
    !
    if (present(full)) then
      dofull = full
    else
      dofull = .false.
    endif
    key = char%key
    call sic_upper(key)
    if (.not.associated(char%val)) then
      write(olun,100)  key,trim(char%comment)
    elseif (dofull) then
      write(olun,'(4A,I0,A,I0)')  &
        trim(key),' (',trim(char%comment),') is a character*',len(char%val(1)),' column of dimensions ',char%n
      call ch_type(char%n,char%val,len(char%val(1)))
    elseif (char%n.ge.3) then
      write(olun,103)  key,char%val(1),char%val(char%n),trim(char%comment)
    elseif (char%n.eq.2) then
      write(olun,102)  key,char%val(1:2),trim(char%comment)
    else
      write(olun,101)  key,char%val(1),trim(char%comment)
    endif
    !
    100 format(A8,' (C)  = NO DATA ASSOCIATED!',                 T64,'/ ',A)
    101 format(A8,' (C)  =',1(1X,A14),                           T64,'/ ',A)
    102 format(A8,' (C)  =',2(1X,A14),                           T64,'/ ',A)
    103 format(A8,' (C)  =',1(1X,A14),'      ...     ',1(1X,A14),T64,'/ ',A)
  end subroutine imbfits_dump_char_1d
  !
  subroutine imbfits_dump_logi_1d(logi,olun,error,full)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    type(fits_logi_1d_t), intent(in)    :: logi
    integer(kind=4),      intent(in)    :: olun   ! Output LUN
    logical,              intent(inout) :: error
    logical, optional,    intent(in)    :: full   ! Full output (all values)?
    ! Local
    character(len=key_length) :: key
    logical :: dofull
    !
    if (present(full)) then
      dofull = full
    else
      dofull = .false.
    endif
    key = logi%key
    call sic_upper(key)
    if (.not.associated(logi%val)) then
      write(olun,100)  key,trim(logi%comment)
    elseif (dofull) then
      write(olun,'(4A,I0)')  &
        trim(key),' (',trim(logi%comment),') is a logical column of dimensions ',logi%n
      call l_type(logi%n,logi%val)
    elseif (logi%n.ge.3) then
      write(olun,103)  key,logi%val(1),logi%val(logi%n),trim(logi%comment)
    elseif (logi%n.eq.2) then
      write(olun,102)  key,logi%val(1:2),trim(logi%comment)
    else
      write(olun,101)  key,logi%val(1),trim(logi%comment)
    endif
    !
    100 format(A8,' (L)  = NO DATA ASSOCIATED!',         T64,'/ ',A)
    101 format(A8,' (L)  =',1(1X,L8),                    T64,'/ ',A)
    102 format(A8,' (L)  =',2(1X,L8),                    T64,'/ ',A)
    103 format(A8,' (L)  =',1(1X,L8),'   ...  ',1(1X,L8),T64,'/ ',A)
  end subroutine imbfits_dump_logi_1d
  !
end module imbfits_column_types
