// ----------------------------------------------------------------------
// iad/src/resources/scripts/ui_core.js
// BeIA core JavaScript routines
//
// The routines in this file allow the BeIA user interface to interact
// with Wagner through its messaging interface.  Also provided are some
// common routines to be used by custom UI code to manipulate the state
// of the browser (the be_* routines).  
//
// To override these routines, make appropriate modifications to 
// ui_custom.js and include that file after ui_core.js in the root
// index.html.
// ----------------------------------------------------------------------

// ----- Environment setup -----

if (FeatureMachine == null) {
	beos.dprintf('ui_core.js: error: ui_core depends on modes.js');
}

// -------------------------------------------------------------

if (beos.globals.inited != 1) {
	beos.globals.kWagnerSig = "application/x-vnd.Web";
	
	// check, because recover page may have changed
	if (beos.globals.modes == null) {	
		/*		beos.globals.mode = BROWSE_MODE; */

		beos.globals.modes = new ModeMachine();
		beos.globals.features = new FeatureMachine();

		// basic setup; can be overridden from ui_custom.js
		beos.globals.modes.AddCluster("application");
		beos.globals.modes.AddMode("application", "web", null, null);
		beos.globals.features.Add("web:bookmarks", null, null);
		beos.globals.features.Add("web:subwindow", null, null);
		beos.globals.features.Add("media:visible", null, null);
		beos.globals.features.Add("softkeyboard:visible", null, null);
	}

	if (beos.globals.pages == null) {
		beos.globals.pages = new Object();
		// if this object is totally new, let's give it some defaults
		beos.globals.pages.search = "http://www.google.com/";
		beos.globals.pages.webhome = "file://$RESOURCES/Web/index.html";

		beos.globals.mainwin_url = beos.globals.pages.webhome;
		beos.globals.displayed_url = ""; // a good bootstrapping value
	}

	if (beos.globals.framenames == null) {
		beos.globals.framenames = new Object();

		beos.globals.framenames.layout = "_be:layout";

		beos.globals.framenames.content = "_be:content0";
		beos.globals.framenames.content_prefix = "_be:content_";
		beos.globals.framenames.bookmarks = "_be:web:bookmarks";

		beos.globals.framenames.settings = "_be:settings";
		beos.globals.framenames.status = "_be:status";
		beos.globals.framenames.navbar = "_be:navbar";
		beos.globals.framenames.title = "_be:webtitle";
		beos.globals.framenames.media = "_be:mediabar";
		
		beos.globals.framenames.subwin = "_be:subwindow";
		beos.globals.framenames.softkeyboard = "_be:softkeyboard";

		beos.globals.framenames.updater = "_be:updated";
	}

	beos.globals.use_redirector = 1;
	//beos.globals.dockable_view_showing = 0;
	//beos.globals.soft_keyboard_showing = 0;
	beos.globals.mediabar_url = "";
	beos.globals.zoomState = 0;

	beos.globals.mainwin_name = "";
	// beos.globals.mainwin_need_src = 1;
	beos.globals.mainwin_title = "";

	beos.globals.subwin_name = "";
	beos.globals.subwin_url = "";
	beos.globals.subwin_width = "0";
	beos.globals.subwin_height = "0";
	// beos.globals.subwin_need_src = 1;
	beos.globals.subwin_title = "";

	beos.globals.subwin_min_height = 100;
	beos.globals.subwin_min_width = 100;
	
	beos.globals.alert_url = "";

	beos.globals.notify_messenger = null;
	beos.globals.notify_string = "";

	beos.globals.next_win_id = 1;

	//
	// observe the net statuses
	//
	beos.binder.service.network.status.observe(beos.realTop.be_netstat, "");
	beos.binder.service.network.pppstatus.observe(beos.realTop.be_netstat, "");
	// bootstrap
	beos.realTop.be_netstat();
	
	if(beos.globals.use_redirector) {
		beos.sendMessageSync(beos.globals.kWagnerSig, "tbGs",
			"be:settings", "string", "redirect");
		beos.globals.redir_base = beos.reply["CONTENT_REDIR"];
		beos.globals.redir_context = beos.reply["APHW_CONTEXT"];
		beos.globals.redir_language = beos.reply["R_LANGUAGE"];
		beos.globals.redir_locale = beos.reply["R_LOCALE"];
	} 
	
	beos.globals.inited = 1;
}

