subroutine xgag_input(line,error)
  use sic_structures
  use sic_dictionaries
  use sic_interactions
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>xgag_input
  !---------------------------------------------------------------------
  ! @ private
  ! GUI\PANEL "Title" HELP_FILE [/CLOSE] [/DETACH]
  !---------------------------------------------------------------------
  character(len=*), intent(in)  :: line   !
  logical,          intent(out) :: error  !
  ! Local
  ! Lengths of TITLE must be equal to TITLELENGTH and
  ! HLPFILELNGTH defined in structure.h to avoid problems. JP
  character(len=256) :: title
  character(len=256) :: helptxt,helpsav
  integer(kind=4) :: nd,nt,i,ier
  integer(kind=4) :: code
  ! Code = 0: non-permanent, 1: permanent
  !
  save helpsav
  !
  error = .false.
  !
  if (sic_present(1,0)) then
    ! /CLOSE
    ! delete the last detached menu or the specified one.
    if (sic_present(0,1)) then
      call sic_ch(line,0,1,helptxt,nt,.true.,error)
      if (error) return
      call sic_parse_file(helptxt,'GAG_PROC:','.hlp',helptxt)
      nt = len_trim(helptxt)
      nt = nt+1
      helptxt(nt:nt) = char(0)
    else
      helptxt = helpsav
    endif
    call xgag_end_detach(helptxt)
  else
    call sic_ch(line,0,1,title,nd,.true.,error)
    if (error) return
    call sic_ch(line,0,2,helptxt,nt,.true.,error)
    if (error) return
    call sic_parse_file(helptxt,'GAG_PROC:','.hlp',helptxt)
    nt = len_trim(helptxt)
    nt = nt+1
    helptxt(nt:nt) = char(0)
    nd = nd+1
    title(nd:nd) = char(0)
    !
    lxwindow = .true.
    !
    if (sic_present(2,0)) then
      ! /DETACH: Create a new menubar & remember the help file name.
      call xgag_detach(title,helptxt)
      helpsav = helptxt
      x_mode = 1
    else
      !
      ! Main dialog window
      x_mode =0
      code = 0
      call xgag_open(title,helptxt,code)
      do i=x_commands,1,-1
        call free_vm(x_cmdlen/4,x_string(2,i))
        call free_vm(varname_length/4,x_variab(2,i))
      enddo
      x_commands = 0
      noptscr = 0
      ! Declare the subroutine which will build the help texts
      call xgag_set_callback_help(help_button)
      !
      ! /LOG option is used for TASK language
      if (sic_present(3,0)) then
        call sic_ch(line,3,1,helptxt,nt,.true.,error)
        if (error) return
        ier = sic_getlun(xlun)
        call sic_parse_file(helptxt,' ','.save',helptxt)
        nt = len_trim(helptxt)
        open (unit=xlun,file=helptxt(1:nt),status='UNKNOWN')
        rewind(unit=xlun)
      else
        xlun = 0
      endif
      !
      if (code.eq.-1) then
        call sic_message(seve%e,'XINPUT','Cannot launch X-Window mode')
        lxwindow = .false.
        error = .true.
      endif
    endif
  endif
end subroutine xgag_input
!
subroutine xgag_menus(line,error)
  use sic_dependencies_interfaces
  use sic_interactions
  use sic_interfaces, except_this=>xgag_menus
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! GUI\MENU "Title"
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   !
  logical,          intent(inout) :: error  !
  ! Local
  character(len=*), parameter :: rname='SIC'
  integer(kind=4) :: nd
  character(len=32) :: command
  !
  if (x_mode.eq.0) then
    if (.not.lxwindow) then
      call sic_message(seve%e,rname,'X-Window mode not active')
      error = .true.
      return
    endif
    if (sic_present(1,0)) then
      ! /CLOSE option
      if (x_group.eq.0) then
        call sic_message(seve%e,rname,'No current group')
        error = .true.
        return
      endif
      call xgag_end_group
      x_group = 0
    elseif (sic_present(2,0)) then
      ! /CHOICES option
      call sic_ch(line,0,1,command,nd,.true.,error)
      if (error) return
      nd = nd+1
      command(nd:nd) = char(0)
      if (x_group.eq.1) call xgag_end_group
      call xgag_begin_group(command)
      x_group = 1
    else
      call sic_message(seve%e,rname,'Command invalid in this context')
      error = .true.
      return
    endif
  elseif (sic_present(1,0)) then
    ! /CLOSE option
    if (x_mode.eq.1) return
    call xgag_endmenu
    x_mode = 1                 ! Plus de menu
  else
    call sic_ch(line,0,1,command,nd,.true.,error)
    if (error) return
    nd = nd+1
    command(nd:nd) = char(0)
    if (x_mode.eq.3) then
      call xgag_endmenu
      call xgag_menu(command)
      x_mode = 2
    elseif (x_mode.ne.2) then
      call xgag_menu(command)
      x_mode = 2               ! Menu cree
    endif
  endif
  !
