module mrtindex_list_colnames
  !
  integer(kind=4), parameter :: ncolumns=31
  character(len=11) :: columns(ncolumns) = (/  &
    'NUMBER     ','ENTRY      ','DIRECTORY  ','FITSFILE   ','MRTFILE    ',  &  !  1- 5
    'RECORD     ','WORD       ','VERSION    ','TELESCOPE  ','PROJID     ',  &  !  6-10
    'SOURCE     ','OBSERVED   ','UT         ','LST        ','AZIMUTH    ',  &  ! 11-15
    'ELEVATION  ','POSITION   ','FRONTEND   ','SCAN       ','BACKEND    ',  &  ! 16-20
    'OBSTYPE    ','SWITCHMODE ','POLARIMETRY','COMPLETE   ','CALIBRATED ',  &  ! 21-25
    'SOLVED     ','ITIME      ','ISLAST     ','WITH       ','RESULTS    ',  &  ! 26-30
    'DEFAULT    ' /)                                                           ! 31
  !
  integer(kind=4), parameter :: col_none        = 0  ! Nullifier
  integer(kind=4), parameter :: col_number      = 1
  integer(kind=4), parameter :: col_entry       = 2
  integer(kind=4), parameter :: col_directory   = 3
  integer(kind=4), parameter :: col_fitsfile    = 4
  integer(kind=4), parameter :: col_mrtfile     = 5
  integer(kind=4), parameter :: col_record      = 6
  integer(kind=4), parameter :: col_word        = 7
  integer(kind=4), parameter :: col_version     = 8
  integer(kind=4), parameter :: col_telescope   = 9
  integer(kind=4), parameter :: col_projid      = 10
  integer(kind=4), parameter :: col_source      = 11
  integer(kind=4), parameter :: col_observed    = 12
  integer(kind=4), parameter :: col_ut          = 13
  integer(kind=4), parameter :: col_lst         = 14
  integer(kind=4), parameter :: col_azimuth     = 15
  integer(kind=4), parameter :: col_elevation   = 16
  integer(kind=4), parameter :: col_position    = 17
  integer(kind=4), parameter :: col_frontend    = 18
  integer(kind=4), parameter :: col_scan        = 19
  integer(kind=4), parameter :: col_backend     = 20
  integer(kind=4), parameter :: col_obstype     = 21
  integer(kind=4), parameter :: col_switchmode  = 22
  integer(kind=4), parameter :: col_polarimetry = 23
  integer(kind=4), parameter :: col_complete    = 24
  integer(kind=4), parameter :: col_calibrated  = 25
  integer(kind=4), parameter :: col_solved      = 26
  integer(kind=4), parameter :: col_itime       = 27
  integer(kind=4), parameter :: col_islast      = 28
  integer(kind=4), parameter :: col_with        = 29
  integer(kind=4), parameter :: col_results     = 30
  ! Aliases
  integer(kind=4), parameter :: col_default     = 31
  !
  ! Aliases translation
  integer(kind=4), parameter :: col_default_list(12) =  &
    [col_number,col_version,col_projid,col_source,col_observed,  &
     col_ut,col_scan,col_backend,col_obstype,col_switchmode,  &
     col_calibrated,col_solved]
  !
