#!/usr/sgitcl/bin/moat
#Tag 0x00FFD000
###########################################################################
#                                                                         #
#               Copyright (C) 1995, Silicon Graphics, Inc.                #
#                                                                         #
#   These coded instructions, statements, and computer programs  contain  #
#   unpublished  proprietary  information of Silicon Graphics, Inc., and  #
#   are protected by Federal copyright law.  They  may  not be disclosed  #
#   to  third  parties  or copied or duplicated in any form, in whole or  #
#   in part, without the prior written consent of Silicon Graphics, Inc.  #
#                                                                         #
###########################################################################

#%COMMENT_BEGIN
# Filename:	dkMgr
# Version:	$Revision: 1.11 $
# Synopsis:	The main script for the XFSM disk manager.
# Functions:	dk:initialize
#		dk:createApplication
#		dk:createMenu
#		dk:createContents
#		dk:createIconPanelPopup
#		dk:searchCompleted
#		dk:openIconCb
#		dk:viewCb
#		dk:selectedCb
#		dk:_save
#		dk:_exit
#%COMMENT_END

global	_GD_dkm
global	_GW_dkm
global	_GW_dkmMenu
global	_GW_dkmPoMenu
global	G_data

#########################################
#	Widget Creation Procedures	#
#########################################
#%COMMENT_BEGIN
# Function:	dk:initialize
# Synopsis:	Initializes variables in preparation for starting the app.
#		This includes defining the menu structures for the pulldown
#		and popup menus and setting traces on variables.
# Arguments:	None
#%COMMENT_END
proc dk:initialize {} \
{
	global	_GD_dkm G_data env

	set _GD_dkm(class)	DISK
	set _GD_dkm(style)	Icon
	set _GD_dkm(commands)	{partition info template quit}
	set _GD_dkm(schemas)	{HALVES THIRDS FOURTHS FIFTHS
				 SIXTHS SEVENTHS EIGHTHS}

	set _GD_dkm(partition,sel)	{ false true true }
	set _GD_dkm(info,sel)		{ false true true  }
	set _GD_dkm(template,sel)	{ false true false }
	set _GD_dkm(quit,sel)		{ true  true true  }

	lappend _GD_dkm(menus) {selected xmCascadeButton {
			{partition xmPushButton}
			{info      xmPushButton}
			{template  xmPushButton}
			{sep1      xmSeparator}
			{quit      xmPushButton}
			}
		}

	lappend _GD_dkm(menus) {view xmCascadeButton {
			{search   xmPushButton}
			{sep1     xmSeparator}
			{asIcon   xmToggleButton}
			{asList   xmToggleButton}
			{asColumn xmToggleButton}
			{sep2     xmSeparator}
			{shelf    xmToggleButton}
			}
		}

	if {[info exists env(XFSTCL_DKSRC_DIR)]} {
		set G_data(sourcedir) $env(XFSTCL_DKSRC_DIR)
	} else {
		set G_data(sourcedir) /usr/xfsm/xdk
	}

	set _GD_dkm(quit,answer) false
	trace variable _GD_dkm(quit,answer) w dk:_exit
}

#%COMMENT_BEGIN
# Function:	dk:createApplication
# Synopsis:	The entry point for creating the widgets for the application.
# Arguments:	None
#%COMMENT_END
proc dk:createApplication {} \
{
	global	_GW_dkm _GW_dkmMenu _GW_dkmPoMenu _GD_dkm argv0 argv

	dk:initialize

	xmMainWindow .main managed
	xmPanedWindow .main.pane

	set menu [dk:createMenu .main]
	set form [dk:createContents .main.pane]
	$menu.selected cascadingCallback \
			"mu:ipSelectCb $_GW_dkm(panel) _GD_dkm _GW_dkmMenu"

	foreach item {Icon List Column} {
		ip:registerMVC dk $item $_GW_dkmMenu(as$item)
	}
	ip:registerMVC dk Shelf $_GW_dkmMenu(shelf)

	set item search
	$_GW_dkmMenu($item) activateCallback "dk:viewCb $_GW_dkm(panel) $item"

	####    Set initial state for the "selected" menu items
	mu:ipSelectCb $_GW_dkm(panel) _GD_dkm {_GW_dkmMenu _GW_dkmPoMenu}

	$menu manageChild
	$form manageChild

	$_GW_dkmMenu(asIcon) setValues -set true

	.main.pane manageChild
}

