#!/bin/sh
# the next line restarts using tclsh \
    exec wish "$0" "$@"

#
# launch.tcl
#
# This script is used to set platform-specific variables for the shell
# that will be used to launch slicer.
#
# - what platform you're on so correct libs are loaded
# - what modules are present so they can be loaded
# - set all PATH, LD_LIBRARY_PATH, TCLLIBPATH, and other shell-level
#   variables to reflect that state
#   
# This is a tcl script rather than a .bat or .sh file so it can handle all 
# the details in one place for all platforms.
#
# This script is used for both the slicer build directory and for the slicer
# install directory.
#
# Note: the version of this file called launch.tcl.in will be configured by 
# cmake such that tokens between @ signs will be replaced by the variable 
# from the cmake cache
#

# set default error code and info so we don't get confused later if no error has
# actually occurred...
set ::errorCode 0
set ::errorInfo ""

set ::EXIT_CODE_NO_ERROR 0
set ::EXIT_CODE_CHILD_KILLED 1
set ::EXIT_CODE_GENERIC_ERROR -1
set ::EXIT_CODE_VTK_ERROR -2
set ::EXIT_CODE_LAUNCHING_ERROR -3

#-------------------------------------------------------------------------------
# .PROC ShowAndLogError
# Helper function.
# Use this function instead of puts to both log an error message and
# show it for the user in a popup window
# (The popup window is automatically closed after a few seconds to allow some
# time for the user to read, but allow application exit in a reasonable time
# for automated tests.)
# .ARGS
# message to be displayed
# .END
#-------------------------------------------------------------------------------
set ::LAUNCH(showErrorPopup) 1
proc ShowAndLogError { msg } {
    set autoCloseTimeoutMs 10000 
    puts $msg
    if { $::LAUNCH(showErrorPopup) } {
        if { [catch "package require Tk" res] } {
            puts "Error displaying error in a popup: $res"
        } else {
            after $autoCloseTimeoutMs {destroy .dialog1}
            tk_dialog .dialog1 "Error" "$msg" error 0 OK
        }
    }
}

#-------------------------------------------------------------------------------
# .PROC StoreDirInEnvVar
# Helper function to safely store directory in environment variable.
# Makes sure that the environment variable is defined, even when the directory
# name is empty (to avoid "no such variable" script error)
# .ARGS
# environment variable name, directory path
# .END
#-------------------------------------------------------------------------------
proc StoreDirInEnvVar { envVarName dir } {
    set dir [file normalize "$dir"] 
    if {$dir == ""} {
        set dir " "
    }
    set ::env($envVarName) "$dir"
}

