// functions.js
// this file contains most of the javascript functions needed to run UniView
// all of the language specific text is in functions-text.js



// note: several global variables are set in prefs.js
var _notesArray = new Array;
var _newNotesArray = false;
var _currentFont = _defaultFont;
if (document.all) { var IE = 'true'; }
var _tempList = false; // true if results of search or c&p displayed (for font change)
var _IE = false;


function getCharFromInt ( n ) {
	// converts a decimal integer into a Unicode character
	// n: integer, the decimal Unicode codepoint to be converted
	// output: a character
    if (n <= 0xFFFF) {
		outputString = String.fromCharCode(n);
		} 
	else if (n <= 0x10FFFF) {
		n -= 0x10000
		outputString = String.fromCharCode(0xD800 | (n >> 10)) + String.fromCharCode(0xDC00 | (n & 0x3FF));
		} 
	else {
		outputString = '!error ' + dec2hex(n) +'!';
		}
	return( outputString );
	}



function showChar () {
	printProperties( this.title );
	}

function setOnclick ( codepoint, node ) {
	//sets the event functions for node, used by createMatrix, createList, etc.
	node.onclick = function(){ printProperties(codepoint) };
	node.onclick = function () { addtocharSelect(codepoint) };

	}
	
function addtocharSelect ( codepoint ) {
	// adds a character to the cut & paste field
	// codepoint: integer, the decimal Unicode codepoint to be added
	var field = document.getElementById( 'charSelect' );
	field.value = field.value + getCharFromInt(codepoint);
//	field.value = getCharFromInt(codepoint);
	document.uni.chars.value=document.getElementById('charSelect').value;
	setUnicodeText();
	setCounter();
	}

function findScriptGroup ( charNum ) {
	// output: returns the name of the script group in which charNum falls
	// charNum: a decimal number representing the code point of the character in question
	var i=0;
	while ( i<scriptGroups.length && charNum > scriptGroups[i][0] ) {
		i++;
		}
	if ( i == scriptGroups.length ) { return( sNotAChar ); }
	if ( scriptGroups[i-1][1] >= charNum ) { return( scriptGroups[i-1][2]); }
	if ( scriptGroups[i][0] == charNum ) { return( scriptGroups[i][2]); }
	return( sNotAChar );
	}	


function createMatrix ( formField ) {
	// output: a grid format list of characters in the left panel
	// formField: a string of the form 'XXXX:YYYY' indicating a range of characters in hex notation
	var table, tbody, tr, td, img;
	_tempList = false;

	var listDiv = document.getElementById( 'listOutput' );
	var oldtable = document.getElementById('chart');

	table = document.createElement( 'table' );
		table.className = 'chartChar';
		table.id = 'chart';
		table.setAttribute( 'border', '1' );
	tbody = table.appendChild( document.createElement( 'tbody' ));

	// work out what the range is
	var cCell = 0;
	var HexURange = formField.split(':');
	var start = parseInt( HexURange[0], 16 );
	var end = parseInt( HexURange[1], 16 );
	var cols = Math.ceil((end-start+1)/16);
	var character = '';
	var totalCodes = cols*16;
	var notFound = true;

	for (i=-1; i<16; i++) {
		tr = tbody.appendChild( document.createElement( 'tr' ));
		
		// Create number column
		td = tr.appendChild( document.createElement( 'td' ));
			td.className = 'hexNum';
//			td.setAttribute( 'noChar', 'y' );
		if (_showNumbers && i>-1) {
			td.appendChild( document.createTextNode( i.toString(16).toUpperCase() ));
			}
		else { td.appendChild( document.createTextNode( '\u00A0' )); }
		
		for (j=0; j<cols; j++) {
			cCell = start+i+(j*16);
			
			// If first row, add numbers or blanks
			if (i == -1) { 
				td = tr.appendChild( document.createElement( 'td' ));
				td.className = 'hexNum';
//				td.setAttribute( 'noChar', 'y' );
				if (_showNumbers) {
					var numStr = (cCell+1).toString(16).toUpperCase();
					td.appendChild( document.createTextNode( numStr.slice(0,numStr.length-1) ));
					}
				else { td.appendChild( document.createTextNode( '\u00A0' )); }
				}
				
			//Otherwise, add character info
			else {
				hexNum = cCell.toString(16).toUpperCase();
				td = tr.appendChild( document.createElement( 'td' ));
					td.title = cCell;
					td.style.fontFamily = _currentFont;
					setOnclick( cCell, td );
					td.className = 'ch';
				if (!U[cCell]) { 
					td.style.backgroundColor = unassignedChar; 
					td.className = 'empty'; 
					}
				if (U[cCell]) {
					if (_utf8) {
						td.appendChild( document.createTextNode( getCharFromInt(cCell) )); 
						}
					else { 
						for (k=hexNum.length; k<4; k++) { hexNum = '0' + hexNum; } 
						img = td.appendChild( document.createElement( 'img' ));
							scriptGroup = findScriptGroup(cCell);
							if (localGraphics.indexOf(scriptGroup+',') > -1) {
								img.src = 'graphics/'+scriptGroup+'/'+hexNum+'.png'; }
							else { img.src = 'http://decodeunicode.org/data/glyph/26x26/'+hexNum+'.gif'; }
						}
					}
				}
			}
		}
	var removedNode = listDiv.replaceChild( table, oldtable );
	if (document.getElementById('generalCat').value != 'startup') {
		highlightList( 2, document.getElementById('generalCat').value );
		}
	if (document.getElementById('directionality').value != 'startup') {
		highlightList( 4, document.getElementById('directionality').value );
		}
	document.getElementById('fontSize').value = '100%';
	}


