<?php
/* 	
	Client-side logic for Wordpress CLI theme
   	R. McFarland, 2006
	http://blog.elinc.ca/rodcli/
	
	Sadly there is some browser sniffing that has to be done. Also
	we set the link to the GUI version of the blog, if any. This is why 
	we're serving a Javascript file via PHP.
*/

require('../cli.conf.php');
require(CLI_DIR.'/lib/utility.inc.php');
header("Content-Type: text/javascript",true,200);
?>
var displayElement 		= null;
var screenElement 		= null;
var promptElement 		= null;
var spinnerElement 		= null;
var preInputArea 		= null;
var inputArea 			= null;
var postInputArea 		= null;
var bottomlineElement 		= null;
var leftOfCursorElement 	= null;
var cursorElement 		= null;
var rightOfCursorElement 	= null;
var pageAlertElement		= null;
var inputBuffer 		= '';
var cursorPosition 		= 0;
var cursorBlinkThreadId 	= false;
var multilineMode 		= false;
var specialCommandHandler 	= false;
var specialCommandHandlerCode 	= false;
var passwordInputMode=false;
var historyArray 		= new Array();
var historyIndex 		= 0;
var clientSideCommandsEnabled 	= true;
var promptText 			= "<?php echo defaultprompt(); ?>";
var sessionId 			= <?php echo(isset($_SESSION['sessions_work'])?'false':"'_".md5(rand(1,5000000))."'"); ?>;
var eatIt 			= false; // eat next character input
var spinnerCharacters 		= new Array('-', '\\', '|', '/');
var spinnerCharacterIndex 	= 0;
var spinnerThreadId 		= false;
var stickyState 		= new Array(); // for "sticky" modifier keys
	stickyState['CTRL']=false;
	stickyState['ALT']=false;
var xmlhttp 			= false;
var interpreter 		= "<?php echo CLI_URI ?>/interpret.php";
var requestId 			= 0;
var firstCommand 		= true;
var waitingForServer 		= false;
var savedDisplayHTML		= false;
var cursorState 		= 1;
var scrLock			= false;
var targetHeight 		= false;
var scrollerThreadId 		= false;
var waitingAtPage 		= false;
var paging 			= true; // there's no option for this, but it's possible. Make false for no "--More--"
var initialScreenOffsetHeight 	= false;
var scrollStep 			= <?php echo get_option('cli_gc_scroll_step') ?>;


var ENTER 			= String.fromCharCode(13);
var DOUBLE_QUOTE 		= String.fromCharCode(34);

<?php
list($gccj,$gcdg)=explode('/',get_option('cli_gc_scheme'));
if($gccj=='js'){
	include(CLI_DIR.'/usr/share/fonts/compile.php');
}else{
echo("var BLANK='".CLI_URI.'/var/cache/fonts/'.get_option('cli_gc_gcfont').".blank.gif';");
}
?>

function initializeCLI(){
	screenElement 		= document.getElementById('scr');
	displayElement 		= document.getElementById('display');
	spinnerElement 		= document.getElementById('spinnerdiv');
	promptElement 		= document.getElementById('prompt');
	bottomlineElement 	= document.getElementById('bottomline');
	leftOfCursorElement 	= document.getElementById('lcommand');
	cursorElement 		= document.getElementById('undercsr');
	rightOfCursorElement 	= document.getElementById('rcommand');
	pageAlertElement	= document.getElementById('pagealert');
	<?php if (get_option('cli_gc_cursor_blink_time') == 0){
		if (get_option('cli_gc_cursor_style') == 'block'){
	?>
	cursorElement.style.color = '<?php echo BG_COLOUR ?>';
	cursorElement.style.backgroundColor = '<?php echo FG_COLOUR ?>';
	<?php	}else{ ?>
	cursorElement.style.textDecoration = 'underline';
	<?php	} 
	}else{
	?>
	if (!cursorBlinkThreadId){
		cursorBlinkThreadId = setInterval('cursorBlink();',<?php echo get_option('cli_gc_cursor_blink_time'); ?>);
	}
	<?php } ?>
	var frm 		= document.forms[0];
	inputArea 		= frm['inputArea'];
	preInputArea 		= frm['preInputArea'];
	postInputArea 		= frm['postInputArea'];
	promptElement.innerHTML = promptText;

	screenElement.scrollTop = 1;

	/*DELME*/
	tn_graphicize_<?php echo $gccj?>(displayElement);
	tn_graphicize_<?php echo $gccj?>(pageAlertElement);
	tn_graphicize_<?php echo $gccj?>(document.getElementById('indicators'));
	tn_graphicize_<?php echo $gccj?>(document.getElementById('rightcol'));
	tn_graphicize_<?php echo $gccj?>(promptElement);
}

