/**
 *********************************************************************************
 *
 * Chess PGN Reader
 * Merci à Ray Wilson qui a écrit le programme original en JavaScript
 * Je l'ai ré-écrit pour :
 *		- utiliser class/method en remplacement des globales
 *		- séparer l'analyse pgn/échecs de la gestion du graphisme
 *		- et d'autres ajouts
 *
 * I use it because my own program (written in Java) is not as simple to translate.
 *
 *
 * Version 2.0 17/04/2008
 * l'analyse PGN est maintenant réalisée dans du PHP
 * c'est beaucoup plus rapide et moins dépendant du navigateur
 *
 * Version 1.0 15/05/2006
 * écrire directement dans les "DIV"
 * gérer plusieurs parties dans le même pgn (ou plusieurs pgn)
 * filtrer les caractères accentués pour affichage html.
 * boutons pour avancer, reculer, ...
 * traduire la notation en français,
 * lien pour revenir au site normal
 * scroll fenêtre pour afficher le coup joué (firefox)
 * afficher les informations "tag"
 * promotion
 *
 *
 * Todo :
 *
 * boutons pour entrer / sortir dans les variantes
 *
 *
 *********************************************************************************
 */


/*
 *********************************************************************************
 * global vars
 *********************************************************************************
 */
var Version= "2.0";
var VersionDate= "17/04/2008";


/* vérifier si tout ça est toujours nécessaire */
var globalsFiles = "abcdefgh";
var globalsRanks = "12345678";

var	King= "K";
var	Queen= "Q";
var	Bishop= "B";
var	Knight= "N";
var	Rook= "R";
var	Pawn= "P";
var	White= "W";
var	Black= "B";
var	NoColor= ".";
var	Empty= ".";

var PgnPiecesNames= "KQBNR";
var PgnPiecesFrench= "RDFCT";
var WPieces= PgnPiecesNames + "P";
var BPieces= WPieces.toLowerCase();
var BWPieces= WPieces + BPieces;

var globalGraphicBoard;
var url_base= '.';
var alertOk= 0;
var traceOk= 0;

var initOK= 0;
var pgnOK= 0;
var uriMemo= new Array();



/*
 *********************************************************************************
 * Special functions
 *********************************************************************************
 */
function traceAlert(str) {
	if (alertOk)
		alert(str);
	if (traceOk)
		document.write('<br>'+str);
}

function startTrace() {
	if (traceOk)
	document.writeln("<font face=\"courier new\">");
	trace("PASSAGE EN MODE TRACE");
}

function stopTrace() {
	trace("QUITTER LE MODE TRACE");
	if (traceOk)
	document.writeln("</font>");
}

function traceString(str) {
	if (traceOk)
	document.write(str);
}

function traceNL(str) {
	traceString("<br>");
}

function trace(str) {
	traceString(str);
	traceNL("<br>");
}

function traceError(str) {
	traceString("ERROR: ");
	traceString(str);
	traceNL("<br>");
}

/*
 *********************************************************************************
 * File access
 *********************************************************************************
 */
function getFile(pUrl) {
	var	xmlhttp;
	var	str;
	if (window.XMLHttpRequest) { // code for Mozilla, Safari, etc
		xmlhttp=new XMLHttpRequest();
		// xmlhttp.onreadystatechange=postFileReady;
		xmlhttp.open("GET", pUrl, false);	// false = synchrone
		xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		xmlhttp.send(null);
	} else if (window.ActiveXObject) { //IE
		xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');
		if (xmlhttp) {
			// xmlhttp.onreadystatechange=postFileReady;
			xmlhttp.open('GET', pUrl, false);	// false = synchrone
			xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			xmlhttp.send();
		}
	}
	if (xmlhttp.readyState==4) {
		if (xmlhttp.status==200) {
			str= xmlhttp.responseText;
			// document.getElementById('theDivToLoad').innerHTML=xmlhttp.responseText;
			return str;
		}
	}
	return "";
}

