subroutine gr8_curve(nxy,x,y,z,var,per,bval,eval,error)
  use gildas_def
  use greg_interfaces, except_this=>gr8_curve
  use greg_kernel
  !---------------------------------------------------------------------
  ! @ public
  !	Connect a polyline with blanking value
  ! Arguments
  !	NXY	I		Number of data points		Input
  !	X	R*8 (*) 	Array of X coordinates		Input
  !	Y	R*8 (*) 	Array of Y coordinates		Input
  !	Z	R*8 (*) 	Array of Z coordinates		Input
  !	VAR	CHAR*(*)	Interpolation variable		Input
  !				'X', 'Y', 'Z',
  !				'NUMBERING',
  !				'POLYGONAL_LENGTH',
  !				'CURVILINEAR_LENGTH'
  !	PER	L*4		Periodic flag			Input
  !	BVAL	R*8 		Blanking value			Input
  !	EVAL	R*8		Tolerance on blanking value	Input
  !---------------------------------------------------------------------
  integer(kind=4)                 :: nxy    !
  real*8                          :: x(*)   !
  real*8                          :: y(*)   !
  real*8                          :: z(*)   !
  character(len=*)                :: var    !
  logical                         :: per    !
  real*8                          :: bval   !
  real*8                          :: eval   !
  logical,          intent(inout) :: error  ! Logical error flag
  ! Global
  external :: gdraw
  ! Local
  integer(kind=size_length) :: nxy_sl,is,ne,in
  !
  nxy_sl = nxy
  if (eval.lt.0.0) then
    if (nxy_sl.ge.2)  &
      call plcurv(nxy_sl,x,y,z,accurd,'CUBIC_SPLINE',var,per,grelocate,gdraw,  &
        error)
  else
    in = 1
    do while (in.ne.0)
      call find_blank8(y,bval,eval,nxy_sl,is,ne,in)
      if (ne.ge.2)  &
        call plcurv(ne,x(is),y(is),z(is),accurd,'CUBIC_SPLINE',var,per,  &
          grelocate,gdraw,error)
    enddo
  endif
end subroutine gr8_curve
!
subroutine gr4_curve(nxy,x,y,z,var,per,bval,eval,error)
  use gildas_def
  use greg_interfaces, except_this=>gr4_curve
  use greg_kernel
  !---------------------------------------------------------------------
  ! @ public
  !	Connect a polyline with blanking value
  ! Arguments
  !	NXY	I		Number of data points		Input
  !	X	R*4 (*) 	Array of X coordinates		Input
  !	Y	R*4 (*) 	Array of Y coordinates		Input
  !	Z	R*4 (*) 	Array of Z coordinates		Input
  !	VAR	CHAR*(*)	Interpolation variable		Input
  !				'X', 'Y', 'Z',
  !				'NUMBERING',
  !				'POLYGONAL_LENGTH',
  !				'CURVILINEAR_LENGTH'
  !	PER	L*4		Periodic flag			Input
  !	BVAL	R*4 		Blanking value			Input
  !	EVAL	R*4		Tolerance on blanking value	Input
  !---------------------------------------------------------------------
  integer(kind=4)                 :: nxy    !
  real*4                          :: x(1)   !
  real*4                          :: y(1)   !
  real*4                          :: z(1)   !
  character(len=*)                :: var    !
  logical                         :: per    !
  real*4                          :: bval   !
  real*4                          :: eval   !
  logical,          intent(inout) :: error  ! Logical error flag
  ! Global
  external :: gdraw
  ! Local
  integer(kind=size_length) :: nxy_sl,is,ne,in
  !
  nxy_sl = nxy
  if (eval.lt.0.0) then
    if (nxy_sl.ge.2)  &
      call plcurv4(nxy_sl,x,y,z,accurd,'CUBIC_SPLINE',var,per,grelocate,gdraw,  &
        error)
  else
    in = 1
    do while (in.ne.0)
      call find_blank4(y,bval,eval,nxy_sl,is,ne,in)
      if (ne.ge.2)  &
        call plcurv4(ne,x(is),y(is),z(is),accurd,'CUBIC_SPLINE',var,per,  &
          grelocate,gdraw,error)
    enddo
  endif
