function onSubmit_PwcForms(form)
{
	var t1 = new Date().getTime();

	var g = function(id) {return document.getElementById(id);};

	// (使用)文字
	var codeTable = "";
	{
		var abstractCodeTable = "";

		var es = myDocument.getElementsById(
			new RegExp("^pwcCharacter[A-Za-z]+$"), g("pwcCharacterGroup"));
		for (var i = 0, n = es.length; i < n; i++) {
			if (es[i].checked) {
				abstractCodeTable += es[i].value;
			}
		}

		if (abstractCodeTable == "") {
			// ERROR
			alert("[文字]を一つ以上選択して下さい．");
			return false;
		}

		codeTable = parseAbstractString(abstractCodeTable, true, true);

		if (codeTable == "" || codeTable === void 0) {
			// ERROR
			alert("[文字]が不正です．");
			return false;
		}
	}

	// 文字数
	var passwordLength = -1;
	{
		var e;
		if (0) {
		} else if ((e = g("pwcLength4")).checked) {
			passwordLength = parseInt(e.value);
		} else if ((e = g("pwcLength8")).checked) {
			passwordLength = parseInt(e.value);
		} else if ((e = g("pwcLength16")).checked) {
			passwordLength = parseInt(e.value);
		} else if ((e = g("pwcLength32")).checked) {
			passwordLength = parseInt(e.value);
		} else if ((e = g("pwcLengthX")).checked) {
			var p = g("pwcLengthXValue").value;

			if (p == "" || isNaN(p)) {
				// ERROR
				alert("[文字数]を正しく入力して下さい．\n"
					+ "[文字数]に数字以外の文字が入力されました．");
				g("pwcLengthXValue").select();
				return false;
			}

			passwordLength = parseInt(p);

			if (passwordLength < 1) {
				// ERROR
				alert("[文字数]を正しく入力して下さい．\n"
					+ "[文字数]に数字以外の文字が入力されました．");
				g("pwcLengthXValue").select();
				return false;
			}
		} else {
			alert("Internal Error!@length");
			return false;
		}
	}

	// 生成個数
	var rowCount = 0, colCount = 0;
	{
		if (0) {
		} else if (g("pwcCount1").checked) {
			rowCount = 1;
			colCount = 1;
		} else if (g("pwcCount10").checked) {
			rowCount = 1;
			colCount = 10;
		} else if (g("pwcCount50").checked) {
			rowCount = 10;
			colCount = 5;
		} else if (g("pwcCount100").checked) {
			rowCount = 10;
			colCount = 10;
		} else if (g("pwcCountX").checked) {
			var p0 = g("pwcCountXValue0").value;
			var p1 = g("pwcCountXValue1").value;

			if (p0 == "" || isNaN(p0)) {
				// ERROR
				alert("[生成個数]を正しく入力して下さい．\n"
					+ "[生成個数]に数字以外の文字が入力されました．");
				g("pwcCountXValue0").select();
				return false;
			}
			if (p1 == "" || isNaN(p1)) {
				// ERROR
				alert("[生成個数]を正しく入力して下さい．\n"
					+ "[生成個数]に数字以外の文字が入力されました．");
				g("pwcCountXValue1").select();
				return false;
			}

			rowCount = parseInt(p0);
			colCount = parseInt(p1);

			if (rowCount < 1) {
				// ERROR
				alert("[生成個数]を正しく入力して下さい．\n"
					+ "[生成個数]に負数が入力されました．");
				g("pwcCountXValue0").select();
				return false;
			}
			if (colCount < 1) {
				// ERROR
				alert("[生成個数]を正しく入力して下さい．\n"
					+ "[生成個数]に負数が入力されました．");
				g("pwcCountXValue1").select();
				return false;
			}
		} else {
			alert("Internal Error!@count");
			return false;
		}
	}

	// 強度
	var passwordGeneratingStrategy = null;
	{
		if (0) {
		} else if (g("pwcStrengthNormal").checked) {
			passwordGeneratingStrategy = normalPasswordGeneratingStrategy;
		} else if (g("pwcStrengthSecure1").checked) {
			if (passwordLength < 3) {
				// ERROR
				alert("[文字数]を" + 3 + "以上に設定して下さい．");
				g("pwcLengthXValue").select();
				return false;
			}
			passwordGeneratingStrategy = safetyPasswordGeneratingStrategy;
		} else if (g("pwcStrengthSecure2").checked) {
			if (passwordLength < 4) {
				// ERROR
				alert("[文字数]を" + 4 + "以上に設定して下さい．");
				g("pwcLengthXValue").select();
				return false;
			}
			passwordGeneratingStrategy = strongPasswordGeneratingStrategy;
		} else {
			// ERROR!
			alert("Internal Error!@strength");
			return false;
		}
	}

	// 擬似乱数生成アルゴリズム
	var randomNumberGenerator = null;
	{
		if (0) {
		} else if (g("pwcRandomGeneratorDefault").checked) {
			randomNumberGenerator = Math.random;
		} else if (g("pwcRandomGeneratorMT").checked) {
			randomNumberGenerator = Math.mersenneTwisterRandom;
		} else {
			// ERROR!
			alert("Internal Error!@generator");
			return false;
		}
	}

	createPasswordTable(
		passwordGeneratingStrategy,
		codeTable,
		passwordLength,
		randomNumberGenerator,
		rowCount,
		colCount);


	var t2 = new Date().getTime();

	// 生成までに要した時間の表示
	{
		var timeString = (Math.floor((t2 - t1) / 10) / 100).toString();
		g("pwcTime").innerHTML = timeString + "sec";
	}

	return false;
}

