subroutine relocate(x,y)
  use greg_kernel
  !---------------------------------------------------------------------
  ! @ public
  !   Position pen at user coordinate (X,Y)
  !---------------------------------------------------------------------
  real(kind=8), intent(in) :: x  ! User X coordinate
  real(kind=8), intent(in) :: y  ! User Y coordinate
  !
  if (axis_xlog) then
    if (x.gt.0) then
      xp = gx1 + gux * (log(x)-lux)
    elseif (gux.gt.0) then
      xp = gx1
    else
      xp = gx2
    endif
  else
    xp = gx1 + gux * (x-gux1)
  endif
  if (axis_ylog) then
    if (y.gt.0) then
      yp = gy1 + guy * (log(y)-luy)
    elseif (guy.gt.0) then
      yp = gy1
    else
      yp = gy2
    endif
  else
    yp = gy1 + guy * (y-guy1)
  endif
end subroutine relocate
!
subroutine grelocate(ax,ay)
  use greg_kernel
  !---------------------------------------------------------------------
  ! @ public-mandatory (because symbol is used elsewhere)
  !   Position pen at Plot coordinate (X,Y)
  !---------------------------------------------------------------------
  real(kind=4), intent(in) :: ax  ! Plot X coordinate
  real(kind=4), intent(in) :: ay  ! Plot Y coordinate
  xp = ax
  yp = ay
end subroutine grelocate
!
subroutine draw(ux,uy)
  use greg_interfaces
  use greg_kernel
  !---------------------------------------------------------------------
  ! @ no-interface (name is too generic)
  !   Draw a vector from current pen position to given point. The
  ! current line type is used.
  !---------------------------------------------------------------------
  real(kind=8), intent(in) :: ux  ! User X coordinate (DRAW)
  real(kind=8), intent(in) :: uy  ! User Y coordinate
  real(kind=4), intent(in) :: ax  ! Plot X coordinate (GDRAW)
  real(kind=4), intent(in) :: ay  ! Plot Y coordinate
  ! Local
  real(kind=4) :: xq,yq
  integer(kind=4) :: c0,c1,c
  real(kind=4) :: x,y, x0,y0, x1,y1
  !
  ! User coordinates
  if (axis_xlog) then
    if (ux.gt.0) then
      xq = gx1 + gux * (log(ux)-lux)
    elseif (gux.gt.0) then
      xq = gx1
    else
      xq = gx2
    endif
  else
    xq = gx1 + gux * (ux-gux1)
  endif
  if (axis_ylog) then
    if (uy.gt.0) then
      yq = gy1 + guy * (log(uy)-luy)
    elseif (guy.gt.0) then
      yq = gy1
    else
      yq = gy2
    endif
  else
    yq = gy1 + guy * (uy-guy1)
  endif
  goto 1
  !
entry gdraw(ax,ay)
  !---------------------------------------------------------------------
  ! @ public
  ! Page coordinates
  !---------------------------------------------------------------------
  xq = ax
  yq = ay
  !
  ! End-points of line are (X0,Y0), (X1,Y1)
  !
1 x0 = xp
  y0 = yp
  x1 = xq
  y1 = yq
  xp = xq
  yp = yq
  !
  ! Clip the line
  if (noclip) goto 100
  !
  ! Change the end-points of the line (X0,Y0) - (X1,Y1)
  ! to clip the line at the window boundary.
  ! The algorithm is that of Cohen and Sutherland (ref: Newman & Sproull)
  !
  call grclip(x0,y0,c0)
  call grclip(x1,y1,c1)
  !
  do while (c0.ne.0 .or. c1.ne.0)
    if (iand(c0,c1).ne.0) then ! line is invisible
      return
    endif
    c = c0
    if (c.eq.0) c = c1
    if (iand(c,1).ne.0) then   ! crosses GX1
      y = y0 + (y1-y0)*(gx1-x0)/(x1-x0)
      x = gx1
    elseif (iand(c,2).ne.0) then   ! crosses GX2
      y = y0 + (y1-y0)*(gx2-x0)/(x1-x0)
      x = gx2
    elseif (iand(c,4).ne.0) then   ! crosses GY1
      x = x0 + (x1-x0)*(gy1-y0)/(y1-y0)
      y = gy1
    elseif (iand(c,8).ne.0) then   ! crosses GY2
      x = x0 + (x1-x0)*(gy2-y0)/(y1-y0)
      y = gy2
    endif
    if (c.eq.c0) then
      x0 = x
      y0 = y
      call grclip(x,y,c0)
    else
      x1 = x
      y1 = y
      call grclip(x,y,c1)
    endif
  enddo
  !
100 continue
  call grline(x0,y0,x1,y1)