end subroutine gr4_curve
!
subroutine curve (line,error)
  use greg_dependencies_interfaces
  use greg_interfaces, except_this=>curve, &
                       no_interface=>find_blank8
  use gildas_def
  use sic_types
  use greg_kernel
  use greg_xyz
  use gbl_message
  use gbl_format
  !---------------------------------------------------------------------
  ! @ private
  ! GREG	Support routine for command
  ! 	CURVE [Array_X Array_Y]
  !	/ACCURACY [en cm]
  !		Fonctions:
  !	/VARIABLE X			Y=F(X)
  !	/VARIABLE Y			X=F(Y)
  !		Courbes parametriques:
  !	/VARIABLE Z [Array_Z]		Parametre: Z
  !	/VARIABLE NUMBERING		Parametre: Numero du point
  !	/VARIABLE POLYGONAL_LENGTH	(Analytique)
  !	/VARIABLE CURVILINEAR_LENGTH	(Iteratif, non analytique)
  !
  !	/PERIODIC
  !		Suppose que les points 1 et NXY sont separes par
  !		un nombre entier de periodes:
  !		/VARIABLE X	Suppose Y(1) = Y(NXY)
  !		/VARIABLE Y	Suppose X(1) = X(NXY)
  !		Courbe parametrique, suppose
  !				X(1) = X(NXY) et Y(1)=Y(NXY)
  !	/BLANKING [Bval [Eval]]
  !
  ! Arguments :
  !	LINE	C*(*)	Command line			Input/Output
  !---------------------------------------------------------------------
  character(len=*)                :: line   !
  logical,          intent(inout) :: error  ! Logical error flag
  ! Global
  external :: gdraw
  include 'gbl_memory.inc'
  ! Local
  character(len=*), parameter :: rname='CURVE'
  logical :: periodic
  character(len=24) :: variable,buffer
  character(len=16) :: algorithm
  real :: accuracy
  real*8 :: bval,eval
  integer :: ialgos,ivar,narg,nc,form
  integer(kind=size_length) :: ixy,is,ne,in
  integer(kind=address_length) :: xaddr,yaddr,zaddr
  type(sic_descriptor_t) :: xinca,yinca,zinca
  !
  save xinca,yinca,zinca
  !
  ! Algorithmes disponibles
  integer, parameter :: nalgos=2
  character(len=16) :: algos(nalgos)
  !
  ! Variables disponibles
  integer, parameter :: nvar=6
  character(len=24) :: var(nvar)
  ! Data
  data var /             &
    'X','Y','Z',         &
    'NUMBERING',         &
    'POLYGONAL_LENGTH',  &
    'CURVILINEAR_LENGTH' /
  data algos /'CUBIC_SPLINE','SMOOTHING_SPLINE'/
  ! Code
  !
  ! Algorithm
  ialgos=1
  algorithm=algos(1)
  !
  ! Decode l'option ACCURACY avec la valeur par defaut ACCURD
  if (sic_present(1,1)) then
    call sic_r4 (line,1,1,accuracy,.false.,error)
    if (error) return
    if (sic_present(1,2)) goto 199
    if (accuracy.le.0. .or. accuracy.gt.10.) then
      call greg_message(seve%w,rname,'ACCURACY out of range, using default')
      accuracy=accurd
    endif
  else
    accuracy=accurd
  endif
  !
  ! Decode l'option /VARIABLE avec la valeur par defaut X
  if (sic_present(2,1)) then
    call sic_ke (line,2,1,buffer,nc,.false.,error)
    if (error) return
    call sic_ambigs ('CURVE',buffer,variable,ivar,var,nvar,error)
    if (error) return
    if (sic_present(2,2).and.ivar.ne.3) goto 199
  else
    ivar=1
    variable='X'
  endif
  !
  ! Decode l'option /PERIODIC
  if (sic_present(3,0)) then
    periodic=.true.
    if (sic_present(3,1)) goto 199
  else
    periodic=.false.
  endif
  !
  ! /BLANKING ?
  bval = cblank
  call sic_r8 (line,4,1,bval,.false.,error)
  if (error) return
  eval = eblank
  call sic_r8 (line,4,2,eval,.false.,error)
  if (error) return
  if (sic_present(4,3)) goto 199
  !
  ! Check on which variable
  form = fmt_r8
  narg = sic_narg(0)
  if (narg.eq.2 .or. narg.eq.0) then
    call get_incarnation('CURVE',line,form,ixy,xinca,yinca,error)
    if (error) return
  else
    call greg_message(seve%e,rname,'Two arguments or none')
    error = .true.
    return
  endif
  xaddr = gag_pointer(xinca%addr,memory)
  yaddr = gag_pointer(yinca%addr,memory)
  !
  ! Get Z if required
  if (ivar.eq.3) then
    if (sic_present(2,2)) then
      call get_same_inca ('CURVE',line,2,2,form,ixy,zinca,error)
    else
      call greg_message(seve%w,rname,'Using Z array')
      call get_greg_inca ('CURVE','Z',form,ixy,zinca,error)
    endif
    if (error) then
      call sic_volatile(xinca)
      call sic_volatile(yinca)
      return
    endif
    zaddr = gag_pointer(zinca%addr,memory)
  endif
  !
  ! On est enfin prets pour travailler
  if (eval.lt.0.0d0) then
    if (ixy.ge.2)  &
      call plcurv(ixy,memory(xaddr),memory(yaddr),memory(zaddr),accuracy,  &
      algorithm,variable,periodic,grelocate,gdraw,error)
  else
    in = 1
    do while (in.ne.0)
      call find_blank8(memory(yaddr),bval,eval,ixy,is,ne,in)
      if (ne.ge.2)  &
        call plcurv(ne,memory(xaddr+2*(is-1)),memory(yaddr+2*(is-1)),  &
          memory(zaddr+2*(is-1)),accuracy,algorithm,variable,periodic,   &
          grelocate,gdraw,error)
    enddo
  endif
  call sic_volatile(xinca)
  call sic_volatile(yinca)
  if (ivar.eq.3) call sic_volatile(zinca)
  return
  !
