// Copyright 2005 Jim Radford <radford@blackbean.org> -*- c -*-
// Copyright 2005 David Caldwell <david@porkrind.org>
function crossword(){}
crossword.prototype=new KeyboardFocusAutoPause();crossword.prototype.from_text=function(text){var m,field={},strings=text.split(/[\r\n]+\s*</);for(var i=",a".split(",").length-1;i<strings.length;i++)
if(m=strings[i].match(/^([^>]+?)>\s*((?:.|\n)*?)\s*$/))
field[m[1]]=m[2];var v2;if((delete field["ACROSS PUZZLE"])==undefined&&(v2=delete field["ACROSS PUZZLE V2"])==undefined)
throw"not an Across puzzle";this.title=field.TITLE;delete field.TITLE;this.author=field.AUTHOR;delete field.AUTHOR;this.copyright=field.COPYRIGHT;delete field.COPYRIGHT;var size=field.SIZE.match(/(\d+)x(\d+)/);delete field.SIZE;var across=field.ACROSS.split(/\s*[\r\n]\s*/);delete field.ACROSS;var down=field.DOWN. split(/\s*[\r\n]\s*/);delete field.DOWN;var grid=field.GRID. split(/\s*[\r\n]\s*/);delete field.GRID;this.notepad=field.NOTEPAD;delete field.NOTEPAD;for(f in field)
throw"unknown field "+field[f];if(!size)throw"no size";var cols=size[1],rows=size[2];if(grid.length!=cols)
throw"grid should have "+cols+" columns, but it has "+grid.length;for(var r in grid){if(grid[r].length!=rows)
throw"the length ("+grid[r].length+") grid row "+r+" should be "+rows;if(!grid[r].match(/^[.A-Za-z0-9]*$/))
throw"grid row "+r+" has illegal chars";grid[r]=grid[r].split("");}
this.grid=Array(rows);this.across=[];this.down=[];for(var r=0;r<rows;r++){this.grid[r]=Array(cols);for(var c=0;c<cols;c++){if(grid[r][c]=='.')
this.grid[r][c]=undefined;else
this.grid[r][c]={solution:grid[r][c],state:nbsp};}}
var number=1;for(var r=0;r<rows;r++){for(var c=0;c<cols;c++){if(this.grid[r][c]==undefined)
continue;var new_across=(c==0||this.grid[r][c-1]==undefined)&&c+1<cols&&this.grid[r][c+1]!=undefined;var new_down=(r==0||this.grid[r-1][c]==undefined)&&r+1<rows&&this.grid[r+1][c]!=undefined;if(new_across){this.across.push({row:Number(r),col:Number(c),clue:across.shift()});for(var cc=c;cc<cols&&this.grid[r][cc];cc++)
this.grid[r][cc].across=this.across.length-1;}
if(new_down){this. down.push({row:Number(r),col:Number(c),clue:down.shift()});for(var rr=r;rr<rows&&this.grid[rr][c];rr++)
this.grid[rr][c].down=this. down.length-1;}
if(new_across||new_down)
this.grid[r][c].number=number++;}}}
crossword.prototype.to_text=function(){var grid=[];for(r in this.grid){grid[r]="";for(c in this.grid[r])
grid[r]+=this.grid[r][c]?this.grid[r][c].solution:'.';}
var across=[];for(a in this.across)across.push(this.across[a].clue);var down=[];for(d in this.down)down.push(this. down[d].clue);var text="";text+="<ACROSS PUZZLE>\n";text+="<TITLE>\n\t"+this.title+"\n";text+="<AUTHOR>\n\t"+this.author+"\n";text+="<COPYRIGHT>\n\t"+this.copyright+"\n";text+="<SIZE>\n\t"+grid.length+"x"+grid[0].length+"\n";text+="<GRID>\n\t"+grid.join("\n\t")+"\n";text+="<ACROSS>\n\t"+across.join("\n\t")+"\n";text+="<DOWN>\n\t"+down.join("\n\t")+"\n";if(this.notepad)text+="<NOTEPAD>\n"+this.notepad+"\n";return text;}
crossword.prototype.from_puz=function(puz){if(puz.slice(2,14)!="ACROSS&DOWN\0")
throw"no puz magic";var i=0;var sum1=puz.charCodeAt(i++)|puz.charCodeAt(i++)<<8;i=44;var cols=puz.charCodeAt(i++);var rows=puz.charCodeAt(i++);var clues=puz.charCodeAt(i++)|puz.charCodeAt(i++)<<8;i+=4;var solution=puz.slice(i,i+rows*cols);i+=rows*cols;var state=puz.slice(i,i+rows*cols);i+=rows*cols;var strings=puz.slice(i).split("\0");this.title=strings.shift();this.author=strings.shift();this.copyright=strings.shift();this.grid=Array(rows);this.across=[];this.down=[];for(var r=0;r<rows;r++){this.grid[r]=Array(cols);for(var c=0;c<cols;c++){if(solution.charAt(r*cols+c)=='.'){this.grid[r][c]=undefined;}else{this.grid[r][c]={solution:solution.charAt(r*cols+c),state:state.charAt(r*cols+c)};if(this.grid[r][c].state=='-')
this.grid[r][c].state=nbsp;}}}
var number=1;for(var r=0;r<rows;r++){for(var c=0;c<cols;c++){if(this.grid[r][c]==undefined)
continue;var new_across=(c==0||this.grid[r][c-1]==undefined)&&c+1<cols&&this.grid[r][c+1]!=undefined,new_down=(r==0||this.grid[r-1][c]==undefined)&&r+1<rows&&this.grid[r+1][c]!=undefined;if(new_across){this.across.push({row:r,col:c,clue:strings.shift()});for(var cc=c;cc<cols&&this.grid[r][cc];cc++)
this.grid[r][cc].across=this.across.length-1;}
if(new_down){this. down.push({row:r,col:c,clue:strings.shift()});for(var rr=r;rr<rows&&this.grid[rr][c];rr++)
this.grid[rr][c].down=this. down.length-1;}
if(new_across||new_down)
this.grid[r][c].number=number++;}}
this.notepad=strings.shift();if(strings.length!=1||strings[0].length!=0);}
function board(board,across,down,title,author,copyright,control_panel){this.div={};this.div.board=board;this.div.across=across;this.div.down=down;this.div.title=title;this.div.author=author;this.div.copyright=copyright;this.div.control_panel=control_panel;}
board.prototype=new crossword();board.prototype.show_help=function(){new_alert(doc.el("div",{},doc.el("h2",{},doc.text("Keyboard Commands")),doc.el("table",{},doc.el("tr",{},doc.el("td",{},doc.text("Arrows")),doc.el("td",{},doc.text("Basic movement. Also changes across/down orientation."))),doc.el("tr",{},doc.el("td",{},doc.text("Shift + Arrows")),doc.el("td",{},doc.text("Basic movement. Does not change across/down orientation."))),doc.el("tr",{},doc.el("td",{},doc.text("A - Z")),doc.el("td",{},doc.text("Enters a character into the current square and advances."))),doc.el("tr",{},doc.el("td",{},doc.text("Shift + A - Z")),doc.el("td",{},doc.text("Pencils in a character into the current square and advances."))),doc.el("tr",{},doc.el("td",{},doc.text("Backspace")),doc.el("td",{},doc.text("Deletes the current square and backs up."))),doc.el("tr",{},doc.el("td",{},doc.text("Space")),doc.el("td",{},doc.text("Clears the current square and advances."))),doc.el("tr",{},doc.el("td",{},doc.text("Tab")),doc.el("td",{},doc.text("Moves to next clue."))),doc.el("tr",{},doc.el("td",{},doc.text("Shift + Tab")),doc.el("td",{},doc.text("Moves to previous clue.")))),doc.el("h2",{},doc.text("Pencil, Ink, and Erasures")),doc.el("p",{},doc.text("When you erase a square with space or tab, the square will darken subtly, "+
"as a pencil eraser might leave residue on real paper. Erasing a square that "+
"was marked in pencil (shift + letter keys) leaves less of an erasure than "+
"normal black letters."))),{goaway:true,title:"Crossword Help",width:500});}
board.prototype.create=function(){this.div.title.appendChild(document.createTextNode(this.title));this.div.author.appendChild(document.createTextNode(this.author));this.div.copyright.appendChild(document.createTextNode(this.copyright.replace(/^(\u00a9\s*)?/,"\u00a9\u00a0")));this.div.control_panel.appendChild(doc.el("input",{value:"Help",type:"button",id:"Help",onclick:this.show_help}));var table=document.createElement("table");var tbody=document.createElement("tbody");table.cellSpacing=0;table.className="grid";this.cell=[];for(var r=0;r<this.grid.length;r++){this.cell[r]=[];var tr=document.createElement("tr");for(var c=0;c<this.grid[r].length;c++){var td=document.createElement("td");this.cell[r][c]={td:td,erasure:0};td.className="cell";if(this.grid[r][c]==undefined){td.className="blank";td.appendChild(document.createTextNode("."));}else{if(this.grid[r][c].number){var number=document.createElement("div");number.className="number";number.appendChild(document.createTextNode(this.grid[r][c].number));td.appendChild(number);}
var text=document.createElement("div");text.className="letter";text.appendChild(this.cell[r][c].text=document.createTextNode(this.grid[r][c].state));td.appendChild(this.cell[r][c].div=text);td.onclick=(function(me,r,c){return function(){me.highlight(false);if(me.cursor.r==r&&me.cursor.c==c)
me.toggle_orientation();me.cursor.r=r;me.cursor.c=c;me.fix_orientation();me.highlight(true);};})(this,r,c);}
tr.appendChild(td);}
tbody.appendChild(tr);}
table.appendChild(tbody);this.div.board.appendChild(table);this.init_keyboard_focus_auto_pause(this.div.board);this.input_focus();this.cursor={c:0,r:0};while(this.grid[this.cursor.r][this.cursor.c]==undefined)
this.cursor.c++;this.orient="across";this.toggle_orientation=function(){return this.orient={down:"across",across:"down"}[this.orient];}
this.fix_orientation=function(){if(this.grid[this.cursor.r][this.cursor.c][this.orient]==undefined)
this.toggle_orientation();}
this.fix_orientation();this.init_panel=function(dir,div){var lis=[],table=document.createElement("table");var tbody=document.createElement("tbody");for(var i in this[dir]){var li=document.createElement("td");li.clue=this[dir][i];li.me=this;li.className="clue";li.onclick=function(){this.me.highlight(false);this.me.cursor.r=this.clue.row;this.me.cursor.c=this.clue.col;this.me.orient=dir;this.me.highlight(true);this.me.input_focus();}
var span=document.createElement("div");span.appendChild(document.createTextNode(this.grid[li.clue.row][li.clue.col].number));span.className="number";li.appendChild(span);li.appendChild(document.createTextNode(li.clue.clue));var tr=document.createElement("tr");tr.appendChild(lis[i]=li);tbody.appendChild(tr);}
table.appendChild(tbody);div.appendChild(table);return lis;}
this.panel={across:this.init_panel("across",this.div.across),down:this.init_panel("down",this.div.down)};this.clue_start=function(){var inc={r:this.orient=="down"?1:0,c:this.orient=="across"?1:0};for(var c={r:this.cursor.r,c:this.cursor.c};c.r>=0&&c.c>=0;c.r-=inc.r,c.c-=inc.c)
if(c.r<inc.r||c.c<inc.c||this.grid[c.r-inc.r][c.c-inc.c]==undefined)
return c;}
this.highlight=function(draw){var start=this.clue_start();for(var c=start;c.r<this.grid.length&&c.c<this.grid[c.r].length&&this.grid[c.r][c.c];this.orient=="down"?c.r++:c.c++){this.cell[c.r][c.c].td.className=!draw?"cell"+Math.min(this.cell[c.r][c.c].erasure,6):(c.c==this.cursor.c&&c.r==this.cursor.r?"cursor":"highlight");}
var highlight_panel=function(panel,div,i,oriented){panel[i].className=draw?oriented?"cursor":"highlight":"clue";var top=panel[i].offsetTop-panel[i].parentNode.parentNode.offsetTop;if(top+panel[i].offsetHeight>div.scrollTop+div.offsetHeight||top<div.scrollTop)
div.scrollTop=top-div.clientHeight/2;}
var c=this.grid[this.cursor.r][this.cursor.c];if(c.down!=undefined)
highlight_panel(this.panel.down,this.div.down,c.down,this.orient=="down");if(c.across!=undefined)
highlight_panel(this.panel.across,this.div.across,c.across,this.orient=="across");}
this.add=function(pt_in,orient,dir){var pt={"r":pt_in.r,"c":pt_in.c};if(orient=="down")
pt.r=(pt.r+dir+this.grid.length)%this.grid.length;else
pt.c=(pt.c+dir+this.grid[pt.r].length)%this.grid[pt.r].length;return pt;}
this.move=function(orient,dir,stop,change_orient){this.highlight(false);if(orient!=this.orient&&change_orient&&this.grid[this.cursor.r][this.cursor.c][orient]!=undefined)
this.orient=orient;else{do{var n=this.add(this.cursor,orient,dir);if(stop&&(this.grid[n.r][n.c]==undefined||Math.abs(n.r-this.cursor.r)>1||Math.abs(n.c-this.cursor.c)>1))break;this.cursor=n;}while(this.grid[this.cursor.r][this.cursor.c]==undefined);me.fix_orientation();}
this.highlight(true);}
this.jump=function(dir){this.highlight(false);var orient=this.orient;var number=this.grid[this.cursor.r][this.cursor.c][orient];number=(number+dir+this[orient].length)%this[orient].length;this.cursor={r:this[orient][number].row,c:this[orient][number].col};this.highlight(true);}
this.highlight(true);var me=this;this.set=function(c){if(me.cell[me.cursor.r][me.cursor.c].text.data!=nbsp&&me.cell[me.cursor.r][me.cursor.c].text.data!=c)
me.cell[me.cursor.r][me.cursor.c].erasure+=me.cell[me.cursor.r][me.cursor.c].div.className=="pencil"?1:2;me.cell[me.cursor.r][me.cursor.c].text.data=c;}
this.register_key_events(function(event){switch(event.key){case"S-up":case"up":me.move("down",-1,false,!event.shiftKey);return false;case"S-down":case"down":me.move("down",+1,false,!event.shiftKey);return false;case"S-left":case"left":me.move("across",-1,false,!event.shiftKey);return false;case"S-right":case"right":me.move("across",+1,false,!event.shiftKey);return false;case"return":print("Return!\n");return false;case"enter":print("Enter!\n");return false;case"S-tab":me.jump(event.shiftKey?-1:1);return false;case"tab":me.jump(event.shiftKey?-1:1);return false;case"backspace":me.set(nbsp);me.move(me.orient,-1,true);return false;}
var wrong=[];if(event.key=="#"){for(var r in me.grid)
for(var c in me.grid[r])
if(me.grid[r][c]&&me.cell[r][c].text.data!=me.grid[r][c].solution){wrong.push({div:me.cell[r][c].div,name:me.cell[r][c].div.className});me.cell[r][c].div.className="wrong";}
var oldup=window.onkeydown;window.onkeyup=function(event){window.onkeyup=oldup;for(var w in wrong)
wrong[w].div.className=wrong[w].name;}
return false;}
if(event.key=="%")
for(var r in me.cell)
for(var c in me.cell[r])
if(me.grid[r][c])
me.cell[r][c].text.data=me.grid[r][c].solution;if(!event.key.toUpperCase().match(/^(S-)?[A-Z]$/)&&event.key!="space")
return true;me.cell[me.cursor.r][me.cursor.c].div.className=event.shiftKey?"pencil":"letter";me.set(event.key=="space"?nbsp:event.key.toUpperCase().replace(/S-/,''));me.move(me.orient,+1,true);return false;});this.on_pause=function(){this.highlight(false);}
this.on_unpause=function(){this.highlight(true);}}
on_load(function(){var this_board=new board(document.getElementById("board"),document.getElementById("across"),document.getElementById("down"),document.getElementById("title"),document.getElementById("author"),document.getElementById("rights"),document.getElementById("control_panel"));var game=URL.param.puz?undefined:(URL.param.game||game_of_the_day[0]);loadBinary("crossword.cgi?"+(URL.param.puz?"puz="+URL.param.puz:"game="+game),function(puz,error,status){if(puz==undefined){if(URL.param.debug)printf("Error loading crossword data: %s\n",error);var text="No crossword data for game "+game+".  You can play this old one until we can find more.";this_board.div.control_panel.appendChild(document.createTextNode(text));loadText("easyt.txt",function(text,error){if(text==undefined){printf("Another error loading crossword data: %s\n",error);return;}
this_board.from_text(text);this_board.create();});return;}
try{this_board.from_puz(puz);}catch(e){print("caught "+e+"\n");print_structure(e,"e");return;}
this_board.create();});});
