subroutine pencil(line,error)
  use greg_dependencies_interfaces
  use greg_interfaces, except_this=>pencil
  use greg_kernel
  use greg_pen
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command:
  !  PEN [I|*]
  !      [/COLOUR Name]
  !      [/DASHED ND]
  !      [/WEIGHT NW|Valmm]
  !      [/DEFAULT]
  ! Define the status of the pen(s) or change the default pen
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Input command line
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='PENCIL'
  integer(kind=4) :: kpen,ipen,kdashe,kcolou,nc,first,last
  real(kind=4) :: kweigh
  character(len=argument_length) :: argum
  logical :: dodefau,dodashe,doweigh,docolou
  character(len=message_length) :: mess
  integer(kind=4), parameter :: allpen=-1000
  integer(kind=4), parameter :: optcolour =1
  integer(kind=4), parameter :: optdashed =2
  integer(kind=4), parameter :: optweight =3
  integer(kind=4), parameter :: optdefault=4
  !
  ! Pen index: no arg = current pen, * = all pen
  argum = ' '
  call sic_ch(line,0,1,argum,nc,.false.,error)
  if (error) return
  if (argum.eq.' ') then
    kpen = cpen
  elseif (argum.eq.'*') then
    kpen = allpen
  else
    call sic_math_inte(argum,nc,kpen,error)
    if (error) return
    if (kpen.lt.0 .or. kpen.gt.maxpen) then
      write(mess,'(A,I0,A,I0)') 'Pen number out of range ',0,':',maxpen
      call greg_message(seve%e,rname,mess)
      error = .true.
      return
    endif
  endif
  !
  ! Parsing
  dodefau = sic_present(optdefault,0)
  dodashe = sic_present(optdashed,1)
  if (dodashe) then
    call gtv_pendash_arg2id(rname,line,optdashed,1,kdashe,error)
    if (error) return
  endif
  doweigh = sic_present(optweight,1)
  if (doweigh) then
    call gtv_penwei_arg2val(rname,line,optweight,1,kweigh,error)
    if (error)  return
  endif
  docolou = sic_present(optcolour,1)
  if (docolou) then
    call gtv_pencol_arg2id(rname,line,optcolour,1,kcolou,error)
    if (error)  return
  endif
  !
  ! Apply
  ! PEN /DEF (no pen number) historical behaviour is to reset and exit
  if (argum.eq.' ' .and. dodefau) then
    call setpendef()
    return
  endif
  !
  if (kpen.eq.allpen) then
    first = 0
    last = maxpen
  else
    first = kpen
    last = kpen
  endif
  !
  do ipen=first,last
    if (dodefau)  call setpendef(ipen)
    if (dodashe)  ldashe(ipen) = kdashe
    if (doweigh)  lweigh(ipen) = kweigh
    if (docolou)  lcolou(ipen) = kcolou
  enddo
  !
  ! Also change current pen?
  if (kpen.ne.allpen) then
    call gr_pen(ipen=kpen,error=error)
    if (error)  return
  endif
  !