// top.onload_func()
// Called when ui_core loads, in order to catch deferred instructions
// to open up a subwindow.
function catch_opened_window_reference()
{
	if (beos.globals.notify_messenger) {
		beos.dprintf('catch_opened_window_reference: looking for subwindow to supply to BMessage reply');
		// Deferred notification
		var win = be_subwindow();
		if ( win == null )
			beos.dprintf('warning: could not find the just-opened subwindow <<'
				+ beos.globals.framenames.content_prefix + beos.globals.subwin_name 
				+ '>> to pass as a return value to the opener.');
		beos.setReturnValue(beos.globals.request_id, win);
		beos.globals.notify_messenger = null;
	}
}
var onload_func = catch_opened_window_reference;

// ----- HTML frame utilities -----

// top.find_frame(name)
// Find an HTML frame object (part of the HTML DOM).
function find_frame(name)
{
	return find_descendent_frame(top, name);
}

// top.find_descendent_frame(win, name)
// Find an HTML frame, starting with window/frame 'win'.
function find_descendent_frame(win, name)
{
	var index, retval;

	// Search through the frames at this level
	for (index = 0; index < win.frames.length; index++)
		if (win.frames[index].name == name)
			return win.frames[index];

	// Check descendent frames		
	for (index = 0; index < win.frames.length; index++) {
		retval = find_descendent_frame(win.frames[index], name);
		if (retval != null)
			return retval;
	}

	return null;
}

// ----- Browser navigation and control code -----

// TODO dsandler: clean up and reorganize these functions.  
// Separate into mode-switching code, web-location-munging code, etc.

function be_content()
{
	return find_frame(beos.globals.framenames.content);
}

function be_subwindow()
{
	// we allow this to look for the frame, even if the subwindow is 
	// nominally hidden .. who knows, you might need this functionality!
	return find_frame(
		beos.globals.framenames.content_prefix +
		beos.globals.subwin_name
	);
}

function be_refresh()
{
	if ( beos.globals.topLayout )
		beos.globals.topLayout.Refresh();
	var layoutFrame = find_frame(beos.globals.framenames.layout);
	if ( layoutFrame ) 
		layoutFrame.location.reload(true);
	else
		top.location.reload(true);
}

// requires that the bookmark frame is available, even if it's
// zeroPixelHidden.
function be_add_bookmark() {
	var returnValue = false;
	var bookmarkFrame 
		= beos.realTop.find_frame(beos.globals.framenames.bookmarks);
	if ( bookmarkFrame != null 
		&& bookmarkFrame.addBookmark != null ) 
	{
		returnValue = bookmarkFrame.addBookmark();
	} else {
		beos.dprintf('be_add_bookmark: error: couldn\'t find bookmarks frame');
	}
	return(returnValue);
}

// replaces doExpandAndOpen()
function be_open_navbar_url() {
	var doc = be_navbar();
	if (!doc) return;
	if (!doc.GetURLText || !doc.SetURLText) {
		beos.dprintf("be_open_navbar_url: error: navbar does not support GetURLText/SetURLText");
		return;
	}

	var url = new String;
	
	// strip space
	var typedText = doc.GetURLText();
	var c;
	for (var i = 0; i < typedText.length; i++)
		if ((c = typedText.charAt(i)) != " ")
			url += c;

	// bail if string is empty
	if (url.length == 0)
		return;
		
	// add scheme and host/domain if needed
	if (url.indexOf(":") == -1) {
		if (url.indexOf(".") == -1)
			url = ("http://www." + url + ".com");
		else
			url = ("http://" + url);
	}
	doc.SetURLText(url);
	beos.realTop.be_goto_url(url, true);
}

function be_navbar() {
	return beos.realTop.find_frame(beos.globals.framenames.navbar);
}