/*
 *********************************************************************************
 * class StringTokenizer
 *********************************************************************************
 */

/*
 * Create StringTokenizer
 */
function StringTokenizer(str) {
	this.setString(str);
	this.lastSep= "";
}

StringTokenizer.prototype.restart= function() {
	this.curPos= 0;
	this.active= 1;
	this.lastPos= 0;
	this.nbtokens= this.tokens.length;
	this.lastString= '';
}

StringTokenizer.prototype.setString= function(str) {
	var pgnString;
	pgnString= str;

	// change html conventions
	// pgnString = pgnString.replace(/&quot;/g,'"');

	// remove all linefeeds, and returns.
	pgnString = pgnString.replace(/[\n\r]/g,"");

	this.tokens= pgnString.split("\t");
	this.restart();
}

StringTokenizer.prototype.unread= function() {
	this.curPos= this.lastPos;
}

StringTokenizer.prototype.hasMoreGame= function() {
	var str;
	var curPos;
	var sep;

	curPos= this.curPos;

	// end of string ?
	if (curPos >= this.nbtokens) return(false);
	return(true);
}

StringTokenizer.prototype.nextToken= function() {
	this.lastPos= this.curPos;
	this.lastStr= this.tokens[this.curPos];
	this.curPos++;
	return this.lastStr;

}

StringTokenizer.prototype.dump= function() {
	var	i;
	var	ascii;
	var	str;
	var	car;

	str= this.pgnString;
	i= 0;
	while ( i<str.length ) {
		car= str.charAt(i);
		switch(car) {
			case '<': car= '&lt;'; break;
			case '>': car= '&gt;'; break;
			case '&': car= '&amp;'; break;
			default:
				ascii= car.charCodeAt(0);
				if (ascii > 127) {
					car= '('+ascii+')';
				}
				break;
		}
		document.write(car);
		i++;
	}
}

/*
 *********************************************************************************
 * class PgnTag
 *********************************************************************************
 */

/*
 * Create PgnTag
 */
function PgnTag(code, value) {
	this.code= code.toLowerCase();
	this.value= value;
}

PgnTag.prototype.getCode= function() {
	return this.code;
}

PgnTag.prototype.getValue= function() {
	return this.value;
}

/*
 *********************************************************************************
 * class PgnMove
 *********************************************************************************
 */

/*
 * Create PgnMove
 */
function PgnMove(game,previousMove) {
	this.id= 0;
	this.var_move_id= 0;
	game.addMove(this);
	this.code= "";
	this.type= "";
	this.color= "";
	this.number= 0;
	this.comment= "";
	this.eval= "";
	this.promotePiece= "";
	this.previousMove= previousMove;
	this.variations= new Array();
	this.board= '';
}

PgnMove.prototype.setCode= function(str) {
	this.code= str;

}

PgnMove.prototype.getCode= function() {
	return this.code;
}

PgnMove.prototype.setBoard= function(str) {
	this.board= str;

}

PgnMove.prototype.getBoard= function() {
	return this.board;
}

PgnMove.prototype.getHtmlCode= function() {
	var str;
	var i;
	str= this.code;
	return str;
}

PgnMove.prototype.setEval= function(str) {
	// if (this.eval.length) this.eval= this.eval + ' ';
	this.eval= this.eval + str + ' ';
}

PgnMove.prototype.setComment= function(str) {
	// this.comment= str;
	this.addComment(str);
}

PgnMove.prototype.setComment2= function(str) {
	this.comment= str;
}

PgnMove.prototype.addComment= function(str) {
	if (this.comment.length) {
		this.comment= this.comment +"<br>"+str;
	} else {
		this.comment= str;
	}
}

/*
 * add variation
 */
PgnMove.prototype.addVariation= function(variation) {
	var nb= this.variations.length;
	this.variations[nb]= variation;
}

/*
 * load pgn
 */