function handleKeyEvent(e){
	var left, right, character = '', keyName, keyCode;
	if (inputBuffer == ENTER) inputBuffer = ''; //bah, i have no idea
	if (waitingForServer) return false; // waiting on a response from server
	if (inputArea.value){
		character = inputArea.value.charAt(0);
	}
	if (window.event){ //i.e. if it's MSIE
		e = window.event;
		inputArea.value = '';
	}else{
		if (inputArea.value){
			inputArea.value = inputArea.value.substr(1);
		}
	}
	if (waitingAtPage){
		if (e.type == 'keydown') return false; 
		pageAlert(false);
		scroller();
		return false;
	}
	if (e && (e.keyCode == 9)){// tab
		if (e.shiftKey){
			postInputArea.focus();
		}else{
			preInputArea.focus();
		}
	}
	if (! (stickyState['CTRL'] || stickyState['ALT'])){	
		if (
			(character.length == 1) && 
			e && 
			(e.keyCode != 13)
		){ // if it's a regular key
			if (eatIt){
				character = '';
				eatIt = false;
			}
			left = inputBuffer.substr(0,cursorPosition);
			right = inputBuffer.substr(cursorPosition, inputBuffer.length-cursorPosition);
			inputBuffer = left + character + right;
			cursorPosition++;
			updateInputDisplay();
			//if (inputArea.value) handleKeyEvent(false);
		}
	}
	if (multilineMode) 
		scroller();
	if (e && e.keyCode){ 
		keyCode = e.keyCode;
	}else if (e){
		keyCode = e.which;
	}
	if (character){
		keyName = character;
	}else if (keycodes[keyCode]){ // in keycodes.js -- is named.
		keyName = keycodes[keyCode];
	}else{
		return false;
	}
	if (keyName == 'SHIFT') return false;
	if (
		keyName == 'ALT' ||
		keyName == 'CTRL' 
	){
		stickyModifierKeys(keyName, e);
		return false;
	}		
	if (e && (e.type == 'keyup')) return false;
	if (e && e.shiftKey) keyName = 'SHIFT_' + keyName;
	if (stickyState['CTRL'] || stickyState['ALT']){
		eatIt = true;
		character = '';
	}
	if ((e && e.ctrlKey) || stickyState['CTRL']){
		keyName = 'CTRL_' + keyName;
		stickyModifierKeys('CTRL', null);
	}
	if ((e && e.altKey) || stickyState['ALT']){
		keyName='ALT_' + keyName;
		stickyModifierKeys('ALT', null);
	}
	if ((keyName == 'BACKSPACE') && (cursorPosition > 0)){
		inputArea.focus();
		left = inputBuffer.substr(0, cursorPosition - 1);
		right = inputBuffer.substr(cursorPosition, inputBuffer.length - cursorPosition);
		inputBuffer = left + right;
		cursorPosition--;
		updateInputDisplay();
		return false;
	}
	if (keyName == 'DEL' && cursorPosition < inputBuffer.length){
		left = inputBuffer.substr(0, cursorPosition);
		right = inputBuffer.substr(cursorPosition + 1, inputBuffer.length - cursorPosition - 1);
		inputBuffer = left + right;
		updateInputDisplay();
		return false;
	}
	if (keyName == 'CTRL_c'){
		if (specialCommandHandler){
			specialCommandHandler('__CANCEL__');
		}else{
			executeCommand('cancel=1', false);
		}
		clearInputBuffer();
		return false;
	}
	if ((keyName == 'LEFT') && (cursorPosition > 0)){
		cursorPosition--;
		updateInputDisplay();
		return false;
	}		
	if ((keyName == 'RIGHT') && (cursorPosition < inputBuffer.length)){
		cursorPosition++;
		updateInputDisplay();
		return false;
	}		
	if (multilineMode){
		if (keyName == 'CTRL_x'){ // end multilineMode input
			if (specialCommandHandler){
				specialCommandHandler('__EXIT__');
			}else{
				executeCommand('c=','p=' + prepareURI(inputBuffer));
			}
			clearInputBuffer();
			return false;
		}
		if (keyName == 'UP'){
			if (inputBuffer.charCodeAt(cursorPosition) == 13) cursorPosition++;
			var previousNewline = inputBuffer.lastIndexOf(ENTER, cursorPosition - 1);
			var previousPreviousNewline = inputBuffer.lastIndexOf(ENTER, previousNewline - 1);
			if (previousNewline < 0){previousNewline = 0; previousPreviousNewline = 0;}
			if (previousPreviousNewline < 0) previousPreviousNewline = 0;
			cursorPosition = previousPreviousNewline + cursorPosition - previousNewline;
			if (cursorPosition > previousNewline) cursorPosition = previousNewline - 1;
			updateInputDisplay();
			return false;
		}
		if (keyName == 'DOWN'){
			if (inputBuffer.charCodeAt(cursorPosition) == 13) cursorPosition--;
			var previousNewline = Math.max(0,inputBuffer.lastIndexOf(ENTER, cursorPosition - 1));
			var nextNewline = inputBuffer.indexOf(ENTER, cursorPosition + 1);
			var nextNextNewline = inputBuffer.indexOf(ENTER, nextNewline + 1);
			if (nextNewline < 0) {nn = inputBuffer.length; nextNextNewline = nextNewline;}
			if (nextNextNewline < 0) nextNextNewline = inputBuffer.length;
			cursorPosition = nextNewline + cursorPosition - previousNewline;
			if (cursorPosition > nextNextNewline) cursorPosition = nextNextNewline;
			updateInputDisplay();
			return false;
		}
		if (keyName == 'ENTER' || keyCode == 13){
			left = inputBuffer.substr(0,cursorPosition);
			right = inputBuffer.substr(cursorPosition);
			inputBuffer = left + ENTER + right; 
			cursorPosition++;
			updateInputDisplay();
			return false;
		}
		if (keyName == 'CTRL_a' || keyName == 'HOME'){
			if (inputBuffer.charCodeAt(cursorPosition) == 13) cursorPosition--;
			var ocursorPosition = cursorPosition;
			cursorPosition = inputBuffer.lastIndexOf(ENTER, cursorPosition) + 1;
			if (cursorPosition >= ocursorPosition){
				cursorPosition = 0;
			}
			updateInputDisplay();
			return false;
		}
		if (keyName == 'CTRL_e' || keyName == 'END'){
			if (inputBuffer.charCodeAt(cursorPosition) == 13) cursorPosition++;
			var ocursorPosition = cursorPosition;
			cursorPosition = inputBuffer.indexOf(ENTER, cursorPosition);
			if (cursorPosition <= ocursorPosition){
				cursorPosition=inputBuffer.length;
			}
			updateInputDisplay();
			return false;
		}
		if (keyName == 'TAB'){
			left = inputBuffer.substr(0,cursorPosition);
			right = inputBuffer.substr(cursorPosition);
			inputBuffer = left + '    ' + right;  // 4 spaces 
			cursorPosition += 4;
			updateInputDisplay();
			return false;
		}
	}else{ //not multilineMode
		if ((keyName == 'CTRL_a' || keyName == 'HOME') 
			&& cursorPosition > 0){
			cursorPosition = 0;
			updateInputDisplay();
			return false;
		}		
		if ((keyName == 'CTRL_e' || keyName == 'END') 
			&& cursorPosition < inputBuffer.length){
			cursorPosition = inputBuffer.length;
			updateInputDisplay();
			return false;
		}		
		if (keyName == 'CTRL_l'){ // well, maybe some browser catches it
			displayElement.innerHTML='';
			return false;
		}
		if (keyName == 'SCRLOCK'){
			scrLock = !scrLock;
			document.getElementById('SCRLOCKindicator').style.display=
				(scrLock ? 'inline' : 'none');
		}		
		if (keyName == 'UP' || keyName == 'SHIFT_UP'){
			if(scrLock || keyName == 'SHIFT_UP'){
				scrollLine(-1);
			}else if (historyIndex > 0){
				inputBuffer = historyArray[--historyIndex];
				cursorPosition = inputBuffer.length;
				updateInputDisplay();
				jumpToBottom();
			}
			return false;
		}
	 	if (keyName == 'DOWN' || keyName == 'SHIFT_DOWN'){
			if(scrLock || keyName == 'SHIFT_DOWN'){
				scrollLine(1);
			}else if (historyIndex < historyArray.length){
				if (historyIndex == historyArray.length - 1){
					historyIndex = historyArray.length;
					clearInputBuffer();
				}else{
					inputBuffer = historyArray[++historyIndex];
				}
				cursorPosition = inputBuffer.length;
				updateInputDisplay();
				jumpToBottom();
			}
			return false;
		}
		if (keyName == 'PGUP' || keyName == 'CTRL_UP'){
			scrollPage(-1);
			return false;
		}
		if (keyName == 'PGDN' || keyName == 'CTRL_DOWN'){
			scrollPage(1);
			return false;
		}
		if (keyName == 'CTRL_HOME'){
			jumpToTop();
			return false;
		}
		if (keyName == 'CTRL_END'){
			jumpToBottom();
			return false;
		}
		if (keyName == 'TAB'){
			executeCommand('tc='+inputBuffer, false); //yay tab completion
			return false;
		}
		if (keyName == 'SHIFT_TAB'){
			return false;
		}
		if (keyName == 'ENTER' || keyCode == 13){
			processInputBuffer(inputBuffer);
			return false;
		}
	}
	if (inputArea.value)handleKeyEvent(false);
	return false;
}