function createList (formField) {
	// output: a list of characters for a range given by formField displayed in the left panel
	// formField: a string of the form 'XXXX:YYYY' indicating a range of characters in hex notation
	
	_tempList = false;
	var HexURange = formField.split(':');
	var start = parseInt( HexURange[0], 16 );
	var end = parseInt( HexURange[1], 16 );
	var rangeLength = end - start;
	
	var listDiv = document.getElementById( 'listOutput' );
	var oldContent = document.getElementById('chart');

	var newContent = document.createElement( 'div' );
		newContent.className = 'charList';
		newContent.id = 'chart';
	
	for (i=start; i<=end; i++) {
		if (U[i]) {
			addLine( i, newContent );
			}	
		}
	var removedNode = listDiv.replaceChild( newContent, oldContent );
	if (document.getElementById('generalCat').value != 'startup') {
		highlightList( 2, document.getElementById('generalCat').value );
		}
	if (document.getElementById('directionality').value != 'startup') {
		highlightList( 4, document.getElementById('directionality').value );
		}
	document.getElementById('fontSize').value = '100%';
	}


function parseString ( string ) {
	// output: a list of the characters contained in string 
	// string: a string of characters
	// ***docObj: the window in which the results will be output
	_tempList = true;
	var codepoint = 0;

	if ( string.length == 1 ) { printProperties(string.charCodeAt(0)); }
	else {
		var listDiv = document.getElementById( 'listOutput' );
		var oldContent = document.getElementById('chart');

		var newContent = document.createElement( 'div' );
			newContent.className = 'charList';
			newContent.id = 'chart';

		for (i=0; i<string.length; i++) {
			codepoint = string.charCodeAt( i ); // alert( codepoint + ' ' + string.charCodeAt( i+1 ) );
			if (0xD800 <= codepoint && codepoint <= 0xDBFF && i<string.length-1) {
				codepoint = 0x10000 + ((codepoint - 0xD800) << 10) + (string.charCodeAt( i+1 ) - 0xDC00);
				i++; //alert( codepoint ); 
				}
				
			if ( U[codepoint] ) {
				addLine( codepoint, newContent );		
				}
			else { 	
				var div = newContent.appendChild( document.createElement( 'div' ));
				div.appendChild( document.createTextNode( codepoint.toString(16).toUpperCase() + sColon
					+ getCharFromInt(codepoint) + sNoName + findScriptGroup( codepoint )));
				}
			}
		var removedNode = listDiv.replaceChild( newContent, oldContent );
		if (document.getElementById('generalCat').value != 'startup') {
			highlightList( 2, document.getElementById('generalCat').value );
			}
		if (document.getElementById('directionality').value != 'startup') {
			highlightList( 4, document.getElementById('directionality').value );
			}
		document.getElementById('fontSize').value = '100%';
		}
	}




