subroutine gtl_change(line,error)
  use gtv_dependencies_interfaces
  use gtv_interfaces, except_this=>gtl_change
  use gtv_graphic
  use gtv_tree
  use gtv_buffers
  use gtv_protocol
  use gtv_plot
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command
  !    CHANGE Item SegName Value [Val2 [Val3]]
  !    CHANGE Behaviour Value
  !---------------------------------------------------------------------
  character(len=*)                :: line   !
  logical,          intent(inout) :: error  !
  ! Local
  character(len=*), parameter :: rname='CHANGE'
  integer, parameter :: nvocab=14,nlut=2,nhard=2
  character(len=12) :: vocab(nvocab),vlut(nlut),vhard(nhard),to_check,comm
  integer :: ncom,mode,nc
  character(len=gtvpath_length) :: argum
  integer :: win_num,cnum,npixx,npixy,sever
  logical :: active
  ! Data
  data vocab /'BLANKING','COLOUR','DASH','DEPTH','DIRECTORY','DRAW',    &
    'PENCIL','PIXEL','POSITION','LUT','SCALING','VISIBILITY','WEIGHT',  &
    'WINDOW'/
  data vlut /'STATIC','DYNAMIC'/
  data vhard /'HARD','SOFT'/
  !
  call sic_ke (line,0,1,to_check,nc,.true.,error)
  if (error) return
  !
  ! Check if type of variable is known
  call sic_ambigs('CHANGE',to_check,comm,ncom,vocab,nvocab,error)
  if (error)  return
  !
  select case (comm)
  case('DIRECTORY')
    ! CHANGE DIRECTORY Name [Window]
    ! Directory name
    argum = dir_top
    call sic_ch (line,0,2,argum,nc,.false.,error)
    if (error) return
    call sic_upper(argum)
    ! Window number
    if (sic_present(0,3)) then
      ! Rely on the window number given by user
      active = .false.
      call sic_i4(line,0,3,win_num,.true.,error)
      if (error) return
    else
      ! Use the active window
      active = .true.
      win_num = 0  ! Dummy value
    endif
    call cd_by_name(argum,active,win_num,error)
    !
  case('WINDOW')
    ! CHANGE WINDOW Num: change to named window
    !
    call gtv_open_segments_for_writing_from_main()
    !
    cnum = get_window_cnum_byname(cw_directory,rname,line,0,2,error)
    !
    call cd_by_win(cw_directory,cnum,error)
    !
    call gtv_close_segments_for_writing_from_main()
    !
  case('DRAW')
    ! CHANGE DRAW ON|OFF
    if (strict2011) then
      sever = seve%e
    else
      sever = seve%w
    endif
    call gtv_message(sever,rname,'CHANGE DRAW is obsolete. GTVirt is always awake.')
    if (strict2011) then
      error = .true.
      return
    endif
    !
  case('PENCIL')
    ! CHANGE PENCIL HARD|SOFT
    if (sic_present(0,2)) then
      call sic_ke(line,0,2,to_check,nc,.true.,error)
      if (error)  return
      call sic_ambigs('PENCIL',to_check,comm,mode,vhard,nhard,error)
      if (error)  return
      if (comm.eq.'HARD') then
        user_hardw_line=.true.
      else
        user_hardw_line=.false.
      endif
    endif
    if (user_hardw_line) then
      call gtv_message(seve%i,rname,'Pencil uses hardware generator (if available)')
    else
      call gtv_message(seve%i,rname,'Pencil uses GTV generator')
    endif
    !
  case('POSITION')
    call gtl_change_position(line,error)
    if (error)  return
    !
  case('LUT')
    ! CHANGE LUT STATIC|DYNAMIC
    if (sic_present(0,2)) then
      call sic_ke (line,0,2,to_check,nc,.true.,error)
      if (error) return
      call sic_ambigs('LUT',to_check,comm,mode,vlut,nlut,error)
      if (error) return
      lut_static = comm.eq.'STATIC'
      !
      call exec_images_recurs(root,change_image_lut)
      call exec_poly_recurs(root,change_poly_penlut)
      call gtview('Update')
    endif
    if (lut_static) then
      call gtv_message(seve%i,rname,'LUT behaviour is STATIC')
    else
      call gtv_message(seve%i,rname,'LUT behaviour is DYNAMIC')
    endif
    !
  case('PIXEL')
    ! CHANGE PIXEL NX NY. Work on the current window only
    if (cw_output%dev%protocol.ne.p_x) then
      call gtv_message(seve%e,rname,'Command is available only for X windows')
      error = .true.
      return
      !
    elseif (cw_output%x%graph_env.eq.0) then
      call gtv_message(seve%w,rname,'No active window, nothing done')
      return
      !
    else
      call sic_i4(line,0,2,npixx,.true.,error)
      if (error) return
      call sic_i4(line,0,3,npixy,.true.,error)
      if (error) return
      call x_resize_window(cw_output%x%graph_env,npixx,npixy)
    endif
    !
  case default
    ! CHANGE SCALING|BLANKING|COLOUR|DASH|DEPTH|VISIBILITY|WEIGHT SegName Value
    call gtl_change_attr(line,comm,error)
    if (error)  return
    !
  end select
  !