end subroutine draw
!
subroutine grline(cxa,cya,cxb,cyb)
  use greg_dependencies_interfaces
  use greg_interfaces, except_this=>grline
  use greg_kernel
  !---------------------------------------------------------------------
  ! @ private
  !   Plot a line from CXA,CYA to CXB,CYB with current pen attributes.
  !---------------------------------------------------------------------
  real(kind=4), intent(in) :: cxa  ! Plot X coordinate of start point
  real(kind=4), intent(in) :: cya  ! Plot Y coordinate of start point
  real(kind=4), intent(in) :: cxb  ! Plot X coordinate of end point
  real(kind=4), intent(in) :: cyb  ! Plot Y coordinate of end point
  !
  if (cxa.ne.gxp .or. cya.ne.gyp) then
    !!print *,'GTRELOC at ',cxa,cya
    call gtreloc(cxa,cya)
  endif
  !!print *,'GRLINE relo at ',gxp,gyp
  call gtdraw(cxb,cyb)
  !!print *,'GRLINE draw at ',cxb,cyb
  gxp = cxb  ! Set the pen location after the 'gtdraw'
  gyp = cyb  !
end subroutine grline
!
subroutine grpoly(nq,xq,yq)
  use gildas_def
  use greg_interfaces, except_this=>grpoly
  use greg_kernel
  !---------------------------------------------------------------------
  ! @ private-mandatory (because symbol is used elsewhere)
  ! Plots a poly-line in paper coordinate, with clipping in the BOX
  !---------------------------------------------------------------------
  integer(kind=size_length), intent(in) :: nq     ! Number of points
  real(kind=4),              intent(in) :: xq(*)  ! Plot X coordinates
  real(kind=4),              intent(in) :: yq(*)  ! Plot Y coordinates
  ! Local
  integer(kind=size_length) :: k
  integer(kind=4) :: c0,c1,c,cold
  real(kind=4) :: x,y, x0,y0, x1,y1
  logical :: up
  !
  ! NQ is less than 2.
  if (nq.lt.2) then
    if (nq.lt.1) return
    xp = xq(1)
    yp = yq(1)
    return
  endif
  !
  ! Update XP and YP
  xp = xq(nq)
  yp = yq(nq)
  !
  ! End-points of line are (X0,Y0), (X1,Y1)
  x0 = xq(1)
  y0 = yq(1)
  call grclip(x0,y0,c0)
  up = .true.
  !
  ! Loop on points
  ! Change the end-points of the line (X0,Y0) - (X1,Y1)
  ! to clip the line at the window boundary.
  ! The algorithm is that of Cohen and Sutherland (ref: Newman & Sproull)
  !
  do k=2,nq
    x1 = xq(k)
    y1 = yq(k)
    call grclip(x1,y1,c1)
    cold = c1
    !
    do while (ior(c0,c1).ne.0)
      if (iand(c0,c1).ne.0) goto 100   ! line is invisible
      if (c0.eq.0) then
        c = c1
      else
        c = c0
      endif
      if (iand(c,1).ne.0) then ! crosses GX1
        if (abs(x0).gt.huge(x0)) then  ! x0 is +-Inf
          y = y1
        else
          y = y0 + (y1-y0)*(gx1-x0)/(x1-x0)
        endif
        x = gx1
      elseif (iand(c,2).ne.0) then ! crosses GX2
        if (abs(x0).gt.huge(x0)) then  ! x0 is +-Inf
          y = y1
        else
          y = y0 + (y1-y0)*(gx2-x0)/(x1-x0)
        endif
        x = gx2
      elseif (iand(c,4).ne.0) then ! crosses GY1
        if (abs(y0).gt.huge(y0)) then  ! y0 is +-Inf
          x = x1
        else
          x = x0 + (x1-x0)*(gy1-y0)/(y1-y0)
        endif
        y = gy1
      elseif (iand(c,8).ne.0) then ! crosses GY2
        if (abs(y0).gt.huge(y0)) then  ! y0 is +-Inf
          x = x1
        else
          x = x0 + (x1-x0)*(gy2-y0)/(y1-y0)
        endif
        y = gy2
      endif
      if (c.eq.c0) then
        x0 = x
        y0 = y
        call grclip(x,y,c0)
      else
        x1 = x
        y1 = y
        call grclip(x,y,c1)
      endif
    enddo
    !
    ! Plot the line : Pen up to X0,Y0 then pen down to X1,Y1
    ! Nor yet optimised
    if (up) then
      call grline(x0,y0,x1,y1)
    else
      call grline(x0,y0,x1,y1)
    endif
    !
    ! End of loop
100 c0 = cold
    x0 = xq(k)
    y0 = yq(k)
    up = cold.ne.0
  enddo