PgnMove.prototype.loadPgn= function(pgn) {
	this.code= pgn.nextToken();
	this.comment= pgn.nextToken();
	this.board= pgn.nextToken();
	this.eval= pgn.nextToken();
	this.type= pgn.nextToken();
	this.color= pgn.nextToken();
	this.moveNumber= pgn.nextToken();
}

/*
 * write move
 */
PgnMove.prototype.writePgn= function(gb,level,startLine) {
	var variation;
	var i, nb;
	var	lineSkipped= false;
	var	needSkip= true;

	if (this.color==White) {
		gb.writeHtml(' '+this.moveNumber+'.');
	} else if (startLine) {
		gb.writeHtml(' '+this.moveNumber+'...');
	}

	gb.writeHtml(' ');
	gb.writeHtml(' <span id="pgn_a_'+this.id+'" class="pgn_pm">');
	// gb.writeHtml('<a alt="'+this.code+'" href="javascript:ViewMove('+this.id+')">');
	gb.writeHtml('<a href="javascript:ViewMove('+this.id+')">');
	gb.writeHtml(this.getHtmlCode());
	gb.writeHtml('</a>');
	if (this.eval.length) {
		gb.writeHtml(' '+this.eval);
	}
	gb.writeHtml('</span>');
	if (this.comment.length) {
		if (needSkip) {
			// gb.writeHtml("<br>");
		}
		gb.writeHtml(' <div class="pgn_pc">');
		gb.writeHtml(this.comment);
		gb.writeHtml("</div>");
		lineSkipped= true;
		needSkip= false;
	}

	if (this.variations.length > 0) {
		i= 0;
		if (needSkip) {
			// gb.writeHtml("<br>");
		}
		while (i < this.variations.length) {
			variation= this.variations[i];
			if (variation.variation) {
				gb.writeHtml(' <div class="pgn_pv">');
			}
			variation.writePgn(gb,level+1);
			if (variation.variation) {
				gb.writeHtml("</div>");
			}
			// gb.writeHtml("<br>");
			i++;
		}
		lineSkipped= true;
		needSkip= false;
	}

	return lineSkipped;
}


/*
 * dump move
 */
PgnMove.prototype.dump= function(level) {
	var variation;
	var i, nb;
	var indent;

	indent= "";
	i= 0;
	while (i < level) {
		indent= indent + " - +";
		i++;
	}

	trace(indent + " : " + this.code + " : Piece="+this.type+"  coords="+this.coords+ " : " + this.comment);

	if (this.variations.length > 0) {
		this.board.dump();
		if (this.code.length>0)	trace(indent + this.variations.length+" Variantes :");
		i= 0;
		while (i < this.variations.length) {
			variation= this.variations[i];
			variation.dump(level+1);
			i++;
		}
	} else {
		// dump board after current move
		// this.board.dump();
	}
}

/*
 *********************************************************************************
 * class PgnVariation
 *********************************************************************************
 */

/*
 * Create PgnVariation
 */
function PgnVariation(game,variation,move) {
	this.parentMove= move;
	this.game= game;
	this.moves= new Array();
	this.comment= '';
	this.postComment= '';
	this.variation= variation;
}

PgnVariation.prototype.setComment= function(str) {
	this.comment= str;
}

PgnVariation.prototype.getComment= function() {
	return this.comment;
}

PgnVariation.prototype.setPostComment= function(str) {
	this.postComment= str;
}

PgnVariation.prototype.getPostComment= function() {
	return this.postComment;
}

/*
 * add move
 */
PgnVariation.prototype.addMove= function(move) {
	var nb= this.moves.length;
	move.variation= this;
	move.var_move_id= nb;
	this.moves[nb]= move;
}

/*
 * load pgn
 */