#%COMMENT_BEGIN
# Function:	dk:createMenu
# Synopsis:	Creates the menu bar at the top of the main window and
#		defines callbacks for the items in the "Selected" menu.
# Arguments:	None
#%COMMENT_END
proc dk:createMenu { parent } \
{
	global	_GW_dkmMenu _GD_dkm

	set mbar [xmMenuBar $parent.menuBar]
	foreach item $_GD_dkm(menus) {
		xfs:createMenu $parent $mbar $item _GW_dkmMenu
	}
	sgiHelpMenu $mbar "1.0"

	foreach item $_GD_dkm(commands) {
		$_GW_dkmMenu($item) activateCallback "dk:selectedCb $item"
	}

	return $mbar
}

#%COMMENT_BEGIN
# Function:	dk:createContents
# Synopsis:	Creates the icon panel and associated widgets.
# Arguments:	- parent	The parent for the icon panel.
#%COMMENT_END
proc dk:createContents { parent } \
{
	global	_GW_dkm _GW_dkmMenu _GW_dkmPoMenu _GD_dkm

	set form [xmForm $parent.form managed]

	set po_panel menu_selected
	set po_tmpl ""
	set _GW_dkm(panel) [ip:create dk $form $_GD_dkm(style) \
				po_panel po_tmpl true true]
	set _GW_dkm(tpanel) [ip:getTemplateWid dk]
	$_GW_dkm(panel) activateCallback Open "dk:openIconCb $_GW_dkm(panel)"
	$_GW_dkm(panel) activateCallback Drop "return 1"
#
#	"Select" does not get called when "Shift-Select" occurs.  Set the
#	sensitivity of menu items when the menu is popped up (mapCallback
#	for the popup menu and cascadingCallback for the pulldown menu).
#
#	$_GW_dkm(panel) postCallback Select "mu:ipSelectCb \
#			$_GW_dkm(panel) _GD_dkm {_GW_dkmMenu _GW_dkmPoMenu}"

	####	Disallow drops on template icon panel
	$_GW_dkm(tpanel) postCallback Drop \
			"tu:drop $_GD_dkm(class) $_GW_dkm(tpanel)"

	dk:createIconPanelPopup $po_panel

	return $form
}

#%COMMENT_BEGIN
# Function:	dk:createIconPanelPopup
# Synopsis:	Creates a popup menu on the icon panel.
# Arguments:	- po		The widget id for the popup menu.
#%COMMENT_END
proc dk:createIconPanelPopup { po } \
{
	global	_GW_dkm _GD_dkm _GW_dkmPoMenu

	xmPopupMenu $po
	xfs:createMenuItems $po $po \
		[lindex [lindex $_GD_dkm(menus) 0] 2] _GW_dkmPoMenu
	foreach item $_GD_dkm(commands) {
		$_GW_dkmPoMenu($item) activateCallback "dk:selectedCb $item"
	}

	$po mapCallback "mu:ipSelectCb $_GW_dkm(panel) _GD_dkm _GW_dkmPoMenu"
}

#########################################
#		Utilities		#
#########################################
#%COMMENT_BEGIN
# Function:	dk:searchCompleted
# Synopsis:	Resets the "Selected" menu items to their initial state.  When
#		a search is completed, the icons are replaced.  After a search
#		is done, all icons are unselected.  This ensures that the menu
#		items reflect that.
# Arguments:	None
#%COMMENT_END
proc dk:searchCompleted { } \
{
	global	_GW_dkm _GW_dkmMenu _GW_dkmPoMenu _GD_dkm

        ####    Reset initial state for the "selected" menu items
	mu:ipSelectCb $_GW_dkm(panel) _GD_dkm {_GW_dkmMenu _GW_dkmPoMenu}
}