end subroutine xgag_menus
!
subroutine xgag_submenu(line,error)
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>xgag_submenu
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ private
  ! GUI\SUBMENU "Title"
  !   1      [/CLOSE]
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   !
  logical,          intent(inout) :: error  !
  ! Local
  character(len=*), parameter :: rname='SIC'
  integer(kind=4) :: nd
  character(len=32) :: command
  !
  if (.not.lxwindow) then
    call sic_message(seve%e,'SIC','X-Window mode not active')
    error = .true.
    return
  endif
  !
  if (sic_present(1,0)) then
    ! /CLOSE option
    if (x_mode.eq.1) return
    call xgag_endmenu
  else
    call sic_ch(line,0,1,command,nd,.true.,error)
    if (error) return
    nd = nd+1
    nd = min(nd,len(command))  ! Avoid overflow
    command(nd:nd) = char(0)
    call xgag_menu(command)
  endif
  !
end subroutine xgag_submenu
!
subroutine xgag_uri(line,error)
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>xgag_uri
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ private
  ! GUI\URI Uri Label
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   !
  logical,          intent(inout) :: error  !
  ! Local
  character(len=filename_length) :: uri,trans
  character(len=64) :: label
  integer(kind=4) :: nd,nb
  !
  if (.not.lxwindow) then
    call sic_message(seve%e,'SIC','X-Window mode not active')
    error = .true.
    return
  endif
  !
  ! 1) Get the URI
  call sic_ch(line,0,1,uri,nd,.true.,error)
  if (error)  return
  call sic_parse_file(uri,'','',trans)
  nd = len_trim(trans)+1
  trans(nd:nd) = char(0)
  !
  ! 2) Get the menu label
  call sic_ch(line,0,2,label,nb,.true.,error)
  if (error)  return
  nb = nb+1
  label(nb:nb) = char(0)
  !
  ! 3) Display
  call xgag_uri_menu (label,trans)
  if (x_mode.gt.1) x_mode = 3    ! Menu non-vide
  !
end subroutine xgag_uri
!
subroutine xgag_comm(line,error)
  use sic_dependencies_interfaces
  use sic_interactions
  use sic_interfaces, except_this=>xgag_comm
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! GUI\BUTTON Command Bouton [Title Help_file [Option_Title]]
  !---------------------------------------------------------------------
  character(len=*), intent(in)  :: line   !
  logical,          intent(out) :: error  !
  ! Local
  character(len=256) :: command,bouton,helptxt,texte,option
  integer(kind=4) :: nd,nb,nt,nh,no
  !
  if (.not.lxwindow) then
    call sic_message(seve%e,'SIC','X-Window mode not active')
    error = .true.
    return
  endif
  error = .false.
  !
  call sic_ch(line,0,1,command,nd,.true.,error)
  if (command.ne.'*') then
    bouton = command
    nd = nd+1
    command(nd:nd) = char(0)
  else
    command = ' '
    nd = 0
  endif
  !
  call sic_ch(line,0,2,bouton,nb,.false.,error)
  nb = len_trim(bouton)+1
  bouton(nb:nb) = char(0)
  !
  ! /DETACH mode
  if (x_mode.ne.0) then
    call xgag_command (bouton,command)
    if (x_mode.gt.1) x_mode = 3    ! Menu non-vide
    return
  endif
  !
  ! Normal mode
  if (sic_present(0,3)) then
    call sic_ch(line,0,3,texte,nt,.false.,error)
  else
    texte = char(0)
    nt = 0
  endif
  !
  if (sic_present(0,4)) then
    call sic_ch(line,0,4,helptxt,nh,.false.,error)
    if (sic_query_file(helptxt,'TASK#DIR:','.hlp',helptxt)) then
    else
      call sic_parse_file(helptxt,'GAG_PROC:','.hlp',helptxt)
    endif
    nh = len_trim(helptxt)
    nh = nh+1
    helptxt(nh:nh) = char(0)
  else
    helptxt = char(0)
  endif
  !
  if (sic_present(0,5)) then
    call sic_ch(line,0,5,option,no,.false.,error)
    no = no+1
    option(no:no) = char(0)
    noptscr = noptscr+1        ! One more optional screen
  else
    option = char(0)
    nt = 0
  endif
  !
  call xgag_button (bouton,command,texte,nt,helptxt,option)
  !