end module mrtindex_list_colnames
!
module mrtindex_toc_parameters
  !---------------------------------------------------------------------
  ! Support module for Table-Of-Contents
  !---------------------------------------------------------------------
  !
  ! Key codes
  integer(kind=4), parameter :: mrtindex_toc_key_number    = 1
  integer(kind=4), parameter :: mrtindex_toc_key_version   = 2
  integer(kind=4), parameter :: mrtindex_toc_key_telescope = 3
  integer(kind=4), parameter :: mrtindex_toc_key_projid    = 4
  integer(kind=4), parameter :: mrtindex_toc_key_source    = 5
  integer(kind=4), parameter :: mrtindex_toc_key_observed  = 6
  integer(kind=4), parameter :: mrtindex_toc_key_frontend  = 7
  integer(kind=4), parameter :: mrtindex_toc_key_scan      = 8
  integer(kind=4), parameter :: mrtindex_toc_key_backend   = 9
  integer(kind=4), parameter :: mrtindex_toc_key_obstype   = 10
  integer(kind=4), parameter :: mrtindex_toc_key_switch    = 11
  integer(kind=4), parameter :: mrtindex_toc_key_polar     = 12
  integer(kind=4), parameter :: mrtindex_toc_key_calstatus = 13
  integer(kind=4), parameter :: mrtindex_toc_key_directory = 14
  !
  ! Mrtcal types, i.e. for fields which needs special decoding (e.g. gag_date:
  ! we won't display the I*4 value, but its translation as a string)
  integer(kind=4), parameter :: mrtindex_ptype_null=0
  integer(kind=4), parameter :: mrtindex_ptype_teles=1
  integer(kind=4), parameter :: mrtindex_ptype_gagdate=2
  integer(kind=4), parameter :: mrtindex_ptype_backend=3
  integer(kind=4), parameter :: mrtindex_ptype_obstype=4
  integer(kind=4), parameter :: mrtindex_ptype_switchmode=5
  integer(kind=4), parameter :: mrtindex_ptype_polarimetry=6
  integer(kind=4), parameter :: mrtindex_ptype_calstatus=7
  integer(kind=4), parameter :: mrtindex_ptype_directory=8
  integer(kind=4), parameter :: mrtindex_ptype_frontend=9
end module mrtindex_toc_parameters
!
module mrtindex_sort_var
  use toc_types
  !---------------------------------------------------------------------
  ! Support module for Table-Of-Contents
  !---------------------------------------------------------------------
  !
  type(toc_t), target :: mtoc
  !
end module mrtindex_sort_var
!
subroutine mrtindex_list_columns(line,custom,error)
  use gbl_message
  use gkernel_interfaces
  use mrtindex_interfaces, except_this=>mrtindex_list_columns
  use mrtindex_list_colnames
  !---------------------------------------------------------------------
  ! @ public
  ! Support routine for command:
  !   MLIST /COLUMNS Key1 ... KeyN
  ! Get the custom list of columns identifiers
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line       !
  integer(kind=4),  intent(out)   :: custom(:)  !
  logical,          intent(inout) :: error      !
  ! Local
  character(len=*), parameter :: rname='MLIST'
  integer(kind=4) :: iarg,nc
  integer(kind=4) :: ukeys(size(custom))
  character(len=12) :: argum,key
  !
  custom(:) = col_none
  ukeys(:) = col_none
  !
  do iarg=1,sic_narg(3)
    if (iarg.gt.size(ukeys)) then
      call mrtindex_message(seve%w,rname,'/COLUMNS list too long, truncated')
      return
    endif
    !
    call sic_ke(line,3,iarg,argum,nc,.true.,error)
    if (error)  return
    call sic_ambigs(rname,argum,key,ukeys(iarg),columns,ncolumns,error)
    if (error)  return
  enddo
  !
  call mrtindex_list_columns_set(ukeys,size(ukeys),custom,size(custom),error)
  if (error)  return
  !
end subroutine mrtindex_list_columns
!
subroutine mrtindex_list_columns_set(ukeys,nukeys,ckeys,nckeys,error)
  use gbl_message
  use mrtindex_list_colnames
  !---------------------------------------------------------------------
  ! @ private
  ! Translate user keys to column keys.
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: nukeys     !
  integer(kind=4), intent(in)    :: nckeys     !
  integer(kind=4), intent(in)    :: ukeys(nukeys)  !
  integer(kind=4), intent(out)   :: ckeys(nckeys)  !
  logical,         intent(inout) :: error     !
  ! Local
  character(len=*), parameter :: rname='MLIST'
  integer(kind=4) :: ikey,iout,nnew
  integer(kind=4) :: new(size(col_default_list))
  !
  ckeys(:) = col_none
  iout = 0
  !
  do ikey=1,nukeys
    if (ukeys(ikey).eq.col_none)  exit
    !
    select case (ukeys(ikey))
    case (col_default)
      nnew = size(col_default_list)
      new(1:nnew) = col_default_list
    case default
      nnew = 1
      new(1) = ukeys(ikey)
    end select
    !
    if (iout+nnew.gt.nckeys) then
      call mrtindex_message(seve%w,rname,'/COLUMNS list too long, truncated')
      return
    endif
    ckeys(iout+1:iout+nnew) = new(1:nnew)
    iout = iout+nnew
  enddo
  !
end subroutine mrtindex_list_columns_set
!
subroutine mrtindex_list(optx,name,custom,olun,page,error)
  use gbl_message
  use gkernel_interfaces
  use imbfits_parameters
  use mrtindex_interfaces, except_this=>mrtindex_list
  use mrtindex_types
  use mrtindex_list_colnames
  !---------------------------------------------------------------------
  ! @ public
  !---------------------------------------------------------------------
  type(mrtindex_optimize_t), intent(in)    :: optx       !
  character(len=*),          intent(in)    :: name       !
  integer(kind=4),           intent(in)    :: custom(:)  ! Columns to be listed
  integer(kind=4),           intent(in)    :: olun       ! Output logical unit
  logical,                   intent(in)    :: page       ! Page or Scroll mode?
  logical,                   intent(inout) :: error      !
  ! Local
  character(len=*), parameter :: rname='MLIST'
  logical, parameter :: rawdebug=.false.
  integer(kind=entry_length) :: ient,jent
  integer(kind=4) :: tt_lines
  logical :: defaul
  character(len=message_length) :: mess
  !
  if (optx%next.le.1) then
    call mrtindex_message(seve%w,rname,'No entry in '//trim(name)//' index')
    return
  endif
  !
  defaul = custom(1).eq.col_none
  tt_lines = sic_ttynlin()-2
  !
  ! Print header
  ient = 0  ! <=> Header
  if (rawdebug) then
    call mrtindex_list_one_raw(optx,ient,mess,error)
  elseif (defaul) then
    call mrtindex_list_one_default(optx,ient,mess,error)
  else
    call mrtindex_list_one_custom(optx,ient,custom,mess,error)
  endif
  call mrtindex_list_one_print(mess,olun)
  !
  do ient=1,optx%next-1
    jent = optx%sort(ient)
    !
    if (olun.eq.6 .and. page) then
      if (mod(ient,tt_lines).eq.0) then
        if (hlp_more().ne.0)  return
      endif
    endif
    !
    if (rawdebug) then
      call mrtindex_list_one_raw(optx,jent,mess,error)
    elseif (defaul) then
      call mrtindex_list_one_default(optx,jent,mess,error)
    else
      call mrtindex_list_one_custom(optx,jent,custom,mess,error)
    endif
    if (error)  return
    call mrtindex_list_one_print(mess,olun)
    !
  enddo
  !
end subroutine mrtindex_list
!
subroutine mrtindex_list_one_raw(optx,ient,mess,error)
  use gkernel_interfaces
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_list_one_raw
  use mrtindex_types
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command
  !   MLIST [IN|OUT] [/FILE OutputFile]
  ! Print 1 line for 1 entry (debugging output => raw values)
  !---------------------------------------------------------------------
  type(mrtindex_optimize_t),  intent(in)    :: optx   !
  integer(kind=entry_length), intent(in)    :: ient   !
  character(len=*),           intent(out)   :: mess   !
  logical,                    intent(inout) :: error  !
  !
  if (ient.eq.0) then
    ! Print header and quit
    write(mess,100)
  else
    write(mess,101)            &
      optx%mnum(ient),         &
      optx%num(ient),          &
      optx%version(ient),      &
      optx%filename(ient),     &
      optx%fnum(ient),         &
      optx%bloc(ient),         &
      optx%word(ient),         &
      optx%telescope(ient),    &
      optx%projid(ient),       &
      optx%source(ient),       &
      optx%dobs(ient)
      !
    write(mess,102)            &
      trim(mess),              &
      optx%ut(ient),           &
      optx%lst(ient),          &
      optx%az(ient),           &
      optx%el(ient),           &
      optx%lon(ient),          &
      optx%lat(ient),          &
      optx%system(ient),       &
      optx%equinox(ient)
      !
    write(mess,103)            &
      trim(mess),              &
      optx%frontend(1,ient),   &
      optx%frontend(2,ient),   &
      optx%frontend(3,ient),   &
      optx%frontend(4,ient)
      !
    write(mess,104)            &
      trim(mess),              &
      optx%scan(ient),         &
      optx%backend(ient),      &
      optx%obstype(ient),      &
      optx%switchmode(ient),   &
      optx%polstatus(ient),    &
      optx%filstatus(ient),    &
      optx%calstatus(ient),    &
      optx%solstatus(ient),    &
      optx%itime(ient),        &
      optx%idir(ient),         &
      optx%islast(ient)
  endif
  !
100 format(                                                                                &
  '# N.V File                                    Ent Blo Wor Tel Pro Source      Date  ',  &
  'UT         LST       Az        El             Frontend                         ',       &
  'Sca Bac Typ Swi Pol Com Cal Sol Time              Dir Last')
  !
  !         #    Num   Ver   File   Ent   Blo   Wor   Tel   Pro    Sour  Dobs
101 format(I0,1X,I0,1X,I0,1X,A40,1X,I0,1X,I0,1X,I0,1X,I0,1X,A8,1X,A12,1X,I5)
  !        Mess UT      LST     Az      El      Lon-Lat    Syst  Equinox
102 format(A,1X,F0.8,1X,F0.8,1X,F0.8,1X,F0.8,1X,2(F0.5,1X),I0,1X,F0.2)
  !        Mess Frontend
103 format(A,1X,4(A8,1X))
  !        Mess Sca   Bac   Typ   Swi   Pol   Com   Cal   Sol   Tim   Dir   Last
104 format(A,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,L1)
end subroutine mrtindex_list_one_raw
!
subroutine mrtindex_list_one_default(optx,ient,mess,error)
  use phys_const
  use classic_api
  use mrtindex_dependencies_interfaces
  use mrtindex_interfaces, except_this=>mrtindex_list_one_default
  use mrtindex_types
  !---------------------------------------------------------------------
  ! @ public
  ! Support routine for command
  !   MLIST [IN|OUT]
  ! Print 1 line for 1 entry (default output)
  !---------------------------------------------------------------------
  type(mrtindex_optimize_t),  intent(in)    :: optx   !
  integer(kind=entry_length), intent(in)    :: ient   !
  character(len=*),           intent(out)   :: mess   !
  logical,                    intent(inout) :: error  !
  ! Local
  real(kind=8), parameter :: rad_per_tsec=pi/4.32d4  ! Radians per seconds (time)
  character(len=11) :: date,num
  character(len=13) :: ut
  integer(kind=4) :: n2,nl
  !
  if (ient.eq.0) then
    ! Print header and quit
    write(mess,100)
    return
    !
  else
    if (optx%num(ient).lt.1000) then
      write(num(1:3),'(I3)')  optx%num(ient)
      n2 = 3
    else
      write(num,'(I0)') optx%num(ient)
      n2 = len_trim(num)
    endif
    call gag_todate(optx%dobs(ient),date,error)
    if (error)  return
    if (optx%ut(ient).ne.optx%ut(ient)) then  ! NaN
      ut = ' unknown'
    else
      call sexag(ut,optx%ut(ient),24)
    endif
    !
    write(mess,101)                               &
      num(1:n2),                                  &
      optx%version(ient),                         &
      optx%projid(ient),                          &
      optx%source(ient),                          &
      date,                                       &
      ut,                                         &
      optx%scan(ient),                            &
      backends_mrtcal(optx%backend(ient)),        &
      obstypes_mrtcal(optx%obstype(ient)),        &
      switchmodes_mrtcal(optx%switchmode(ient)),  &
      mrtindex_list_calstatus(optx%calstatus(ient)),  &
      mrtindex_list_solstatus(optx%solstatus(ient)),  &
      mrtindex_list_results(optx,ient)
    !
    nl = len_trim(mess)
    if (optx%filstatus(ient).ne.complete_full) then
      mess(nl+2:) = completenesses(optx%filstatus(ient))
    endif
  endif
  !
  !        'NNN.V PPPPPPPP SSSSSSSSSSSS DDDDDDDDDDD UUUUUUUUUUU SSS BBBBB OOOOOOOOOOO SSS CCCCCC SSSSSS RRRR...
100 format('  N.V ProjId    Source         Date          UT     Scn Backe  ObsType    Swi Calibr Solved Results')
  !        N    V     proj  sourc  date   ut     scan  back  obst   swit  cali
101 format(A,'.',I0,1X,A8,1X,A12,1X,A11,1X,A11,1X,I3,1X,A5,1X,A11,1X,A3,1X,A6,1X,A6,1X,A)
end subroutine mrtindex_list_one_default
!
subroutine mrtindex_list_one_custom(optx,ient,custom,mess,error)
  use gbl_constant
  use phys_const
  use classic_api
  use imbfits_parameters
  use mrtindex_dependencies_interfaces
  use mrtindex_interfaces, except_this=>mrtindex_list_one_custom
  use mrtindex_types
  use mrtindex_list_colnames
  use mrtindex_vars
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command
  !   MLIST [IN|OUT]
  ! Print 1 line for 1 entry (custom output)
  !---------------------------------------------------------------------
  type(mrtindex_optimize_t),  intent(in)    :: optx       !
  integer(kind=entry_length), intent(in)    :: ient       !
  integer(kind=4),            intent(in)    :: custom(:)  !
  character(len=*),           intent(out)   :: mess       !
  logical,                    intent(inout) :: error      !
  ! Local
  integer(kind=4) :: icol,nc,nc2
  real(kind=8), parameter :: rad_per_tsec=pi/4.32d4  ! Radians per seconds (time)
  character(len=11) :: date
  character(len=13) :: str13
  character(len=128) :: results
  type(mrtindex_entry_t) :: entry
  !
  mess = ''
  nc = 0
  if (ient.eq.0) then
    ! Print header only
    do icol=1,size(custom)
      select case (custom(icol))
      case (col_number)
        write(mess(nc+1:),'(A6)')   'NUMBER'
        nc = nc+7
      case (col_entry)
        write(mess(nc+1:),'(A6)')   'ENTRY'
        nc = nc+7
      case (col_directory)
        write(mess(nc+1:),'(A20)')  '-----DIRECTORY------'
        nc = nc+21
      case (col_fitsfile)
        write(mess(nc+1:),'(A40)')  '----------------FITSFILE----------------'
        nc = nc+fitsname_length+1
      case (col_mrtfile)
        write(mess(nc+1:),'(A20)')  '------MRTFILE-------'
        nc = nc+21
      case (col_record)
        write(mess(nc+1:),'(A4)')   'RECO'
        nc = nc+5
      case (col_word)
        write(mess(nc+1:),'(A4)')   'WORD'
        nc = nc+5
      case (col_version)
        write(mess(nc+1:),'(A3)')   'VER'
        nc = nc+4
      case (col_telescope)
        write(mess(nc+1:),'(A8)')   'TELESCOP'
        nc = nc+9
      case (col_projid)
        write(mess(nc+1:),'(A8)')   '-PROJID-'
        nc = nc+9
      case (col_source)
        write(mess(nc+1:),'(A12)')  '---SOURCE---'
        nc = nc+13
      case (col_observed)
        write(mess(nc+1:),'(A11)')  '-OBSERVED--'
        nc = nc+12
      case (col_ut)
        write(mess(nc+1:),'(A11)')  '----UT-----'
        nc = nc+12
      case (col_lst)
        write(mess(nc+1:),'(A11)')  '----LST----'
        nc = nc+12
      case (col_azimuth)
        write(mess(nc+1:),'(A11)')  '--AZIMUTH--'
        nc = nc+12
      case (col_elevation)
        write(mess(nc+1:),'(A11)')  '-ELEVATION-'
        nc = nc+12
      case (col_position)
        write(mess(nc+1:),'(A36)')  '--------------POSITION--------------'
        nc = nc+37
      case (col_frontend)
        write(mess(nc+1:),'(A19)')  '------FRONTEND-----'
        nc = nc+20
      case (col_scan)
        write(mess(nc+1:),'(A3)')   'SCA'
        nc = nc+4
      case (col_backend)
        write(mess(nc+1:),'(A5)')   'BACKE'
        nc = nc+6
      case (col_obstype)
        write(mess(nc+1:),'(A11)')  '--OBSTYPE--'
        nc = nc+12
      case (col_switchmode)
        write(mess(nc+1:),'(A3)')   'SWI'
        nc = nc+4
      case (col_polarimetry)
        write(mess(nc+1:),'(A3)')   'POL'
        nc = nc+4
      case (col_complete)
        write(mess(nc+1:),'(A10)')  '-COMPLETE-'
        nc = nc+11
      case (col_calibrated)
        write(mess(nc+1:),'(A6)')   'CALIBR'
        nc = nc+7
      case (col_solved)
        write(mess(nc+1:),'(A6)')   'SOLVED'
        nc = nc+7
      case (col_itime)
        write(mess(nc+1:),'(A19)')  '-------ITIME-------'
        nc = nc+20
      case (col_islast)
        write(mess(nc+1:),'(A3)')   'LAS'
        nc = nc+4
      case (col_with)
        write(mess(nc+1:),'(A28)')  '---WITH (OBS SCA BAC VER)---'
        nc = nc+29
      case (col_results)
        write(mess(nc+1:),'(A7)')  'RESULTS'
        nc = nc+8
      case default
        exit
      end select
    enddo
    !
  else
    !
    do icol=1,size(custom)
      select case (custom(icol))
      case (col_number)
        write(mess(nc+1:),'(I6)')   optx%num(ient)
        nc = nc+7
      case (col_entry)
        write(mess(nc+1:),'(I6)')   optx%fnum(ient)
        nc = nc+7
      case (col_directory)
        write(mess(nc+1:),'(A20)')  ix_dirs(optx%idir(ient))
        nc = nc+21
      case (col_fitsfile)
        write(mess(nc+1:),'(A40)')  optx%filename(ient)
        nc = nc+fitsname_length+1
      case (col_mrtfile)
        write(mess(nc+1:),'(A20)')  ix_files(optx%idir(ient))%spec
        nc = nc+21
      case (col_record)
        write(mess(nc+1:),'(I4)')   optx%bloc(ient)
        nc = nc+5
      case (col_word)
        write(mess(nc+1:),'(I4)')   optx%word(ient)
        nc = nc+5
      case (col_version)
        write(mess(nc+1:),'(I3)')   optx%version(ient)
        nc = nc+4
      case (col_telescope)
        write(mess(nc+1:),'(A8)')   telescopes(optx%telescope(ient))
        nc = nc+9
      case (col_projid)
        write(mess(nc+1:),'(A8)')   optx%projid(ient)
        nc = nc+9
      case (col_source)
        write(mess(nc+1:),'(A12)')  optx%source(ient)
        nc = nc+13
      case (col_observed)
        call gag_todate(optx%dobs(ient),date,error)
        if (error)  return
        write(mess(nc+1:),'(A11)')  date
        nc = nc+12
      case (col_ut)
        if (optx%ut(ient).ne.optx%ut(ient)) then  ! NaN
          str13 = ' unknown'
        else
          call sexag(str13,optx%ut(ient),24)
        endif
        write(mess(nc+1:),'(A11)')  str13
        nc = nc+12
      case (col_lst)
        if (optx%lst(ient).ne.optx%lst(ient)) then  ! NaN
          str13 = ' unknown'
        else
          call sexag(str13,optx%lst(ient)*rad_per_tsec,24)
        endif
        write(mess(nc+1:),'(A11)')  str13
        nc = nc+12
      case (col_azimuth)
        if (optx%az(ient).ne.optx%az(ient)) then  ! NaN
          str13 = ' unknown'
        else
          write(str13,'(F0.8)') optx%az(ient)*deg_per_rad
        endif
        write(mess(nc+1:),'(A11)')  str13
        nc = nc+12
      case (col_elevation)
        if (optx%el(ient).ne.optx%el(ient)) then  ! NaN
          str13 = ' unknown'
        else
          write(str13,'(F0.8)') optx%el(ient)*deg_per_rad
        endif
        write(mess(nc+1:),'(A11)')  str13
        nc = nc+12
      case (col_position)
        if (optx%lon(ient).ne.optx%lon(ient)) then  ! NaN
          mess(nc+1:nc+12) = ' --:--:--.--'
        elseif (optx%system(ient).eq.type_eq) then
          call rad2sexa(optx%lon(ient), 24,mess(nc+1:nc+12))
        else
          call rad2sexa(optx%lon(ient),360,mess(nc+1:nc+12))
        endif
        nc = nc+13
        if (optx%lat(ient).ne.optx%lat(ient)) then  ! NaN
          mess(nc+1:nc+12) = ' ---:--:--.-'
        else
          call rad2sexa(optx%lat(ient),360,mess(nc+1:nc+12))
        endif
        nc = nc+13
        if (optx%system(ient).eq.type_eq) then
          write(mess(nc+1:),'(A3,1X,F0.1)')  'Eq.',optx%equinox(ient)
        elseif (optx%system(ient).eq.type_ga) then
          mess(nc+1:nc+3) = 'Ga.'
        else
          mess(nc+1:nc+2) = '??'
        endif
        nc = nc+11
      case (col_frontend)
        write(mess(nc+1:),'(A19)')  mrtindex_list_frontend(optx%frontend(:,ient))
        nc = nc+20
      case (col_scan)
        write(mess(nc+1:),'(I3)')   optx%scan(ient)
        nc = nc+4
      case (col_backend)
        write(mess(nc+1:),'(A5)')   backends_mrtcal(optx%backend(ient))
        nc = nc+6
      case (col_obstype)
        write(mess(nc+1:),'(A11)')  obstypes_mrtcal(optx%obstype(ient))
        nc = nc+12
      case (col_switchmode)
        write(mess(nc+1:),'(A3)')   switchmodes_mrtcal(optx%switchmode(ient))
        nc = nc+4
      case (col_polarimetry)
        write(mess(nc+1:),'(A3)')   polstatus(optx%polstatus(ient))
        nc = nc+4
      case (col_complete)
        write(mess(nc+1:),'(A10)')  completenesses(optx%filstatus(ient))
        nc = nc+11
      case (col_calibrated)
        write(mess(nc+1:),'(A6)')   calstatus(optx%calstatus(ient))
        nc = nc+7
      case (col_solved)
        write(mess(nc+1:),'(A6)')   solstatus(optx%solstatus(ient))
        nc = nc+7
      case (col_itime)
        write(mess(nc+1:),'(I19)')  optx%itime(ient)
        nc = nc+20
      case (col_islast)
        write(mess(nc+1:),'(L3)')   optx%islast(ient)
        nc = nc+4
      case (col_with)
        call mrtindex_optimize_to_entry(optx,ient,entry,error)
        if (error)  return
        call mrtindex_entry_lscience(entry%head,mess(nc+1:),nc2,error)
        if (error)  return
        nc = nc+nc2+1
      case (col_results)
        results = mrtindex_list_results(optx,ient)
        write(mess(nc+1:),'(A)')  trim(results)
        nc = nc+len_trim(results)+1
      case default
        exit
      end select
    enddo
    !
  endif
  !
  call mrtindex_entry_free(entry,error)
  if (error)  return
  !
end subroutine mrtindex_list_one_custom
!
function mrtindex_list_frontend(frontend) result(ostring)
  use mrtindex_types
  !---------------------------------------------------------------------
  ! @ private
  ! Return the frontend string to be displayed by the MLIST command.
  ! Note the syntax must match the one understood by MFIND /FRONTEND
  !---------------------------------------------------------------------
  character(len=19) :: ostring ! 4 receivers * 4 chars + 3 ampersands
  character(len=*), intent(in) :: frontend(:)
  !
  integer(kind=4) :: ifront,nc,nc2
  !
  nc = 0
  do ifront=1,mrtcal_indx_mfrontend
    nc2 = len_trim(frontend(ifront))
    if (nc2.le.0)  exit
    write(ostring(nc+1:),'(A,A1)') frontend(ifront)(1:nc2),'&'
    nc = nc+nc2+1
  enddo
  if (nc.gt.0)  ostring(nc:nc) = ' '  ! Drop the last '&'
end function mrtindex_list_frontend
!
function mrtindex_list_calstatus(status)
  use mrtindex_parameters
  !---------------------------------------------------------------------
  ! @ private
  ! Return the calibration status string to be displayed by the LIST
  ! command
  !---------------------------------------------------------------------
  character(len=calstatus_length) :: mrtindex_list_calstatus
  integer(kind=4), intent(in) :: status
  !
  select case (status)
  case (calstatus_none)
    mrtindex_list_calstatus = '--'
  case (calstatus_done,calstatus_failed,calstatus_empty,calstatus_skipped)
    mrtindex_list_calstatus = calstatus(status)
  case default
    mrtindex_list_calstatus = '???'
  end select
end function mrtindex_list_calstatus
!
function mrtindex_list_solstatus(status)
  use mrtindex_parameters
  !---------------------------------------------------------------------
  ! @ private
  ! Return the solve status string to be displayed by the LIST command
  !---------------------------------------------------------------------
  character(len=solstatus_length) :: mrtindex_list_solstatus
  integer(kind=4), intent(in) :: status
  !
  select case (status)
  case (solstatus_none)
    mrtindex_list_solstatus = '--'
  case (solstatus_done,solstatus_failed)
    mrtindex_list_solstatus = solstatus(status)
  case default
    mrtindex_list_solstatus = '???'
  end select
end function mrtindex_list_solstatus
!
function mrtindex_list_results(optx,ient) result(string)
  use mrtindex_interfaces, except_this=>mrtindex_list_results
  use mrtindex_types
  !---------------------------------------------------------------------
  ! @ private
  ! List the scan results (Tsys, pointing, etc).
  ! No error returned on purpose (LIST should not stop)
  !---------------------------------------------------------------------
  character(len=128) :: string
  type(mrtindex_optimize_t),  intent(in) :: optx
  integer(kind=entry_length), intent(in) :: ient
  ! Local
  type(mrtindex_entry_t) :: entry
  logical :: error
  !
  error = .false.
  !
  call mrtindex_optimize_to_entry(optx,ient,entry,error)
  if (error)  goto 10
  !
  if (entry%head%presec(sec_calib_id)) then
    call mrtindex_entry_lcalib(entry%head,string,error)
    if (error)  goto 10
  elseif (entry%head%presec(sec_pointing_id)) then
    call mrtindex_entry_lpointing(entry%head,string,error)
    if (error)  goto 10
  else
    string = ''
  endif
  !
  call mrtindex_entry_free(entry,error)
  if (error)  goto 10
  !
  return
10 continue
  string = '<error>'
end function mrtindex_list_results
!
subroutine mrtindex_list_one_print(message,olun)
  use gbl_message
  use mrtindex_interfaces, except_this=>mrtindex_list_one_print
  !---------------------------------------------------------------------
  ! @ private
  !  Send the message to the given Logical Unit. Quite generic, could
  ! be used in other contexts.
  !---------------------------------------------------------------------
  character(len=*), intent(in) :: message
  integer(kind=4),  intent(in) :: olun
  ! Local
  character(len=*), parameter :: rname='MLIST'
  !
  if (olun.eq.6) then
    call mrtindex_message(seve%r,rname,message)
  else
    write(olun,'(A)') trim(message)
  endif
  !
end subroutine mrtindex_list_one_print
!
!=======================================================================
!
subroutine mrtindex_list_pointing(optx,name,olun,error)
  use gbl_message
  use mrtindex_dependencies_interfaces
  use mrtindex_interfaces, except_this=>mrtindex_list_pointing
  use mrtindex_types
  use mrtindex_table
  !---------------------------------------------------------------------
  ! @ public
  ! MRTCAL support routine for command
  !   MLIST [IN|CURRENT] /POINTING [/FILE Output]
  ! List the current with specific 'pointing' format (listing the
  ! pointing results)
  !---------------------------------------------------------------------
  type(mrtindex_optimize_t), intent(in)    :: optx   !
  character(len=*),          intent(in)    :: name   ! Index name
  integer(kind=4),           intent(in)    :: olun   !
  logical,                   intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='MLIST>POINTING'
  integer(kind=entry_length) :: ient,jent
  type(mrtindex_entry_t) :: entry
  type(table_t) :: tab
  type(line_t) :: line
  !
  if (optx%next.le.1) then
    call mrtindex_message(seve%w,rname,'No entry in '//trim(name)//' index')
    return
  endif
  !
  ! Register columns
  call tab%register_column('Date','[gag]',6,'(i6)',error)
  if (error)  return
  call tab%register_column('Scan','',3,'(i3)',error)
  if (error)  return
  call tab%register_column('idBe','',5,'(a5)',error)
  if (error)  return
  call entry%head%poi%list_register_columns(tab,error)
  if (error)  return
  !
  ! List header
  call tab%header(olun,error)
  if (error)  return
  !
  ! List lines
  do ient=1,optx%next-1
    jent = optx%sort(ient)
    !
    call mrtindex_optimize_to_entry(optx,jent,entry,error)
    if (error)  return
    if (.not.entry%head%presec(sec_pointing_id))  cycle
    !
    call line%new_value(tab,entry%head%key%dobs,error)
    if (error)  return
    call line%new_value(tab,entry%head%key%scan,error)
    if (error)  return
    call line%new_value(tab,backends_mrtcal(entry%head%key%backend),error)
    if (error)  return
    call entry%head%poi%list(tab,line,entry%head%key%backend,olun,error)
    if (error)  return
    !
    call line%reset(error)
    if (error)  return
  enddo
  !
end subroutine mrtindex_list_pointing
!
!=======================================================================
!
subroutine mrtindex_list_toc_comm(optx,line,olun,error)
  use gildas_def
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_list_toc_comm
  use mrtindex_sort_var
  use mrtindex_toc_parameters
  use mrtindex_types
  !---------------------------------------------------------------------
  ! @ public
  ! MRTCAL support routine for command
  !   MLIST [IN|CURRENT] /TOC [Key1] ... [KeyN]  [/VARIABLE VarName]
  ! Main entry point
  !---------------------------------------------------------------------
  type(mrtindex_optimize_t), intent(in)    :: optx   !
  character(len=*),          intent(in)    :: line   ! Input command line
  integer(kind=4),           intent(in)    :: olun   !
  logical,                   intent(inout) :: error  ! Logical error flag
  ! Local
  integer(kind=4), parameter :: opttoc=1  ! /TOC
  integer(kind=4), parameter :: optvar=5  ! /VARIABLE
  integer(kind=4) :: toc_keys(13)  ! Arbitrary number of args accepted in option /TOC
  character(len=varname_length) :: tocname
  integer(kind=4) :: nc
  !
  call mrtindex_toc_init(mtoc,error)
  if (error)  return
  !
  ! Default (unchanged in no arguments)
  toc_keys(:) = toc_key_null
  toc_keys(1) = mrtindex_toc_key_observed
  toc_keys(2) = mrtindex_toc_key_scan
  call toc_getkeys(line,opttoc,mtoc,toc_keys,error)
  if (error)  return
  !
  tocname = 'MTOC'  ! Default structure name
  call sic_ch(line,optvar,1,tocname,nc,.false.,error)
  if (error)  return
  !
  call mrtindex_list_toc(optx,toc_keys,tocname,olun,error)
  if (error)  return
  !
end subroutine mrtindex_list_toc_comm
!
subroutine mrtindex_toc_init(toc,error)
  use gkernel_interfaces
  use toc_types
  use classic_api
  use mrtindex_toc_parameters
  !---------------------------------------------------------------------
  ! @ private
  ! MRTCAL Support routine for command MLIST /TOC
  ! Initialization routine
  !---------------------------------------------------------------------
  type(toc_t), intent(inout) :: toc    !
  logical,     intent(inout) :: error  !
  ! Local
  character(len=*), parameter :: rname='TOC/INIT'
  integer(kind=4) :: ier
  !
  if (toc%initialized)  return
  !
  toc%nkey = 14
  allocate(toc%keys(toc%nkey),stat=ier)
  if (failed_allocate(rname,'keys array',ier,error)) return
  !
  toc%keys(1)%id            = mrtindex_toc_key_number
  toc%keys(1)%keyword       = 'NUM'
  toc%keys(1)%sic_var_name  = 'num'
  toc%keys(1)%human_name    = 'NUMBER'
  toc%keys(1)%message       = 'Number of numbers......'
  toc%keys(1)%ftype         = toc_ftype_i8_1d
  toc%keys(1)%ptype         = mrtindex_ptype_null
  !
  toc%keys(2)%id            = mrtindex_toc_key_version
  toc%keys(2)%keyword       = 'VER'
  toc%keys(2)%sic_var_name  = 'ver'
  toc%keys(2)%human_name    = 'VERSION'
  toc%keys(2)%message       = 'Number of versions.....'
  toc%keys(2)%ftype         = toc_ftype_i4_1d
  toc%keys(2)%ptype         = mrtindex_ptype_null
  !
  toc%keys(3)%id            = mrtindex_toc_key_telescope
  toc%keys(3)%keyword       = 'TELE'
  toc%keys(3)%sic_var_name  = 'tele'
  toc%keys(3)%human_name    = 'TELESCOPE'
  toc%keys(3)%message       = 'Number of telescopes...'
  toc%keys(3)%ftype         = toc_ftype_i4_1d
  toc%keys(3)%ptype         = mrtindex_ptype_teles
  !
  toc%keys(4)%id            = mrtindex_toc_key_projid
  toc%keys(4)%keyword       = 'ID'
  toc%keys(4)%sic_var_name  = 'id'
  toc%keys(4)%human_name    = 'ID'
  toc%keys(4)%message       = 'Number of projects.....'
  toc%keys(4)%ftype         = toc_ftype_c8_1d
  toc%keys(4)%ptype         = mrtindex_ptype_null
  !
  toc%keys(5)%id            = mrtindex_toc_key_source
  toc%keys(5)%keyword       = 'SOUR'
  toc%keys(5)%sic_var_name  = 'sour'
  toc%keys(5)%human_name    = 'SOURCE'
  toc%keys(5)%message       = 'Number of sources......'
  toc%keys(5)%ftype         = toc_ftype_c12_1d
  toc%keys(5)%ptype         = mrtindex_ptype_null
  !
  toc%keys(6)%id            = mrtindex_toc_key_observed
  toc%keys(6)%keyword       = 'OBS'
  toc%keys(6)%sic_var_name  = 'obs'
  toc%keys(6)%human_name    = 'OBSERVED' ! Observed date
  toc%keys(6)%message       = 'Number of observation dates'
  toc%keys(6)%ftype         = toc_ftype_i4_1d
  toc%keys(6)%ptype         = mrtindex_ptype_gagdate
  !
  toc%keys(7)%id            = mrtindex_toc_key_frontend
  toc%keys(7)%keyword       = 'FRONTEND'
  toc%keys(7)%sic_var_name  = 'frontend'
  toc%keys(7)%human_name    = 'FRONTEND'
  toc%keys(7)%message       = 'Number of frontends.....'
  toc%keys(7)%ftype         = toc_ftype_c8_2d
  toc%keys(7)%ptype         = mrtindex_ptype_frontend
  !
  toc%keys(8)%id            = mrtindex_toc_key_scan
  toc%keys(8)%keyword       = 'SCAN'
  toc%keys(8)%sic_var_name  = 'scan'
  toc%keys(8)%human_name    = 'SCAN'
  toc%keys(8)%message       = 'Number of scans........'
  toc%keys(8)%ftype         = toc_ftype_i4_1d
  toc%keys(8)%ptype         = mrtindex_ptype_null
  !
  toc%keys(9)%id            = mrtindex_toc_key_backend
  toc%keys(9)%keyword       = 'BACK'
  toc%keys(9)%sic_var_name  = 'back'
  toc%keys(9)%human_name    = 'BACKEND'
  toc%keys(9)%message       = 'Number of backends.....'
  toc%keys(9)%ftype         = toc_ftype_i4_1d
  toc%keys(9)%ptype         = mrtindex_ptype_backend
  !
  toc%keys(10)%id           = mrtindex_toc_key_obstype
  toc%keys(10)%keyword      = 'TYPE'
  toc%keys(10)%sic_var_name = 'type'
  toc%keys(10)%human_name   = 'OBSTYPE'
  toc%keys(10)%message      = 'Number of obs. types...'
  toc%keys(10)%ftype        = toc_ftype_i4_1d
  toc%keys(10)%ptype        = mrtindex_ptype_obstype
  !
  toc%keys(11)%id           = mrtindex_toc_key_switch
  toc%keys(11)%keyword      = 'SWITCH'
  toc%keys(11)%sic_var_name = 'switch'
  toc%keys(11)%human_name   = 'SWITCHMODE'
  toc%keys(11)%message      = 'Number of switch modes.'
  toc%keys(11)%ftype        = toc_ftype_i4_1d
  toc%keys(11)%ptype        = mrtindex_ptype_switchmode
  !
  toc%keys(12)%id           = mrtindex_toc_key_polar
  toc%keys(12)%keyword      = 'POLAR'
  toc%keys(12)%sic_var_name = 'polarimetry'
  toc%keys(12)%human_name   = 'POLARIMETRY'
  toc%keys(12)%message      = 'Number of polar. files.'
  toc%keys(12)%ftype        = toc_ftype_i4_1d
  toc%keys(12)%ptype        = mrtindex_ptype_polarimetry
  !
  toc%keys(13)%id           = mrtindex_toc_key_calstatus
  toc%keys(13)%keyword      = 'CALIB'
  toc%keys(13)%sic_var_name = 'calibrated'
  toc%keys(13)%human_name   = 'CALIBRATED'
  toc%keys(13)%message      = 'Number of calib status.'
  toc%keys(13)%ftype        = toc_ftype_i4_1d
  toc%keys(13)%ptype        = mrtindex_ptype_calstatus
  !
  toc%keys(14)%id           = mrtindex_toc_key_directory
  toc%keys(14)%keyword      = 'DIR'
  toc%keys(14)%sic_var_name = 'directory'
  toc%keys(14)%human_name   = 'DIRECTORY'
  toc%keys(14)%message      = 'Number of directories.'
  toc%keys(14)%ftype        = toc_ftype_i4_1d
  toc%keys(14)%ptype        = mrtindex_ptype_directory
  !
  call toc_init_pointers(toc,error)
  if (error)  return
  !
  toc%initialized = .true.
  !
end subroutine mrtindex_toc_init
!
subroutine mrtindex_toc_clean(error)
  use classic_api
  use mrtindex_sort_var
  !---------------------------------------------------------------------
  ! @ private
  ! MRTCAL Support routine for command MLIST /TOC
  ! Clean the global variable holding the TOC
  !---------------------------------------------------------------------
  logical, intent(inout) :: error  !
  !
  call toc_clean(mtoc,error)
  ! if (error)  continue
  !
end subroutine mrtindex_toc_clean
!
subroutine mrtindex_list_toc(optx,keywords,tocname,olun,error)
  use classic_api
  use mrtindex_interfaces, except_this=>mrtindex_list_toc
  use mrtindex_types
  use mrtindex_sort_var
  !---------------------------------------------------------------------
  ! @ private
  ! MRTCAL Support routine for command
  !   MLIST /TOC
  ! Processing routine
  !---------------------------------------------------------------------
  type(mrtindex_optimize_t), intent(in)    :: optx         ! The optx whose TOC is desired
  integer(kind=4),           intent(in)    :: keywords(:)  ! Key identifiers
  character(len=*),          intent(in)    :: tocname      ! Structure name
  integer(kind=4),           intent(in)    :: olun         !
  logical,                   intent(inout) :: error        ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='MLIST/TOC'
  !
  call mrtindex_toc_datasetup(mtoc,optx)
  !
  call toc_main(rname,mtoc,optx%next-1,keywords,tocname,olun,mrtindex_toc_format,error)
  if (error)  return
  !
end subroutine mrtindex_list_toc
!
subroutine mrtindex_toc_datasetup(toc,idx)
  use toc_types
  use mrtindex_types
  !---------------------------------------------------------------------
  ! @ private
  ! MRTCAL support routine for command
  !   MLIST /TOC
  ! Associate the TOC data pointers to the index whose TOC is desired
  !---------------------------------------------------------------------
  type(toc_t),               intent(inout) :: toc
  type(mrtindex_optimize_t), intent(in)    :: idx  ! The idx whose TOC is desired
  !
  toc%keys( 1)%ptr%i8%data1  => idx%num
  toc%keys( 2)%ptr%i4%data1  => idx%version
  toc%keys( 3)%ptr%i4%data1  => idx%telescope
  toc%keys( 4)%ptr%c8%data1  => idx%projid
  toc%keys( 5)%ptr%c12%data1 => idx%source
  toc%keys( 6)%ptr%i4%data1  => idx%dobs
  toc%keys( 7)%ptr%c8%data2  => idx%frontend
  toc%keys( 8)%ptr%i4%data1  => idx%scan
  toc%keys( 9)%ptr%i4%data1  => idx%backend
  toc%keys(10)%ptr%i4%data1  => idx%obstype
  toc%keys(11)%ptr%i4%data1  => idx%switchmode
  toc%keys(12)%ptr%i4%data1  => idx%polstatus
  toc%keys(13)%ptr%i4%data1  => idx%calstatus
  toc%keys(14)%ptr%i4%data1  => idx%idir
  !
end subroutine mrtindex_toc_datasetup
!
subroutine mrtindex_toc_format(key,ival,output)
  use toc_types
  use imbfits_parameters
  use mrtindex_parameters
  use mrtindex_vars
  use mrtindex_toc_parameters
  use mrtindex_interfaces, except_this=>mrtindex_toc_format
  !---------------------------------------------------------------------
  ! @ private-mandatory (because symbol is used elsewhere)
  ! MRTCAL support routine for command
  !   MLIST /TOC
  ! Custom display routine (because there are custom types)
  !---------------------------------------------------------------------
  type(toc_descriptor_t),     intent(in)  :: key     !
  integer(kind=entry_length), intent(in)  :: ival    !
  character(len=*),           intent(out) :: output  !
  ! Local
  integer(kind=4) :: nc,i
  logical :: error
  !
  select case(key%ftype)
  case(toc_ftype_i4_1d) ! integer*4
    if (key%ptype.eq.mrtindex_ptype_teles) then
      output = telescopes(key%ptr%i4%data1(ival))
    elseif (key%ptype.eq.mrtindex_ptype_gagdate) then
      call gag_todate(key%ptr%i4%data1(ival),output,error)
    elseif (key%ptype.eq.mrtindex_ptype_backend) then
      output = backends_mrtcal(key%ptr%i4%data1(ival))
    elseif (key%ptype.eq.mrtindex_ptype_obstype) then
      output = obstypes_mrtcal(key%ptr%i4%data1(ival))
    elseif (key%ptype.eq.mrtindex_ptype_switchmode) then
      output = switchmodes_mrtcal(key%ptr%i4%data1(ival))
    elseif (key%ptype.eq.mrtindex_ptype_polarimetry) then
      output = polstatus(key%ptr%i4%data1(ival))
    elseif (key%ptype.eq.mrtindex_ptype_calstatus) then
      output = calstatus(key%ptr%i4%data1(ival))
    elseif (key%ptype.eq.mrtindex_ptype_directory) then
      output = ix_dirs(key%ptr%i4%data1(ival))
    else
      write(output,'(i12)') key%ptr%i4%data1(ival)
    endif
    !
  case(toc_ftype_i8_1d)  ! integer*8
    write(output,'(i12)') key%ptr%i8%data1(ival)
    !
  case(toc_ftype_r4_1d)  ! real*4
    write(output,'(f8.3)') key%ptr%r4%data1(ival)
    !
  case(toc_ftype_c8_1d)  ! string*8
    output = key%ptr%c8%data1(ival)
    !
  case(toc_ftype_c12_1d) ! string*12
    output = key%ptr%c12%data1(ival)
    !
  case(toc_ftype_c8_2d)  ! string*8 (2D)
    if (key%ptype.eq.mrtindex_ptype_frontend) then
      output = mrtindex_list_frontend(key%ptr%c8%data2(:,ival))
    else  ! Generic formatting (unclear)
      nc = 1
      do i=1,ubound(key%ptr%c8%data2,1)
        output(nc:) = key%ptr%c8%data2(i,ival)
        nc = len_trim(output)+2  ! Compact the names
      enddo
    endif
  end select
  !
end subroutine mrtindex_toc_format
