!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Main program management utilities
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module gmaster_private
  use sic_def
  use sic_interactions
  use gpack_def
  !---------------------------------------------------------------------
  ! @ private
  ! Structure for handling static master informations. They can be set
  ! from logical variables, command line or gmaster API.
  !---------------------------------------------------------------------
  type :: master_info_t
     character(len=filename_length) :: logname = ""           ! Basename for log_file and message_file
     character(len=filename_length) :: log_file = ""          ! For specific log_file
     character(len=filename_length) :: message_file = ""      ! For specific message_file
     logical                        :: append_date_on_logname = .false. ! Do not append date on logname
     character(len=gprompt_length)  :: prompt = ""            ! Prompt at startup
     logical                        :: disable_gui = .false.  ! Enable gui
     logical                        :: disable_log = .false.  ! Enable log files
     logical                        :: disable_menu = .false. ! Enable menu
     logical                        :: hide_gui = .false.     ! Show gui at startup
     logical                        :: hide_welcome = .false. ! Show welcome message at startup
     logical                        :: no_welcome_procedure = .false. ! Run welcome procedure at startup
     logical                        :: use_debug = .false.    ! Do not display debug messages
     logical                        :: usage = .false.        ! Display usage only?
     character(len=filename_length) :: display = ""           ! XWindow display to use
  end type master_info_t
  !
  !---------------------------------------------------------------------
  ! Structure for handling master dynamic state.
  !---------------------------------------------------------------------
  type :: master_prop_t
     type(master_info_t)               :: info              ! Master static info
     integer                           :: id = 0            ! Master package id
     character(len=filename_length)    :: logname = ""      ! Effective logname
     character(len=filename_length)    :: log_file = ""
     character(len=filename_length)    :: message_file = ""
     character(len=filename_length)    :: history_file = ""
     character(len=commandline_length) :: command_line = ""
  end type master_prop_t
  !
  type(master_prop_t), save :: gmaster         ! The master instance
  !
  logical :: exit_noprompt=.false.  ! For programs which may prompt answers at EXIT time.
  integer(kind=4) :: exit_code=0    ! EXIT status?
  !
end module gmaster_private
!
function gmaster_get_id()
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Return master package id.
  !---------------------------------------------------------------------
  integer :: gmaster_get_id         !
  !
  gmaster_get_id = gmaster%id
  !
end function gmaster_get_id
!
subroutine gmaster_build_logname
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_build_logname
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Build effective logname by appending date to logname.
  !---------------------------------------------------------------------
  character(len=64) :: mess
  integer :: i
  !
  !if (.not.gmaster%info%append_date_on_logname) then
  !   gmaster%logname = gmaster%info%logname
  !   return
  !endif
  !
  call sic_date(mess)
  call sic_lower(mess)
  i = index(mess,':')
  do while (i.gt.0)
     mess(i:) = mess(i+1:)
     i = index(mess,':')
  enddo
  i = index(mess,'-')
  do while (i.gt.0)
     mess(i:) = mess(i+1:)
     i = index(mess,'-')
  enddo
  !
  gmaster%logname = trim(gmaster%info%logname)//'-'//mess(1:9)//'-'//mess(11:16)
  !
end subroutine gmaster_build_logname
!
subroutine gmaster_set_logname(logname)
  use sic_interfaces, except_this=>gmaster_set_logname
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Set logname instead of default (i.e. package name).
  !---------------------------------------------------------------------
  character(len=*) :: logname       !
  !
  gmaster%info%logname = logname
  !
  call gmaster_build_logname
  !
end subroutine gmaster_set_logname
!
subroutine gmaster_set_message_file(message_file)
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Set logname instead of default (i.e. package name).
  !---------------------------------------------------------------------
  character(len=*) :: message_file  !
  !
  gmaster%info%message_file = message_file
  !