PgnVariation.prototype.loadPgn= function(pgn) {
	var variation;
	var str;
	var tag, value, code;
	var encore;
	var move, lastMove;

	this.setComment(pgn.nextToken());
	this.setPostComment(pgn.nextToken());

	lastMove= this.parentMove;
	encore= true;
	while (encore) {
		str= pgn.nextToken();
		switch (str) {
			case 'MOVE':
				move= new PgnMove(this.game,lastMove);
				this.addMove(move);
				lastMove= move;
				move.loadPgn(pgn);
				break;

			case 'VARIATION':
				variation= new PgnVariation(this.game,1,lastMove);
				lastMove.addVariation(variation)
				variation.loadPgn(pgn);
				break;

			case 'END':
				encore= false;
				break;

			default:
				traceError("PgnVariation : unknown token '"+str+"'");
				break;

		}
	}
}

/*
 * write game
 */
PgnVariation.prototype.writePgn= function(gb,level) {
	var move;
	var i, nb;
	var indent;
	var lineSkipped;

	indent= "";
	i= 0;
	while (i < level) {
		indent= indent + " - +";
		i++;
	}

	if (this.comment.length>0) {
		gb.writeHtml(' <div class="pgn_pc">');
		gb.writeHtml(this.comment);
		gb.writeHtml("</div>");
	}
	i= 0;
	lineSkipped= true;
	while (i < this.moves.length) {
		move= this.moves[i];
		lineSkipped= move.writePgn(gb,level,lineSkipped);
		i++;
	}

	if (this.postComment.length>0) {
		gb.writeHtml(' <div class="pgn_pc">');
		gb.writeHtml(this.postComment);
		gb.writeHtml("</div>");
	}
}

/*
 * dump game
 */
PgnVariation.prototype.dump= function(level) {
	var move;
	var i, nb;
	var indent;

	indent= "";
	i= 0;
	while (i < level) {
		indent= indent + " - +";
		i++;
	}

	if (this.comment.length>0)	trace(indent + this.comment);
	trace(indent + "Moves :");
	i= 0;
	while (i < this.moves.length) {
		move= this.moves[i];
		move.dump(level);
		i++;
	}

	trace("Final board :");
	move.board.dump();
}

/*
 *********************************************************************************
 * class PgnGame
 *********************************************************************************
 */

/*
 * Create PgnGame
 */
function PgnGame() {
	this.tags= new Array();
	this.moves= new Array();
	this.pgnMain= null;
	this.name= "";
}

/*
 * add piece
 */
PgnGame.prototype.addMove= function(move) {
	var nb= this.moves.length;
	this.moves[nb]= move;
	move.id= nb;
}

/*
 * add tag
 */
PgnGame.prototype.addTag= function(tag) {
	var nb= this.tags.length;
	this.tags[nb]= tag;
}

/*
 * search tag
 */
PgnGame.prototype.searchTag= function(code) {
	var tag;
	var nb= this.tags.length;
	code= code.toLowerCase();
	while (nb > 0) {
		nb--;
		tag= this.tags[nb];
		if (tag.getCode()==code) {
			return tag.getValue();
		}
	}
	return null;
}

/*
 * load pgn file
 */
PgnGame.prototype.loadPgn= function(pgn) {
	var variation;
	var str;
	var tag, value, code;
	var encore;
	var move, lastMove;

	lastMove= null;
	encore= true;
	while (encore) {
		str= pgn.nextToken();
		switch (str) {
			case 'TAG':
				code= pgn.nextToken();
				value= pgn.nextToken();
				this.addTag(new PgnTag(code,value));
				break;

			case 'MOVE':
				move= new PgnMove(this,lastMove);
				if (lastMove==null) {
					this.pgnStart= move;
				}
				lastMove= move;
				move.loadPgn(pgn);
				break;

			case 'VARIATION':
				variation= new PgnVariation(this,0,lastMove);
				lastMove.addVariation(variation)
				variation.loadPgn(pgn);
				break;

			case 'END':
				encore= false;
				break;

			default:
				traceError("PgnGame : unknown token '"+str+"'");
				exit(1);
				break;

		}
	}

	str= this.searchTag('event');
	if (str!=null) {
		this.name= str;
	}
}