end subroutine gtl_change
!
subroutine gtl_change_position(line,error)
  use gtv_dependencies_interfaces
  use gtv_interfaces, except_this=>gtl_change_position
  use gbl_message
  use gtv_protocol
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command:
  !  CHANGE POSITION Num
  !  CHANGE POSITION Posx[Unitx] Posy[Unity]
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Command line
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='CHANGE'
  character(len=12) :: argx,argy
  integer(kind=4) :: icode,nc,posx,posy
  !
  if (cw_device%protocol.ne.p_x)  return
  !
  if (cw_output%x%graph_env.eq.0) then
    call gtv_message(seve%w,rname,'No active window, nothing done')
    return
  endif
  !
  if (sic_present(0,3)) then
    call sic_ch(line,0,2,argx,nc,.true.,error)
    if (error)  return
    call sic_ch(line,0,3,argy,nc,.true.,error)
    if (error)  return
    call decode_coordinates(cw_output%x%position,argx,argy,error)
    if (error)  return
    !
    call compute_coordinates_position(cw_output,posx,posy,error)
    if (error)  return
    ! And finally move
    call x_move_window(cw_output%x%graph_env,posx,posy)
    !
  else
    call sic_i4(line,0,2,icode,.true.,error)
    if (error) return
    if (icode.le.0 .or. icode.ge.10) return
    call x_corner(cw_output%x%graph_env,icode)
  endif
  !
