/*
Copyright (c) 2009 Thomas Peri
MIT License

Combined and minified:
Logo.js
Logo.IO.js
Logo.Lib.js
Logo.Graphics.js
Logo.Editor.js
Logo.UI.js
*/

var Logo={Interpreter:Talky.InterpreterIF('Logo.Interpreter',function(options){var
construct,recursion,any,comment,word,number,trim,core,cache,hub,contexts,ctx,setHub,init,stop,parse,next,setOptions,tokenize,encounter,special,push,pop,assertWord,local,global,scope,lookup,assign,run,modMem,resolve,enterContext,exitProc,exitContext;construct=function(){recursion=500;setOptions(options||{});cache={};any=new RegExp(";.*([\\r\\n]\\s*|$)|(\"(\\\\?.)*?\"|\\S+)?(\\s+|$)",'g');comment=new RegExp("^(;.*[\\r\\n]\\s*)$");word=new RegExp("^[^\\s\\.;:\\[\\]\"']+$");number=new RegExp("^-?(0|[1-9]\\d*)(\\.\\d+)?([eE][-+]?\\d+)?$");trim=new RegExp("^\\s+|\\s+$");};setHub=function(h){hub=h;hub.addModule(core);};init=function(){contexts=[];enterContext({type:'main',proc:[],stack:[]});};stop=function(){contexts.splice(0,contexts.length-1);ctx=contexts[0];ctx.tokens=[];};parse=function(code){stop();try{ctx.tokens=tokenize(code);}catch(e){throw'parse error: '+e;}};next=function(){if(ctx.tokens.length===0){if(ctx.type==='main'){return false;}exitProc();}else{encounter(ctx.tokens);}return true;};setOptions=function(options){var value;if(typeof options.recursion!=='undefined'){value=parseInt(options.recursion,10)||0;if(value<=0){throw"recursion must be greater than zero.";}recursion=value;}};tokenize=function(code){var tok,tokens,i,val;tokens=code.replace(trim,'').match(any)||[];for(i=0;i<tokens.length;i+=1){tok=tokens[i];if(!tok||comment.test(tok)){tokens.splice(i,1);i-=1;}else{tok=tok.replace(trim,'');val=special(tok);tokens[i]=(typeof val==='undefined')?tok:val;}}return tokens;};special=function(str){if(number.test(str)){return parseFloat(str);}else{switch(str.toLowerCase()){case'true':return true;case'false':return false;case'null':return null;}}};encounter=function(tokens){var tok,first,rest,val,list,depth;tok=tokens.shift();switch(typeof tok){case'function':run(tok);return;case'number':case'boolean':push(tok);return;case'object':if(!tok||(tok instanceof Array)){push(tok);return;}else if(tok.type==='mod'){run(tok);return;}break;case'string':tok=tok.replace(trim,'');first=tok.charAt(0);rest=tok.substring(1);switch(tok.length){case 0:throw"empty token";case 1:switch(tok){case'[':list=[];depth=1;while(true){if(tokens.length===0){throw"unbalanced [";}tok=tokens.shift();if(typeof tok==='string'){switch(tok.replace(trim,'')){case'[':depth+=1;break;case']':depth-=1;break;default:}}if(depth===0){push(list);return;}list.push(tok);}return list;case']':throw"unbalanced ]";case'"':case"'":case':':throw"orphaned "+tok;}}if(/\s/.test(tok)&&first!=='"'){throw"only string tokens can contain spaces.";}switch(first){case'"':try{push(JSON.parse(tok));}catch(s){throw"Invalid string.";}return;case"'":push(rest);return;case':':push(lookup(rest));return;}val=special(tok);if(typeof val!=='undefined'){push(val);return;}run(tok);return;}throw'unknown value '+JSON.stringify(tok);};push=function(v){ctx.stack.unshift(v);};pop=function(){if(ctx.stack.length===0){throw"the stack is empty";}return ctx.stack.shift();};assertWord=function(wd){if(typeof wd!=='string'||!word.test(wd)||number.test(wd)){throw wd+' is not a valid word';}};local=function(wd){var low;assertWord(wd);low=wd.toLowerCase();ctx.locals[low]=true;delete ctx.globals[low];};global=function(wd){var low;assertWord(wd);low=wd.toLowerCase();ctx.globals[low]=true;delete ctx.locals[low];};scope=function(wd){var i,low;assertWord(wd);low=wd.toLowerCase();if(ctx.globals.hasOwnProperty(low)){return contexts.length-1;}if(ctx.locals.hasOwnProperty(low)){return 0;}for(i=0;i<contexts.length;i+=1){if(contexts[i].dictionary.hasOwnProperty(low)){return i;}}return-1;};lookup=function(wd){var low,index,found;assertWord(wd);low=wd.toLowerCase();index=scope(low);if(index>=0){return contexts[index].dictionary[low];}if(cache.hasOwnProperty(low)){return cache[low];}found=hub.lookup(low);if(found){found={type:'mod',proc:found};cache[low]=found;return found;}throw"no such word as "+wd;};assign=function(val,wd){var low,index,bottom;assertWord(wd);low=wd.toLowerCase();bottom=contexts.length-1;index=scope(low);if(index<0){index=bottom;}contexts[index].dictionary[low]=val;};run=function(proc){if(typeof proc==='string'){proc=lookup(proc);}if(typeof proc==='function'){proc.call();}else if(proc instanceof Array){if(contexts.length>=recursion){throw'too much recursion';}enterContext({type:'run',proc:proc});}else if(proc&&proc.type==='mod'){modMem(proc.proc);}else{throw proc+" is not a procedure";}};modMem=function(proc){var i,p,args,result,overload;if(proc.hasOwnProperty('fn')){overload=[proc];}else if(proc.hasOwnProperty('overload')){overload=proc.overload;}if(overload){proc=resolve(proc.memberName,overload);}if(proc.hasOwnProperty('fn')&&typeof proc.fn==='function'){p=proc.params;args=[];for(i=proc.params.length-1;i>=0;i-=1){args.push(pop());}result=proc.fn.apply(null,args.reverse());if(result&&typeof result==='object'&&result.hasOwnProperty('run')){run(result.run);}else if(typeof result!=='undefined'){push(result);}}else if(proc.hasOwnProperty('value')){push(proc.value);}else{throw"invalid module member "+(typeof proc);}};resolve=function(name,overload){var i,p,params,op,type,last;for(i=0;i<overload.length;i+=1){params=overload[i].params;last=params.length-1;for(p=0;p<=last;p+=1){op=ctx.stack[p];type=typeof op;if(op&&type==='object'){type=op.constructor;}switch(params[last-p]){case type:case null:continue;}break;}if(p===params.length){return overload[i];}}throw"wrong number or type of operands for '"+name+"'";};enterContext=function(c){var opt;opt=ctx&&ctx.tokens.length===0&&ctx.type!=='main'&&c.type!=='eval';if(opt){c.globals=ctx.globals;c.locals=ctx.locals;c.dictionary=ctx.dictionary;}else{c.globals={};c.locals={};c.dictionary={};}c.tokens=c.proc.slice(0);if(!c.hasOwnProperty('stack')){c.stack=ctx.stack;}if(opt){ctx=contexts[0]=c;}else{contexts.unshift(c);ctx=contexts[0];}};exitProc=function(){switch(ctx.type){case'forever':ctx.repcount+=1;ctx.tokens=ctx.proc.slice(0);break;case'repeat':if(ctx.repcount<ctx.reptotal){ctx.repcount+=1;ctx.tokens=ctx.proc.slice(0);}else{exitContext();}break;default:exitContext();}};exitContext=function(viaStop){var c;c=contexts.shift();ctx=contexts[0];switch(c.type){case'if':if(viaStop){exitContext(true);}break;case'eval':c.stack.reverse();push(c.stack);break;}};core=new(Talky.module('Logo.core',function(){this.talky={'make':{overload:[{params:[null,'string'],fn:function(val,wd){assign(val,wd);}},{params:[Array],fn:function(list){var i;if(list.length%2){throw"when make uses a list, it must have an even number of items";}for(i=0;i<list.length;i+=2){assign(list[i],list[i+1]);}}}]},'localmake':{overload:[{params:[null,'string'],fn:function(val,wd){local(wd);assign(val,wd);}},{params:[Array],fn:function(list){var i;if(list.length%2){throw"when localmake uses a list, it must have an even number of items";}for(i=0;i<list.length;i+=2){local(list[i+1]);assign(list[i],list[i+1]);}}}]},'thing':{params:['string'],fn:function(wd){return lookup(wd);}},'local':{overload:[{params:['string'],fn:function(wd){local(wd);}},{params:[Array],fn:function(list){var i;for(i=0;i<list.length;i+=1){local(list[i]);}}}]},'global':{overload:[{params:['string'],fn:function(wd){global(wd);}},{params:[Array],fn:function(list){var i;for(i=0;i<list.length;i+=1){global(list[i]);}}}]},'unscope':{params:['string'],fn:function(wd){var low;assertWord(wd);low=wd.toLowerCase();delete ctx.globals[low];delete ctx.locals[low];}},'erase':{params:['string'],fn:function(wd){var low,index,bottom;low=wd.toLowerCase();bottom=contexts.length-1;index=scope(low);if(index<0){index=bottom;}if(index===bottom&&hub.lookup(low)){throw"can't erase '"+wd+" globally";}delete contexts[index].dictionary[low];}},'bind':{params:[Array],fn:function(list){var i,item,result;result=list.slice(0);for(i=0;i<result.length;i+=1){item=result[i];if(typeof item==='string'&&item.charAt(0)===':'){result[i]=lookup(item.substring(1));}}return result;}},'run':{params:[null],fn:function(val){run(val);}},'list':{overload:[{params:['number'],fn:function(n){var stack,list;stack=ctx.stack;n=Math.max(0,Math.round(n));if(stack.length<n){throw n+" list needs "+n+" more operand(s)";}list=stack.splice(0,n);list.reverse();return list;}},{params:[Array],fn:function(list){enterContext({type:'eval',proc:list,stack:[]});}}]},'unlist':{params:[Array],fn:function(list){list=list.slice(0);list.reverse();list.splice(0,0,0,0);Array.prototype.splice.apply(ctx.stack,list);}},'dup':{params:[],fn:function(){var stack;stack=ctx.stack;if(stack.length===0){throw"dup needs 1 operand";}stack.unshift(stack[0]);}},'pop':{params:[],fn:function(){pop();}},'swap':{params:[],fn:function(){var stack;stack=ctx.stack;if(stack.length<2){throw"swap needs 2 operands";}stack.splice(0,2,stack[1],stack[0]);}},'roll':{params:['number','number'],fn:function(n,j){var movers,stack;n=Math.round(n);j=Math.round(j);stack=ctx.stack;if(stack.length<n){throw n+" "+j+" roll needs "+n+" extra operand(s)";}j%=n;if(j<0){j+=n;}movers=stack.splice(0,j);movers.splice(0,0,n-j,0);Array.prototype.splice.apply(stack,movers);}},'if':{params:[Array,'boolean'],fn:function(list,test){if(test){enterContext({type:'if',proc:list});}}},'ifelse':{params:[Array,Array,'boolean'],fn:function(yes,no,test){enterContext({type:'if',proc:test?yes:no});}},'repeat':{params:[Array,'number'],fn:function(list,times){times=Math.floor(times);if(times>0){enterContext({type:'repeat',reptotal:times,repcount:1,proc:list});}}},'repcount':{params:[],fn:function(){var i,c;for(i=0;i<contexts.length;i+=1){c=contexts[i];if(c.repcount){return c.repcount;}}return-1;}},'forever':{params:[Array],fn:function(list){enterContext({type:'forever',repcount:1,proc:list});}},'stop':{params:[],fn:function(){if(ctx.type==='main'){stop();}else{exitContext(true);}}},'word?':{params:[null],fn:function(v){return typeof v==='string'&&word.test(v);}},'defined?':{params:[null],fn:function(wd){var low;assertWord(wd);low=wd.toLowerCase();return scope(low)>=0||hub.lookup(low)?true:false;}}};this.update=function(flag){if(flag==='done'){stop();}};this.changed=this.setHub=function(){return false;};this.init=init;}))();this.setHub=setHub;this.parse=parse;this.next=next;this.setOptions=setOptions;construct();})};Logo.IO=Talky.module('Logo.IO',function(parts){var print,clear,hub;print=function(s){parts.pre.append(hub.lookup('string','Logo.Lib').fn(s)+"\n").each(function(){this.scrollTop=this.scrollHeight;});};clear=function(){parts.pre.html('');};this.talky={'print':{params:[null],fn:print},'cleartext':{params:[],fn:clear}};this.talky.ct=this.talky.cleartext;this.changed=this.stop=this.update=function(){return false;};this.setHub=function(h){hub=h;};this.init=function(){clear();print("Welcome to Stack Logo!");};this.print=print;this.clear=clear;});Logo.Lib=Talky.module('Logo.Lib',function(){var talky,hub,degToRad,radToDeg,assertList,assertNumber,assertString;degToRad=function(d){return d*Math.PI/180;};radToDeg=function(r){return r/Math.PI*180;};assertList=function(a,min,max){if(!(a instanceof Array)){throw a+' is not a list';}if((min||min===0)&&a.length<min){throw'not enough items in list';}if((max||max===0)&&a.length>max){throw'too many items in list';}};assertNumber=function(n,min,max){if(typeof n!=='number'){throw n+' is not a valid number';}if((min||min===0)&&n<min){throw'number must be at least '+min;}if((max||max===0)&&n>max){throw'number must be at most '+max;}};assertString=function(s,min,max){if(typeof s!=='string'){throw s+' is not a string';}if(min&&s.length<min){throw'not enough characters in string';}if(max&&s.length>max){throw'too many characters in string';}};talky={'pi':{value:Math.PI},'number':{params:[null],fn:function(v){var n;switch(v){case true:return 1;case false:case null:return 0;}if(typeof v==='string'){n=parseFloat(v,10);}if(!n&&n!==0){throw v+" cannot be made into a number";}return n;}},'string':{params:[null],fn:function(value){var convert,arrays;arrays=[];convert=function(v){var i,result;if(v&&typeof v==='object'){if(v instanceof Array){if(arrays.indexOf(v)>=0){return'{circular reference}';}else{arrays.push(v);result=[];for(i=0;i<v.length;i+=1){result.push(convert(v[i]));}return'[ '+result.join(' ')+' ]';}}else if(v.type==='mod'){return'{'+v.proc.moduleName+'.'+v.proc.memberName+'}';}else{return'{object}';}}else if(typeof v==='function'){return'{js-function}';}else{return String(v);}};return convert(value);}},'boolean':{params:[null],fn:function(value){return!!value;}},'number?':{params:[null],fn:function(n){return typeof n==='number';}},'boolean?':{params:[null],fn:function(v){return typeof v==='boolean';}},'string?':{params:[null],fn:function(v){return typeof v==='string';}},'list?':{params:[null],fn:function(v){return v instanceof Array;}},'add':{overload:[{params:['number','number'],fn:function(a,b){return a+b;}},{params:[Array],fn:function(many){var i,sum;sum=0;for(i=0;i<many.length;i+=1){sum+=many[i];}return sum;}}]},'mul':{overload:[{params:['number','number'],fn:function(a,b){return a*b;}},{params:[Array],fn:function(many){var i,prod;prod=0;for(i=0;i<many.length;i+=1){prod*=many[i];}return prod;}}]},'sub':{params:['number','number'],fn:function(a,b){return a-b;}},'div':{params:['number','number'],fn:function(a,b){if(b===0){throw"division by zero";}return a/b;}},'mod':{params:['number','number'],fn:function(a,b){if(b===0){throw"modulo by zero";}return a%b;}},'sqrt':{params:['number'],fn:function(n){return Math.sqrt(n);}},'power':{params:['number','number'],fn:function(a,b){return Math.pow(a,b);}},'exp':{params:['number'],fn:function(n){return Math.exp(n);}},'log':{params:['number'],fn:function(n){return Math.log(n);}},'round':{params:['number'],fn:function(n){return Math.round(n);}},'floor':{params:['number'],fn:function(n){return Math.floor(n);}},'ceiling':{params:['number'],fn:function(n){return Math.ceil(n);}},'abs':{params:['number'],fn:function(n){return Math.abs(n);}},'max':{params:[Array],fn:function(list){var i,max;if(list.length===0){throw"max needs a list with at least one item";}max=list[0];for(i=1;i<list.length;i+=1){if(typeof list[i]!=='number'){throw"each item in the list given to max must be a number";}max=Math.max(max,list[i]);}return max;}},'min':{params:[Array],fn:function(list){var i,min;if(list.length===0){throw"min needs a list with at least one item";}min=list[0];for(i=1;i<list.length;i+=1){if(typeof list[i]!=='number'){throw"each item in the list given to min must be a number";}min=Math.min(min,list[i]);}return min;}},'sin':{params:['number'],fn:function(n){return Math.sin(degToRad(n));}},'cos':{params:['number'],fn:function(n){return Math.cos(degToRad(n));}},'tan':{params:['number'],fn:function(n){return Math.tan(degToRad(n));}},'asin':{params:['number'],fn:function(n){if(-1>n||n>1){throw"asin needs a number from -1 to 1";}return radToDeg(Math.asin(n));}},'acos':{params:['number'],fn:function(n){if(-1>n||n>1){throw"acos needs a number from -1 to 1";}return radToDeg(Math.acos(n));}},'atan':{params:['number','number'],fn:function(n){return radToDeg(Math.acos(n));}},'random':{params:['number','number'],fn:function(low,high){var swap;if(low>high){swap=low;low=high;high=swap;}low=Math.ceil(low);high=Math.floor(high);return Math.floor(Math.random()*(high-low+1)+low);}},'eq?':{params:[null,null],fn:function(a,b){if(a&&b&&a.type==='mod'&&b.type==='mod'){return a.proc===b.proc;}return a===b;}},'lt?':{params:['number','number'],fn:function(a,b){return a<b;}},'lte?':{params:['number','number'],fn:function(a,b){return a<=b;}},'gt?':{params:['number','number'],fn:function(a,b){return a>b;}},'gte?':{params:['number','number'],fn:function(a,b){return a>=b;}},'and':{params:['boolean','boolean'],fn:function(a,b){return a&&b;}},'or':{params:['boolean','boolean'],fn:function(a,b){return a||b;}},'xor':{params:['boolean','boolean'],fn:function(a,b){return a!==b;}},'not':{params:['boolean'],fn:function(a){return!a;}},'pushfirst':{params:[null,Array],fn:function(thing,list){list.unshift(thing);}},'pushlast':{params:[null,Array],fn:function(thing,list){list.push(thing);}},'popfirst':{params:[Array],fn:function(list){assertList(list,1);return list.shift();}},'poplast':{params:[Array],fn:function(list){assertList(list,1);return list.pop();}},'first':{overload:[{params:[Array],fn:function(list){assertList(list,1);return list[0];}},{params:['string'],fn:function(s){assertString(s,1);return s.charAt(0);}}]},'item':{overload:[{params:[Array,'number'],fn:function(list,index){assertNumber(index,1);assertList(list,index);return list[index-1];}},{params:['string','number'],fn:function(s,index){assertNumber(index,1);assertString(s,index);return s.charAt(index-1);}}]},'pick':{overload:[{params:[Array],fn:function(list){assertList(list,1);return list[Math.floor(Math.random()*list.length)];}},{params:['string'],fn:function(s){assertString(s,1);return s.charAt(Math.floor(Math.random()*s.length));}}]},'rest':{overload:[{params:[Array],fn:function(list){assertList(list,1);return list.slice(1);}},{params:['string'],fn:function(s){assertString(s,1);return s.substring(1);}}]},'concat':{overload:[{params:[Array,Array],fn:function(a,b){return a.concat(b);}},{params:['string','string'],fn:function(a,b){return a+b;}}]},'reverse':{overload:[{params:[Array],fn:function(list){list=list.slice(0);list.reverse();return list;}},{params:['string'],fn:function(string){var i,result;result=[];for(i=string.length-1;i>=0;i-=1){result.push(string[i]);}return result.join('');}}]},'count':{overload:[{params:['string'],fn:function(s){return s.length;}},{params:[Array],fn:function(list){return list.length;}}]},'wait':{params:['number'],fn:function(n){hub.async(function(callback){setTimeout(callback,Math.round(n*1000));});}}};(function(){var a,i;a={'?':'boolean','#':'number','$':'string'};for(i in a){if(a.hasOwnProperty(i)){talky[i]=talky[a[i]];}}}());this.talky=talky;this.setHub=function(h){hub=h;};this.changed=this.init=this.update=function(){return false;};});Logo.Graphics=Talky.module('Logo.Graphics',function(parts){var
format,paper,turtle,changed,state,hub,talky,shape,convert,turtleShape,turtlePenShape,canvas,reformat,update,move,setxy,rotate,setheading,startShape,endShape;convert=function(s){return{x:Math.floor(s.width/2)+s.x,y:Math.floor(s.height/2)-s.y,h:(s.heading-90)*Math.PI/180};};turtleShape=function(c){function draw(){c.beginPath();c.moveTo(18,0);c.lineTo(-6.5,-9);c.lineTo(-6.5,9);c.lineTo(18,0);c.closePath();}draw();c.fillStyle="rgba(255,255,255,.75)";c.fill();draw();c.lineWidth=2;c.lineCap='round';c.strokeStyle="rgb(0,0,0)";c.stroke();};turtlePenShape=function(c){c.beginPath();c.arc(0,0,2,0,2*Math.PI,false);c.closePath();};canvas=function(cnv){var c,s;if(cnv.node){format.removeChild(cnv.node);}c=document.createElement('canvas');c.height=state.height;c.width=state.width;format.appendChild(c);cnv.ctx=c.getContext("2d");cnv.ctx.translate(0.5,0.5);cnv.ctx.lineCap='round';s=c.style;s.position='absolute';s.top=s.left='0px';cnv.node=c;return cnv;};reformat=function(w,h){var s;s=format.style;s.width=w+'px';s.height=h+'px';s.position='relative';s.top=s.left='0px';state.width=w;state.height=h;paper=canvas(paper);turtle=canvas(turtle);talky.clearscreen.fn();};update=function(){var s,c;changed=false;s=convert(state);c=turtle.ctx;c.clearRect(-1,-1,state.width+1,state.height+1);if(state.shown){c.save();c.translate(s.x,s.y);c.rotate(s.h);turtleShape(c);c.lineWidth=1;if(state.down){turtlePenShape(c);c.fillStyle=state.pencolor;c.fill();}else{c.strokeStyle="rgba(0,0,0,0.25)";}turtlePenShape(c);c.stroke();c.restore();}};move=function(d){var p;p=convert(state);setxy(state.x+d*Math.cos(p.h),state.y-d*Math.sin(p.h));};setxy=function(x,y){var c,p,s;c=paper.ctx;p=convert(state);state.x=x;state.y=y;s=convert(state);if(state.down){c.beginPath();c.moveTo(p.x,p.y);c.lineTo(s.x,s.y);c.strokeStyle=state.pencolor;c.lineWidth=state.pensize;c.stroke();}if(shape){shape.push([s.x,s.y]);}changed=true;};rotate=function(d){setheading(state.heading+d);};setheading=function(h){state.heading=h;changed=true;};startShape=function(){var s;if(shape){throw"filled can't happen inside another filled";}s=convert(state);shape=[[s.x,s.y]];};endShape=function(){var c,i;c=paper.ctx;c.fillStyle=state.fillcolor;c.beginPath();c.moveTo(shape[0][0],shape[0][1]);for(i=1;i<shape.length;i+=1){c.lineTo(shape[i][0],shape[i][1]);}c.closePath();c.fill();changed=true;shape=null;};this.init=function(){changed=false;shape=null;state={shown:true,down:true,background:'white',fillcolor:'gray',pencolor:'black',pensize:1,x:0,y:0,heading:0,width:parts.width||300,height:parts.height||200,resized:true};paper={};turtle={};format=document.createElement('div');while(parts.container.firstChild){parts.container.removeChild(parts.container.firstChild);}parts.container.appendChild(format);reformat(state.width,state.height);update();};this.setHub=function(h){hub=h;};this.update=update;this.changed=function(){return changed;};this.talky=talky={'forward':{params:['number'],fn:function(d){move(d);}},'back':{params:['number'],fn:function(d){move(-d);}},'left':{params:['number'],fn:function(d){rotate(-d);}},'right':{params:['number'],fn:function(d){rotate(d);}},'setpos':{params:[Array],fn:function(pos){if(pos.length!==2||typeof pos[0]!=='number'||typeof pos[1]!=='number'){throw"setpos needs a list of two numbers";}setxy(pos[0],pos[1]);}},'setxy':{params:['number','number'],fn:setxy},'setx':{params:['number'],fn:function(x){setxy(x,state.y);}},'sety':{params:['number'],fn:function(y){setxy(state.x,y);}},'setheading':{params:['number'],fn:setheading},'home':{params:[],fn:function(){setheading(0);setxy(0,0);}},'pos':{params:[],fn:function(){return[state.x,state.y];}},'xcor':{params:[],fn:function(){return state.x;}},'ycor':{params:[],fn:function(){return state.y;}},'heading':{params:[],fn:function(){return state.heading;}},'towards':{params:[Array],fn:function(pos){var dx,dy,angle;dx=pos[0]-state.x;dy=pos[1]-state.y;angle=Math.atan2(dy,dx);return 90-angle*180/Math.PI;}},'showturtle':{params:[],fn:function(){state.shown=true;changed=true;}},'hideturtle':{params:[],fn:function(){state.shown=false;changed=true;}},'clean':{params:[],fn:function(){paper.ctx.fillStyle=state.background;paper.ctx.fillRect(-1,-1,state.width+1,state.height+1);changed=true;}},'clearscreen':{params:[],fn:function(){talky.home.fn();talky.clean.fn();changed=true;}},'setpapersize':{params:[Array],fn:function(dim){reformat(dim[0],dim[1]);changed=true;}},'papersize':{params:[],fn:function(){return[state.width,state.height];}},'filled':{params:[Array],fn:function(proc){startShape();proc=proc.slice(0);proc.push(endShape);return{'run':proc};}},'shown?':{params:[],fn:function(){return state.shown;}},'pendown':{params:[],fn:function(){state.down=true;changed=true;}},'penup':{params:[],fn:function(){state.down=false;changed=true;}},'setpencolor':{params:['string'],fn:function(c){state.pencolor=c;changed=true;}},'setpensize':{params:['number'],fn:function(n){state.pensize=n;changed=true;}},'setfillcolor':{params:['string'],fn:function(c){state.fillcolor=c;}},'setbackground':{params:['string'],fn:function(c){state.background=c;}},'pendown?':{params:[],fn:function(){return state.down;}},'pencolor':{params:[],fn:function(){return state.pencolor;}},'fillcolor':{params:[],fn:function(){return state.fillcolor;}},'pensize':{params:[],fn:function(){return state.pensize;}},'background':{params:[],fn:function(){return state.background;}}};(function(){var a,i;a={'fd':'forward','bk':'back','lt':'left','rt':'right','seth':'setheading','setpc':'setpencolor','setbg':'setbackground','pc':'pencolor','pu':'penup','pd':'pendown','ht':'hideturtle','st':'showturtle','cs':'clearscreen'};for(i in a){if(a.hasOwnProperty(i)){talky[i]=talky[a[i]];}}}());});Logo.Editor=function(parts){var init,balance,isolated,key,click,start,area,any;any=new RegExp(";.*([\\r\\n]\\s*|$)|(\"(\\\\?.)*?\"|\\S+)?(\\s+|$)",'g');init=function(){area=parts.textarea;area.attr('spellcheck',false).mousedown(function(){start=this.selectionStart;}).dblclick(click).keypress(key);};balance=function(code,pos){var open,close,depth,i,dir;open=code.charAt(pos);switch(open){case'[':close=']';dir=1;break;case']':close='[';dir=-1;break;default:return pos;}depth=0;for(i=pos;i<code.length;i+=dir){switch(code.charAt(i)){case open:if(isolated(code,i)){depth+=1;}break;case close:if(isolated(code,i)){depth-=1;}break;}if(depth===0){return i;}}return pos;};isolated=function(val,index){var pos,begin,end,tok;if((index>0&&val.charCodeAt(index-1)>32)||(index<val.length-1&&val.charCodeAt(index+1)>32)){return false;}begin=val.lastIndexOf('\n',index);end=val.indexOf('\n',index);val=val.substring(begin,end).match(any);pos=begin;do{tok=val.shift();pos+=tok.length;}while(pos<index);return tok.charAt(0)!=='"';};key=function(e){var self,val,start,first,last,i,depth,indent;if(e.keyCode===13){self=this;val=self.value;depth=0;indent='';start=0;first=self.selectionStart;last=0;loop:for(i=first-1;i>=0;i-=1){switch(val.charAt(i)){case'\n':case'\r':break loop;case'[':depth-=1;break;case']':depth+=1;break;}if(!last&&depth<0){last=i;}if(!last&&val.charCodeAt(i)>32){first=i;}}start=i+1;for(i=start;i<first;i+=1){indent+=' ';}setTimeout(function(){var pos,top;pos=self.selectionStart;top=self.scrollTop;self.value=self.value.substring(0,pos)+indent+self.value.substring(pos);pos+=indent.length;self.selectionStart=pos;self.selectionEnd=pos;self.scrollTop=top;},0);}return true;};click=function(){var end,swap;end=balance(this.value,start);if(end===start){start-=1;end=balance(this.value,start);if(end===start){return false;}}if(start>end){swap=start;start=end;end=swap;}this.selectionStart=start;this.selectionEnd=end+1;return false;};this.val=function(){return area.val();};init();};Logo.UI=function(parts){var $,hub,state,updateUI,enable,disable,check,uncheck,message,done,start,quick,run,startpaused,pause,step,resume,stop,reset,updates,duration,delay,useupdates,useduration,lastduration,apply,editor;$=jQuery;hub=parts.hub;editor=parts.editor;state='stopped';message=$('#status-message');quick=$('#quick');run=$('#run');startpaused=$('#startpaused');pause=$('#pause');step=$('#step');resume=$('#resume');stop=$('#stop');reset=$('#reset');updates=$('#updates');duration=$('#duration');delay=$('#delay');useupdates=$('#useupdates');useduration=$('#useduration');updateUI=function(){var options;options=hub.getOptions();lastduration=options.clumpyDuration;duration.val(lastduration);delay.val(options.clumpyDelay);updates.val(options.maxUpdatesPerClump);if(options.ignoreMaxUpdatesPerClump){uncheck(useupdates);disable(updates);}else{check(useupdates);enable(updates);}if(options.clumpyManual){uncheck(useduration);disable(duration);}else{check(useduration);enable(duration);}switch(state){case'running':message.html('<strong>Running.&nbsp;</strong> A Logo program is running right now.  You can Pause it, End it, or Reset the Logo environment, which will also end the program.');disable(run);disable(startpaused);disable(quick);enable(pause);disable(step);disable(resume);enable(stop);break;case'paused':message.html('<strong>Paused.&nbsp;</strong> A Logo program is running, but paused.  You can Resume it, End it, or Reset the Logo environment, which will also end the program.');disable(run);disable(startpaused);disable(quick);disable(pause);enable(step);enable(resume);enable(stop);break;case'stopped':message.html('<strong>Stopped.&nbsp;</strong> No Logo code is running at the moment.  You can start a program using the Quick Box or the Editor, or you can Reset the Logo environment.');enable(run);enable(startpaused);enable(quick);disable(pause);disable(step);disable(resume);disable(stop);break;}};enable=function(el){el.attr('disabled','');};disable=function(el){el.attr('disabled','disabled');};check=function(el){el.attr('checked','checked');};uncheck=function(el){el.attr('checked','');};done=function(){state='stopped';updateUI();};start=function(val,finish){var sp;sp=startpaused.is(':checked');if(state==='stopped'){state=sp?'paused':'running';setTimeout(updateUI,0);hub.run(val,finish);if(sp){hub.pause();}}};apply=function(el){el.focus();hub.setOptions({clumpyDelay:delay.val(),clumpyDuration:duration.val(),clumpyManual:!useduration.is(':checked'),maxUpdatesPerClump:updates.val(),ignoreMaxUpdatesPerClump:!useupdates.is(':checked')});updateUI();return false;};quick.each(function(){$(this.form).submit(function(){start(quick.val(),function(){done();quick.blur();quick.select();});return false;});});run.click(function(){start(editor.val(),done);return false;});pause.click(function(){if(state==='running'){state='paused';updateUI();hub.pause();}return false;});step.click(function(){if(state==='paused'){hub.next();}return false;});resume.click(function(){if(state==='paused'){state='running';updateUI();hub.resume();}return false;});stop.click(function(){if(state==='running'||state==='paused'){state='stopped';updateUI();hub.stop();}return false;});reset.click(function(){state='stopped';updateUI();hub.init();return false;});delay.change(function(){apply(this);});updates.change(function(){apply(this);});duration.change(function(){if((parseInt(duration.val(),10)||0)>1000){if(!confirm("Are you sure?  More than 1000ms between refreshes could cause your browser to hang.")){duration.val(lastduration);}}apply(this);});useupdates.click(function(){if(useupdates.is(':checked')){enable(updates);}else{disable(updates);}apply(this);});useduration.click(function(){if(useduration.is(':checked')){enable(duration);}else{if(confirm("Are you sure?  Disabling the timed refresh could cause your browser to hang.")){disable(duration);}else{check(useduration);}}apply(this);});updateUI();};