function be_goto_home()
{
	be_goto_url(beos.globals.pages.webhome);
}

function be_goto_search()
{
	be_goto_url(beos.globals.pages.search);
}

if ( beos.globals.scalingFactors == null ) {
	beos.globals.scalingFactors = new Array(4);
	beos.globals.scalingFactors[0] = 1.0;
	beos.globals.scalingFactors[1] = 1.2;
	beos.globals.scalingFactors[2] = 1.5;
	beos.globals.scalingFactors[3] = 2;
}

function be_textzoom_cycleup() {
	var index = beos.globals.zoomState;
	index = index + 1;
	if (index >= beos.globals.scalingFactors.length) index = 0;
	beos.globals.zoomState = index;
	beos.fontScale = beos.globals.scalingFactors[index];
}
var be_zoom = be_textzoom_cycleup;

function be_textzoom_up() {
	be_textzoom_change("up");
}

function be_textzoom_down() {
	be_textzoom_change("down");
}

function be_textzoom_change(mode) {
	var index = beos.globals.zoomState;
	if (mode == "down") {
		index = index - 1;
	} else {
		index = index + 1;
	}
	if (index >= beos.globals.scalingFactors.length) {
		index = beos.globals.scalingFactors.length - 1;
	} else if (index < 0) {
		index = 0;
	} else {
		beos.globals.zoomState = index;
		beos.fontScale = beos.globals.scalingFactors[index];
	}
}

function be_goto_url(url, force) {
	//debug('entering be_goto_url("'+url+'")');
	var reloadPanes = false;
	
	// install this URL in the URL box of the toolbar.
	// we don't do this here anymore.
	// beos.globals.displayed_url = beos.globals.mainwin_url = url;
	
	var changedURL = true;
	var c = beos.realTop.be_content();
	// is there a content window, *and* are the bookmarks hidden?
	if (c != null && !be_get_bookmarks_state()) {
		debug('already in web mode, changing location of content pane');
		changedURL = (c.location.href != url);
		c.location.href = url;
	} else {
		reloadPanes = true;
		// beos.globals.mainwin_need_src = 1; // obsolete
	}
	
	if (force && !changedURL) {
		beos.dprintf("URL is no different and force is specified -- calling be_reload()");
		be_reload();
	}

	// Get rid of the subwindow
	if (be_get_bookmarks_state()) {
		be_close_bookmarks();
		reloadPanes = true;
	}

	if ( beos.globals.modes.Get("application") != "web" ) {
		beos.globals.modes.Set("application", "web");
		reloadPanes = true;
	}
	
	beos.globals.mainwin_url = url;
	
	if ( reloadPanes )
		top.be_refresh();

	// the "nurl" message will take care of updating things like the toolbar
}


// ** bookmarks **
function be_toggle_bookmarks() // new!
{
	if ( !be_get_bookmarks_state() ) 
		be_open_bookmarks();
	else
		be_close_bookmarks();
}

var be_goto_bookmarks = be_toggle_bookmarks; // for legacy code

function be_get_bookmarks_state() { // new!
	var state;
	if ( beos.globals.use_fullscreen_bookmarks ) {
		state = ( beos.globals.modes.Get("application") == "bookmarks" );
	} else {
		state = ( beos.globals.features.Get("web:bookmarks") );
	}
	return(state);
}

function be_close_bookmarks() { // new!
	var refresh = false;
	if ( beos.globals.use_fullscreen_bookmarks ) {
		if ( beos.globals.modes.Get("application") == "bookmarks" )  {
			refresh = true;
			beos.globals.modes.Set("application", "web");
		}
	} else {
		if ( beos.globals.features.Get("web:bookmarks") ) {
			refresh = true;
			beos.globals.features.Close("web:bookmarks");
		}
	}
	if ( refresh ) top.be_refresh();
}