/*
 * write tags
 */
PgnGame.prototype.writeTags= function(gb) {
	var value;
	gb.writeHtml('<div class="pgn_tags">');

	value= this.searchTag('event');
	if (value!=null && value.length > 0) {
		gb.writeHtml('<div class="pgn_tag_event">');
		gb.writeHtml(value);
		gb.writeHtml('</div>');
	}

	gb.writeHtml('<div class="pgn_tag_player">');
	value= this.searchTag('white');
	if (value!=null && value.length > 0) {
		gb.writeHtml('<span class="pgn_tag_white">');
		gb.writeHtml(value);
		gb.writeHtml('</span>');
	}

	value= this.searchTag('black');
	if (value!=null && value.length > 0) {
		gb.writeHtml('<span class="pgn_tag_black">');
		gb.writeHtml(value);
		gb.writeHtml('</span>');
	}
		gb.writeHtml('</div>');

	value= this.searchTag('date');
	if (value!=null && value.length > 0) {
		var dd, mm, yy;
		var tokens;
		var sep;
		sep= '.';
		if (value.indexOf('.')>=0)	sep= '.';
		if (value.indexOf('-')>=0)	sep= '-';
		if (value.indexOf('/')>=0)	sep= '/';
		tokens= value.split(sep);
		yy= tokens[0];
		mm= tokens[1];
		dd= tokens[2];
		if (yy==null)	yy= '????';
		if (mm==null)	mm= '??';
		if (dd==null)	dd= '??';

		gb.writeHtml('<div class="pgn_tag_date">');
		gb.writeHtml(dd+'/'+mm+'/'+yy);
		gb.writeHtml('</div>');
	}

	gb.writeHtml('</div>');

}

/*
 * write tag
 */
PgnGame.prototype.writeTag= function(gb,tag) {
	var value;
	value= tag.value;
	if (value!=null && value.length > 0) {
		gb.writeHtml('<tr>');
		gb.writeHtml('<td class="pgn_tag_code">');
		gb.writeHtml(tag.code);
		gb.writeHtml('</td>');
		gb.writeHtml('<td class="pgn_tag_value">');
		gb.writeHtml(value);
		gb.writeHtml('</td>');
		gb.writeHtml('</tr>');
	}
}

/*
 * write all tags
 */
PgnGame.prototype.writeAllTags= function(gb) {
	var value;
	var tag;
	var i;
	var nb= this.tags.length;
	gb.writeHtml('<table border="1" cellpadding="0" cellspacing="0">');
	i= 0;
	while (i < nb) {
		tag= this.tags[i];
		this.writeTag(gb,tag);
		i++;
	}
	gb.writeHtml('</table>');
}

/*
 * write pgn
 */
PgnGame.prototype.writePgn= function(gb) {
	gb.writeHtml('<div class="pgn_pgm">');
	this.pgnStart.writePgn(gb,0);
	gb.writeHtml('</div>');
}

/*
 * dump game
 */
PgnGame.prototype.dump= function() {
	var tag;
	var move;
	var pgn;
	var i, nb;

	trace("Liste des TAGS :");
	i= 0;
	while (i < this.tags.length) {
		tag= this.tags[i];
		trace(" - - " + tag.code + "=" + tag.value);
		i++;
	}

	i= 0;
	while (i < this.moves.length) {
		move= this.moves[i];
		trace(" - - "+i+" " + move.id + "=" + move.code);
		i++;
	}

	this.pgnStart.dump(0);
}

/*
 *********************************************************************************
 * Graphic Board
 *********************************************************************************
 */

function GraphicBoard() {
	this.last_id= 0;
	this.dimX= 35;
	this.dimY= 35;
	this.images= new Array();
	this.contener= document;
	this.drawed= false;
	this.games= new Array();
	this.currentGame= null;
}