function stickyModifierKeys(key, evt){
	if (evt != null && evt.type == 'keydown') return false;
	stickyState[key] = !stickyState[key];
	document.getElementById(key + 'indicator').style.display=
		(stickyState[key] ? 'inline' : 'none');
	return true;
}

function updateInputDisplay(){
	var left = '', underCursor = ' ', right = '';
	if (trim(inputBuffer) == '') inputBuffer='';
	if (cursorPosition < 0) cursorPosition = 0;
	if (cursorPosition > inputBuffer.length) cursorPosition = inputBuffer.length;
	if (cursorPosition > 0){
		left = inputBuffer.substr(0, cursorPosition);
	}
	if (cursorPosition < inputBuffer.length){
		underCursor = inputBuffer.substr(cursorPosition, 1);
	}
	if (inputBuffer.length - cursorPosition > 1){
		right = inputBuffer.substr(cursorPosition + 1, inputBuffer.length-cursorPosition-1);
	}

	leftOfCursorElement.innerHTML = prepareInputForDisplay(left);
	cursorElement.innerHTML = prepareInputForDisplay(underCursor);
	if (underCursor == ' ') cursorElement.innerHTML = '&nbsp;';
	rightOfCursorElement.innerHTML = prepareInputForDisplay(right);
	promptElement.innerHTML=promptText;
	tn_graphicize_<?php echo $gccj?>(bottomlineElement);
	return;
}