function be_open_bookmarks() { // new!
	var refresh = false;
	if ( beos.globals.use_fullscreen_bookmarks ) {
		if ( beos.globals.modes.Get("application") != "bookmarks" )  {
			refresh = true;
			beos.globals.modes.Set("application", "bookmarks");
		}
	} else {
		if ( ! beos.globals.features.Get("web:bookmarks") ) {
			refresh = true;
			beos.globals.features.Open("web:bookmarks");
		}
	}
	if ( refresh ) top.be_refresh();
}


function be_print_content() { // new!
	beos.sendMessage(beos.globals.kWagnerSig, "tbPR");
}

function be_goto_settings()
{
	top.be_goto_url(beos.globals.pages.settings);
}

function be_toggle_settings()
{
	// nop for now
}

function be_goto_browse()
{
	var refresh = false;
	if ( beos.globals.modes.Get("application") != "web" ) {
		beos.globals.modes.Set("application", "web");
		refresh = true;
	}
	if ( refresh ) top.be_refresh();
}

function be_stop()
{
	beos.sendMessage(beos.globals.kWagnerSig, "tbSL");
}

function be_reload()
{
	var c = be_content();
	if (c != null)
		c.location.reload(true);
}

function be_forward()
{
	if ( beos.globals.features.Get("web:subwindow") ) {
		beos.globals.features.Close("web:subwindow");
		beos.realTop.be_refresh();
	} else {
		var c = be_content();
		if (c != null)
			c.history.forward();
	}
}

function be_back()
{
	if ( beos.globals.features.Get("web:subwindow") ) {
		beos.globals.features.Close("web:subwindow");
		beos.realTop.be_refresh();
	} else {
		var c;
		c = be_content();
		if (c != null)
			c.history.back();
	}
}

function be_special_key(n)
{
	if (beos.globals.use_redirector) {
		// Use redirector URLs
		if (n == "back") be_back();
		else if (n == "forward") be_forward();
		else if (n == "bookmarks") be_goto_bookmarks();
		else if (n == "home") be_goto_home();
		else if (n == "settings") be_toggle_settings();
		else {
			var redirector = beos.globals.redir_base + "?s=";
			if (n == "news") redirector += "bnews";
			else if (n == "shopping") redirector += "bshopping";
			else if (n == "email") redirector += "bmail";
			else if (n == "compaq") redirector += "bhome";
			else if (n == "search") redirector += "bsearch";
			else if (n == "rocket") redirector += "bfinance";
			else if (n == "lightbulb") redirector += "bentertain";
		
			redirector += "&c=" + beos.globals.redir_context + "&i=" + 
				beos.globals.redir_language + "&lc=" + beos.globals.redir_locale;

			be_goto_url(redirector);
		}
	} else {
		// Hardcoded values for special keys
		if (n == "back") be_back();
		else if (n == "forward") be_forward();
		else if (n == "news") be_goto_url("http://www.cnn.com/");
		else if (n == "shopping") be_goto_url("http://www.amazon.com/");
		else if (n == "email") be_goto_url("http://mail.yahoo.com/");
		else if (n == "bookmarks") be_goto_bookmarks();
		else if (n == "home") be_goto_home();
		else if (n == "settings") be_toggle_settings();
		else if (n == "compaq") be_goto_url("http://www.compaq.com/");
		else if (n == "search") be_goto_url("http://www.google.com/");
		else if (n == "lightbulb") be_goto_url("http://www.cnnfn.com/");
		else if (n == "rocket") be_goto_url("http://www.sports.com/");
	}
}


function be_set_status(s) {
	var statusFrame = beos.realTop.find_frame(beos.globals.framenames.status);
	if (statusFrame == null) {
		beos.dprintf("be_set_status(): error: couldn't find status frame");
		return;
	}
	// beos.dprintf('be_set_status(): setting status text: "' + s + '"');
	if (statusFrame.statusBar == null) {
		beos.dprintf("be_set_status(): statusBar unbound in status frame -- unable to locate plugin in frame");
		return;
	}
	beos.sendMessage(statusFrame.statusBar, 'uSTT',
		'status_text', 'string', s);
}

// ----------------------------------------------------------------------
// Subwindow routines

