function ValidatePicture(sId, sPicture, bCompletePicture)
{
	var sValue;
	var sOutValue;
	var iValueIndex;
	var cValueChar;
	var iPictureIndex;
	var cPictureChar;
	var cNextPictureChar;
	var cNewChar;
	var bStick;
	var bFail;
	
	sValue = document.all[sId].value;
	if(0 < sValue.length && 0 < sPicture.length)
	{
		sOutValue = "";
		iValueIndex = 0;
		cValueChar = sValue.charAt(iValueIndex);
		iPictureIndex = 0;
		cPictureChar = sPicture.charAt(iPictureIndex);
		cNextPictureChar = iPictureIndex < sPicture.length ? sPicture.charAt(iPictureIndex + 1) : '\0';
		bFail = false;

//		while(!bFail && iValueIndex < sValue.length && iPictureIndex < sPicture.length)
		while(iValueIndex < sValue.length && iPictureIndex < sPicture.length)
		{
			bStick = false;
			switch (cPictureChar)
			{
				case 'a':
				case 'A':
				case 'x':
				case 'X':
				case '0':
				case '?':
					cNewChar = TestCharacter(cValueChar, cPictureChar);
					if(cNewChar != '\0')
					{
						iValueIndex++;
						cValueChar = iValueIndex < sValue.length ? sValue.charAt(iValueIndex) : '\0';

						sOutValue += cNewChar;
						bStick = cNextPictureChar == '+' || cNextPictureChar == '@';
					}
					else
					{
						if(cNextPictureChar == '+' || cNextPictureChar == '@')
						{
							iPictureIndex++;
							cPictureChar = cNextPictureChar;
							cNextPictureChar = iPictureIndex < sPicture.length ? sPicture.charAt(iPictureIndex + 1) : '\0';
						}
						else
						{
							iValueIndex++;
							cValueChar = iValueIndex < sValue.length ? sValue.charAt(iValueIndex) : '\0';
							bFail = true;
						}
					}
					break;
				case '\\':
					if(cNextPictureChar == '\0')
					{
						bFail = true;
					}
					else
					{
						if(cValueChar == cNextPictureChar)
						{
							iValueIndex++;
							sOutValue += cNextPictureChar;
							cValueChar = iValueIndex < sValue.length ? sValue.charAt(iValueIndex) : '\0';

							iPictureIndex++;
							cPictureChar = cNextPictureChar;
							cNextPictureChar = iPictureIndex < sPicture.length ? sPicture.charAt(iPictureIndex + 1) : '\0';
						}
					}
					break;
				default:
					if(cValueChar == cPictureChar)
					{
						iValueIndex++;
						sOutValue += cValueChar;
						cValueChar = iValueIndex < sValue.length ? sValue.charAt(iValueIndex) : '\0';
					}
			}
			
			if(!bStick && cNextPictureChar != '\0')
			{
				iPictureIndex++;
				cPictureChar = cNextPictureChar;
				cNextPictureChar = iPictureIndex < sPicture.length ? sPicture.charAt(iPictureIndex + 1) : '\0';
			}
		}

		bStick = true;
		while(bStick && iPictureIndex < sPicture.length)
		{
			switch (cPictureChar)
			{
				case 'a':
				case 'A':
				case 'x':
				case 'X':
				case '0':
				case '?':
					bStick = false;
					break;
				case '\\':
					if(cNextPictureChar == '\0')
					{
						bStick = false;
					}
					else
					{
						iPictureIndex++;
						cPictureChar = cNextPictureChar;
						cNextPictureChar = iPictureIndex < sPicture.length ? sPicture.charAt(iPictureIndex + 1) : '\0';
						sOutValue += cPictureChar;
					}
					break;
				default:
					sOutValue += cPictureChar;				
			}
			
			if(cNextPictureChar != '\0')
			{
				iPictureIndex++;
				cPictureChar = cNextPictureChar;
				cNextPictureChar = iPictureIndex < sPicture.length ? sPicture.charAt(iPictureIndex + 1) : '\0';
			}
		}

		if(document.all[sId].value != sOutValue) 
		{
			document.all[sId].value = sOutValue;
		}
		return !bFail && (!bCompletePicture || iValueIndex == sValue.length && iPictureIndex == sPicture.length);
	}
	else
	{
		return true;
	}
}

function TestCharacter(cValueChar, cPictureChar)
{
	switch (cPictureChar)
	{
		case 'a':
			return ('a' <= cValueChar && cValueChar <= 'z' ) || ('A' <= cValueChar && cValueChar <= 'Z' ) ? cValueChar : '\0';
			break;
		case 'A':
			return ('A' <= cValueChar && cValueChar <= 'Z' ) ? cValueChar : (('a' <= cValueChar && cValueChar <= 'z' ) ? cValueChar.toUpperCase() : '\0');
			break;
		case 'x':
			return ('a' <= cValueChar && cValueChar <= 'z' ) || ('A' <= cValueChar && cValueChar <= 'Z' ) || ('0' <= cValueChar && cValueChar <= '9' ) ? cValueChar : '\0';
			break;
		case 'X':
			return ('A' <= cValueChar && cValueChar <= 'Z' ) || ('0' <= cValueChar && cValueChar <= '9' ) ? cValueChar : ('a' <= cValueChar && cValueChar <= 'z' ) ? cValueChar.toUpperCase() : '\0';
			break;
		case '0':
			return ('0' <= cValueChar && cValueChar <= '9' ) ? cValueChar : '\0';
			break;
		case '?':
			return cValueChar;
			break;
	}
	return '\0';
}
