// debug alerts used: # 10

// jcontrol.js - control panel support for controlling Jmol.

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// (frames only)
// The control.htm document and its javascript must complete loading
// before we try to run a script defined there in the jmol frame!
// Therefore we must not load jmol until after control.htm is loaded.

function startJmol()
{
	if (top.usingFrames)
		top.frameRight.document.location.replace("moldoc.htm");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function initFG()
{
	top.initHelpTarget();
// removed to facilitate use of "javascript" sitemeter.
//	showHelp2('makeBePatientHelp()');
	startJmol();
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// writeToggleButton() is used to write each toggle button.
// Each button is numbered in the order in which it is written.
// The button numbers are used to take the correct action in: doToggleButton().
// The up and down command scripts, button state, and labels are
// kept in arrays.

var toggleIndex = 0;
var toggleUpSptName = new Array();
var toggleDownSptName = new Array();
var toggleIsDown = new Array();
var toggleHelpName = new Array();
var waterIndex, ligandIndex, backgroundIndex,	slabIndex, spinIndex,
	resetIndex;
var hideIndex, centerIndex, findIndex;


//var toggleIndexFromName = new Array(
//"ligands+", "water", "slab", "background", "spin");

// start is "up" or "down"
function writeToggleButton(downSptName, upSptName, label, start, helpName,
titleMsg)
{
	// remember up and down scripts
	toggleIndex++;
	toggleUpSptName[toggleIndex] = upSptName;
	toggleDownSptName[toggleIndex] = downSptName;
	toggleHelpName[toggleIndex] = helpName;


	if (match(label, "water"))
		waterIndex = toggleIndex;
	if (match(label, "ligand"))
		ligandIndex = toggleIndex;
	if (match(label, "background"))
		backgroundIndex = toggleIndex;
	if (match(label, "spin"))
		spinIndex = toggleIndex;
	if (match(label, "slab"))
		slabIndex = toggleIndex;
	if (match(label, "view1"))
		resetIndex = toggleIndex;

	if (start == "up")
		toggleIsDown[toggleIndex] = false;
	else
		toggleIsDown[toggleIndex] = true;

	if (typeof(titleMsg) == "undefined")
		titleMsg = "";

	var tog = "<a href='javascript: doToggleButton(" + toggleIndex + ")'>" +
"<img src='" + start + ".gif' border='0' name='toggle" + toggleIndex + "'" +
" title='" + titleMsg + "'\/><\/a>&nbsp;" + label;

	document.writeln(tog);

}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// could have been named doButton  dtb
function doToggleButton(tognum)
{
//	alert("doToggleButton(" + tognum + ")");

// ======== REFUSE TOGGLE ================

	// DON'T USE WATER BUTTON DURING CONTACTS TARGET SELECTION
	if (selectMode != "" && tognum == waterIndex)
		if (confirm("To select water as a target for contacts,\n" +
			"please use the \"Show Water\" checkbox below.\n" +
			"OK to continue target selection, or\n" +
			"Cancel to quit target selection."))
			return;

	// SLAB can't be turned on during precontacts selection.
	if (tognum == slabIndex && selectMode != "")
	{
		alert("Sorry, but slab mode is not compatible\n\
with target selection.");
		return;
	}

	// SLAB can't be turned on during hiding.
	if (tognum == slabIndex && hideMode != "")
	{
		alert("Sorry, but slab mode is not compatible\n\
with hiding.");
		return;
	}

// ======== END REFUSE TOGGLE ================
// ======== BEGIN EXECUTE TOGGLE ================

	var sptname = toggleUpSptName[tognum];

	var spt;

	var imgnum = eval("document.toggle" + tognum);
	if (toggleIsDown[tognum]) // going up/off
	{
		imgnum.src = "up.gif";
		spt = eval(toggleUpSptName[tognum]);
		toggleIsDown[tognum] = false;
	}
	else // toggle is up, going on/down
	{
		showHelp2(toggleHelpName[tognum]);

		imgnum.src = "down.gif";
		spt = eval(toggleDownSptName[tognum]);
		toggleIsDown[tognum] = true;
	}

	// For background, refresh the PDB Id echo
	if (tognum == backgroundIndex)
		spt += makeEchoPdbIdSpt(""); // blank parameter means get color from toggle

	// if centering was on, and the button went down (except for bkg, spin),
	// now the centering controls are gone, so turn centering off.
	// Ditto for hiding & selecting.
	if (tognum != spinIndex && tognum != backgroundIndex)
	{
		if (toggleIsDown[tognum]) // button went down
		{
			// must be done before scriptToJmol!
			centerMode = false; // scriptToJmol turns off picking center
			top.hideMode = "";
			top.selectMode = "";
		}
	}

//	alert("jcontrol.js #3: doToggleButton(" + spt + ")");
	doMolViewSpt(spt); // in doToggleButton()
}


//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// writepresToggle() is used to write each toggle button for PRESENTATION.
// This differ from other toffle button by the image used it indicate up or down.
// Which is done or undone too.
// Each button is numbered in the order in which it is written.
// The button numbers are used to take the correct action in doToggle().
// The up and down command scripts, button state, and labels are
// kept in arrays.

var prestoggleNumber = 0;
var prestoggleUpSpt = new Array();
var prestoggleDownSpt = new Array();
var prestoggleIsDown = new Array();
var prestoggleHelp = new Array();
 

// start is "undone" or "done"
function writepresToggle(presdownSpt, presupSpt, label, start, help)
{
	// remember up and down scripts
	prestoggleNumber++;
	prestoggleUpSpt[prestoggleNumber] = presupSpt;
	prestoggleDownSpt[prestoggleNumber] = presdownSpt;
	prestoggleHelp[prestoggleNumber] = help;
 
	if (start == "undone")
		prestoggleIsDown[prestoggleNumber] = false;
	else
		prestoggleIsDown[prestoggleNumber] = true;

	var prestog = "<a href='javascript: presdoToggle(" + prestoggleNumber + ")'>" +
"<img src='" + start + ".gif' border='0' name='prestoggle" + prestoggleNumber + "'" +
" \/><\/a>&nbsp;" ;

	document.writeln(prestog);

}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function presdoToggle(prestognum)
{
//	alert("doToggle(" + tognum + ")");

	var spt;

	var presimgnum = eval("document.prestoggle" + prestognum);
	if (prestoggleIsDown[prestognum]) // going up/off
	{
		presimgnum.src = "undone.gif";
		spt = prestoggleUpSpt[prestognum];
		prestoggleIsDown[prestognum] = false;
	}
	else // toggle is up, going on/down
	{
		showHelp2(prestoggleHelp[prestognum]);

		presimgnum.src = "done.gif";
		spt = prestoggleDownSpt[prestognum];
		prestoggleIsDown[prestognum] = true;
	}

//	alert("jcontrol.js #3: doToggle(" + spt + ")");
	scriptToJmol(spt);

	// return false;	displays at text on page!
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// writepresentbutton() is used to write each presentation button.
// Each button is numbered in the order in which it is written.
// The button numbers are used to take the correct action in dopresbutton().
// The up and down command scripts, button state, and labels are
// kept in arrays.
var presbuttonNumber = 0;
//var presbuttonUpSpt = new Array();
var presbuttonDownSpt = new Array();
var presbuttonIsDown = new Array();
var presbuttonHelp = new Array();
 

// start is "up" or "down"
function writepresentbutton(downSpt, label, start, help)
{
	// remember up and down scripts
	presbuttonNumber++;
//	presbuttonUpSpt[presbuttonNumber] = upSpt;
	presbuttonDownSpt[presbuttonNumber] = downSpt;
	presbuttonHelp[presbuttonNumber] = help;


	if (start == "undone")
		presbuttonIsDown[presbuttonNumber] = false;
	else
		presbuttonIsDown[presbuttonNumber] = true;

	var  butt = "<a href='javascript: dopresbutton(" + presbuttonNumber + ")'>" +
"<img src='" + start + ".gif' border='0' name='presbutton" + presbuttonNumber + "'" +
" \/><\/a>&nbsp;" ;

	document.writeln(butt);

}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function dopresbutton(buttnum)
{
	//alert("dopresbutton(" + buttnum + ")");

	var spt;

	var imgnum = eval("document.presbutton" + buttnum);
	spt = eval(presbuttonDownSpt[buttnum]);
	showHelp2(presbuttonHelp[buttnum]);
	imgnum.src = "done.gif";
	//spt = eval(presbuttonDownSpt[buttnum]); //need eval command if anything but the actual spcript like 'spin on;'
	//however for reasons beyond my grasp in Eric's Dotoggle function there is no eval and it works with things like slabSpt???
	presbuttonIsDown[buttnum] = true;
	

	//alert("jcontrol.js #3: dopresbutton((" + spt + ")");
	scriptToJmol(spt);
	

	// return false;	displays at text on page!
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function writeInfoLinks()
{
	if (top.validPDBId.length == 0)
		return;

	var info = "<b>" + top.validPDBId + "</b>:&nbsp;";
	info += writePQS();
		info +=	"&nbsp;";
	info += writeRCSB();
		info +=	"&nbsp;";
	info += writeOCA();
		info +=	"&nbsp;";
	info += writeGaps();

	document.writeln(info);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// Write a pdb code-specific link to RCSB's Structure Explorer.

function writeRCSB()
{
	if (top.validPDBId.length == 0)
		return "";

	var tmsg = validPDBId + ' at the Protein Data Bank';

	var rcsb = "<a href='http:\/\/www.rcsb.org\/pdb\/cgi\/explore.cgi?pdbId=" +
	top.validPDBId + "' target='rcsbwin' \/>" +
//	"Structure Explorer<\/a>";
	"<img src='pdb.gif' border=1 align='center' \
title='" + tmsg + "'><\/a>";

	return(rcsb);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function writeOCA()
{
	if (top.validPDBId.length == 0)
		return "";

	var oca = "<a href='http:\/\/bip.weizmann.ac.il\/oca-bin\/ocashort?id=" +
	top.validPDBId + "' target='ocawin' \/>" +
	"<img src='oca.gif' border=1 align='center' \
title='" + validPDBId + " info at OCA'><\/a>";

	return oca;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function writeGaps()
{
	if (top.validPDBId.length == 0)
		return "";

	var descrip = "<img src='gaps2.gif' border=1 align='center'>";
	var ttl = validPDBId + " Sequences with Gaps from S2C";
	var gaps = "<a href='notes.htm?mol=" + validPDBId + "#seq' " +
		"title='" + ttl + "' target=_blank>" +
		descrip + "</a>";

	return gaps;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function writePQS()
{
	if (top.validPDBId.length == 0)
		return "";

	var pqs = 
		"<a href='http://pqs.ebi.ac.uk/pqs-bin/macmol.pl?filename=" +
		top.validPDBId + "' target='pqswin'>" +
		"<img src='pqs.gif' border=1 align='center' \
title='" + validPDBId + " Specific Oligomers or Monomers'></a>";

	return (pqs);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// Write a special troubleshooting message, only if the Safari browser
// is being used. In 11/05, this bug in Apple's java had been fixed in
// OSX.4 (tiger) but not in OSX.3.9.

function writeSafari()
{
	if (navigator.appVersion.indexOf("Mac") == -1)
		return;
	var safariBug =
"Quit, restart the browser if the above controls don't work. \
<a href=\"notes.htm#safari\" target=_blank>Why?</a><br>";

	document.writeln(safariBug);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// Write a pdb code-specific link to Protein Explorer.

function writePE()
{
	if (top.validPDBId.length == 0)
		return "";

	var pe = "<a href='http:\/\/www.umass.edu/microbio/chime/pe/protexpl/pe.htm?id=" +
	top.validPDBId + "' target='_top'>Protein Explorer<\/a>";

	return(pe);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// Write a link that sends a command script to Jmol.
// Each link is numbered in the order in which they are written.
// The link numbers are used to perform the correct action in: doViewLink().
// Actions and link labels are stored in arrays.

var linkTotal = 0;
var viewLinkSptName = new Array();
var viewLinkHelpName = new Array();

function writeViewLink(sptName, label, helpName, titleMsg)
{

// This is what jmol.js jmolLink() makes:
//<A name='jmolLink0' id='jmolLink0'
//href='javascript:_jmolClick(1);'
//onMouseover='_jmolMouseOver(1);return true;' onMouseout='_jmolMouseOut()'
//>Cartoon</A>

	linkTotal++;
	viewLinkSptName[linkTotal] = sptName;
	viewLinkHelpName[linkTotal] = helpName;
//	linkLabel[linkTotal] = label;

	if (match(sptName, "hide"))
		hideIndex = linkTotal;
	if (match(sptName, "center"))
		centerIndex = linkTotal;
	if (match(sptName, "find"))
		findIndex = linkTotal;
	
	var lk = "<a href='javascript: doViewLink(" + linkTotal + ")'";
	if (typeof(titleMsg) != "undefined")
	{
		if (titleMsg != "")
			lk += " title='" + titleMsg + "' ";
	}
	lk += ">" + label + "<\/a>"

	document.writeln(lk);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function doViewLink(lnum) // dvl
{
	// LOCAL CONVENIENCE FLAGS
	var hideNow = match(viewLinkSptName[lnum], "hide");
	var vinesNow = match(viewLinkSptName[lnum], "vine");
	var preContacts = match(viewLinkSptName[lnum], "precontacts");
	var preFind = match(viewLinkSptName[lnum], "find");
	var resetNow = match(viewLinkSptName[lnum], "view1");

	// CONFIRM NEW CONTACTS
	if (preContacts && contactsShowing)
	{
		if (!confirm("OK to select new targets for Contacts,\n" +
			"or Cancel to keep current Contacts."))
		{
			showHelp2("makeContactsShownHelp()");
			return;
		}
	}
			
	// contactsShowing goes off unless Find, Hide, Center, More Views, or
	// Troubleshooting.
	// This must happen before showing help!
	if (!hideNow && !preFind && !match(viewLinkSptName[lnum], "center") &&
		!match(viewLinkSptName[lnum], "moreviews") &&
		!match(viewLinkSptName[lnum], "troubleshooting"))
	{
		contactsShowing = false;
		markContactsTargets = false;
	}

	if (preContacts)
		resetContacts(); // must be done before showing help

	// RESET
	if (resetNow)
	{
		doReset();
	}

	if (vinesNow) // must be done before help
	{
		setButtonState("up", waterIndex);
		allWireframe = false;
		hydrogensVisible = true;
		sidechainsVisible = true;
	}

	// SHOW HELP
	showHelp2(viewLinkHelpName[lnum]);
//	alert("jcontrol.js #6: help shown in doViewLink()");

	// FOCUS FIND SLOT
	if (match(viewLinkHelpName[lnum], "makefindhelp"))
		setTimeout("document.findForm.toFind.focus()", 100);

	// RETURN IF NO SCRIPT
	// More Views, Troubleshooting are special cases with NO SCRIPT
	if (match(viewLinkSptName[lnum], "moreviews") ||
		match(viewLinkSptName[lnum], "troubleshooting"))
	{
		cancelCenteringNoHelp(); // sends script set picking on
		selectMode = ""; // in doViewLink()
		return;
	}

	// SET VARIOUS FLAGS
	// For all remaining views, non-standard residues will be hidden.
//	alert("jcontrol.js #4: turning off showNonStandardResidues");
	top.showNonStandardResidues = false;

	// For all remaining views, hiding mode goes off.
	top.hideMode = "";

	// Unless this is Contacts, selectMode goes off.
	if (!preContacts)
		top.selectMode = ""; // in doViewLink()

	//..................................................
	// BUTTONS FORCED UP/DOWN
	//..................................................

	// WATER BUTTON GOES ON/DOWN if Composition, Contacts
	if (match(viewLinkSptName[lnum], "composition") || preContacts)
		setButtonState("down", waterIndex);

	// LIGAND BUTTON GOES ON/DOWN if Composition, Vines, precontacts, reset
	if (match(viewLinkSptName[lnum], "composition") ||
		vinesNow ||	preContacts || resetNow)
			setButtonState("down", ligandIndex);

	// WATER BUTTON GOES OFF/UP if Polarity, Charge, All Models, reset,
	// Vines done above.
	// preContacts
	if (match(viewLinkSptName[lnum], "polarity") ||
		match(viewLinkSptName[lnum], "charge") ||
		match(viewLinkSptName[lnum], "allmodels") || resetNow || preContacts)
			setButtonState("up", waterIndex);

	// LIGAND BUTTON GOES OFF/UP if Polarity, Charge, All Models
	if (match(viewLinkSptName[lnum], "polarity") ||
		match(viewLinkSptName[lnum], "charge") ||
		match(viewLinkSptName[lnum], "allmodels"))
			setButtonState("up", ligandIndex);

	// BACKGROUND BUTTON GOES BLACK/UP if precontacts, prefind
	if (preContacts || preFind)
	{
		setButtonState("up", backgroundIndex); // Background Black
	}

	// BACKGROUND BUTTON GOES DOWN/WHITE if reset
	if (resetNow)
		setButtonState("down", backgroundIndex);

	// SLAB BUTTON GOES OFF/UP if precontacts, reset, or hide
	if (preContacts || resetNow || hideNow)
		setButtonState("up", slabIndex);

	// SPIN BUTTON GOES DOWN/ON if reset
	if (resetNow)
		setButtonState("down", spinIndex);

	//....................................................
	// END BUTTONS
	//....................................................

	// SET centerMode IF CENTERING
	if (match(viewLinkSptName[lnum], "center"))
		top.centerMode = true;

	// SET default view for contacts
	if (preContacts)
		contactsView = "sf";

	// SET hideMode
	if (hideNow)
		hideMode = "c"; // hide has blank script, but needs sTJ postscripts!

	// RECORD CURRENT VIEW UNLESS ...
//	alert("jcontrol.js #7: doViewLink() viewLinkSptName=" + viewLinkSptName[lnum]);
	if (!match(viewLinkSptName[lnum], "center") &&
		!match(viewLinkSptName[lnum], "find") &&
		!match(viewLinkSptName[lnum], "hide"))
			currentView = viewLinkSptName[lnum];

	// MAIN VIEW SCRIPT
	var spt = eval(viewLinkSptName[lnum]);

	if (preContacts || resetNow || hideNow) // SLAB FORCED OFF
		spt += 	hoverSpt; // restore hover report

	if (hideNow)
		spt += "slab off;\n"; // in doViewLink, for Hide

	if (resetNow)
		spt += clearBoxes();

	spt += makeEchoPdbIdSpt(""); // blank parameter means get color from toggle

	// Clicking "Contacts.." always starts with nothing selected.
	if (preContacts)
	{
		clearSelectedArrays();		
		spt += "select none; define ~targ_current selected;\n";
	}

	// if centering was on, now the controls are gone, so turn it off.
	if (!match(viewLinkSptName[lnum], "center"))
		top.centerMode = false; // DO BEFORE SENDING SCRIPT!

	doMolViewSpt(spt); // in doViewLink()
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function writeHTML(h)
{
	document.writeln(h);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// showHelp2() is called by showHelp(), as well as directly in several
// places.

function showHelp2(helpname)
{
//	alert("jcontrol.js #8: showHelp2 receives " + helpname);
	if (helpname == "")
		return;
	
	// In some cases, the help HTML must be dynamically generated.
	// In other cases, the help HTML text is static.
	// Regardless of whether helpname is a static variable or a function,
	// the code below works.

	var prehtxt = makeHelpPrefix(helpname);

	var htxt;
	if (typeof(htxt = eval("top." + helpname)) == "undefined")
		htxt = top.nohelp;

	htxt = prehtxt + htxt;

//	alert("jcontrol.js #5: " + top.helpTarget.document)

//	htxt = eval("top." + helpname);

	// In most cases, add a footer with a link back to the introHelp.
	if (!match(helpname, "ntrohelp") && !match(helpname, "epatienthelp"))
			htxt += top.helpFooter;

	// Write the htxt to the help frame or division.

	if (top.usingFrames)
	{
		with(top.helpTarget.document)
		{
			open();
			writeln("<html><head><\/head><body bgcolor='#" + top.backgroundColor + "'>");
			writeln(htxt);
			writeln("<\/body><\/html>");
			close();
		}
	}
	else // write to the division helpDiv
	{
		helpTarget.innerHTML = htxt;

// Cris Necocea says this is not possible:
//		top.document.getElementById('helpDiv').innerHTML = htxt;
	}
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function closeFgij()
{
	if (confirm("Close window, ending this\n" +
		"FirstGlance session?"))
		top.window.close();
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function clearHidden()
{
	hiddenChains.length = 0;
	hiddenGroups.length = 0;
	hiddenAtoms.length = 0;
	hideProtein = hideDNA = hideRNA = hideCarbohydrate = hideHydrogen = false;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function unHideAll()
{
	clearHidden();
	reDisplay(makeEchoSpt("Nothing Remains Hidden"), "");
	showHelp2("makeHideHelp()");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function unHideLast()
{
	var es;

	if (hideMode == "c")
	{
		es = "Chain " + hiddenChains[hiddenChains.length - 1] + " Re-Displayed";
		hiddenChains.length = hiddenChains.length - 1;
	}
	else if (hideMode == "g")
	{
		es = "Residue/Group " + hiddenGroups[hiddenGroups.length - 1] + " Re-Displayed";
		hiddenGroups.length = hiddenGroups.length - 1;
	}
	else if (hideMode == "a")
	{
		es = hiddenAtoms[hiddenAtoms.length - 1];
		es = es.substring(es.indexOf(" ")); // trim off leading serial number
		es += " Re-Displayed";
		hiddenAtoms.length = hiddenAtoms.length - 1;
	}
	else alert("Programmer's error: unhideLast() with hideMode blank");

	reDisplay("", makeEchoSpt(es)); // put echo last so not overwritten
	showHelp2("makeHideHelp()");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function reDisplay(echoSpt, trailingSpt)
{
	var rds = echoSpt;

	rds += eval(currentView);

	// don't obey water/ligand buttons when contactsShowing

	if (!contactsShowing)
	{
		if (toggleIsDown[ligandIndex])
		{
			
			// toggleDownSpt[ligandIndex]; colors cpk unconditionally
			rds += ligandClearSpt + "spacefill;\n"; 
			if (match(currentView, "precontacts"))
				rds += "color [x" + colorLigand + "];\n";
		}
		else
			rds += ligandClearSpt; // clears		
		if (toggleIsDown[waterIndex])
			rds += "select water; spacefill;\n"; // don't change color
		else
			rds += "restrict not water;\n";
	}

	rds += trailingSpt; // e.g. center, echo

	doMolViewSpt(rds); // in reDisplay()
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function centerVisible()
{
	reDisplay(makeEchoSpt("Visible Chains Centered"),
		"select (" + proteinSpt + ", nucleic) and not ~hidden_jdef; center selected;");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function centerContacting()
{
	var ccs = "center ~cont_current;\n";

	ccs += makeEchoSpt("Visible Contacting Atoms Centered");

	doMolViewSpt(ccs);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeSelectHiddenSpt()
{
	var hs = "# makeSelectHiddenSpt();\n" +
		"select none;\n";

	var ih;
	if (hiddenChains.length > 0)
	{
		// Changing from 'restrict not' to 'select selected or' to enable
		// centerVisible();

		if (hiddenChains[0].length > 1)
		{
			if (hiddenChains[0] == "Protein")
				hs += "select selected or ((" + proteinSpt + ") and not hetero);\n";
			else
				hs += "select selected or (nucleic and not hetero);\n";
		}
		else
		{
			hs += "select selected or ((";
			for (ih = 0; ih < hiddenChains.length; ih++)
			{
				if (ih > 0)
					hs += ",";
				hs += ":" + hiddenChains[ih];
			}
			hs += ") and not hetero);\n";
		}
	}
	if (hiddenGroups.length > 0)
	{
		// This is to workaround a bug in Jmol 10.00.48.
		// Should be fixed in a future Jmol release.
		hs += "set bondmode or;\n";

		hs += "select selected or (";
		for (ih = 0; ih < hiddenGroups.length; ih++)
		{
			if (ih > 0)
				hs += ",";
			hs += hiddenGroups[ih];
		}
		hs += ");\n";
	}
	if (hiddenAtoms.length > 0)
	{
		// This is to workaround a bug in Jmol 10.00.48.
		// Should be fixed in a future Jmol release.
		hs += "set bondmode or;\n";

		for (ih = 0; ih < hiddenAtoms.length; ih++)
		{
			hs += "select selected or (atomno=";
			hs += firstWord(hiddenAtoms[ih]);
			hs += ");\n";
		}
	}

	if (hideProtein)
		hs += "select selected or " + proteinSpt + ";\n";
	if (hideDNA)
		hs += "select selected or DNA;\n";
	if (hideRNA)
		hs += "select selected or RNA;\n";
	if (hideCarbohydrate)
		hs += "select selected or " + carbohydrateSpt + ";\n";
	if (hideHydrogen)
		hs += "select selected or hydrogen;\n";

	hs += "define ~hidden_jdef selected;\n";

	return hs;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeHideSpt()
{
	var hs = makeSelectHiddenSpt();

	if (hs.length > 0)
		hs = "# makeHideSpt();\n" + 
			hs + "restrict not selected;\n"; // makeHideSpt()
	return hs;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function showContacts()
{
	if ((selectedChains.length + selectedGroups.length + selectedAtoms.length
		+ selectedFound.length + selectedRanges.length == 0) &&
		!selectedWater)
		{
			alert("Before Contacts can be shown, you must first\n" +
				"select a target by clicking on the molecule,\n" +
				"or checking \"Atoms with Halos\".");
			return;
		}

	selectMode = "";

	// flags that affect other views are also set in doViewLink(), namely
	// contactsShowing and markContactsTargets (maybe redundant here)?
	contactsShowing = true;
	markContactsTargets = true;

	// flags that affect only contacts are set here

	targetSF = contactingSF = true;
	targetCPK = contactingCPK = false;

	backboneContacts = true;
	hydrogensContacts = false;
	labelContacts = false;

	doMolViewSpt(makeGenerateContactsSpt());
	currentView = "makeContactsViewSpt(false, false)";

	showHelp("makeContactsShownHelp()");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function toggleAxes()
{
	if (document.setForm.axes.checked)
	{
		scriptToJmol("set axes on;\n");
		axesOn = true;
	}
	else
	{
		scriptToJmol("set axes off;\n");
		axesOn = false;
	}
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function toggleBoundbox()
{
	if (document.setForm.boundbox.checked)
	{
		scriptToJmol("set boundbox on;\n");
		boundboxOn = true;
	}
	else
	{
		scriptToJmol("set boundbox off;\n");
		boundboxOn = false;
	}
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function toggleUnitcell()
{
	var ducs = "";
	if (document.setForm.unitcell.checked)
	{
		ducs += "set unitcell on;\n";
		ducs += "set echo top left; echo;\n";
		unitcellOn = true;
	}
	else
	{
		ducs += "set unitcell off;\n";
		unitcellOn = false; // must be before makeEchoPdbIdSpt()!
		ducs += makeEchoPdbIdSpt("");
	}

//	alert(ducs);
	scriptToJmol(ducs); // in toggleUnitcell()
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function getHiddenTot()
{
	var hiddenTot =
		hiddenChains.length +
		hiddenGroups.length +
		hiddenAtoms.length;

	if (hideProtein) hiddenTot++;
	if (hideDNA) hiddenTot++;
	if (hideRNA) hiddenTot++;
	if (hideCarbohydrate) hiddenTot++;
	if (hideHydrogen) hiddenTot++;

	return hiddenTot;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function changeContactsBackbones()
{
	var bb = top.document.contactsForm.contactsBackbones.checked;
	if (bb)
		doMolViewSpt(showContactsBackbonesSpt);
	else
		doMolViewSpt(hideContactsBackbonesSpt);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function changeContactsTargetsMarks()
{
	var conhal = top.document.contactsForm.markContactsTargets.checked;
	if (conhal)
		markContactsTargets = true;
	else
		markContactsTargets = false;
	doMolViewSpt("");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function hideMonitors()
{
	doMolViewSpt("monitors off;");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function changeSlabThickness()
{
	var thk = getRadioValue(top.document.slabForm.slabThickness);	
	slabThickness = thk;

	doMolViewSpt(makeSlabSpt(false));

}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function match(name, subname)
{
	if (name.toLowerCase().indexOf(subname.toLowerCase()) == -1)
		return false;
	return true;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function doFind()
{
	var find = document.findForm.toFind.value;
//	var quoted = false;
//	if (find.charAt(0) == "\"")
//		quoted = true;

	// STRIP OUT QUOTE MARKS & CHANGE CASE TO UPPER
	find = find.toUpperCase().replace(/\"/g, "");

	// SINGULARIZE SPACES
	while (find.indexOf("\ \ ") != -1)
		find = find.replace(/\ \ /g, " ");

//	if (!quoted)
//	{
//		// GUARANTEE COMMA BEFORE EVERY SPACE
//		var is;
//		for (is = 0; is < find.length; is++)
//			if (find.charAt(is) == " " && is > 0)
//				if (find.charAt(is - 1) != ",")
//					find = find.substring(0, is) + "," + find.substring(is);
//	}

	// BUG in Jmol 48: u works but U is not recog. and kills selection
	// EMBEDDED
	find = find.replace(/\ U,/g, "\ u,");
	find = find.replace(/,U,/g, ",u,");
	// BEGINNING
	find = find.replace(/^U,/g, "u,");
	// END
	find = find.replace(/\ U$/g, "\ u");
	find = find.replace(/,U$/g, ",u");

	// REWRITE QUERY WITHOUT QUOTES INTO SLOT
	document.findForm.toFind.value = find;

	// find it
	toFind = find;

	// makeFindSpt() sets background black if (forceBackgroundBlack):
	// Each doFind() forces the background to black.
	// But after the halos are rendered, subsequent refreshes don't force
	// the background, so user has control.
	setButtonState("up", backgroundIndex);
	forceBackgroundBlack = true;

	doMolViewSpt(""); // makeFindSpt() is called automatically when toFind
	// is not blank.


	// redisplay help
	showHelp2("makeFindHelp()");
	setTimeout("document.findForm.toFind.select()", 100);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function setButtonState(state, istate)
{
//	alert("jcontrol.js #9 setButtonState(" + state + ", " + istate + ")");
	var imgnum = eval("document.toggle" + istate);

	if (state == "up")
	{
		toggleIsDown[istate] = false;
		imgnum.src = "up.gif";		
	}
	else
	{
		toggleIsDown[istate] = true;
		imgnum.src = "down.gif";		
	}
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function changeContactsView()
{
	// this change is initiated from the form, so
	// true1 = read radio buttons
	// true 2 = read checkboxes
	doMolViewSpt(makeContactsViewSpt(true, true));
	showHelp2("makeContactsShownHelp()");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// setContactsView(vw) sets one of four preset views from snapshots
// in the contacts shown help.

function setContactsView(vw)
{
	var tailSpt = makeEchoPdbIdSpt("");
	if (vw == 1)
	{
		targetSF = true;
		contactingSF = true;
		targetCPK = false;
		contactingCPK = false;		
	}
	else if (vw == 2)
	{
		targetSF = true;
		contactingSF = false;
		targetCPK = false;
		contactingCPK = false;		
	}
	else if (vw == 3)
	{
		targetSF = true;
		contactingSF = false;
		targetCPK = true;
		contactingCPK = true;
	}
	else if (vw == 4)
	{
		targetSF = false;
		contactingSF = false;
		targetCPK = true;
		contactingCPK = true;
		tailSpt = makeEchoMsgSpt('Double click each atom to measure a distance.',
			'top', '20', '[xff4040]');
	}

	// preset views force radio buttons, so
	// false = don't read radio buttons
	// true = read checkboxes
	doMolViewSpt(makeContactsViewSpt(false, true) + tailSpt);
	showHelp2("makeContactsShownHelp()");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function toggleContactsRadioButtons()
{
	var showrad = top.document.contactsForm.contactsRadioButtons.checked;	
	if (showrad)
		contactsRadioViews = true;
	else
		contactsRadioViews = false;
	showHelp2("makeContactsShownHelp()");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function clearFindForm()
{
	document.findForm.toFind.value = "";
	doFind();
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function changePreContactsView()
{
	// SPACEFILL OR CARTOON
	preContactsView = getRadioValue(document.contactsForm.pCView);

	var fc = document.contactsForm.selectFound.checked;

	// SELECT FOUND?
	if (fc && toFind.length == 0)
	{
		alert("First, please use Find.. (above)\n" +
			"to apply halos to some atoms.");
		document.contactsForm.selectFound.checked = false;
		return;
	}

	if (fc)
		selectedFound = toFind;
	else
		selectedFound = "";

	// REGENERATE ~targ_current (selectedFound does not use pickCallback)
	// with makeSelectSpt()

	// REGENERATE VIEW
	doMolViewSpt(makeSelectSpt() + makePreContactsSpt());
	showHelp2("makePreContactsHelp()");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function cancelCenteringNoHelp()
{
	if (centerMode)
	{
		centerMode = false;
		doMolViewSpt("set picking on;\n"); // cancels set picking center
	}
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function changePreContactsWater(tailSpt)
{
	var pcw = top.document.contactsForm.preContactsWater.checked;
	preContactsWater = pcw;
	var pcws = "";

	if (pcw)
	{
		pcws = "select water and not hydrogen; color [x" + colorSolvent + "]; spacefill;\n";
		setButtonState("down", waterIndex);
	}
	else
	{
		pcws = "select water; spacefill off;\n";
		setButtonState("up", waterIndex);
	}

	doMolViewSpt(pcws + tailSpt);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function cancelRange()
{
	selectedRangeStart = "";
	doMolViewSpt(makeSelectSpt()); // to reset ~targ_current
	showHelp2("makePreContactsHelp()");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function isStdAA(aaq)
{
	aaq = "" + aaq.toUpperCase();
//	alert("jcontrol.js #10: isStdAA receives " + aaq);

	switch (aaq)
	{
		case ("ALA"):
		case ("ARG"):
		case ("ASN"):
		case ("ASP"):
		case ("CYS"):
		case ("GLN"):
		case ("GLU"):
		case ("GLY"):
		case ("HIS"):
		case ("ILE"):
		case ("LYS"):
		case ("LEU"):
		case ("MET"):
		case ("PHE"):
		case ("PRO"):
		case ("SER"):
		case ("THR"):
		case ("TRP"):
		case ("TYR"):
		case ("VAL"):
			return true;
		default:
			return false;
	}	
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function isStdNucleotide(nq)
{
	nq = "" + nq.toUpperCase();
//	alert("jcontrol.js #11: isStdNucleotide receives " + nq);

	switch (nq)
	{
		case ("A"):
		case ("C"):
		case ("G"):
		case ("T"):
		case ("U"):
			return true;
		default:
			return false;
	}	
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function changePreContactsWaterTarget()
{
	selectedWater = document.contactsForm.preContactsWaterTarget.checked;

	if (selectedWater)
		top.document.contactsForm.preContactsWater.checked = true;

	changePreContactsWater(makeSelectSpt());
	showHelp2("makePreContactsHelp()");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function doCatPiSB()
{
	clearSelectedArrays();
	selectedFound = "LYS, ARG";
	var css = makeSelectHiddenSpt() + // to define ~hidden_jdef in Jmol
		makeDefineContactsSpt();
	clearSelectedArrays();

	contactsShowing = false;

	currentView = "makeCatPiSBSpt(false)";

	showHelp2("makeCatPiSBHelp()");
	showCatPiSB(css);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function showCatPiSB(preSpt)
{
	setButtonState("down", backgroundIndex);
	setButtonState("up", ligandIndex);
	setButtonState("up", waterIndex);

	doMolViewSpt(preSpt + makeCatPiSBSpt(true));
	showHelp("makeCatPiSBHelp()");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function clearBoxes()
{
	var spt = "";
	if (axesOn)
	{
		axesOn = false;
		spt += "set axes off;\n";
	}
	if (unitcellOn)
	{
		unitcellOn = false;
		spt += "set unitcell off;\n";
	}
	if (boundboxOn)
	{
		boundboxOn = false;
		spt += "set boundbox off;\n";
	}
	return spt;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function doReset()
{
	toFind = ""; // must be before help!
	clearHidden();
	showCatPi = false;
	colorCatPiSBChain = false;
	resetContacts();
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function doAnomalousAtoms()
{
	showAnomalous = document.anomalousForm.showAA.checked;
	var rendAA = getRadioValue(document.anomalousForm.renderAA);
	anomalousDots = (rendAA == "d");

//	doMolViewSpt("");
	reDisplay("", "");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function resetContacts()
{
	markContactsTargets = true;
	targetSF = true;
	preContactsView = "sf"; // must be done before showing help
	preContactsWater = false;
	selectedWater = false;
	labelContacts = false;

	showContactsHBonds = true;
	showContactsMeMi   = true;
	showContactsHphob  = true;
	showContactsSB     = true;
	showContactsCatPi  = true;
	showContactsSticks = true;
	showContactsWater  = true;
	showWaterBridges   = true;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