function open_window(name, url, messenger, requestID, height, width)
{
	var subframe = find_frame(beos.globals.framenames.content_prefix + name);
	if (subframe) {
		beos.dprintf("open_window: loading in existing pane");
		subframe.location.href = url;
		beos.setReturnValue(requestID, subframe);
		return;
	}

	beos.globals.subwin_need_src = 1;
	beos.globals.subwin_url = url;
	beos.globals.subwin_name = name;

	var content = top.be_content().parent;
	var halfWidth = parseInt(content.innerWidth / 2);
	// var halfHeight = parseInt(content.innerHeight / 2);
	var halfHeight = beos.globals.geometry.window_h / 2; // HACK for Opera bug.

	if ( width < beos.globals.subwin_min_width ) 
		width = beos.globals.subwin_min_width;
	else if ( width > halfWidth ) 
		width = halfWidth;

	if ( height < beos.globals.subwin_min_height ) 
		height = beos.globals.subwin_min_height;
	else if ( height > halfHeight )
		height = halfHeight;

	beos.dprintf("open_window: content geometry: " + content.innerWidth 
		+ "x" + content.innerHeight);
	beos.dprintf("open_window: max geometry: " + halfWidth + "x" + halfHeight);
	beos.dprintf("open_window: selected geometry: " + width + "x" + height);
	beos.globals.subwin_width = width;
	beos.globals.subwin_height = height;
	beos.globals.notify_messenger = messenger;
	beos.globals.request_id = requestID;
	beos.globals.notify_string = "find_frame('" 
		+ beos.globals.framenames.content_prefix 
		+ beos.globals.subwin_name + "');";

	beos.globals.features.Open("web:subwindow");

	beos.dprintf('opened subwindow [name: ' + name + '] [url: ' + url + ']');
	// beos.dprintf('refreshing to show split ...');

	top.be_refresh();
} 


function close_window(name)
{
	if (name == beos.globals.framenames.content 
		|| name == beos.globals.mainwin_name) {

		if (beos.globals.subwin_url != "") {
			// Close the main window and replace it with the subwindow.
			// Note how we set the location of the mainwindow.  This way, the
			// subwindow just gets inserted into the history and the user can
			// hit the back button from it.
			beos.globals.mainwin_name = beos.globals.subwin_name;
			var subFrame = be_subwindow();
			if (subFrame != null) {
				top.be_content().location.href = subFrame.location.href;
				beos.dprintf('url for sub frame is now ' + subFrame.location.href);
			} else
				top.be_content().location.href = beos.globals.subwin_url;

			beos.globals.subwin_name = "";
			beos.globals.subwin_url = "";
		} else {
			// Someone wants to close the main window.  This is because
			// it is a promoted subwindow (that's why it has a name).  Just
			// go back and we should restore the right page.  Reset the name
			// too so  we don't get confused in the future.
			// NOTE: This doesn't work quite as well anymore.  We'll need to 
			// refresh anyway.  Bleah.  -dsandler
			beos.globals.mainwin_name = "";
			// top.be_back();
		}
	} else if (name == 
		(beos.globals.framenames.content_prefix + beos.globals.subwin_name)) {
		// Close the subwindow
		beos.globals.subwin_name = "";
		beos.globals.subwin_url = "";
	} else { 
		beos.dprintf("Couldn't find window to close: <<" + name + ">>");
		return; // no window by that name, buddy
	}
	// we do this no matter what!
	beos.globals.features.Close("web:subwindow");
	top.be_refresh();
}


function be_netstat()
{
	var net;
	
	beos.globals.network_info = beos.realTop.network_get_info();
	beos.dprintf("be_netstat: new network information => "
		+ beos.globals.network_info);
	
	var status = beos.globals.network_info.status; // "online" or "offline"

	// Step 1: Handle hardware LED
    //beos.sendMessage("application/x-vnd.Web", "cpql",
    //                "led", "string", "connect",
    //                "state", "string", status == "up" ? "on" : "off");
	beos.binder.service.indicators.connection = (status == "online"?1:0);

	// Step 2: Handle connection-status widget
	var tabs = find_frame(beos.globals.framenames.navbar);
	if (tabs != null && tabs.be_ShowCnxnStatus != null)
		tabs.be_ShowCnxnStatus();
		
	// Step 3: Update network settings panel, if visible
	var netset = find_frame("panel"); // we have GOT to change this framename
	if (netset != null && netset.net_status_change != null) {
		netset.net_status_change();
	}
}

