subroutine sicsay (line,nline,error)
  use gildas_def
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sicsay
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ private
  ! SIC   Support routine for command SAY
  !       SAY 'Expression' "String" 'Character_variable' ...
  !  [opt 1]     /FORMAT  a10 i2 f5.2 ...
  !---------------------------------------------------------------------
  character(len=*)                :: line   !
  integer                         :: nline  !
  logical,          intent(inout) :: error  !
  ! Global
  include 'gbl_memory.inc'
  ! Local
  character(len=*), parameter :: rname='SAY'
  ! Note: ARGUM must have at least a length equal to TEXTLENGTH parameter
  ! in 'gwidget.h' .
  character(len=1024) :: argum,chain,string
  integer :: nleft,nchara,nfirst,nremain,iarg,narg,curwidth,lstring
  integer(kind=address_length) :: ia,ja
  character(len=message_length) :: mess
  logical :: noadvance
  !
  if (siclun.eq.0) then
    curwidth = sic_ttyncol()
  else
    curwidth = len(chain)
  endif
  !
  noadvance = sic_present(2,0)
  !
  ! /FORMAT Option
  if (sic_present(1,0)) then
    narg = sic_narg(0)
    nfirst = 1
    do iarg=1,narg
      !
      call say_format_arg(line,iarg,iarg,string,lstring,error)
      if (error) return
      !
      argum(nfirst:) = string(:lstring)
      nfirst = nfirst+lstring
    enddo
    !
    ! Check for widget creation
    if (lxwindow) then
      if (nfirst.eq.1) then
        call xgag_separator (noptscr)
      else
        ia = locstr(argum)
        ja = bytpnt(ia,membyt)
        call xgag_show (membyt(ja),nfirst-1,noptscr)
      endif
    else
      if (siclun.ne.0) then
        if (noadvance) then
          if (nfirst.gt.1) write(siclun,101,advance='NO') argum(1:nfirst-1)
        else
          write(siclun,101) argum(1:nfirst-1)
        endif
      else
        write(6,100) argum(1:nfirst-1)
      endif
    endif
  else
    !
    ! Automatic format
    if (lxwindow) then
      curwidth = len(chain)
    endif
    nleft = curwidth           ! Pas 0
    nfirst = 0
    narg = sic_narg(0)
    do iarg=1,narg
      call sic_ch (line,0,iarg,argum,nchara,.true.,error)
      if (error) then
        write(mess,'(A,I0)')  'Could not read argument #',iarg
        call sic_message(seve%e,rname,mess)
        return
      endif
      if (nchara.le.nleft) then
        chain (nfirst+1:) = argum(1:nchara)
        nleft = nleft-nchara-1
        nfirst = nfirst+nchara+1
      else
        if (nfirst.gt.0) then
          if (siclun.ne.0) then
            write(siclun,101) chain(1:nfirst-1)  ! Drop last blank
          else
            write(6,100) chain(1:nfirst-1)  ! Drop last blank
          endif
        endif
        nfirst = 0
        nremain = nchara
        do while (nfirst.lt.nchara)
          if (nremain.le.curwidth) then
            chain = argum(nfirst+1:nchara)
            nleft = curwidth-nremain-1
            nfirst = nchara+2
          else
            !
            if (lxwindow) then
              argum(nfirst+curwidth+1:nfirst+curwidth+1) = char(0)
              ia = locstr(argum)
              ja = bytpnt(ia,membyt)+nfirst
              call xgag_show (membyt(ja),curwidth,noptscr)
            else
              if (siclun.ne.0) then
                write(siclun,101) argum(nfirst+1:nfirst+curwidth)
              else
                write(6,100) argum(nfirst+1:nfirst+curwidth)
              endif
              nfirst = nfirst+curwidth
              nremain = nremain-curwidth
            endif
          endif
        enddo
      endif
    enddo
    !
    ! Check for widget creation
    if (nfirst.gt.0) then
      if (lxwindow) then
        nfirst = len_trim(argum)
        if (nfirst.gt.0) then
          nfirst = nfirst+1
          argum(nfirst:nfirst) = char(0)
          ia = locstr(argum)
          ja = bytpnt(ia,membyt)
          call xgag_show (membyt(ja),nfirst,noptscr)
        else
          call xgag_separator(noptscr)
        endif
      else
        if (siclun.ne.0) then
          write(siclun,101) chain(1:nfirst-1)  ! Drop last blank
        else
          write(6,100) chain(1:nfirst-1)  ! Drop last blank
        endif
      endif
    elseif (lxwindow) then
      call xgag_separator(noptscr)
    endif
  endif
  !
