subroutine cd_by_name(argum,active,win_num,error)
  use gildas_def
  use gtv_buffers
  use gtv_protocol
  use gtv_interfaces, except_this=>cd_by_name
  use gtv_tree
  use gtv_types
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  !  Effectively move to the explicit directory named ARGUM, and on the
  ! specified window number if any.
  !  Warning: the window number is the number as seen by user!
  ! ---
  !  Thread status: thread safe for reading/writing from main.
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: argum    ! Directory name to go to
  logical,          intent(in)    :: active   ! Use the active window?
  integer(kind=4),  intent(inout) :: win_num  ! Else, window number to use
  logical,          intent(inout) :: error    ! Error flag
  ! Local
  character(len=*), parameter :: rname='CD'
  logical :: dir,found
  integer :: win_num_c
  type(gt_segment), pointer :: segm
  type(gt_directory), pointer :: dir_new
  !
  ! Note philosophique
  ! ------------------
  ! Il y a un probleme de M.A.J. de la couleur courante sur CD
  ! Manifestation: Avec les fenetres blanches et noires, la plume change mal
  ! parfois ... Je LAISSE ce probleme en suspens, jusqu'a ce que les attributs
  ! du repertoire contiennent toutes les caracteristiques (Plot page, limites ..
  ! et je pense aussi plume courante. (Cette p.. de plume courante me fait
  ! bien marcher - A mon age, on ne court plus-)
  !
  if (argum.eq.' ') then
    ! Input is empty: return to root '<'
    dir_new => root
    !
  else
    !
    ! Input is a standard directory
    call decode_chemin(argum,cw_directory,dir_new,dir,segm,found)
    !
    ! Not found?
    if (.not. (found.and.dir)) then
      error = .true.
      call gtv_message(seve%e,rname,'No such directory '//argum)
      return
    endif
    !
    ! Root?
    if (associated(dir_new,root)) then
      error = .true.
      call gtv_message(seve%e,rname,'Root directory - permission denied')
      return
    endif
    !
  endif
  !
  call gtv_open_segments_for_writing_from_main()
  !
  if (active) then
    ! Use the active window
    win_num_c = dir_new%x%curwin
  else
    ! Translate the window number into its internal value
    win_num_c = get_window_cnum(dir_new,win_num,error)
  endif
  !
  call cd_by_adr(dir_new,win_num_c,error)
  !
  call gtv_close_segments_for_writing_from_main()
  !
end subroutine cd_by_name
!
subroutine cd_by_adr(dir_new,win_num,error)
  use gtv_interfaces, except_this=>cd_by_adr
  use gtv_buffers
  use gtv_graphic
  use gtv_protocol
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !  Effectively move to the directory identified by DIR_NEW, and on the
  ! specified window number if any.
  !  Warning: the window number is the internal number!
  ! ---
  !  Thread status: not thread safe. Calling routine must be thread
  ! safe for writing (because the active window can be changed).
  !---------------------------------------------------------------------
  type(gt_directory), pointer       :: dir_new  ! Directory to move to
  integer*4,          intent(inout) :: win_num  ! Can be adjusted on return
  logical,            intent(inout) :: error    ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='CD'
  type(greg_values) :: tab_greg
  integer :: nc
  !
  if (error)  return
  !
  ! Update extrema of the Pere
  if (associated(cw_directory%father)) then
    ! We are not in root
    call dir_extrema(cw_directory%father,cw_directory%gen%minmax)
  endif
  !
  ! Sauvegarde du contexte courant
  if (flag_greg) then
    call get_greg_values(tab_greg)
    call attach_greg_values(cw_directory,tab_greg,error)
    if (error)  return
  endif
  !
  if (associated(cw_directory,dir_new)) then
    ! New dir is old dir
    if (win_num.eq.cw_directory%x%curwin) return  ! Nothing to do
  else
    cw_directory => dir_new
  endif
  call cree_chemin_dir(cw_directory,pwd,nc)
  !
  ! Restauration "a priori" des constantes de Greg
  if (flag_greg)  &
    call send_greg_values(cw_directory%val_greg)
  !
  ! Change to input window
  call cd_by_win(cw_directory,win_num,error)
  if (error)  return
  !
end subroutine cd_by_adr
!
subroutine cd_by_win(dir,win_num_in,error)
  use gildas_def
  use gbl_message
  use gtv_buffers
  use gtv_interfaces, except_this=>cd_by_win
  use gtv_protocol
  use gtv_types
  !---------------------------------------------------------------------
  ! @ private
  !   Change the active window of the input directory.
  !  Warning: the window number is the internal number!
  ! ---
  !  Thread status: not thread safe. Calling routine must be thread
  ! safe for writing (because the active window can be changed).
  !---------------------------------------------------------------------
  type(gt_directory)             :: dir         ! Directory to work on
  integer(kind=4), intent(in)    :: win_num_in  ! Window to move to
  logical,         intent(inout) :: error       ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='CD'
  integer :: win_num
  integer(kind=address_length) :: graph_env
  logical :: found
  !
  if (error)  return
  !
  if (dir%x%nbwin.eq.0) then
    ! No windows attached
    call gt_output_reset(null_output)
    null_output%dev => cw_device  ! Use current protocol
    cw_output => null_output
    return
  endif
  !
  ! Basic check.
  win_num = win_num_in
  if ( win_num.lt.0 .or. (win_num.ne.0 .and. win_num.ge.dir%x%nbwin) ) then
    call gtv_message(seve%w,'CD','Invalid window number - using first window')
    win_num = 0
  endif
  !
  ! Get the address of the table of genv addresses for this directory
  if (dir%x%genv_array.eq.0) then
    call gtv_message(seve%e,rname,  &
      'Internal error: no graphical environments found')
    error = .true.
    return
  endif
  !
  ! Get the current graphical environment from the table (indexed by window num)
  graph_env = c_get_win_genv(dir%x%genv_array,win_num)
  !
  if (graph_env.eq.-1) then
    call gtv_message(seve%e,rname,'No valid Graphic Environment')
    error=.true.
    return
    !
  elseif (graph_env.eq.0) then
    if (win_num.ne.0) then
      call gtv_message(seve%e,rname,'Invalid window number')
      error=.true.
      return
    endif
    !
  else
    ! Store the address of the environment in the directory descriptor.
    dir%x%genv = graph_env
    !
    ! Update the Current Working Instance
    call get_slot_output_by_genv(graph_env,cw_output,.true.,found,error)
    if (error)  return
    !
  endif
  !
  ! Update the value of the current window for this directory
  dir%x%curwin = win_num
  !
end subroutine cd_by_win
!
function gtexist(name)
  use gtv_buffers
  use gtv_interfaces, except_this=>gtexist
  use gtv_types
  !---------------------------------------------------------------------
  ! @ public
  ! Logical function indicating wether a segment/directory exists
  !---------------------------------------------------------------------
  logical :: gtexist                    ! Function value on return
  character(len=*), intent(in) :: name  ! Name to search for
  ! Local
  logical :: isdir,found
  type(gt_segment), pointer :: segm
  type(gt_directory), pointer :: dir
  !
  call decode_chemin(name,cw_directory,dir,isdir,segm,found)
  gtexist = found
end function gtexist