function addLine (codepoint, newContent) {
	cRecord = U[codepoint].split(';');
	var div = newContent.appendChild( document.createElement( 'div' ));
//		div.onclick = function(){ printProperties(codepoint) };
		setOnclick( codepoint, div );
		div.title = codepoint;
		div.className = 'ch';
	div.appendChild( document.createTextNode( cRecord[0] + sColon ));
	if (_utf8) {
		var span = div.appendChild( document.createElement( 'span' ));
			span.className = 'chSpan';
			span.style.fontFamily = _currentFont;
		span.appendChild( document.createTextNode( getCharFromInt(parseInt(cRecord[0],16)) ));
		}
	else { 
		var img = div.appendChild( document.createElement( 'img' ));
		scriptGroup = findScriptGroup(codepoint);
		if (localGraphics.indexOf(scriptGroup+',') > -1) {
			img.src = 'graphics/'+scriptGroup+'/'+cRecord[0]+'.png'; }
		else { img.src = 'http://decodeunicode.org/data/glyph/26x26/'+cRecord[0]+'.gif'; }
		//img.src = 'http://decodeunicode.org/data/glyph/26x26/'+cRecord[0]+'.gif';
		}
	div.appendChild( document.createTextNode( '\u00A0 '+cRecord[1] ));
	}
	

function findString ( searchString ) {
//function findString ( searchString, docObj ) {
	// effect: outputs in the left panel a list of characters whose descriptions in the database match searchString
	// searchString: a string of text to search for in the database
	// ***docObj: the window in which the result will be output
	// U: the Unicode database
	_tempList = true;
	var counter = 0;
	var i = 0;
	searchString = searchString.toUpperCase();

	var listDiv = document.getElementById( 'listOutput' );
	var oldContent = document.getElementById('chart');

	var tempContent = document.createElement( 'div' );
		tempContent.className = 'charList';
		tempContent.id = 'chart';
	tempContent.appendChild( document.createTextNode( sSearching ))
	var removedNode = listDiv.replaceChild( tempContent, oldContent );
	oldContent = document.getElementById('chart');
		
	var newContent = document.createElement( 'div' );
		newContent.className = 'charList';
		newContent.id = 'chart';
	for (i=0; i <13311; i++ ) {
		if ( U[i] && U[i].indexOf(searchString, 0) > -1 ) {
			addLine(i, newContent);
			counter++;
			}
		}
	for (i=40960; i <42183; i++ ) {
		if ( U[i] && U[i].indexOf(searchString, 0) > -1 ) {
			addLine(i, newContent);
			counter++;
			}
		}
	for (i=64256; i <65534; i++ ) {
		if ( U[i] && U[i].indexOf(searchString, 0) > -1 ) {
			addLine(i, newContent);
			counter++;
			}
		}
	for (i=66304; i <66638; i++ ) {
		if ( U[i] && U[i].indexOf(searchString, 0) > -1 ) {
			addLine(i, newContent);
			counter++;
			}
		}
	for (i=118784; i <120832; i++ ) {
		if ( U[i] && U[i].indexOf(searchString, 0) > -1 ) {
			addLine(i, newContent);
			counter++;
			}
		}
	for (i=917505; i <917632; i++ ) {
		if ( U[i] && U[i].indexOf(searchString, 0) > -1 ) {
			addLine(i, newContent);
			counter++;
			}
		}

	if (counter == 0) { newContent.appendChild( document.createTextNode( sNoMatch )); }

	removedNode = listDiv.replaceChild( newContent, oldContent );
	if (document.getElementById('generalCat').value != 'startup') {
		highlightList( 2, document.getElementById('generalCat').value );
		}
	if (document.getElementById('directionality').value != 'startup') {
		highlightList( 4, document.getElementById('directionality').value );
		}
	document.getElementById('fontSize').value = '100%';
	}