#########################################
#		Callbacks		#
#########################################
#%COMMENT_BEGIN
# Function:	dk:openIconCb
# Synopsis:	The function that is defined for the "Open" action on the
#		icon panel.
# Arguments:	- panel		The widget id for the icon panel.
#%COMMENT_END
proc dk:openIconCb { panel } \
{
	dk:selectedCb partition

	#	Returning 1 here prevents the default "open"
	#	action from being invoked
	return 1
}

#%COMMENT_BEGIN
# Function:	dk:viewCb
# Synopsis:	This is called when the user selects an item from the "View"
#		pulldown menu.  This function ignores any item other than
#		"search", since all the other items have special callbacks
#		to ensure consistency with the view toggle buttons to the
#		left of the icon panel.
# Arguments:	- w		The widget id for the icon panel.
#		- op		Indicates which item was selected from the menu.
#%COMMENT_END
proc dk:viewCb { w op } \
{
	global  _GW_dkm _GD_dkm

	switch $op {
		search {
			dkSrch:realize dk "" $_GW_dkm(panel)
			dkSrch:manage dk
		}
	}
}

#%COMMENT_BEGIN
# Function:	dk:selectedCb
# Synopsis:	This is called when the user selects an item from the "Selected"
#		pulldown menu or the icon panel popup menu.  It creates a list
#		of object signatures representing each item that was selected
#		in the icon panel when the action was invoked.  It then
#		performs the action.
#		The procedure mu:ipSelectCb() ensures that a valid number
#		of icons are selected in the icon panel before this procedure
#		is called.
# Arguments:	- op		Indicates which item was selected from the menu.
#%COMMENT_END
proc dk:selectedCb { op } \
{
	global	_GW_dkm _GD_dkm G_data _GD_resources

	set chosen [$_GW_dkm(panel) selection -encode]
	if {! [ip:encodeToObject $chosen selected]} {
		####	TODO
	}

	. defineCursor watch

	switch $op {
	    template {
		svTmpl:realize dk ""
		svTmpl:fill dk $_GD_dkm(class) dk:_save dk
		svTmpl:manage dk
		set _GD_dkm(sv,obj) [lindex $selected 0]
	    }
	    partition {
		if {[llength $selected] == 1} {
			if {! [info exists _GD_dkm(source,dkPtDlg)]} {
				source $G_data(sourcedir)/dkPtDlg
				set _GD_dkm(source,dkPtDlg) true
				dkPt:realize dkPt ""
			}
			if {[dkPt:fill dkPt [lindex $selected 0]]} {
				dkPt:manage dkPt
			}
		} elseif {[llength $selected] > 1} {
			if {! [info exists _GD_dkm(source,dkMPtDlg)]} {
				source $G_data(sourcedir)/dkMPtDlg
				set _GD_dkm(source,dkMPtDlg) true
				dkMPt:realize dkMPt ""
			}
			if {[dkMPt:fill dkMPt $selected]} {
				dkMPt:manage dkMPt
			}
		}
	    }
	    info {
		if {! [info exists _GD_dkm(source,dkInfoDlg)]} {
			source $G_data(sourcedir)/dkInfoDlg
			set _GD_dkm(source,dkInfoDlg) true
			dkInfo:realize dkInfo ""
		}
		if {[dkInfo:fill dkInfo replace $selected]} {
			dkInfo:manage dkInfo
		}
	    }
	    quit {
		if {! [info exists _GW_dkm(quit,dialog)]} {
			set _GW_dkm(quit,dialog) [xmQuestionDialog .quitDlg \
				-messageString $_GD_resources(msg,quit) \
				-noResize true]
			$_GW_dkm(quit,dialog).Help unmanageChild
			$_GW_dkm(quit,dialog) okCallback \
				"set _GD_dkm(quit,answer) true"
		}
		$_GW_dkm(quit,dialog) manageChild
	    }
	}

	. defineCursor ""
}

