module gtv_metacode
  !---------------------------------------------------------------------
  ! Support module for command METACODE
  !---------------------------------------------------------------------
  !
  ! Versions
  integer, parameter :: signature_length=15
  character(len=signature_length), parameter :: signature='GTVIRT-Metacode'
  ! integer(kind=4), parameter :: current=20101217  ! 17-dec-2010
  ! integer(kind=4), parameter :: current=20110615  ! 15-jun-2011
  ! integer(kind=4), parameter :: current=20130911  ! 11-sep-2013
  integer(kind=4), parameter :: current=20160908    ! Segment color identifiers changed
  !
  ! Markers
  integer(kind=4), parameter :: seg_sos = -101  ! Start-of-segment
  integer(kind=4), parameter :: seg_sod = -102  ! Start-of-directory
  integer(kind=4), parameter :: seg_eos = -201  ! End-of-segment
  integer(kind=4), parameter :: seg_eod = -202  ! End-of-directory
  !
end module gtv_metacode
!
subroutine gtl_metacode(line,error)
  use gtv_dependencies_interfaces
  use gtv_interfaces, except_this=>gtl_metacode
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !   Support for command METACODE [IMPORT|EXPORT] [...]
  !
  ! Load or save in an binary file a sub-tree of the metacode.
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Input command line
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='METACODE'
  integer :: nc,ncom
  integer, parameter :: nvocab=2
  character(len=12) :: vocab(nvocab),to_check,comm
  ! Data
  data vocab /'EXPORT','IMPORT'/
  !
  call sic_ke(line,0,1,to_check,nc,.true.,error)
  if (error) return
  call sic_ambigs(rname,to_check,comm,ncom,vocab,nvocab,error)
  if (error)  return
  !
  if (comm.eq.'EXPORT') then
    call meta_export(line,error)
    !
  elseif (comm.eq.'IMPORT') then
    call meta_import(line,error)
    call gtview('Update')
    !
  else
    call gtv_message(seve%e,rname,'Internal programming error')
    error = .true.
    return
  endif
  !