function setDescription()
{
	var g = function(id) {return document.getElementById(id);};

	g("Id405").title = "生成するパスワードに使用する文字を指定します．";
	g("Id410").title = "パスワードに，半角数字(\"012...9\")を使用します．";
	g("Id420").title = "パスワードに，半角アルファベット大文字(\"ABC...XYZ\")を使用します．";
	g("Id430").title = "パスワードに，半角アルファベット小文字(\"abc...xyz\")を使用します．";
	g("Id440").title = "パスワードに，\"_\"を使用します．";
	g("Id450").title = "パスワードに，半角スペース\" \"を使用します．";
	g("Id460").title = "パスワードに，印刷可能なASCII記号文字(\"@=^+\"など)を使用します．";
	g("Id465").title = "生成するパスワードの文字数を指定します．";
	g("Id470").title = "4文字のパスワードを生成します．";
	g("Id480").title = "8文字のパスワードを生成します．";
	g("Id490").title = "16文字のパスワードを生成します．";
	g("Id500").title = "32文字のパスワードを生成します．";
	g("Id510").title = "指定した文字数のパスワードを生成します．1以上の任意の数字を指定します．ただし，[強度]に\"Safety\"または\"High Security\"を指定しているとき，制限があります．";
	g("Id515").title = "生成するパスワードの個数を指定します．";
	g("Id520").title = "パスワードを1個生成します．";
	g("Id530").title = "パスワードを10個生成します．";
	g("Id540").title = "パスワードを50個生成します．";
	g("Id550").title = "パスワードを100個生成します．";
	g("Id560").title = "指定した個数のパスワードを生成します．生成するパスワードの個数を[縦方向個数]×[横方向個数]で指定します．パスワードの総数は[縦方向個数]×[横方向個数]個です．";
	g("Id565").title = "生成するパスワードの強度を指定します．強度の強いパスワードほど安全です．";
	g("Id570").title = "指定した[文字]をランダムに使用してパスワードを生成します．";
	g("Id580").title = "数字/大文字/小文字のそれぞれについて少なくとも1文字含みます．[文字数]を3以上に設定します．0-9A-Za-zの文字を使用します．";
	g("Id590").title = "数字/大文字/小文字/記号のそれぞれについて少なくとも1文字含みます．[文字数]を4以上に設定します．0-9A-Za-z!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~の文字を使用します．";
	g("Id595").title = "擬似乱数生成アルゴリズムを指定します．通常は\"Default\"を選択します．";
	g("Id600").title = "擬似乱数生成にビルトインの Math.random を使用し，高速にパスワードを生成します．";
	g("Id610").title = "擬似乱数生成にメルセンヌ・ツイスタ法を使用し，高品質なパスワードを生成します．";
	g("pwcSubmit").title = "設定したパラメータをもとにパスワードを生成します．";
//	g("pwcSubmit").value = "パスワード生成";
	g("pwcReset").title = "パラメータをリセットします．確認のダイアログは表示しませんので，ご注意下さい．";
//	g("pwcReset").value = "リセット";
}