100 format(20(a))
101 format(a)
end subroutine sicsay
!
subroutine sicmsg(line)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>sicmsg
  use sic_interactions
  use sic_structures
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  character(len=*) :: line          !
  ! Local
  integer :: nl,nt,n1,tt_width
  !
  if (sic_quiet) return
  !
  tt_width = sic_ttyncol()
  nl = len_trim(line)
  n1 = 1
  nt = nl
  do while (n1.le.nl)
    if (nt.le.tt_width) then
      write(6,100) line(n1:nl)
      return
    else
      write(6,100) line(n1:n1+tt_width-1)
      n1 = n1+tt_width
      nt = nt-tt_width
    endif
  enddo
  !
100 format(20(a))
end subroutine sicmsg
!
subroutine say_format_arg(line,iarg,iform,fmtd_string,lstring,error)
  use sic_dependencies_interfaces
  use gildas_def
  use gbl_format
  use gbl_message
  use sic_interactions
  use sic_interfaces, except_this=>say_format_arg
  use sic_types
  !---------------------------------------------------------------------
  ! @private
  ! From input line, format the iarg-th argument of the command
  ! according to the iform-th format of the option /FORMAT. Formatted
  ! string is returned in fmtd_string, and its usefull length is lstring.
  ! Warnings!
  !  1) /FORMAT option must be the 1st option of the calling command
  !  2) In return, fmtd_string(1:lstring) != fmtd_string
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line         ! Line to analyze
  integer,          intent(in)    :: iarg         ! The arg number to analyze
  integer,          intent(in)    :: iform        ! The format number to be used
  character(len=*), intent(out)   :: fmtd_string  ! Output string
  integer,          intent(out)   :: lstring      ! Output string usefull length
  logical,          intent(inout) :: error        ! Error status
  ! Global
  include 'gbl_memory.inc'
  ! Local
  character(len=*), parameter :: rname='/FORMAT'
  character(len=512) :: forma,arg
  integer :: lforma,larg,arg_start,arg_end,ier
  integer(kind=size_length) :: nelem
  integer(kind=address_length) :: ia
  type(sic_descriptor_t) :: adesc
  logical :: found
  ! Arguments
  logical :: l
  integer(kind=8) :: n
  real(kind=8) :: r
  !
  fmtd_string = ''
  lstring = 0
  !
  ! Get the desired format
  call sic_ke(line,1,iform,forma(2:),lforma,.true.,error)
  if (error) return
  forma(1:1) =  '('
  !
  ! A "?" will always be appended. It allows to keep the desired length of
  ! string variables even if they are ended with blanks, e.g.
  ! SIC> SAY "Hello   "  1  /FORMAT A8 F4.2
  ! will preserve the 3 blanks. This terminating "?" is dropped off before
  ! returning the current routine.
  forma(lforma+2:lforma+4) = ',A)'
  lforma = lforma+4
  !
  ! Character strings
  if (forma(2:2).eq.'A') then  ! Format (A...)
    ! NB: character arrays not supported
    call sic_ch(line,0,iarg,arg,larg,.true.,error)
    ! Check if argument is a plain variable name
    arg_start = sic_start(0,iarg)
    arg_end   = sic_end(0,iarg)
    if (arg(1:larg).eq.line(arg_start:arg_end)) then
      call sic_descriptor(arg,adesc,found)
      if (found) then
        call destoc(adesc%type,adesc%addr,arg)
        larg = len_trim(arg)
      endif
    endif
    write(fmtd_string,forma(1:lforma),iostat=ier) arg(1:larg),'?'
  !
  ! Something not character
  else
    !
    ! Test for arrays
    call sic_ch(line,0,iarg,arg,larg,.true.,error)
    call sic_descriptor(arg,adesc,found)
    if (found) then
      ! Ok, a variable is found
      nelem = desc_nelem(adesc)
    else
      nelem = 1
    endif
    !
    ! This is an array
    if (nelem.gt.1) then
      ia = gag_pointer(adesc%addr,memory)
      lforma=lforma-2  ! Do not use the terminating "?" mechanism
      forma(lforma:lforma) =')'
      if (adesc%type.eq.fmt_r4) then
        call say_array_r4(memory(ia),nelem,forma(1:lforma),siclun,error)
      elseif (adesc%type.eq.fmt_r8) then
        call say_array_r8(memory(ia),nelem,forma(1:lforma),siclun,error)
      elseif (adesc%type.eq.fmt_i4) then
        call say_array_i4(memory(ia),nelem,forma(1:lforma),siclun,error)
      elseif (adesc%type.eq.fmt_i8) then
        call say_array_i8(memory(ia),nelem,forma(1:lforma),siclun,error)
      elseif (adesc%type.eq.fmt_l) then
        call say_array_l4(memory(ia),nelem,forma(1:lforma),siclun,error)
      else
        call sic_message(seve%e,rname,  &
          'Array printout not supported for that type')
        error = .true.
      endif
      return
    endif
    !
    ! Simple scalars
    if (index(forma,'I').ne.0) then
      call sic_i8 (line,0,iarg,n,.true.,error)
      if (.not.error) write(fmtd_string,forma(1:lforma),iostat=ier) n,'?'
    elseif (index(forma,'L').ne.0) then
      call sic_l4 (line,0,iarg,l,.true.,error)
      if (.not.error) write(fmtd_string,forma(1:lforma),iostat=ier) l,'?'
    else
      call sic_r8 (line,0,iarg,r,.true.,error)
      if (.not.error) write(fmtd_string,forma(1:lforma),iostat=ier) r,'?'
    endif
    !
    if (error) then
      call sic_message(seve%e,rname,'Format/Variable type mismatch')
      return
    endif
  endif
  !
  ! Format error
  if (ier.ne.0) then
    call sic_message(seve%e,rname,'Invalid format '//forma(2:lforma-5))
    error  = .true.
    return
  endif
  !
  ! Drop the last "?"
  lstring = len_trim(fmtd_string)-1
  !
end subroutine say_format_arg
!
subroutine say_array_r4 (array,na,form,lun,error)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length) :: na   !
  real(4) :: array(na)              !
  character(len=*) :: form          !
  integer :: lun                    !
  logical :: error                  !
  ! Local
  integer :: mylun,ier
  !
  mylun = lun
  if (lun.eq.0) mylun = 6
  if (form.ne.'(*)') then
    write(mylun,form,iostat=ier) array
  else
    write(mylun,*,iostat=ier) array
  endif
  !
  if (ier.ne.0) then
    write (*,'(A)') form
    call putios('E-SAY ',ier)
    error = .true.
  else
    error = .false.
  endif