#########################################
#		Utilities		#
#########################################
#%COMMENT_BEGIN
# Function:	dk:_save
# Synopsis:	This is called when the user presses the "Make Template" item
#		in the "Selected" menu.  It gets the data from the selected
#		object, creates an object signature and writes out the
#		information to the given file name in the template directory.
# Arguments:	- handle	The identifier for the desired instance.
#		- nm		The file name chosen by the user in which
#				to store the template.
#		- unique	Whether or not this template already exists
#				in the template directory.
#%COMMENT_END
proc dk:_save { handle nm unique } \
{
	global	_GD_dkm _GD_resources

	if {[lsearch -exact $_GD_dkm(schemas) $nm] != -1} {
		em:simpleMsg $handle warning \
			[format $_GD_resources(msg,tmpl,reserved) \
			$nm [join $_GD_dkm(schemas) {, }]]
		return 0
	}

	if {[catch {set data [xfsGetPartTable $_GD_dkm(sv,obj)]} error]} {
		regsub -all -- "\n" [string trim $error] "\n\t" nerr
		em:storeMsg $handle error \
		"Unable to get partition table for [obj:getName $_GD_dkm(sv,obj)].\n\t$nerr"
		return 0
	}

	set obj [list [list _TEMPLATE_ $_GD_dkm(class) $nm -]]
	if {[tu:write $_GD_dkm(class) $nm $obj $data]} {
		if {$unique} {
			ip:fillPanel dk $obj
		}
		return 1
	}

	return 0
}

#%COMMENT_BEGIN
# Function:	dk:_exit
# Synopsis:	This is called when the user confirms the exit action.  It
#		is called by setting a trace on a variable which is updated
#		when the user presses a dialog button in the confirmation
#		dialog.  If the user accepts the action, the application exits.
# Arguments:	- vname		The name of the traced variable.
#		- element	The variables element name if it is an array
#				element, otherwise an empty string.
#		-op		"r" for read, "w" for write, "u" for unset.
#%COMMENT_END
proc dk:_exit { vname element op } \
{
	if {$element != ""} {
		set vname ${vname}($element)
	}
	upvar $vname x

	if {$x} {
		exit 0
	}
}