end subroutine grpoly
!
subroutine grdots(nq,xq,yq)
  use gildas_def
  use greg_dependencies_interfaces
  use greg_interfaces
  use greg_kernel
  !---------------------------------------------------------------------
  ! @ no-interface (rank mismatch)
  ! GREG Internal routine
  !  Plots a list of dot points in paper coordinate, with clipping in
  ! the BOX. REAL*4 coordinates.
  !---------------------------------------------------------------------
  integer(kind=size_length), intent(in) :: nq     ! Number of points
  real(kind=4),              intent(in) :: xq(*)  ! Plot X coordinates
  real(kind=4),              intent(in) :: yq(*)  ! Plot Y coordinates
  ! Local
  integer(kind=size_length) :: ip,fp
  integer(kind=4) :: c0,np
  logical :: error
  !
  ! Update XP and YP (pen position)
  xp = xq(nq)
  yp = yq(nq)
  !
  c0 = -1
  np = 0
  fp = 1
  do ip=1,nq
    call grclip(xq(ip),yq(ip),c0)
    if (c0.eq.0) then
      if (np.eq.0)  fp = ip  ! First point
      np = np+1
    elseif (c0.ne.0) then
      ! Point is clipped out
      if (np.ne.0) then
        error = .false.
        call gtv_points(np,xq(fp),yq(fp),error)
        if (error)  return
        np = 0
      endif
    endif
  enddo
  !
  if (c0.eq.0) then
    ! Last (serie of) point(s)
    if (np.ne.0) then
      error = .false.
      call gtv_points(np,xq(fp),yq(fp),error)
      if (error)  return
    endif
  endif
  !
end subroutine grdots
!
subroutine grclip (x,y,c)
  use greg_kernel
  !---------------------------------------------------------------------
  ! @ private
  !   Support routine for the clipping algorithm ; called from DRAW
  ! and GRPOLY only.  C is a 4 bit code indicating the relationship
  ! between point (X,Y) and the window boundaries ; 0 implies the
  ! point is within the window.
  !---------------------------------------------------------------------
  real(kind=4),    intent(in)  :: x  ! Plot X coordinate
  real(kind=4),    intent(in)  :: y  ! Plot Y coordinate
  integer(kind=4), intent(out) :: c  ! Code for clipping
  !
  c = 0
  if (x.lt.gx1) then
    c = 1
  elseif (x.gt.gx2) then
    c = 2
  endif
  if (y.lt.gy1) then
    c = c+4
  elseif (y.gt.gy2) then
    c = c+8
  endif
end subroutine grclip
!
subroutine cross(xp,yp,xq,yq,x1,x2,y1,y2,xc,yc,xd,yd,ok)
  !---------------------------------------------------------------------
  ! @ private
  ! Clipping subroutine. Not used, kept for reference.
  !
  ! Return segment XC,YC,XD,YD where the segment XP,YP,XQ,YQ crosses the
  ! box X1,Y1,X2,Y2. Set OK to FALSE if never in the box.
  ! It is assumed that X1 < X2 and Y1 < Y2.
  !---------------------------------------------------------------------
  real(kind=4), intent(in)  :: xp,yp  ! Line to be clipped (start point)
  real(kind=4), intent(in)  :: xq,yq  ! Line to be clipped (end point)
  real(kind=4), intent(in)  :: x1,y1  ! Box BLC
  real(kind=4), intent(in)  :: x2,y2  ! Box TRC
  real(kind=4), intent(out) :: xc,yc  ! Clipped line (start point)
  real(kind=4), intent(out) :: xd,yd  ! Clipped line (end point)
  logical,      intent(out) :: ok     ! Is the clipped line visible?
  ! Local
  real(kind=4) :: x,y
  !
  xc = xp
  yc = yp
  xd = xq
  yd = yq
  !
  ! Cross left boundary?
  if ((xc-x1)*(xd-x1).lt.0) then
    y = yc + (yd-yc)*(x1-xc)/(xd-xc)
    if (xc-x1.gt.0) then
      xd = x1
      yd = y
    else
      xc = x1
      yc = y
    endif
  endif
  !
  ! Cross right boundary?
  if ((xc-x2)*(xd-x2).lt.0) then
    y = yc + (yd-yc)*(x2-xc)/(xd-xc)
    if (x2-xc.gt.0) then
      xd = x2
      yd = y
    else
      xc = x2
      yc = y
    endif
  endif
  !
  ! Cross bottom boundary?
  if ((yc-y1)*(yd-y1).lt.0) then
    x = xc + (xd-xc)*(y1-yc)/(yd-yc)
    if (yc-y1.gt.0) then
      yd = y1
      xd = x
    else
      yc = y1
      xc = x
    endif
  endif
  !
  ! Cross top boundary?
  if ((yc-y2)*(yd-y2).lt.0) then
    x = xc + (xd-xc)*(y2-yc)/(yd-yc)
    if (y2-yc.gt.0) then
      yd = y2
      xd = x
    else
      yc = y2
      xc = x
    endif
  endif
  !
  ok = xc.ge.x1 .and. xc.le.x2 .and.  &
       yc.ge.y1 .and. yc.le.y2 .and.  &
       xd.ge.x1 .and. xd.le.x2 .and.  &
       yd.ge.y1 .and. yd.le.y2
  !
end subroutine cross
