// 下ごしらえ

var bNoFrame = false;
if (getParam("noframe") == "1")
	bNoFrame = true;


// ユーティリティ

function addEvent(element, eventType, fn) {
    if (element.addEventListener) {
        element.addEventListener(eventType, fn, false);
    }
    else if (element.attachEvent) {
        var r = element.attachEvent('on' + eventType, fn);
    }
    else {
        element['on' + eventType] = fn;
    }
}

function getEventTarget(e)
{
	if (defined(e.target))
		return e.target;
	else if (defined(e.srcElement))
		return e.srcElement;
	return null;
}

function defined(v)
{
    if (typeof(v) == "undefined")
        return false;
    return true;
}

function getParam(name)
{
	var param = location.search.substring(1);
	var params = param.split("&");
	for (var i = 0; i < params.length; i++)
	{
		if (params[i].substr(0, name.length) == name &&
			params[i].charAt(name.length) == '=')
		{
			return params[i].substr(name.length+1);
		}
	}
	return null;
}

function enCER(str)
{
	var cerTable = 
	{
				" " : "&nbsp;",
				"<" : "&lt;",
				">" : "&gt;",
				"\"" : "&quot;",
				"&" : "&amp;"
	};
	
	return str.replace(/([ <>\"&])/g, 
		function(whole, char)
		{
			return cerTable[char];
		});
}


// フレーム

function writeFrameSet(chap)
{
	var hash = "";
	
	{
	    var param = location.search.substring(1);
	    var params = param.split("&");
	    var topic = null;
	    
	    for (var i = 0; i < params.length; i++)
	    {
	        if (params[i].substr(0, 6) == "topic=")
	        {
	            topic = params[i].substr(6);
	        }
	    }
	
	    if (topic)
	        hash = "#" + topic;
	}
	
	document.writeln('<frameset cols="350,*">');
	document.writeln('    <frame src="program.html?chap=' +  chap + '" id="framep" name="framep">');
	document.writeln('    </frame>');
	document.writeln('    <frame src="chapter' + chap + '.html' + location.search + hash + '" id="framec" name="framec">');
	document.writeln('    </frame>');
	document.writeln('</frameset>');
}

// 内容

function setupLineRef()
{
	if (!bNoFrame)
	{
		var ar = document.getElementsByTagName("span");
		if (ar)
		{
			for (var i = 0; i < ar.length; i++)
			{
				var elem = ar[i];
				if (elem.className == "lineref")
				{
					addEvent(elem, "mousemove", onMouseMoveLineRef);
					addEvent(elem, "mouseout", onMouseOutLineRef);				
				}
			}
		}
	}
}

function setupGoogleLink()
{
	var ar = document.getElementsByTagName("a");
	if (ar)
	{
		for (var i = 0; i < ar.length; i++)
		{
			var elem = ar[i];
			if (elem.className == "googlelink")
			{
				elem.target = "_blank";
				elem.href = "http://www.google.co.jp/search?hl=ja&q=" + encodeURIComponent('"' + elem.innerHTML + '"') + "&lr=lang_ja";
			}
		}
	}
}

function onMouseMoveLineRef(e)
{
	var elem = getEventTarget(e);
	markProgLines(elem.innerHTML, true);
}

function onMouseOutLineRef(e)
{
	var elem = getEventTarget(e);
	markProgLines(elem.innerHTML, false);
}

function markProgLines(str, mark)
{
	var ar = str.match(/(\d+)/g);
	if (ar.length == 0)
		return;
		
	var startline = ar[0] - 0;
	var endline = startline;
	if (ar.length > 1)
		endline = ar[1] - 0;
		
	for (var i = startline; i <= endline; i++)
	{
		var elem = top.framep.document.getElementById("progline" + i);
		if (elem)
			elem.style.backgroundColor = mark ? "#FFFF00" : "#FFFFFF";
		else 
			break;
		elem = top.framep.document.getElementById("proglno" + i);
		if (elem)
			elem.style.color = mark ? "#FF0000" : "#0000FF";
		else 
			break;
	}
			
}

// 内容ページのボディサイズ

function bodyOnLoad()
{
	setupLineRef();
	setupGoogleLink();
	bodyOnResize(); 
}

function bodyOnResize()
{
    setWidth();
}

function setWidth()
{
    var body1 = document.getElementById("body1");
    var page1 = document.getElementById("page1");
    var width = getClientWidth();
    width = Math.min(width, 600);

   	page1.style.width = "" + (width - 12) + "px";
}

function getClientWidth()
{
    if (defined(document.documentElement) && defined(document.documentElement.clientWidth))
    {
        return document.documentElement.clientWidth;
    }
    else if (defined(document.body) && defined(document.body.clientWidth))
    {
        return document.body.clientWidth;
    }
    else if (defined(window.innerWidth))
    {
        return window.innerWidth;
    }
    else 
        return 600;
}

// 拡張・縮退

function ExpandBlock(titleId, contentId, titleShrunk, titleExpanded, initiallyExpanded)
{
	this.onClick = function()
	{
		this.expanded = !this.expanded;
		this.expandOrShrink();
		return false;
	}
	
	this.expandOrShrink = function()
	{
		var elemTitle = document.getElementById(this.titleId);
		if (elemTitle)
			elemTitle.innerHTML = this.expanded ? this.titleExpanded : this.titleShrunk;
			
		var elemContent = document.getElementById(this.contentId);
		if (elemContent)
		{
			if (this.expanded)
			{
				elemContent.style.position = "relative";
				elemContent.style.visibility = "visible";
			}
			else 
			{
				elemContent.style.visibility = "hidden";
				elemContent.style.position = "absolute";
			}
		}
	}
	
	// コンストラクタ
	this.titleId = titleId;
	this.contentId = contentId;
	this.titleShrunk = titleShrunk;
	this.titleExpanded = titleExpanded;
	this.expanded = initiallyExpanded;
	this.expandOrShrink();
}


function writeProg(ar)
{
	for (var i = 0; i < ar.length; i++)
	{
		// コメントを分ける
		var parser = new CaslTokenParser(ar[i]);
	
		document.write(enCER(parser.statement));
		if (parser.comment.length > 0)
		{
			document.write('<span style="color: #008000">');
			document.write(enCER(parser.comment));
			document.write('</span>');
		}
		
		document.write('<br />');
	}
}

function CaslTokenParser(line)
{
	var pos = findCommentStartPos(line);
	if (pos >= 0)
	{
		this.statement = line.substring(0, pos);
		this.comment = line.substring(pos);
	}
	else
	{
		this.statement = line;
		this.comment = "";
	}
}

function findCommentStartPos(line)
{
	var n = line.length;
	if (n == 0)
		return -1;
	
	var i = 0;
	for (var field = 0; field < 3; field++)
	{
		// 最初のスペースが出るまでがラベル・命令・オペランド
		var inQuote = false;
		for (; i < n; i++)
		{
			var c = line.charAt(i);
			if (c == '\'')
				inQuote = !inQuote;
			else if (c == ';')
			{
				if (!inQuote)
					return i;
			}
			else if (c == ' ')
			{
				if (!inQuote)
					break;
			}
		}
		
		if (i >= n)
			return -1;
		
		// スペースをスキップ
		for (; i < n; i++)
		{
			var c = line.charAt(i);
			if (c == ';')
				return i;
			else if (c != ' ')
				break;
		}
		if (i >= n)
			return -1;
	}
	return i;
}
	
// メールアドレスへのリンクを書く
function writeMailAddressWithName(domain, name, displayname)
{
	var mailaddress = name + "\u0040" + domain;
	
	document.write('<a href="mailto:' + mailaddress + '">' + displayname + " &lt;" + mailaddress + "&gt;" + '</a>');
}