#########################################
#		Initialization		#
#########################################
xtAppInitialize -class Xdkm
. getAppResources {
	{ hostName \
	  HostName \
	  "" \
	  _GD_resources(hostName) }
	{ hostsFile \
	  HostsFile \
	  /etc/hosts \
	  _GD_resources(hostsFile) }
	{ graphicBackground \
	  GraphicBackground \
	  orange1 \
	  _GD_resources(graphicBackground) }
	{ defaultPartType \
	  DefaultPartType \
	  efs \
	  _GD_resources(defaultPartType) }
	{ tmplReservedMsg \
	  TmplReservedMsg \
	  "Unable to save template as %s.  The following names \
	   are reserved: @n @n %s" \
	  _GD_resources(msg,tmpl,reserved) }
	{ cfrmQuit \
	  CfrmQuit \
	  "Do you really want to quit?" \
	  _GD_resources(msg,quit) }
	{ cfrmPartition \
	  CfrmPartition \
	  "Partition disk %s on %s?" \
	  _GD_resources(dkpt,msg,partition) }
	{ cfrmMPartition \
	  CfrmMPartition \
	  "Are you sure you want to partition multiple disks on %s?" \
	  _GD_resources(dkmpt,msg,partition) }
	{ mPartSelectTmpl \
	  MPartSelectTmpl \
	  "Please select a template with which to partition @n the disks." \
	  _GD_resources(dkmpt,msg,selTmpl) }
	{ mPartSelectAccept \
	  MPartSelectAccept \
	  "Click on \\\"Accept\\\" to begin partitioning the disks."
	  _GD_resources(dkmpt,msg,selAccept) }
	{ mPartInProgress \
	  MPartInProgress \
	  "Partitioning %s ..."
	  _GD_resources(dkmpt,msg,inProgress) }
	{ mPartDiskDone \
	  MPartDiskDone \
	  "Partitioning %s ... DONE"
	  _GD_resources(dkmpt,msg,diskDone) }
	{ mPartUserInterrupt \
	  MPartUserInterrupt \
	  "You have interrupted this procedure prior to partitioning @n \
	   disk \\\"%s\\\"."
	  _GD_resources(dkmpt,msg,userIntr) }
	{ mPartWarnInterrupt \
	  MPartWarnInterrupt \
	  "A non-fatal error has occured while preparing to partition @n \
	   disk \\\"%s\\\".  Make sure you understand the problem @n \
	   shown below if you decide to continue partitioning this disk. @n \
	   __________"
	  _GD_resources(dkmpt,msg,warnIntr) }
	{ mPartFatalInterrupt \
	  MPartFatalInterrupt \
	  "An unrecoverable error has occured while preparing to @n \
	   partition disk \\\"%s\\\". @n __________"
	  _GD_resources(dkmpt,msg,fatalIntr) }
	{ mPartNoInfo \
	  MPartNoInfo \
	  "Unable to get information for disk \\\"%s\\\" @n \ \\\ \\\ %s"
	  _GD_resources(dkmpt,msg,noInfo) }
	{ mPartBadInfo \
	  MPartBadInfo \
	  "Information for disk \\\"%s\\\" is incomplete."
	  _GD_resources(dkmpt,msg,badInfo) }
	{ mPartDiffDiskTmpl \
	  MPartDiffDiskTmpl \
	  "The template \\\"%s\\\" was not based upon the same @n \
	   %s disk as %s. @n @n \
	   If you partition this disk, the template will be scaled to match @n \
	   the size of the disk.  This may produce unintended side effects. @n \
	   After the partitioning has finished you should confirm that the @n \
	   partitions were created to your satisfaction." \
	  _GD_resources(dkmpt,msg,diffDiskTmpl) }
	{ dkSizeString \
	  DkSizeString \
	  "size" \
	  _GD_resources(msg,dkSize) }
	{ dkTypeString \
	  DkTypeString \
	  "type" \
	  _GD_resources(msg,dkType) }
	{ cfrmAutoScale \
	  CfrmAutoScale \
	  "The template \\\"%s\\\" was not based upon the same @n \
	   size disk as %s.  @n @n \
	   If you would like to auto-scale the template press 'Yes'. @n \
	   Press 'No' to use the template 'as-is'." \
	  _GD_resources(dkpt,msg,autoscale) }
    }

####	Set the path for autoloading
if {[info exists env(XFSTCL_TLIB)]} {
	set xsh_tlib $env(XFSTCL_TLIB)
} else {
	set xsh_tlib /usr/xfsm/lib/tlib
}
lvarpush auto_path $xsh_tlib

####	Load the dso
if {! [xfs:openDSO reason]} {
	exit 1
}

####	Parse any command line arguments - ignore any we don't understand
if {$argc != 0} {
	set hostname ""; set hostfile ""
	xfs:parseArgs hostname hostfile
	if {[clength $hostname]} { set _GD_resources(hostName) $hostname }
	if {[clength $hostfile]} { set _GD_resources(hostsFile) $hostfile }
}
if {! [clength $_GD_resources(hostName)]} {
	set _GD_resources(hostName) [exec /sbin/uname -n]
}

####	Make widgets
dk:createApplication
. realizeWidget

####	Set the view for the icon panel(s)
ip:viewCb dk true Icon

####    Must do this after ". realizeWidget"
source $G_data(sourcedir)/dkSrchDlg
dkSrch:realize dk "" $_GW_dkm(panel)
dkSrch:fill dk $_GD_resources(hostName)
dkSrch:_accept dk

####	Get all the existing templates
set templates [tu:getTemplates $_GD_dkm(class)]
ip:fillPanel dk $templates

. mainLoop