function clearInputBuffer(){
	inputArea.value = '';
	inputBuffer = '';
	cursorPosition = 0;
	updateInputDisplay();
}

function prepareInputForDisplay(str){
	str = str.replace(/&/g,'&amp;'); // keep first
	str = str.replace(/</g,'&lt;');
	str = str.replace(/>/g,'&gt;');
	str = str.replace(/  /g,' &nbsp;');
<?php if ($is_winIE){ ?>
	str = str.replace("\n",'&nbsp;<br />');
<?php }else{ ?>
	str = str.replace(/\x0D/g,'&nbsp;<br />');
<?php } ?>
	return str;
}

function processInputBuffer(input){
	clearInputBuffer();
	
	/* redisplay command in display div */
	var inputForDisplay = input;
	if (passwordInputMode){
		inputForDisplay = "";
		for(i = 0; i < input.length; i++){
			inputForDisplay += '*';
		}
	}
	appendToDisplay("<p>" + promptText + prepareInputForDisplay(inputForDisplay) + '</p>');

	input = trim(input);

	/* for weird local-only interaction, maybe editor */
	if (specialCommandHandler){
		specialCommandHandler(input);
		setPromptActive(true);
		return false;
	}
			
	if (clientSideCommandsEnabled){
			/* add to history */
			if (input != ''){
				historyArray[historyArray.length] = input;
				historyIndex = historyArray.length;
			}
			var possibleCommand = input.toLowerCase();
			/*LOCALLY EVALUATED COMMANDS */
		//CLS
			if (
				possibleCommand == 'cls' 
				|| possibleCommand == 'clear'
			){
				displayElement.innerHTML='';
				return false;
			}
		//ADMIN
			if (
				possibleCommand == 'admin' 
				|| possibleCommand == 'su'
			){
				document.location.href = "<?php echo SITE_URI ?>/wp-admin/index.php";
				return false;
			}
		<?php if ($username == 'guest'){ ?>
		//LOGIN
			if (possibleCommand == 'login'){
				document.location.href = "<?php echo SITE_URI ?>/wp-login.php";
				return false;
			}
		<?php }else{ ?>
		//LOGOUT
			if (
				possibleCommand == 'logout' 
				|| possibleCommand == 'exit'
				|| possibleCommand == 'quit'
				|| possibleCommand == 'bye'
			){
				document.location.href = "<?php echo SITE_URI ?>/wp-login.php?action=logout";
				return false;
			}
		<?php } ?>
		//STARTX
			if (
				possibleCommand == 'gui' 
				|| possibleCommand == 'startx'
			){
		<?php if (get_option('cli_gc_gui_url')) { ?>
				document.location.href = "<?php echo get_option('cli_gc_gui_url'); ?>";
		<?php } else { ?>
				alert('No GUI link configured!');
		<?php } ?>
				return false;
			}
	/* END LOCALLY EVALUATED COMMANDS */
	}
	setPromptActive(false);
	executeCommand("c=" + input, false);
	return false;
}