end subroutine gtl_change_position
!
subroutine gtl_change_attr(line,comm,error)
  use gbl_message
  use gtv_buffers
  use gtv_graphic
  use gtv_dependencies_interfaces
  use gtv_interfaces, except_this=>gtl_change_attr
  use gtv_protocol
  use gtv_plot
  use gtv_segatt
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command
  !   CHANGE SCALING|BLANKING|COLOUR|DASH|DEPTH|VISIBILITY|WEIGHT SegName Value
  ! Modify (macro)segment attributes
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Input command line
  character(len=*), intent(in)    :: comm   ! Attribute (already resolved)
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='CHANGE'
  real(kind=4) :: cutvalue(6),wei
  logical :: cutreset(6)
  integer :: att_code,att_val_in,att_val
  character(len=12) :: to_check,keyw
  character(len=gtvpath_length) :: argum_in,argum
  logical :: isdir,found,done
  integer :: ia,la,iseg,iseg1,iseg2,i,nc,mode,scaling
  character(len=message_length) :: mess
  type(gt_directory), pointer :: workdir,father
  type(gt_segment), pointer :: segm
  !
  integer, parameter :: nscale=4
  integer, parameter :: nvisi=2
  character(len=12) :: vscal(nscale),vvisi(nvisi)
  data vscal /'SAME','LINEAR','LOGARITHMIC','EQUALIZATION'/
  data vvisi /'ON','OFF'/
  !
  ! Get (macro)segment name
  call sic_ch(line,0,2,argum_in,nc,.false.,error)
  if (error) return
  call sic_upper(argum_in)
  !
  argum = argum_in
  call decode_chemin(argum,cw_directory,workdir,isdir,segm,found)
  if (.not.found .or. .not.isdir) then
    ! Not a known macrosegment: assume it represents a segment
    ! Parse wildcards, range and so on
    call gtl_segment_parse(argum,iseg1,iseg2,error)
    if (error) return
    la = len_trim(argum)
    ia = index(argum,':')
    iseg=1
    if (iseg1.ge.iseg2) iseg=-1
  endif
  !
  done = .false.
  !
  ! CHANGE VISIBILITY SegName ON|OFF|CLEAR
  if (comm.eq.'VISIBILITY') then
    call sic_ke (line,0,3,to_check,nc,.true.,error)
    if (error) return
    call sic_ambigs('VISIBILITY',to_check,keyw,nc,vvisi,nvisi,error)
    if (error) return
    !
    if (keyw.eq.'ON') then
      att_val = 1
    else  ! 'OFF' or 'CLEAR'
      att_val = -1
    endif
    !
    if (isdir) then
      call gtv_open_segments_for_writing_from_main()
      call change_attr_dir(workdir,att_vis,att_val)
      call gtv_close_segments_for_writing_from_main()
      father => workdir%father
      done = .true.
    else
      do i=iseg1,iseg2,iseg
        if (i.ne.0) then
          write(argum(ia+1:),'(I6)') i
          la = ia+6
          call sic_black(argum,la)
          call decode_chemin(argum,cw_directory,workdir,isdir,segm,found)
        endif
        if (found) then
          if (isdir) then
            call gtv_open_segments_for_writing_from_main()
            call change_attr_dir(workdir,att_vis,att_val)
            call gtv_close_segments_for_writing_from_main()
            ! Need to know the parent directory of all the affected
            ! segments, because we have to update its minmax limits
            ! at the end.
            father => workdir%father
          else
            call gtv_open_segments_for_writing_from_main()
            call change_attr_seg(segm,att_vis,att_val)
            call gtv_close_segments_for_writing_from_main()
            father => workdir
          endif
          !
          done = .true.
        endif
      enddo
    endif
    !
    ! Recompute parent directory limits.
    if (done) then
      call gtv_limits(father,error)
      if (error) then
        call gtv_message(seve%e,rname,'Updating the parent directory limits')
        return
      endif
    endif
  !
  ! CHANGE BLANKING SegName Value
  elseif (comm.eq.'BLANKING') then
    ! TBD : To be defined,  but the blanking colour is a window attribute ?
    call sic_i4(line,0,3,att_val_in,.true.,error)
    if (error) return
    call gtv_message(seve%w,rname,'BLANKING action is not yet implemented')
  !
  ! CHANGE SCALING Segments NEW_MODE NEW_LCUT NEW_HCUT
  elseif (comm.eq.'SCALING') then
    call sic_ke (line,0,3,to_check,nc,.true.,error)
    if (error) return
    call sic_ambigs('SCALING',to_check,keyw,mode,vscal,nscale,error)
    if (error)  return
    !
    ! More sophisticated logic with * used when going back to automatic
    ! Low and High cuts
    call gtl_change_parse(line,4,cutreset(1),cutvalue(1),error)
    if (error)  return
    call gtl_change_parse(line,5,cutreset(2),cutvalue(2),error)
    if (error)  return
    call gtl_change_parse(line,6,cutreset(3),cutvalue(3),error)
    if (error)  return
    call gtl_change_parse(line,7,cutreset(4),cutvalue(4),error)
    if (error)  return
    call gtl_change_parse(line,8,cutreset(5),cutvalue(5),error)
    if (error)  return
    call gtl_change_parse(line,9,cutreset(6),cutvalue(6),error)
    if (error)  return
    !
    ! Set the new mode
    scaling = mode-1
    if (isdir) then
      done = .true.
      call change_scaling_dir(workdir,scaling,cutreset,cutvalue,error)
      if (error)  return
    else
      do i=iseg1,iseg2
        if (i.ne.0) then
          write(argum(ia+1:),'(I6)') i
          la = ia+6
          call sic_black(argum,la)
          call decode_chemin(argum,cw_directory,workdir,isdir,segm,found)
        endif
        if (found) then
          done = .true.
          call change_scaling_image(segm,scaling,cutreset,cutvalue,.true.,error)
          if (error)  return
        endif
      enddo
    endif
    !
    ! Force bitmap refresh on X-Window (GTVIEW is too clever...)
    if (done .and. cw_device%protocol.eq.p_x)  &
      call gti_xforceupdate(cw_output)
  !
  ! CHANGE COLOUR|DASH|DEPTH|WEIGHT SegName Value
  else
    if (comm.eq.'COLOUR') then
      att_code = att_colour
      call gtv_pencol_arg2id(rname,line,0,3,att_val,error)
      if (error)  return
    elseif (comm.eq.'DASH') then
      att_code = att_dash
      call sic_i4(line,0,3,att_val,.true.,error)
      if (error) return
      att_val = max(min_dash,min(att_val,max_dash))
    elseif (comm.eq.'WEIGHT') then
      att_code = att_weight
      call gtv_penwei_arg2val(rname,line,0,3,wei,error)
      if (error) return
      ! Because change_attr_seg requires an int value, and for
      ! simplicity we just multiply and later divide the value
      ! by 10000
      att_val = 10000*wei
    elseif (comm.eq.'DEPTH') then
      att_code = att_depth
      call sic_i4(line,0,3,att_val_in,.true.,error)
      if (error) return
      att_val = att_val_in
      if (att_val.gt.cdepth) then
        if (cdepth.eq.0) cdepth = 1
        cdepth = cdepth+1
        att_val = cdepth
      endif
      att_val = max(1,min(att_val,max_depth))
      if (att_val.ne.att_val_in) then
        write(mess,'(A,I2,A)') 'Corrected input depth value to ',att_val,  &
        ' before setting'
        call gtv_message(seve%w,rname,mess)
      endif
      vdepth(att_val) = .true.
    endif
    !
    if (isdir) then
      done = .true.
      call gtv_open_segments_for_writing_from_main()
      call change_attr_dir(workdir,att_code,att_val)
      call gtv_close_segments_for_writing_from_main()
    else
      do i=iseg1,iseg2,iseg
        if (i.ne.0) then
          write(argum(ia+1:),'(I6)') i
          la = ia+6
          call sic_black(argum,la)
          call decode_chemin(argum,cw_directory,workdir,isdir,segm,found)
        endif
        if (found) then
          done = .true.
          call gtv_open_segments_for_writing_from_main()
          if (isdir) then
            call change_attr_dir(workdir,att_code,att_val)
          else
            call change_attr_seg(segm,att_code,att_val)
          endif
          call gtv_close_segments_for_writing_from_main()
        endif
      enddo
    endif
    !
  endif
  !
  if (done) then
    call gtview('Update')
  else
    call gtv_message(seve%e,rname,'No such segment '//argum_in)
    error = .true.
    return
  endif
  !
end subroutine gtl_change_attr
!
subroutine gtl_change_parse(line,iarg,reset,value,error)
  use gtv_dependencies_interfaces
  use gtv_interfaces, except_this=>gtl_change_parse
  !---------------------------------------------------------------------
  ! @ private
  !  Retrieve the iarg-th argument of the command. Return reset=.true.
  ! (i.e. use internal default) if argument is wildcard '*', else
  ! reset=.false. and value is filled.
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Command line
  integer(kind=4),  intent(in)    :: iarg   ! Argument number
  logical,          intent(out)   :: reset  !
  real(kind=4),     intent(out)   :: value  !
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  integer(kind=4) :: nc
  character(len=8) :: arg
  !
  arg = '*'
  call sic_ch(line,0,iarg,arg,nc,.false.,error)
  if (error)  return
  !
  if (arg.eq.'*') then
    reset = .true.
    value = 0.  ! Unused
  else
    reset = .false.
    call sic_r4(line,0,iarg,value,.true.,error)
    if (error) return
  endif
  !
end subroutine gtl_change_parse
!
subroutine gtl_segment_parse(argum,iseg1,iseg2,error)
  use gbl_message
  use gtv_buffers
  use gtv_interfaces, except_this=>gtl_segment_parse
  use gtv_tree
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  ! Parse segment name given in input, return segments number (min and
  ! max) to search in
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: argum  ! Segment name to parse
  integer,          intent(out)   :: iseg1  ! Lower segment number
  integer,          intent(out)   :: iseg2  ! Upper segment number
  logical,          intent(inout) :: error  ! Error flag
  ! Local
  character(len=*), parameter :: rname='SEGMENT'
  integer :: ia,ka,la,ier,isep
  character(len=*), parameter :: wildcard='********'
  character(len=gtvpath_length) :: dirname
  type(gt_directory), pointer :: workdir
  type(gt_segment), pointer :: segm
  logical :: isdir,found
  !
  ! Find what is the parent
  isep = index(argum,dir_sep,.true.)
  if (isep.eq.0) then
    workdir => cw_directory
  elseif (isep.eq.1) then
    workdir => root
  else
    dirname = argum(:isep-1)
    call decode_chemin(dirname,cw_directory,workdir,isdir,segm,found)
    if (.not.found .or. .not.isdir) then
      call gtv_message(seve%e,rname,'No such directory '//dirname)
      error = .true.
      return
    endif
  endif
  !
  la = len_trim(argum)
  ia = index(argum,':')
  ka = index(argum(ia:),'-')
  !
  if (ia.eq.la) then
    ! Form is "xxx:" corresponds to whole range
    iseg1 = 1
    iseg2 = workdir%segn
    !
  elseif (ia.eq.0 .and. ka.eq.0) then
    ! No ':', no '-'
    read(argum(1:la),'(I20)',iostat=ier) iseg1
    if (ier.eq.0) then
      ! argum is one or more digits
      iseg2=iseg1
      argum='*:'
    elseif (argum(1:la).eq.wildcard(1:min(8,la))) then
      ! argum is one or more stars
      iseg1 = 1
      iseg2 = workdir%segn
      argum = '*:'
    else
      ! argum should be a segment name
      iseg1 = 1
      iseg2 = workdir%segn
      ia=la+1
      argum(ia:ia) = ':'
    endif
    !
  elseif (ia.gt.0.and.ka.eq.0) then
    ! ':' but no '-'
    read(argum(ia+1:la),*,iostat=ier) iseg1
    if (ier.eq.0) then
      iseg2=iseg1
    elseif (argum(ia+1:la).eq.wildcard(1:min(8,la-ia))) then
      iseg1 = 1
      iseg2 = workdir%segn
    else
      call gtv_message(seve%e,rname,'Invalid segment name(s)')
      error = .true.
      return
    endif
    !
  else
    ! Range given?
    ka = ia-1+ka
    read(argum(ia+1:ka-1),*,iostat=ier) iseg1
    if (ier.eq.0) read(argum(ka+1:la),*,iostat=ier) iseg2
    if (ier.ne.0) then
      call gtv_message(seve%e,rname,'Invalid segment range')
      error = .true.
      return
    endif
    if (ia.le.1) then
      ia = 2
      argum(1:ia) = '*:'
    endif
  endif
  !
end subroutine gtl_segment_parse
!
subroutine change_attr_seg(segm,att_code,att_val)
  use gtv_interfaces, except_this=>change_attr_seg
  use gtv_segatt
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !  Elemental routine which modifies the ATT_CODE-th attribute and
  ! assigns it ATT_VAl. Work on a single segment only.
  !---------------------------------------------------------------------
  type(gt_segment)            :: segm      ! Segment instance
  integer(kind=4), intent(in) :: att_code  ! Attribute code
  integer(kind=4), intent(in) :: att_val   ! Attribute value
  !
  select case (att_code)
  case (att_vis)
    segm%head%gen%visible = att_val.ge.0
  case (att_dash)
    segm%head%attr%dash = att_val
  case (att_weight)
    segm%head%attr%weight = att_val/1e4
  case (att_colour)
    segm%head%attr%colour = att_val
  case (att_depth)
    segm%head%attr%depth = att_val
  end select
  !
end subroutine change_attr_seg
!
recursive subroutine change_attr_dir(dir,att_code,att_val)
  use gtv_buffers
  use gtv_graphic
  use gtv_interfaces, except_this=>change_attr_dir
  use gtv_protocol
  use gtv_segatt
  use gtv_tree
  use gtv_types
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !  Routine which modifies the ATT_CODE-th attribute and assigns it
  ! ATT_VAl. Work on the input directory and its elements.
  !---------------------------------------------------------------------
  type(gt_directory)          :: dir       ! Directory
  integer(kind=4), intent(in) :: att_code  ! Attribute code
  integer(kind=4), intent(in) :: att_val   ! Attribute value
  ! Local
  type(gt_segment), pointer :: segm
  type(gt_directory), pointer :: son
  !
  ! Modification de l'attribut 'visible' du macrosegment donne
  if (att_code.eq.att_vis)  dir%gen%visible = att_val.ge.0
  !
  ! 1) Run on the current directory segments
  segm => dir%leaf_first
  do while (associated(segm))
    call change_attr_seg(segm,att_code,att_val)
    !
    ! Next segment
    segm => segm%nextseg
  enddo
  !
  ! 2) Run on the subdirectories
  son => dir%son_first
  do while (associated(son))
    call change_attr_dir(son,att_code,att_val)
    !
    ! Next directory
    son => son%brother
  enddo
  !
