#!/bin/csh -f
#
# XIMTOOL-ALT --  Script wrapper to start XImtool using the alternate GUI.
# The GUI file is contained is this script which is created when the system
# is built, it may be used to run any alternate GUI by simply replacing the
# Tcl script making up the GUI at the end of this script or by using the
# "-gui" command line flag.  The only configurable item is the path to the
# XImtool binary to be used, by default the one found in the user's path will
# be used.
#	Arguments specific to this GUI include:
#
#	    -displayMagnifier <bool>	show magnifier marker on startup
#	    -showToolBar <bool>		show toolbar on startup
#	    -showPanelBar <bool>	show panelbar on startup
#
#----------------------------------------------------------------------------

# Configurable parameters
set	XIMTOOL		= ximtool	# Path to default ximtool binary


#------------------------------------------------------------------
#--------------- Do not modify below this line --------------------
#------------------------------------------------------------------
unset 	noclobber
onintr	cleanup

set	SKIP		= 106		# offset to GUI file

# Dump the GUI from this script file.
tail +$SKIP $0 > /tmp/_gui.$$

# Check for no arguments.
set q	= '"'
set cmd = "-gui /tmp/_gui.$$ -title $q XImtool Experimental GUI $q"

# Process the script arguments, quoting args when necessary.
if ($#argv > 0) then
    while ("$1" != "")
        if ("$1" == "-xrm") then
	    if ("$2" != "") then
	        shift
	    else
	        echo "missing argument to '-xrm <resource>' switch"
	        exit 1
	    endif
	    set cmd = "$cmd -xrm $q$1$q"
        else if ("$1" == "-help") then
	     $XIMTOOL -help
	     exit 0
        else if ("$1" == "-defgui") then
	    tail +$SKIP $0
	    exit 0
        else if ("$1" == "-displayMagnifier") then
	    if ("$2" != "") then
	        shift
	    else
	        echo "missing argument to '-displayMagnifier <bool>' switch"
	        exit 1
	    endif
	    set cmd = "$cmd -xrm $q XImtool.displayMagnifier:$1$q"
        else if ("$1" == "-showToolBar") then
	    if ("$2" != "") then
	        shift
	    else
	        echo "missing argument to '-showToolBar <bool>' switch"
	        exit 1
	    endif
	    set cmd = "$cmd -xrm $q XImtool.showToolBar:$1$q"
        else if ("$1" == "-showPanelBar") then
	    if ("$2" != "") then
	        shift
	    else
	        echo "missing argument to '-showPanelBar <bool>' switch"
	        exit 1
	    endif
	    set cmd = "$cmd -xrm $q XImtool.showPanelBar:$1$q"
        else
	    set cmd = "$cmd $1"
        endif

        if ("$2" == "") then
	    break
	else
	    shift
	endif
    end
endif

# Run the command.
echo  "$XIMTOOL $cmd ; /bin/rm -f /tmp/_gui*.$$" > /tmp/_gui.cmds.$$
sh /tmp/_gui.cmds.$$

cleanup:
	/bin/rm -f /tmp/_gui*.$$
	exit 0

#--------------------------------------------------------------------------
#-------------------------- XIMTOOL-ALT.GUI -------------------------------
#------								     ------
#------  To change the GUI run by this script just delete everything ------
#------  below here and replace with the new GUI Tcl script.         ------
#------								     ------
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------

#!/usr/local/bin/obmsh
#
# XIMTOOL-MAG.GUI -- Default GUI for the Ximtool-mag image display server.
#
# Version 1.2 -- Released 4/30/2000


reset-server
appInitialize ximtool XImtool {
    *objects:\
	toplevel	Layout		display \
	display		Layout		menubar \
	menubar		MenuButton	fileButton \
	menubar		MenuButton	viewButton \
	menubar		MenuButton	optionsButton \
	menubar		TextBox		imageTitle \
	menubar		Toggle		panelButton \
	menubar		Toggle		xflipButton \
	menubar		Toggle		yflipButton \
	menubar		Command		prevButton \
	menubar		MenuButton	frameButton \
	menubar		Command		nextButton \
	menubar		Toggle		helpButton \
	display		Gterm		imagewin \
	display		Gterm		colorbar \
\
	toplevel	TopLevelShell	info \
	info		Paned		infoPanel \
	infoPanel	Box		infoBox \
	infoBox		Command		infoDone \
	infoBox		Command		infoDown \
	infoBox		Command		infoUp \
	infoBox		Command		infoSave \
	infoBox		Command		infoUpdate \
	infoBox		Command		infoClear \
	infoPanel	AsciiText	infoText \
\
	toplevel	TopLevelShell	controlShell \
	controlShell	Layout		controlPanel \
	controlPanel	Group		viewBox \
	controlPanel	Group		enhancementBox \
	controlPanel	Group		blinkBox \
	controlPanel	Group		optionsBox \
	controlPanel	Frame		controlBox \
\
	viewBox		Layout		view \
	view		Group		frameSelect \
	frameSelect	Layout		frameBox \
	frameBox	TextToggle	frame1 \
	frameBox	TextToggle	frame2 \
	frameBox	TextToggle	frame3 \
	frameBox	TextToggle	frame4 \
	frameBox	Command		prevFrame \
	frameBox	Command		nextFrame \
	view		Frame		frameDataBox \
	frameDataBox	TextBox		frameData \
	view		Group		zoomBox \
	zoomBox		Layout		zoom \
	zoom		TextButton	toggleZoom \
	zoom		TextButton	zoomIn \
	zoom		Command		x1 \
	zoom		Command		z2 \
	zoom		Command		z3 \
	zoom		Command		z4 \
	zoom		Command		z5 \
	zoom		Command		z8 \
	zoom		TextButton	zoomOut \
	zoom		TextButton	centerFrame \
	zoom		Command		d2 \
	zoom		Command		d3 \
	zoom		Command		d4 \
	zoom		Command		d5 \
	zoom		Command		d8 \
	view		Layout		viewButtons \
	viewButtons	Command		aspect \
	viewButtons	Command		flipX \
	viewButtons	Command		flipY \
	viewButtons	Command		flipXY \
	viewButtons	Command		clearFrame \
	viewButtons	Command		fitFrame \
\
	enhancementBox	Layout		enhance \
	enhance		Scrollbar2	colorlistScroll \
	enhance		Frame		colorlistFrame \
	colorlistFrame	Porthole	colorlistPort \
	colorlistPort	MultiList	colorlist \
	enhance		Frame		colordataFrame \
	colordataFrame	TextBox		colordata \
	enhance		Label		contrastLabel \
	enhance		Slider2d	contrastSlider \
	enhance		Label		brightnessLabel \
	enhance		Slider2d	brightnessSlider \
	enhance		Command		invertButton \
	enhance		Command		optimizeButton \
\
	blinkBox	Layout		blink \
	blink		Label		blinkFramesLabel \
	blink		Command		blinkFrame1 \
	blink		Command		blinkFrame2 \
	blink		Command		blinkFrame3 \
	blink		Command		blinkFrame4 \
	blink		Command		blinkReset \
	blink		Label		blinkRateLabel \
	blink		Frame		BRframe \
	BRframe		Layout		BRlayout \
	BRlayout	Arrow		BRdecrease \
	BRlayout	TextBox		BRtext \
	BRlayout	Arrow		BRincrease \
	blink		Command		registerButton \
	blink		Command		matchButton \
	blink		Toggle		blinkButton \
\
	optionsBox	TextToggle	pannerButton \
	optionsBox	TextToggle	magnifierButton \
	optionsBox	TextToggle	coordsBoxButton \
	optionsBox	TextToggle	autoscaleButton \
	optionsBox	TextToggle	antialiasButton \
	optionsBox	TextToggle	tileFramesButton \
	optionsBox	TextToggle	warningsButton \
\
	controlBox	Layout		control \
	control		Command		initializeButton \
	control		Command		normalizeButton \
	control		Command		doneButton \
\
        toplevel        TopLevelShell   tclShell\
        tclShell        Paned           tclPanel\
        tclPanel        Box             tclForm\
        tclForm         Label           tclLabel\
        tclForm         Command         tclClear\
        tclForm         Command         tclExecute\
        tclForm         Command         tclcloseButton\
        tclPanel        AsciiText       tclEntry\
\
	toplevel	TransientShell	warning \
	warning		Layout		warn \
	warn		Frame		warnFrame \
	warnFrame	Layout		WFlayout \
	WFlayout	Icon		warnIcon \
	WFlayout	TextBox		warnText \
	warn		TextButton	warnOk \
	warn		TextButton	warnCancel \
	warn		TextButton	warnHelp \
\
	toplevel	TopLevelShell	print_panel\
	print_panel	Layout		printLayout\
\
	printLayout	Group		printCmdGroup\
	printLayout	Group		optGroup\
	printLayout	Group		cmdGroup\
\
	printCmdGroup	Layout		printCmdLayout\
	printCmdLayout	Layout		labelLayout\
	labelLayout	Label		toLabel\
	labelLayout	Label		printerLabel\
	printCmdLayout	Layout		inputLayout\
	inputLayout	TextToggle	toPrinter\
	inputLayout	TextToggle	toFile\
	inputLayout	Frame		printcmdFrame\
	printcmdFrame	AsciiText	printcmd\
\
	optGroup	Layout		optLayout\
	optLayout	Group		epsPageGroup\
	optLayout	Group		optionsGroup\
	optLayout	Group		printColorGroup\
	optLayout	Group		printerGroup\
\
        epsPageGroup    Layout          epsPage\
        epsPage         Label           epsOrientLabel\
	epsPage    	TextToggle	epsPortButton\
	epsPage    	TextToggle	epsLandButton\
        epsPage         Label           epsSizeLabel\
	epsPage    	TextToggle	epsLetterButton\
	epsPage    	TextToggle	epsLegalButton\
	epsPage    	TextToggle	epsA4Button\
        epsPage         Label           epsScaleLabel\
        epsPage         Frame           ScaleFrame \
        ScaleFrame      Layout          ScaleLayout \
        ScaleLayout     Arrow           SCdecrease \
        ScaleLayout     TextBox         SCtext \
        ScaleLayout     Arrow           SCincrease \
\
        optionsGroup    Layout          options\
        options         TextToggle      epsscaleButton\
        options         TextToggle      autorotateButton\
        options         TextToggle      aspectButton\
        options         TextToggle      annotateButton\
        options         TextToggle      compressButton\
\
        printColorGroup Layout          printColor\
        printColor      TextToggle      prGrayButton\
        printColor      TextToggle      prPseudoButton\
	printColor	TextToggle	prRGBButton\
\
        printerGroup    Layout          printers \
        printers        Scrollbar2      printlistScroll \
        printers        Frame           printlistFrame \
        printlistFrame  Porthole        printlistPort \
        printlistPort   MultiList       printlist \
\
	cmdGroup	Layout		cmdLayout\
	cmdLayout	TextButton	okayPrint\
	cmdLayout	Label		printStatus\
	cmdLayout	TextButton	donePrint\
\
	toplevel	TopLevelShell	save_panel\
	save_panel	Layout		saveLayout\
\
	saveLayout	Group		saveNameGroup\
	saveLayout	Group		saveOptGroup\
	saveLayout	Group		saveCmdGroup\
\
	saveNameGroup	Layout		saveNameLayout\
	saveNameLayout	Label		saveLabel\
	saveNameLayout	Frame		fnameFrame\
	fnameFrame	AsciiText	saveFile\
\
	saveOptGroup	Layout		saveOptLayout\
	saveOptLayout	Group		fmtGroup\
	saveOptLayout	Group		saveColorGroup\
	saveOptLayout	Frame		saveDataBox \
	saveDataBox	TextBox		saveData \
\
	fmtGroup	Layout		formats\
        formats        	TextToggle      rasButton\
        formats        	TextToggle      gifButton\
        formats        	TextToggle      jpegButton\
	formats		TextToggle	tiffButton\
        formats        	TextToggle      fitsButton\
	formats		TextToggle	x11Button\
        formats        	TextToggle      pnmButton\
	formats		TextToggle	rawButton\
\
        saveColorGroup  Layout          saveColor\
        saveColor       TextToggle      svGrayButton\
        saveColor       TextToggle      svPseudoButton\
	saveColor	TextToggle	svRGBButton\
\
	saveCmdGroup	Layout		saveCmdLayout\
	saveCmdLayout	TextButton	okaySave\
	saveCmdLayout	Label		saveStatus\
	saveCmdLayout	TextButton	doneSave\
\
	toplevel        TopLevelShell   load_panel \
	load_panel	Layout          filesLayout \
	filesLayout	Group		imagesGroup \
	imagesGroup	Layout		imagesLayout \
	imagesLayout	Label		imtemplateLabel \
	imagesLayout	Frame		imtemplateFrame \
	imtemplateFrame	AsciiText	imtemplateText \
	imagesLayout	Scrollbar2	imlistScrollbar \
	imagesLayout	Frame		imlistFrame \
	imlistFrame	Porthole	imlistPorthole \
	imlistPorthole	MultiList	imageList \
	imagesLayout	TextButton	rootButton \
	imagesLayout	TextButton	homeButton \
	imagesLayout	TextButton	upButton \
	imagesLayout	TextButton	rescanButton \
	imagesLayout	TextToggle	grayToggle \
	imagesLayout	TextToggle	browseToggle \
	imagesLayout	Label		dirLabel \
	imagesLayout	Label		fnameLabel \
	imagesLayout	Frame		filnamFrame \
	imagesLayout	Label		frameLabel \
	imagesLayout	Command		frameFrame \
	filnamFrame	AsciiText	fnameText \
\
	filesLayout	Group		fbuttonsGroup \
	fbuttonsGroup	Layout		fbuttonsLayout \
	fbuttonsLayout	Command		filesLoadButton \
	fbuttonsLayout	Label		filesStatus \
	fbuttonsLayout	Command		filesCloseButton \
\
	toplevel	TopLevelShell	help_panel \
	help_panel	Layout		helpLayout \
	helpLayout	Layout		helpMenuLayout \
	helpLayout	Layout		helpInfoLayout \
\
	helpMenuLayout	Command		helpBack \
	helpMenuLayout	Command		helpForward \
	helpMenuLayout	Command		helpHome \
	helpMenuLayout	Command		helpClose \
\
	helpLayout	Frame		helpTextFrame\
	helpTextFrame	HTML            helpText \
\
	helpInfoLayout	Label		helpIRAFLogo \
	helpInfoLayout	Label		helpInfo1 \
	helpInfoLayout	Label		helpInfo2 \
	helpInfoLayout	Label		helpInfo3 \
	helpInfoLayout	Label		helpNOAOLogo \
\
	toplevel	Parameter	ximtool\
	ximtool		Parameter	alert\
	ximtool		Parameter	initialize\
	ximtool		Parameter	resize\
	ximtool		Parameter	frame\
	ximtool		Parameter	nframes\
	ximtool		Parameter	frameSize\
	ximtool		Parameter	frameRegion\
	ximtool		Parameter	frameView\
	ximtool		Parameter	frameTitle\
	ximtool		Parameter	frameFit\
	ximtool		Parameter	enhancement\
	ximtool		Parameter	colortables\
	ximtool		Parameter	autoscale\
	ximtool		Parameter	antialias\
	ximtool		Parameter	tileFrames\
	ximtool		Parameter	cursorMode\
	ximtool		Parameter	xflip\
	ximtool		Parameter	yflip\
	ximtool		Parameter	printerList\
	ximtool		Parameter	printOptions\
	ximtool		Parameter	loadOptions\
	ximtool		Parameter	saveOptions\
	ximtool		Parameter	filelist\
	ximtool		Parameter	help


    ! Main image window resources.
    ! -------------------------------
    *allowShellResize:				True
    *beNiceToColormap:				False
    *menuLabel.foreground:			Gold
    *markerMenu.foreground:			Black
    *markerMenu.background:			SteelBlue
    *markerMenu*SimpleMenu.foreground:		Black
    *markerMenu*SimpleMenu.background:		SteelBlue
    *markerColor.SmeBSB.leftMargin:		64
    *markerColor.SmeBSB.rightMargin:		0
    *markerColor.menuLabel.leftMargin:		5
    *markerColor.menuLabel.rightMargin:		5

    *display.background:			gray
    *display.borderWidth:			0

    *display.debug:				False
    *display.layout: horizontal { \
	-1 \
	vertical { \
	    3 \
	    menubar < +inf -inf * > \
	    3 \
	    imagewin < +inf -inf * +inf - inf > \
	    3 \
	    colorbar < +inf -inf * > \
	} \
	-1 \
    }

    *menubar.layout: horizontal { \
	1 < -1 > \
	fileButton 1 < -1 > viewButton 1 < -1 > optionsButton \
	1 < -1 > \
	imageTitle < +inff -inff * > \
	1 < -1 > \
	panelButton 1 < -1 > \
	1 < -1 > \
	xflipButton 1 < -1 > yflipButton \
	1 < -1 > \
	prevButton 1 < -1 > frameButton 1 < -1 > nextButton \
	1 < -1 > \
	helpButton \
	1 < -1 > \
    }

    *menubar*SimpleMenu.foreground:		Black
    *menubar*SimpleMenu.background:		gray65
    *menubar*SimpleMenu.borderColor:		Black
    *menubar*SimpleMenu.borderWidth:		1
    *SmeBSB.vertSpace:				10

    *SimpleMenu*font:	  -adobe-times-bold-r-normal-*-12-*-*-*-*-*-iso8859-1
    *fileButton.font:	  -adobe-times-bold-i-normal-*-12-*-*-*-*-*-iso8859-1
    *optionsButton.font:  -adobe-times-bold-i-normal-*-12-*-*-*-*-*-iso8859-1
    *viewButton.font:     -adobe-times-bold-i-normal-*-12-*-*-*-*-*-iso8859-1

    *menubar.width:				512
    *menubar*background:			gray
    *menubar*foreground:			black
    *menubar*borderWidth:			0
    *menubar*Command.label:			x
    *menubar*Command.internalWidth:		0
    *menubar*Command.borderWidth:		0
    *menubar*Toggle.label:			x
    *menubar*Toggle.internalWidth:		0
    *menubar*Toggle.borderWidth:		0

    *fileButton.label:				File
    *fileButton.menuName:			fileMenu
    *viewButton.label:				View
    *viewButton.menuName:			viewMenu
    *optionsButton.label:			Options
    *optionsButton.menuName:			optionsMenu
    *imageTitle*font:				*times-bold-r*12*
    *imageTitle.width:				40
    *imageTitle.height:				20
    *frameButton.menuName:			frameMenu
    *frameButton.label:				1
    *frameButton.width:				20

    *Gterm.cmapName:				image
    *Gterm.basePixel:				64
    *imagewin.warpCursor:			true
    *imagewin.raiseWindow:			true
    *imagewin.deiconifyWindow:			true
    *imagewin.ginmodeCursor:			circle
    *imagewin.ginmodeBlinkInterval:		500
    *imagewin.resizable:			true
    *imagewin.copyOnResize:			false
    *imagewin.width:				512
    *imagewin.height:				512
    *imagewin.color8:				#7c8498
    *imagewin.color9:				steelblue

    *imagewin.translations:     \
        None<Key>Left: call(move_cursor,-1,0)                   \n\
        None<Key>Down: call(move_cursor,0,1)                    \n\
          None<Key>Up: call(move_cursor,0,-1)                   \n\
       None<Key>Right: call(move_cursor,1,0)                    \n\
     !Shift <Key>Left: call(move_cursor,-10,0)                  \n\
     !Shift <Key>Down: call(move_cursor,0,10)                   \n\
       !Shift <Key>Up: call(move_cursor,0,-10)                  \n\
    !Shift <Key>Right: call(move_cursor,10,0)                   \n\
         !Ctrl <Key>h: call(move_cursor,-1,0)                   \n\
         !Ctrl <Key>j: call(move_cursor,0,1)                    \n\
         !Ctrl <Key>k: call(move_cursor,0,-1)                   \n\
         !Ctrl <Key>l: call(move_cursor,1,0)                    \n\
   !Ctrl Shift <Key>h: call(move_cursor,-10,0)                  \n\
   !Ctrl Shift <Key>j: call(move_cursor,0,10)                   \n\
   !Ctrl Shift <Key>k: call(move_cursor,0,-10)                  \n\
   !Ctrl Shift <Key>l: call(move_cursor,10,0)                   \n\
          !Alt <Key>1: call(cpSetFrame,frame1)               	\n\
          !Alt <Key>2: call(cpSetFrame,frame2)               	\n\
          !Alt <Key>3: call(cpSetFrame,frame3)               	\n\
          !Alt <Key>4: call(cpSetFrame,frame4)               	\n\
         !Ctrl <Key>1: call(cpZoom,1,1,fixed) 			\n\
         !Ctrl <Key>2: call(cpZoom,2,2,fixed) 			\n\
         !Ctrl <Key>3: call(cpZoom,3,3,fixed) 			\n\
         !Ctrl <Key>4: call(cpZoom,4,4,fixed) 			\n\
         !Ctrl <Key>5: call(cpZoom,5,5,fixed) 			\n\
         !Ctrl <Key>6: call(cpZoom,6,6,fixed) 			\n\
         !Ctrl <Key>7: call(cpZoom,7,7,fixed) 			\n\
         !Ctrl <Key>8: call(cpZoom,8,8,fixed) 			\n\
         !Ctrl <Key>9: call(cpZoom,9,9,fixed) 			\n\
         !Ctrl <Key>b: call(prevFrame,$name)                 	\n\
         !Ctrl <Key>c: call(cpZoomAction,centerFrame)        	\n\
         !Ctrl <Key>f: call(nextFrame,$name)                 	\n\
         !Ctrl <Key>i: call(cpInvert)                 		\n\
         !Ctrl <Key>n: call(normalize)                       	\n\
         !Ctrl <Key>m: call(toggleMagnifier)                    \n\
         !Ctrl <Key>p: call(togglePanner)                       \n\
     !Ctrl Alt <Key>q: call(Quit)               		\n\
         !Ctrl <Key>r: call(cpRegisterFrames)                	\n\
         !Ctrl <Key>s: call(cpMatchFrames)                   	\n\
         !Ctrl <Key>t: call(tileFramesToggle)                  	\n\
         !Ctrl <Key>u: call(cpZoom,1,1,fixed) 			\n\
         !Ctrl <Key>x: call(cpFrameAction,flipX)               	\n\
         !Ctrl <Key>y: call(cpFrameAction,flipY)               	\n\
     !Ctrl Alt <Key>=: call(Print)                              \n\
          Ctrl <Key>+: call(cpZoom,2.0,2.0,relative)            \n\
          Ctrl <Key>-: call(cpZoom,0.5,0.5,relative)            \n\
         Ctrl <Key>\<: call(cpSetBlinkRate,BRdecrease)          \n\
         Ctrl <Key>\>: call(cpSetBlinkRate,BRincrease)          \n\
          !Alt <Key>b: call(toggleBlink)            		\n\
          !Alt <Key>c: call(panel)               		\n\
     !Ctrl Alt <Key>f: call(fitFrame)            		\n\
          !Alt <Key>h: call(Help)                 		\n\
          !Alt <Key>i: call(infoPanel)               		\n\
          !Alt <Key>l: call(loadPanel)               		\n\
          !Alt <Key>p: call(printPanel)               		\n\
          !Alt <Key>s: call(savePanel)               		\n\
          !Alt <Key>t: call(tclPanel)               		\n\
     !Shift<Btn1Down>: call(setDynamicMagnifier,1)              \n\
       !Shift<Btn1Up>: call(setDynamicMagnifier,0)              \n\
          !<Btn1Down>: call(makeMarker,$name,$x,$y) m_create()	\n\
    !Shift <Btn2Down>: crosshair(on)                         	\n\
  !Shift <Btn2Motion>: crosshair(on)                         	\n\
       !Shift<Btn2Up>: crosshair(off)                        	\n\
            !<Btn2Up>: crosshair(off)                        	\n\
          !<Btn2Down>: call(zoom,$x,$y)                      	\n\
          !<Btn3Down>: call(windowColormap,$x,$y)            	\n\
        !<Btn3Motion>: call(windowColormap,$x,$y)            	\n\
        <EnterWindow>: enter-window()                        	\n\
        <LeaveWindow>: leave-window()                        	\n\
           <KeyPress>: graphics-input()                      	\n\
             <Motion>: track-cursor() call(wcsUpdate,$x,$y) call(magnifierMapImage,$x,$y)

! The following translations can be used to enable windowing of the
! individual RGB components of the colormap.  It's not very useful but
! included here for those that may wish to use it.
!--------------------------------------------------------------------------
!     !Ctrl <Btn1Down>: call(windowRGB,1,$x,$y,0)               	\n\
!   !Ctrl <Btn1Motion>: call(windowRGB,1,$x,$y,0)               	\n\
!       !Ctrl <Btn1Up>: call(windowRGB,1,$x,$y,1)               	\n\
!     !Ctrl <Btn2Down>: call(windowRGB,2,$x,$y,0)               	\n\
!   !Ctrl <Btn2Motion>: call(windowRGB,2,$x,$y,0)               	\n\
!       !Ctrl <Btn2Up>: call(windowRGB,2,$x,$y,1)               	\n\
!     !Ctrl <Btn3Down>: call(windowRGB,3,$x,$y,0)               	\n\
!   !Ctrl <Btn3Motion>: call(windowRGB,3,$x,$y,0)               	\n\
!       !Ctrl <Btn3Up>: call(windowRGB,3,$x,$y,1)               	\n\

    *colorbar.maxRasters:			1
    *colorbar.maxMappings:			1
    *colorbar.width:				512
    *colorbar.height:				10

    ! INFO box resources.
    ! ------------------------------
    *info.geometry:				420x240
    *info.title:				Information Panel
    *info*Command.font:				7x13bold
    *infoPanel*background:			gray
    *infoDone.label:				Done
    *infoDown.label:				Down
    *infoDown.sensitive:			False
    *infoUp.label:				Up
    *infoUp.sensitive:				False
    *infoSave.label:				Save
    *infoSave.sensitive:			False
    *infoUpdate.label:				Update
    *infoClear.label:				Clear
    *infoText*scrollVertical:			always
    *infoText*scrollHorizontal:			whenNeeded
    *infoText*displayCaret:			False
    *infoText*editType:				append
    *info*ScrollbarBackground:                  #c0c0c0
    *info*Scrollbar*background:                 #c0c0c0
    *info*Scrollbar*width:                      17
    *info*Scrollbar*height:                     17
    *info*Scrollbar*shadowWidth:                2
    *info*Scrollbar*cursorName:                 top_left_arrow
    *info*Scrollbar*pushThumb:                  true


    ! Main Control Panel.
    ! ------------------------------
    *controlShell.title:			XImtool Control
    *controlShell.iconName:			XimCon
    *controlPanel*background:			gray
    *controlPanel*foreground:			black
    *controlPanel*TextBox.background:		gray63
    *controlPanel*internalWidth:		0
    *controlPanel*borderWidth:			0
    *controlPanel*Command.highlightThickness:	0

    *TextBox.font:	7x13bold
    *TextToggle.font:	-adobe-times-medium-r-normal-*-12-*-*-*-*-*-iso8859-1
    *Command.font:	-adobe-times-medium-r-normal-*-12-*-*-*-*-*-iso8859-1
    *Toggle.font:	-adobe-times-medium-r-normal-*-12-*-*-*-*-*-iso8859-1
    *Label.font:	-*-helvetica-medium-r-normal-*-12-*-iso8859-1
    *MultiList.font:	-adobe-times-medium-r-normal-*-12-*-*-*-*-*-iso8859-1
    *toggleZoom.font:	-*-helvetica-medium-r-normal-*-12-*-iso8859-1
    *centerFrame.font:	-*-helvetica-medium-r-normal-*-12-*-iso8859-1
    *zoom*Command.font:	7x13bold
    *blinkFrame1.font:	7x13bold
    *blinkFrame2.font:	7x13bold
    *blinkFrame3.font:	7x13bold
    *blinkFrame4.font:	7x13bold

    *controlPanel.debug:			False
    *controlPanel.layout: vertical { \
	5 < -5 > \
	horizontal { \
	    -1 \
	    viewBox < +inf -inf * > \
	    -1 \
	} \
	5 < -5 > \
	horizontal { \
	    -1 \
	    enhancementBox < +inf -inf * +inf -inf > \
	    -1 \
	    vertical { \
		-1 \
		blinkBox < * +inf - inf > \
		 1 \
		optionsBox < * +inff -inff > \
		-1 \
	    } \
	    -1 \
	} \
	controlBox < +inf * > \
    }

    ! VIEW
    ! ------------------
    *viewBox.label:				View
    *viewBox.location:				0 0 410 0
    *viewBox.shrinkToFit:			True
    *viewBox.outerOffset:			5

    *view.debug:				False
    *view.layout: vertical { \
	5 < +inf -5 > \
	horizontal { \
	    -1 \
	    frameSelect \
	    -1 \
	    vertical { \
		5 < -5 > \
		frameDataBox < +inff -100% * +inff -100% > \
		5 < -5 > \
	    } \
	    -1 \
	    zoomBox \
	    -1 \
	} \
	1 < +inf > \
	viewButtons < +inf -inf * +inf -inf > \
	5 < +inf -5 > \
    }

    *frameDataBox.frameType:			sunken
    *frameDataBox.frameWidth:			2
    *frameData.width:				130
    *frameData.height:				50

    *frameSelect.location:			0 0 72 0
    *frameSelect.shrinkToFit:			True
    *frameSelect.outerOffset:			5
    *frameSelect.innerOffset:			5
    *frameSelect.frameWidth:			2
    *frameSelect*offIcon:			diamond0s
    *frameSelect*onIcon:			diamond1s
    *frameSelect*highlightColor:		blue
    *frameSelect.label:				Frame:

    *frameBox.debug:				False
    *frameBox.layout: vertical { \
	frame1 < +inf * > \
	frame2 < +inf * > \
	frame3 < +inf * > \
	frame4 < +inf * > \
	10 < +inf -10 > \
	horizontal { \
	    -1 \
	    prevFrame \
	    10 < +inf -5 > \
	    nextFrame \
	    -1 \
	} \
	-1 \
    }

    *frameBox*location:				0 0 10 20
    *frameBox*alignment:			left
    *frameBox*frameWidth:			0
    *frameBox*highlightThickness:		0
    *frameBox*frame1.label:			\ 1\ \ 
    *frameBox*frame2.label:			\ 2\ \ 
    *frameBox*frame3.label:			\ 3\ \ 
    *frameBox*frame4.label:			\ 4\ \ 
    *frameBox*Command.width:			24
    *frameBox*prevFrame.label:			xx
    *frameBox*nextFrame.label:			xx

    *zoomBox.label:				Zoom:
    *zoomBox.location:				0 0 160 127
    *zoomBox.outerOffset:			5
    *zoomBox.shrinkToFit:			True

    *zoom.debug:				False
    *controlPanel*zoom*internalWidth:		4
    *zoom.layout: vertical { \
	space = ((50% of width zoom) - (50% of width z5)) \
	1 < +inf > \
	horizontal { \
	    vertical { \
		toggleZoom < +inf * +inf > \
		2 \
	    } \
	    2 \
	    vertical { \
		2 < +inf > \
		z5 \
		1 < +inf > \
		z3 \
		0 < +inf > \
	    } \
	    2 \
	    vertical { \
		zoomIn < +inf * +inf > \
		2 \
	    } \
	} \
	1 < +inf > \
	horizontal { \
	    2 < +inf > \
	    d8 d4 d2 x1 z2 z4 z8 \
	    2 < +inf > \
	} \
	1 < +inf > \
	horizontal { \
	    vertical { \
		2 \
		zoomOut < +inf * +inf > \
	    } \
	    2 \
	    vertical { \
		0 < +inf > \
		d3 \
		1 < +inf > \
		d5 \
		2 < +inf > \
	    } \
	    2 \
	    vertical { \
		2 \
		centerFrame < +inf * +inf > \
	    } \
	} \
	1 < +inf > \
    }

    *toggleZoom.label:				Toggle\nZoom
    *toggleZoom.outerOffset:			0
    *toggleZoom.width:				30
    *toggleZoom.height:				25

    *zoomIn.label:				Zoom\nIn
    *zoomIn.outerOffset:			0
    *zoomIn.width:				30
    *zoomIn.height:				25

    *x1.label:					1
    *z2.label:					2
    *z3.label:					3
    *z4.label:					4
    *z5.label:					5
    *z8.label:					8

    *controlPanel*zoomIn.foreground:		royalBlue3
    *controlPanel*z4.foreground:		royalBlue3
    *controlPanel*z5.foreground:		royalBlue3
    *controlPanel*z8.foreground:		royalBlue3
    *controlPanel*z2.foreground:		royalBlue3
    *controlPanel*z3.foreground:		royalBlue3

    *zoomOut.label:				Zoom\nOut
    *zoomOut.outerOffset:			0
    *zoomOut.width:				30
    *zoomOut.height:				25

    *centerFrame.label:				Center
    *centerFrame.outerOffset:			0
    *centerFrame.width:				30
    *centerFrame.height:			25

    *d2.label:					2
    *d3.label:					3
    *d4.label:					4
    *d5.label:					5
    *d8.label:					8

    *controlPanel*zoomOut.foreground:		mediumVioletRed
    *controlPanel*d2.foreground:		mediumVioletRed
    *controlPanel*d3.foreground:		mediumVioletRed
    *controlPanel*d4.foreground:		mediumVioletRed
    *controlPanel*d5.foreground:		mediumVioletRed
    *controlPanel*d8.foreground:		mediumVioletRed

    *viewButtons.location:			0 0 100 80
    *viewButtons.debug:				False
    *viewButtons.layout: horizontal { \
	5 < -2 > \
	aspect < +inf * > \
	5 < -2 > \
	flipX < +inf * > \
	5 < -2 > \
	flipY < +inf * > \
	5 < -2 > \
	flipXY < +inf * > \
	5 < -2 > \
	clearFrame < +inf * > \
	5 < -2 > \
	fitFrame < +inf * > \
	5 < -2 > \
    }

    *nextFrame.label:				Next Frame
    *prevFrame.label:				Previous Frame
    *fitFrame.label:				Fit Frame
    *aspect.label:				Aspect
    *clearFrame.label:				Clear Frame
    *flipX.label:				Flip X
    *flipY.label:				Flip Y
    *flipXY.label:				Flip XY


    ! ENHANCEMENT
    ! ------------------
    *enhancementBox.label:			Enhancement
    *enhancementBox.location:			0 0 110 0
    *enhancementBox.shrinkToFit:		True
    *enhancementBox.outerOffset:		5

    *enhance.debug:				False
    *enhance.layout: vertical { \
	3 < -3 > \
	horizontal { \
	    2 < -2 > \
	    colorlistScroll < * +inff -inff > \
	    -1 \
	    colorlistFrame < +inf -inf * +inff -inff > \
	    2 < -2 > \
	} \
	-1 \
	horizontal { \
	    2 < -2 > \
	    colordataFrame < +inf -inf * +inf -inf > \
	    2 < -2 > \
	} \
	5 < -5 > \
	horizontal { \
	    2 < -2 > \
	    vertical { \
		-1 \
		contrastLabel \
		3 < -3 > \
		brightnessLabel \
		-1 \
	    } \
	    3 < -3 > \
	    vertical { \
		-1 \
		contrastSlider < +inf -inf * > \
		3 < -3 > \
		brightnessSlider < +inf -inf * > \
		-1 \
	    } \
	    2 < -2 > \
	} \
	5 < -5 > \
	horizontal { \
	    3 < -3 > \
	    invertButton < +inf -inf * > \
	    5 < -5 > \
	    optimizeButton < +inf -inf * > \
	    3 < -3 > \
	} \
	3 < -3 > \
    }

    *enhance*FrameType:				sunken
    *enhance*FrameWidth:			2
    *enhance*BorderWidth:			0
    *enhance*Label.ShadowWidth:			0
    *enhance*thumbColor:			gray

    *colorlistScroll.location:			0 0 20 10
    *colorlistScroll.vertical:			True
    *colorlistScroll*minsize:			10
    *colorlist.width:				100
    *colorlist.height:				78
    *colordata.width:				100
    *colordata.height:				45
    *enhance*colordata.frameWidth:		0
    *contrastLabel.label:			x
    *contrastSlider.location:			0 0 100 20
    *brightnessLabel.label:			x
    *brightnessSlider.location:			0 0 100 20
    *invertButton.label:			Invert
    *optimizeButton.label:			Optimize

    ! BLINK
    ! ---------------------
    *blinkBox.label:				Blink
    *blinkBox.location:				0 0 230 0
    *blinkBox.shrinkToFit:			True
    *blinkBox.outerOffset:			5


    *blink.debug:				False
    *blink.layout: vertical { \
	space = (width blinkFramesLabel - width blinkRateLabel) \
	3 < -3 > \
	horizontal { \
	    0 \
	    blinkFramesLabel \
	    3 < +inf > \
	    blinkFrame1 < -50% * > \
	    blinkFrame2 < -50% * > \
	    blinkFrame3 < -50% * > \
	    blinkFrame4 < -50% * > \
	    4 < +inf > \
	    blinkReset \
	    2 \
	} \
	5 < -5 > \
	horizontal { \
	    $space \
	    blinkRateLabel \
	    2  \
	    BRframe < +inf * > \
	} \
	5 < +inf -100% > \
	horizontal { \
	    3 \
	    registerButton < +inf * > \
	    5 < -5 > \
	    matchButton < +inf * > \
	    5 < -5 > \
	    blinkButton < +inf * > \
	    2 \
	} \
	3 < -3 > \
    }

    *BRlayout.layout: horizontal { \
	BRdecrease \
	BRtext < +inf -100% * > \
	BRincrease \
    }

    *blink.Label.borderWidth:			0
    *blink.Label.shadowWidth:			0
    *controlPanel*blink*internalWidth:		4
    *controlPanel*blink*Arrow.foreground:	gray
    *controlPanel*blink*Arrow.background:	gray63
    *blink*Arrow.width:				16
    *blink*Arrow.height:			25

    *blinkFramesLabel.label:			Blink Frames:
    *blinkFrame1.label:				1
    *blinkFrame2.label:				2
    *blinkFrame3.label:				3
    *blinkFrame4.label:				4
    *blinkReset.label:				Reset

    *blinkRateLabel.label:			Blink Rate:
    *BRframe.frameType:				sunken
    *BRframe.frameWidth:			2
    *BRtext.width:				40
    *BRtext.height:				25
    *BRdecrease.direction:			left
    *BRincrease.direction:			right
    *registerButton.label:			Register
    *matchButton.label:				Match LUTs
    *blinkButton.label:				Blink

    ! OPTIONS
    ! ---------------------
    *optionsBox.label:				Options
    *optionsBox.location:			0 0 220 0
    *optionsBox.shrinkToFit:			False
    *optionsBox.outerOffset:			5
    *optionsBox*offIcon:			square0s
    *optionsBox*onIcon:				square1s
    *optionsBox*selectionStyle:			multi
    *optionsBox*highlightColor:			yellow
    *optionsBox.TextToggle.location:		0 0 102 25
    *optionsBox.TextToggle.frameWidth:		0
    *optionsBox*alignment:			left

    *pannerButton.label:			Panner
    *magnifierButton.label:                     Magnifier
    *coordsBoxButton.label:			Coords Box
    *autoscaleButton.label:			Autoscale
    *antialiasButton.label:			Antialias
    *tileFramesButton.label:			Tile Frames
    *warningsButton.label:			Warnings
 

    ! CONTROL
    ! ----------------------
    *controlBox.frameType:			chiseled
    *controlBox.frameWidth:			2
    *controlBox.outerOffset:			5
    *controlBox.innerOffset:			5
    *controlBox.height:				30

    *control.debug:  False
    *control.layout: horizontal { \
	1 \
	initializeButton < +inf * > \
	5 < -5 > \
	normalizeButton < +inf * > \
	80 < +inf -100% > \
	doneButton < +inf * > \
	1 \
    }

    *initializeButton.label:			Initialize
    *normalizeButton.label:			Normalize
    *doneButton.label:				Done

    ! WARNING dialog.
    ! ---------------------
    *warning.geometry:				+400+300
    *warning*background:			gray
    *warning*borderWidth:			0
    *warning*TextBox.frameWidth:		0
    *warning*TextButton.frameWidth:		2
    *warning*TextButton.width:			40
    *warning*TextButton.height:			25

    *warn.layout: vertical { \
	5 < -5 > \
	horizontal { \
	    5 < -5 > \
	    warnFrame < +inf * +inf > \
	    5 < -5 > \
	} \
	1 < -1 > \
	horizontal { \
	    5 < -5 > \
	    warnOk < +inf * > \
	    5 < +inf -5 > \
	    warnCancel < +inf * > \
	    5 < +inf -5 > \
	    warnHelp < +inf * > \
	    5 < -5 > \
	} \
	1 < -1 > \
    }

    *WFlayout.layout: horizontal { \
	5 < -5 > \
	vertical { \
	    5 < +inf -5 > \
	    warnIcon \
	    5 < +inf -5 > \
	} \
	5 < -5 > \
	warnText < +inf -inf * +inf -inf > \
	5 < -5 > \
    }

    *warnLabel.label:				Warning
    *warnLabel.width:				300
    *warnLabel.height:				20
    *warnFrame.frameType:			sunken
    *warnFrame.frameWidth:			2
    *warnIcon.location:				0 0 40 40
    *warnIcon.image:				WARNING
    *warnText.label:				generic warning text
    *warnText.width:				270
    *warnText.height:				60
    *warnOk.label:				OK
    *warnCancel.label:				Cancel
    *warnHelp.label:				Help
    *warnHelp.sensitive:			False


    !=====================================
    !  Print Setup Panel resources.      !
    !=====================================
    *print_panel.title:                         Printer Setup
    *print_panel.highlightThickness:		1
    *print_panel*background:			gray
    *print_panel*TextBox.background:            gray63
    *print_panel*TextBox.foreground:            black
    *print_panel*TextToggle.alignment:          left
    *print_panel*Arrow.background:              gray63
    *print_panel*Arrow.foreground:              gray
    *print_panel*Arrow.width:                   16
    *print_panel*Arrow.height:                  25
    *print_panel*TextToggle.frameWidth:		0
    *print_panel*TextToggle.height:		20
    *print_panel*Label.borderWidth:		0
    *print_panel*Label.shadowWidth:		0
    *print_panel*Label.background:		gray
    *print_panel*TextButton.width:		40
    *print_panel*TextButton.height:		25

    *printLayout.borderWidth:			0
    *printLayout.layout: vertical { \
        -1 \
        printCmdGroup < +inf * > \
        -1 \
        optGroup < +inf -inf * +inf -inf > \
	-1 \
	cmdGroup < +inf * > \
        -1\
    }


    ! Print Group resources.
    !----------------------------------
    *printCmdGroup.borderWidth:			0
    *printCmdGroup.outerOffset:			5
    *printCmdGroup.label:			
    *printCmdGroup.location:			0 0 400 85
    *printCmdGroup*offIcon:                     diamond0s
    *printCmdGroup*onIcon:                      diamond1s
    *printCmdGroup*highlightColor:              cyan
    *printCmdGroup*Frame.frameType:		sunken
    *printCmdGroup*Frame.frameWidth:		2
    *printCmdGroup*Frame.width:			300
    *printCmdGroup*Label.justify:		right
    *printCmdGroup*Text*editType:		edit
    *printCmdGroup*TextToggle.width:		70
    *printCmdGroup*shadowWidth:                 0
    *printCmdGroup*borderWidth:                 0
    *printCmdLayout.borderWidth: 		0
    *printCmdLayout*Label.font:    		7x13bold
    *printCmdLayout.layout: horizontal { \
	-1 \
	labelLayout \
	5 < -5 > \
	inputLayout < +inf -inf * +inf > \
	2 \
     }

    *labelLayout.borderWidth:			0
    *labelLayout.layout: vertical { \
	5 \
	toLabel \
	11 \
	printerLabel \
	-3 \
     }
    *printerLabel.label:			Print Command:
    *toLabel.label:				Print To:
    *toPrinter.label:				Printer
    *toPrinter.on:				True
    *toFile.label:				File


    *inputLayout*Text*font:	-*-helvetica-medium-r-normal-*-12-*-iso8859-1
    *inputLayout.borderWidth:			0
    *inputLayout.layout: horizontal { \
	3 \
	vertical { \
	    5 \
	    horizontal { \
	        5 < -5 > \
	        toPrinter \
	        5 < -5 > \
	        toFile \
	        5 < +inf -inf > \
	    } \
	    5 \
	    printcmdFrame < +inf -inf * > \
	    5 \
	} \
	3 \
     }
    *printcmd*string:				lpr
    *printcmd*height:				22
    *printcmd*Text*editType:			edit
    *printcmd*Text*font:	-*-helvetica-medium-r-normal-*-12-*-iso8859-1

    !  Main options groups layout resources.
    !---------------------------------------
    *optGroup.frameWidth:			2
    *optGroup.frameType:			chiseled
    *optGroup.label:			
    *optGroup.location:				0 0 400 265
    *optGroup.outerOffset:                 	5
    *optGroup.innerOffset:                 	0
    *optLayout*borderWidth:			0
    *optLayout.layout: horizontal { \
	-1 \
        vertical { \
            5 < -5 >  \
	    epsPageGroup  < +inf -inf * > \
	    0 < -0 > \
	    optionsGroup  < +inf -inf * +inf -inf > \
            -1 \
        } \
	0 < -0 > \
        vertical { \
            5 < -5 >  \
	    printColorGroup  < +inf -inf * > \
	    0 < -0 > \
	    printerGroup  < +inf * +inf > \
            -1 \
        } \
 	-1 \
    }


    ! Postscript Options group resources.
    ! -----------------------------------
    *epsPageGroup.label:                        Postscript Options
    *epsPageGroup.outerOffset:                  5
    *epsPageGroup.innerOffset:                  5
    *epsPageGroup.location:                     0 0 250 150
    *epsPageGroup*offIcon:                      diamond0s
    *epsPageGroup*onIcon:                       diamond1s
    *epsPageGroup*highlightColor:               cyan
    *epsPage*Label.justify:                     left
    *epsPage*Label.font:                        7x13bold
    *epsPage.layout: vertical { \
        -1 \
        epsOrientLabel \
        4 < -4 > \
        horizontal { \
            10 \
	    epsPortButton \
	    epsLandButton \
	    -1 \
        } \
        4 < -4 > \
        epsSizeLabel \
        -1 \
        horizontal { \
            10 \
	    epsLetterButton \
	    epsLegalButton \
	    epsA4Button \
	    -1 \
        } \
        5 < -5 > \
        horizontal { \
            -1 \
            epsScaleLabel \
            4 < -4 > \
            ScaleFrame \
        } \
        -1 \
    }


    ! Page Layout resources.
    ! -------------------------------
    *epsOrientLabel.label:                      Orientation:
    *epsPortButton.label:			Portrait
    *epsPortButton.width:			90
    *epsLandButton.label:			Landscape
    *epsLandButton.width:			90

    *epsSizeLabel.label:                        Paper Size:
    *epsLetterButton.label:			Letter
    *epsLetterButton.width:			75
    *epsLegalButton.label:			Legal
    *epsLegalButton.width:			75
    *epsA4Button.label:				A4
    *epsA4Button.width:				75

    ! Image scale box resources.
    ! -------------------------------
    *epsScaleLabel.label:                       Image Scale:
    *ScaleFrame.frameType:                      sunken
    *ScaleFrame.frameWidth:                     2
    *ScaleFrame*shadowWidth:                    0
    *ScaleLayout.location:                      0 0 100 50
    *ScaleLayout.label:                         
    *ScaleLayout.layout: horizontal { \
        SCdecrease \
        SCtext < +inf -100% * > \
        SCincrease \
    }
    *SCdecrease.direction:                      left
    *SCtext.width:                              75
    *SCtext.height:                             25
    *SCtext.label:                              100 %
    *SCincrease.direction:                      right


    ! Miscellaneous print options box resources.
    ! ------------------------------------
    *optionsGroup.outerOffset:                  5
    *optionsGroup.innerOffset:                  5
    *optionsGroup*onIcon:                    	square1s
    *optionsGroup*offIcon:                   	square0s
    *optionsGroup.label:                        Processing Options
    *optionsGroup*TextToggle.width:             100
    *optionsGroup*TextToggle.highlightColor:    yellow
    *options.frameWidth:                        2
    *options.location:                          0 0 250 75
    *options.layout: horizontal { \
        10 \
        vertical { \
            -1 \
            epsscaleButton \
            2 \
            autorotateButton \
            2 \
            aspectButton \
            -1 \
        } \
        3 \
        vertical { \
            -1 \
            annotateButton \
            2 \
            compressButton \
            25 \
	    -1 \
        } \
        -1 \
    }
    *epsscaleButton.label:                      Auto Scale
    *autorotateButton.label:                    Auto Rotate
    *annotateButton.label:                      Annotate
    *aspectButton.label:                        Max Aspect
    *compressButton.label:                      Compress
    *compressButton.sensitive:                  False

!    *epsscaleButton.on:                     	True
!    *autorotateButton.on:                    	False
!    *spectButton.on:                        	False
!    *annotateButton.on:                      	True
!    *compressButton.on:                      	False


    ! Output color box resources.
    ! ------------------------------
    *printColorGroup.location:                     0 0 150 90
    *printColorGroup.outerOffset:                  5
    *printColorGroup.frameWidth:                   2
    *printColorGroup*offIcon:                      diamond0s
    *printColorGroup*onIcon:                       diamond1s
    *printColorGroup*highlightColor:               cyan
    *printColorGroup.innerOffset:                  5
    *printColorGroup.label:                        Output Color
    *printColorGroup*TextToggle.width:             100
    *printColor.frameWidth:                        2
    *printColor.location:                          0 0 250 75
    *printColor.layout: horizontal { \
        15 \
        vertical { \
            -1 \
            prGrayButton \
            2 \
            prPseudoButton \
            2 \
            prRGBButton \
            -1 \
        } \
	-1 \
    }
    *prGrayButton.label:			Grayscale
    *prPseudoButton.label:			PseudoColor
    *prRGBButton.label:				RGB

    ! Printer Selection.
    ! --------------------------
    *printerGroup.label:                      	Printers
    *printerGroup.location:                   	0 0 110 100
    *printerGroup.shrinkToFit:                	True
    *printerGroup.outerOffset:                	5

    *printers.debug:                            False
    *printers.layout: vertical { \
        3 < -3 > \
        horizontal { \
            2 < -2 > \
            printlistFrame < +inf -inf * +inff -inff > \
            -1 \
            printlistScroll < * +inff -inff > \
            2 < -2 > \
        } \
        3 < -3 > \
    }

    *printers*FrameType:                         sunken
    *printers*FrameWidth:                        2
    *printers*BorderWidth:                       0
    *printers*Label.ShadowWidth:                 0
    *printers*thumbColor:                        gray

    *printlistScroll.location:                  0 0 20 10
    *printlistScroll.vertical:                  True
    *printlistScroll*minsize:                   10
    *printlist.width:                           100
    *printlist.height:                          78


    ! Panel command resources.
    ! ------------------------------
    *cmdGroup.frameType:			chiseled
    *cmdGroup.frameWidth:			2
    *cmdGroup.outerOffset:			5
    *cmdGroup.innerOffset:			5
    *cmdGroup.label:
    *cmdGroup.location:				0 0 150 54
    *cmdGroup*Command.font:			7x13bold
    *cmdLayout.borderWidth:			0
    *cmdLayout.layout: horizontal { \
        -1 \
        okayPrint \
        1 < +inf -1 > \
	printStatus < +inf -inf * +inf -inf > \
        1 < +inf -1 > \
        donePrint \
        -1 \
    }
    *cmdGroup*TextButton*location:		0 0 80 0
    *okayPrint.label:				Print
    *donePrint.label:				Done


    !=====================================
    !  Save Setup Panel resources.      !
    !=====================================
    *save_panel.title:				Save to Disk...
    *save_panel*background:			gray
    *save_panel*TextBox.background:		gray63
    *save_panel*TextToggle.alignment:		left
    *save_panel*AsciiText*background:		gray63
    *save_panel*Arrow.background:		gray63
    *save_panel*Arrow.foreground:		gray
    *save_panel*Arrow.width:			16
    *save_panel*Arrow.height:			25
    *save_panel*TextToggle.frameWidth:		0
    *save_panel*TextToggle.height:		20
    *save_panel*Label.borderWidth:		0
    *save_panel*Label.shadowWidth:		0
    *save_panel*TextButton.width:		80


    *save_panel*debug:				False
    *saveLayout.borderWidth:			0
    *saveLayout.layout: vertical { \
        -1 \
        saveNameGroup < +inf * > \
        -1 \
        saveOptGroup < +inf -inf * +inf -inf > \
        -1 \
        saveCmdGroup < +inf * > \
        -1\
    }

    ! Save Name Group resources.
    !----------------------------------
    *saveNameGroup.borderWidth:			0
    *saveNameGroup.outerOffset:			5
    *saveNameGroup.label:			
    *saveNameGroup.location:			0 0 400 60
    *saveNameGroup*offIcon:                     diamond0s
    *saveNameGroup*onIcon:                      diamond1s
    *saveNameGroup*highlightColor:              cyan
    *saveNameGroup*Frame.frameType:		sunken
    *saveNameGroup*Frame.frameWidth:		2
    *saveNameGroup*Label.justify:		right
    *saveNameGroup*Text*editType:		edit
    *saveNameGroup*Text*font:	-*-helvetica-medium-r-normal-*-12-*-iso8859-1
    *saveNameGroup*TextBox*font:-*-helvetica-medium-r-normal-*-12-*-iso8859-1
    *saveNameGroup*shadowWidth:                 0
    *saveNameGroup*borderWidth:                 0
    *saveNameLayout.borderWidth: 		0
    *saveNameLayout*Label.font:    		7x13bold
    *saveNameLayout.layout: vertical { \
	5 \
	horizontal { \
	    5 \
	    saveLabel \
	    5 \
	    fnameFrame < +inf -inf * > \
	    5 \
	} \
	5 \
     }
    *saveLabel.label:				File Name:
    *saveFile.height:				22
!   *save_panel*saveFile*background:		gray63

    !  Main options groups layout resources.
    !---------------------------------------
    *saveOptGroup.frameWidth:			2
    *saveOptGroup.frameType:			chiseled
    *saveOptGroup.label:			
    *saveOptGroup.location:			0 0 400 145
    *saveOptGroup.outerOffset:                 	5
    *saveOptGroup.innerOffset:                 	0
    *saveOptLayout*borderWidth:			0
    *saveOptLayout.layout: horizontal { \
	-1 \
        vertical { \
            5 < -5 > \
	    fmtGroup < +inf * +inf >  \
            -1 \
        } \
	-1 \
        vertical { \
	    10 < -10 > \
	    saveDataBox < +inff -100% * +inff -100% > \
	    5 < -5 > \
        } \
 	-1 \
        vertical { \
            5 < -5 >  \
	    saveColorGroup < +inf * +inf >  \
            -1 \
        } \
	-1 \
    }

    ! Output color box resources.
    ! ------------------------------
    *saveColorGroup.location:                     0 0 125 120
    *saveColorGroup.outerOffset:                  5
    *saveColorGroup.frameWidth:                   2
    *saveColorGroup*offIcon:                      diamond0s
    *saveColorGroup*onIcon:                       diamond1s
    *saveColorGroup*highlightColor:               cyan
    *saveColorGroup.innerOffset:                  5
    *saveColorGroup.label:                        Output Color
    *saveColorGroup*TextToggle.width:             100
    *saveColor.frameWidth:                        2
    *saveColor.layout: horizontal { \
        3 \
        vertical { \
            5 \
            svGrayButton \
            2 \
            svPseudoButton \
            2 \
            svRGBButton \
            -1 \
        } \
	-1 \
    }
    *svGrayButton.label:			Grayscale
    *svPseudoButton.label:			PseudoColor
    *svPseudoButton.on:				true
    *svRGBButton.label:				RGB

    *saveDataBox*TextBox.background:		gray63
    *saveDataBox.frameType:			sunken
    *saveDataBox.frameWidth:			2


    ! Output format box resources.
    ! -----------------------------------
    *fmtGroup.location:                		0 0 140 120
    *fmtGroup.outerOffset:             		5
    *fmtGroup.frameWidth:              		2
    *fmtGroup*offIcon:                 		diamond0s
    *fmtGroup*onIcon:                  		diamond1s
    *fmtGroup*TextToggle.width:             	55
    *fmtGroup*highlightColor:          		cyan
    *fmtGroup.label:                   		File Format
    *formats.layout: horizontal { \
        3 \
        vertical { \
            7 \
            fitsButton \
            2 \
            gifButton \
            2 \
            x11Button \
            2 \
            rawButton \
            -1 \
        } \
        2 < -2 > \
        vertical { \
            7 \
            rasButton \
            2 \
            tiffButton \
            2 \
            jpegButton \
            2 \
            pnmButton \
            -1 \
        } \
        -1 \
    }
    *rasButton.label:                        	RAS
    *gifButton.label:                           GIF
    *jpegButton.label:                          JPEG
    *tiffButton.label:                          TIFF
    *fitsButton.label:                          FITS
    *x11Button.label:                           X11
    *pnmButton.label:                           PNM
    *rawButton.label:                           Raw

    ! Change the sensitivity once these formats are implemented. !
    !-------------------------------------------------------------
    *jpegButton.sensitive:                      false
    *x11Button.sensitive:                       false
    *pnmButton.sensitive:                       false
    *rawButton.sensitive:                       false

    ! Panel command resources.
    ! ------------------------------
    *saveCmdLayout.borderWidth:			0
    *saveCmdGroup.frameType:			chiseled
    *saveCmdGroup.frameWidth:			2
    *saveCmdGroup.outerOffset:			5
    *saveCmdGroup.innerOffset:			5
    *saveCmdGroup.label:			
    *saveCmdGroup.location:			0 0 400 54
!   *saveCmdLayout*Command.font:		7x13bold
    *saveCmdLayout.layout: horizontal { \
        -1 \
        okaySave \
        1 < +inf -1 > \
	saveStatus \
        1 < +inf -1 > \
        doneSave \
        -1 \
    }
    *okaySave.label:				Save
    *doneSave.label:				Done

    ! File Load Control Panel.
    !-------------------------------
    *load_panel.geometry:			400x320
    *load_panel.title:				File Load Panel
    *filesLayout*borderWidth:			0
    *filesLayout*highlightThickness:		0
    *filesLayout*background:			gray
    *filesLayout*Group.outerOffset:		7
    *filesLayout*Group.shrinkToFit:		True
    *filesLayout*Group.frameType:		chiseled
    *filesLayout*Frame*frameType:		sunken
    *filesLayout*Frame*frameWidth:		2
    *filesLayout*Text*background:		gray63
    *filesLayout*Text*font:	-*-helvetica-medium-r-normal-*-12-*-iso8859-1
    *filesLayout*TextBox*font:	-*-helvetica-medium-r-normal-*-12-*-iso8859-1
    *filesLayout*TextToggle.frameWidth:		0
    *filesLayout*TextToggle.height:		28
    *filesLayout*TextToggle.width:		80
    *filesLayout*TextToggle.alignment:          left
    *filesLayout*Scrollbar2*background:		gray63
    *filesLayout*scrollbarForeground:		gray
    *filesLayout*Scrollbar2*location:		0 0 20 10
    *filesLayout*Scrollbar2*vertical:		True
    *filesLayout*Scrollbar2*minsize:		20
    *filesLayout*MultiList*background:		gray63
    *filesLayout*MultiList*foreground:		black
    *filesLayout*MultiList*shadeSurplus:	False
    *filesLayout*MultiList*width:		120
    *filesLayout*MultiList.font:    		7x13bold
    *filesLayout*Label.font:    		7x13bold
    *filesLayout*Label.borderWidth:             0
    *filesLayout*Label.shadowWidth:             0
    *filesLayout.layout: vertical { \
        5 < +0 -5 > \
        horizontal { \
    	    0 < +0 -0 > \
    	    imagesGroup < +inf -inf * +inf -inf > \
    	    0 < +0 -0 > \
        } \
        0 < +0 -0 > \
        horizontal { \
    	    0 < +0 -0 > \
    	    fbuttonsGroup < +inf -inf * > \
    	    0 < +0 -0 > \
        } \
        0 < +0 -0 > \
    }

    *imagesGroup.label:				Images
    *imagesGroup.frameWidth:			2
!   *imagesGroup.outerOffset:			5
    *imagesGroup*offIcon:                 	square0s
    *imagesGroup*onIcon:                  	square1s
    *imagesGroup*highlightColor:          	yellow
    *imagesLayout*Label.shadowWidth:		0
    *imagesLayout*Label.justify:		left
    *imagesLayout*Command.width:		90
    *imagesLayout*TextButton.width:		90
    *imagesLayout*TextButton.height:		23
    *imagesLayout*TextButton.font:		*times*medium*r*normal*-12-*
    *imagesLayout.layout: vertical { \
        7 < +0 -7 > \
	horizontal { \
    	    5 \
    	    rootButton < +inf -inf * > \
    	    2 \
    	    homeButton < +inf -inf * > \
    	    2 \
    	    upButton < +inf -inf * > \
    	    2 \
    	    rescanButton < +inf -inf * > \
    	    5 \
	} \
	7 \
        horizontal { \
    	    5 < +0 -5 > \
            vertical { \
    	        5 \
    	        imtemplateLabel < * > \
    	        5 \
    	        imtemplateFrame < +inf -inf  * > \
    	        10 < +inf -inf > \
    	        grayToggle < * > \
    	        5 \
    	        browseToggle < * > \
    	        5 \
            } \
    	    5 \
	    horizontal { \
    	        5 < +0 -5 > \
    	        imlistFrame < +inf -inf * +inf -inf > \
    	        3 < +0 -3 > \
    	        imlistScrollbar < * +inf - inf > \
    	        0 < +0 -0 > \
	    } \
    	    5 < +0 -5 > \
        } \
        5 \
        horizontal { \
    	    5 \
            dirLabel < +inf -inf * > \
    	    5 \
	} \
        10 \
        horizontal { \
    	    5 < +0 -5 > \
            fnameLabel < * > \
    	    5 < +0 -5 > \
            filnamFrame < +inf -inf * > \
    	    5 < +0 -5 > \
            frameLabel < * > \
    	    5 < +0 -5 > \
            frameFrame < -50% * > \
    	    5 < +0 -5 > \
	} \
        5 < +0 -5 > \
    }
    *imtemplateLabel.label:			File Pattern:
    *imtemplateText*editType:			edit
    *imtemplateText.height:			20
    *imageList.width:				100
    *upButton.label:				Up
    *rootButton.label:				Root
    *homeButton.label:				Home
    *rescanButton.label:			Rescan
    *browseToggle.label:			Browse
    *browseToggle.on:				True
    *grayToggle.label:				Greyscale
    *dirLabel.label:				Directory:
    *dirLabel.alignment:			left
    *fnameLabel.label:				Load File:
    *fnameText*editType:			edit
    *fnameText.height:				20
    *frameLabel.label:				Frame:
    *frameFrame.label:				1
    
    *fbuttonsGroup.label:
    *fbuttonsGroup*frameWidth:			2
    *fbuttonsGroup*outerOffset:			5
    *fbuttonsGroup*innerOffset:			5
    *fbuttonsGroup.frameType:			sunken
    *fbuttonsGroup*Command.font:                7x13bold
    *fbuttonsLayout*Command.height:		50
    *fbuttonsLayout*Command.width:		70
    *fbuttonsLayout.layout: horizontal { \
        -1 \
        filesLoadButton \
        1 < +inf -1 > \
        filesStatus \
        1 < +inf -1 > \
        filesCloseButton \
        -1 \
    }
    
    *filesLoadButton.label:			Load
    *filesStatus.label:				
    *filesCloseButton.label:			Done

    ! Help panel resources.
    !----------------------
    *help_panel.title:				XImtool Help Summary
    *help_panel.width:				450
    *help_panel.height:				525
    *helpLayout*borderWidth:                    0
    *helpLayout.background:                     gray
    *helpLayout*Frame*frameType:                sunken
    *helpLayout*Frame*frameWidth:               2
    *helpLayout*Frame.background:               gray
    *helpLayout*Layout.background:              gray
    *helpLayout*ScrollbarBackground:            #c0c0c0
    *helpLayout*Scrollbar*background:           #c0c0c0
    *helpLayout*Scrollbar*width:                17
    *helpLayout*Scrollbar*height:               17
    *helpLayout*Scrollbar*shadowWidth:          2
    *helpLayout*Scrollbar*cursorName:           top_left_arrow
    *helpLayout*Scrollbar*pushThumb:            true

   
    *helpLayout.layout: vertical { \
        -1 \
        horizontal { \
            0 < +0 -0 > \
            helpMenuLayout < +inf -inf * > \
            0 < +0 -0 > \
        } \
        0 < +0 -0 > \
        horizontal { \
            0 < +0 -0 > \
            helpTextFrame < +inf -inf * +inf -inf > \
            0 \
        } \
        0 < +0 -0 > \
        horizontal { \
            0 < +0 -0 > \
            helpInfoLayout < +inf -inf * > \
            0 < +0 -0 > \
        } \
        -1 \
    }
    *helptext*background:			white
    *helptext*foreground:			black
      
    *helpMenuLayout*background:			gray
    *helpMenuLayout*Command.highlightThickness: 2
    *helpMenuLayout*Command.internalHeight:     2
    *helpMenuLayout*Command.font: 	-*-helvetica-bold-r-normal-*-12-*-*-*
    *helpMenuLayout.layout: vertical { \
        5 \
	horizontal { \
            5 < +0 -5 > \
            helpBack \
            2 < +0 -2 > \
            helpForward \
            2 < +0 -2 > \
            helpHome \
            20 < +inf -20 > \
            helpClose \
            5 < +0 -5 > \
	} \
        5 \
    }
    *helpBack.label:				Back
    *helpBack.sensitive:			False
    *helpForward.label:				Forward
    *helpForward.sensitive:			False
    *helpHome.label:				Home
    *helpClose.label:				Done
 
    *helpInfoLayout*background:			gray
    *helpInfoLayout*Label.justify: 		center
    *helpInfoLayout*Label.internalHeight:	0
    *helpInfoLayout.layout: horizontal { \
        5 \
        vertical { \
            5 \
            helpIRAFLogo \
            5 \
        } \
        1 \
        vertical { \
	    5 \
            horizontal { \
                0 < +inf -inf > \
                helpInfo1 \
                0 < +inf -inf > \
            } \
	    0 < +inf -0 > \
            horizontal { \
                0 < +inf -inf > \
                helpInfo2 \
                0 < +inf -inf > \
            } \
	    0 < +inf -0 > \
            horizontal { \
                0 < +inf -inf > \
                helpInfo3 \
                0 < +inf -inf > \
            } \
	    5 \
        } \
        1 \
        vertical { \
	    5 \
            helpNOAOLogo \
	    5 \
        } \
        5 \
    }
    *helpInfo1.label:            XImtool V1.2   --   Released: 4/30/2000
    *helpInfo2.label:               iraf@noao.edu    (520) 318-8160
    *helpInfo3.label:       NOAO is operated by AURA under cooperative agreement with the NSF
    *helpInfoLayout*helpInfo1.font: -*-helvetica-medium-r-normal-*-12-*-*-*
    *helpInfoLayout*helpInfo2.font: -*-helvetica-medium-r-normal-*-12-*-*-*
    *helpInfoLayout*helpInfo3.font: -*-helvetica-medium-r-normal-*-10-*-*-*
    *helpInfoLayout.helpIRAFLogo.internalWidth:       	0
    *helpInfoLayout.helpIRAFLogo.internalheight:       	0
    *helpInfoLayout.helpIRAFLogo.foreground:       	steelblue
    *helpInfoLayout.helpIRAFLogo.background:       	white
    *helpInfoLayout.helpNOAOLogo.internalWidth:       	0
    *helpInfoLayout.helpNOAOLogo.internalheight:       	0
    *helpInfoLayout.helpNOAOLogo.foreground:       	steelblue
    *helpInfoLayout.helpNOAOLogo.background:       	white
 
    *helpText.width:					450
    *helpText.height:					500
    *helpText.anchorUnderlines:				1
    *helpText.visitedAnchorUnderlines:			1
    *helpText.verticalScrollOnRight:			true
    *helpText.plainFont:				6x13


    ! Define a debug Tcl shell.
    !--------------------------------
    *tclShell.title:                            Interactive Tcl Shell
    *tclForm.background:                        gray
    *tclForm*Label.background:                  gray
    *tclForm*Label.borderWidth:                 0
    *tclForm*Label.resize:                      False
    *tclForm*Command.resize:                    False
    *tclForm*Command.background:                grey75
    *tclForm*Command.font:                      7x13bold
    *tclLabel.label:                            Server  Command Entry
    *tclClear.label:                            Clear
    *tclExecute.label:                          Execute
    *tclEntry*Text.font:                        7x13
    *tclEntry*width:                            500
    *tclEntry*borderWidth:                      1
    *tclEntry*height:                           150
    *tclEntry*editType:                         edit
    *tclEntry*scrollHorizontal:                 whenNeeded
    *tclEntry*scrollVertical:                   never
    *tclEntry*displayCaret:                     True
    *tclcloseButton.label:                      Done


    ! GUI resources.
    ! ------------------------------
    *autoscale:					True
    *zoomfactors:				1 2 4 8
    *displayCoords:				True
    *displayPanner:				True
    *displayMagnifier:				False
    *blinkRate:					1.0
    *pannerArea:				150*150
    *pannerGeom:				-5+5
    *magnifierArea:                             100*100
    *magnifierGeom:                             +5+5
    *wcsboxGeom:				-5-5
    *maxContrast:				5.0
    *warnings:					True
}

# Start up the GUI.
createObjects
send colorbar setGterm ; send colorbar activate
send imagewin setGterm ; send imagewin activate
activate

# Utility procedure to test True/False strings in resources.
proc true {v} {expr {$v == "true" || $v == "True" || $v == "TRUE"}}

# Utility functions.
proc min {a b} { expr {($a < $b) ? $a : $b} }
proc max {a b} { expr {($a > $b) ? $a : $b} }

# Global variables.
set version     "NOAO/IRAF XImtool Version 1.2"

set winWidth [send imagewin get width]		;# display window width
set winHeight [send imagewin get height]	;# display window height
set marker none					;# selected marker
set markno 0					;# used to name new markers
set blinkFrames "1 2"				;# list of blink/tile frames

set loadP_up    0
set saveP_up    0
set printP_up   0
set infoP_up    0
set panel_up    0
set helpP_up    0


proc winResize {w width height} \
    { global winWidth winHeight; set winWidth $width; set winHeight $height}
send imagewin addCallback winResize resize

# Additional global variables, taking default values from resources.
getResources {
    { zoomfactors }
    { displayCoords }
    { displayPanner }
    { displayMagnifier }
    { blinkRate }
    { pannerArea }
    { pannerGeom }
    { magnifierArea }
    { magnifierGeom }
    { wcsboxGeom }
    { maxContrast }
    { warnings }
}

set warnings [true $warnings]
set defaultBlinkRate $blinkRate

# Client state variables (UI parameter objects).  Certain of these parameters
# we mirror in Tcl variables here, updating the values with a callback when
# the parameter value changes.  Others require special callbacks.

set frame 1			;# current display frame
set nframes 0			;# number of frame buffers
set frames {1 2 3 4}		;# list of image frames
set frameWidth 0		;# frame buffer width, pixels
set frameHeight 0		;# frame buffer height, pixels
set frameDepth 8		;# frame buffer pixel size, bits
set cursorMode 0		;# true when cursor read pending

foreach i $frames {
    set frameZoomX($i) 0	;# X zoom factor
    set frameZoomY($i) 0	;# Y zoom factor
    set frameCenterX($i) 0	;# X center of field
    set frameCenterY($i) 0	;# Y center of field
    set frameScaleX($i) 0	;# X scale factor
    set frameScaleY($i) 0	;# Y scale factor
    set enhancement($i) none	;# colortable enhancement
}

# Called when the number of frames changes.
proc setNFrames {param old new} {
    global frameMenuDescription nframes frames
    set nframes $new
    if {$old != $new} {
	foreach i {prevButton nextButton} {
	    send $i set sensitive [expr "$nframes > 1"]
	}
	editMenu frameMenu frameButton $frameMenuDescription
    }
    foreach i $frames {
	if {$i <= $nframes} {
	    send frameBox manage frame$i 
	} else {
	    send frameBox unmanage frame$i 
	}
    }
}; send nframes addCallback setNFrames

set frameMenuDescription {
    { 1  f.exec "send client setFrame 1"  sensitive {[expr "$nframes >= 1"]}  }
    { 2  f.exec "send client setFrame 2"  sensitive {[expr "$nframes >= 2"]}  }
    { 3  f.exec "send client setFrame 3"  sensitive {[expr "$nframes >= 3"]}  }
    { 4  f.exec "send client setFrame 4"  sensitive {[expr "$nframes >= 4"]}  }
}; createMenu frameMenu frameButton $frameMenuDescription

# Called when the frame being displayed changes.
proc frameChanged {param old new} {
    global frame
    set frame $new
    send frameButton set label $frame
}; send frame addCallback frameChanged

# Called when the frame buffer configuration changes.
proc setFrameSize {param old new} {
    global frameWidth frameHeight frameDepth
    set frameWidth [lindex $new 0]
    set frameHeight [lindex $new 1]
    set frameDepth [lindex $new 2]
}; send frameSize addCallback setFrameSize

# Called when the current frame is zoomed or panned.
proc setFrameView {param old new} {
    global frameZoomX frameZoomY frameCenterX frameCenterY
    global frameScaleX frameScaleY frame
    set frameZoomX($frame) [lindex $new 0]
    set frameZoomY($frame) [lindex $new 1]
    set frameCenterX($frame) [lindex $new 2]
    set frameCenterY($frame) [lindex $new 3]
    set frameScaleX($frame) [lindex $new 4]
    set frameScaleY($frame) [lindex $new 5]
}; send frameView addCallback setFrameView

# Called when the color enhancement for a frame changes.
proc setEnhancement {param old new} {
    global enhancement
    set enhancement([lindex $new 0]) [lrange $new 1 end]
}; send enhancement addCallback setEnhancement

# Called when the frame title changes (e.g. frame change or new frame loaded).
proc setTitle {param old new} {
    send imageTitle set label [string trimright $new]
}; send frameTitle addCallback setTitle

# Called when the image is flipped in an axis.
proc setFlip {param old new} {
    send ${param}Button set state [true $new]
}; foreach i {xflip yflip} { send $i addCallback setFlip }


# Various general callbacks.
proc Quit args			{ send client Quit }
proc nextFrame args		{ send client nextFrame }
proc prevFrame args		{ send client prevFrame }
proc setColormap { mapno }	{ send client setColormap $mapno }
proc xflip args			{ send client flip x }
proc yflip args			{ send client flip y }
proc xyflip args		{ send client flip x y }

# Initialize bitmaps.
createBitmap xflip 16 16 {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x18, 0x18,
   0x1c, 0x38, 0xfe, 0x7f, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18, 0x10, 0x08,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

createBitmap yflip 16 16 {
   0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0x80, 0x01,
   0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f,
   0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00};

createBitmap qmark 16 16 {
   0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x0f, 0x18, 0x0c, 0x18, 0x0c,
   0x18, 0x0e, 0x00, 0x07, 0x80, 0x03, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00,
   0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00};

createBitmap larrow 16 16 {
   0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0xc0, 0x03, 0xe0, 0x1e, 0x70, 0x1e,
   0x38, 0x18, 0x1c, 0x18, 0x1c, 0x18, 0x38, 0x18, 0x70, 0x1e, 0xe0, 0x1e,
   0xc0, 0x03, 0x80, 0x03, 0x00, 0x03, 0x00, 0x00};

createBitmap rarrow 16 16 {
   0x00, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x03, 0x78, 0x07, 0x78, 0x0e,
   0x18, 0x1c, 0x18, 0x38, 0x18, 0x38, 0x18, 0x1c, 0x78, 0x0e, 0x78, 0x07,
   0xc0, 0x03, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0x00};

createBitmap panel 16 16 {
   0x00, 0x00, 0xf8, 0x1f, 0xf8, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
   0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x18, 0x18,
   0x18, 0x18, 0x18, 0x18, 0xf8, 0x1f, 0xf8, 0x1f};

createBitmap brightness 15 15 {
   0x00, 0x00, 0x80, 0x00, 0x84, 0x10, 0xe8, 0x0b, 0x10, 0x04, 0x08, 0x08,
   0x08, 0x08, 0x0e, 0x38, 0x08, 0x08, 0x08, 0x08, 0x10, 0x04, 0xe8, 0x0b,
   0x84, 0x10, 0x80, 0x00, 0x00, 0x00};

createBitmap contrast 15 15 {
   0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x30, 0x07, 0x08, 0x0f, 0x08, 0x0f,
   0x04, 0x1f, 0x04, 0x1f, 0x04, 0x1f, 0x08, 0x0f, 0x08, 0x0f, 0x30, 0x07,
   0xc0, 0x01, 0x00, 0x00, 0x00, 0x00};

createBitmap solid 64 24 {
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

send panelButton "set bitmap panel;  addCallback panel"
send xflipButton "set bitmap xflip;  addCallback xflip"
send yflipButton "set bitmap yflip;  addCallback yflip"
send helpButton  "set bitmap qmark;  addCallback Help"
send prevButton  "set bitmap larrow; addCallback prevFrame"
send nextButton  "set bitmap rarrow; addCallback nextFrame"


# WINDOW the current frame.
proc windowColormap {x y} \
{
    global winWidth winHeight maxContrast

    send client windowColormap \
	[expr "double($x) / $winWidth"] \
	[expr "(double($y) - $winHeight / 2.0) / $winHeight * \
	    $maxContrast * 2.0"]
}

# WINDOW the current frame, but only one color at a time.
proc windowRGB {color x y save_flag} \
{
    global winWidth winHeight maxContrast

    send client windowRGB $color \
        [expr "double($x) / $winWidth"] \
        [expr "(double($y) - $winHeight / 2.0) / $winHeight * \
            $maxContrast * 2.0"] $save_flag
} 


# ZOOM and PAN.
set xcen 0
set ycen 0
foreach i $frames {set zoomindex($i) 0}
set nzoomfactors 0
foreach i $zoomfactors {
    set zoomfactor($nzoomfactors) $i
    incr nzoomfactors
}

# Zoom or pan image at given center.
proc zoom {x y} \
{
    global xcen ycen frame
    global zoomindex zoomfactor
    global nzoomfactors

    set rx $x;  set ry $y
    set raster 0

    # Convert raw screen coordinates to frame buffer raster coordinates.
    send imagewin unmapPixel $x $y raster rx ry

    # Select a pixel.
    set rx [expr "int ($rx)"]
    set ry [expr "int ($ry)"]

    # If the pointer did not move (much) zoom the image, otherwise
    # pan it.

    send imagewin setCursorType busy
    if {sqrt(pow($x-$xcen, 2) + pow($y-$ycen, 2)) < 4} {
	set zoomindex($frame) [expr [incr zoomindex($frame)] % $nzoomfactors]
	set mag $zoomfactor($zoomindex($frame))
	send client zoom $mag $mag $rx $ry
    } else {
	send client pan $rx $ry
	set xcen $x
	set ycen $y
    }

    # Move the pointer so that it tracks the object feature the user
    # selected.

    send imagewin setCursorPos $rx $ry $raster
    send imagewin getCursorPos xcen ycen
    send imagewin setCursorType idle
}

# Zoom using a marker to indicate the region to be displayed.
proc zoomMarker {marker aspect} \
{
    global xcen ycen frame
    global winWidth winHeight
    global zoomindex nzoomfactors

    # getRegion returns: "rectangle raster x y width height rotangle".
    set region [send $marker getRegion unmap]

    set raster [lindex $region 1]
    set xcen [expr "int([lindex $region 2]) + 0.5"]
    set ycen [expr "int([lindex $region 3]) + 0.5"]
    set snx  [expr "[lindex $region 4] * 2"]
    set sny  [expr "[lindex $region 5] * 2"]

    # Compute the magnification ratio.
    set xmag [expr "$winWidth / $snx"]
    set ymag [expr "$winHeight / $sny"]
    if {$aspect == "equal"} {
	set mag [expr "($xmag < $ymag) ? $xmag : $ymag"]
	set xmag $mag;  set ymag $mag
    }

    # Zoom the image.
    send client zoomAbs $xmag $ymag $xcen $ycen

    # The following causes a button2 to redisplay the full image.
    send imagewin setCursorPos $xcen $ycen $raster
    send imagewin getCursorPos xcen ycen
    set zoomindex($frame) [expr "$nzoomfactors - 1"]
}

proc resetView {param old new} {
    global zoomindex xcen ycen frames
    global frameWidth frameHeight

    if {$new == "done"} {
	foreach i $frames {
	    send client setFrame $i
	    set xcen [expr $frameWidth / 2]
	    set ycen [expr $frameHeight / 2]
	    send client zoom 1 1 $xcen $ycen
	    set zoomindex($i) 0
	    send client setColormap Grayscale
	    normalize
	}
	send client setFrame 1
    }
}; #send initialize addCallback resetView


# CURSOR READ stuff.
proc setCursorMode {param old new} \
{
    global cursorMode

    if {$new == "on"} {
	send imagewin "activate; setCursorType ginMode"
	set cursorMode 1
    } elseif {$new == "off"} {
	send imagewin "setCursorType idle; deactivate"
	set cursorMode 0
    }
}

proc keyInput {widget event sx sy data} \
{
    global cursorMode frame

    if {!$cursorMode || $event != "keyPress"} \
	return
    if {[lindex $data 0] == "??"} \
	return

    # Convert raw screen coordinates to raster pixel coordinates.
    send imagewin unmapPixel $sx $sy raster rx ry

    # Return the cursor value and exit cursor mode.
    send client retCursorVal $rx $ry $frame 1 [lindex $data 0]
}

proc resetCursorMode args {
    global cursorMode frame
    if {$cursorMode} {
	send imagewin getCursorPos x y
	send client retCursorVal $x $y $frame 1 ^D
    }
}; send initialize addCallback resetCursorMode

send cursorMode addCallback setCursorMode
send imagewin addCallback keyInput input


# MARKER stuff.  The active marker is determined by the global variable
# "marker", which is the marker the pointer is in, or which the pointer
# was most recently in.

# Translations when pointer is inside marker.
set markerTranslations { \
       !Shift <Btn1Motion>:	m_rotateResize()
	      <Btn1Motion>:	m_moveResize()
	 !Shift <Btn1Down>:	m_raise()  m_markpos()
		<Btn1Down>:	m_raise()  m_markposAdd()
		  <Btn1Up>:	m_redraw() m_destroyNull()
		<Btn2Down>:	m_lower()
	        <Btn3Down>:	popup(markerMenu)
	          <Btn3Up>:	popdown(markerMenu)
              !Ctrl <Key>b:     call(prevFrame,$name)
              !Ctrl <Key>f:     call(nextFrame,$name)
              !Ctrl <Key>h:     call(move_cursor,-1,0)
              !Ctrl <Key>j:     call(move_cursor,0,1)
              !Ctrl <Key>k:     call(move_cursor,0,-1)
              !Ctrl <Key>l:     call(move_cursor,1,0)
              !Ctrl <Key>n:     call(normalize)
              !Ctrl <Key>m:     call(toggleMagnifier)
              !Ctrl <Key>p:     call(togglePanner)
              !Ctrl <Key>c:     call(cpZoomAction,centerFrame)
              !Ctrl <Key>i:     call(cpInvert)
              !Ctrl <Key>s:     call(cpMatchFrames)
              !Ctrl <Key>r:     call(cpRegisterFrames)
               !Alt <Key>1:     call(cpSetFrame,frame1)
               !Alt <Key>2:     call(cpSetFrame,frame2)
               !Alt <Key>3:     call(cpSetFrame,frame3)
               !Alt <Key>4:     call(cpSetFrame,frame4)
              !Ctrl <Key>1:     call(cpZoom,1,1,fixed)
              !Ctrl <Key>2:     call(cpZoom,2,2,fixed)
              !Ctrl <Key>3:     call(cpZoom,3,3,fixed)
              !Ctrl <Key>4:     call(cpZoom,4,4,fixed)
              !Ctrl <Key>5:     call(cpZoom,5,5,fixed)
              !Ctrl <Key>6:     call(cpZoom,6,6,fixed)
              !Ctrl <Key>7:     call(cpZoom,7,7,fixed)
              !Ctrl <Key>8:     call(cpZoom,8,8,fixed)
              !Ctrl <Key>9:     call(cpZoom,9,9,fixed)
	    <Key>BackSpace:	m_deleteDestroy()
	       <Key>Delete:	m_deleteDestroy()
		<KeyPress>:	m_input()
		  <Motion>:	track-cursor()
}

# Popup menu in effect when inside marker.
createMenu markerMenu imagewin {
    {	Marker		f.title			}
    {			f.dblline		}
    {	Zoom		f.exec {
			    zoomMarker $marker equal
			    send $marker destroy
			}			}
    {	Fill		f.exec {
			    zoomMarker $marker fill
			    send $marker destroy
			}			}
    {	Print		f.exec {
			    send $marker getRect interior x0 y0 nx ny
			    setPrintCorners $x0 [expr $y0 + $ny -1] \
				[expr $x0 + $nx -1] $y0
			    send client print $x0 $y0 $nx $ny
			}			}
    {	Save		f.exec {
    			    send imagewin setCursorType busy
			    send $marker getRect interior x0 y0 nx ny
			    send client save $x0 $y0 $nx $ny
    			    send imagewin setCursorType idle
			}			}
    {	Info		f.exec {
			    send infoText append \
				[format "%s\n" [send $marker getRegion unmap]]
			}			}
    {	Unrotate	f.exec {
			    send $marker setAttribute rotangle 0
			}			}
    {			f.line			}
    {	Color		f.menu markerColor	}
    {	Type		f.menu markerType	}
    {			f.line			}
    {	Destroy		f.exec {
			    send $marker destroy
			}			}
}

createMenu markerType markerMenu {
    {	Type		f.title			}
    {			f.dblline		}
    {	Rectangle	f.exec "m_setType $marker rectangle"	}
    {	Box		f.exec "m_setType $marker box"		}
    {	Circle		f.exec "m_setType $marker circle"	}
    {	Ellipse		f.exec "m_setType $marker ellipse"	}
    {	Polygon		f.exec "m_setType $marker polygon"	}
}

createMenu markerColor markerMenu {
    {	Color		f.title			}
    {			f.dblline		}
    {	""		f.exec "m_setColor $marker black"
			    bitmap solid foreground black }
    {	""		f.exec "m_setColor $marker white" 
			    bitmap solid foreground white }
    {	""		f.exec "m_setColor $marker red" 
			    bitmap solid foreground red }
    {	""		f.exec "m_setColor $marker green" 
			    bitmap solid foreground green }
    {	""		f.exec "m_setColor $marker blue" 
			    bitmap solid foreground blue }
    {	""		f.exec "m_setColor $marker magenta" 
			    bitmap solid foreground magenta }
    {	""		f.exec "m_setColor $marker cyan" 
			    bitmap solid foreground cyan }
    {	""		f.exec "m_setColor $marker yellow" 
			    bitmap solid foreground yellow }
}

proc m_setType {marker type}  {
    send $marker "markpos; set type $type; redraw"
}
proc m_setColor {marker color}  {
    send $marker "markpos;
	set lineColor $color;  set highlightColor $color; redraw"
}

# Callback executed when a marker gets or loses the focus.
proc selectMarker {active_marker event event_data} \
{
    global marker
    switch $event {
	focusIn		{ set marker $active_marker }
	focusOut	{  }
    }
}

# Create marker action.  Makes a new marker.
proc makeMarker {parent x y} \
{
    global markerTranslations markno
    set marker marker$markno;  incr markno

    send $parent createMarker $marker \
	type		rectangle \
	createMode	interactive \
	translations	$markerTranslations \
	x		$x \
	y		$y

    send $marker addCallback selectMarker focusIn focusOut
}


# WCSBOX -- Real time coordinate display.
set track_enable 0

proc wcsUpdate {x y} \
{
    global track_enable frame

    # Convert screen coords to raster pixel.
    send imagewin unmapPixel $x $y raster rx ry rz

    # Set the current frame to the frame the pointer is within.
    if {$frame && $raster} {
	set track_frame [send client getFrame $raster]
	if {$frame != $track_frame} {
	    send client setFrame $track_frame
	}
    }

    # Update coords box.
    if {$track_enable} {
	if {$raster} {
	    set text [send client encodewcs $rx $ry $rz]
	} else {
	    set text [format " %7.2f %7.2f %7.1f " $rx $ry $rz]
	}
	send wcsbox "set text \{$text\}; redraw noerase"
    }
}

proc setTrack {state} \
{
    global track_enable wcsboxGeom
    global winWidth winHeight

    if {$state} {
	if {$track_enable} \
	    return

	send imagewin createMarker wcsbox {
	    type		text
	    createMode		noninteractive
	    width		25ch
	    height		1ch
	    lineWidth		0
	    imageText		true
	    textBgColor		black
	    textColor		yellow
	    visible		false
	}

	set box_width [send wcsbox get width]
	set box_height [send wcsbox get height]
	set defGeom [format "%sx%s-5-5" $box_width $box_height]
	send imagewin parseGeometry $wcsboxGeom $defGeom x y width height

	send wcsbox setAttributes \
	    x			$x \
	    y			$y \
	    activated		true \
	    visible		true \
	    sensitive		true

	send wcsbox {
	    addCallback wcsboxDestroyCallback destroy
	    addCallback wcsboxMoved moveResize
	}

	send imagewin addCallback wcsboxWindowResize resize
	set track_enable 1
	send imagewin getCursorPos x y
	wcsUpdate $x $y
        magnifierMapImage $x $y
 
    } elseif {$track_enable} {
	set track_enable 0
	send wcsbox destroy
    }
}

proc wcsboxDestroyCallback args {
    global track_enable
    send imagewin deleteCallback wcsboxWindowResize
    set track_enable 0
}

# If the window is resized make the wcsbox track the corner.
proc wcsboxWindowResize args {
    global track_enable
    global wcsboxGeom

    if {$track_enable} {
	# Get new location.
	set box_width [send wcsbox get width]
	set box_height [send wcsbox get height]
	set defGeom [format "%sx%s-5-5" $box_width $box_height]
	send imagewin parseGeometry $wcsboxGeom $defGeom x y width height

	# Move the marker.
	send wcsbox "\
	    deleteCallback wcsboxMoved; \
	    markpos; setAttributes x $x y $y; redraw; \
	    addCallback wcsboxMoved moveResize"
    }
}

proc wcsboxMoved {marker event position} {
    global wcsboxGeom
    send wcsbox getRect boundary x y width height
    set wcsboxGeom [send imagewin getGeometry $x $y $width $height]
}

proc resetWcsbox {param old new} {
    global track_enable wcsboxGeom displayCoords
    if {$new == "done"} {
	setTrack [true $displayCoords]
    } elseif {$track_enable} {
	setTrack 0
	if {$new == "restart"} {
	    set wcsboxGeom -5-5
	}
    }
}; send initialize addCallback resetWcsbox


# PANNER.  The full frame mapped into the main image window is displayed at a
# reduced resolution in a marker (known as the panner window) within the main
# image window.  The currently displayed region of the frame is indicated
# using a small marker within the panner window.  This small marker may be
# moved or resized to pan or zoom the image in the main display window.

set panner_x 0
set panner_y 0
set panner_width 0
set panner_height 0
set prm_width 0
set prm_height 0

set panner_enable 0
set panner_pan_enable 0
set panner_region_enable 0
set panner_mapping 0

# Panner window translations.
set pannerWinTranslations { \
       !Shift <Btn1Motion>:	m_rotateResize()
	      <Btn1Motion>:	m_moveResize()
	 !Shift <Btn1Down>:	m_raise() m_markpos()
		<Btn1Down>:	m_raise() m_markposAdd()
		  <Btn1Up>:	m_redraw() m_destroyNull()
		<Btn2Down>:	m_lower()
              !Ctrl <Key>b:     call(prevFrame,$name)
              !Ctrl <Key>f:     call(nextFrame,$name)
              !Ctrl <Key>h:     call(move_cursor,-1,0)
              !Ctrl <Key>j:     call(move_cursor,0,1)
              !Ctrl <Key>k:     call(move_cursor,0,-1)
              !Ctrl <Key>l:     call(move_cursor,1,0)
              !Ctrl <Key>n:     call(normalize)
              !Ctrl <Key>m:     call(toggleMagnifier)
              !Ctrl <Key>p:     call(togglePanner)
              !Ctrl <Key>c:     call(cpZoomAction,centerFrame)
              !Ctrl <Key>i:     call(cpInvert)
              !Ctrl <Key>s:     call(cpMatchFrames)
              !Ctrl <Key>r:     call(cpRegisterFrames)
               !Alt <Key>1:     call(cpSetFrame,frame1)
               !Alt <Key>2:     call(cpSetFrame,frame2)
               !Alt <Key>3:     call(cpSetFrame,frame3)
               !Alt <Key>4:     call(cpSetFrame,frame4)
              !Ctrl <Key>1:     call(cpZoom,1,1,fixed)
              !Ctrl <Key>2:     call(cpZoom,2,2,fixed)
              !Ctrl <Key>3:     call(cpZoom,3,3,fixed)
              !Ctrl <Key>4:     call(cpZoom,4,4,fixed)
              !Ctrl <Key>5:     call(cpZoom,5,5,fixed)
              !Ctrl <Key>6:     call(cpZoom,6,6,fixed)
              !Ctrl <Key>7:     call(cpZoom,7,7,fixed)
              !Ctrl <Key>8:     call(cpZoom,8,8,fixed)
              !Ctrl <Key>9:     call(cpZoom,9,9,fixed)
		  <Btn2Up>:	call(pannerPanXY,$x,$y)
	    <Key>BackSpace:	m_deleteDestroy()
	       <Key>Delete:	m_deleteDestroy()
		<KeyPress>:     graphics-input()
		  <Motion>:	track-cursor() call(wcsUpdate,$x,$y)
}


# setPanner -- Turn the panner on or off.

proc togglePanner args {
    global panner_enable

    if {$panner_enable} {
        setPanner 0
    } else {
        setPanner 1
    }
}

proc setPanner {state} \
{
    global winWidth winHeight frameWidth frameHeight
    global frame panner_mapping pannerWinTranslations pannerArea
    global panner_enable panner_region_enable panner_pan_enable
    global pannerGeom panner_x panner_y panner_width panner_height

    if {$state} {
	if {$panner_enable} \
	    return

	# Determine where to place the panner.
	set scale \
	    [expr sqrt(double($pannerArea) / ($frameWidth * $frameHeight))]
	set scaled_width [expr int($frameWidth * $scale) / 2 * 2 + 1]
	set scaled_height [expr int($frameHeight * $scale) / 2 * 2 + 1]
	set defGeom [format "%sx%s-5+5" $scaled_width $scaled_height]
	send imagewin parseGeometry $pannerGeom $defGeom x y width height

	# Create the main panner window (marker).
	send imagewin createMarker pannerWin \
	    type		rectangle \
	    createMode		noninteractive \
	    width		[expr $width / 2] \
	    height		[expr $height / 2] \
	    x			[expr $x + $width / 2] \
	    y			[expr $y + $height / 2] \
	    lineColor		8 \
	    highlightColor	8 \
	    translations	$pannerWinTranslations \
	    visible		true \
	    sensitive		true \
	    activated		true

	# Update the panner window position variables so that it comes up
	# in the same place the next time.

	send pannerWin getRect boundary \
	    panner_x panner_y panner_width panner_height
	set pannerGeom [send imagewin getGeometry \
	    $panner_x $panner_y $panner_width $panner_height]

	# Register callbacks.
	send frame addCallback pannerMapImage
	send frameRegion addCallback pannerSetRegion
	send imagewin addCallback pannerImagewinResized resize
	send resize addCallback pannerImagewinResized

	send pannerWin {
	    addCallback pannerMapImage moveResize;
	    addCallback pannerMoved moveResize;
	    addCallback pannerDestroy destroy;
	    addCallback pannerWinConstraint constraint;
	}

	# Map display frame to panner window.
	set panner_enable 1
	set panner_region_enable 1
	set panner_mapping [send imagewin nextMapping]
	pannerMapImage init; send imagewin refreshMapping $panner_mapping

	# Draw a marker in the panner window outlining displayed region.
	send imagewin createMarker pannerRegionMarker \
	    type		box \
	    createMode		noninteractive \
	    translations	$pannerWinTranslations \
	    lineColor		green \
	    highlightColor	green \
	    sensitive		true

	# Fire up the panner region marker.
	send client getSource raster sx sy snx sny
	pannerSetRegion dummy dummy [concat $frame $sx $sy $snx $sny]
	send pannerRegionMarker "\
	    addCallback pannerPanImage moveResize; \
	    addCallback pannerDestroy destroy; \
	    addCallback pannerRegionConstraint constraint; \
	    setAttributes visible true activated true; \
	    redraw"
	set panner_pan_enable 1

    } elseif {$panner_enable} {
	pannerDestroy
    }
}


# pannerDestroy -- Delete the panner.

proc pannerDestroy args {
    global panner_enable panner_region_enable panner_pan_enable
    global panner_mapping

    if {$panner_enable} {
	set panner_enable 0
	set panner_pan_enable 0
	set panner_region_enable 0

	send imagewin freeMapping $panner_mapping
	send imagewin deleteCallback pannerImagewinResized
	send resize deleteCallback pannerImagewinResized
	send frame deleteCallback pannerMapImage
	send frameRegion deleteCallback pannerSetRegion

	if [send server queryObject pannerRegionMarker] {
	    send pannerRegionMarker destroy
	}
	if [send server queryObject pannerWin] {
	    send pannerWin destroy
	}
    }
}


# pannerMapImage -- Map the current display frame into the panner window.
# Called when the frame changes or the panner window is moved or resized.
# The panner window displays a small dezoomed version of the full frame.

proc pannerMapImage args {
    global panner_enable frame
    global panner_mapping

    if {!$panner_enable || $frame == 0} \
	return

    set raster [send client getRaster]
    send pannerWin getRect interior dx dy dnx dny
    send imagewin queryRaster $raster width height

    if [send imagewin activeMapping $panner_mapping] {
	send imagewin raiseMapping $panner_mapping
    }
    send imagewin setMapping $panner_mapping 0 \
	$raster pixel 0 0 $width $height \
	0 pixel $dx $dy $dnx $dny
}


# pannerSetRegion -- Adjust the pannerWin region marker to outline the
# region displayed in the main display window.  This is called in response
# to a frameRegion event when the main display mapping changes, e.g. when
# the frame changes or the user zooms or pans the main window.  The region
# marker is moved and resized to reflect the new view.

proc pannerSetRegion {param old new} {
    global panner_enable panner_region_marker
    global panner_region_enable panner_pan_enable
    global frame frameWidth frameHeight prm_width prm_height

    if {!$panner_enable || !$panner_region_enable || $frame == 0} \
	return

    # new: frame sx sy snx sny
    set src_frame [lindex $new 0]
    set sx [lindex $new 1];  set snx [lindex $new 3]
    set sy [lindex $new 2];  set sny [lindex $new 4]

    if {$src_frame != $frame} \
	return

    send pannerWin getRect interior px py pnx pny

    set x [expr ($sx + $snx/2.0) / $frameWidth * $pnx + $px]
    set y [expr ($sy + $sny/2.0) / $frameHeight * $pny + $py]
    set width [expr ($snx/2.0) / $frameWidth * $pnx + 1]
    set height [expr ($sny/2.0) / $frameHeight * $pny + 1]

    set pan_save $panner_pan_enable;  set panner_pan_enable 0
    set panner_region_enable 0

    send pannerRegionMarker "\
	markpos; \
	setAttributes x $x y $y width $width height $height; \
	redraw; raise"
    send pannerRegionMarker getAttributes width prm_width height prm_height

    set panner_region_enable 1
    set panner_pan_enable $pan_save
}


# pannerPanImage -- Pan or zoom the image in the main image window.  This is
# called when the user moves the region marker within the panner window.

proc pannerPanImage {marker event position} {
    global panner_pan_enable
    global winWidth winHeight
    global prm_width prm_height

    if {!$panner_pan_enable} \
	return

    # position: x y width height.
    set new_width [lindex $position 2]
    set new_height [lindex $position 3]

    # region: type raster x y width height.
    set region [send pannerRegionMarker getRegion unmap]
    set x [expr [lindex $region 2] + 1];  set width [lindex $region 4]
    set y [expr [lindex $region 3] + 1];  set height [lindex $region 5]

    set panner_pan_enable 0
    if {$new_width == $prm_width && $new_height == $prm_height} {
	send client pan $x $y
    } else {
	set xscale [expr ($winWidth / 2.0) / $width]
	set yscale [expr ($winHeight / 2.0) / $height]
	send client zoom $xscale $yscale $x $y
    }
    set panner_pan_enable 1
}


# pannerPanXY -- Pan to the point X,Y in the panner window coordinate
# system.  Called when the user clicks MB2 in the panner window.

proc pannerPanXY {x y} {
    send imagewin unmapPixel $x $y raster rx ry
    send client pan $rx $ry
}


# pannerMoved -- Called when the user moves the panner window.  We need to
# move the region marker to the new window location and record the new location
# so that the window will come up in the same place if closed and reopened.

proc pannerMoved {marker event position} {
    global winWidth winHeight
    global frame panner_pan_enable pannerGeom
    global panner_x panner_y panner_width panner_height

    # Move the region marker to the new location.
    set pan_save $panner_pan_enable;  set panner_pan_enable 0
    send client getSource raster sx sy snx sny
    pannerSetRegion dummy dummy [concat $frame $sx $sy $snx $sny]
    set panner_pan_enable $pan_save

    # Update the panner window position variables so that it comes up
    # in the same place the next time.

    send pannerWin getRect boundary \
	panner_x panner_y panner_width panner_height
    set pannerGeom [send imagewin getGeometry \
	$panner_x $panner_y $panner_width $panner_height]

    send pannerRegionMarker raise
}


# pannerWinConstraint -- Called when the panner window is moved, resized, or
# rotated.  Constrain the panner window to remain within the image window;
# rotation is not permitted.

proc pannerWinConstraint {marker event attributes} {
    global winWidth winHeight
    global panner_width panner_height

    set width $panner_width
    set height $panner_height
    set constraints [list {}]

    # Check the width and height first as we need these below.
    foreach i $attributes {
	set new [lindex $i 2]
	switch [lindex $i 0] {
	    width	{   set ww [expr $winWidth / 2]
			    if {$new > $ww} {
				lappend constraints "width $ww"
				set width $ww
			    } else {
				set width $new
			    }
			}
	    height	{   set wh [expr $winHeight / 2]
			    if {$new > $wh} {
				lappend constraints "height $wh"
				set height $wh
			    } else {
				set height $new
			    }
			}
	    rotangle	{    lappend constraints "rotangle 0"
			}
	}
    }

    # Constrain X and Y.
    foreach i $attributes {
	set new [lindex $i 2]
	switch [lindex $i 0] {
	    x		{   set pw [expr $width / 2]
			    if {$new < $pw} {
				lappend constraints "x $pw"
			    } elseif {$new > $winWidth - $pw} {
				lappend constraints "x [expr $winWidth - $pw]"
			    }
			}
	    y		{   set ph [expr $height / 2]
			    if {$new < $ph} {
				lappend constraints "y $ph"
			    } elseif {$new > $winHeight - $ph} {
				lappend constraints "y [expr $winHeight - $ph]"
			    }
			}
	}
    }

    return $constraints
}


# pannerRegionConstraint -- Called when the region marker in the panner
# window is moved, resized, or rotated.

proc pannerRegionConstraint {marker event attributes} {
    global winWidth winHeight

    set constraints [list {}]
    send pannerWin getRect interior p_x p_y p_width p_height
    send pannerRegionMarker getAttributes width rwidth height rheight

    # Since the panner region marker is a box marker x,y and width,height
    # will not both change in the same call, so we can process them all
    # independently.

    foreach i $attributes {
	set new [lindex $i 2]

	switch [lindex $i 0] {
	    x		{   set left [expr $p_x + $rwidth + 1]
			    set right [expr $p_x + $p_width - $rwidth - 1]
			    if {$new < $left} {
				lappend constraints "x $left"
			    } elseif {$new > $right} {
				lappend constraints "x $right"
			    }
			}
	    y		{   set top [expr $p_y + $rheight + 1]
			    set bottom [expr $p_y + $p_height - $rheight - 1]
			    if {$new < $top} {
				lappend constraints "y $top"
			    } elseif {$new > $bottom} {
				lappend constraints "y $bottom"
			    }
			}
	    width	{   set ww [expr $winWidth / 2]
			    if {$new > $ww / 2} {
				lappend constraints "width $ww"
			    }
			}
	    height	{   set wh [expr $winHeight / 2]
			    if {$new > $wh / 2} {
				lappend constraints "height $wh"
			    }
			}
	    rotangle	{    lappend constraints "rotangle 0"
			}
	}
    }

    return $constraints
}


# pannerImagewinResized -- If the display window is resized make the panner
# track the corner.

proc pannerImagewinResized args {
    global panner_enable panner_mapping
    global pannerGeom panner_x panner_y panner_width panner_height

    if {$panner_enable} {
	set old_x $panner_x;  set old_width $panner_width
	set old_y $panner_y;  set old_height $panner_height

	# Get new location of panner window.
	set defGeom [format "%sx%s-5+5" $panner_width $panner_height]
	send imagewin parseGeometry $pannerGeom $defGeom x y width height

	# Reposition the marker.
	send pannerWin "\
	    markpos; \
	    setAttributes \
		x		[expr $x + $width / 2] \
		y		[expr $y + $height / 2] \
		width		[expr $width / 2] \
		height		[expr $height / 2]; \
	    redraw"

	# Update the panner window position variables so that it comes up
	# in the same place the next time.
	send pannerWin getRect boundary \
	    panner_x panner_y panner_width panner_height
	set pannerGeom [send imagewin getGeometry \
	    $panner_x $panner_y $panner_width $panner_height]

	# Make sure the panner window is on top.
	send imagewin raiseMapping $panner_mapping

	# Refresh the panner window if it did not move.
	if {$panner_x == $old_x && $panner_y == $old_y &&
	    $panner_width == $old_width && $panner_height == $old_height} {
	    send imagewin refreshMapping $panner_mapping
	}
    }
}


# resetPanner -- Reinitialize the panner.

proc resetPanner {param old new} {
    global pannerGeom displayPanner
    if {$new == "done"} {
	setPanner [true $displayPanner]
    } else {
	setPanner 0
	if {$new != "startup"} {
	    set pannerGeom -5+5
	}
    }
}; send initialize addCallback resetPanner



# MAGNIFIER.  A subraster around the cursor in the main image window is
# displayed at a high resolution in a marker (known as the magnifier window)
# within the main image window.

set magnifier_x 0
set magnifier_y 0
set magnifier_width 0
set magnifier_height 0
set mrm_width 0
set mrm_height 0

set magnifier_enable 0
set magnifier_mag_enable 0
set magnifier_mapping 0

createMenu magzoomMenu imagewin {
    {   "Zoom Factors"        	f.title                         }
    {                           f.dblline                       }
    {   "Zoom 1"                f.exec "setMagnifierZoom 1"     }
    {   "Zoom 2"                f.exec "setMagnifierZoom 2"     }
    {   "Zoom 4"                f.exec "setMagnifierZoom 4"     }
    {   "Zoom 8"                f.exec "setMagnifierZoom 8"     }
    {   "Zoom 16"               f.exec "setMagnifierZoom 16"    }
} 

# Magnifier window translations.
set magnifierWinTranslations { \
       !Shift <Btn1Motion>:	m_rotateResize()
	      <Btn1Motion>:	m_moveResize()
	 !Shift <Btn1Down>:	m_raise() m_markpos()
		<Btn1Down>:	m_raise() m_markposAdd()
		  <Btn1Up>:	m_redraw() m_destroyNull()
		<Btn2Down>:	m_lower()
        	<Btn3Down>:     popup(magzoomMenu)
        	<Btn3Up>:       popdown(magzoomMenu)
              !Ctrl <Key>m:     call(toggleMagnifier)
              !Ctrl <Key>p:     call(togglePanner)
	    <Key>BackSpace:	m_deleteDestroy()
	       <Key>Delete:	m_deleteDestroy()
		<KeyPress>:     graphics-input()
		  <Motion>:	track-cursor() call(wcsUpdate,$x,$y)
}


# setMagnifier -- Turn the magnifier on or off.

set magAlreadyOn	0

proc setDynamicMagnifier {state} \
{
    global magAlreadyOn magnifier_enable

    if {$state} {
        set magAlreadyOn $magnifier_enable
    }
    if {$magAlreadyOn} {
        return
    } else {
        setMagnifier $state
    }
}


proc toggleMagnifier args {
    global magnifier_enable

    if {$magnifier_enable} {
        setMagnifier 0
        send pbMagM set state False
    } else {
        setMagnifier 1
        send pbMagM set state True
    }
}


proc setMagnifier {state} \
{
    global winWidth winHeight frameWidth frameHeight
    global frame magnifier_mapping magnifierWinTranslations magnifierArea
    global magnifier_enable magnifier_height
    global magnifierGeom magnifier_x magnifier_y magnifier_width

    if {$state} {
	if {$magnifier_enable} \
	    return

	# Determine where to place the magnifier.
	set scale  [expr sqrt(double($magnifierArea) / (512 * 512))]
	set scaled_width [expr int(512 * $scale) / 2 * 2 + 1]
	set scaled_height [expr int(512 * $scale) / 2 * 2 + 1]
	set defGeom [format "%sx%s-5+5" $scaled_width $scaled_height]
	send imagewin parseGeometry $magnifierGeom $defGeom x y width height

	# Create the main magnifier window (marker).
	send imagewin createMarker magnifierWin \
	    type		rectangle \
	    createMode		noninteractive \
	    width		[expr $width / 2] \
	    height		[expr $height / 2] \
	    x			[expr $x + $width / 2] \
	    y			[expr $y + $height / 2] \
	    lineColor		8 \
	    highlightColor	8 \
	    translations	$magnifierWinTranslations \
	    visible		true \
	    sensitive		true \
	    activated		true

	# Update the magnifier window position variables so that it comes up
	# in the same place the next time.

	send magnifierWin getRect boundary \
	    magnifier_x magnifier_y magnifier_width magnifier_height
	set magnifierGeom [send imagewin getGeometry \
	    $magnifier_x $magnifier_y $magnifier_width $magnifier_height]

	# Register callbacks.
	send imagewin addCallback magnifierImagewinResized resize
	send resize addCallback magnifierImagewinResized
        send magnifierWin addCallback magnifierMovedMapImage moveResize

	send magnifierWin {
	    addCallback magnifierMoved moveResize;
	    addCallback magnifierDestroy destroy;
	    addCallback magnifierWinConstraint constraint;
	}

	# Map display frame to magnifier window.
	set magnifier_enable 1
	set magnifier_mapping [send imagewin nextMapping]
	send imagewin refreshMapping $magnifier_mapping

        # create cross-hair
        send imagewin createMarker magPointer \
                type                rectangle \
                createMode          noninteractive \
                width               3 \
                height              3 \
                lineWidth           3 \
                lineColor           green \
                highlightcolor      green \
                activated           true \
                visible             true

        # set its position and size
        setMagPointerPosition 
        magnifierMapImage [expr $winWidth / 2] [expr $winHeight / 2]

    } elseif {$magnifier_enable} {
	magnifierDestroy
    }
}


# magnifierDestroy -- Delete the magnifier.

proc magnifierDestroy args {
    global magnifier_enable 
    global magnifier_mapping

    if {$magnifier_enable} {
	set magnifier_enable 0

	send imagewin freeMapping $magnifier_mapping
	send imagewin deleteCallback magnifierImagewinResized
	send resize deleteCallback magnifierImagewinResized
	send frame deleteCallback magnifierMapImage

	if [send server queryObject magnifierWin] {
	    send magnifierWin destroy
	}
        if [send server queryObject magPointer] {
            send magPointer destroy
        }  
    }
}


# magnifierMoved -- Called when the user moves the magnifier window.  We need to
# move the region marker to the new window location and record the new location
# so that the window will come up in the same place if closed and reopened.

proc magnifierMoved {marker event position} {
    global winWidth winHeight magnifierGeom frame 
    global magnifier_x magnifier_y magnifier_width magnifier_height

    # Move the region marker to the new location.
    send client getSource raster sx sy snx sny

    # Update the magnifier window position variables so that it comes up
    # in the same place the next time.

    send magnifierWin getRect boundary \
	magnifier_x magnifier_y magnifier_width magnifier_height
    set magnifierGeom [send imagewin getGeometry \
	$magnifier_x $magnifier_y $magnifier_width $magnifier_height]
}


# magnifierWinConstraint -- Called when the magnifier window is moved, resized,
# or rotated. Constrain the magnifier window to remain within the image window;
# rotation is not permitted.

proc magnifierWinConstraint {marker event attributes} {
    global winWidth winHeight
    global magnifier_width magnifier_height

    set width $magnifier_width
    set height $magnifier_height
    set constraints [list {}]

    # Check the width and height first as we need these below.
    foreach i $attributes {
	set new [lindex $i 2]
	switch [lindex $i 0] {
	    width	{   set ww [expr $winWidth / 2]
			    if {$new > $ww} {
				lappend constraints "width $ww"
				set width $ww
			    } else {
				set width $new
			    }
			}
	    height	{   set wh [expr $winHeight / 2]
			    if {$new > $wh} {
				lappend constraints "height $wh"
				set height $wh
			    } else {
				set height $new
			    }
			}
	    rotangle	{    lappend constraints "rotangle 0"
			}
	}
    }

    # Constrain X and Y.
    foreach i $attributes {
	set new [lindex $i 2]
	switch [lindex $i 0] {
	    x		{   set pw [expr $width / 2]
			    if {$new < $pw} {
				lappend constraints "x $pw"
			    } elseif {$new > $winWidth - $pw} {
				lappend constraints "x [expr $winWidth - $pw]"
			    }
			}
	    y		{   set ph [expr $height / 2]
			    if {$new < $ph} {
				lappend constraints "y $ph"
			    } elseif {$new > $winHeight - $ph} {
				lappend constraints "y [expr $winHeight - $ph]"
			    }
			}
	}
    }

    return $constraints
}


# magnifierRegionConstraint -- Called when the region marker in the magnifier
# window is moved, resized, or rotated.

proc magnifierRegionConstraint {marker event attributes} {
    global winWidth winHeight

    set constraints [list {}]
    send magnifierWin getRect interior p_x p_y p_width p_height

    # Since the magnifier region marker is a box marker x,y and width,height
    # will not both change in the same call, so we can process them all
    # independently.

    foreach i $attributes {
	set new [lindex $i 2]

	switch [lindex $i 0] {
	    x		{   set left [expr $p_x + $rwidth + 1]
			    set right [expr $p_x + $p_width - $rwidth - 1]
			    if {$new < $left} {
				lappend constraints "x $left"
			    } elseif {$new > $right} {
				lappend constraints "x $right"
			    }
			}
	    y		{   set top [expr $p_y + $rheight + 1]
			    set bottom [expr $p_y + $p_height - $rheight - 1]
			    if {$new < $top} {
				lappend constraints "y $top"
			    } elseif {$new > $bottom} {
				lappend constraints "y $bottom"
			    }
			}
	    width	{   set ww [expr $winWidth / 2]
			    if {$new > $ww / 2} {
				lappend constraints "width $ww"
			    }
			}
	    height	{   set wh [expr $winHeight / 2]
			    if {$new > $wh / 2} {
				lappend constraints "height $wh"
			    }
			}
	    rotangle	{    lappend constraints "rotangle 0"
			}
	}
    }

    return $constraints
}


# magnifierImagewinResized -- If the display window is resized make the
# magnifier track the corner.

proc magnifierImagewinResized args {
    global magnifier_enable magnifier_mapping magnifier_height
    global magnifierGeom magnifier_x magnifier_y magnifier_width

    if {$magnifier_enable} {
	set old_x $magnifier_x;  set old_width $magnifier_width
	set old_y $magnifier_y;  set old_height $magnifier_height

	# Get new location of magnifier window.
	set defGeom [format "%sx%s+5+5" $magnifier_width $magnifier_height]
	send imagewin parseGeometry $magnifierGeom $defGeom x y width height

	# Reposition the marker.
	send magnifierWin "\
	    markpos; \
	    setAttributes \
		x		[expr $x + $width / 2] \
		y		[expr $y + $height / 2] \
		width		[expr $width / 2] \
		height		[expr $height / 2]; \
	    redraw"

	# Update the magnifier window position variables so that it comes up
	# in the same place the next time.
	send magnifierWin getRect boundary \
	    magnifier_x magnifier_y magnifier_width magnifier_height
	set magnifierGeom [send imagewin getGeometry \
	    $magnifier_x $magnifier_y $magnifier_width $magnifier_height]

	# Make sure the magnifier window is on top.
	send imagewin raiseMapping $magnifier_mapping

	# Refresh the magnifier window if it did not move.
	if {$magnifier_x == $old_x && $magnifier_y == $old_y &&
	    $magnifier_width == $old_width && $magnifier_height == $old_height} {
	    send imagewin refreshMapping $magnifier_mapping
	}
    }
}


# resetMagnifier -- Reinitialize the magnifier.

proc resetMagnifier {param old new} {
    global magnifierGeom displayMagnifier
    if {$new == "done"} {
	setMagnifier [true $displayMagnifier]
    } else {
	setMagnifier 0
	if {$new != "startup"} {
	    set magnifierGeom +5+5
	}
    }
}; send initialize addCallback resetMagnifier


set last_mag_x [expr $winWidth / 2]
set last_mag_y [expr $winHeight / 2]

# magnifierMovedMapImage -- Front end to magnifierMapImage, called when 
# magnifier window is moved or resized.

proc magnifierMovedMapImage args {
    global last_mag_x last_mag_y

    magnifierMapImage $last_mag_x $last_mag_y
    setMagPointerPosition
}


# The following code was borrowed from the SAOtng GUI by Eric Mandel of SAO
#--------------------------------------------------------------------------

# globals for magnifier
set mag_w 0
set mag_h 0

#
# setMagnifierZoom -- set the zoom factor for the magnifier
#
proc setMagnifierZoom { zoom } \
{
    global mag_w mag_h

    send magnifierWin getRect boundary \
		magnifier_x magnifier_y magnifier_width magnifier_height
    set mag_w [expr int( ( $magnifier_width  + $zoom - 1 ) / $zoom) ]
    set mag_h [expr int( ( $magnifier_height + $zoom - 1 ) / $zoom) ]

    #set mw [expr int (($magnifier_width - 1) / ($mag_w * 2))]
    #if { $mw < 4 } { set mw 4 }
    #set mh [expr int (($magnifier_height - 1) / ($mag_h * 2))]
    #if { $mh < 4 } { set mh 4 }
    #send magPointer "setAttributes width $mw height $mh; redraw"
}

# magnifierMapImage -- Map the of the current display frame centered on the
# pointer into the magnifier window.  Called when the frame changes, the
# pointer moves in the main image window, or (via magnifierMovedMapImage)
# the magnifier window is moved or resized.

set magnifierROP 0

proc magnifierMapImage {x y} \
{
    global magnifier_enable frame
    global last_mag_x last_mag_y
    global magnifier_mapping
    global winWidth winHeight
    global mag_w mag_h
    global magnifierROP

    if {!$magnifier_enable || $frame == 0} \
	return

    if {abs($last_mag_x-$x) != 1 && abs($last_mag_y-$y) != 1} {
	# For efficiency we won't compute the sqrt of the distance but instead
	# just compare the square.  Use a threshold of 6 pixels so when we
	# narrow in on the ROI the magnifier is still (mostly) correctly.
        set diff  [expr (($last_mag_x-$x) * ($last_mag_x-$x)) + \
			(($last_mag_y-$y) * ($last_mag_y-$y))]
        if {$diff > 36} {
    	    set last_mag_x $x
    	    set last_mag_y $y
	    return
  	}
    }

    set last_mag_x $x
    set last_mag_y $y

    send magnifierWin getRect interior dx dy dnx dny
    if [send imagewin activeMapping $magnifier_mapping] {
	send imagewin raiseMapping $magnifier_mapping
    }
    # initialize the magnifier zoom factor, if necessary
    if { !$mag_w || !$mag_h } {
	setMagnifierZoom 4
    }

    set sx [expr $x - $mag_w / 2 ]
    set sy [expr $y - $mag_h / 2 ]

    # Constrain the source rectangle within the main image window 
    # (not overlapping an edge or the magnifier window).

    if {$sx > [expr $dx - $mag_w] && $sx < [expr $dx + $dnx] && 
        $sy > [expr $dy - $mag_h] && $sy < [expr $dy + $dny]    } {

	# The source rectangle would overlap the magnifier window; fix that.

	set dist(l) [expr $sx - ($dx - $mag_w)]
	set dist(b) [expr $dy + $dny - $sy]
	set dist(r) [expr $dx + $dnx - $sx]
	set dist(t) [expr $sy - ($dy - $mag_h)]

	#  Put the distances in order.

	foreach j [array names dist] {
	    set alreadyset($j) 0
	}

	for {set i 0} {$i < 4} {incr i} {
	    set candidate ""
	    foreach j [array names dist] {
		if {!$alreadyset($j)} {
		    if {$candidate == ""} {
			set candidate $j
			set minsofar $dist($j)
		    } elseif {$dist($j) < $minsofar} {
			set candidate $j
			set minsofar $dist($j)
		    }
		}
	    }
	    set order($i) $candidate
	    set alreadyset($candidate) 1
	}

	# Try the sides in order, using the first one where there's room.

	for {set i 0} {$i < 4} {incr i} {
	    if {$order($i) == "l"} {
		if {$dx >= $mag_w} {
		    set sx [expr $dx - $mag_w]
		    break
		}
	    } elseif {$order($i) == "b"} {
		if {$winHeight >= $dy + $dny + $mag_h} {
		    set sy [expr $dy + $dny]
		    break
		}
	    } elseif {$order($i) == "r"} {
		if {$winWidth >= $dx + $dnx + $mag_w} {
		    set sx [expr $dx + $dnx]
		    break
		}
	    } elseif {$order($i) == "t"} {
		if {$dy >= $mag_h} {
		    set sy [expr $dy - $mag_h]
		    break
		}
	    }
	}
    }

    # Make sure we don't go beyond an edge of the main window.

    if {$sx < 0} {
	set sx 0
    } else {
	set sxmax [expr $winWidth - $mag_w]
	if {$sx > $sxmax} {
	    set sx $sxmax
	}
    }

    if {$sy < 0} {
	set sy 0
    } else {
	set symax [expr $winHeight - $mag_h]
	if {$sy > $symax} {
	    set sy $symax
	}
    }

    # Map 32 x 32 centered on pointer in main window.
    set err [catch {send imagewin setMapping $magnifier_mapping $magnifierROP \
	0 pixel $sx $sy $mag_w $mag_h \
	0 pixel $dx $dy $dnx   $dny}]
    if { $err != 0 } {
	Print "There was a problem setting up the magnifier ... recovering"
    }
}


# set the position of the magnifier marker in the center of the mag window
proc setMagPointerPosition args \
{
    global magnifier_enable

    if { !$magnifier_enable } {
        return
    }

    send magnifierWin "getAttributes x x y y"
    set xpos [expr $x + 1]
    set ypos [expr $y + 1]

    send magPointer "setAttributes x $xpos y $ypos visible true; redraw"
}



# FRAME BLINK.
set blinkId 0
set blinkIndex 0

proc toggleBlink args {
    global blinkId blinkRate blinkIndex
    global optionsMenuDescription

    if {$blinkId} {
	deleteTimedCallback $blinkId
	set blinkId 0
    } else {
	set blinkId [postTimedCallback blink [expr int($blinkRate * 1000)]]
    }

    set blinkIndex 0
    editMenu optionsMenu viewButton $optionsMenuDescription
}

proc blink args {
    global blinkId blinkRate blinkFrames blinkIndex

    send client setFrame [lindex $blinkFrames $blinkIndex]
    incr blinkIndex
    if {$blinkIndex >= [llength $blinkFrames]} {
	set blinkIndex 0
    }

    set blinkId [postTimedCallback blink [expr int($blinkRate * 1000)]]
}

proc resetBlink args {
    global blinkId
    if {$blinkId} \
	toggleBlink
}; send initialize addCallback resetBlink



# Normalize -- Reset the view parameters for the current frame.
proc normalize args {
    global zoomindex zoomfactor
    global frameWidth frameHeight
    global xcen ycen frame

    #set zoomindex($frame) 0
    #set xcen [expr $frameWidth / 2]
    #set ycen [expr $frameHeight / 2]
    #send client zoom 1 1 $xcen $ycen
    send client windowColormap 0.5 1.0
}


# Popdown menus.
createMenu fileMenu fileButton {
    {	"Info"		f.exec {
			    send info map
			    infoUpdate
			}				}
    {	"Load"		f.exec {
			    send client setLoadOption rescan
			    send load_panel map
			    set loadP_up 1
			}				}
    {	"Save"		f.exec {
			    Save
			}				}
    {	"Save As..."	f.exec {
			    send save_panel map
			    set saveP_up 1
			}				}
    {	"Print"		f.exec { 
			    send imagewin setCursorType busy
			    Print
			    send imagewin setCursorType idle
			}				}
    {	"Print Setup"	f.exec {
			    send print_panel map
			    set printP_up 1
			}				}
    {	"TclShell"	f.exec {
			    send tclShell map
			}				}
    {			f.line				}
    {	"Reset"		f.exec {
			    # Do a hard reset.
			    send client Reset
			    #resetView initialize done done
			}				}
    {	"Quit"		f.exec Quit			}
}

createMenu viewMenu viewButton {
    {	"Next frame"	f.exec nextFrame		}
    {	"Prev frame"	f.exec prevFrame		}
    {			f.line				}
    {	"Colormap"	f.menu cmapMenu			}
    {	"Flip"		f.menu flipMenu			}
    {			f.line				}
    {	"Equal aspect"	f.exec {
			    set xmag $frameZoomX($frame)
			    set ymag $frameZoomY($frame)
			    set zoom [expr ($xmag + $ymag) / 2.0]
			    cpZoom $zoom $zoom fixed
			}				}
    {	"Integer zoom"	f.exec {
			    set xmag [expr round ($frameZoomX($frame))]
			    set ymag [expr round ($frameZoomY($frame))]
			    cpZoom $xmag $ymag fixed
			}				}
    {	"Toggle zoom"	f.exec toggleZoom		}
    {	"Unzoom"	f.exec {
			    set zoomindex($frame) 0
			    set mag $zoomfactor($zoomindex($frame))
			    send client zoom $mag $mag $xcen $ycen
			}				}
}

createMenu cmapMenu viewMenu {
    {	"Colormaps"	f.title			}
    {			f.dblline		}
    {	"Normalize"	f.exec normalize	}
    {	"Invert"	f.exec cpInvert		}
    {	"Optimize"	f.exec cpOptimize	sensitive false }
    {			f.line			}
    {	"Grayscale"	f.exec "send client setColormap Grayscale" }
    {	"Color"		f.exec "send client setColormap Color" }
    {	"Heat"		f.exec "send client setColormap Heat" }
    {	"HSV"		f.exec "send client setColormap HSV" }
    {	"AIPS0"		f.exec "send client setColormap AIPS0" }
    {	"Halley"	f.exec "send client setColormap Halley" }
    {	"Ramp"		f.exec "send client setColormap Ramp" }
    {	"Standard"	f.exec "send client setColormap Standard" }
    {	"Staircase"	f.exec "send client setColormap Staircase" }
    {	"Rainbow1"	f.exec "send client setColormap Rainbow1" }
    {	"Rainbow2"	f.exec "send client setColormap Rainbow2" }
    {	"Random8"	f.exec "send client setColormap Random8" }
}

createMenu flipMenu viewMenu {
    {	"Flip X"	f.exec xflip		}
    {	"Flip Y"	f.exec yflip		}
    {	"Flip XY"	f.exec xyflip		}
}

set optionsMenuDescription {
    {	"Autoscale"	f.exec {
			    set value [send autoscaleButton get on]
			    send autoscaleButton set on [expr !$value]
			    cpSetAutoscale
			}			}
    {	"Antialias"	f.exec {
			    set value [send antialiasButton get on]
			    send antialiasButton set on [expr !$value]
			    cpSetAntialias
			}			}
    {	"Panner"	f.exec { setPanner [expr !$panner_enable] }	}
    {   "Magnifier"     f.exec { setMagnifier [expr !$magnifier_enable] }}
    {	"Coords box"	f.exec { setTrack [expr !$track_enable] }	}
    {	"Tile frames"	f.exec {
			    set value [send tileFramesButton get on]
			    send tileFramesButton set on [expr !$value]
			    cpSetTileFrames
			}			}
    {	"Clear frame"	f.exec clearFrame	}
    {	"Fit frame"	f.exec fitFrame		}
    {	"Match LUTs"	f.exec cpMatchFrames	}
    {	"Register"	f.exec cpRegisterFrames	}
    {	{$blinkId ? "Stop blink" : "Blink frames"}
			f.exec toggleBlink	}
    {			f.line			}
    {   "Control Panel"	f.exec  { panel	
				  set panel_up 1 
				} 	}
    {   "Print Panel"	f.exec  { send print_panel map 
				  set printP_up 1 
				}	}
    {   "Load Panel"	f.exec  { send client setLoadOption rescan
				  send load_panel  map 
				  set loadP_up 1 
				} 	}
    {   "Save Panel"	f.exec  { send save_panel  map 
				  set saveP_up 1 
				}	}
}; createMenu optionsMenu optionsButton $optionsMenuDescription


# MAIN CONTROL PANEL
# ---------------------------


foreach i $frames {set saveView($i) "1 1"}

send prevFrame set bitmap larrow
send nextFrame set bitmap rarrow
send contrastLabel set bitmap contrast
send brightnessLabel set bitmap brightness
send contrastSlider resizeThumb 0.1 1.0
send brightnessSlider resizeThumb 0.1 1.0

proc controlPanelDone args {
    global panel_up
    send controlShell unmap
    send panelButton set state 0
    set panel_up 0
}; send doneButton addCallback controlPanelDone

# panel -- Toggle control panel display.
proc panel args {
    global panel_up
    if {$panel_up} {
	send controlShell unmap
	send panelButton set state 0
	set panel_up 0
    } else {
	send controlShell map
	send panelButton set state 1
	set panel_up 1
    }
}

# resetPanel -- Calling during startup or in an initialize, to reset things.
proc resetPanel {param old new} {
    global frame nframes frames
    global displayPanner displayCoords displayMagnifier
    global blinkFrames warnings

    switch $new {
    startup	{
		}
    restart	{   foreach i $frames {
			send frame$frame set on 0
		    }
		}
    done	{   if {$frame} {
			send frame$frame set on 1
		    }

		    cpResetBlink
		    set button 1
		    foreach i $blinkFrames {
			send blinkFrame$button set label $i
			incr button
		    }

		    cpResetEnhance
		    send pannerButton set on [true $displayPanner]
                    send magnifierButton set on [true $displayMagnifier]
		    send coordsBoxButton set on [true $displayCoords]
		    send warningsButton set on $warnings
		}
    }
}; send initialize addCallback resetPanel


# Frame selection.
# -------------------------------
proc cpSetFrame {widget args} {
    send $widget set on 0
    send client setFrame [send $widget get label]
}

proc cpFrameChanged {param old new} {
    if {$old > 0} {
	send frame$old set on 0
    }
    if {$new > 0} {
	send frame$new set on 1
    }
}

send prevFrame addCallback prevFrame
send nextFrame addCallback nextFrame
send frame addCallback cpFrameChanged
foreach i $frames {send frame$i addCallback cpSetFrame}

# Frame buttons.
proc cpFrameAction {widget args} {
    global frameZoomX frameZoomY frame
    switch $widget {
    aspect	{   set xmag $frameZoomX($frame)
		    set ymag $frameZoomY($frame)
		    set zoom [expr round (($xmag + $ymag) / 2.0)]
		    cpZoom $zoom $zoom fixed
		}
    flipX	{   send client flip x }
    flipY	{   send client flip y }
    flipXY	{   send client flip x y }
    clearFrame	{   clearFrame }
    fitFrame	{   fitFrame }
    }
}
foreach widget {aspect flipX flipY flipXY clearFrame fitFrame} {
    send $widget addCallback cpFrameAction
}

# clearFrame -- Clear the current display frame.
proc clearFrame	args {
    global warnings
    if {$warnings} {
	Wexec client \
	    "Clearing the frame will destroy\n\
	    all data in the frame" \
	    clearFrame
    } else {
	send client clearFrame
    }
}

# fitFrame -- Resize the display window to fit the frame buffer.
proc fitFrame args {
    global frameWidth frameHeight winWidth winHeight
    set dw [expr [send display get width] - $winWidth]
    set dh [expr [send display get height] - $winHeight]
    send display "resize [expr $frameWidth + $dw] [expr $frameHeight + $dh]"
}; 

proc initFitFrame { param old new } {
    if { [lindex $new 0] == "resize"} {
        fitFrame
    }
    pannerMapImage init
}; send frameFit addCallback initFitFrame


# Zoom and pan buttons.
# -------------------------------
proc cpZoomAction {widget args} {
    global frameWidth frameHeight

    switch $widget {
    x1		{   cpZoom 1 1 fixed }

    z2		{   cpZoom 2 2 fixed }
    z3		{   cpZoom 3 3 fixed }
    z4		{   cpZoom 4 4 fixed }
    z5		{   cpZoom 5 5 fixed }
    z8		{   cpZoom 8 8 fixed }

    d2		{   cpZoom [expr 1.0/2] [expr 1.0/2] fixed }
    d3		{   cpZoom [expr 1.0/3] [expr 1.0/3] fixed }
    d4		{   cpZoom [expr 1.0/4] [expr 1.0/4] fixed }
    d5		{   cpZoom [expr 1.0/5] [expr 1.0/5] fixed }
    d8		{   cpZoom [expr 1.0/8] [expr 1.0/8] fixed }

    zoomIn	{   cpZoom 2.0 2.0 relative }
    zoomOut	{   cpZoom 0.5 0.5 relative }

    centerFrame	{   send client pan \
			[expr $frameWidth/2.0] \
			[expr $frameHeight/2.0]
		}

    toggleZoom	{   toggleZoom }
    }
}

proc cpZoom {zoom_x zoom_y mode} {
    global frameZoomX frameZoomY zoomindex frame

    if {$mode == "fixed"} {
	send client zoom $zoom_x $zoom_y
    } else {
	send client zoom \
	    [expr $frameZoomX($frame) * $zoom_x] \
	    [expr $frameZoomY($frame) * $zoom_y]
    }

    set zoomindex($frame) 0
}

proc toggleZoom	args {
    global frameZoomX frameZoomY frameCenterX frameCenterY
    global frameWidth frameHeight saveView frame

    if {$frameZoomX($frame) != 1 && $frameZoomY($frame) != 1} {
	set saveView($frame) \
	    "$frameZoomX($frame) $frameZoomY($frame) \
	     $frameCenterX($frame) $frameCenterY($frame)"
	send client zoom 1 1 \
	    [expr $frameWidth/2.0] \
	    [expr $frameHeight/2.0]
    } else {
	send client zoom $saveView($frame)
    }
}

foreach widget {toggleZoom centerFrame zoomIn zoomOut \
	x1  z2 z3 z4 z5 z8  d2 d3 d4 d5 d8} {
    send $widget addCallback cpZoomAction
}

# Frame data display.
# -------------------------------
set cpFrame 0
set cpXcen 0
set cpYcen 0
set cpXmag 0
set cpYmag 0
set cpXscale 0
set cpYscale 0

proc cpDisplayFrameData {name old new} {
    global cpFrame cpXcen cpYcen
    global cpXmag cpYmag cpXscale cpYscale

    set update 0
    switch $name {
    frame	{   if {$new != $cpFrame} {
			set cpFrame $new
			set update 1
		    }
		}
    frameView	{   # Parse the frameView input.
		    set xmag  [lindex $new 0]; set ymag  [lindex $new 1]
		    set xcen  [lindex $new 2]; set ycen  [lindex $new 3]
		    set xnorm [lindex $new 4]; set ynorm [lindex $new 5]

		    # We need client coords and the overall scale factors.
		    set text [send client encodewcs $xcen $ycen]
		    set xcen [lindex $text 0]
		    set ycen [lindex $text 1]
		    set xscale [expr $xmag * $xnorm]
		    set yscale [expr $ymag * $ynorm]

		    if {$xcen != $cpXcen || $ycen != $cpYcen ||
			$xmag != $cpXmag || $ymag != $cpYmag ||
			$xscale != $cpXscale || $yscale != $cpYscale} {

			set cpXcen $xcen;  set cpXscale $xscale
			set cpYcen $ycen;  set cpYscale $yscale
			set cpXmag $xmag;  set cpYmag $ymag
			set update 1
		    }
		}
    }

    if {$update} {
	set header [format "-- Frame %d --" $cpFrame]
	set center [format "X center: %0.1f\nY center: %0.1f" $cpXcen $cpYcen]
	if {int($cpXmag) >= 10} {
	    set zoom1 [format " X zoom: %0.1f" $cpXmag]
	    set zoom2 [format " Y zoom: %0.1f" $cpYmag]
	} else {
	    set zoom1 [format "X zoom: %0.1f" $cpXmag]
	    set zoom2 [format "Y zoom: %0.1f" $cpYmag]
	}
	if {int($cpXscale) >= 10} {
	    set scale1 [format "X scale: %0.1f" $cpXscale]
	    set scale2 [format "Y scale: %0.1f" $cpYscale]
	} else {
	    set scale1 [format "X scale: %0.2f" $cpXscale]
	    set scale2 [format "Y scale: %0.2f" $cpYscale]
	}
	send frameData set label [format "%s\n%s\n%s\n%s\n%s\n%s" \
	    $header $center $scale1 $scale2 $zoom1 $zoom2]
    }
}; foreach p {frame frameView} {send $p addCallback cpDisplayFrameData}


# Frame enhancement.
# -------------------------------
set cpEnhanceDisable 0
set cpEnhanceId 0
set cpEnhanceMode none
set cpEnhanceVal 0
set cpListItem none

# Windowing the colormap is slow when the mouse is not in the image window,
# so it is necessary to execute the windowColormap in a work procedure.
# This allows any number of slider motion events to be processed for each
# windowColormap, preventing slider events from queueing up.

proc cpResetEnhance args {
    global cpListItem cpEnhanceId
    set cpListItem none
    set cpEnhanceId 0
}

proc cpSetEnhancement {widget cbtype x y} {
    global cpEnhanceMode cpEnhanceVal cpEnhanceId cpEnhanceDisable
    set cpEnhanceMode $widget
    set cpEnhanceVal $x
    if {!$cpEnhanceId && !$cpEnhanceDisable} {
	set cpEnhanceId [postWorkProc cpEnhanceProc]
    }
}
proc cpEnhanceProc args {
    global cpEnhanceMode cpEnhanceVal cpEnhanceId
    global enhancement frame maxContrast
    set val $cpEnhanceVal

    if {$cpEnhanceMode == "contrastSlider"} {
	set contrast [lindex $enhancement($frame) 2]
	send client windowColormap [lindex $enhancement($frame) 1] \
	    [expr (($contrast < 0) ? -$val : $val) * $maxContrast] 
    } else {
	send client windowColormap $val
    }

    set cpEnhanceId 0
    return done
}

proc cpInvert args {
    global enhancement frame
    set contrast [lindex $enhancement($frame) 2]
    send client windowColormap [lindex $enhancement($frame) 1] \
	[expr -1.0 * $contrast]
}

proc cpDisplayEnhancement {param old new} {
    global cpEnhanceId maxContrast cpEnhanceDisable
    global cpListItem enhancement frame

    if {!$frame} \
	return
    set enhance $enhancement($frame)
    if {[llength $enhance] < 3} \
	return

    set colortable [lindex $enhance 0]
    set offset     [lindex $enhance 1]
    set scale      [lindex $enhance 2]

    send colordata set label [format "-- %s --\nCon %0.2f  Brt %0.2f" \
	$colortable $scale $offset]

    if {$colortable != $cpListItem} {
	send colorlist highlight $colortable
	set cpListItem $colortable
    }

    if {!$cpEnhanceId && !$cpEnhanceDisable} {
	set cpEnhanceDisable 1
	send contrastSlider moveThumb [expr abs($scale) / $maxContrast]
	send brightnessSlider moveThumb $offset
	set cpEnhanceDisable 0
    }
}

foreach i {enhancement frame} {
    send $i addCallback cpDisplayEnhancement
}
send contrastSlider addCallback cpSetEnhancement scroll
send brightnessSlider addCallback cpSetEnhancement scroll
send invertButton addCallback cpInvert


# Colortable display and selection.
# -------------------------------
set cpScrollHeight 0

proc cpSetColorList {param old new} {
    send colorlist setList $new resize
}; send colortables addCallback cpSetColorList

proc cpResizeScrollbar {widget cbtype flags x y w h cw ch} {
    global cpScrollHeight
    set newHeight [expr $ch - $h]
    if {$newHeight && $newHeight != $cpScrollHeight} {
	send colorlistScroll setScrollbar 0.0 [expr double($h) / $ch]
	set rowHeight [send colorlist get rowHeight]
	set rowSpacing [send colorlist get rowSpacing]
	send colorlistScroll set increment [expr ($ch <= $h) ? 0 : \
	    "double ($rowHeight + $rowSpacing) / ($ch - $h)"]
	set cpScrollHeight $newHeight
    }
}; send colorlistPort addCallback cpResizeScrollbar

proc cpScrollColorlist {widget cbtype pos} {
    global cpScrollHeight
    send colorlist set y [expr -int($cpScrollHeight * $pos)]
}; send colorlistScroll addCallback cpScrollColorlist scroll

proc cpSelectColor {widget cbtype selections indices} {
    global colortable
    foreach selection $selections {
	send client setColormap $selection
    }
}; send colorlist addCallback cpSelectColor
    

# Frame blink.
# -------------------------------
send BRtext set label $blinkRate

proc cpSetBlinkRate {widget args} {
    global blinkRate
    if {$widget == "BRincrease"} {
	if {$blinkRate < 0.01} {
	    set blinkRate 0.125
	} else {
	    set blinkRate [expr $blinkRate * 2.0]
	}
    } else {
	set blinkRate [expr $blinkRate / 2.0]
	if {$blinkRate < 0.01} {
	    set blinkRate 0
	}
    }
    send BRtext set label $blinkRate
}
foreach widget {BRincrease BRdecrease} {
    send $widget addCallback cpSetBlinkRate
}

proc cpSetBlinkFrame {widget args} {
    global blinkFrames nframes

    set frame [send $widget get label]
    if {$frame == " "} {
	set frame 1
    } else {
	incr frame
	if {$frame > $nframes} {
	    set frame " "
	}
    }
    send $widget set label $frame

    set blinkFrames {}
    foreach i {1 2 3 4} {
	set frame [send blinkFrame$i get label]
	if {$frame != " "} {
	    lappend blinkFrames $frame
	}
    }
}; foreach i $frames {send blinkFrame$i addCallback cpSetBlinkFrame}

proc cpBlink {widget args} {
    global blinkRate blinkId

    if {$blinkRate < 0.01} {
	send $widget set state 0
	blink
    } elseif {($blinkId != 0) != [send $widget get state]} {
	toggleBlink
    }
}; send blinkButton addCallback cpBlink

proc cpResetBlink args {
    global blinkRate blinkFrames blinkIndex frames
    global defaultBlinkRate

    foreach i $frames {
	send blinkFrame$i set label " "
    }
    set blinkRate $defaultBlinkRate
    send BRtext set label $blinkRate
    set blinkIndex 0
}; send blinkReset addCallback cpResetBlink

proc cpTraceBlink {name element op} {
    upvar $name blinkId
    send blinkButton set state [expr $blinkId != 0]
}; trace variable blinkId w cpTraceBlink

proc cpSetBlinkFrames {param old new} {
    global blinkFrames frames
    set blinkFrames {}
    foreach i $frames {
	if {$i <= $new} {
	    lappend blinkFrames $i
	}
    }
    cpResetBlink
    set button 1
    foreach i $blinkFrames {
	send blinkFrame$button set label $i
	incr button
    }
}; send nframes addCallback cpSetBlinkFrames

proc cpRegisterFrames args {
    global blinkFrames
    send client registerFrames \{$blinkFrames\}
}; send registerButton addCallback cpRegisterFrames

proc cpMatchFrames args {
    global blinkFrames
    send client matchFrames \{$blinkFrames\}
}; send matchButton addCallback cpMatchFrames


# Options buttons.
# -------------------------------
proc cpSetPanner {widget args} {
    setPanner [send $widget get on]
}; send pannerButton addCallback cpSetPanner

proc cpTracePanner {name element op} {
    upvar $name panner_enable
    send pannerButton set on $panner_enable
}; trace variable panner_enable w cpTracePanner

proc cpSetMagnifier {widget args} {
    setMagnifier [send $widget get on]
}; send magnifierButton addCallback cpSetMagnifier

proc cpTraceMagnifier {name element op} {
    upvar $name magnifier_enable
    send magnifierButton set on $magnifier_enable
}; trace variable magnifier_enable w cpTraceMagnifier

proc cpSetCoordsBox {widget args} {
    setTrack [send $widget get on]
}; send coordsBoxButton addCallback cpSetCoordsBox

proc cpTraceCoordsBox {name element op} {
    upvar $name track_enable
    send coordsBoxButton set on $track_enable
}; trace variable track_enable w cpTraceCoordsBox

proc cpSetWarnings args {
    global warnings
    set warnings [send warningsButton get on]
}; send warningsButton addCallback cpSetWarnings

proc cpSetAutoscale args {
    set value [send autoscaleButton get on]
    send client setOption autoscale [expr {$value ? "True" : "False"}]
}; send autoscaleButton addCallback cpSetAutoscale

proc cpTrackAutoscale {param old new} {
    send autoscaleButton set on [true $new]
}; send autoscale addCallback cpTrackAutoscale

proc cpSetAntialias args {
    set value [send antialiasButton get on]
    send client setOption antialias [expr {$value ? "True" : "False"}]
}; send antialiasButton addCallback cpSetAntialias

proc cpTrackAntialias {param old new} {
    send antialiasButton set on [true $new]
}; send antialias addCallback cpTrackAntialias

proc cpSetTileFrames args {
    global blinkFrames
    set value [send tileFramesButton get on]
    send client setOption tileFrames \
	[expr {$value ? "True" : "False"}] \{ $blinkFrames \}
}; send tileFramesButton addCallback cpSetTileFrames

proc cpTrackTileFrames {param old new} {
    send tileFramesButton set on [true $new]
}; send tileFrames addCallback cpTrackTileFrames

proc tileFramesToggle args {
    set value [send tileFramesButton get on]
    send tileFramesButton set on [expr !$value]
    cpSetTileFrames
}


# Warning dialog.  This pops up a dialog box with the given warning message,
# and executes the given command if the user pushes OK.
#
# Usage:	Wexec object message [ok_action [cancel_action]]
#
# The message text is displayed in a popup and the user hits the ok or
# cancel button to close the popup.  If an action has been posted for the
# button selected then it is sent to the named object.  Only one alert can
# be in effect at a time; posting another alert before the first has
# completed causes the new alert to override the first.

set W_object ""
set W_ok_command ""
set W_cancel_command ""

proc Wexec {object msg args} {
    global W_object W_ok_command W_cancel_command
    set W_object $object
    set W_ok_command [lindex $args 0]
    set W_cancel_command [lindex $args 1]
    send warnText set label $msg
    send warning map
}

proc Wbutton {widget args} {
    global W_object W_ok_command W_cancel_command
    switch $widget {
    warnOk		{   if [llength $W_ok_command] {
				send $W_object $W_ok_command
			    }
			}
    warnCancel		{   if [llength $W_cancel_command] {
				send $W_object $W_cancel_command
			    }
			}
    }
    send warning unmap
}; foreach w {warnOk warnCancel} {send $w addCallback Wbutton}

# The parameter "alert" is used to forward alerts from the client.
proc setAlert {param old new} {
    Wexec client [lindex $new 0] [lindex $new 1] [lindex $new 2]
}; send alert addCallback setAlert


# Global control panel buttons.
# -------------------------------
proc cpInitialize args {
    send imagewin setCursorType busy
    send client initialize
    send imagewin setCursorType idle
}
send initializeButton addCallback cpInitialize
send normalizeButton addCallback normalize

# Temporarily deactivate some buttons.
send optimizeButton setSensitive false


# INFO box.
#-----------
proc infoDone args	{ send info unmap }
send infoDone addCallback infoDone
proc infoClear args	{ send infoText set string "" }
send infoUpdate addCallback infoUpdate
send infoClear addCallback infoClear

proc infoUpdate args {
    global version frame nframes
    global frameWidth frameHeight frameDepth
    global enhancement
    global cpXcen cpYcen
    global cpXmag cpYmag cpXscale cpYscale

    if {$frame == 0} {
	send infoText set string "initializing display..."
    } else {
	set line1 $version
	set line2 [format "Image:\t\t%s" [send imageTitle get label]]
	set line3 [format "Frame %d of %d:\t%d x %d" \
	    $frame $nframes $frameWidth $frameHeight]
	set cmap [lindex $enhancement($frame) 0]
	set brt [lindex $enhancement($frame) 1]
	set con [lindex $enhancement($frame) 2]
	set line4 [format "Colormap:\t%s" $cmap]
	set line5 [format "Enhancement:\tBrt=%s  Cont=%s" $brt $con]

        set center [format "X: %0.1f\n\t\tY: %0.1f" $cpXcen $cpYcen]
	set line6 [format "Center:\t\t%s" $center]

	set line7 [format "Zoom:\t\tX: %0.2f\n\t\tY: %0.2f" $cpXmag $cpYmag]
	set line8 [format "Scale:\t\tX: %0.2f\n\t\tY: %0.2f" $cpXscale $cpYscale]

	send infoText set string [
	    format "%s\n\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n\n" \
		$line1 $line2 $line3 $line4 $line5 $line6 $line7 $line8
	]
    }
}
foreach param { frame frameView nframes frameSize frameTitle enhancement } {
    send $param addCallback infoUpdate
}


# Cursor positioning routines
#----------------------------

proc move_cursor { xstep ystep args } {
    set raster 0
    send imagewin getCursorPos rx ry
    send imagewin setCursorPos [expr $rx + $xstep] [expr $ry + $ystep] $raster
}   


# Print Panel Functions.
#------------------------
# Global variables needed for the print setup panel

set printColor	prGrayButton
set orientation	epsPortButton
set page_size	epsLetterButton
set imageScale	100

set epsWidgets { epsPageGroup epsOrientLabel epsSizeLabel 
	epsPortButton epsLandButton epsLetterButton epsLegalButton epsA4Button
	ScaleFrame SCdecrease SCtext SCincrease 
}


proc psetup_init args {
    global printColor orientation page_size imageScale #format

    set_printer toPrinter callback 1
    send SCtext set label [ format "%d %%" $imageScale ]
    send $printColor set on true
    send $orientation set on true
    send $page_size set on true
}


proc doPrintOptions { param old new } {
    global imageScale page_size orientation imageScale printColor
    global warnings

    send printStatus set label {}
    set val [join [lrange $new 1 end] " "]

    # print [format "doPrintOptions %s = %s" [lindex $new 0] $val]
    switch [lindex $new 0] {
    autoscale	    { 	if { $val == "True" } {
			    send epsscaleButton set on true
			} elseif { $val == "False" } {
			    send epsscaleButton set on false
			}
		    }
    autorotate	    { 	if { $val == "True" } {
			    send autorotateButton set on true
			} elseif { $val == "False" } {
			    send autorotateButton set on false
			}
		    }
    maxaspect	    { 	if { $val == "True" } {
			    send aspectButton set on true
			} elseif { $val == "False" } {
			    send aspectButton set on false
			}
		    }
    annotate	    { 	if { $val == "True" } {
			    send annotateButton set on true
			} elseif { $val == "False" } {
			    send annotateButton set on false
			}
		    }
    compress	    { 	if { $val == "True" } {
			    send compressButton set on true
			} elseif { $val == "False" } {
			    send compressButton set on false
			}
		    }
    orientation	    { 	send $orientation set on false
			if { $val == "portrait" } {
			    send epsPortButton set on true
			    set orientation epsPortButton
			} elseif { $val == "landscape" } {
			    send epsPortButton set on false
			    set orientation epsLandButton
			}
		    }
    papersize	    { 	send $page_size set on false
			if { $val == "letter" } {
			    send epsLetterButton set on true
			    set page_size epsLetterButton
			} elseif { $val == "legal" } {
			    send epsLegalButton set on true
			    set page_size epsLegalButton
			} elseif { $val == "A4" } {
			    send epsA4Button set on true
			    set page_size epsA4Button
			}
		    }
    imscale	    { 	set imageScale $val
    			send SCtext set label [ format "%d %%" $imageScale ]
		    }
    colortype	    { 	send $printColor set on false
			if { $val == "gray" } {
			    send prGrayButton set on true
			    set printColor prGrayButton
			} elseif { $val == "pseudo" } {
			    send prPseudoButton set on true
			    set printColor prPseudoButton
			} elseif { $val == "rgb" } {
			    send prRGBButton set on true
			    set printColor prRGBButton
			}
		    }
    printerName	    {	if [send toPrinter get on] {
			    send printlist highlight $val
			}
		    }
    printCmd	    {	if [send toPrinter get on] {
			    send printcmd set string $val
			}
		    }
    printFile	    {	if [send toFile get on] {
			    send printcmd set string $val
			}
		    }
    deviceType      {   if { $val == "Printer" } {
			    send printerLabel set label "Print Command:"
			    send toPrinter set on true
			    send toFile set on false
		        } elseif { $val == "File" } {
			    send printerLabel set label "File Name:"
			    send toPrinter set on false
			    send toFile set on true
			    send printlist unhighlight
		        }
		    }

    status	    {   send printStatus set label $val
			send server synchronize
	 	    }
    warning	    {   if {$warnings} { Wexec server $val }
		    }
    }
}; send printOptions addCallback doPrintOptions


# Print options procedures.
# -------------------------------

set prOptsWidgets { 
    toPrinter toFile
    prGrayButton prPseudoButton prRGBButton
    epsLandButton epsPortButton
    epsLetterButton epsLegalButton epsA4Button
    SCincrease SCdecrease
}
set prSimpleOptions { 
    epsscaleButton autorotateButton aspectButton annotateButton compressButton 
}

proc prPrintCommand { widget cbtype args } {
    if [send toFile get on] {
	send client setPrintOption printfile $args
	send printStatus set label [format "output file set to %s" $args]
    } else {
	send client setPrintOption printcmd $args
	send printStatus set label [format "print command set to %s" $args]
    }
}; send printcmd addCallback prPrintCommand

proc prOptionToggle { widget cbtype args } {
    global imageScale

    # Handle the image scale widgets first.
    #print [ format "prOptionToggle %s" $widget ]
    switch $widget {
    SCincrease	{ set scale [expr $imageScale + 5] 
  		  send client setPrintOption imscale $scale
		  return
		}
    SCdecrease	{ set scale [ expr $imageScale - 5 ]
		  send client setPrintOption imscale $scale
		  return
		}
    }

    # If it's not one of those it must be one of the radio toggles.
    set val [ send $widget get on ]
    #print [ format "prOptionToggle %s = %s" $widget $val ]
    if { $val == 1 } {
        switch $widget {
        toPrinter  	{ send client setPrintOption devicetype printer }
        toFile  	{ send client setPrintOption devicetype file }

        epsLandButton   { send client setPrintOption orientation landscape }
        epsPortButton   { send client setPrintOption orientation portrait }

        epsLetterButton { send client setPrintOption papersize letter }
        epsLegalButton  { send client setPrintOption papersize legal }
        epsA4Button     { send client setPrintOption papersize A4 }

        prGrayButton    { send client setPrintOption colortype gray }
        prPseudoButton  { send client setPrintOption colortype pseudo }
        prRGBButton     { send client setPrintOption colortype rgb }
	}
    } else {
	send $widget set on true
    }

} ; foreach w $prOptsWidgets { send $w addCallback prOptionToggle }

proc prSimpleOptionToggle { widget args } {
    set val [ send $widget get on ]
    #print [ format "prSimpleOptionToggle %s = %s" $widget $val ]

    switch $widget {
    epsscaleButton   { send client setPrintOption autoscale  $val }
    autorotateButton { send client setPrintOption autorotate $val }
    aspectButton     { send client setPrintOption maxaspect  $val }
    annotateButton   { send client setPrintOption annotate   $val }
    compressButton   { send client setPrintOption compress   $val }
    }
} ; foreach w $prSimpleOptions { send $w addCallback prSimpleOptionToggle }



# Printer display and selection.
# -------------------------------
set psScrollHeight 0

proc psSetPrintList {param old new} {
    send printlist setList $new resize
    send printlist highlight 0
}; send printerList addCallback psSetPrintList

proc psResizeScrollbar {widget cbtype flags x y w h cw ch} {
    global psScrollHeight
    set newHeight [expr $ch - $h]
    if {$newHeight && $newHeight != $psScrollHeight} {
        send printlistScroll setScrollbar 0.0 [expr double($h) / $ch]
        set rowHeight [send printlist get rowHeight]
        set rowSpacing [send printlist get rowSpacing]
        send printlistScroll set increment [expr ($ch <= $h) ? 0 : \
            "double ($rowHeight + $rowSpacing) / ($ch - $h)"]
        set psScrollHeight $newHeight
    }
}; send printlistPort addCallback psResizeScrollbar

proc psScrollPrintlist {widget cbtype pos} {
    global psScrollHeight
    send printlist set y [expr -int($psScrollHeight * $pos)]
}; send printlistScroll addCallback psScrollPrintlist scroll

proc psSelectPrint {widget cbtype selections indices} {
    global printerlist
    foreach selection $selections {
        send client setPrintOption printername $selection
    }
}; send printlist addCallback psSelectPrint


proc printQuit { args } {
    send print_panel unmap
} ; send donePrint addCallback printQuit

proc Print { args } {
    global winWidth winHeight
    send imagewin setCursorType busy

    # Get the print command or file template if not previous reset.
    set val [ send printcmd get string ]
    if [send toFile get on] {
	send client setPrintOption printfile $val
    } else {
	send client setPrintOption printcmd $val
    }
    setPrintCorners 0 [expr $winWidth - 1] [expr $winHeight - 1] 0

    send client print
    send imagewin setCursorType idle
} ; send okayPrint addCallback Print


# setPrintCorners -- Tell the client the WCS of the image being printed.

proc setPrintCorners { lx ly ux uy args } {
    global winWidth winHeight

    # Convert raw corner screen coordinates to frame buffer raster coords.
    send imagewin unmapPixel $lx $ly raster llx lly
    set llx [expr "int ($llx)"]
    set lly [expr "int ($lly)"]
    set str  [send client encodewcs $llx $lly]
    scan $str "%g %g %g" llx_r lly_r z
    set llx_i [expr "int ($llx_r)"]
    set lly_i [expr "int ($lly_r)"]

    send imagewin unmapPixel $ux $uy raster urx ury
    set urx [expr "int ($urx)"]
    set ury [expr "int ($ury)"]
    set str [send client encodewcs $urx $ury]
    scan $str "%g %g %g" urx_r ury_r z
    set urx_i [expr "int ($urx_r)"]
    set ury_i [expr "int ($ury_r)"]

    send client setPrintOption corners $llx_i $lly_i $urx_i $ury_i
}


#--------------------------
# Save panel functions.
#--------------------------
# Global variables needed for the save setup panel

set format	rasButton
set saveColor	svPseudoButton

set fileFmtButtons {
    rasButton gifButton jpegButton tiffButton 
    fitsButton x11Button pnmButton rawButton 
}


# Format group procedures.
#---------------------------------

# Select a format.

proc set_format { widget func state args } {
    global format saveColor

    send $format set on false
    if {$widget == $format} {
	send $widget set on true
    } else {
	switch $widget  { 
	rasButton	{ send client setSaveOption format ras  } 
	gifButton	{ send client setSaveOption format gif  }
	jpegButton	{ send client setSaveOption format jpeg }
	tiffButton	{ send client setSaveOption format tiff }
	fitsButton	{ send client setSaveOption format fits }
	x11Button	{ send client setSaveOption format x11  }
	pnmButton	{ send client setSaveOption format pnm  }
	rawButton	{ send client setSaveOption format raw  }
	}
    }
} ; foreach fmt $fileFmtButtons { send $fmt addCallback set_format }

proc setSaveFile { widget cbtype args } {
	send client setSaveOption fname $args
	send saveStatus set label [format "output file set to %s" $args]
}; send saveFile addCallback setSaveFile


proc doSaveOptions { param old new } {
    global format saveColor
    global warnings

    send saveStatus set label {}
    set val [join [lrange $new 1 end] " "]

    #print [format "doSaveOptions %s = %s" [lindex $new 0] $val]
    switch [lindex $new 0] {
    format  {   
        	# Now (de)sensitize the color options depending on the format,
        	# force the color choice when needed.
    		send $format set on false
        	switch [lindex $val 0] {
        	ras       { #send svRGBButton setSensitive false
                            send svPseudoButton setSensitive true
			    set format rasButton
                          }
        	gif       { send svRGBButton setSensitive false
                            send svPseudoButton setSensitive true
                            if {$saveColor == "svRGBButton"} {
                                send $saveColor set on false
                                send svPseudoButton set on true
                                set saveColor svPseudoButton
                            }
			    set format gifButton
                          }
        	jpeg      { send svRGBButton setSensitive true
                            send svPseudoButton setSensitive true
			    set format jpegButton
                          }
        	tiff      { send svRGBButton setSensitive false
                            send svPseudoButton setSensitive true
			    set format tiffButton
                          }
        	fits      { send svRGBButton setSensitive false
                            send svPseudoButton setSensitive false
                            send $saveColor set on false
                            send svGrayButton set on true
                            set saveColor svGrayButton
			    set format fitsButton
                          }
        	x11       { send svRGBButton setSensitive true
                            send svPseudoButton setSensitive true
			    set format x11Button
                          }
        	pnm       { send svRGBButton setSensitive true
                            send svPseudoButton setSensitive true
			    set format pnmButton
                          }
        	raw       { send svRGBButton setSensitive true
                       	    send svPseudoButton setSensitive true
			    set format rawButton
                          }
        	}
    		send $format set on true
	    }
    color   { send $saveColor set on false
	      switch [lindex $val 0] {
	      grayscale   { send svGrayButton set on true
     			    set saveColor svGrayButton
			  }
	      pseudocolor { send svPseudoButton set on true
     			    set saveColor svPseudoButton
			  }
	      rgb	  { send svRGBButton set on true
     			    set saveColor svRGBButton
			  }
	      }
	    }
    fname   { send saveFile set string $val
	    }
    status  { send saveStatus set label $val
	      send server synchronize
	    }
    text    { send saveData set label $val
	    }
    warning { if {$warnings} { Wexec server $val }
	    }
    }
} ; send saveOptions addCallback doSaveOptions


# Color group procedures.
#---------------------------------
send svGrayButton   addCallback "send client setSaveOption color grayscale"
send svPseudoButton addCallback "send client setSaveOption color pseudocolor"
send svRGBButton    addCallback "send client setSaveOption color rgb"

send doneSave     addCallback "send save_panel unmap"

proc Save { args } {
    send imagewin setCursorType busy

    # Get the print command or file template if not previous reset.
    set val [ send saveFile get string ]
    send client setSaveOption fname $val
    send saveStatus set label [format "output file set to %s" $args]

    send client save
    send imagewin setCursorType idle
    #send save_panel unmap
} ; send okaySave addCallback Save


# ------------------------------------------
# Image and objects list display and section
# ------------------------------------------

set load_frame 1

proc filesTextHighlight { widget event args } {
    if { $event == "enterNotify" } {
        send $widget set displayCaret True
    } elseif { $event == "leaveNotify" } {
        send $widget set displayCaret False
    }
}
send imtemplateText addEventHandler filesTextHighlight enterWindowMask
send imtemplateText addEventHandler filesTextHighlight leaveWindowMask
send fnameText      addEventHandler filesTextHighlight enterWindowMask
send fnameText      addEventHandler filesTextHighlight leaveWindowMask

send rootButton     addCallback "send client setLoadOption root"
send homeButton     addCallback "send client setLoadOption home"
send upButton       addCallback "send client setLoadOption up"
send rescanButton   addCallback "send client setLoadOption rescan"

proc setPattern { widget mode pattern args } {
    send client setLoadOption pattern $pattern
} ; send imtemplateText addCallback setPattern

proc doLoadOptions { param old new } {
    global warnings loadP_up

    set val     [ join [lrange $new 1 end] " " ]

    #print [format "doLoadOptions %s = %s" [lindex $new 0] $val]
    switch [lindex $new 0] {
    pattern  	{ send imtemplateText set string [format "%s" $val ] }
    curdir   	{ send dirLabel set label [format "Directory:  %s" $val ] }
    newfile  	{ send fnameText set string $val
                  if { [ string last / $val ] < 0 } {
	              if { [send browseToggle get on] == 0 } {
		         send load_panel unmap
			 set loadP_up 0
	              }
	          }
	        }
    status  { send filesStatus set label $val
              if { ! $loadP_up } { send imageTitle set label $val }
	      send server synchronize
	    }
    warning 	{ if {$warnings} { Wexec server $val } }
    gray	{ send grayToggle set on $val }
    }
} ; send loadOptions addCallback doLoadOptions

proc toggleGraymap { widget args } {
    send client setLoadOption gray [ send grayToggle get on ]
} ; send grayToggle addCallback toggleGraymap

proc fileLoad { widget mode fname args } {
    global load_frame loadP_up
    send imagewin setCursorType busy
    send client load $fname $load_frame
    set fpath [format "%s/%s" \
        [string range [send dirLabel get label] 12 end] \
        $fname ]
    if { [ string last / $fname ] < 0  && [ file isfile $fpath] == 1 } {
        if { [send browseToggle get on] == 0 } {
            send load_panel unmap
	    set loadP_up 0
        }
    }
    send imagewin setCursorType idle
} ; send fnameText addCallback fileLoad


set imlistScrollheight 0

proc setFileList {param old new} {
    send imageList setList $new resize
}; send filelist addCallback setFileList

proc flresizeScrollbar { widget cbtype flags x y w h cw ch } {
    global imlistScrollheight
    set newheight [expr $ch - $h]
    if { $newheight != $imlistScrollheight } {
        send imlistScrollbar setScrollbar 0.0 [expr double($h) / $ch]
        set imlistScrollheight $newheight
    }
} ; send imlistPorthole addCallback flresizeScrollbar

proc flscrollList { widget cbtype pos } {
    global imlistScrollheight
    send imageList set y [expr -int($imlistScrollheight * $pos)]
} ; send imlistScrollbar addCallback flscrollList scroll

proc flSelectPrint {widget cbtype selections args} {
    global load_frame loadP_up
    foreach selection $selections {
        send client load $selection $load_frame
        if { [ string last / $selection ] < 0 } {
            if { [send browseToggle get on] == 0 } {
                send load_panel unmap
		set loadP_up 0
            }
        }
    }
}; send imageList addCallback flSelectPrint

proc fileSetFrame {widget args} {
    global nframes load_frame

    set frame [send $widget get label]
    if {$frame == $nframes} {
        set frame 1
    } else {
        incr frame
    }
    send $widget set label $frame
    set load_frame $frame
}; send frameFrame addCallback fileSetFrame

proc fileLoadB args {
    global load_frame loadP_up
    send imagewin setCursorType busy
    set fname [send fnameText get string]
    if {$fname == ""} {
	Wexec client "No image name specified"
    } else {
        send client load $fname $load_frame
        set fpath [format "%s/%s" \
            [string range [send dirLabel get label] 12 end] \
            $fname ]
        if { [ string last / $fname ] < 0  && [ file isfile $fpath] == 1 } {
            if { [send browseToggle get on] == 0 } {
                send load_panel unmap
                set loadP_up 0
            }
        }
        send imagewin setCursorType idle
    }
} ; send filesLoadButton addCallback fileLoadB

proc fileQuit args {
    send load_panel unmap
    set loadP_up 0
} ; send filesCloseButton addCallback fileQuit


# More Panel toggles

proc infoPanel args {
    global infoP_up
    if {$infoP_up} {
        send info unmap
        set infoP_up 0
    } else {
        send info map
        set infoP_up 1
    }
}

proc pannerPanel args {
    global panner_enable
    setPanner [expr !$panner_enable]
}

proc magnifierPanel args {
    global magnifier_enable
    setMagnifier [expr !$magnifier_enable]
}

proc wcsPanel args {
    global track_enable
    setTrack [expr !$track_enable]
}

proc loadPanel args {
    global loadP_up
    if {$loadP_up} {
        send load_panel unmap
        set loadP_up 0
    } else {
        send client setLoadOption rescan
        send load_panel map
        set loadP_up 1
    }
}

proc savePanel args {
    global saveP_up
    if {$saveP_up} {
        send save_panel unmap
        set saveP_up 0
    } else {
        send save_panel map
        set saveP_up 1
    }
}

proc printPanel args {
    global printP_up
    if {$printP_up} {
        send print_panel unmap
        set printP_up 0
    } else {
        send print_panel map
        set printP_up 1
    }
}


#------------------------------------
# Define procedure for the help panel
#------------------------------------

# Help Panel Bitmaps
#-------------------
createBitmap iraf_logo 45 45 {
0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff,
0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff,
0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xff,
0xff, 0x3f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0xff, 0xff, 0xff,
0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff,
0xff, 0x3f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x80, 0xfc, 0xff, 0xff,
0xff, 0x3f, 0x84, 0xf8, 0xff, 0xff, 0xff, 0x1f, 0x84, 0xf4, 0xff, 0xff,
0xff, 0x1b, 0x04, 0x09, 0x00, 0xfc, 0xff, 0x11, 0x04, 0x11, 0xf8, 0xff,
0x7f, 0x10, 0x04, 0x21, 0xc0, 0xff, 0x1f, 0x10, 0x04, 0x41, 0xf0, 0xff,
0x00, 0x18, 0x04, 0x01, 0xe0, 0xff, 0x00, 0x18, 0x00, 0x81, 0xc0, 0xff,
0x00, 0x08, 0x00, 0x01, 0xe0, 0xff, 0x07, 0x08, 0x00, 0x01, 0xf1, 0xff,
0x1f, 0x08, 0x80, 0x21, 0xf0, 0xff, 0xff, 0x08, 0xc0, 0x41, 0xf4, 0xff,
0xff, 0x08, 0xc0, 0x41, 0xf8, 0xff, 0xff, 0x09, 0xc0, 0xc1, 0xf0, 0xff,
0xff, 0x0b, 0x80, 0xc1, 0xf1, 0xff, 0xff, 0x07, 0x80, 0x81, 0xe1, 0xff,
0xff, 0x07, 0x80, 0x01, 0xc1, 0xff, 0xff, 0x07, 0x00, 0x01, 0xc0, 0xff,
0xff, 0x07, 0xc2, 0x05, 0x81, 0xff, 0xff, 0x07, 0xf2, 0x07, 0x81, 0xff,
0xff, 0x07, 0xf2, 0x17, 0x03, 0xff, 0xff, 0x03, 0xfa, 0x7f, 0x02, 0xfe,
0xff, 0x03, 0xfe, 0xff, 0x02, 0xfe, 0xff, 0x03, 0xfe, 0xff, 0x03, 0xfc,
0xff, 0x03, 0xff, 0xff, 0x07, 0xfc, 0xff, 0x83, 0xff, 0xff, 0x0f, 0xf8,
0xff, 0xc1, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xe1, 0xff, 0xff, 0x7f, 0xf8,
0xff, 0xf1, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xe0,
0xff, 0xf8, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xe7,
0xff, 0xfc, 0xff, 0xff, 0xff, 0xef}; send helpIRAFLogo "set bitmap iraf_logo"

createBitmap noao_logo 45 45 {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfe, 0xff, 0xff,
0xff, 0xff, 0x01, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf8, 0xff, 0xff,
0xff, 0xff, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf8, 0xff, 0xff,
0xff, 0x7f, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf8, 0xff, 0xff,
0xff, 0xff, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf8, 0xff, 0xff,
0xff, 0xff, 0x01, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfe, 0xff, 0xff,
0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff,
0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff,
0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
0xff, 0xff, 0x03, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfe, 0xff, 0xff,
0xff, 0xff, 0x01, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfc, 0xff, 0xff,
0xff, 0xff, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xf0, 0xff, 0xff,
0xff, 0x7f, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xe0, 0xff, 0xff,
0xff, 0x3f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xc0, 0xff, 0xff,
0xff, 0x1f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x80, 0xff, 0xff,
0xff, 0x0f, 0x00, 0x80, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff,
0xff, 0x03, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x03, 0x00, 0x00, 0xfe, 0xff,
0xff, 0x01, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x01, 0x00, 0x00, 0xfc, 0xff,
0xff, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf8, 0xff,
0x7f, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xf0, 0xff,
0x3f, 0x00, 0x00, 0x00, 0xe0, 0xff}; send helpNOAOLogo "set bitmap noao_logo"

# Stuff for keeping track of visited anchors.
set links 	{ 0 }
set linkIndex 	  0
set visited(0)	empty

send helpInfo1 set label $version

proc Help args {
    global helpP_up
    if {$helpP_up == 0} {
        send client help
    } else {
        send help_panel unmap
        set helpP_up 0
    }
}

proc helpPanel args {
    global helpP_up
    if {$helpP_up} {
        send help_panel unmap
        set helpP_up 0
    } else {
        send help_panel map
        set helpP_up 1
    }
}

proc helpQuit args {
    global helpP_up
    send help_panel unmap
    set helpP_up 0
    send helpButton set state 0
    send helpText setText ""
}; send helpClose addCallback helpQuit

proc getHelpText { param old new } {
    send helpText setText $new
    helpPanel
}; send help addCallback getHelpText

proc anchorSelected {widget cbtype event text href args} {
    global visited links linkIndex
    set anchID [send helpText anchorToId $href]
    set visited($href) 1
    if {$linkIndex == 0} {
	send helpBack set sensitive True
        if {[lindex $links 1] != $anchID} {
	    set links { 0 }
	    send helpForward set sensitive False
        } 
    } 
    if {$linkIndex > 0 && [lindex $links [expr $linkIndex + 1]] != $anchID} {
	set links [lrange $links 0 $linkIndex]
    }
    if {[lindex $links [expr $linkIndex + 1]] != $anchID} {
        lappend links $anchID
        incr linkIndex
    } else {
        send helpForward set sensitive False
        incr linkIndex
    }
    if {$linkIndex == [expr [llength $links] - 1]} {
	send helpForward set sensitive False
    }
    send helpText gotoId $anchID
    send helpText retestAnchors
}; send helpText addCallback anchorSelected anchor

proc testAnchor {widget cbtype href} {
    global visited
    return [info exists visited($href)]
}; send helpText addCallback testAnchor testAnchor


# Callbacks to position forwards and backwards in link list.
proc hlpForward args {
    global links linkIndex
    incr linkIndex
    if {$linkIndex <= [llength $links]} {
        set anchID [lindex $links $linkIndex] 
        send helpText gotoId $anchID
        send helpText retestAnchors
	if {$linkIndex == [expr [llength $links] - 1]} {
	    send helpForward set sensitive False
	    send helpBack set sensitive True
	} else {
	    send helpBack set sensitive True
	}
    } else {
	incr linkIndex -1
    }
}; send helpForward addCallback hlpForward

proc hlpBack args {
    global links linkIndex
    incr linkIndex -1
    if {$linkIndex >= 0} {
        set anchID [lindex $links $linkIndex] 
        send helpText gotoId $anchID
        send helpText retestAnchors
	if {$linkIndex == 0} { send helpBack set sensitive False   }
	if {$linkIndex >= 0} { send helpForward set sensitive True }
    } else {
        incr linkIndex 1
    }
}; send helpBack addCallback hlpBack

proc hlpHome args {
    global links linkIndex
    set links { 0 }
    set linkIndex  0
    send helpText gotoId 0
    send helpForward set sensitive False
    send helpBack set sensitive False
}; send helpHome addCallback hlpHome



#------------------------------------
# Define some TCL debug procedures.
#------------------------------------

set tclP_up 0

proc tclCommandClear {widget args}   { send tclEntry set string "" }
proc tclCommandExecute {widget args} { send server [send tclEntry {get string}]
}
proc tclCommand {widget mode command args} { send server $command }
proc tclClose {widget args}                { send tclShell unmap }
proc tclOpen { args } { 
    global tclP_up
    send tclShell map 
    set tclP_up 1
}

proc tclPanel args {
    global tclP_up
    if {$tclP_up} {
        send tclShell unmap
        set tclP_up 0
    } else {
        send tclShell map
        set tclP_up 1
    }
}

send tclClear                     addCallback tclCommandClear
send tclExecute                   addCallback tclCommandExecute
send tclEntry                     addCallback tclCommand
send tclcloseButton               addCallback tclClose