function prepareURI(what){
	what = encodeURI(what);
	what = what.replace(/&amp;/g,'%26');
	what = what.replace(/&lt;/g,'<');
	return what;
}

function createXMLHTTP(){
	/* I stole this from somebody a long time ago. Sorry, somebody. */
        /*@cc_on @*/
        /*@if (@_jscript_version >= 5)
        try {
        	xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
        	try {
			xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
		} catch (E) {
			xmlhttp = false;
		}
	}
        @end @*/
        if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
		xmlhttp = new XMLHttpRequest();
        }
}

function executeCommand(getCommand, postData){
	multilineMode = false;
	if (!xmlhttp) createXMLHTTP();
	if (!xmlhttp){
		alert('Darn.');
		return false;
	}
	if (firstCommand){
		firstCommand = false;
	}else{
		requestId = Math.round(Math.random() * 100000);
	}
	var url = interpreter 
		+ "?" 
		+ prepareURI(getCommand)
		+ "&requestId=" + requestId
		<?php 
		if (!isset($_SESSION['sessions_work'])){ /* no kidding. php5.2 appears to have pooched sessions */
			echo('+"&CSID="+sessionId');
		}else if (SID){
			echo('+"&'.htmlspecialchars(SID).'"');
		} 
		?>;
	if (postData){
		xmlhttp.open("POST", url, true);
		xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	}else{
		xmlhttp.open("GET", url, true);
	}
	xmlhttp.onreadystatechange = function(){
		xstate = xmlhttp.readyState;
		if (xstate == 4 && xmlhttp.status == 200){
			waitingForServer = false;
			busySpinner(false);
			handleServerXML(xmlhttp.responseXML);
			scroller();
			setPromptActive(true);
			return true;
		}
		return false;
	}
	waitingForServer = true;
	busySpinner(true);
	if (postData){
		xmlhttp.send(prepareURI(postData));
	}else{
		xmlhttp.send("");
	}
	return false;
}