end subroutine xgag_comm
!
subroutine xgag_more(bouton,command,texte,option)
  use sic_interfaces, except_this=>xgag_more
  use sic_dependencies_interfaces
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ private
  ! Support for command
  !   TASK\MORE
  ! Create a sub-menu in the TASK\ Window interface
  !---------------------------------------------------------------------
  character(len=*) :: bouton        !
  character(len=*) :: command       !
  character(len=*) :: texte         !
  character(len=*) :: option        !
  ! Local
  integer :: nt
  !
  noptscr = noptscr+1
  nt = len_trim(texte)
  !
  call xgag_button (bouton,command,texte,nt,help_text_file,option)
end subroutine xgag_more
!
subroutine xgag_variable(line,nline,error)
  use gildas_def
  use gbl_format
  use gbl_message
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>xgag_variable
  use sic_dictionaries
  use sic_interactions
  use sic_structures
  use sic_types
  use let_options
  !---------------------------------------------------------------------
  ! @ private
  ! This routine fills in the widget structure that will be exchanged
  ! between the SIC-using Program and the standalone Widget Panel. The
  ! structures are defined in sic_structures.h and constructed by the C
  ! routines of sic_xgag.c
  ! The standalone widget panels define mirror structures (their C code
  ! include sic_structures.h). They communicate with SIC by setting the
  ! SIGUSER2 signal. The structure contents are exchanged via a shared
  ! memory segment, whose address is passed by xgag_dialog. The
  ! following FORTRAN code merely allocate room for strings containing
  ! variable names, prompts, options... as read on the command line. It
  ! calls then the C function to fill the C structures. Once passed to
  ! the C code, the memory allocated by the FORTRAN can be freed.
  ! REMARKS:
  ! There should not be any "null-terminated" character chain in the
  ! following FORTRAN code. All the pointers to Strings passed to the
  ! routines in sic_xgag.c should concern well-defined character arrays,
  ! of length known by the sic_xgag routines (varname_length for
  ! VARIABLES NAMES for example). It is up to the C interface routines
  ! of sic-xgag.c (and easier, too) to convert fixed-length arrays to
  ! null-terminated strings in the widgets's structure, BACK AND FORTH!
  !---------------------------------------------------------------------
  !     LET Variable [Pre_loaded_value]
  !     [/NEW Type [Attr]]                         Invalid here
  !     [/PROMPT "Prompt text"]
  !     [/WHERE Logical_Expression]                Invalid here
  !     [/RANGE Min Max]
  !     [/CHOICE C1 .. CN [*]]
  !     [/FILE Filter ]
  !     [/INDEX C1 .. CN]
  !     [/SEXAGESIMAL]                             Invalid here ?
  !     [/LOWER]
  !     [/UPPER]
  !     [/FORMAT String]                           Invalid here
  !     [/NOQUOTE]                                 For VALUES in Widget modes
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   !
  integer(kind=4),  intent(in)    :: nline  !
  logical,          intent(inout) :: error  !
  ! Global
  include 'gbl_memory.inc'
  ! Local
  logical :: upper,lower,noquote
  integer(kind=address_length) :: addr,addr1,addr2,ipx
  type(sic_descriptor_t) :: descr
  integer(kind=index_length) :: ichoi,j
  integer(kind=4) :: ii
  logical :: found
  character(len=x_cmdlen) :: chain,argum,filter
  character(len=varname_length) :: varia,svaria
  type(sic_identifier_t) :: var
  integer(kind=4) :: ier,i,nc,nx,na,nf,nv,vtype,in
  real(kind=8) :: rmin,rmax,dbl
  logical :: reado,goon,logi,resize
  !
  ! No option ==> No X-Window mode...
  goon = sic_present(optprompt,0) .or.  &
         sic_present(optrange,0) .or.  &
         sic_present(optchoice,0) .or.  &
         sic_present(optfile,0) .or.  &
         sic_present(optindex,0)
  if (.not.goon) then
    call let_variable(line,nline,error)
    return
  elseif (x_mode.gt.0) then
    call sic_message(seve%e,'SIC','Command invalid in this context')
    error = .true.
    return
  endif
  !
  ! On pourrait re-allouer, mais pour un test...
  if (x_commands.gt.m_commands) then
    call sic_message(seve%e,'SIC','Too many commands in X-Window mode')
    error = .true.
    return
  endif
  !
  noquote = sic_present(optnoquote,0)
  upper = sic_present(optupper,0)
  lower = sic_present(optlower,0)
  resize = sic_present(optresize,0)
  !
  if (upper.and.lower .or. upper.and.noquote .or. lower.and.noquote) then
    call sic_message(seve%e,'SIC','Conflicting options')
    error = .true.
    return
  endif
  !
  ! Variable name
  chain = ' '
  call sic_ke(line,0,1,chain,nc,.true.,error)
  if (error) return
  call sic_vtype(chain(1:nc),vtype,reado,error)
  if (error) then
    call sic_message(seve%e,'LET','Variable '//chain(1:nc)//' does not exists')
    return
  elseif (reado) then
    call sic_message(seve%e,'LET','Variable '//chain(1:nc)//' cannot be '//  &
    'modified')
    error = .true.
    return
  endif
  if (vtype.lt.0 .and. (upper.or.lower)) then
    call sic_message(seve%e,'SIC','Invalid option in this context')
    error = .true.
    return
  endif
  !
  ! Remember its short name
  varia = chain
  nv = index(varia,'[')
  if (nv.ne.0) then
    svaria = varia(1:nv-1)
  else
    svaria = varia
  endif
  !
  ! Old code
  !      VARIA = SVARIA
  !
  ! Allocate a character string area to store variable name (size
  ! varname_length) and UserChain (size X_CMDLEN chars)
  ier = sic_getvm(varname_length/4,addr1)
  if (ier.ne.1) then
    call sic_message(seve%e,'LET','Memory allocation failure')
    error = .true.
    return
  endif
  ier = sic_getvm(x_cmdlen/4,addr2)
  if (ier.ne.1) then
    call sic_message(seve%e,'LET','Memory allocation failure')
    error = .true.
    return
  endif
  ! Add these to the Common describing the list of variables
  ! seen by the panel:
  x_commands = x_commands+1
  x_variab(1,x_commands) = varname_length
  x_variab(2,x_commands) = addr1
  x_string(1,x_commands) = x_cmdlen
  x_string(2,x_commands) = addr2
  x_vtypes(x_commands) = vtype
  !
  ! Set the "X-Window mode" modifier in the variable status, and
  ! add the variable number to the list of X-Window variables.
  !
  var%name = svaria
  var%lname = len_trim(svaria)
  var%level = var_level
  ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,var,in)
  if (ier.ne.1 .and. var_level.ne.0) then
    var%level = 0
    ier = sic_hasfin(maxvar,pfvar,pnvar,dicvar,var,in)
  endif
  x_number(x_commands) = in
  !
  ! Variable name...
  nc = x_variab(1,x_commands)
  addr = x_variab(2,x_commands)
  call ctodes (chain,nc,addr)
  !
  ! Pre-loaded text
  chain = ' '
  argum = ' '
  nc = 0
  do i=2,sic_narg(0)
    call sic_ch(line,0,i,argum,na,.false.,error)
    chain(nc+1:) = argum(1:na)
    nc = nc+na+1
  enddo
  nc = x_string(1,x_commands)
  addr = x_string(2,x_commands)
  call ctodes (chain,nc,addr)
  nx = len_trim(chain)
  !
  ! User prompt (Default = variable name)
  call sic_ch(line,optprompt,1,chain,nc,.false.,error)
  nc = nc+1
  chain(nc:nc) = char(0)
  !
  ! Slider
  if (sic_present(optrange,0)) then
    call sic_r8 (line,optrange,1,rmin,.true.,error)
    call sic_r8 (line,optrange,2,rmax,.true.,error)
    ipx = gag_pointer(x_string(2,x_commands),memory)
    call sic_r8 (line,0,2,dbl,.false.,error)
    call r8tor8(dbl,memory(ipx),1)
    call xgag_slider(varia,chain(1:nc),memory(ipx),rmin,rmax,noptscr)
    x_vtypes(x_commands) = x_vtypes(x_commands)+slider_offset
    !
    ! Choice or Index
  elseif (sic_present(optchoice,0).or.sic_present(optindex,0)) then
    ! Remember if index or choice
    if (sic_present(optchoice,0)) ii=optchoice
    if (sic_present(optindex,0)) ii=optindex
    x_choices=0
    do i=1,sic_narg(ii)
      !     check keyword first; if null, drop it. SIC_ST to preserve double
      !     quotes implying this is not a character variable...
      call sic_st(line,ii,i,chain,nc,.true.,error)
      if (error)  cycle
      if (nc.le.0)  cycle  ! Can this happen?
      !
      ! Test wether this could be a character variable name, possibly
      ! of dim 1. In that case, the list of choices will be made with these
      ! character chains.
      found = .false.
      call sic_descriptor (chain,descr,found)    ! Checked
      if (.not.found) then   ! normal chain
        if (chain(1:1).eq.'"') then  ! Is this test fully correct?
          ! Chain was protected with double-quotes: retrieve it without quotes,
          ! do not modify case
          call sic_ch(line,ii,i,chain,nc,.true.,error)
        else
          ! No protecting quotes: upcase
          call sic_upper(chain)
        endif
        if (error)  cycle
        !     Allocate space for the choice list.
        ier = sic_getvm(x_cholen,addr)   !allocate integers
        if (ier.ne.1) then
          call sic_message(seve%e,'LET /CHOICE','Memory allocation failure')
          error = .true.
          return
        endif
        x_choices = x_choices+1
        x_choice(2,x_choices) = addr
        x_choice(1,x_choices) = x_cholen*4   ! size for chars.
        ! Store the string choices
        call ctodes (chain,x_cholen*4,addr)
        if (x_choices.ge.m_choices) then
          call sic_message(seve%e,'LET /CHOICE','Too Many Choices (at '//  &
          chain(1:nc)//'), truncated')
          goto 10
        endif
      else
        descr%readonly = .false.
        if (descr%type.le.0) then
          ! This is not a character variable.
          ! Use the text contained in CHAIN as the value
          !     Do not printout any warning in this case
          !                     CALL GAGOUT('W-/CHOICE, Array '//
          !     $               CHAIN(1:NC)//' must be of type CHAR to be used.')
          ier = sic_getvm(x_cholen,addr) !allocate integers
          if (ier.ne.1) then
            call sic_message(seve%e,'LET /CHOICE','Memory allocation failure')
            error = .true.
            return
          endif
          x_choices = x_choices+1
          x_choice(2,x_choices) = addr
          x_choice(1,x_choices) = x_cholen*4 ! size for chars.
          call ctodes (chain,x_cholen*4,addr)
          if (x_choices.ge.m_choices) then
            call sic_message(seve%e,'LET /CHOICE','Too Many Choices (at '//  &
            chain(1:nc)//'), truncated')
            goto 10
          endif
        else
          ! This is a character array
          ! Check dimensions (must be 0 or 1)
          if (descr%ndim.gt.1) then
            call sic_message(seve%e,'LET /CHOICE','Character Array '//  &
            chain(1:nc)//' must be of Dimension 0 or 1')
            goto 999
            !
            ! Check length
          elseif (descr%type.gt.x_cholen*4) then
            call sic_message(seve%w,'LET /CHOICE','Elements of '//  &
            chain(1:nc)//' are too long, truncated')
          endif
          !     Number of choices
          ichoi = descr%dims(1)
          if (ichoi.eq.0) ichoi=1
          do j=1,ichoi
            call destoc(descr%type,descr%addr,chain)
            nc=len_trim(chain)
            if (nc.gt.0) then
              !     Allocate space for the choice(s) only if not null
              !     do the job only for valid choices
              ier = sic_getvm(x_cholen,addr) !allocate integers
              if (ier.ne.1) then
                call sic_message(seve%e,'LET /CHOICE','Memory '//  &
                'allocation failure')
                error = .true.
                return
              endif
              x_choices = x_choices+1
              x_choice(2,x_choices) = addr
              x_choice(1,x_choices) = x_cholen*4 ! size for chars.
              call ctodes (chain,x_cholen*4,addr)
              if (x_choices.ge.m_choices) then
                call sic_message(seve%e,'LET /CHOICE','Too Many Choices '//  &
                '(at '//chain(1:nc)//'), end of list ignored')
                goto 10
              endif
            endif
            ! Point to next element of table
            descr%addr = descr%addr+descr%type
          enddo
        endif  ! descr%type < or > 0
      endif  ! found / .not.found
      !
    enddo
    !
10  continue
    if (ii.eq.optchoice) then
      !     The following for /CHOICE option
      if (x_choices.eq.0) then
        !     No choice: just a fixed string, use XGAG_CH
        call sic_ch(line,optprompt,1,chain,nc,.false.,error)
        nc = nc+1
        chain(nc:nc) = char(0)
        nx = x_cmdlen
        ipx = gag_pointer(x_string(2,x_commands),memory)
        call xgag_ch (varia, chain(1:nc),memory(ipx),nx,noptscr,0)  ! Non - Editable
      elseif (chain.eq.'*') then
        !     If last choice is '*' make choice Editable
        call sic_ch(line,optprompt,1,chain,nc,.false.,error)
        nc = nc+1
        chain(nc:nc) = char(0)
        ipx = gag_pointer(x_string(2,x_commands),memory)
        nx = x_cmdlen
        call xgag_choice(varia,chain(1:nc),memory(ipx),nx,x_choice,  &
        (x_choices-1),0,noptscr)     ! hide the "*". 0 Free choice
      else
        !     Non editable
        call sic_ch(line,optprompt,1,chain,nc,.false.,error)
        nc = nc+1
        chain(nc:nc) = char(0)
        ipx = gag_pointer(x_string(2,x_commands),memory)
        nx = x_cmdlen
        call xgag_choice(varia,chain(1:nc),memory(ipx),nx,x_choice,x_choices,  &
        -1,noptscr)    ! -1 Fixed choice
      endif
    else
      ! This for /INDEX
      ! Set String according to Pre-loaded value
      call sic_i4 (line,0,2,i,.false.,error)
      if (i.gt.0 .and. i.le.x_choices) then
        ! Copy the index of the choice in 'x_string' for current 'x_commands'
        write(chain,'(I0)') i
        chain = trim(chain)//char(0)
        nc = x_string(1,x_commands)
        addr = x_string(2,x_commands)
        call ctodes(chain,nc,addr)
      endif
      !
      ! Get the field name (e.g. "Choose in this list:")
      call sic_ch(line,optprompt,1,chain,nc,.false.,error)
      nc = nc+1
      chain(nc:nc) = char(0)
      !
      ipx = gag_pointer(x_string(2,x_commands),memory)
      nx = x_cmdlen
      call xgag_choice(varia,chain(1:nc),memory(ipx),nx,x_choice,x_choices,1,  &
      noptscr)       ! 1 Index
      !
    endif
    !
    ! File
  elseif (sic_present(optfile,0)) then
    call sic_ch(line,optprompt,1,chain,nc,.false.,error)
    nc = nc+1
    chain(nc:nc) = char(0)
    filter = ''
    nf = 0
    call sic_ch(line,optfile,1,filter,nf,.false.,error)
    nf = nf+1
    filter(nf:nf) = char(0)
    ipx = gag_pointer(x_string(2,x_commands),memory)
    nx = x_cmdlen
    call xgag_file(varia,chain(1:nc),memory(ipx),nx,filter(1:nf),noptscr)
    !
    ! Logical
  elseif (vtype.eq.fmt_l) then
    ipx = gag_pointer(x_string(2,x_commands),memory)
    call sic_l4 (line,0,2,logi,.false.,error)
    if (logi) then
      call l4tol4(1,memory(ipx),1)  !  ZZZ should copy 'logi'!
    else
      call l4tol4(0,memory(ipx),1)
    endif
    call xgag_logic (varia,chain(1:nc),memory(ipx),noptscr)
    x_vtypes(x_commands) = x_vtypes(x_commands)+slider_offset
    !
    ! Normal
  else
    ipx = gag_pointer(x_string(2,x_commands),memory)
    nx = x_cmdlen
    call xgag_ch (varia,chain(1:nc),memory(ipx),nx,noptscr,1)  ! Editable
    !
    ! Anything here about /NOQUOTE ?
    if (noquote) then
      x_vtypes(x_commands) = x_vtypes(x_commands)+quote_offset
    elseif (upper) then
      x_vtypes(x_commands) = x_vtypes(x_commands)+upper_offset
    elseif  (lower) then
      x_vtypes(x_commands) = x_vtypes(x_commands)+lower_offset
    elseif (resize) then
      x_vtypes(x_commands) = x_vtypes(x_commands)+resize_offset    
    endif
  endif
  !     If choices have been allocated, purge memory:
999 continue
  do i=x_choices,1,-1
    call free_vm(x_cholen,x_choice(2,i))
  enddo
  x_choices = 0
  !
end subroutine xgag_variable
!
subroutine xgag_go(line,error)
  use sic_interfaces, except_this=>xgag_go
  use sic_dependencies_interfaces
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for commands
  !  GUI\GO  [CommandString]
  !  TASK\GO
  ! End menus (in this case call xgag_launch that activates an xmenu
  ! detached menubar, or activates a Widget panel via the call to
  ! xgag_dialog)
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Input command line
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  integer(kind=4) :: abort,nc
  character(len=256) :: command
  !
  ! /DETACH
  if (x_mode.ne.0) then
    if (x_mode.gt.1) call xgag_endmenu
    error = .false.
    call xgag_launch
    x_mode = 0
    lxwindow = .false.
    return
  endif
  !
  ! XGO already typed ?
  if (.not.lxwindow) return
  !
  lxwindow = .false.
  if (x_commands.eq.0) return
  !
  ! Retrieve the command to be executed when the user will push
  ! the GO button:
  command = ' '
  nc = 0
  call sic_ch (line,0,1,command,nc,.false.,error)
  nc = nc+1
  command(nc:nc) = char(0)
  call xgag_dialog(command,abort)
  !
end subroutine xgag_go
!
subroutine xgag_end(icode,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>xgag_end
  use gildas_def
  use sic_structures
  use sic_interactions
  use sic_dictionaries
  use gbl_message
  use gbl_format
  !---------------------------------------------------------------------
  ! @ private
  ! We come back here after the GO or ABORT button on a xmenu panel
  ! has been pressed.
  ! We write (through unit XLUN) a temporary file to hold
  ! the original commands to re-write the .init file later.
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: icode  ! 0 ABORT=DISMISS, 1 ABORT=Error
  logical,         intent(inout) :: error  !
  ! Global
  include 'gbl_memory.inc'
  ! Local
  character(len=1), parameter :: backslash=char(92)
  character(len=varname_length) :: var
  character(len=x_cmdlen) :: expr
  character(len=x_cmdlen+2) :: string  ! Can contain 'expr' + quotes
  character(len=256) :: par
  character(len=commandline_length) :: chain
  character(len=command_length) :: command
  integer(kind=address_length) :: ipx,addr
  integer(kind=4) :: i,ne,nv,nc,abort,n_commands,inte,lt,lpar,next
  real(kind=8) :: r8
  logical :: slider, resize
  !
  ! Read back the shared memory
  call get_user_input(abort)
  if (abort.eq.-3) then
    n_commands = 0
  else
    n_commands = x_commands
    x_commands = 0
  endif
  !
  do i=1,n_commands
    if (x_vtypes(i).eq.0)  cycle
    !
    var = ' '
    nc = x_variab(1,i)
    addr = x_variab(2,i)
    call destoc(nc,addr,var)
    nv = min(len_trim(var),varname_length)
    expr = ' '
    !
    ! Real, logical, integers, etc...
    resize = .false.
    if (x_vtypes(i).gt.(resize_offset-100)) then
      resize = .true.
      x_vtypes(i) = x_vtypes(i)-resize_offset
    endif
    ! 
    if (x_vtypes(i).gt.(slider_offset-100) .and.  &
        x_vtypes(i).lt.(quote_offset-100)) then
      slider = .true.
      x_vtypes(i) = x_vtypes(i)-slider_offset
      ipx = gag_pointer(x_string(2,i),memory)
      if (x_vtypes(i).eq.fmt_l) then
        ! Logical
        call r4tor4 (memory(ipx),inte,1)
        if (inte.eq.0) then
          expr = 'NO'
          ne = 2
        else
          expr = 'YES'
          ne = 3
        endif
      else
        ! Others
        call r8tor8(memory(ipx),r8,1)
        write(expr,'(1PG23.16)') r8
        ne = len_trim(expr)
        call sic_blanc(expr,ne)
      endif
    else
      slider = .false.
      ! Character strings
      nc = x_string(1,i)
      addr = x_string(2,i)
      call destoc(nc,addr,expr)
      ne = index(expr,char(0))-1
      if (ne.gt.0) then
        ne = min(ne,len_trim(expr(1:ne)))
      else
        ne = len_trim(expr)
      endif
    endif
    if (x_vtypes(i).gt.0 .and. expr(1:1).ne.'"') then
      if (x_vtypes(i).gt.quote_offset) then
        if (xlun.ne.0) write(xlun,'(A,A,A)') expr(1:ne)
!
! Here we have to expand all "keywords" of the pseudo-string. Do this
! by a specific parsing
        next = 1
        lt = 1
        par = ' '
        string = ' '
        error = .false.
        !
        do while (.true.)
          lpar = 0
          par = ' '
          call sic_next (expr(next:),par,lpar,next)
          r8 = 0.0
          call sic_math_dble (par,lpar,r8,error)
          if (error) goto 10
          call sic_dble_to_string(r8,par)
          !
          ! Add to argument string
          string(lt:) = par
          lt = len_trim(string)+2
          if (next.gt.ne) exit
        enddo
        chain = 'SIC'//backslash//'LET '//var(1:nv)//' '//string(1:lt)//' /NOQUOTE' !!TEST
      else if (resize) then
        !
        ! No translation for Variable dimension character arrays
        chain = 'SIC'//backslash//'LET '//var(1:nv)//' '//expr(1:ne)
        if (xlun.ne.0) write(xlun,'(A,A,A)') expr(1:ne)            
      else
        if (x_vtypes(i).gt.lower_offset) then
          call sic_lower(expr)
        elseif  (x_vtypes(i).gt.upper_offset) then
          call sic_upper(expr)
        endif
!  Il y a un probleme entre les simples et doubles quotes ici
! en raison de comportement contradictoire entre le mode GUI
! et le mode terminal.
!
!  Idealement, on voudrait que le mode GUI ne traduise rien (re-ecrit dans
!  XLUN), alors que le mode terminal traduit les variables plus ou moins
!  comme SIC.
!
! Actuellement, rien n'est traduit, ce qui pose un veritable probleme
! dans le fichier .par, et interdit d'utiliser des expressions SIC
! generalisees.
!
!OLD!        chain = 'SIC'//backslash//'LET '//var(1:nv)//' "'//expr(1:ne)//'"'
!OLD!        if (xlun.ne.0) write(xlun,'(A,A,A)') '"',expr(1:ne),'"'
!
! Ici, pour l'interpretation, on
!    - scanne les simples quotes
!    - les fait preceder ou suivre d'un double quote (selon la parite)
! et pour XLUN
!    - on englobe l'expression dans une double quote
! C'est ce qui se rapproche le plus d'un comportement "attendu"
!
! Get read of any trailing Null
        expr(ne+1:) = ' '
        call xgag_quote(expr,string)
        !!Print *,'after quotes '//trim(string)
        !!Print *,'after quotes '//trim(expr)
        chain = 'SIC'//backslash//'LET '//var(1:nv)//' '//trim(string)
        if (xlun.ne.0) write(xlun,'(A,A,A)') '"',expr(1:ne),'"'
      endif
! Done
    else
      call sic_upper(expr(1:ne))
      chain = 'SIC'//backslash//'LET '//var(1:nv)//' '//expr(1:ne)
      if (xlun.ne.0) write(xlun,'(A)') expr(1:ne)
    endif
    !
    nc = len_trim(chain)
    if (resize) then
      chain(nc+1:) = ' /RESIZE'
      nc = nc+8
    endif
    ! Put quickly back the VTYPE of the widget!
    if (resize) x_vtypes(i) = x_vtypes(i)+resize_offset
    if (slider) x_vtypes(i) = x_vtypes(i)+slider_offset
    nc =  len_trim(chain)
    call sic_format(chain,nc)
    call sic_analyse (command,chain,nc,error)
    if (error) goto 10
    call let_variable(chain,nc,error)
    if (error) then
      call sic_message(seve%e,'XEND','Error executing ')
      call sic_message(seve%e,'XEND',chain(1:nc))
      goto 10
    endif
  enddo
  !
10 continue
  call xgag_finish
  call trap_ctrlc
  ! Abort code
  if (abort.eq.-3) then
    ! Delete variables
    do i=x_commands,1,-1
      call free_vm(x_cmdlen/4,x_string(2,i))
      call free_vm(varname_length/4,x_variab(2,i))
    enddo
    x_commands = 0
    !
    ! True ABORT only if required by user
    if (icode.ne.0) then
      call sic_message(seve%e,'SIC','Aborted by user')
      error = .true.
    endif
  else
    x_commands = n_commands
  endif
  !
end subroutine xgag_end
!
subroutine xgag_finish
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>xgag_finish
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  if (xlun.eq.0) return
  close(unit=xlun)
  call sic_frelun(xlun)
  xlun = 0
  !
end subroutine xgag_finish

subroutine xgag_quote(expr,chain)
  use sic_interfaces, except_this=>xgag_quote
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  character(len=*), intent(in)  :: expr
  character(len=*), intent(out) :: chain
  ! Local
  integer(kind=4) :: i, istart, ilast, j
  logical :: apres
  !
  chain = ' '
  if (expr(1:1).eq."'") then
    j = 2 ! Bug correction on Apr 3, 2015 (was 1 before)
    chain(1:1) = "'"
    istart = 2
    apres = .true.
  else
    chain(1:1) = '"'
    j = 2
    istart = 1
    apres = .false.
  endif
  !
  ilast = len_trim(expr)
  do i=istart,ilast
    if (expr(i:i).eq."'") then
      if (apres) then
        chain(j:j+1) = expr(i:i)//'"'
        apres = .false.
      else
        chain(j:j+1) = '"'//expr(i:i)
        apres = .true.
      endif
      j = j+2
    else
      chain(j:j) = expr(i:i)
      j = j+1
    endif
  enddo
  if (.not.apres) then
    chain(j:j) = '"'
  endif
end subroutine xgag_quote