window.onload = function() {
	var g = function(id) {return document.getElementById(id);};

	setDescription();

	g("pwcParameters").onsubmit = function() {
		return onSubmit_PwcForms(this);
	};
	g("pwcParameters").onreset = function() {
		window.setTimeout(function() {g("pwcStrengthGroup").action()}, 1);
		return true;
	};

	g("pwcLengthX").onclick = function() {
		g("pwcLengthXValue").focus();
	};
	{
		g("pwcLengthXValue").onfocus = function() {
			this.select();
		};
		g("pwcLengthXValue").onclick = function() {
			g("pwcLengthX").checked = true;
		};
	}

	g("pwcCountX").onclick = function() {
		g("pwcCountXValue0").focus();
	};
	{
		g("pwcCountXValue0").onfocus = function() {
			this.select();
		};
		g("pwcCountXValue0").onclick = function() {
			g("pwcCountX").checked = true;
		};
	}
	{
		g("pwcCountXValue1").onfocus = function() {
			this.select();
		};
		g("pwcCountXValue1").onclick = function() {
			g("pwcCountX").checked = true;
		};
	}

	g("pwcStrengthGroup").action = function() {
		var checked = false
			|| g("pwcStrengthSecure1").checked
			|| g("pwcStrengthSecure2").checked;

		var es = myDocument.getElementsById(
			new RegExp("^pwcCharacter[A-Za-z]+$"), g("pwcCharacterGroup"));
		for (var i = 0, n = es.length; i < n; i++) {
			es[i].disabled = checked;
		}
	};
	g("pwcStrengthNormal").onfocus = function() {
		var es = myDocument.getElementsById(
			new RegExp("^pwcCharacter[A-Za-z]+$"), g("pwcCharacterGroup"));
		for (var i = 0, n = es.length; i < n; i++)
			es[i].disabled = false;
		return false;
	};
	g("pwcStrengthSecure1").onfocus = function() {
		var es = myDocument.getElementsById(
			new RegExp("^pwcCharacter[A-Za-z]+$"), g("pwcCharacterGroup"));
		for (var i = 0, n = es.length; i < n; i++)
			es[i].disabled = true;
		return true;
	};
	g("pwcStrengthSecure2").onfocus = function() {
		var es = myDocument.getElementsById(
			new RegExp("^pwcCharacter[A-Za-z]+$"), g("pwcCharacterGroup"));
		for (var i = 0, n = es.length; i < n; i++)
			es[i].disabled = true;
		return true;
	};

	g("pwcSubmit").onmouseover = function() {
		this.style.backgroundColor = "#000033";
	};
	g("pwcSubmit").onmouseout = function() {
		this.style.backgroundColor = "#6666cc";
	};

	// URIのクエリ文字列から起動（異常時処理なし）
	// ?c=0-9A-Za-z&l=10&n=10&m=8
	// ?l=10&n=10&m=8&s=2
	var args = getArgs();
	if ((args["c"] !== void 0
			&& args["l"] !== void 0
			&& args["n"] !== void 0
			&& args["m"] !== void 0)
		||
		(args["l"] !== void 0
			&& args["n"] !== void 0
			&& args["m"] !== void 0
			&& args["s"] !== void 0))
	{
		g("TITLE").style.display = "none";
		g("TITLE").innerHTML = "";
		g("DESCRIPTION").innerHTML = "";
		g("pwcUserParameters").innerHTML = "";
		g("PASSWORDS").innerHTML = "";
		g("COPYRIGHT").style.display = "none";
		g("COPYRIGHT").innerHTML = "";

		var codeTable = "";

		if (args["c"] !== void 0) {
			codeTable = parseAbstractString(args["c"]);
		}

		var passwordLength = parseInt(args["l"]);

		var rowCount = parseInt(args["n"]);
		var colCount = parseInt(args["m"]);

		var passwordGeneratingStrategy = normalPasswordGeneratingStrategy;

		if (args["s"] !== void 0) {
			switch (parseInt(args["s"])) {
			case 1:
				passwordGeneratingStrategy = normalPasswordGeneratingStrategy;
				break;
			case 2:
				passwordGeneratingStrategy = safetyPasswordGeneratingStrategy;
				if (passwordLength < 3) {
					alert("l を" + 3 + "以上に設定して下さい．");	// ERROR
					return;
				}
				break;
			case 3:
				passwordGeneratingStrategy = strongPasswordGeneratingStrategy;
				if (passwordLength < 4) {
					alert("l を" + 4 + "以上に設定して下さい．");	// ERROR
					return;
				}
				break;
			default:
				// TODO: Warning
				passwordGeneratingStrategy = normalPasswordGeneratingStrategy;
				break;
			}
		}

		var randomNumberGenerator = Math.random;

		createPasswordTable(
			passwordGeneratingStrategy,
			codeTable,
			passwordLength,
			randomNumberGenerator,
			rowCount,
			colCount
		);

		return;
	}

	g("pwcStrengthGroup").action();

	g("DESCRIPTION").style.display = "block";
	g("pwcUserParameters").style.display = "block";

	onSubmit_PwcForms(g("pwcParameters"));
};



function createPasswordTable(
	passwordGeneratingStrategy,
	codeTable,
	passwordLength,
	randomNumberGenerator,
	rowCount,
	colCount)
{
	var markups = new Array();

	markups.push("<div align=\"center\">"
		+ "<table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n");

	var cellTag = rowCount == 1 && colCount == 1
		? "<td class=\"one\">" : "<td>";

	var cache = new Object();

	for (var i = 0; i < rowCount; i++) {
		markups.push("<tr>");
		for (var j = 0; j < colCount; j++) {
			var password = passwordGeneratingStrategy(
					codeTable, passwordLength, randomNumberGenerator, cache);
			markups.push(cellTag + adjustText(password) + "</td>");
		}
		markups.push("</tr>\n");
	}

	markups.push("</table></div>");

	document.getElementById("PASSWORDS").innerHTML = markups.join("");
}



function normalPasswordGeneratingStrategy(
	codeTable,
	passwordLength,
	randomNumberGenerator,
	cache)
{
	return generateRandomString(
		codeTable,
		passwordLength,
		randomNumberGenerator,
		cache
	);
}

function safetyPasswordGeneratingStrategy(
	codeTable,
	passwordLength,
	randomNumberGenerator,
	cache)
{
	return generateSafetyPassword(
		passwordLength,
		randomNumberGenerator,
		cache
	);
}

function strongPasswordGeneratingStrategy(
	codeTable,
	passwordLength,
	randomNumberGenerator,
	cache)
{
	return generateStrongPassword(
		passwordLength,
		randomNumberGenerator,
		cache
	);
}