end subroutine gtl_metacode
!
subroutine meta_export(line,error)
  use gildas_def
  use gbl_message
  use gtv_buffers
  use gtv_dependencies_interfaces
  use gtv_interfaces, except_this=>meta_export
  use gtv_metacode
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !   Support for command METACODE EXPORT File [Dir]
  !
  ! Permet de sauver dans un fichier binaire une sous arborescence du
  ! metacode.
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Input command line
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META EXPORT'
  character(len=filename_length) :: argum,filename
  character(len=gtvpath_length) :: rep_name  ! Nom du repertoire a sauver
  logical :: isdir,found
  integer :: nc,lun,ier
  type(gt_directory), pointer :: dir
  type(gt_segment), pointer :: segm
  !
  ! No option allowed METACODE EXPORT command
  if (sic_present(1,1)) then
    call gtv_message(seve%e,rname,'No option allowed with EXPORT keyword')
    error = .true.
    return
  endif
  !
  ! Flush the current segment into the metacode
  call gtsegm_flush(error)
  if (error)  return
  !
  ! Recuperation du nom du fichier
  call sic_ch(line,0,2,argum,nc,.true.,error)
  if (error) return
  filename = argum
  call sic_parsef(argum,filename,' ','.meta')
  !
  ! Recuperation du nom du directory
  if (sic_present(0,3)) then
    call sic_ch(line,0,3,rep_name,nc,.true.,error)
    if (error) return
    call sic_upper(rep_name)
    !
    call decode_chemin(rep_name,cw_directory,dir,isdir,segm,found)
    if (.not.found) then
      call gtv_message(seve%e,rname,  &
        'Directory '''//trim(rep_name)//''' does not exists')
      error = .true.
      return
    elseif (.not.isdir) then
      call gtv_message(seve%e,rname,trim(rep_name)//  &
        ''' is not a directory')
      error = .true.
      return
    endif
  else
    ! Save Current Working Directory
    dir => cw_directory
  endif
  call cree_chemin_dir(dir,rep_name,nc)
  !
  if (.not.dir%gen%visible) then
    call gtv_message(seve%e,rname,  &
      'Directory '''//trim(rep_name)//''' is not visible')
    error = .true.
    return
  endif
  !
  ! Get a unit for the output file
  ier = sic_getlun(lun)
  if (ier.ne.1) then
    error = .true.
    return
  endif
  !
  ! Open the output file
  if (gag_inquire(filename,len_trim(filename)).eq.0)  &
    call gag_delete(filename)
  !
  open(unit=lun, file=filename, status='NEW', form='UNFORMATTED',  &
       access='SEQUENTIAL', iostat=ier)
  if (ier.ne.0) then
    call gtv_message(seve%e,rname,'Open error on output file '//filename)
    error = .true.
    goto 100
  endif
  !
  ! Process
  write(unit=lun,iostat=ier)  signature  ! File signature
  write(unit=lun,iostat=ier)  current    ! Current version
  if (ier.ne.0) then
    call gtv_message(seve%e,rname,'Write error 1')
    error = .true.
    goto 100
  endif
  !
  call meta_export_dir(dir,lun,error)
  if (error)  goto 100
  !
  call gtv_message(seve%i,rname,  &
    'Directory '//trim(rep_name)//' exported to file '//filename)
  !
100 continue
  !
  ! Close the file
  close(unit=lun)
  call sic_frelun(lun)
  !
end subroutine meta_export
!
recursive subroutine meta_export_dir(dir,lun,error)
  use gtv_interfaces, except_this=>meta_export_dir
  use gbl_message
  use gtv_metacode
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !
  !---------------------------------------------------------------------
  type(gt_directory), intent(in)    :: dir    ! Directory to dump
  integer(kind=4),    intent(in)    :: lun    ! Logical unit
  logical,            intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META EXPORT'
  integer :: ier
  type(gt_segment), pointer :: segm
  type(gt_directory), pointer :: child
  !
  ! Mark the start-of-directory
  write(unit=lun,iostat=ier)  seg_sod
  if (ier.ne.0)  goto 100
  !
  write(unit=lun,iostat=ier)  dir%gen%name
  ! Do not save minmax, we will recompute it dynamically
  write(unit=lun,iostat=ier)  dir%phys_size
  write(unit=lun,iostat=ier)  dir%val_greg
  if (ier.ne.0)  goto 100
  !
  ! Dump all the segments in this directory
  segm => dir%leaf_first
  do while (associated(segm))
    call meta_export_seg(segm,lun,error)
    if (error)  return
    !
    ! Next segment
    segm => segm%nextseg
  enddo
  !
  ! Dump all the directories in this directory
  child => dir%son_first
  do while (associated(child))
    call meta_export_dir(child,lun,error)
    if (error)  return
    !
    ! Next directory
    child => child%brother
  enddo
  !
  ! Mark the end-of-directory
  write(unit=lun,iostat=ier)  seg_eod
  if (ier.ne.0)  goto 100
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Write error 2')
  error = .true.
  return
end subroutine meta_export_dir
!
subroutine meta_export_seg(segm,lun,error)
  use gtv_interfaces, except_this=>meta_export_seg
  use gbl_message
  use gtv_metacode
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !
  !---------------------------------------------------------------------
  type(gt_segment), intent(in)    :: segm   ! Segment to dump
  integer(kind=4),  intent(in)    :: lun    ! Logical unit
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META EXPORT'
  integer :: ier,icol
  character(len=segname_length) :: name
  type(gt_segment_data), pointer :: segdata
  !
  ! Mark the start-of-segment
  write(unit=lun,iostat=ier)  seg_sos
  if (ier.ne.0)  goto 100
  !
  icol = index(segm%head%gen%name,':')
  if (icol.gt.0) then
    name = segm%head%gen%name(1:icol-1)
  else
    name = segm%head%gen%name
  endif
  write(unit=lun,iostat=ier)  name
  write(unit=lun,iostat=ier)  segm%head%gen%minmax
  write(unit=lun,iostat=ier)  segm%head%attr
  if (ier.ne.0)  goto 100
  !
  ! Export segment data
  segdata => segm%data
  do while (associated(segdata))
    call meta_export_segdata(segdata,lun,error)
    if (error)  return
    !
    segdata => segdata%nextdata
  enddo
  !
  ! Mark the end-of-segment
  write(unit=lun,iostat=ier)  seg_eos
  if (ier.ne.0)  goto 100
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Write error 3')
  error = .true.
  return
  !
end subroutine meta_export_seg
!
subroutine meta_export_segdata(segdata,lun,error)
  use gtv_interfaces, except_this=>meta_export_segdata
  use gbl_message
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !
  !---------------------------------------------------------------------
  type(gt_segment_data), intent(in)    :: segdata  ! Segment data to dump
  integer(kind=4),       intent(in)    :: lun      ! Logical unit
  logical,               intent(inout) :: error    ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META EXPORT'
  !
  select case (segdata%kind)
  case (seg_points)
    call meta_export_polyline(segdata,lun,error)
  case (seg_poly)
    call meta_export_polyline(segdata,lun,error)
  case (seg_hfpoly)
    call meta_export_polyline(segdata,lun,error)
  case (seg_vfpoly)
    call meta_export_polyline(segdata,lun,error)
  case (seg_image)
    call meta_export_image(segdata%image,lun,error)
  case (seg_lutcol)
    call meta_export_lut(segdata,lun,error)
  case (seg_pencol)
    call meta_export_lut(segdata,lun,error)
  case default
    call gtv_message(seve%w,rname,'Unsupported kind of data skipped')
    return
  end select
  if (error)  return
  !
end subroutine meta_export_segdata
!
subroutine meta_export_polyline(segdata,lun,error)
  use gtv_interfaces, except_this=>meta_export_polyline
  use gbl_message
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !
  !---------------------------------------------------------------------
  type(gt_segment_data), intent(in)    :: segdata  ! Segment data to dump
  integer(kind=4),       intent(in)    :: lun      ! Logical unit
  logical,               intent(inout) :: error    ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META EXPORT'
  integer :: ier
  !
  write(unit=lun,iostat=ier)  segdata%kind
  write(unit=lun,iostat=ier)  segdata%poly%n
  write(unit=lun,iostat=ier)  segdata%poly%x(1:segdata%poly%n)
  write(unit=lun,iostat=ier)  segdata%poly%y(1:segdata%poly%n)
  if (ier.ne.0)  goto 100
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Write error 4')
  error = .true.
  return
  !
end subroutine meta_export_polyline
!
subroutine meta_export_image(segima,lun,error)
  use gtv_interfaces, except_this=>meta_export_image
  use gbl_message
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !
  !---------------------------------------------------------------------
  type(gt_image),  intent(in)    :: segima  ! Image data to dump
  integer(kind=4), intent(in)    :: lun     ! Logical unit
  logical,         intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META EXPORT'
  integer :: ier
  integer(kind=8) :: taille(2)
  !
  if (segima%isrgb) then
    call gtv_message(seve%w,rname,'Exporting RGB images is not yet supported. Ignored')
    return
  endif
  !
  ! Descriptor
  write(unit=lun,iostat=ier)  seg_image
  write(unit=lun,iostat=ier)  segima%r%blank
  write(unit=lun,iostat=ier)  segima%scaling
  write(unit=lun,iostat=ier)  segima%r%cuts
  write(unit=lun,iostat=ier)  segima%r%extrema
  write(unit=lun,iostat=ier)  segima%conv
  write(unit=lun,iostat=ier)  segima%limits
  write(unit=lun,iostat=ier)  segima%position
  if (ier.ne.0)  goto 100
  ! Data
  taille(:) = segima%r%taille(:)
  write(unit=lun,iostat=ier)  taille
  write(unit=lun,iostat=ier)  segima%r%values
  if (ier.ne.0)  goto 100
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Write error 5')
  error = .true.
  return
  !
end subroutine meta_export_image
!
subroutine meta_export_lut(segdata,lun,error)
  use gtv_interfaces, except_this=>meta_export_lut
  use gbl_message
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !
  !---------------------------------------------------------------------
  type(gt_segment_data), intent(in)    :: segdata  ! Segment data to dump
  integer(kind=4),       intent(in)    :: lun      ! Logical unit
  logical,               intent(inout) :: error    ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META EXPORT'
  integer :: ier
  !
  write(unit=lun,iostat=ier)  segdata%kind
  write(unit=lun,iostat=ier)  segdata%lut%size
  write(unit=lun,iostat=ier)  segdata%lut%r
  write(unit=lun,iostat=ier)  segdata%lut%g
  write(unit=lun,iostat=ier)  segdata%lut%b
  if (ier.ne.0)  goto 100
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Write error 6')
  error = .true.
  return
  !
end subroutine meta_export_lut
!
subroutine meta_import(line,error)
  use gildas_def
  use gbl_message
  use gtv_buffers
  use gtv_dependencies_interfaces
  use gtv_interfaces, except_this=>meta_import
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command
  !   METACODE IMPORT File [DirName] [/PATH LoadPath]
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Input command line
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META IMPORT'
  character(len=filename_length) :: filename,argum
  character(len=gtvpath_length) :: path
  integer :: lun,nc,ier
  type(gt_directory), pointer :: parent
  type(gt_segment), pointer :: segm
  logical :: isdir,found
  !
  ! Recuperation du nom de fichier
  call sic_ch(line,0,2,argum,nc,.true.,error)
  if (error) return
  call sic_parsef(argum,filename,' ','.meta')
  !
  if (gag_inquire(filename,len_trim(filename)).ne.0) then
    call gtv_message(seve%e,rname,'No such file '//filename)
    error = .true.
    return
  endif
  !
  ! Get a unit for the output file
  ier = sic_getlun(lun)
  if (ier.ne.1) then
    error = .true.
    return
  endif
  !
  ! Open the output file
  open(unit=lun, file=filename, status='OLD', form='UNFORMATTED',  &
         access='SEQUENTIAL', iostat=ier)
  if (ier.ne.0) then
    call gtv_message(seve%e,rname,'Open error on output file '//filename)
    error = .true.
    goto 100
  endif
  !
  ! Get the host directory
  if (sic_present(1,0)) then
    call sic_ch(line,1,1,path,nc,.true.,error)
    if (error) goto 100
    call sic_upper(path)
    call decode_chemin(path,cw_directory,parent,isdir,segm,found)
    if (.not.found) then
      call gtv_message(seve%e,rname,'No such directory '//path)
      error = .true.
      goto 100
    endif
    if (.not.isdir) then
      call gtv_message(seve%e,rname,  &
        trim(path)//' is a segment (must be a directory)')
      error = .true.
      goto 100
    endif
  else
    parent => cw_directory
  endif
  !
  ! Process
  call meta_import_load(parent,lun,error)
  if (error)  goto 100
  !
!   ! Recuperons le nom du repertoire devant contenir l'arborescence
!   dirname = argum
!   call sic_ch(line,0,3,dirname,nc,.false.,error)
!   if (error) return
!   call sic_upper(dirname)
  !
  call gtv_message(seve%i,rname,'Metacode imported from file '//filename)
  !
100 continue
  !
  ! Close the file
  close(unit=lun)
  call sic_frelun(lun)
  !
end subroutine meta_import
!
subroutine meta_import_load(parent,lun,error)
  use gbl_message
  use gtv_interfaces, except_this=>meta_import_load
  use gtv_metacode
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(gt_directory), pointer       :: parent  ! Directory to be filled
  integer(kind=4),    intent(in)    :: lun     ! Logical unit opened on the file
  logical,            intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META IMPORT'
  integer :: ier,marker,version
  character(len=message_length) :: mess
  character(len=signature_length) :: sig
  !
  ! Get signature
  read(unit=lun,iostat=ier) sig
  if (ier.ne.0)  goto 100
  if (sig.ne.signature) then
    call gtv_message(seve%e,rname,'File does not seem to be a GTVIRT metacode')
    error = .true.
    return
  endif
  !
  ! Get version
  read(unit=lun,iostat=ier) version
  if (ier.ne.0)  goto 100
  if (version.ne.current) then
    write(mess,'(A,I0,A)')  &
      'Unknown version of the GTVIRT metacode (',version,')'
    call gtv_message(seve%e,rname,mess)
    error = .true.
    return
  endif
  !
  ! Read first marker. Should be start-of-directory
  read(unit=lun,iostat=ier) marker
  if (ier.ne.0)  goto 100
  !
  if (marker.ne.seg_sod) then
    call gtv_message(seve%e,rname,'Unexpected marker 1')
    error = .true.
    return
  endif
  !
  call meta_import_dir(parent,lun,error)
  if (error)  return
  !
  ! Recompute all the minmax
  call gtv_limits(parent,error)
  if (error)  return
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Read error 1')
  error = .true.
  return
  !
end subroutine meta_import_load
!
recursive subroutine meta_import_dir(parent,lun,error)
  use gbl_message
  use gtv_buffers
  use gtv_metacode
  use gtv_interfaces, except_this=>meta_import_dir
  use gtv_protocol
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(gt_directory), pointer       :: parent  ! Parent directory
  integer(kind=4),    intent(in)    :: lun     ! Logical unit opened on the file
  logical,            intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META IMPORT'
  type(gt_directory), pointer :: newdir
  character(len=segname_length) :: name
  integer :: ier,marker
  real(kind=4) :: phys_size(2)
  logical :: istop
  type(x_output) :: xdisplay
  !
  read(unit=lun,iostat=ier) name
  read(unit=lun,iostat=ier) phys_size
  if (ier.ne.0)  goto 100
  !
  istop = associated(parent,root) ! Host directory is root, i.e. we create a top directory
  if (.not.istop) then
    ! No choice, only top directories can have a custom physical size.
    ! Subdirectories inherit the physical size of their parent.
    if (any(phys_size.ne.parent%phys_size)) then
      call gtv_message(seve%w,rname,'Host and imported directories have different physical size')
      call gtv_message(seve%w,rname,'Plot may be truncated')
    endif
    phys_size = parent%phys_size
  endif
  !
  ! Create the directory
  call gtsegm_dir(name,parent,phys_size(1),phys_size(2),error)
  if (error)  return
  newdir => parent%son_last
  !
  ! Set the remaining attributes
  newdir%gen%visible = .true.  ! Always visible
  read(unit=lun,iostat=ier) newdir%val_greg
  if (ier.ne.0)  goto 100
  !
  ! Create a window if top directory
  if (istop .and. cw_device%protocol.eq.p_x) then
    call x_display_reset(xdisplay)  ! Default values
    call gtv_mkdir_topwindow(newdir,xdisplay,error)
    if (error)  return
  endif
  !
  ! Read next marker
  do
    read(unit=lun,iostat=ier)  marker
    if (ier.ne.0)  goto 100
    !
    if (marker.eq.seg_sos) then
      call meta_import_seg(newdir,lun,error)
    elseif (marker.eq.seg_sod) then
      call meta_import_dir(newdir,lun,error)
    elseif (marker.eq.seg_eod) then
      return
    else
      goto 101
    endif
    if (error)  return
    !
  enddo
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Read error 2')
  error = .true.
  return
  !
101 continue
  call gtv_message(seve%e,rname,'Unexpected marker 2')
  error = .true.
  return
  !
end subroutine meta_import_dir
!
subroutine meta_import_seg(parent,lun,error)
  use gbl_message
  use gtv_interfaces, except_this=>meta_import_seg
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(gt_directory), pointer       :: parent  ! Parent directory
  integer(kind=4),    intent(in)    :: lun     ! Logical unit opened on the file
  logical,            intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META IMPORT'
  character(len=segname_length) :: name
  type(gt_segment), pointer :: newseg
  integer :: ier
  !
  ! Read the new segment name
  read(unit=lun,iostat=ier) name
  !
  ! Create it in the metacode
  call gtsegm_create(name,parent,error)
  if (error)  return
  !
  newseg => parent%leaf_last
  read(unit=lun,iostat=ier) newseg%head%gen%minmax
  read(unit=lun,iostat=ier) newseg%head%attr
  if (ier.ne.0)  goto 100
  newseg%head%gen%visible = .true.  ! Always visible
  !
  ! Read the segment data
  call meta_import_segdata(newseg%data,lun,error)
  if (error) return
  !
  ! Close the segment
  call gtsegm_close(error)
  if (error)  return
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Read error 3')
  error = .true.
  return
  !
end subroutine meta_import_seg
!
recursive subroutine meta_import_segdata(new,lun,error)
  use gbl_message
  use gtv_interfaces, except_this=>meta_import_segdata
  use gtv_metacode
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(gt_segment_data), pointer       :: new     ! New data segment to be filled
  integer(kind=4),       intent(in)    :: lun     ! Logical unit opened on the file
  logical,               intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META IMPORT'
  integer :: ier,kind
  !
  read(unit=lun,iostat=ier) kind
  if (ier.ne.0)  goto 100
  !
  select case (kind)
  case (seg_eos)
    return
  case (seg_points)
    call meta_import_polyline(new,kind,lun,error)
  case (seg_poly)
    call meta_import_polyline(new,kind,lun,error)
  case (seg_hfpoly)
    call meta_import_polyline(new,kind,lun,error)
  case (seg_vfpoly)
    call meta_import_polyline(new,kind,lun,error)
  case (seg_image)
    call meta_import_image(lun,error)
  case (seg_lutcol)
    call meta_import_lut(new,kind,lun,error)
  case (seg_pencol)
    call meta_import_lut(new,kind,lun,error)
  case default
    call gtv_message(seve%e,rname,'Unknown kind of data')
    error = .true.
  end select
  if (error)  return
  !
  ! Read next piece of data
  call meta_import_segdata(new%nextdata,lun,error)
  if (error)  return
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Read error 4')
  error = .true.
  return
  !
end subroutine meta_import_segdata
!
subroutine meta_import_polyline(new,kind,lun,error)
  use gtv_interfaces, except_this=>meta_import_polyline
  use gbl_message
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(gt_segment_data), pointer       :: new     ! New data segment to be filled
  integer(kind=4),       intent(in)    :: kind    ! Kind of polyline
  integer(kind=4),       intent(in)    :: lun     ! Logical unit opened on the file
  logical,               intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META IMPORT'
  integer :: ier,n
  !
  ! General section
  read(unit=lun,iostat=ier) n
  if (ier.ne.0)  goto 100
  !
  allocate(new,stat=ier)
  if (ier.ne.0)  goto 101
  allocate(new%poly%x(n),new%poly%y(n),stat=ier)
  if (ier.ne.0)  goto 101
  !
  new%kind = kind
  new%poly%n = n
  new%image => null()
  ! new%lut = ?
  new%nextdata => null()
  !
  read(unit=lun,iostat=ier) new%poly%x
  read(unit=lun,iostat=ier) new%poly%y
  if (ier.ne.0)  goto 100
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Read error 5')
  error = .true.
  return
  !
101 continue
  call gtv_message(seve%e,rname,'Allocation error 1')
  error = .true.
  return
  !
end subroutine meta_import_polyline
!
subroutine meta_import_image(lun,error)
  use gtv_interfaces, except_this=>meta_import_image
  use gbl_message
  use gtv_bitmap
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: lun    ! Logical unit opened on the file
  logical,         intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META IMPORT'
  integer(kind=4) :: ier,scaling
  integer(kind=8) :: taille(2)
  integer(kind=index_length) :: taille_il(2)
  real(kind=4) :: cuts(2),extrema(2),conv(6),limits(4),position(4),blank(3)
  logical :: is_visible,is_curima
  real(kind=4), allocatable :: data(:,:)
  !
  ! Descriptor
  read(unit=lun,iostat=ier)  blank
  read(unit=lun,iostat=ier)  scaling
  read(unit=lun,iostat=ier)  cuts
  read(unit=lun,iostat=ier)  extrema
  read(unit=lun,iostat=ier)  conv
  read(unit=lun,iostat=ier)  limits
  read(unit=lun,iostat=ier)  position
  if (ier.ne.0)  goto 100
  !
  ! Data
  read(unit=lun,iostat=ier)  taille  ! Always read 2*8 bytes
  if (ier.ne.0)  goto 100
  taille_il(:) = taille(:)
  !
  allocate(data(taille_il(1),taille_il(2)),stat=ier)
  if (ier.ne.0)  goto 101
  read(unit=lun,iostat=ier)  data
  if (ier.ne.0)  goto 100
  !
  ! Create the image slot in GTVIRT
  is_visible = .true.
  is_curima = .false.
  call gtv_image(taille_il(1),taille_il(2),data,position,limits,conv,scaling,  &
    cuts,extrema,blank,is_visible,is_curima,error)
  deallocate(data)
  if (error)  &
    call gtv_message(seve%e,rname,'Error creating the image slot')
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Read error 6')
  error = .true.
  return
  !
101 continue
  call gtv_message(seve%e,rname,'Allocation error 2')
  error = .true.
  return
  !
end subroutine meta_import_image
!
subroutine meta_import_lut(new,kind,lun,error)
  use gtv_dependencies_interfaces
  use gtv_interfaces, except_this=>meta_import_lut
  use gbl_message
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(gt_segment_data), pointer       :: new     ! New data segment to be filled
  integer(kind=4),       intent(in)    :: kind    ! Kind of polyline
  integer(kind=4),       intent(in)    :: lun     ! Logical unit opened on the file
  logical,               intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='META IMPORT'
  integer :: ier,size,icol
  !
  ! General section
  read(unit=lun,iostat=ier) size
  if (ier.ne.0)  goto 100
  !
  allocate(new,stat=ier)
  if (ier.ne.0)  goto 101
  allocate(new%lut%r(size),new%lut%g(size),new%lut%b(size),stat=ier)
  if (ier.ne.0)  goto 101
  !
  new%kind = kind
  new%lut%size = size
  new%image => null()
  new%nextdata => null()
  !
  read(unit=lun,iostat=ier) new%lut%r
  read(unit=lun,iostat=ier) new%lut%g
  read(unit=lun,iostat=ier) new%lut%b
  if (ier.ne.0)  goto 100
  !
  ! Fill the HSV arrays:
  allocate(new%lut%hue(size),new%lut%sat(size),new%lut%val(size),stat=ier)
  if (ier.ne.0)  goto 101
  do icol=1,size
    call rgb_to_hsv(new%lut%r(icol),new%lut%g(icol),new%lut%b(icol),  &
                    new%lut%hue(icol),new%lut%sat(icol),new%lut%val(icol))
  enddo
  !
  return
  !
100 continue
  call gtv_message(seve%e,rname,'Read error 7')
  error = .true.
  return
  !
101 continue
  call gtv_message(seve%e,rname,'Allocation error 3')
  error = .true.
  return
  !
end subroutine meta_import_lut