function busySpinner(active){
	if (active){
		spinnerCharacterIndex = (++spinnerCharacterIndex) % spinnerCharacters.length;
		spinnerElement.innerHTML = spinnerCharacters[spinnerCharacterIndex];
		if (!spinnerThreadId){
			spinnerElement.style.display = 'block';
			spinnerThreadId = setInterval('busySpinner(true);', 100);
		}
	}else{
		spinnerElement.style.display = 'none';
		clearInterval(spinnerThreadId);
		spinnerThreadId = false;
	}
}

function handleServerXML(xml){
	if (!xml) return false;
	xmlDocumentElement = xml.documentElement;
	if (!xmlDocumentElement) return false;
/* 
	//for some weird-ass reason some people's servers are responding with empty responseId's
	xresponseId = xmlDocumentElement.getElementsByTagName('responseId');
	if (xresponseId.length == 0 || 
		(xresponseId[0].getAttribute('value') != requestId)
	){ // to avoid confusion with slow-arriving results
		alert('Out-of-order or malformed server response');
		return false;
	}
*/
	xmultilineMode = xmlDocumentElement.getElementsByTagName('multiline');
	if (xmultilineMode.length > 0 && xmultilineMode[0].getAttribute('value') == "1"){
		multilineMode = true;
	}
	
	xclientSideCommandsEnabled = xmlDocumentElement.getElementsByTagName('clientsidecommands');
	if (
		xclientSideCommandsEnabled.length > 0 
		&& xclientSideCommandsEnabled[0].getAttribute('value') == "off"
	){
		clientSideCommandsEnabled = false;
	}else{
		clientSideCommandsEnabled = true;
	}
	
	xcommandlineData = xmlDocumentElement.getElementsByTagName('commandline');
	if (xcommandlineData.length > 0){
		inputBuffer = xcommandlineData[0].firstChild.data;
		cursorPosition = inputBuffer.length;
	}else{
		inputBuffer = '';
		cursorPosition = 0;
	}

	xprompt = xmlDocumentElement.getElementsByTagName('prompt');
	if (xprompt && xprompt[0]){
		promptText = xprompt[0].firstChild.data;
	}
	
	xdisplayData = xmlDocumentElement.getElementsByTagName('display');
	if (xdisplayData.length > 0){
		displayFromXML(xdisplayData);
	}
	
	xspecialCommandHandler = xmlDocumentElement.getElementsByTagName('specialcommandhandler');
	if (xspecialCommandHandler.length > 0){
		initializeSpecialCommandHandler(xspecialCommandHandler);
	}
	
	updateInputDisplay();
	return true;
}

function displayFromXML(xdisplayData){
	var html = '';
	for(i = 0; i < xdisplayData.length; i++){
		if (xdisplayData[i].firstChild){
			html += xdisplayData[i].firstChild.data;
		}
	}
	appendToDisplay(html);
}

function initializeSpecialCommandHandler(xspecialCommandHandler){
	for(i = 0; i < xspecialCommandHandler.length; i++){
		if (xspecialCommandHandler[i].firstChild){
			specialCommandHandlerCode += xspecialCommandHandler[i].firstChild.data;
		}
	}
	if (specialCommandHandlerCode == '0'){
		specialCommandHandler = false;
		specialCommandHandlerCode = false;
	}else{
		specialCommandHandler = function(input){
			eval(specialCommandHandlerCode);
			return false;
		};
		specialCommandHandler('__INIT__');
	}
}

function setPromptActive(active){
	if (active){
		bottomlineElement.style.visibility = 'visible';
		inputArea.focus();
		return true;
	}else{
		bottomlineElement.style.visibility = 'hidden';
		return false;
	}
}

function appendToDisplay(html){
	var appendNode=tn_graphicize_html_<?php echo $gccj?>(html);
	displayElement.appendChild(appendNode);
	scroller();
}

function pageAlert(active){
	waitingAtPage = active;
	if (active){
		pageAlertElement.style.visibility = 'visible';
	}else{
		pageAlertElement.style.visibility = 'hidden';
	}
}