GraphicBoard.prototype.writeElement= function(where,str) {
	if (document.getElementById) {
		obj= document.getElementById(where);
		if (obj) {
			obj.innerHTML = str;
		}
		return;
	}
	
	if (document.all) {
		obj= document.all(where);
		if (obj) {
			obj.innerHTML = str;
		}
		return;
	}
	
	if (document.layers) {
		obj= document.layers[where];
		if (obj) {
			with (obj.document) {
				open(); write(str); close();
			}
		}
		return;
	}
	
}

GraphicBoard.prototype.writeHtmlStart= function() {
	this.leftString= '';
}

GraphicBoard.prototype.writeHtmlStop= function(where) {
	this.writeElement(where,this.leftString);
}

GraphicBoard.prototype.writeHtml= function(str) {
	this.leftString= this.leftString + str;
}

GraphicBoard.prototype.drawEmpty= function(board) {
	var f, r, rr;
	var coord;
	var name;
	var	htmlText;
	var	wb_image;
	var	wb_mode;
	if (this.drawed)	return;
	this.writeHtmlStart();
	this.drawed= true;
	this.writeHtml('<div class="pgn_board">');
	wb_mode= 0;
	for (rr= 0; rr < 8; rr++) {
		r= 7 - rr;
		this.writeHtml('<div class="pgn_board_tr">');
		this.writeHtml("\n");
		for (f= 0; f < 8; f++) {
			if (wb_mode==0) {
				wb_image= "w_";
			} else {
				wb_image= "b_";
			}
			wb_mode= 1 - wb_mode;
			this.writeHtml('<div class="pgn_boardcell">');
			coord= globalsFiles.charAt(f) + globalsRanks.charAt(r);
			name= 'i';
			this.writeHtml('<img id="pgn_board_'+coord+'" src="'+this.images[name].src+'" />');
			this.writeHtml('</div>');
			this.writeHtml("\n");
		}
		this.writeHtml('</div>');
		this.writeHtml("\n");
	}
	this.writeHtml('</div>');
	this.writeHtmlStop('pgn_chessboard');
}

GraphicBoard.prototype.writeSelector= function() {
	var i, name;
	if (this.games.length<=1)	return;
	this.writeHtmlStart();
	this.writeHtml('<form name="Selector" >');
	this.writeHtml('<fieldset>');
	this.writeHtml('<select class="pgn_select" name="pgnList" size="1" onChange="ViewGame(this.value)">');
	i= 0;
	while (i<this.games.length) {
		name= this.games[i].name;
		this.writeHtml('<option value="'+i+'">'+name+'</option>');
		i++;
	}
	this.writeHtml('</select>');
	this.writeHtml('</fieldset>');
	this.writeHtml('</form>');
	this.writeHtmlStop('pgn_selector');
}

GraphicBoard.prototype.firstMove= function() {
	var pgnMove;
	var id;
	id= 0;
	this.lightMove(id);
	pgnMove= this.currentGame.moves[id];
	this.draw(pgnMove.board);
}

GraphicBoard.prototype.previousMove= function() {
	var pgnMove;
	var variation;
	var id;
	id= this.last_id;
	if (id >=0 && id < this.currentGame.moves.length) {
		pgnMove= this.currentGame.moves[id];
		variation= pgnMove.variation;
		if (pgnMove.var_move_id > 0) {
			pgnMove= variation.moves[pgnMove.var_move_id -1];
			id= pgnMove.id;
		} else {
			id= -1;
		}
	} else {
		id= -1;
	}

	if (id >= 0) {
		this.lightMove(id);
		pgnMove= this.currentGame.moves[id];
		this.draw(pgnMove.board);
	}
}

GraphicBoard.prototype.nextMove= function() {
	var pgnMove;
	var id;
	id= this.last_id;
	if (id==0) {
		id= 1;
	} else {
		if (id > 0 && id < this.currentGame.moves.length) {
			pgnMove= this.currentGame.moves[id];
			variation= pgnMove.variation;
			if (pgnMove.var_move_id < variation.moves.length - 1) {
				pgnMove= variation.moves[pgnMove.var_move_id +1];
				id= pgnMove.id;
			} else {
				id= -1;
			}
		} else {
			id= -1;
		}
	}

	if (id >= 0) {
		this.lightMove(id);
		pgnMove= this.currentGame.moves[id];
		this.draw(pgnMove.board);
	}
}