end subroutine pencil
!
subroutine gr_pen(ipen,icolour,colour,idash,iweight,weight,error)
  use gbl_message
  use greg_interfaces, except_this=>gr_pen
  use greg_pen
  !---------------------------------------------------------------------
  ! @ public
  ! This subroutine:
  !  - sets the pen to be used (if present) or uses the current pen, AND/OR
  !  - sets the new color (if present) of this pen, AND/OR
  !  - sets the new dashing (if present) of this pen, AND/OR
  !  - sets the new weight (if present) of this pen.
  ! All arguments are optional but at least 1 must be present
  !---------------------------------------------------------------------
  integer(kind=4),  intent(in), optional :: ipen
  integer(kind=4),  intent(in), optional :: icolour  ! By Greg colour number OR
  character(len=*), intent(in), optional :: colour   ! By colour name
  integer(kind=4),  intent(in), optional :: idash
  integer(kind=4),  intent(in), optional :: iweight  ! By Greg weight number OR
  real(kind=4),     intent(in), optional :: weight   ! By weight value (cm)
  logical,          intent(inout)        :: error
  ! Local
  character(len=*), parameter :: rname='PEN'
  integer(kind=4) :: kpen,kcol
  character(len=message_length) :: mess
  real(kind=4) :: wei
  !
  ! Pen index
  if (present(ipen)) then
    kpen = ipen
    if (kpen.lt.0 .or. kpen.gt.maxpen) then
      write(mess,100) 'Pen number',0,maxpen
      call greg_message(seve%e,rname,mess)
      call greg_message(seve%e,rname,'Default pen not changed')
      error = .true.
      return
    endif
  else
    kpen = cpen
  endif
  !
  ! Colour index or name (exclusive)
  if (present(icolour) .and. present(colour)) then
    call greg_message(seve%e,rname,'Exclusive arguments ''icolour'' and ''colour''')
    error = .true.
    return
  endif
  if (present(icolour)) then
    call gtv_pencol_num2id(rname,icolour,kcol,error)
    if (error)  return
    lcolou(kpen) = kcol
  endif
  if (present(colour)) then
    call gtv_pencol_name2id(rname,colour,kcol,error)
    if (error)  return
    lcolou(kpen) = kcol
  endif
  !
  ! Dashed pattern
  if (present(idash)) then
    if (idash.lt.mindashed .or. idash.gt.maxdashed) then
      write(mess,100) 'Dashed pattern',mindashed,maxdashed
      call greg_message(seve%e,rname,mess)
      error = .true.
      return
    endif
    ldashe(kpen) = idash
  endif
  !
  ! Line thickness
  if (present(iweight) .and. present(weight)) then
    call greg_message(seve%e,rname,'Exclusive arguments ''iweight'' and ''weight''')
    error = .true.
    return
  endif
  if (present(iweight)) then
    call gtv_penwei_num2val(rname,iweight,wei,error)
    if (error)  return
    lweigh(kpen) = wei
  endif
  if (present(weight)) then
    if (weight.le.0.) then
      call gtv_message(seve%e,rname,'Weight value must be positive')
      error = .true.
      return
    endif
    lweigh(kpen) = weight
  endif
  !
  ! Update the globals
  cpen = kpen
  cdashe = ldashe(cpen)
  cweigh = lweigh(cpen)
  ccolou = lcolou(cpen)
  penupd = .true.
  !
100 format(A,' out of range ',I0,':',I0)
end subroutine gr_pen
!
subroutine setpendef(kpen)
  use greg_pen
  !---------------------------------------------------------------------
  ! @ private
  !  Update all or single the pen attributes to their default, and
  ! reset the pen number
  !---------------------------------------------------------------------
  integer(kind=4), intent(in), optional :: kpen
  ! Local
  integer(kind=4) :: i,first,last,jpen
  !
  if (present(kpen)) then
    if (kpen.lt.0 .or. kpen.gt.maxpen)  return
    first = kpen
    last = kpen
    jpen = kpen
  else
    first = 0
    last = maxpen
    jpen = defpen  ! Also reset current pen to default
  endif
  !
  do i = first,last
    ldashe(i) = defdashe(i)
    lcolou(i) = defcolid(i)
    lweigh(i) = defweival(i)
  enddo
  !
  ! Update the globals
  cpen = jpen
  cdashe = ldashe(cpen)
  cweigh = lweigh(cpen)
  ccolou = lcolou(cpen)
  penupd = .true.
  !
end subroutine setpendef
!
subroutine greset
  use greg_kernel
  use greg_pen
  !---------------------------------------------------------------------
  ! @ public
  ! Reset the current Pen position to "undefined"
  !---------------------------------------------------------------------
  !
  gxp = -1e10
  gyp = -1e10
  penupd = .true.
end subroutine greset