var uc, ntn, nfc;
function cursorBlink(){
	cursorState = 1 - cursorState;
	if(!inputBuffer || inputBuffer=='' || cursorPosition==inputBuffer.length){
		uc = ' ';
	}else{
		uc = inputBuffer.charAt(cursorPosition);
	}
	var t='span';
	if(cursorState==1){ t= 'b'; } //b, among others, displays as reverse
	nfc=document.createElement(t);
	ntn=document.createTextNode(uc);
	nfc.appendChild(ntn);
	cursorElement.replaceChild(nfc,cursorElement.firstChild);
	tn_graphicize_<?php echo $gccj ?>(cursorElement);
}

function scroller(){
	initialScreenOffsetHeight = screenElement.offsetHeight;
	if (!waitingAtPage && !scrollerThreadId) 
		scrollerThreadId = setTimeout('backgroundScroller()', 10);
	return;
}

function scrollPage(mul){
	screenElement.scrollTop += mul * screenElement.offsetHeight;
	return false;	
}

function scrollLine(mul){
	var s = scrollStep;
	if(s == 0) s = 24;
	screenElement.scrollTop += mul * scrollStep;
	return false;	
}

function jumpToBottom(){
	screenElement.scrollTop = screenElement.scrollHeight - screenElement.offsetHeight;
	inputArea.focus();
}

function jumpToTop(){
	screenElement.scrollTop = screenElement.offsetHeight;
	inputArea.focus();
}

function backgroundScroller(){
//	topofscreentotopofviewport	= screenElement.scrollTop;
// +	viewportheight			= screenElement.offsetHeight;
// <=	fullheight			= screenElement.scrollHeight;
	
	if (
		scrollStep > 0 
		&& (
			screenElement.scrollHeight - screenElement.offsetHeight 
			> screenElement.scrollTop + scrollStep
		)
	){
		if (
			!targetHeight 
			|| initialScreenOffsetHeight != screenElement.offsetHeight
		){
			initialScreenOffsetHeight = screenElement.offsetHeight;
			if (paging){ 
				targetHeight = Math.min(
						screenElement.scrollTop+screenElement.offsetHeight-40,
						screenElement.scrollHeight
						);
			}else{
				targetHeight = screenElement.scrollHeight;
			}
		}
		if (screenElement.scrollTop < targetHeight){
			screenElement.scrollTop += scrollStep;
			scrollerThreadId = setTimeout('backgroundScroller()', 10);
			return;
		}else{
			targetHeight = false;
			scrollerThreadId = false;
			pageAlert(true);
		}
	}else{
		screenElement.scrollTop = screenElement.scrollHeight - screenElement.offsetHeight;
		targetHeight = false;
		scrollerThreadId = false;
		pageAlert(false);
		jumpToBottom();
	}
}

/**** start from http://snippets.dzone.com/posts/show/701 ****/
// Removes leading whitespaces
function LTrim( value ) {
	if (value){
	var re = /\s*((\S+\s*)*)/;
	return value.replace(re, "$1");
	}
	return '';
	
}

// Removes ending whitespaces
function RTrim( value ) {
	if (value){
	var re = /((\s*\S+)*)\s*/;
	return value.replace(re, "$1");
	}
	return '';
}

// Removes leading and ending whitespaces
function trim( value ) {
	if (value)
	return LTrim(RTrim(value));
	return '';
}
/**** end from http://snippets.dzone.com/posts/show/701 ****/

function showpost(which){
	if (which == 'latest'){
		executeCommand('c=latest', false);
	}else{
		executeCommand('c=cat ' + which, false);
	}
}

function ls(which){
	executeCommand('c=ls ' + which, false);
}

function help(what){
	executeCommand('c=help ' + what, false);
}

function autosearch(which){
	executeCommand('c=grep ' + which, false);
}

function showcomments(){
	executeCommand('c=comments', false);
}

function showcat(which){
	executeCommand('c=category ' + which, false);
}

function setcl(addend){
        inputBuffer += addend;
        cursorPosition = inputBuffer.length;
	//updateInputDisplay();
	processInputBuffer(inputBuffer)
}

function telnet(which){
	executeCommand('c=telnet ' + which, false);
}




