subroutine greg_arrow(line,error)
  use sic_types
  use greg_dependencies_interfaces
  use greg_interfaces, except_this=>greg_arrow
  !---------------------------------------------------------------------
  ! @ private
  ! Support file for command
  !   G\ARROW Xref Yref Length Angle [Reference]
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line
  logical,          intent(inout) :: error
  ! Local
  type(sic_descriptor_t) :: xdesc,ydesc,ldesc,adesc
  real(kind=4) :: reference
  !
  ! Retrieve descriptors of arguments (can be explicit scalar value,
  ! scalar variable name, vector variable name).
  call sic_de(line,0,1,xdesc,.true.,error)
  if (error)  goto 10
  call sic_de(line,0,2,ydesc,.true.,error)
  if (error)  goto 10
  call sic_de(line,0,3,ldesc,.true.,error)
  if (error)  goto 10
  call sic_de(line,0,4,adesc,.true.,error)
  if (error)  goto 10
  !
  ! Reference point definition
  reference = 0.5
  call sic_r4(line,0,5,reference,.false.,error)
  if (error)  goto 10
  !
  call greg_arrow_desc(xdesc,ydesc,ldesc,adesc,reference,error)
  if (error)  goto 10
  !
10 continue
  call sic_volatile(xdesc)
  call sic_volatile(ydesc)
  call sic_volatile(ldesc)
  call sic_volatile(adesc)
  !
end subroutine greg_arrow
!
subroutine greg_arrow_desc(xdesc,ydesc,ldesc,adesc,reference,error)
  use sic_types
  use greg_dependencies_interfaces
  use greg_interfaces, except_this=>greg_arrow_desc
  !---------------------------------------------------------------------
  ! @ private
  ! Incarnate the arguments as R*4
  !---------------------------------------------------------------------
  type(sic_descriptor_t), intent(in)    :: xdesc
  type(sic_descriptor_t), intent(in)    :: ydesc
  type(sic_descriptor_t), intent(in)    :: ldesc
  type(sic_descriptor_t), intent(in)    :: adesc
  real(kind=4),           intent(in)    :: reference
  logical,                intent(inout) :: error
  ! Local
  type(sic_descriptor_t) :: xinca,yinca,linca,ainca
  !
  ! Incarnate all arguments as R*4
  call sic_incarnate(fmt_r4,xdesc,xinca,error)
  if (error)  goto 20
  call sic_incarnate(fmt_r4,ydesc,yinca,error)
  if (error)  goto 20
  call sic_incarnate(fmt_r4,ldesc,linca,error)
  if (error)  goto 20
  call sic_incarnate(fmt_r4,adesc,ainca,error)
  if (error)  goto 20
  !
  call greg_arrow_do(xinca,yinca,linca,ainca,reference,error)
  if (error)  goto 20
  !
20 continue
  call sic_volatile(xinca)
  call sic_volatile(yinca)
  call sic_volatile(linca)
  call sic_volatile(ainca)
  !
end subroutine greg_arrow_desc
!
subroutine greg_arrow_do(xdesc,ydesc,ldesc,adesc,reference,error)
  use gbl_message
  use sic_types
  use greg_dependencies_interfaces
  use greg_interfaces, except_this=>greg_arrow_do
  !---------------------------------------------------------------------
  ! @ private
  ! Incarnate the arguments as R*4
  !---------------------------------------------------------------------
  type(sic_descriptor_t), intent(in)    :: xdesc
  type(sic_descriptor_t), intent(in)    :: ydesc
  type(sic_descriptor_t), intent(in)    :: ldesc
  type(sic_descriptor_t), intent(in)    :: adesc
  real(kind=4),           intent(in)    :: reference
  logical,                intent(inout) :: error
  ! Global
  include 'gbl_memory.inc'
  ! Local
  character(len=*), parameter :: rname='ARROW'
  integer(kind=size_length) :: nelem(4),ntot
  integer(kind=address_length) :: ipx,ipy,ipl,ipa
  !
  ! Sanity
  nelem(1) = desc_nelem(xdesc)
  nelem(2) = desc_nelem(ydesc)
  nelem(3) = desc_nelem(ldesc)
  nelem(4) = desc_nelem(adesc)
  ntot = maxval(nelem)
  if (any(nelem.ne.1.and.nelem.ne.ntot)) then
    call greg_message(seve%e,rname,'Array mismatch')
    error = .true.
    return
  endif
  !
  ipx = gag_pointer(xdesc%addr,memory)
  ipy = gag_pointer(ydesc%addr,memory)
  ipl = gag_pointer(ldesc%addr,memory)
  ipa = gag_pointer(adesc%addr,memory)
  !
  call greg_arrow_loop(memory(ipx),memory(ipy),memory(ipl),memory(ipa),  &
    nelem,reference,error)
  if (error)  return
  !
end subroutine greg_arrow_do
!
subroutine greg_arrow_loop(xarray,yarray,larray,aarray,nelem,reference,error)
  use gildas_def
  use phys_const
  use greg_dependencies_interfaces
  use greg_interfaces
  use greg_pen
  !---------------------------------------------------------------------
  ! @ no-interface
  !---------------------------------------------------------------------
  real(kind=4),              intent(in)    :: xarray(*)  ! [user]
  real(kind=4),              intent(in)    :: yarray(*)  ! [user]
  real(kind=4),              intent(in)    :: larray(*)  ! [cm]
  real(kind=4),              intent(in)    :: aarray(*)  ! [deg]
  integer(kind=size_length), intent(in)    :: nelem(4)
  real(kind=4),              intent(in)    :: reference
  logical,                   intent(inout) :: error
  ! Local
  integer(kind=size_length) :: ielem
  logical :: many(4)
  real(kind=4) :: xc,yc,length,angle
  real(kind=4) :: xp,yp,x1,y1,x2,y2
  !
  call gtsegm('ARROW',error)
  if (penupd) call setpen(cpen)
  call setdas(1)
  !
  many(:) = nelem(:).gt.1
  do ielem=1,maxval(nelem)
    ! Retrieve the 4 values
    if (many(1)) then
      xc = xarray(ielem)
    else
      xc = xarray(1)
    endif
    if (many(2)) then
      yc = yarray(ielem)
    else
      yc = yarray(1)
    endif
    if (many(3)) then
      length = larray(ielem)
    else
      length = larray(1)
    endif
    if (many(4)) then
      angle = aarray(ielem)*rad_per_deg
    else
      angle = aarray(1)*rad_per_deg
    endif
    !
    ! Convert position (user coordinates) to physical
    call gr4_user_phys (xc,yc,xp,yp,1)
    !
    ! NB: the reference can also go beyond the range [0:1], this means
    ! the reference point is not on the arrow but before or after.
    x1 = xp-length*reference*cos(angle)
    y1 = yp-length*reference*sin(angle)
    !
    x2 = xp+length*(1-reference)*cos(angle)
    y2 = yp+length*(1-reference)*sin(angle)
    !
    call grelocate(x1,y1)
    call garrow2(x2,y2)
  enddo
  !
  call gtsegm_close(error)
  !
end subroutine greg_arrow_loop