GraphicBoard.prototype.lastMove= function() {
	var pgnMove;
	var id;
	id= this.currentGame.moves.length - 1;
	this.lightMove(id);
	pgnMove= this.currentGame.moves[id];
	this.draw(pgnMove.board);
}

GraphicBoard.prototype.lightMove= function(id) {
	var a_id;
	var element;
	last_id= this.last_id;
	if (last_id) {
		a_id= 'pgn_a_'+last_id;
		element= this.contener.getElementById(a_id);
		if (element) element.className= 'pgn_pm';
	}
	a_id= 'pgn_a_'+id;
	element= this.contener.getElementById(a_id);
	if (element) {
		element.className= 'pgn_pm2';

		var winHeight;
		var winTopPos;
		var marginTop;
		/*
		if (document.all) {
		// no scroll in IE : it doesn't work
			// winTopPos = document.body.scrollTop;
			// winHeight = document.body.clientHeight;
			// marginTop = 0;
			winTopPos = 0;
			marginTop = 0;
			winHeight = 999999;
		} else {
		*/
			winTopPos = window.pageYOffset;
			winHeight = window.innerHeight;
			parentTop= document.getElementById('pgn_fullchessboard');
			marginTop= 0;
			while (parentTop!=null) {
				marginTop+= parentTop.offsetTop;
				parentTop= parentTop.offsetParent;
			}
			// marginTop = document.getElementById('groupe-PGN-haut').clientHeight;
		/*
		}
		*/
		if (element.offsetTop <= winTopPos+marginTop || (element.offsetTop+element.offsetHeight) >= winTopPos+winHeight) {
			var newPos;
			newPos= element.offsetTop - (winHeight / 2 );
			window.scroll(0, newPos);
		}

	}
	this.last_id= id;
}

GraphicBoard.prototype.draw= function(board) {
	var f, r, rr;
	var coord;
	var pos;
	var name;
	var image, piece;
	this.drawEmpty(board);
	pos= 0;
	for (rr= 0; rr < 8; rr++) {
		r= 7 - rr;
		for (f= 0; f < 8; f++) {
			coord= globalsFiles.charAt(f) + globalsRanks.charAt(r);
			piece= board.substring(pos,pos+1);
			pos++;
			if (piece!=Empty) {
				if (piece >= 'a' && piece <= 'z') {
					color= 'b';
				} else {
					color= 'w';
				}
				name= color + piece;
				name= name.toLowerCase();
			} else {
				name= 'i';
			}
			image= this.contener.getElementById('pgn_board_'+coord);
			if (image) {
				if (image.src!=this.images[name].src) {
					image.src= this.images[name].src;
				}
			} else {
				traceError("No image Id for pgn_board_"+coord);
			}
		}
	}
}

GraphicBoard.prototype.loadImageSuf= function(pc,suf) {
	var filename;
	this.images[pc]= new Image(this.dimX,this.dimY);
	this.images[pc].src= url_base + '/img/'+pc+this.dimX+'.'+suf;
	filename= pc + this.dimX;
	// str= getFile(url_path + "/" + fileName);
}

GraphicBoard.prototype.loadImage= function(pc) {
	this.loadImageSuf(pc,'gif');
}

GraphicBoard.prototype.loadImages= function() {
	this.loadImage('wk');
	this.loadImage('wq');
	this.loadImage('wr');
	this.loadImage('wn');
	this.loadImage('wb');
	this.loadImage('wp');
	this.loadImage('bk');
	this.loadImage('bq');
	this.loadImage('br');
	this.loadImage('bn');
	this.loadImage('bb');
	this.loadImage('bp');
	this.loadImage('i');
	this.loadImageSuf('brdimg','jpg');
	this.loadImage('mark');
}