// ----------------------------------------------------------------------
// BMessage handler

// use this object to modularize your message handlers
// in ui_core.js, or override in ui_custom.js.
// signature: message_handlers[<what>] = <Function>(msg)
if ( beos.globals.message_handlers == null ) {
	beos.globals.message_handlers = new Object();

	beos.globals.message_handlers['dock'] = function be_handle_dock(msg) {
		beos.globals.mediabar_url = msg.url;
		var mediabar = null;
		if (beos.globals.features.Get("media:visible"))
			mediabar = beos.realTop.find_frame(beos.globals.framenames.media);

		if (mediabar != null)
			mediabar.location.reload(false);		
		else {
			beos.globals.features.Open("media:visible");
			beos.realTop.be_refresh();
		}
	}


	beos.globals.message_handlers['mary'] = function be_handle_mary(msg) {
		if (beos.globals.features.Get("media:visible")) {
			beos.globals.features.Close("media:visible");
			beos.globals.mediabar_url = "";
			beos.realTop.be_refresh();
		}
	}

	beos.globals.message_handlers['idle'] = function be_handle_idle(msg) {
		var navbar = beos.realTop.find_frame(beos.globals.framenames.navbar);
		if (navbar != null && navbar.be_onLoadStop != null)
			navbar.be_onLoadStop(msg);
	}

	beos.globals.message_handlers['busy'] = function be_handle_busy(msg) {
		var navbar = beos.realTop.find_frame(beos.globals.framenames.navbar);
		if (navbar != null && navbar.be_onLoadStart != null)
			navbar.be_onLoadStart(msg);
	}

	beos.globals.message_handlers['opnw'] = function be_handle_opnw(msg) {
		beos.realTop.open_window(
			msg.name, 
			msg.url, 
			msg.messenger, 
			msg.requestID, 
			msg.height, 
			msg.width);
	}

	beos.globals.message_handlers['clsw'] = function be_handle_clsw(msg) {
		beos.realTop.close_window(msg.name);
	}

	beos.globals.message_handlers['shwj'] = 
	beos.globals.message_handlers['shwk'] = function be_handle_shwk(msg) {
		if (!beos.globals.features.Get("softkeyboard:visible")) {
			// Show soft keyboard
			beos.globals.features.Open("softkeyboard:visible");
			beos.realTop.be_refresh();
		}
	}

	beos.globals.message_handlers['hidj'] = 
	beos.globals.message_handlers['hidk'] = function be_handle_hidk(msg) {
		if (beos.globals.features.Get("softkeyboard:visible")) {
			// Hide soft keyboard
			beos.globals.features.Close("softkeyboard:visible");
			beos.realTop.be_refresh();
		}
	}

	beos.globals.message_handlers['togj'] = 
	beos.globals.message_handlers['togk'] = function be_handle_togk(msg) {
		if (beos.globals.features.Get("softkeyboard:visible")) 
			beos.globals.features.Close("softkeyboard:visible");
		else
			beos.globals.features.Open("softkeyboard:visible");
		beos.realTop.be_refresh();
	}

	beos.globals.message_handlers['qNCI'] = function be_handle_qNCI(msg) {
		var status = "offline";
		if (msg.connectiontype == "ppp") {
			if (msg.pppstate == 3)
				status = "online";
			else if (msg.pppstate == 4)
				status = "offline";
			else
				status = "busy";
		}

		if (msg.connectiontype == "dhcp") {
			if (msg.dhcpstate == 5)
				status = "online";
			else
				status = "offline";
		}

		beos.sendMessage(beos.globals.kWagnerSig, "cpql",
			"led", "string", "connect",
			"state", "string", status == "online" ? "on" : "off");

		beos.globals.cnxn = status;    
		// TODO dsandler: implement notification of connection status
		var tabs = find_frame(beos.globals.framenames.navbar);
		if (tabs != null && tabs.be_ShowCnxnStatus != null)
			tabs.be_ShowCnxnStatus();
	}

	beos.globals.message_handlers['$KEY'] = function be_handle_dollarKEY(msg) {
		be_special_key(msg.keyname);
	}
	
	// Handler: ouui: "open URL in UI"
	// changes the location of ANY frame in the entire UI.  Crazy!  (and dangerous.)
	beos.globals.message_handlers['ouui'] = function be_handle_ouui(msg) {
		// this is a hichly sensitive call.  We *really* need security here.
		if (msg.groupid == null || msg.groupid != 0) {
			beos.dprintf("ouui: denying request: bad security group (" + msg.groupid + ")!");
			return;
		}

		var frame = null;
		frame = beos.realTop.find_frame(msg.target);
		
		// if no such frame exists, we're supposed to open a new window
		if (frame == null) {
			beos.dprintf("ouui: couldn't find target frame <<" + msg.target + ">>.");
		} else {
			frame.location.href = msg.url;
		}
	}

	// Handler: jsev "JavaScript eval"
	// Run arbitrary JavaScript code and output the result, if any.
	beos.globals.message_handlers['jsev'] = function be_handle_jsev(msg) {
		// this is a hichly sensitive call.  We *really* need security here.
		if (msg.groupid == null || msg.groupid != 0) {
			beos.dprintf("jsev: denying request: bad security group (" + msg.groupid + ")!");
			return;
		}
		
		beos.dprintf('jsev: eval result: <<' + eval(msg.code) + '>>');
	}
	
	beos.globals.message_handlers['olre'] = 
	beos.globals.message_handlers['ourl'] = function be_handle_ourl(msg) {
		// Don't allow unsecure sources to link to local content
		msg.printToStream();
		if ((msg.groupid == null || msg.groupid != 0)
			&& (msg.url.substr(0, 4) == "file" || msg.url.substr(0, 4) == "beos")) {
			beos.dprintf("ourl error: bad group ID (" + msg.groupid + ")!");
			return;
		}
		
		if ( beos.globals.modes.Get("application") != "web" ) {
			// We're on a settings page.  Note that I don't check the
			// frame target.  Doesn't matter anyway, there aren't frames below the
			// content area anyway.
			beos.globals.mainwin_url = msg.url;
			beos.globals.mainwin_need_src = 1;
			beos.globals.subwin_url = "";
			beos.realTop.be_goto_browse();
		} else {
			var content = beos.realTop.be_content();
			if (msg.target == null || msg.target == "" || msg.target == "_top") {
				// no target, reload entire content area
				beos.globals.mainwin_url = msg.url;
				if (content != null && beos.globals.subwin_url == "")
					content.location.href = msg.url;
				else {
					beos.globals.subwin_url = "";
					beos.globals.mainwin_need_src = 1;
					beos.realTop.be_reload();
				}
			} else {
				// Targeted a frame
				var frame = null;
				if ( beos.globals.features.Get("web:subwindow") ) {
					frame = beos.realTop.find_descendent_frame(
						beos.realTop.be_subwindow(),
						msg.target);
				}
				if (frame == null) {
					frame = beos.realTop.find_descendent_frame(
						beos.realTop.be_content(), msg.target);
				}
				// if no such frame exists, we're supposed to open a new window
				if (frame == null) {
					beos.dprintf("couldn't find target frame <<" + msg.target + ">>.");
					open_window(msg.target, msg.url,
						msg.messenger, msg.requestID, 1000, 1000);
				} else {
					frame.location.href = msg.url;
				}
			}
		}
	}

	beos.globals.message_handlers['otop'] = function be_handle_otop(msg) {
		beos.realTop.location.href = msg.url;
	}

	beos.globals.message_handlers['back'] = function be_handle_back(msg) {
		beos.realTop.be_back();
	}

	beos.globals.message_handlers['forw'] = function be_handle_forw(msg) {
		beos.realTop.be_forward();
	}

	beos.globals.message_handlers['home'] = function be_handle_home(msg) {
		beos.realTop.be_goto_home();
	}
	
	beos.globals.message_handlers['nurl'] = function be_handle_nurl(msg) {
		// msg.printToStream();
		var c;
		if ( beos.globals.modes.Get("application") == "web" ) {
			var thetop = beos.realTop; 
			
			if (thetop && thetop.be_content && (c = thetop.be_content())) {
				// We still check to see if the content area has changed, because this
				// might be a notification from a sub frame.
				if (beos.globals.old_content != c.location.href) {
					var navbar = be_navbar();

					beos.globals.old_content = c.location.href;
					beos.globals.mainwin_url = c.location.href;

					// Note that we don't put the URLs of local files because it looks messy
					if (beos.globals.old_content.substr(0, 4) != "file")
						beos.globals.displayed_url = c.location.href;
					else
						beos.globals.displayed_url = "";
							
					// Note: important to check for null, otherwise this will
					// think it has updated the url when it couldn't, and the
					// location area will be blank.
					if (navbar != null 
						&& navbar.SetURLText != null) {
						navbar.SetURLText(beos.globals.displayed_url);
					}
				}
				if (beos.globals.mainwin_title != c.document.title) {
					// new for title-display
					beos.globals.mainwin_title = c.document.title;

					var titlebar = find_frame(beos.globals.framenames.title);
					if ( titlebar != null && titlebar.titleBar != null ) {
						beos.sendMessage(titlebar.titleBar, 'uSTT',
							'status_text', 'string', beos.globals.mainwin_title);
					}
				}
			}
		}
	} // end of nurl handler
}