end subroutine change_attr_dir
!
subroutine change_scaling_image(segm,scaling,reset,value,strict,error)
  use gtv_bitmap
  use gtv_buffers
  use gtv_interfaces, except_this=>change_scaling_image
  use gtv_plot
  use gtv_segatt
  use gtv_tree
  use gtv_types
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !  Modifie la valeur des attributs SCALING et CUTS
  !---------------------------------------------------------------------
  type(gt_segment), intent(inout) :: segm      ! Segment
  integer,          intent(in)    :: scaling   ! Scaling code (0 = do not change)
  logical,          intent(in)    :: reset(6)  ! Reset the cut limits?
  real(kind=4),     intent(in)    :: value(6)  ! Cut value, if reset
  logical,          intent(in)    :: strict    ! Is it an error that the segment is not an image?
  logical,          intent(inout) :: error     ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='CHANGE'
  type(gt_segment_data), pointer :: segdata
  type(gt_image), pointer :: image
  logical :: done
  !
  done = .false.
  segdata => segm%data
  do while (associated(segdata))
    if (segdata%kind.eq.seg_image) then
      !
      ! Il s'agit d'un segment-image
      image => segdata%image
      !
      ! Compute new range, resetting default if needed
      if (image%isrgb) then
        if (reset(1)) then
          image%r%cuts(1) = image%r%extrema(1)
        else
          image%r%cuts(1) = value(1)
        endif
        if (reset(2)) then
          image%r%cuts(2) = image%r%extrema(2)
        else
          image%r%cuts(2) = value(2)
        endif
        if (reset(3)) then
          image%g%cuts(1) = image%g%extrema(1)
        else
          image%g%cuts(1) = value(3)
        endif
        if (reset(4)) then
          image%g%cuts(2) = image%g%extrema(2)
        else
          image%g%cuts(2) = value(4)
        endif
        if (reset(5)) then
          image%b%cuts(1) = image%b%extrema(1)
        else
          image%b%cuts(1) = value(5)
        endif
        if (reset(6)) then
          image%b%cuts(2) = image%b%extrema(2)
        else
          image%b%cuts(2) = value(6)
        endif
      else
        if (reset(1)) then
          image%r%cuts(1) = image%r%extrema(1)
        else
          image%r%cuts(1) = value(1)
        endif
        if (reset(2)) then
          image%r%cuts(2) = image%r%extrema(2)
        else
          image%r%cuts(2) = value(2)
        endif
      endif
      !
      ! Put in place
      if (scaling.ne.0)  image%scaling = scaling
      !
      if (image%scaling.eq.scale_equ) then
        ! (New) scale is EQUAL: (re)compute the bins
        if (image%isrgb) then
          call gtv_image_equalize(image%r,error)
          if (error)  return
          call gtv_image_equalize(image%g,error)
          if (error)  return
          call gtv_image_equalize(image%b,error)
          if (error)  return
        else
          call gtv_image_equalize(image%r,error)
          if (error) return
        endif
      else
        ! Other scaling mode: eqvalues not needed, free memory
        if (allocated(image%r%eqvalues))  deallocate(image%r%eqvalues)
        if (allocated(image%g%eqvalues))  deallocate(image%g%eqvalues)
        if (allocated(image%b%eqvalues))  deallocate(image%b%eqvalues)
      endif
      !
      call gtv_image_variables(image,.true.,error)
      if (error)  return
      !
      done = .true.
    endif
    !
    ! Next data
    segdata => segdata%nextdata
    !
  enddo
  !
  if (.not.done .and. strict) then
    call gtv_message(seve%e,rname,'This is not an image segment')
    error = .true.
    return
  endif
  !