end subroutine say_array_r4
!
subroutine say_array_r8 (array,na,form,lun,error)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length) :: na   !
  real(8) :: array(na)              !
  character(len=*) :: form          !
  integer :: lun                    !
  logical :: error                  !
  ! Local
  integer :: mylun,ier
  !
  mylun = lun
  if (lun.eq.0) mylun = 6
  if (form.ne.'(*)') then
    write(mylun,form,iostat=ier) array
  else
    write(mylun,*,iostat=ier) array
  endif
  !
  if (ier.ne.0) then
    write (*,'(A)') form
    call putios('E-SAY ',ier)
    error = .true.
  else
    error = .false.
  endif
end subroutine say_array_r8
!
subroutine say_array_i4 (array,na,form,lun,error)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length) :: na   !
  integer(4) :: array(na)           !
  character(len=*) :: form          !
  integer :: lun                    !
  logical :: error                  !
  ! Local
  integer :: mylun,ier
  !
  mylun = lun
  if (lun.eq.0) mylun = 6
  if (form.ne.'(*)') then
    write(mylun,form,iostat=ier) array
  else
    write(mylun,*,iostat=ier) array
  endif
  !
  if (ier.ne.0) then
    write (*,'(A)') form
    call putios('E-SAY ',ier)
    error = .true.
  else
    error = .false.
  endif
end subroutine say_array_i4
!
subroutine say_array_i8 (array,na,form,lun,error)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length) :: na   !
  integer(8) :: array(na)           !
  character(len=*) :: form          !
  integer :: lun                    !
  logical :: error                  !
  ! Local
  integer :: mylun,ier
  !
  mylun = lun
  if (lun.eq.0) mylun = 6
  if (form.ne.'(*)') then
    write(mylun,form,iostat=ier) array
  else
    write(mylun,*,iostat=ier) array
  endif
  !
  if (ier.ne.0) then
    write (*,'(A)') form
    call putios('E-SAY ',ier)
    error = .true.
  else
    error = .false.
  endif
end subroutine say_array_i8
!
subroutine say_array_l4(array,na,form,lun,error)
  use sic_dependencies_interfaces
  use sic_interfaces
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  !---------------------------------------------------------------------
  integer(kind=size_length), intent(in) :: na   ! Number of elements in array
  logical,          intent(in)    :: array(na)  ! Array which will be displayed
  character(len=*), intent(in)    :: form       ! Format to be used
  integer,          intent(in)    :: lun        ! Send output to this logical unit
  logical,          intent(inout) :: error      ! Error flag
  ! Local
  integer :: mylun,ier
  !
  mylun = lun
  if (lun.eq.0) mylun = 6
  if (form.ne.'(*)') then
    write(mylun,form,iostat=ier) array
  else
    write(mylun,*,iostat=ier) array
  endif
  !
  if (ier.ne.0) then
    write (*,'(A)') form
    call putios('E-SAY ',ier)
    error = .true.
  endif
end subroutine say_array_l4