// be_msg_rcvd(msg)
// BMessage dispatch.
// Checks if message_handlers[msg.what] exists; if so, runs that function
// otherwise uses its case statement
function be_msg_rcvd(msg)
{
	var message_handlers = beos.globals.message_handlers;
	if (message_handlers != null && message_handlers[msg.what] != null) {
		message_handlers[msg.what](msg);
	} else {
		// 'dock' 		// add dockable MediaBar
		// 'mary' 		// remove dockable MediaBar
		// 'idle' 		// no www_content loading.
		// 'busy' 		// www_content data is loading.
		// 'opnw' 		// open new window
		// 'clsw' 		// close named window
		// 'shwk'		// show softkeyboard
		// 'hidk'		// hide softkeyboard
		// 'togk'		// toggle softkeyboard
		// 'qNCI'		// network event
		// '$KEY'		// special key handler
		// 'olre'		// open URL in web content
		// 'ourl'		// open URL in web content
		// 'otop'		// open URL as the root BeIA interface
		// 'back'		// go back in web content
		// 'forw'		// go forward in web content
		// 'home'		// go to web homepage in web content
		// 'nurl'		// A new url is displaying.  Update toolbar location
		
		if ( beos.globals.last_unknown_message == ("what:" + msg.what) ) {
			beos.dprintf("repeated unknown message: what='" + msg.what + "'");
		} else {	
			beos.dprintf("unknown message received: what='" + msg.what + "'");
			msg.printToStream();
			beos.globals.last_unknown_message = ("what:" + msg.what);
		}
	}
}

beos.messageReceived = be_msg_rcvd;

// LEGACY: setTimeout("be_timer();", 1000);

// ---- debugging code -----

function debug()
{
	var i;
	var s = "";
	for(i = 0; i < arguments.length; i++) s = s + arguments[i];
	//beos.sendMessage("application/listener", "TEXT", "text", "string", s);
	beos.dprintf("debug>> " + s)
}

function dump_frames(win,prefix)
{
	var i;
	beos.dprintf("dumping frames of window " + (null==win?'null':win));
	//top.debug(prefix,"[",win.name,"] (",win.frames.length," frames)");
	top.debug(prefix,"[",win.name,"] (",win.frames.length," frames)");
	for(i=0;i<win.frames.length;i++) dump_frames(win.frames[i],prefix + "    ");
}