199 call greg_message(seve%e,rname,'Too many parameters for Command or '//  &
      'Option')
  error=.true.
  return
end subroutine curve
!
subroutine get_same_inca (command,line,iopt,iarg,form,ixy,xinca,error)
  use greg_dependencies_interfaces
  use greg_interfaces, except_this=>get_same_inca
  use gildas_def
  use sic_types
  use gbl_message
  use gbl_format
  !---------------------------------------------------------------------
  ! @ private
  ! GreG  Internal routine
  !  Get incarnation of variables in command line
  !---------------------------------------------------------------------
  character(len=*),          intent(in)    :: command  !
  character(len=*),          intent(in)    :: line     !
  integer(kind=4),           intent(in)    :: iopt     !
  integer(kind=4),           intent(in)    :: iarg     !
  integer(kind=4),           intent(in)    :: form     !
  integer(kind=size_length), intent(inout) :: ixy      !
  type(sic_descriptor_t),    intent(out)   :: xinca    !
  logical,                   intent(inout) :: error    !
  ! Local
  character(len=varname_length) :: var
  type(sic_descriptor_t) :: xdesc
  integer(kind=4) :: nc
  logical :: found
  !
  call sic_ke (line,iopt,iarg,var,nc,.true.,error)
  if (error) return
  found = .true.
  call sic_materialize(var,xdesc,found)
  if (.not.found) then
    call greg_message(seve%e,command,'Unknown variable '//var)
    error = .true.
    return
  endif
  call sic_incarnate(form,xdesc,xinca,error)
  if (error) then
    call sic_volatile(xdesc)   ! It may have been transposed...
    return
  endif
  !
  if (ixy.eq.0) then
    ! First call in current command
    ixy = desc_nelem(xinca)
  elseif (ixy.ne.desc_nelem(xinca)) then
    ! Subsequent calls in current command: consistency check
    call greg_message(seve%w,command,'Arrays have different sizes')
    ixy = min(desc_nelem(xinca),ixy)
  endif
  !
  if (sic_notsamedesc(xdesc,xinca)) call sic_volatile(xdesc)
end subroutine get_same_inca
!
subroutine get_greg_inca (command,name,form,ixy,xinca,error)
  use greg_dependencies_interfaces
  use greg_interfaces, except_this=>get_greg_inca
  use gildas_def
  use sic_types
  use gbl_message
  use gbl_format
  !---------------------------------------------------------------------
  ! @ private
  ! Get incarnation of GREG X Y or Z variable. Note that the code does
  ! not distinguish the program-defined variables (by e.g. COLUMN) from
  ! user-defined ones.
  !---------------------------------------------------------------------
  character(len=*),          intent(in)    :: command  ! Command name (feedback)
  character(len=*),          intent(in)    :: name     ! Variable name
  integer(kind=4),           intent(in)    :: form     ! Desired incarnation type
  integer(kind=size_length), intent(inout) :: ixy      ! Number of elements
  type(sic_descriptor_t),    intent(out)   :: xinca    ! Incarnation descriptor
  logical,                   intent(inout) :: error    ! Logical error flag
  ! Local
  type(sic_descriptor_t) :: xdesc
  logical :: found
  character(len=varname_length) :: var
  !
  var = name
  found = .true.
  call sic_materialize(var,xdesc,found)
  if (.not.found) then
    call greg_message(seve%e,command,'Unknown variable '//var)
    error = .true.
    return
  endif
  call sic_incarnate(form,xdesc,xinca,error)
  if (error) then
    call sic_volatile(xdesc)   ! It may have been transposed...
    return
  endif
  !
  if (ixy.eq.0) then
    ! First call in current command
    ixy = desc_nelem(xinca)
  elseif (ixy.ne.desc_nelem(xinca)) then
    ! Subsequent calls in current command: consistency check
    call greg_message(seve%w,command,'Arrays have different sizes')
    ixy = min(desc_nelem(xinca),ixy)
  endif
  !
  if (sic_notsamedesc(xdesc,xinca)) call sic_volatile(xdesc)
end subroutine get_greg_inca