end subroutine gmaster_set_message_file
!
subroutine gmaster_set_log_file(log_file)
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Set logname instead of default (i.e. package name).
  !---------------------------------------------------------------------
  character(len=*) :: log_file      !
  !
  gmaster%info%log_file = log_file
  !
end subroutine gmaster_set_log_file
!
subroutine gmaster_append_date_on_logname
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Append date on logname
  !---------------------------------------------------------------------
  !
  gmaster%info%append_date_on_logname = .true.
  !
end subroutine gmaster_append_date_on_logname
!
subroutine gmaster_set_prompt(prompt)
  use sic_interfaces, except_this=>gmaster_set_prompt
  use gbl_message
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Set prompt instead of default (i.e. package name)
  !---------------------------------------------------------------------
  character(len=*) :: prompt        !
  !
  call sic_message(seve%d,'MASTER','Setting prompt to '//prompt)
  !
  gmaster%info%prompt = prompt
  !
end subroutine gmaster_set_prompt
!
subroutine gmaster_set_display(display)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_set_display
  use gbl_message
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Set display instead of default
  !---------------------------------------------------------------------
  character(len=*) :: display       !
  ! Local
  integer :: ier
  !
  call sic_message(seve%d,'MASTER','Setting display to '//display)
  !
  gmaster%info%display = display
  ier = sic_setlog('display',gmaster%info%display)  ! Set the logical DISPLAY
  !
end subroutine gmaster_set_display
!
subroutine gmaster_set_disable_log
  use sic_interfaces, except_this=>gmaster_set_disable_log
  use gbl_message
  use gmaster_private
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ public
  ! Disable the log files (.log and .mes)
  !---------------------------------------------------------------------
  !
  call sic_message(seve%d,'MASTER','Disabling log')
  !
  gmaster%info%disable_log = .true.
  !
end subroutine gmaster_set_disable_log
!
subroutine gmaster_set_disable_gui
  use sic_interfaces, except_this=>gmaster_set_disable_gui
  use gbl_message
  use gmaster_private
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ public
  ! Disable gui
  !---------------------------------------------------------------------
  !
  call sic_message(seve%d,'MASTER','Disabling gui')
  !
  gmaster%info%disable_gui = .true.
  sic_window = .false.  ! SIC%WINDOW is mapped on it
  call gmaster_set_hide_gui
  !
end subroutine gmaster_set_disable_gui
!
subroutine gmaster_set_disable_menu
  use sic_interfaces, except_this=>gmaster_set_disable_menu
  use gbl_message
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Disable gui
  !---------------------------------------------------------------------
  !
  call sic_message(seve%d,'MASTER','Disabling menu')
  !
  gmaster%info%disable_menu = .true.
  !
end subroutine gmaster_set_disable_menu
!
subroutine gmaster_set_hide_gui
  use sic_interfaces, except_this=>gmaster_set_hide_gui
  use gbl_message
  use gmaster_private
  use sic_interactions
  !---------------------------------------------------------------------
  ! @ public
  ! Hide gui at startup
  !---------------------------------------------------------------------
  !
  call sic_message(seve%d,'MASTER','Hiding gui')
  !
  gmaster%info%hide_gui = .true.
  sic_initwindow = .false.  ! SIC%INITWINDOW is mapped on it
  !
end subroutine gmaster_set_hide_gui
!
function gmaster_hide_gui()
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! return "hide gui" property
  !---------------------------------------------------------------------
  logical :: gmaster_hide_gui       !
  !
  gmaster_hide_gui = gmaster%info%hide_gui
  !
end function gmaster_hide_gui
!
subroutine gmaster_set_hide_welcome
  use sic_interfaces, except_this=>gmaster_set_hide_welcome
  use gbl_message
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Hide welcome at startup
  !---------------------------------------------------------------------
  !
  call sic_message(seve%d,'MASTER','Hiding welcome')
  !
  gmaster%info%hide_welcome = .true.
  !
end subroutine gmaster_set_hide_welcome
!
subroutine gmaster_set_usage
  use sic_interfaces, except_this=>gmaster_set_usage
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Activate 'usage' message at startup
  !---------------------------------------------------------------------
  !
  gmaster%info%usage = .true.
  call gmaster_set_hide_welcome
  call gmaster_set_disable_gui  ! No menu nor window
  !
end subroutine gmaster_set_usage
!
subroutine gmaster_set_no_welcome_procedure
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Hide welcome at startup
  !---------------------------------------------------------------------
  !
  gmaster%info%no_welcome_procedure = .true.
  !
end subroutine gmaster_set_no_welcome_procedure
!
subroutine gmaster_set_use_debug
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Enable display of debug messages
  !---------------------------------------------------------------------
  !
  gmaster%info%use_debug = .true.
  !
end subroutine gmaster_set_use_debug
!
subroutine gmaster_get_command_line(command_line)
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Get input command line
  !---------------------------------------------------------------------
  character(len=*) , intent(out) :: command_line  !
  !
  command_line = gmaster%command_line
  !
end subroutine gmaster_get_command_line
!
subroutine gmaster_gui(pack_id)
  use sic_interfaces, except_this=>gmaster_gui
  use gbl_message
  use gmaster_private
  use sic_dependencies_interfaces
  !---------------------------------------------------------------------
  ! @ private
  ! Show user interface of loaded packages
  !---------------------------------------------------------------------
  integer, intent(in) :: pack_id    !
  ! Local
  integer :: lun,ier
  character(len=filename_length) :: menu_file
  type(gpack_info_t) :: pack
  logical :: error
  !
  if (gmaster%info%disable_gui.or.gmaster%info%disable_menu) return
  !
  call sic_message(seve%t,'gmaster_gui',"Welcome")
  !
  error = .false.
  !
  ier = sic_getlun(lun)
  if (ier.ne.1) call sic_message(seve%f,'gmaster_gui','sic_getlun failed')
  !
  pack = gpack_get_info(gmaster%id)
  if (pack%ext.eq."") return
  !
  call sic_parse_file('menu-proc'//trim(pack%ext),'gag_proc:',"",menu_file)
  ier = sic_open(lun,menu_file,'NEW',.false.)
  if (ier.ne.0) then
     call sic_message(seve%f,'gmaster_gui','Unable to open '//trim(menu_file))
     call putios('E-GMASTER_GUI,  ',ier)
  else
     write (lun,'(A)') 'begin procedure menu'
     !
     write (lun,'(A)') 'gui\panel "'//trim(pack%name)//' GUI" gag_pro:greg-menu.hlp /detach'
     call gmaster_gui_menus(lun,error)
     call gmaster_gui_demo(lun,error)
     call gmaster_gui_help(lun,error)
     write (lun,'(A)') 'gui\go'
     !
     write (lun,'(A)') 'end procedure menu'
     close(lun)
     !
     call exec_program('@ "'//trim(menu_file)//'"')
     call gag_filrm(menu_file)
     if (.not.gmaster%info%hide_gui) then
        call exec_program('@ menu')
     endif
  endif
  call sic_frelun(lun)
  !
  call sic_message(seve%t,'gmaster_gui',"Bye")
  !
end subroutine gmaster_gui
!
subroutine gmaster_gui_menus(lun,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_gui_menus
  use gpack_def
  !---------------------------------------------------------------------
  ! @ private
  !  Define the menus in the gui. One menu per package, if provided by
  ! the package.
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: lun    ! The logical to write in
  logical,         intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='GUI'
  integer(kind=4) :: ipack,ier
  type(gpack_info_t) :: pack
  character(len=filename_length) :: pack_menu_file
  !
  do ipack=1,gpack_get_count(),1
    pack = gpack_get_info(ipack)
    if (sic_query_file('submenu'//trim(pack%ext),'macro#dir:',"",pack_menu_file)) then
      write (lun,'(A)',iostat=ier) '@ "submenu'//trim(pack%ext)//'"'
      if (ier.ne.0) then
        call sic_message(seve%e,rname,'Could not build gui menus')
        error = .true.
        return
      endif
    endif
  end do
  !
end subroutine gmaster_gui_menus
!
subroutine gmaster_gui_demo(lun,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_gui_demo
  use gpack_def
  !---------------------------------------------------------------------
  ! @ private
  !  Define the Demo menu in the gui. One submenu per package, if
  ! provided by the package.
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: lun    ! The logical to write in
  logical,         intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='GUI'
  integer(kind=4) :: ipack,ier
  type(gpack_info_t) :: pack
  character(len=filename_length) :: pack_menu_file
  !
  write (lun,'(A)') 'gui\menu "Demos"'
  !
  do ipack=gpack_get_count(),1,-1
    pack = gpack_get_info(ipack)
    if (sic_query_file('subdemo'//trim(pack%ext),'macro#dir:',"",pack_menu_file)) then
      write (lun,'(A)',iostat=ier) '@ "subdemo'//trim(pack%ext)//'"'
      if (ier.ne.0) then
        call sic_message(seve%e,rname,'Could not build gui Demo')
        error = .true.
        return
      endif
    endif
  end do
  !
  write (lun,'(A)') 'gui\menu /close'
  !
end subroutine gmaster_gui_demo
!
subroutine gmaster_gui_help(lun,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_gui_help
  use gpack_def
  use sic_dictionaries
  !---------------------------------------------------------------------
  ! @ private
  !  Define the Help menu in the gui. One submenu per package, if
  ! provided by the package.
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: lun    ! The logical to write in
  logical,         intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='GUI'
  integer(kind=4) :: ipack,ier,ilan
  type(gpack_info_t) :: pack
  character(len=filename_length) :: pack_menu_file
  !
  write (lun,'(A)') 'gui\menu "Help"'
  !
  ! Load help submenus for each dependency
  do ipack=gpack_get_count(),1,-1
    pack = gpack_get_info(ipack)
    if (sic_query_file('subhelp'//trim(pack%ext),'macro#dir:',"",pack_menu_file)) then
      write (lun,'(A)',iostat=ier) '@ "subhelp'//trim(pack%ext)//'"'
      if (ier.ne.0) then
        call sic_message(seve%e,rname,'Could not build gui Help')
        error = .true.
        return
      endif
    endif
  end do
  !
  ! Build a list of languages help
  write (lun,'(A)') 'gui\submenu "Languages"'
  do ilan=1,nlang
    write (lun,'(5A)')  &
      'gui\button "sic\help ',trim(languages(ilan)%name),'\" "',trim(languages(ilan)%name),'\"'
  enddo
  write (lun,'(A)') 'gui\submenu /close'
  !
  write (lun,'(A)') 'gui\menu /close'
  !
end subroutine gmaster_gui_help
!
subroutine gmaster_show_loaded_packages
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_show_loaded_packages
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Print informations on screen of all loaded packages
  !---------------------------------------------------------------------
  integer :: ipack
  type(gpack_info_t) :: pack
  !
  ! Show all loaded packages on screen
  write (*,'(A)') ""
  write (*,'(A)') ' * Loaded modules'
  do ipack=1,gpack_get_count(),1
     pack = gpack_get_info(ipack)
     if (pack%authors.ne."") then
        write (*,'(A)') '    '//trim(pack%name)//' ('//trim(pack%authors)//')'
     else
        write (*,'(A)') '    '//trim(pack%name)
     endif
  end do
  !
end subroutine gmaster_show_loaded_packages
!
subroutine gmaster_welcome(pack_id)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_welcome
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Execute the welcome procedure from master package
  !---------------------------------------------------------------------
  integer, intent(in) :: pack_id    !
  ! Local
  type(gpack_info_t) :: pack
  character(len=gpack_name_length) :: pack_name
  character(len=32) :: name
  character(len=filename_length) :: file
  logical :: found
  !
  if (gmaster%info%hide_welcome) return
  !
  pack = gpack_get_info(pack_id)
  !
  ! Print Welcome
  pack_name = pack%name
  call sic_upper(pack_name)
  write (*,'(A)') ""
  write (*,'(A)') ' * Welcome to '//pack_name
  !
  call gmaster_show_loaded_packages
  !
  ! Execute welcome procedure
  if (.not.gmaster%info%no_welcome_procedure.and.pack%ext.ne."") then
    name = 'welcome'//trim(pack%pro_suffix)//pack%ext
    call find_procedure(name,file,found)
    if (found)  call exec_program('@ '//name)  ! No error if no welcome procedure
  endif
  !
end subroutine gmaster_welcome
!
subroutine gmaster_loop
  use sic_interfaces, except_this=>gmaster_loop
  use gbl_message
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Execute optionnal commands from command line and run the interpreter
  ! loop
  !---------------------------------------------------------------------
  !
  call sic_message(seve%t,"GAG_LOOP","Welcome")
  !
  ! Begin session with user command or nothing
  ! Start the real work
  if (gmaster%command_line.ne."") then
     call play_program(gmaster%command_line)
  else
     call enter_program
  endif
  !
  call sic_message(seve%t,"GAG_LOOP","Bye")
  !
end subroutine gmaster_loop
!
subroutine gmaster_custom_init
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_custom_init
  !---------------------------------------------------------------------
  ! @ private
  ! Check if some features are customized in dictionaries and different
  ! from defaults.
  ! Nothing is done if values are the defaults (e.g. "sic_window yes")
  !---------------------------------------------------------------------
  ! Local
  character(len=32) :: logic
  integer :: ier
  !
  ! No initial window
  logic = 'sic_initwindow'
  ier = sic_getlog(logic)
  if (ier.eq.0) then
    call sic_upper(logic)
    if (logic.eq.'NO') call gmaster_set_hide_gui
  endif
  !
  ! No window (from global dictionary)
  logic = 'gag_widgets'
  ier = sic_getlog(logic)
  if (ier.eq.0) then
    call sic_upper(logic)
    if (logic.eq.'NONE') call gmaster_set_disable_gui
  endif
  !
  ! No window (from local dictionary)
  logic = 'sic_window'
  ier = sic_getlog(logic)
  if (ier.eq.0) then
    call sic_upper(logic)
    if (logic.eq.'NO') call gmaster_set_disable_gui
  endif
  !
  ! Display
  logic = 'display'
  ier = sic_getlog(logic)
  if (ier.eq.0) call gmaster_set_display(logic)
  !
  ! No log files?
  logic = 'sic_logfiles'
  ier = sic_getlog(logic)
  if (ier.eq.0) then
    call sic_upper(logic)
    if (logic.eq.'NO')  call gmaster_set_disable_log
  endif
  !
end subroutine gmaster_custom_init
!
subroutine gmaster_parse_command_line(nomore,error)
  use sic_interfaces, except_this=>gmaster_parse_command_line
  use sic_dependencies_interfaces
  use sic_def
  use gbl_message
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Parse command line options. Override customizations from
  ! dictionaries
  !---------------------------------------------------------------------
  logical, intent(out)   :: nomore  ! Should program stop after this?
  logical, intent(inout) :: error   !
  ! Local
  integer :: iarg, arg_count
  integer :: command_line_length = 0
  character(len=filename_length) :: arg  ! Longest argument can be a file name
  !
  iarg = 1
  arg_count = sic_get_arg_count()
  nomore = .false.
  do while (iarg.le.arg_count)
     call sic_get_arg(iarg,arg)
     if (arg(1:1).eq.'-'.and.command_line_length.eq.0) then
        if (arg.eq.'-nw') then
           call gmaster_set_disable_gui
        elseif (arg.eq.'-niw') then
           call gmaster_set_hide_gui
        elseif (arg.eq.'-nl') then
           call gmaster_set_disable_log
        elseif (arg.eq.'-display') then
           iarg = iarg+1
           call sic_get_arg(iarg,arg)
           call gmaster_set_display(arg)
        elseif (arg.eq.'-logname') then
           iarg = iarg+1
           call sic_get_arg(iarg,arg)
           call gmaster_set_logname(arg)
! Examples for new options
!        elseif (arg.eq.'-prompt') then
!           iarg = iarg+1
!           call sic_get_arg(iarg,arg)
!           call gmaster_set_prompt(arg)
        elseif (arg.eq.'-d') then
           call gmaster_set_use_debug
        elseif (arg.eq.'-v') then
           ! At this stage version has already been displayed
           nomore = .true.
        elseif (arg.eq.'-h') then
           call gmaster_set_usage
        else
          call sic_message(seve%e,'gmaster_get_command_line','unrecognized option '//arg)
          error = .true.
        endif
     else
        gmaster%command_line(command_line_length+1:) = arg
        command_line_length = command_line_length+1+len_trim(arg)
     endif
     iarg = iarg+1
  enddo
  !
  ! Memorize this command line in the keyboard recall stack
  call gprompt_set_command_line(gmaster%command_line)
  !
end subroutine gmaster_parse_command_line
!
subroutine gmaster_usage
  use sic_interfaces, except_this=>gmaster_usage
  !---------------------------------------------------------------------
  ! @ private
  ! Display the usage and exit. In particular, describe the available
  ! options.
  !---------------------------------------------------------------------
  !
  call exec_program('@ usage.sic')
  !
end subroutine gmaster_usage
!
subroutine gmaster_on_exit(error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_on_exit
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Execute the on_exit routines of all registered packages
  ! Program can exit if error is false on output
  !---------------------------------------------------------------------
  logical, intent(inout) :: error   !
  ! Global
  include 'gbl_memory.inc'
  ! Local
  integer :: ipack
  type(gpack_info_t) :: pack
  !
  ! Close all the GUI-menus (needed if their support procedure is to
  ! be removed, e.g. in GAG_PROC: : some NFS servers deny the cleaning
  ! as long as the GUI-menu exists). Must be called before routine
  ! 'end_procedure'.
  if (sic_inter_state(0))  &
     call xgag_end_detach_all
  !
  ! Loop over the registered packages and call on_exit routine
  ! in registering reverse order
  do ipack=gpack_get_count(),1,-1
     pack = gpack_get_info(ipack)
     if (pack%on_exit.ne.0) then
        call gexec1(membyt(bytpnt(pack%on_exit,membyt)),error)
        if (error) return
     endif
  end do
  !
end subroutine gmaster_on_exit
!
subroutine gmaster_clean(error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_clean
  use sic_def
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Execute the clean routines of all registered packages
  !---------------------------------------------------------------------
  logical, intent(inout) :: error   !
  ! Global
  include 'gbl_memory.inc'
  ! Local
  integer :: ipack,ier
  type(gpack_info_t) :: pack
  character(len=filename_length) :: file
  !
  ! Loop over the registered packages and call clean routine
  ! in registering reverse order (just in case...)
  do ipack=gpack_get_count(),1,-1
     pack = gpack_get_info(ipack)
     if (pack%clean.ne.0) call gexec1(membyt(bytpnt(pack%clean,membyt)),error)
  end do
  !
  ! Close opened units
  call sic_close_log(error)
  call gmessage_close(error)
  !
  ! Any remaining?
!   ier = gag_stalun(0)  ! Debug: stat all the units. Should be already closed
!                        ! (sic_close) and freed (gag_frelun).
  ier = sic_close(0)  ! => close all for safety
  !
  if (.not.gmaster%info%disable_log) then
    ! Log files were activated
    if (.not.gmaster%info%append_date_on_logname) then
      ! Remove date from filenames
      if (gmaster%info%message_file.eq."") then
          call sic_parse_file(gmaster%info%logname,'gag_log:','.mes',file)
          ier = gag_filrename(gmaster%message_file,file)
      endif
      if (gmaster%info%log_file.eq."") then
          call sic_parse_file(gmaster%info%logname,'gag_log:','.log',file)
          ier = gag_filrename(gmaster%log_file,file)
      endif
    endif
  endif
  !
end subroutine gmaster_clean
!
subroutine gmaster_build_info(pack_set)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_build_info
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Build master info
  !---------------------------------------------------------------------
  external :: pack_set              ! Package definition routine
  ! Local
  type(gpack_info_t) :: pack
  !
  call pack_set(pack)
  !
  if (gmaster%info%logname.eq."") then
     call gmaster_set_logname(pack%name)
  endif
  !
  if (gmaster%info%prompt.eq."") then
     gmaster%info%prompt = pack%name
     call sic_upper(gmaster%info%prompt)
  endif
  !
end subroutine gmaster_build_info
!
subroutine gmaster_raw_import(master,pack_set,debug,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_raw_import
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Imports a package, and returns package registration id
  !---------------------------------------------------------------------
  logical, intent(in)    :: master    ! Import master package
  external               :: pack_set  ! Package definition method
  logical, intent(in)    :: debug     ! Debug mode
  logical, intent(inout) :: error     !
  ! Local
  integer :: pack_id
  logical :: already_registered
  !
  if (.not.debug) then
     call gmessage_quiet
  endif
  !
  pack_id = gpack_build(pack_set,already_registered,error)
  if (master) gmaster%id = pack_id
  !
  if (.not.already_registered) call gmaster_gui(pack_id)
  !
  if (.not.debug) then
     call gmessage_standard
  endif
  !
end subroutine gmaster_raw_import
!
subroutine gmaster_main_import(pack_set,debug,error)
  use sic_interfaces, except_this=>gmaster_main_import
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Imports the main package and sets the master package id
  !---------------------------------------------------------------------
  external               :: pack_set  ! Package definition method
  logical, intent(in)    :: debug     ! Debug mode
  logical, intent(inout) :: error     !
  !
  call gmaster_raw_import(.true.,pack_set,debug,error)
  !
  call gmaster_welcome(gmaster%id)
  !
end subroutine gmaster_main_import
!
subroutine gmaster_import(pack_set,debug,error)
  use sic_interfaces, except_this=>gmaster_import
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private
  ! Imports a package
  !---------------------------------------------------------------------
  external               :: pack_set  ! Package definition method
  logical, intent(in)    :: debug     ! Debug mode
  logical, intent(inout) :: error     !
  !
  call gmaster_raw_import(.false.,pack_set,debug,error)
  !
end subroutine gmaster_import
!
subroutine gmaster_build(pack_set,error)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_build
  use gbl_message
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public (should be private!)
  ! Build master package
  !---------------------------------------------------------------------
  external               :: pack_set  ! Package definition routine
  logical, intent(inout) :: error     ! Error code
  !
  ! If '-d' was present, revert debugging mode (default is off)
  if (gmaster%info%use_debug) call gmessage_debug_swap
  !
  call sic_message(seve%t,"gmaster_build","Start package setting")
  !
  ! Initialize widget library
#if defined(GAG_USE_STATICLINK)
  call init_gui
#endif
  !
  call gmaster_build_info(pack_set)
  !
  ! Must be first to ensure that gag directories are available (e.g.
  ! for message file)
  call sic_build_environment
  !
  ! Must be called ASAP to ensure correct logging of message afterwards
  if (.not.gmaster%info%disable_log) then
    ! Message file (.mes)
    if (gmaster%info%message_file.eq."") then
      call sic_parse_file(gmaster%logname,'gag_log:','.mes',gmaster%message_file)
    else
      gmaster%message_file = gmaster%info%message_file
    endif
    call gmessage_init(gmaster%message_file,error)
    if (error) return
    !
    ! Log file (.log)
    if (gmaster%info%log_file.eq."") then
      call sic_parse_file(gmaster%logname,'gag_log:','.log',gmaster%log_file)
    else
      gmaster%log_file = gmaster%info%log_file
    endif
    call sic_open_log(gmaster%log_file,error)
    if (error) return
  endif
  !
  call gprompt_set(gmaster%info%prompt)
  !
  ! Set keyboard history filename
  call sic_parse_file(gmaster%info%logname,'gag_log:','.hist',gmaster%history_file)
  call gkbd_f_histo_set_filename(gmaster%history_file)
  !
  ! Import package
  call gmaster_main_import(pack_set,gmaster%info%use_debug,error)
  if (error) return
  !
  call sic_message(seve%t,"gmaster_build","Stop package setting")
  !
end subroutine gmaster_build
!
subroutine gmaster_run(pack_set)
  use sic_dependencies_interfaces
  use sic_interfaces, except_this=>gmaster_run
  use gpack_def
  use gmaster_private
  use gbl_message
  !---------------------------------------------------------------------
  ! @ public
  ! Run master program
  !---------------------------------------------------------------------
  external :: pack_set              ! Package definition routine
  ! Local
  logical :: error,nomore
  character(len=256) :: release
  !
  error = .false.
  !
  call sic_message(seve%t,"gmaster_run","Welcome")
  !
  ! Echo the Gildas version
  call gag_release(release)
  write(*,'(a)') trim(release)
  !
  ! Get custom initialization from dictionaries
  call gmaster_custom_init
  !
  ! Parse command line options (override custom init)
  call gmaster_parse_command_line(nomore,error)
  if (nomore.or.error) return
  !
  ! Disable gui for non interactive session
  if (gmaster%info%usage) then
    ! If e.g. sic -h, disable interactive status. This will avoid launching
    ! the keyboard thread in gmaster_build.
    call set_inter_state(.false.)
  else
    call sense_inter_state
  endif
  if (.not.sic_inter_state(0))  call gmaster_set_disable_gui
  !
  call gmaster_set_ismaster(.true.)  ! Set program as master, Python slave
  call gmaster_build(pack_set,error)
  !
  if (gmaster%info%usage) then
    ! Print usage and leave cleanly. Must come after build (gmaster%id must
    ! have been set)
    call gmaster_usage
    !
  elseif (.not.error) then
    ! Main loop
    call gmaster_enter_loop(gmaster%command_line)
  endif
  !
  call gmaster_clean(error)
  if (error) return
  !
  if (exit_code.ne.0)  call exit(exit_code)  ! EXIT() is GNU and Intel
  !
  call sic_message(seve%t,"gmaster_run","Bye")
  !
end subroutine gmaster_run
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine gmaster_set_exitcode(code)
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private (should it be public?)
  ! Set the 'exit code' to be issued when leaving
  !---------------------------------------------------------------------
  integer(kind=4), intent(in) :: code
  exit_code = code
end subroutine gmaster_set_exitcode
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine gmaster_set_exitnoprompt(flag)
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ private (should it be public?)
  ! Set the 'exit noprompt' flag
  !---------------------------------------------------------------------
  logical, intent(in) :: flag
  exit_noprompt = flag
end subroutine gmaster_set_exitnoprompt
!
subroutine gmaster_get_exitnoprompt(flag)
  use gmaster_private
  !---------------------------------------------------------------------
  ! @ public
  ! Get the 'exit noprompt' flag. To be called by the exit subroutine of
  ! the program (and their dependent packages) to know if they are
  ! allowed to ask anything at exit time.
  !---------------------------------------------------------------------
  logical, intent(out) :: flag
  flag = exit_noprompt
end subroutine gmaster_get_exitnoprompt