GraphicBoard.prototype.writeTags= function() {
	this.currentGame.writeTags(this);
}

GraphicBoard.prototype.writeAllTags= function() {
	this.currentGame.writeAllTags(this);
}

GraphicBoard.prototype.writePgn= function() {
	this.currentGame.writePgn(this);
	this.draw(this.currentGame.pgnStart.board);
}

GraphicBoard.prototype.dump= function() {
	this.currentGame.dump();
}

/*
 * load pgn file
 * use a php script for HTML conversions
 */
GraphicBoard.prototype.loadPgnFile= function(fileName) {
	var pgn;
	var url_path;
	var url_php;
	var game;
	var nb;
	var str;
	var encore;
	url_path= location.protocol +"//"+ location.host + location.pathname.substring(0,location.pathname.lastIndexOf('/'));
	url_path= url_base;
	// url_php= url_path + '/' + 'plugins/genas_echecs' + '/' + 'ge_chess/read.php';
	url_php= url_base + '/exec/' + 'readpgn.php';
	var str;
	str= getFile(url_php + "?pgnfile=" + fileName);
	var pgn= new StringTokenizer(str);
	encore= true;
	while (encore) {
		str= pgn.nextToken();
		switch (str) {
			case 'PGN':
				str= pgn.nextToken();
				str= pgn.nextToken();
				break;

			case 'GAME':
				game= new PgnGame();
				game.loadPgn(pgn);
				nb= this.games.length;
				this.games[nb]= game;
				if (this.currentGame==null) {
					this.currentGame= game;
				}
				break;

			case 'END':
				encore= false;
				str= pgn.nextToken();
				break;

			default:
				traceError("PGN : unknown token '"+str+"'");
				break;

		}
	}

}

/*
 *********************************************************************************
 * MAIN
 *********************************************************************************
 */

function ViewMove(id) {
	var pgnMove;
	globalGraphicBoard.lightMove(id);
	pgnMove= globalGraphicBoard.currentGame.moves[id];
	globalGraphicBoard.draw(pgnMove.board);
}
function ViewGame(id) {
	globalGraphicBoard.last_id= 0;
	globalGraphicBoard.currentGame= globalGraphicBoard.games[id];
	globalGraphicBoard.writeHtmlStart();
	globalGraphicBoard.writeTags();
	globalGraphicBoard.writePgn();
	globalGraphicBoard.writeHtmlStop('pgn_game');
	globalGraphicBoard.writeHtmlStart();
	globalGraphicBoard.writeAllTags();
	globalGraphicBoard.writeHtmlStop('pgn_tags');
}
function doPgnOk() {
	traceAlert("doPgnOk");
	if (initOK==1 && pgnOK==1) {
		nb= uriMemo.length;
		i= 0;
		while (i < nb) {
	traceAlert("loadPgn " + i);
			globalGraphicBoard.loadPgnFile(uriMemo[i]);
			i++;
		}
	traceAlert("drawBoard");
		drawBoard();
		writePgn();
	}
}
function initPgn(url) {
	// alertOk= 1;
	url_base= url;
	globalGraphicBoard= new GraphicBoard();
	globalGraphicBoard.loadImages();
	initOK= 1;
	doPgnOk();
}
function loadPgn(uri) {
	var nb= this.uriMemo.length;
	this.uriMemo[nb]= uri;
}
function loadPgnOK() {
	pgnOK= 1;
	doPgnOk();
}
function drawBoard() {
	globalGraphicBoard.drawEmpty();
}
function writePgn() {
	globalGraphicBoard.writeSelector();
	ViewGame(0);
}
function NextMove() {
	globalGraphicBoard.nextMove();
}
function PreviousMove() {
	globalGraphicBoard.previousMove();
}
function FirstMove() {
	globalGraphicBoard.firstMove();
}
function LastMove() {
	globalGraphicBoard.lastMove();
}