#-------------------------------------------------------------------------------
# .PROC launch_SetEnvironment
# Initialize environment variables
# .ARGS
# .END
#-------------------------------------------------------------------------------
proc launch_SetEnvironment {} {

    #
    # Slicer3_HOME: , find it relative to the location of this script
    # -- when run by the launcher, this variable will be set already
    # -- this environment variable can be relied on by slicer code to know "where it lives"
    #    e.g. the build or install dir, so resources and other files can be found
    #
    set wd [pwd]
    cd [file dirname [file dirname [file dirname [info script]]]]
    set ::Slicer3_HOME [pwd]
    cd $wd
    set ::env(Slicer3_HOME) $::Slicer3_HOME
    
    if { [string match -nocase "windows*" $::tcl_platform(os)] } {
      set ::Slicer3_HOME [file attributes $::Slicer3_HOME -shortname]
      set ::env(Slicer3_HOME) $::Slicer3_HOME
    }
    
    #
    # Indicate if Slicer was build with QT support
    #
    set ::Slicer3_USE_QT "@Slicer3_USE_QT@"
    
    #
    # set up variables for the OS Builds
    # 
    set ::SOLARIS "solaris8"
    set ::LINUX "linux-x86"
    set ::LINUX_64 "linux-x86_64"
    set ::DARWIN "darwin-ppc"
    set ::DARWIN_X86 "darwin-x86"
    set ::WINDOWS "win32"
    
    #
    # set the default locations for the main components
    #
    switch $::tcl_platform(os) {
        "SunOS" { set ::env(BUILD) $::SOLARIS }
        "Linux" {           
            if {$::tcl_platform(machine) == "x86_64"} {
                set ::env(BUILD) $::LINUX_64 
            } else {
                set ::env(BUILD) $::LINUX
            }
        }       
        "Darwin" { 
            if {$::tcl_platform(machine) == "i386"} {
                set ::env(BUILD) $::DARWIN_X86
            } else {
                set ::env(BUILD) $::DARWIN 
            }
        }
        default { 
            set ::env(BUILD) $::WINDOWS 
        }
    }
    
    
    if {$::tcl_platform(os) == "SunOS"} {
      set isainfo [exec isainfo -b]
      set SlicerBinaryBitness [exec file $::env(Slicer3_HOME)/bin/Slicer3-real | cut -d "," -f 1 | cut -d " " -f2 | cut -d "-" -f1]
        if {$SlicerBinaryBitness == "32"} {
            set ::BUILD(bitness) "32"
        } elseif {$SlicerBinaryBitness == "64" && $isainfo == 64} {
            set ::BUILD(bitness) "64"
        } elseif {$SlicerBinaryBitness == "64" && $isainfo == 32} {
    	ShowAndLogError "You can't run a 64 bit program on a 32 bit kernel!"
    	exit $::EXIT_CODE_GENERIC_ERROR
        }
    }	
    
    #
    # check if this is an install or a build directory
    # - an install will have a copy of vtk in the bin directory
    # - a build dirctory will not
    #
    set installed 0
    set ext ""
    if { [string match -nocase "windows*" $::tcl_platform(os)] } {
      set ext ".exe"
    }
    
    if { [file exists $::env(Slicer3_HOME)/bin/vtk$ext] } {
      set installed 1
    }
    
    if { $installed } {
    
    
      # if installed, everything is in the local tree
      set ::Slicer3_REAL $::Slicer3_HOME/bin/Slicer3-real$ext
    
      set ::env(SANDBOX_BIN_DIR)   ""
    
      # additional system libs
    
      set ::env(X11_LIB_DIR) ""
      set ::env(SFW_LIB_DIR) ""
      if { $::env(BUILD) == $::SOLARIS && $::BUILD(bitness) == "32"} {
        set ::env(X11_LIB_DIR) /usr/X11/lib
        set ::env(SFW_LIB_DIR) /usr/sfw/lib
      } else {
        set ::env(X11_LIB_DIR) /usr/X11/lib/64
        set ::env(SFW_LIB_DIR) /usr/sfw/lib/64
      }
    
      # 3rd party toolkits
    
      set ::env(VTK_DIR)            $::env(Slicer3_HOME)/lib/vtk-@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@
      set ::env(VTK_BIN_DIR)        $::env(Slicer3_HOME)/bin
    
      set ::env(KWWidgets_DIR)      $::env(Slicer3_HOME)/lib/KWWidgets
      set ::env(KWWidgets_LIB_DIR)  $::env(Slicer3_HOME)/lib/KWWidgets
      set ::env(KWWidgets_BIN_DIR)  $::env(Slicer3_HOME)/bin
    
      # TODO -- where will Qt be in the install tree?
      set ::env(QT_LIB_DIR)         $::env(Slicer3_HOME)/lib/Qt
      # Let's make QT binaries available
      set ::env(QT_BINARY_DIR)         $::env(Slicer3_HOME)/bin
    
      set ::env(ITK_BIN_DIR)        $::env(Slicer3_HOME)/lib/InsightToolkit
    
      set ::env(Teem_DIR)           $::env(Slicer3_HOME)/lib/Teem-@Teem_VERSION_MAJOR@.@Teem_VERSION_MINOR@.@Teem_VERSION_PATCH@
    
      set ::env(TCL_DIR)            $::env(Slicer3_HOME)/lib/TclTk
      set ::env(TCL_LIBRARY)        "$::env(TCL_DIR)/lib/tcl@TCL_TK_VERSION_DOT@"
      if {$::env(BUILD) == $::WINDOWS} {
        set ::env(PYTHON_DIR)         $::env(Slicer3_HOME)/lib/Python/PCbuild
      } else {
        set ::env(PYTHON_DIR)         $::env(Slicer3_HOME)/lib/Python
      }
    
      set ::env(OpenIGTLink_DIR)      $::env(Slicer3_HOME)/lib/OpenIGTLink
      set ::env(OpenIGTLink_LIB_DIR)  $::env(Slicer3_HOME)/lib/OpenIGTLink
      set ::env(OpenIGTLink_BIN_DIR)  $::env(Slicer3_HOME)/bin
    
      set ::env(BatchMake_DIR)      $::env(Slicer3_HOME)/lib/BatchMake
      set ::env(BatchMake_LIB_DIR)  $::env(Slicer3_HOME)/lib/BatchMake
      set ::env(BatchMake_BIN_DIR)  $::env(Slicer3_HOME)/bin
      set ::env(bmModuleDescriptionParser_DIR)        $::env(Slicer3_HOME)/lib/bmModuleDescriptionParser
    
    
      # Slicer3 Libs
    
      set ::env(FreeSurfer_DIR)     $::env(Slicer3_HOME)/lib/FreeSurfer
      set ::env(IGT_DIR)            $::env(Slicer3_HOME)/lib/IGT
      set ::env(ITKCommandIO_DIR)   $::env(Slicer3_HOME)/lib/ITKCommandIO
      set ::env(LoadableModule_DIR) $::env(Slicer3_HOME)/lib/LoadableModule
      set ::env(MGHImageIO_DIR)     $::env(Slicer3_HOME)/lib/MGHImageIO
      set ::env(MRML_DIR)           $::env(Slicer3_HOME)/lib/MRML
      set ::env(MRMLCLI_DIR)        $::env(Slicer3_HOME)/lib/MRMLCLI
      set ::env(ModuleDescriptionParser_DIR)        $::env(Slicer3_HOME)/lib/ModuleDescriptionParser
      set ::env(MRMLIDImageIO_DIR)  $::env(Slicer3_HOME)/lib/MRMLIDImageIO
      set ::env(Qdec_DIR)           $::env(Slicer3_HOME)/lib/Qdec
      set ::env(RemoteIO_DIR)       $::env(Slicer3_HOME)/lib/RemoteIO
      set ::env(FileWatcher_DIR)    $::env(Slicer3_HOME)/lib/FileWatcher
      set ::env(SlicerIO_DIR)       $::env(Slicer3_HOME)/lib/SlicerIO
      set ::env(tclap_DIR)          $::env(Slicer3_HOME)/lib/tclap
      set ::env(vtkITK_DIR)         $::env(Slicer3_HOME)/lib/vtkITK
      set ::env(vtkTeem_DIR)        $::env(Slicer3_HOME)/lib/vtkTeem
      set ::env(qCTKWidgets_DIR)    $::env(Slicer3_HOME)/lib/qCTKWidgets
      set ::env(qVTKWidgets_DIR)    $::env(Slicer3_HOME)/lib/qVTKWidgets
      set ::env(qMRMLWidgets_DIR)   $::env(Slicer3_HOME)/lib/qMRMLWidgets
    
      set ::env(Slicer3_COMPILER_DIR) ""
      if { $::env(BUILD) == $::SOLARIS } {
        set ::env(Slicer3_COMPILER_DIR) $::env(Slicer3_HOME)/lib/Slicer3/CompilerLibs/$::BUILD(bitness)
      }
    
      # Slicer3 Base
    
      set ::env(Slicer3_LIB_DIR)    $::env(Slicer3_HOME)/lib/Slicer3
      set ::env(Slicer3_BIN_DIR)    $::env(Slicer3_HOME)/bin
    
      set ::env(Slicer3_PLUGINS_DIR)            $::env(Slicer3_HOME)/@Slicer3_INSTALL_PLUGINS_LIB_DIR@
      set ::env(Slicer3_MODULES_DIR)            $::env(Slicer3_HOME)/@Slicer3_INSTALL_MODULES_LIB_DIR@
      set ::env(Slicer3_QTLOADABLEMODULES_DIR)  $::env(Slicer3_HOME)/@Slicer3_INSTALL_QTLOADABLEMODULES_LIB_DIR@
    
      # QtDesigner variable
      #
      set ::env(Slicer3_QT_PLUGIN_PATH)  "@Slicer3_INSTALL_LIB_DIR@"
    
    } else {
    
      # the not-installed case
    
      set ::BUILD_SUBDIR  ""
      set ::VTK_BUILD_SUBDIR  ""
      set ::KWWidgets_BUILD_SUBDIR  ""
      set ::ITK_BUILD_SUBDIR  ""
      set ::Teem_BUILD_SUBDIR  ""
      set ::OpenIGTLink_BUILD_SUBDIR  ""
      set ::BatchMake_BUILD_SUBDIR  ""
      set ::QtDesignerPlugins_BUILD_SUBDIR  ""
    
      if {$::env(BUILD) == $::WINDOWS} {
        foreach buildType {"." Debug RelWithDebInfo Release MinSizeRel} {
          set try "$::Slicer3_HOME/bin/$buildType/Slicer3-real.exe"
          if { [file exists "$try"] } {
            set ::Slicer3_REAL $try
            set ::BUILD_SUBDIR $buildType
          }
          if { [file exists "@VTK_DIR@/bin/$buildType/vtk.exe"] } {
            set ::VTK_BUILD_SUBDIR $buildType
          }
          if { [file exists "@KWWidgets_DIR@/bin/$buildType/KWWidgets.dll"] } {
            set ::KWWidgets_BUILD_SUBDIR $buildType
          }
          if { [file exists "@ITK_DIR@/bin/$buildType/ITKCommon.dll"] } {
            set ::ITK_BUILD_SUBDIR $buildType
          }
          if { [file exists "@Teem_DIR@/bin/$buildType/air.dll"] ||
                 [file exists "@Teem_DIR@/bin/$buildType/teem.dll"] } {
            set ::Teem_BUILD_SUBDIR $buildType
          }
          if { [file exists "@OpenIGTLink_DIR@/bin/$buildType/OpenIGTLink.dll"] } {
            set ::OpenIGTLink_BUILD_SUBDIR $buildType
          }
          if { [file exists "@BatchMake_DIR@/bin/$buildType/BatchMake.dll"] } {
            set ::BatchMake_BUILD_SUBDIR $buildType
          }
          if { "@Slicer3_QT_PLUGIN_PATH@" != "" } {
            if { [file exists "@Slicer3_QT_PLUGIN_PATH@/$buildType/designer/qCTKWidgetsPlugin.dll"] } {
              set ::QtDesignerPlugins_BUILD_SUBDIR $buildType
            }
          }
        }
      } else {
        set ::Slicer3_REAL $::Slicer3_HOME/bin/Slicer3-real
      }
      set ::env(SANDBOX_BIN_DIR)   ""
    
    
      # additional system libs
    
      if { $::env(BUILD) == $::SOLARIS && $::BUILD(bitness) == "32"} {
        set ::env(X11_LIB_DIR) /usr/X11/lib
        set ::env(SFW_LIB_DIR) /usr/sfw/lib
      } else {
        set ::env(X11_LIB_DIR) /usr/X11/lib/64
        set ::env(SFW_LIB_DIR) /usr/sfw/lib/64
      }
    
      set ::env(Slicer3_COMPILER_DIR) ""
      if { $::env(BUILD) == $::SOLARIS } {
        set ::env(Slicer3_COMPILER_DIR) $::env(Slicer3_HOME)/lib/Slicer3/CompilerLibs/$::BUILD(bitness)
      }
    
    
      # 3rd party toolkits
    
      set ::env(VTK_DIR)            [file normalize "@VTK_DIR@"]
      set ::env(VTK_BIN_DIR)        [file normalize "@VTK_DIR@/bin/$::VTK_BUILD_SUBDIR"]
    
      set ::env(KWWidgets_DIR)      [file normalize "@KWWidgets_DIR@"]
      set ::env(KWWidgets_LIB_DIR)  [file normalize "@KWWidgets_DIR@/bin/$::KWWidgets_BUILD_SUBDIR"]
      set ::env(KWWidgets_BIN_DIR)  [file normalize "@KWWidgets_DIR@/bin/$::KWWidgets_BUILD_SUBDIR"]
    
      if { "@QT_LIBRARY_DIR@" != "" } {
        set ::env(QT_LIB_DIR)         [file normalize "@QT_LIBRARY_DIR@"]
      } else {
        set ::env(QT_LIB_DIR)         "$::Slicer3_HOME/bin"
      }
      # Let's make QT binaries available
      StoreDirInEnvVar QT_BINARY_DIR "@QT_BINARY_DIR@"
    
      set ::env(ITK_BIN_DIR)        [file normalize "@ITK_DIR@/bin/$::ITK_BUILD_SUBDIR"]
    
      set ::env(TCL_DIR)            [file normalize [file dirname [file dirname "@TCL_LIBRARY@"]]]
      set ::env(TCL_LIBRARY)        "$::env(TCL_DIR)/lib/tcl@TCL_TK_VERSION_DOT@"
    
      if {$::env(BUILD) == $::WINDOWS} {
        set ::env(PYTHON_DIR)         [file normalize [file dirname "@PYTHON_INCLUDE_PATH@"]/PCbuild]
      } else {
        set ::env(PYTHON_DIR)         [file normalize [file dirname [file dirname "@PYTHON_INCLUDE_PATH@"]]]
      }
    
      set ::env(Teem_DIR)           [file normalize "@Teem_DIR@/bin/$::Teem_BUILD_SUBDIR"]
    
      set ::env(OpenIGTLink_DIR)      [file normalize "@OpenIGTLink_DIR@"]
      set ::env(OpenIGTLink_LIB_DIR)  [file normalize "@OpenIGTLink_DIR@/bin/$::OpenIGTLink_BUILD_SUBDIR"]
      set ::env(OpenIGTLink_BIN_DIR)  [file normalize "@OpenIGTLink_DIR@/bin/$::OpenIGTLink_BUILD_SUBDIR"]
    
      set ::env(BatchMake_DIR)      [file normalize "@BatchMake_DIR@"]
      set ::env(BatchMake_LIB_DIR)  [file normalize "@BatchMake_DIR@/bin/$::BatchMake_BUILD_SUBDIR"]
      set ::env(BatchMake_BIN_DIR)  [file normalize "@BatchMake_DIR@/bin/$::BatchMake_BUILD_SUBDIR"]
      set ::env(bmModuleDescriptionParser_DIR) $::env(BatchMake_BIN_DIR)
    
    
      # Slicer3 Libs
    
      set ::env(FreeSurfer_DIR)     [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(IGT_DIR)            [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(ITKCommandIO_DIR)   [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(LoadableModule_DIR) [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(MGHImageIO_DIR)     [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(MRML_DIR)           [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(MRMLCLI_DIR)        [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(ModuleDescriptionParser_DIR)        [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(MRMLIDImageIO_DIR)  [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(Qdec_DIR)           [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(RemoteIO_DIR)       [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(FileWatcher_DIR)    [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(SlicerIO_DIR)       [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(tclap_DIR)          [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(vtkITK_DIR)         [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(vtkTeem_DIR)        [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(qCTKWidgets_DIR)    [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(qMRMLWidgets_DIR)   [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      set ::env(qVTKWidgets_DIR)    [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
      
    
      # Slicer3 Base
    
      set ::env(Slicer3_BIN_DIR)    [file normalize "$::Slicer3_HOME/bin/$::BUILD_SUBDIR"]
      set ::env(Slicer3_LIB_DIR)    [file normalize "$::Slicer3_HOME/lib/$::BUILD_SUBDIR"]
    
      set ::env(Slicer3_PLUGINS_DIR) [file normalize "$::env(Slicer3_HOME)/@Slicer3_INSTALL_PLUGINS_LIB_DIR@/$::BUILD_SUBDIR"]
      set ::env(Slicer3_MODULES_DIR) [file normalize "$::env(Slicer3_HOME)/@Slicer3_INSTALL_MODULES_LIB_DIR@/$::BUILD_SUBDIR"]
      set ::env(Slicer3_QTLOADABLEMODULES_DIR) [file normalize "$::env(Slicer3_HOME)/@Slicer3_INSTALL_QTLOADABLEMODULES_LIB_DIR@/$::BUILD_SUBDIR"]
    
    
      # QtDesigner variable  
      StoreDirInEnvVar Slicer3_QT_PLUGIN_PATH "@Slicer3_QT_PLUGIN_PATH@/$::QtDesignerPlugins_BUILD_SUBDIR"
      
    }
    
    set ::env(Slicer3_VERSION)    @Slicer3_VERSION_PATCH@
    
    # If reportVTKErrors is nonzero, then we check for VTK errors and
    # if a VTK error is found then launcher returns with error (causing the test to FAIL)
    set ::LAUNCH(reportVTKErrors) 0
    if {"@LAUNCHER_REPORT_VTK_ERRORS@"=="ON"} {
      set ::LAUNCH(reportVTKErrors) 1
    }
}

#-------------------------------------------------------------------------------
# .PROC launch_ParseArgs
# Setup launch options by parsing command-line parameters 
# .ARGS
# command-line parameter list
# .END
#-------------------------------------------------------------------------------
proc launch_ParseArgs {argv} {

  set ::LAUNCH(showSplash) 1
  set ::LAUNCH(launchCommand) ""
  set ::LAUNCH(launchDesigner) 0
  set ::LAUNCH(detach) 0

  # 
  # look for launcher-specific arguments
  #  --launch <program>
  # or 
  #  --launch-script <script.tcl>
  #    (this is a special case that runs the script
  #     in this interp and then exits)
  #
  #  --designer - Attempt to start Qt Designer
  #
  #  --no-error-popup - Don't display errors in a popup
  #
  #  --detach - Run the command without monitoring the stdio
  #
  # and obey --no-splash, but don't swallow it (pass it on to slicer)
  #

  set argv0 [lindex $::argv 0]
  set argv1 [lindex $::argv 1]
  switch -glob -- $argv0 {
    "--launch" {
      if { $argv1 == "" } {
        error "--launch requires argument of program to run"
      } else {
          set ::LAUNCH(launchCommand) $argv1
          regsub -all "\\\\" $::LAUNCH(launchCommand) "/" ::LAUNCH(launchCommand)
          set ::argv [lreplace $::argv 0 1]

          # don't show splash if running a custom command
          set ::LAUNCH(showSplash) 0
      }
    }
    "--designer" {
      if { $::Slicer3_USE_QT != "ON" } {
        ShowAndLogError "Failed to start Qt Designer - Slicer is *NOT* built with QT Support"
        exit $::EXIT_CODE_GENERIC_ERROR
      }
      set ::LAUNCH(launchDesigner) 1
      set ::argv [lreplace $::argv 0 1]
      set ::LAUNCH(showSplash) 0
    }
    "*.slicer" -
    "--launch-script" {
      set ::argv [lreplace $::argv 0 1]
      uplevel #0 source $argv1
      exit $::EXIT_CODE_NO_ERROR
    }
  }

  # check for the arguments
  set newargs ""
  foreach arg $::argv {
    switch -- $arg {
      "--help" -
      "-h" -
      "--no_splash" -
      "--no-splash" {
          set ::LAUNCH(showSplash) 0
          lappend newargs $arg ;# pass arg to Slicer3-real
      }
      "--test_mode" -
      "--test-mode" {
        set ::LAUNCH(showSplash) 0
        lappend newargs $arg ;# pass arg to Slicer3-real
      }
      "--detach" {
        set ::LAUNCH(detach) 1
      }      
      "--no-error-popup" {
        set ::LAUNCH(showErrorPopup) 0
      }      
      default {
        # escape any pipe characters 
        regsub -all "\\|" $arg "\\\\|" arg
        lappend newargs $arg
      }
    }
  }
  set ::argv $newargs
}


#-------------------------------------------------------------------------------
# .PROC launch_SetPaths
# Setup system path variables to find Slicer libraries 
# .ARGS
# .END
#-------------------------------------------------------------------------------
proc launch_SetPaths {} {

    foreach var {LD_LIBRARY_PATH TCLLIBPATH DYLD_LIBRARY_PATH PATH} {
        # if it is an empty string or doesn't exist, set the environment variable
        if { ![info exists ::env($var)] || $::env($var) == "" } {
            set ::env($var) " "
        }
    }

    #
    # add the necessary library directories, both Base and Modules, to the 
    # LD_LIBRARY_PATH environment variable
    #
    #
    # set the base library paths for this build 
    # 
    if {$::env(BUILD) == $::SOLARIS ||
        $::env(BUILD) == $::LINUX_64 || 
        $::env(BUILD) == $::LINUX} {
        # add vtk, slicer, and tcl bins
            set ::env(LD_LIBRARY_PATH) $::env(VTK_BIN_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(KWWidgets_LIB_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(QT_LIB_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(OpenIGTLink_LIB_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(BatchMake_LIB_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(bmModuleDescriptionParser_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(ITK_BIN_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(TCL_DIR)/lib:$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(TCL_DIR)/lib/itcl@INCR_TCL_VERSION_DOT@:$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(TCL_DIR)/lib/itk@INCR_TCL_VERSION_DOT@:$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(Teem_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(VTK_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(PYTHON_DIR)/lib:$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(FreeSurfer_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(IGT_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(ITKCommandIO_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(LoadableModule_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(MGHImageIO_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(MRML_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(MRMLCLI_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(ModuleDescriptionParser_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(MRMLIDImageIO_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(Qdec_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(RemoteIO_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(FileWatcher_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(SlicerIO_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(tclap_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(vtkITK_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(vtkTeem_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(qCTKWidgets_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(qVTKWidgets_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(qMRMLWidgets_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(Slicer3_LIB_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(Slicer3_PLUGINS_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(Slicer3_MODULES_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(Slicer3_QTLOADABLEMODULES_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(X11_LIB_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(SFW_LIB_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(LD_LIBRARY_PATH) $::env(Slicer3_COMPILER_DIR):$::env(LD_LIBRARY_PATH)
            set ::env(PATH) "$::env(PATH):$::env(TCL_DIR)/bin"
            set ::env(PATH) "$::env(PATH):$::env(Teem_DIR)"
            set ::env(PATH) "$::env(Slicer3_BIN_DIR):$::env(PATH)"
            set ::env(PATH) "$::env(Slicer3_PLUGINS_DIR):$::env(PATH)"
            set ::env(PATH) "$::env(Slicer3_MODULES_DIR):$::env(PATH)"
            set ::env(PATH) "$::env(Slicer3_QTLOADABLEMODULES_DIR):$::env(PATH)"
            set ::env(PATH) "$::env(QT_BINARY_DIR):$::env(PATH)"
            set ::env(QTDESIGNER_EXE) "designer"
            set ::env(QT_PLUGIN_PATH) "$::env(Slicer3_QT_PLUGIN_PATH)"
        } elseif {$::env(BUILD) ==  $::DARWIN || $::env(BUILD) == $::DARWIN_X86} { 
            # add vtk, slicer, and tcl bins
            set ::env(DYLD_LIBRARY_PATH) $::env(VTK_BIN_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(KWWidgets_LIB_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(QT_LIB_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(OpenIGTLink_LIB_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(BatchMake_LIB_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(bmModuleDescriptionParser_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(ITK_BIN_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(TCL_DIR)/lib:$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(TCL_DIR)/lib/itcl@INCR_TCL_VERSION_DOT@:$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(TCL_DIR)/lib/itk@INCR_TCL_VERSION_DOT@:$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(Teem_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(VTK_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(PYTHON_DIR)/lib:$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(FreeSurfer_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(IGT_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(ITKCommandIO_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(LoadableModule_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(MGHImageIO_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(MRML_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(MRMLCLI_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(ModuleDescriptionParser_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(MRMLIDImageIO_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(Qdec_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(RemoteIO_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(FileWatcher_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(SlicerIO_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(tclap_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(vtkITK_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(vtkTeem_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(qCTKWidgets_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(qVTKWidgets_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(qMRMLWidgets_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(Slicer3_LIB_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(Slicer3_PLUGINS_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(Slicer3_MODULES_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(DYLD_LIBRARY_PATH) $::env(Slicer3_QTLOADABLEMODULES_DIR):$::env(DYLD_LIBRARY_PATH)
            set ::env(PATH) "$::env(PATH):$::env(TCL_DIR)/bin"
            set ::env(PATH) "$::env(PATH):$::env(Teem_DIR)"
            set ::env(PATH) "$::env(Slicer3_BIN_DIR):$::env(PATH)"
            set ::env(PATH) "$::env(Slicer3_PLUGINS_DIR):$::env(PATH)"
            set ::env(PATH) "$::env(Slicer3_MODULES_DIR):$::env(PATH)"
            set ::env(PATH) "$::env(Slicer3_QTLOADABLEMODULES_DIR):$::env(PATH)"
            set ::env(PATH) "$::env(QT_BINARY_DIR):$::env(PATH)"
            set ::env(QTDESIGNER_EXE) "Designer.app"
            set ::env(QT_PLUGIN_PATH) "$::env(Slicer3_QT_PLUGIN_PATH)"
        } elseif {$::env(BUILD) == $::WINDOWS} {
            # add vtk, slicer, and tcl bins
            set ::env(Path) $::env(VTK_BIN_DIR)\;$::env(Path)
            set ::env(Path) $::env(KWWidgets_BIN_DIR)\;$::env(Path)
            set ::env(Path) $::env(QT_LIB_DIR)\;$::env(Path)
            set ::env(Path) $::env(OpenIGTLink_BIN_DIR)\;$::env(Path)
            set ::env(Path) $::env(BatchMake_BIN_DIR)\;$::env(Path)
            set ::env(Path) $::env(bmModuleDescriptionParser_DIR)\;$::env(Path)
            set ::env(Path) $::env(ITK_BIN_DIR)\;$::env(Path)
            set ::env(Path) $::env(TCL_DIR)/bin\;$::env(Path)
            set ::env(Path) $::env(TCL_DIR)/lib/itcl@INCR_TCL_VERSION_DOT@\;$::env(Path)
            set ::env(Path) $::env(TCL_DIR)/lib/itk@INCR_TCL_VERSION_DOT@\;$::env(Path)
            set ::env(Path) $::env(Teem_DIR)\;$::env(Path)
            set ::env(Path) $::env(PYTHON_DIR)\;$::env(Path)
            set ::env(Path) $::env(VTK_DIR)\;$::env(Path)
            set ::env(Path) $::env(FreeSurfer_DIR)\;$::env(Path)
            set ::env(Path) $::env(IGT_DIR)\;$::env(Path)
            set ::env(Path) $::env(ITKCommandIO_DIR)\;$::env(Path)
            set ::env(Path) $::env(LoadableModule_DIR)\;$::env(Path)
            set ::env(Path) $::env(MGHImageIO_DIR)\;$::env(Path)
            set ::env(Path) $::env(MRML_DIR)\;$::env(Path)
            set ::env(Path) $::env(MRMLCLI_DIR)\;$::env(Path)
            set ::env(Path) $::env(ModuleDescriptionParser_DIR)\;$::env(Path)
            set ::env(Path) $::env(MRMLIDImageIO_DIR)\;$::env(Path)
            set ::env(Path) $::env(Qdec_DIR)\;$::env(Path)
            set ::env(Path) $::env(RemoteIO_DIR)\;$::env(Path)
            set ::env(Path) $::env(FileWatcher_DIR)\;$::env(Path)
            set ::env(Path) $::env(SlicerIO_DIR)\;$::env(Path)
            set ::env(Path) $::env(tclap_DIR)\;$::env(Path)
            set ::env(Path) $::env(vtkITK_DIR)\;$::env(Path)
            set ::env(Path) $::env(vtkTeem_DIR)\;$::env(Path)
            set ::env(Path) $::env(qCTKWidgets_DIR)\;$::env(Path)
            set ::env(Path) $::env(qVTKWidgets_DIR)\;$::env(Path)
            set ::env(Path) $::env(qMRMLWidgets_DIR)\;$::env(Path)
            set ::env(Path) $::env(Slicer3_BIN_DIR)\;$::env(Path)
            set ::env(Path) $::env(Slicer3_LIB_DIR)\;$::env(Path)
            set ::env(Path) $::env(Slicer3_PLUGINS_DIR)\;$::env(Path)
            set ::env(Path) $::env(Slicer3_MODULES_DIR)\;$::env(Path)
            set ::env(Path) $::env(Slicer3_QTLOADABLEMODULES_DIR)\;$::env(Path)
            set ::env(Path) $::env(QT_BINARY_DIR)\;$::env(Path)
            set ::env(QTDESIGNER_EXE) "designer.exe"
            set ::env(QT_PLUGIN_PATH) $::env(Slicer3_QT_PLUGIN_PATH)
        } else {
            ShowAndLogError "Libraries: unknown build $::env(BUILD)"
        }

    # set the base tcl/tk library paths, using the previously defined TCL_LIB_DIR
    set ::env(TCL_LIBRARY) "$::env(TCL_DIR)/lib/tcl@TCL_TK_VERSION_DOT@"
    set ::env(TK_LIBRARY) "$::env(TCL_DIR)/lib/tk@TCL_TK_VERSION_DOT@"

    #
    # add the default search locations for tcl packages
    #
    set ::env(TCLLIBPATH) "$::env(VTK_DIR)/Wrapping/Tcl $::env(TCLLIBPATH)"
    set ::env(TCLLIBPATH) "$::env(KWWidgets_DIR)/Wrapping/Tcl $::env(TCLLIBPATH)"
    if { [info exists ::env(OpenIGTLink_DIR] } {
      set ::env(TCLLIBPATH) "$::env(OpenIGTLink_DIR)/Wrapping/Tcl $::env(TCLLIBPATH)"
    }
    set ::env(TCLLIBPATH) "$::env(Slicer3_HOME)/Base/Wrapping/Tcl/vtkSlicerBase $::env(TCLLIBPATH)"
    set ::env(TCLLIBPATH) "$::env(TCL_DIR)/lib/itcl@INCR_TCL_VERSION_DOT@ $::env(TCLLIBPATH)"
    set ::env(TCLLIBPATH) "$::env(TCL_DIR)/lib/itk@INCR_TCL_VERSION_DOT@ $::env(TCLLIBPATH)"
    set ::env(TCLLIBPATH) "$::env(TCL_DIR)/lib/iwidgets4.0.1 $::env(TCLLIBPATH)"
    set ::env(TCLLIBPATH) "$::env(TCL_DIR)/lib/blt2.4 $::env(TCLLIBPATH)"

    #
    # add the default search locations for python packages for a slicer build of python
    #

    if { "@Slicer3_USE_SYSTEM_PYTHON@" != "ON" } {
      if {$::env(BUILD) == $::WINDOWS} {
        set SEP ";"
        set ::env(PYTHON_DIR) "$::env(PYTHON_DIR)/.."
      } else {
        set SEP ":"
      }

      set ::env(PYTHONHOME) "$::env(PYTHON_DIR)"

      # check for existing variable to avoid empty entries in PYTHONPATH
      if { ![info exists ::env(PYTHONPATH)] } {
        set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib"
      } else {
        set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib$SEP$::env(PYTHONPATH)"
      }
      set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib/lib-tk$SEP$::env(PYTHONPATH)"
      set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib/site-packages$SEP$::env(PYTHONPATH)"
      set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib/site-packages/numpy$SEP$::env(PYTHONPATH)"
      set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib/site-packages/numpy/lib$SEP$::env(PYTHONPATH)"
      set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib/site-packages/numpy/core$SEP$::env(PYTHONPATH)"
      set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib/python2.6$SEP$::env(PYTHONPATH)"
      set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib/python2.6/site-packages$SEP$::env(PYTHONPATH)"
      set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib/python2.6/lib-tk$SEP$::env(PYTHONPATH)"
      set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib/python2.6/site-packages/numpy/lib$SEP$::env(PYTHONPATH)"
      set ::env(PYTHONPATH) "$::env(PYTHON_DIR)/lib/python2.6/site-packages/numpy/core$SEP$::env(PYTHONPATH)"
      set ::env(PYTHONPATH) "$::env(Slicer3_HOME)/lib/Slicer3/SlicerBaseGUI/Python$SEP$::env(PYTHONPATH)"
    }
}

#-------------------------------------------------------------------------------
# .PROC launch_SplashScreen
# Show splash screen (optional) 
# .ARGS
# .END
#-------------------------------------------------------------------------------
proc launch_SplashScreen {} {

  if { $::LAUNCH(showSplash) } {

    if { ($::env(BUILD) ==  $::DARWIN || $::env(BUILD) == $::DARWIN_X86) || [catch "package require Tk"] } {
      puts "Setting up launch environment..."
      set $::LAUNCH(showSplash) 0
      return
    }

    wm withdraw .
    launch_SplashShow
  }
  
  # windows always has a display, so get rid of the default window
  if { [string match -nocase "windows*" $::tcl_platform(os)] } {
    wm withdraw .
  }
}


#-------------------------------------------------------------------------------
# .PROC SplashKill
# Release the application grab on the splash window, destroy the window, and delete the image.
# .ARGS
# .END
#-------------------------------------------------------------------------------
proc launch_SplashKill {} { 

    # because this is called from bgerror, don't cause any errors 
    if {[info command .splash] != ""} {
        # release the grab
        grab release .splash
        destroy .splash
    }
}

#-------------------------------------------------------------------------------
# .PROC launch_SplashAnimate
# Animate splash screen by drawing dots. 
# .ARGS
# delay before displaying a new point
# .END
#-------------------------------------------------------------------------------
proc launch_SplashAnimate { {delayms 100} } {
  if {[info command .splash] != ""} {
    set dots [.splash.v cget -text]
    if { $dots == "**********" } { 
      set dots "*" 
    } else {
      set dots *$dots
    }
    .splash.v configure -text $dots
    update
    after $delayms "launch_SplashAnimate $delayms"
  }
}

#-------------------------------------------------------------------------------
# .PROC SplashShow
# Builds and displays a splash screen, .splash
# .ARGS
# int delayms how long to show the splash screen, defaults to 7000, in milliseconds
# .END
#-------------------------------------------------------------------------------
proc launch_SplashShow { {delayms 7000} } {

    set oscaling [tk scaling]
    # ignore screen based default scaling and pick scale so words show up nicely inside box
    tk scaling 1.5
    set width 500
    set height 200
    set splashfont [font create -family Helvetica -size 10]
    set splashfontb [font create -family Helvetica -size 10 -weight bold]
    toplevel .splash -relief raised -borderwidth 6 -width $width -height $height -bg white
    wm overrideredirect .splash 1
    set xcorner [expr [winfo screenwidth .splash]/2-($width/2)]
    set ycorner [expr [winfo screenheight .splash]/2-($height/2)]
    wm geometry .splash +$xcorner+$ycorner

    label .splash.t1 -text "Slicer3 starting up..." -bg white -font $splashfontb
    label .splash.t2 -text "" -bg white -fg red -font $splashfont
    label .splash.v -text "" -bg white -fg darkblue -font $splashfont

    place .splash.t1 -relx 0.5 -rely 0.30 -anchor center
    #place .splash.t2 -relx 0.5 -rely 0.50 -anchor center
    place .splash.v -relx 0.5 -rely 0.60 -anchor center
    update

    after 100 "launch_SplashAnimate 300" 

    bind .splash <1> launch_SplashKill
    after 10000 launch_SplashKill
    tk scaling $oscaling
}

#-------------------------------------------------------------------------------
# .PROC launch_FileEvent
# helper proc to handle text coming from the child process
# if output is set to 0, a variable ::globallines has to exist to buffer the lines
# .ARGS
# file pointer, output enable switch
# .END
#-------------------------------------------------------------------------------
set ::count 0
proc launch_FileEvent {fp {output 1}} {
    if {[eof $fp]} {
        set ret [catch "close $fp" res]
        set ::saved_errorCode $::errorCode
        set ::saved_errorInfo $::errorInfo
        set ::saved_result $res
        set ::saved_return $ret
        set ::END 1
    } else {
        gets $fp line
        if {$output == 1} {
            puts $line
        } else {
            if {$line != ""} {
                append ::globallines $line
            }
        }
        launch_SplashKill ;# just in case the pre-splash screen is still up
    }
}

#-------------------------------------------------------------------------------
# .PROC launch_RunProgram
# run the actual program 
# - check for a --launch argument for a replacement main app, otherwise run Slicer3-real
# - process the arguments to adjust the escape characters
# - launch the main app as a child process and monitor the stdout and return codes
# .ARGS
# .END
#-------------------------------------------------------------------------------
proc launch_RunProgram {} {

    #
    # change from tcl escape to shell escape for command line arguments 
    # that contain spaces -- note that shell notation only works for a single
    # level of nesting
    # - change backslashes to forward slashes (for windows paths)
    # - escape the spaces in each of the arguments (non-windows only)
    # - handle any escaped | where the \ was changed to / by mistake
    #
    regsub -all "\\\\" $::argv "/" ::argv
    regsub -all "/\\|" $::argv "\\\\|" ::argv
    if {$::env(BUILD) != $::WINDOWS} {
      set newargv ""
      foreach a $::argv {
          regsub -all " " $a "\\\ " a
          lappend newargv $a
      }
      set ::argv $newargv
    }

    if {$::env(BUILD) != $::WINDOWS} {
      # turn curly braces into quotes
      regsub -all "{|}" $::argv "\\\"" ::argv
    }

    #
    # If launchDesigner True,
    # let's update launchCommand with the complete path to Qt Designer
    #
    
    if { $::LAUNCH(launchDesigner)} {
      set ::LAUNCH(launchCommand) $::env(QT_BINARY_DIR)/$::env(QTDESIGNER_EXE)
      puts "Starting $::LAUNCH(launchCommand)"
      puts "Loading plugins from $::env(Slicer3_QT_PLUGIN_PATH)/designer"
    }

    #
    # launch the slicer main script as a sub-process and monitor the output
    # - process is started with the 'open' command through a pipe
    # - the file_event callback is triggered when subprocess has written to stdout
    # - pipe is closed when process exits, causing launcher to exit too.
    #
    # why? well, some messages only go to console stdout and we don't want to lose them.
    # Also, on windows if you block waiting for the process to exit the launcher would
    # be "Not Responding" and things like screen savers and power management might not 
    # work right.
    #

    # 
    # determine the correct arguments and executable for the platform
    #
    if { $::LAUNCH(launchCommand) == "" } {          
        if { [catch { set ::LAUNCH(launchCommand) $::Slicer3_REAL } res] } {
            ShowAndLogError "Failed to execute Slicer3_REAL: $res"
            exit $::EXIT_CODE_GENERIC_ERROR
        }              
    }

    set ::errorCode ""  
    set ::errorInfo ""  ;# reset error info so we are sure to get errors from the 
                         # launch and not leftovers from previous 'catch' calls

    # detach mode: start the executable and then go away
    if { $::LAUNCH(detach) } {
        exec $::LAUNCH(launchCommand) $::argv &
        exit $::EXIT_CODE_NO_ERROR
    }

    if {$::env(BUILD) == $::WINDOWS} {        
        if { [catch { set fp [open "| \"$::LAUNCH(launchCommand)\" $::argv" r] } res] } {
            ShowAndLogError "Failed to execute $::LAUNCH(launchCommand): $res"
            exit $::EXIT_CODE_GENERIC_ERROR
        }        
    } else {               
        if { [catch { set fp [open "| sh -c \"'$::LAUNCH(launchCommand)' $::argv \" |& cat" r] } res] } {
            ShowAndLogError "Failed to execute $::LAUNCH(launchCommand): $res"
            exit $::EXIT_CODE_GENERIC_ERROR
        }        
    }

    #
    # now go into a loop waiting for the child process
    # - the launch_FileEvent handles output from the child and
    #   also detects when the child exits and sets global variables
    #   to handle the return code
    #
    fileevent $fp readable "launch_FileEvent $fp"
    set ::END 0
    while { ![catch "pid $fp"] && ![eof $fp] } {
        vwait ::END
    }

    #
    # get the actual exit code of the child process
    #
    # strip the tcl stack information from the end of the errorInfo string
    set index [string last "    while executing" $::saved_errorInfo]
    set result ""
    if { $index != -1 } {
      set result [string range $::saved_errorInfo 0 $index]
    }

    set codeString [lindex $::saved_errorCode 0]
    switch $codeString {
      "" -
      "NONE" { 
        set code "$::EXIT_CODE_NO_ERROR" 
      }
      "CHILDKILLED" {
        set code "$::EXIT_CODE_CHILD_KILLED"
        set result "$result\n$::saved_errorCode"
      }
      "CHILDSTATUS" {
        set code [lindex $::saved_errorCode 2] 
      }
      default {
        set code "$::EXIT_CODE_GENERIC_ERROR"
        set result "Exceptional errorCode: $::saved_errorCode, $::saved_errorCode\n$::saved_errorInfo"
      }
    }
         
    # If the process returned without errors, but there are VTK errors in the output, then return with error code
    if { $code == "$::EXIT_CODE_NO_ERROR" && $::LAUNCH(reportVTKErrors) != 0 } {
      set vtkErrorString "ERROR: In "
      if { [string first $vtkErrorString $result] != -1 } {
        set code "$::EXIT_CODE_VTK_ERROR"
        set result "VTK error\n $result"
      }
    }         
         
    if { $result != "" } {
      if {$code != "$::EXIT_CODE_NO_ERROR"} {
        ShowAndLogError "Launch $::LAUNCH(launchCommand) returned with error: $result"
      } else {
        puts "$result"
      }
      
    }
    exit $code
}

#-------------------------------------------------------------------------------
# .PROC launch_ImportModulePaths
# run the program with the argument --print-module-paths to get the module path from
# registry so dependencies can be set before the actual program launch
# .ARGS
# .END
#-------------------------------------------------------------------------------
proc launch_ImportModulePaths {} {

    set ::globallines ""  ; # reset buffer for global lines

    # run the program with argument --print-module-paths
    if {$::env(BUILD) == $::WINDOWS} {
        set fp [open "| \"$::Slicer3_REAL\" --print-module-paths" r]
    } else {
        set fp [open "| sh -c \"'$::Slicer3_REAL' --print-module-paths \" |& cat" r]
    }

    # call the helper but do not pass thru output directly!
    fileevent $fp readable "launch_FileEvent $fp 0"
    set ::END 0    
    while { ![catch "pid $fp"] && ![eof $fp] } {
        vwait ::END
    }

    # we should have the module paths now

    # parse the svn revision of the version file
    set dp [open "$::env(Slicer3_HOME)/lib/Slicer3/Slicer3Version.txt" r]
    set data [read $dp]
    close $dp

    set exp {svnrevision ([0-9]+)}

    foreach {lines} [regexp -line $exp $data matched svnrevision] {
        if {$lines==1} {
            # find only one line
            # substitute @SVN@ in $result with the found svnrevision
            set newpath [string map [list \@SVN\@ $svnrevision] $::globallines]
        }
    }
    # set the dependencies
    if {$::env(BUILD) == $::SOLARIS ||
        $::env(BUILD) == $::LINUX_64 || 
        $::env(BUILD) == $::LINUX} {
      set ::env(LD_LIBRARY_PATH) ":$::env(LD_LIBRARY_PATH)"
      set ::env(LD_LIBRARY_PATH) "$newpath$::env(LD_LIBRARY_PATH)"
      set ::env(PATH) "$::env(PATH):$newpath"
    } elseif {$::env(BUILD) ==  $::DARWIN || $::env(BUILD) == $::DARWIN_X86} { 
      set ::env(DYLD_LIBRARY_PATH) ":$::env(DYLD_LIBRARY_PATH)"
      set ::env(DYLD_LIBRARY_PATH) "$newpath$::env(DYLD_LIBRARY_PATH)"
      set ::env(PATH) "$::env(PATH):$newpath"
    } elseif {$::env(BUILD) == $::WINDOWS} {
      set newpath [string map [list : \;] $newpath] ; # really needed?
      set ::env(Path) $newpath\;$::env(Path)
    }

}


######
#######  The actual steps for launching:
######

if { [catch launch_SetEnvironment res] } {
  ShowAndLogError "launch_SetEnvironment failed: $res"
  exit $::EXIT_CODE_LAUNCHING_ERROR
}
if { [catch {launch_ParseArgs $argv} res] } {
  ShowAndLogError "launch_ParseArgs failed: $res"
  exit $::EXIT_CODE_LAUNCHING_ERROR
}
if { [catch launch_SplashScreen res] } {
  ShowAndLogError "launch_SplashScreen failed: $res"
}
if { [catch launch_SetPaths res] } {
  ShowAndLogError "launch_SetPaths failed: $res"
  exit $::EXIT_CODE_LAUNCHING_ERROR
}
if { [catch launch_ImportModulePaths res] } {
  ShowAndLogError "launch_ImportModulePaths failed: $res"
  exit $::EXIT_CODE_LAUNCHING_ERROR
}
# run program until it exits and then exit this script with the ouput
if { [catch launch_RunProgram res] } {
  ShowAndLogError "launch_RunProgram failed: $res"
  exit $::EXIT_CODE_LAUNCHING_ERROR
}