function printProperties ( codepoint ) {
//function printProperties ( codepoint, docObj ) {
	// output: a description of a single character in the right panel, plus notes if an appropriate file has been loaded
	// codepoint: an integer representing the Unicode scalar value of the character to be displayed
	// ***docObj: the window to which the results will be output
	
	var MsPadding = '';  // Will be set to a space if this is a non-spacing mark
	var description = false;
	var div, span, img, table, tbody, tr, td;

	var listDiv = document.getElementById( 'charOutput' );
	var oldContent = document.getElementById('charInfo');

	var newContent = document.createElement( 'div' );
			newContent.className = 'charInfo';
			newContent.setAttribute( 'id', 'charInfo' );

//		resultString += 'onDblClick="' + 'parent.keyboard.displayHighlight(document.selection.createRange().text)"';


	if (U[codepoint]) { 
		cRecord = U[codepoint].split(';');
		if (cRecord[3] > 0) { MsPadding = '\u00A0'; }  // ie. this is a combining character


		// float the large character to the right
		div = newContent.appendChild( document.createElement( 'div' ));
			if (IE) { div.style.styleFloat = 'right'; } else { div.style.cssFloat = 'right'; }
			div.style.paddingRight = '20px';
			div.style.paddingLeft = '40px';
		if (_utf8) { 
			span = div.appendChild( document.createElement( 'span' ));
				span.setAttribute( 'id', 'largeChar' );
				span.className = 'largeChar' ;
				span.style.fontFamily = _currentFont;
				span.appendChild( document.createTextNode( MsPadding + getCharFromInt(parseInt(cRecord[0],16)) ));
			}
		else {
			img = div.appendChild( document.createElement( 'img' ));
				scriptGroup = findScriptGroup(codepoint);

				if (localGraphics.indexOf(scriptGroup+',') > -1) {
					img.src = 'graphics/'+scriptGroup+'/'+cRecord[0]+'.png'; }
				else { img.src = 'http://decodeunicode.org/data/glyph/196x196/'+cRecord[0]+'.gif'; }
				//img.setAttribute( 'src', 'http://decodeunicode.org/data/glyph/196x196/'+cRecord[0]+'.gif');
			}
		
		
		// set up navigational graphics
		img = newContent.appendChild( document.createElement( 'img' ));
			img.onclick = function () { adjacentChar( codepoint, -1 ) };
			img.src = 'images/undo.gif';
			img.className = 'icon';
			img.alt = sPrevChar;
			img.title = sPrevChar;
		img = newContent.appendChild( document.createElement( 'img' ));
			img.onclick = function () { adjacentChar( codepoint, 1 ) };
			img.src = 'images/go.gif';
			imgclassName = 'icon';
			img.alt = sNextChar;
			img.title = sNextChar;


		// character no. & name
		div = newContent.appendChild( document.createElement( 'div' ));
			div.style.marginTop = '10px';
		div.appendChild( document.createTextNode( cRecord[0]+': \u00A0 '+cRecord[1]+' \u00A0 \u00A0 ' ));
		
		// fill out properties table		
		table = newContent.appendChild( document.createElement( 'table' ));
			table.className = 'propsTable';
			table.width = '90%';
			table.style.clear = 'both';
		tbody = table.appendChild( document.createElement( 'tbody' ));
		tr = tbody.appendChild( document.createElement( 'tr' ));
		td = tr.appendChild( document.createElement( 'td' ));
			td.appendChild( document.createTextNode( sGeneralCat ));
		td = tr.appendChild( document.createElement( 'td' ));
			td.appendChild( document.createTextNode( cRecord[2] + ' - ' + generalProp[ cRecord[2] ] ));

		tr = tbody.appendChild( document.createElement( 'tr' ));
		td = tr.appendChild( document.createElement( 'td' ));
			td.appendChild( document.createTextNode( sCanonCombClass ));
		td = tr.appendChild( document.createElement( 'td' ));
			td.appendChild( document.createTextNode( cRecord[3] + ' - ' + combClass[ cRecord[3] ] ));

		tr = tbody.appendChild( document.createElement( 'tr' ));
		td = tr.appendChild( document.createElement( 'td' ));
			td.appendChild( document.createTextNode( sBidiCat ));
		td = tr.appendChild( document.createElement( 'td' ));
			string = cRecord[4] + ' - ' + bidiProp[ cRecord[4] ];
			if (cRecord[9] == 'Y' ) { string += sMirrored };
			td.appendChild( document.createTextNode( string ));

		if (cRecord[5]) {
			tr = tbody.appendChild( document.createElement( 'tr' ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( sCharDecompMap ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( cRecord[5] ));
			}

		if (cRecord[6]) {
			tr = tbody.appendChild( document.createElement( 'tr' ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( sDecDigitValue ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( cRecord[6] ));
			}

		if (cRecord[7]) {
			tr = tbody.appendChild( document.createElement( 'tr' ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( sDigitValue ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( cRecord[7] ));
			}

		if (cRecord[8]) {
			tr = tbody.appendChild( document.createElement( 'tr' ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( sNumValue ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( cRecord[8] ));
			}

		if (cRecord[10]) {
			tr = tbody.appendChild( document.createElement( 'tr' ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( sUnicode1Name ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( cRecord[10] ));
			}

		if (cRecord[11]) {
			tr = tbody.appendChild( document.createElement( 'tr' ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( s10646Comment ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( cRecord[11] ));
			}

		if (cRecord[12]) {
			tr = tbody.appendChild( document.createElement( 'tr' ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( sUppercaseMap ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( cRecord[12] ));
			}

		if (cRecord[13]) {
			tr = tbody.appendChild( document.createElement( 'tr' ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( sLowercaseMap ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( cRecord[13] ));
			}

		if (cRecord[14]) {
			tr = tbody.appendChild( document.createElement( 'tr' ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( sTitlecaseMap ));
			td = tr.appendChild( document.createElement( 'td' ));
				td.appendChild( document.createTextNode( cRecord[14] ));
			}
		
		//find script group
		p = newContent.appendChild( document.createElement( 'p' ));
			p.style.marginTop = "18px";
		strong = p.appendChild( document.createElement( 'strong' ));
		strong.appendChild( document.createTextNode( sScriptGroup ));
		p.appendChild( document.createTextNode( findScriptGroup( codepoint )));
		

		// find the descriptions
		var hexLength = cRecord[0].length;
		for (i=0; i < descriptions.length-1; i++ ) {
			if ( descriptions[i].slice(0, hexLength) == cRecord[0] ) { 
				dRecord = descriptions[i].split('¶');
				p = newContent.appendChild( document.createElement( 'p' ));
					p.style.marginTop = "18px";
				strong = p.appendChild( document.createElement( 'strong' ));
				strong.appendChild( document.createTextNode( sDescription ));
				p.appendChild( document.createElement( 'br' ));
				description = true;
				for (var j=1; j < dRecord.length; j++ ) {
					p.appendChild( document.createTextNode( dRecord[j] ));
					p.appendChild( document.createElement( 'br' ));
					}
				break;
				}
			}
		
		// add notes from iframe
//		alert( _newNotesArray );
//		if ( _newNotesArray ) {
//			var iframe = document.getElementById( 'iframe' );
//			if (iframe.contentDocument) { //alert('using DOM');
//				_notesArray = iframe.contentDocument.getElementsByTagName('div');
//				alert( sNotesReadIn + _notesArray.length + sDivs );
//				}
//			else if ( iframe.Document ) { //alert( 'must be IE' ); 
//				_IE = true;  // this is a hack until such time as I can figure out how to make IE work
//				_notesArray = iframe.Document.getElementsByTagName('div');
//				alert( sNotesReadIn + _notesArray.length + sDivs );
//				}
//			_newNotesArray = false;
//			}
//		if (_notesArray.length == 0){alert('no notes array');} else {alert('notes array exists');}
			

//		var codeID = 'C' + cRecord[0];
//		_notesArray = document.getElementById( codeID );
//		var iframe = document.getElementById('iframe');
//		nodeArray = iframe.contentDocument.getElementsByTagName('div');	
//		alert( _notesArray.length + ' ' + codeID );
//		if (_notesArray) {
//			for (i=0; i < _notesArray.length-1; i++ ) {
//				alert(_notesArray[i].getAttribute('id'));
//				if (_notesArray[i].id == codeID) {
//					alert( 'found it' );
//					var notesNode = _notesArray[i].cloneNode(true);
//					hr = newContent.appendChild( document.createElement( 'hr' ) );
//						hr.noShade = true; hr.style.color = '#009966';
//					alert( 'after' );
//					if ( ! _IE ) { // this is a hack until such time as I can figure out how to make IE work
//					newContent.appendChild( notesNode );
//						}
//				newContent.appendChild( _notesArray[i] );
//				newContent.appendChild( test );
//				alert( 'leaving' );
//					break;
//					}
//				}
//			}
		var codeID = 'C' + cRecord[0];
		notesNode = document.getElementById( codeID );
//		alert( codeID );
		if (notesNode) {
			var clonedNode = notesNode.cloneNode(true);
			hr = newContent.appendChild( document.createElement( 'hr' ) );
			hr.noShade = true; 
			hr.style.color = '#009966';
			newContent.appendChild( clonedNode );
			}
	
		// add any notes
		}
	else { // this is either not a recognized character or a Han or Hangul character
		var group = findScriptGroup(codepoint);
		if (group != sNotAChar){
			// float the large character to the right
			div = newContent.appendChild( document.createElement( 'div' ));
				if (IE) { div.style.styleFloat = 'right'; } else { div.style.cssFloat = 'right'; }
				div.style.paddingRight = '20px';
				div.style.paddingLeft = '40px';
			if (_utf8) { 
				span = div.appendChild( document.createElement( 'span' ));
					span.id = 'largeChar';
					span.className = 'largeChar' ;
					span.style.fontFamily = _currentFont;
					span.appendChild( document.createTextNode( MsPadding + getCharFromInt(codepoint) ));
				}
			else {
				img = div.appendChild( document.createElement( 'img' ));
					scriptGroup = findScriptGroup(codepoint);
					if (localGraphics.indexOf(scriptGroup+',') > -1) {
						img.src = 'graphics/'+scriptGroup+'/'+cRecord[0]+'.png'; }
					else { img.src = 'http://decodeunicode.org/data/glyph/196x196/'+cRecord[0]+'.gif'; }
					//img.setAttribute( 'src', 'http://decodeunicode.org/data/glyph/196x196/'+cRecord[0]+'.gif');
				}
			}
		
		// character no. & name
		div = newContent.appendChild( document.createElement( 'div' ));
			div.style.marginTop = '10px';
		div.appendChild( document.createTextNode( codepoint.toString(16).toUpperCase() +
				sNoDescAvail ));
		
		//display script group
		p = newContent.appendChild( document.createElement( 'p' ));
			p.style.marginTop = "18px";
		strong = p.appendChild( document.createElement( 'strong' ));
		strong.appendChild( document.createTextNode( sScriptGroup ));
		p.appendChild( document.createTextNode( group ));
		}
	var removedNode = listDiv.replaceChild( newContent, oldContent );
	}	
		//???	




function highlightList ( field, searchString ) {
	// output: highlighting in the left panel of all characters that fall into the category selected
	// field: string, the field in the record to search for a match
	// searchString: string, the specific setting to search for in the field
	var nodeArray = new Array;
	
	var leftpanel = document.getElementById('chart');

	if ( _displayStyle == 'list' ) { nodeArray = leftpanel.getElementsByTagName("div") }
	else { nodeArray = leftpanel.getElementsByTagName("td") } 

	// clear out any existing highlighting
	for (var i=0; i < nodeArray.length; i++) { 
//		if (U[nodeArray[i].title]) { nodeArray[i].style.backgroundColor = 'white'; }
//		else if (! nodeArray[i].noChar) { nodeArray[i].style.backgroundColor = unassignedFiltered; }
		if (nodeArray[i].className == 'ch' ) { 
			nodeArray[i].style.backgroundColor = 'white'; 
			}
		else if (nodeArray[i].className == 'empty') { 
			nodeArray[i].style.backgroundColor = unassignedFiltered; }
	    }
	    	
	// if you set searchstring to 'none' to clear highlighting, quit now
	if (searchString == 'none') { 
		if (_displayStyle == 'matrix') {
			for (var i=0; i < nodeArray.length; i++) {
//				if (!U[nodeArray[i].title] && nodeArray[i].className == 'empty' ) {
				if ( nodeArray[i].className == 'empty' ) {
					nodeArray[i].style.backgroundColor = unassignedChar;
					}
				}
		    }  
		return; 
		}  

	// check whether this is a general or specific category
	if (searchString.charAt(0) == 'x') {
		searchString = searchString.charAt(1);
		for (var i=0; i < nodeArray.length; i++) {
//			if (U[nodeArray[i].title]) {
			if (nodeArray[i].className == 'ch') {
				cRecord = U[ nodeArray[i].title ].split( ';' );
				if ( cRecord[field].charAt(0) == searchString ) {
					nodeArray[i].style.backgroundColor = filterHighlight;
					}
				}
		    }  
		}
	else {	for (var i=0; i < nodeArray.length; i++) {
			if (nodeArray[i].className == 'ch') {
				cRecord = U[ nodeArray[i].title ].split( ';' );
				if ( cRecord[field] == searchString ) {
					nodeArray[i].style.backgroundColor = filterHighlight;
					}
				}
	    	}
		}
	}
 	

function adjacentChar (codepoint, direction) {
	// output: shows the next or previous character in the database in the right panel
	// codepoint: integer, the decimal Unicode scalar value of the character currently displayed
	// direction: integer, either 1 or -1
	
	while (codepoint != 0 && codepoint != U.length) {
		codepoint += direction;
		if (U[codepoint]) { break; }
		}
	printProperties(codepoint);
	}




// ACTION ROUTINES


function showCodepoint (codepoint) {
	printProperties(parseInt( codepoint, 16 ));
	}
	
function showUnihan (codepoint) {
	unihan = window.open('http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint='+codepoint+'&useutf8=true', 'unihan');
	unihan.focus();
	}

function showConverter (codepoints, origin) {
	converter = window.open('conversion.php?codepoints='+codepoints+'&origin='+origin, 'converter');
	converter.focus();
	}

function showRange() {
	if (document.getElementById('customRange1').value) {
		createMatrix(document.getElementById('customRange1').value + ':' + document.getElementById('customRange2').value);
		}
//	alert( document.getElementById('URangeSelector').value );
	document.getElementById('URangeSelector').value = 'Custom';
	//this doesn't work yet - fix it
	}	
					
function showSelection(range) {
	if (_displayStyle == 'matrix') { createMatrix(range); }
	else { createList(range); }
	rangeArray = range.split(':')
	document.getElementById('customRange1').value = rangeArray[0];
	document.getElementById('customRange2').value = rangeArray[1]; 
	}

function toggleDisplay (graphic) {
	if (_displayStyle == 'matrix') {
		_displayStyle = 'list';
		graphic.src = 'images/grid.gif';
		}
	else {
		_displayStyle = 'matrix';
		graphic.src = 'images/list.gif';
		}
	refreshRange();
	}
		
function toggleGraphic (graphic) {
	if (_utf8) {
		_utf8 = false;
		graphic.src = 'images/utf-8.gif';
		}
	else { 
		_utf8 = true;
		graphic.src = 'images/graphic.gif';
		}
	refreshRange();
	}
	
function toggleNumbers (graphic) {
	if (_showNumbers) {
		_showNumbers = false;
		graphic.src = 'images/num-on.gif';
		}
	else { 
		_showNumbers = true;
		graphic.src = 'images/num-off.gif';
		}
	refreshRange();
	}
	
function refreshRange () {
	if (document.getElementById('customRange1').value != '') {
		showSelection( document.getElementById('customRange1').value+':'
		+document.getElementById('customRange2').value );
		}
	}
	
function changeFontSize (size) {
	var leftpanel = document.getElementById('chart');
	
	if ( _displayStyle == 'matrix' ) {
		nodeArray = leftpanel.getElementsByTagName("td");
		for (var i=0; i < nodeArray.length; i++) { 
			if (nodeArray[i].className != 'hexNum') {
				nodeArray[i].style.fontSize = size;
				}
	    	}
	   }
		
	else { nodeArray = leftpanel.getElementsByTagName('span') 
		for (var i=0; i < nodeArray.length; i++) { 
			if (nodeArray[i].className == 'ch') {
				nodeArray[i].style.fontSize = size; 
				}
	    	}
		}  
	}
	
function changeFont (fontName) {
	// changes the font used for character display
	// fontName: string, the name of the font to apply
	// _defaultFont: string, set in prefs.js
	// _currentFont: string, allows changes to persist
	
	//deal with accidents or resets
	if (fontName == sApplyFont || fontName == '') {
		document.getElementById('chFont').value = sApplyFont;
		_currentFont = _defaultFont;
		}
	else { _currentFont = fontName; }
		
	// make the changes
	var leftpanel = document.getElementById('chart');
	
	if ( _displayStyle == 'matrix' ) {
		nodeArray = leftpanel.getElementsByTagName("td");
		for (var i=0; i < nodeArray.length; i++) { 
			if (nodeArray[i].className != 'hexNum') {
				nodeArray[i].style.fontFamily = _currentFont;
				}
	    	}
	   }
		
	else { nodeArray = leftpanel.getElementsByTagName('span') 
		for (var i=0; i < nodeArray.length; i++) { 
			if (nodeArray[i].className == 'chSpan') {
				nodeArray[i].style.fontFamily = _currentFont; 
				}
	    	}
		} 
		
	if ( document.getElementById('largeChar')) {
		document.getElementById('largeChar').style.fontFamily = _currentFont;
		}
 	}

	
function setupNotesSelector () {	
	var selector = document.getElementById( 'notesSelector' );
	for (i=0; i<charNotesFiles.length-1; i++) {
		cRecord = charNotesFiles[i].split('¶');
		option = selector.appendChild( document.createElement( 'option' ));
		option.appendChild( document.createTextNode( cRecord[0] ));
		option.setAttribute( 'value', cRecord[1] );
		}
	}



function readNotesFile (notesFile) {
	var iframe = document.getElementById('iframe');
	if (notesFile == '') { 
		_notesArray.length = 0;
		iframe.src = '';
		_newNotesArray = false;
//		alert( '_notesArray killed' );
		if (!_notesArray) { alert( 'No notes array found.' ); }
		return false; 
		}
	
	iframe.src = notesFile;
	_newNotesArray = true;
	alert( sReadingNotes );
	}	
	
	
function previewChar ( hexCode ) {
	// converts a hex code dropped into the drop point to a character displayed below
	// hexCode: string, the hex code of the character
	var hexStart = '1234567890abcdefABCDEF';
	var notHex = false;
	var ccPadding = ''; // will be space if combining char
	
	// delete all spaces
	while ( hexCode.indexOf( ' ' ) > -1 ) {
		hexCode = hexCode.replace(' ', '');
		}
		
	// if not a hex number, set notHex to true
	for (i=0; i<hexCode.length; i++) {
		if ( hexStart.indexOf( hexCode.charAt(i) ) == -1 ) { notHex = true; break; }
		}
	if (hexCode.length > 6) { notHex = true; }
	
	if (notHex) { alert( sNotHex ); return; }
	else {
		var decCode = parseInt( hexCode, 16 );

		//check for combining character
		cRecord = U[decCode].split(';');
		if (cRecord[3] > 0) { ccPadding = '\u00A0'; }  // ie. this is a combining character
		
		var preview = document.getElementById('preview');
		var dropPoint = preview.firstChild;
		var newText = document.createTextNode( ccPadding + getCharFromInt(decCode));
		var removedText = preview.replaceChild(newText, dropPoint);
		preview.style.fontFamily = _currentFont;
		}
	}

function changeHeight ( height ) {
	// changes the height of the visible text in the left panel by user request
	// height: user specified height (including px, etc.)
	var panel = document.getElementById( 'listOutput' );
	panel.style.height = height;
	}