end subroutine change_scaling_image
!
recursive subroutine change_scaling_dir(dir,scaling,reset,value,error)
  use gtv_interfaces, except_this=>change_scaling_dir
  use gtv_types
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !
  !---------------------------------------------------------------------
  type(gt_directory), intent(in)    :: dir       ! Directory
  integer,            intent(in)    :: scaling   ! Scaling code
  logical,            intent(in)    :: reset(6)  ! Reset the cut limits?
  real(kind=4),       intent(in)    :: value(6)  ! Cut value, if reset
  logical,            intent(inout) :: error     ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='CHANGE'
  type(gt_segment), pointer :: segm
  type(gt_directory), pointer :: son
  !
  ! 1) Run on the current directory segments
  segm => dir%leaf_first
  do while (associated(segm))
    call change_scaling_image(segm,scaling,reset,value,.false.,error)
    if (error)  return
    !
    ! Next segment
    segm => segm%nextseg
  enddo
  !
  ! 2) Run on the subdirectories
  son => dir%son_first
  do while (associated(son))
    call change_scaling_dir(son,scaling,reset,value,error)
    if (error)  return
    !
    ! Next directory
    son => son%brother
  enddo
  !
end subroutine change_scaling_dir
!
subroutine change_image_lut(head,image)
  use gtv_interfaces, except_this=>change_image_lut
  use gtv_bitmap
  use gtv_buffers
  use gtv_plot
  use gtv_segatt
  !---------------------------------------------------------------------
  ! @ private-mandatory (because symbol is used elsewhere)
  !  Change the input image LUT according to the current status of
  ! 'lut_static' flag
  !---------------------------------------------------------------------
  type(gt_segment_head), intent(in) :: head   ! Segment header
  type(gt_image)                    :: image  ! Image instance
  !
  image%lut => head%lut  ! Which can be null()
  !
end subroutine change_image_lut
!
subroutine change_poly_penlut(head,poly)
  use gtv_interfaces, except_this=>change_poly_penlut
  use gtv_plot
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private-mandatory (because symbol is used elsewhere)
  !  Change the input polyline/polygon PENLUT according to the current
  ! status of 'lut_static' flag
  !---------------------------------------------------------------------
  type(gt_segment_head), intent(in) :: head  ! Segment header
  type(gt_polyline)                 :: poly  ! Polyline instance
  !
  poly%penlut => head%lut  ! Which can be null()
  !
end subroutine change_poly_penlut
