~ubuntu-branches/ubuntu/saucy/phpmyadmin/saucy-proposed

« back to all changes in this revision

Viewing changes to js/codemirror/lib/codemirror.js

  • Committer: Package Import Robot
  • Author(s): Thijs Kinkhorst
  • Date: 2013-08-04 13:24:37 UTC
  • mfrom: (1.2.44)
  • Revision ID: package-import@ubuntu.com-20130804132437-jznw8efwy4hr1nms
Tags: 4:4.0.5-1
* New upstream release.
  - Fixes security issue PMASA-2013-10.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
window.CodeMirror=(function(){function r(a9,a5){var ct={},bG=r.defaults;for(var aX in bG){if(bG.hasOwnProperty(aX)){ct[aX]=(a5&&a5.hasOwnProperty(aX)?a5:bG)[aX]}}var bJ=ak("textarea",null,null,"position: absolute; padding: 0; width: 1px; height: 1em");bJ.setAttribute("wrap","off");bJ.setAttribute("autocorrect","off");bJ.setAttribute("autocapitalize","off");var cp=ak("div",[bJ],null,"overflow: hidden; position: relative; width: 3px; height: 0px;");var cR=ak("div",null,"CodeMirror-scrollbar-inner");var a8=ak("div",[cR],"CodeMirror-scrollbar");var aO=ak("div"),bD=ak("div",null,null,"position: relative; z-index: -1");var bA=ak("pre","\u00a0","CodeMirror-cursor"),bu=ak("pre","\u00a0","CodeMirror-cursor","visibility: hidden");var aT=ak("div",null,null,"position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;");var bU=ak("div",[aT,bA,bu,bD,aO],null,"position: relative; z-index: 0");var bl=ak("div",null,"CodeMirror-gutter-text"),a3=ak("div",[bl],"CodeMirror-gutter");var cM=ak("div",[a3,ak("div",[bU],"CodeMirror-lines")],null,"position: relative");var cC=ak("div",[cM],null,"position: relative");var bH=ak("div",[cC],"CodeMirror-scroll");bH.setAttribute("tabIndex","-1");var a1=ak("div",[cp,a8,bH],"CodeMirror"+(ct.lineWrapping?" CodeMirror-wrap":""));if(a9.appendChild){a9.appendChild(a1)}else{a9(a1)}c8();c1();if(i){bJ.style.width="0px"}if(!m){bH.draggable=true}bU.style.outline="none";if(ct.tabindex!=null){bJ.tabIndex=ct.tabindex}if(ct.autofocus){b1()}if(!ct.gutter&&!ct.lineNumbers){a3.style.display="none"}if(ah){cp.style.height="1px",cp.style.position="absolute"}if(W){a8.style.zIndex=-2;a8.style.visibility="hidden"}else{if(L){a8.style.minWidth="18px"}}var cA=new j(),aU=new j(),dl;var cH,c4=new al([new Q([new J("")])]),df=0,cO;cm();var dt={from:{line:0,ch:0},to:{line:0,ch:0},inverted:false};var cN,bO,bn,bW=0,bz,cT=false,cY=false,cf=false;var cV,cz,aZ,dj,bc,bf,c5;var bB=0,dm=0,cc=0,cd=0;var cw;var b6=db(0),c9=false,bN=true;var bS=false;var c0=null;aP(function(){bj(ct.value||"");cV=false})();var bx=new F();aE(bH,"mousedown",aP(cP));aE(bH,"dblclick",aP(co));aE(bU,"selectstart",f);if(!x){aE(bH,"contextmenu",bp)}aE(bH,"scroll",cE);aE(a8,"scroll",b2);aE(a8,"mousedown",function(){if(cO){setTimeout(b1,0)}});var cD=aE(window,"resize",function(){if(a1.parentNode){cJ(true)}else{cD()}},true);aE(bJ,"keyup",aP(cQ));aE(bJ,"input",bd);aE(bJ,"keydown",aP(cI));aE(bJ,"keypress",aP(bK));aE(bJ,"focus",dr);aE(bJ,"blur",a2);function b5(dv){if(ct.onDragEvent&&ct.onDragEvent(cF,R(dv))){return}ae(dv)}if(ct.dragDrop){aE(bH,"dragstart",a4);aE(bH,"dragenter",b5);aE(bH,"dragover",b5);aE(bH,"drop",aP(aK))}aE(bH,"paste",function(){b1();bd()});aE(bJ,"paste",function(){cf=true;bd()});aE(bJ,"cut",aP(function(){if(!ct.readOnly){bR("")}}));if(ah){aE(cC,"mouseup",function(){if(document.activeElement==bJ){bJ.blur()}b1()})}var c2;try{c2=(document.activeElement==bJ)}catch(cB){}if(c2||ct.autofocus){setTimeout(dr,20)}else{a2()}function bQ(dv){return dv>=0&&dv<c4.size}var cF=a1.CodeMirror={getValue:cu,setValue:aP(bj),getSelection:cv,replaceSelection:aP(bR),focus:function(){window.focus();b1();dr();bd()},setOption:function(dw,dx){var dv=ct[dw];ct[dw]=dx;if(dw=="mode"||dw=="indentUnit"){cm()}else{if(dw=="readOnly"&&dx=="nocursor"){a2();bJ.blur()}else{if(dw=="readOnly"&&!dx){c7(true)}else{if(dw=="theme"){c8()}else{if(dw=="lineWrapping"&&dv!=dx){aP(dc)()}else{if(dw=="tabSize"){cJ(true)}else{if(dw=="keyMap"){c1()}else{if(dw=="tabindex"){bJ.tabIndex=dx}else{if(dw=="showCursorWhenSelecting"){ds()}}}}}}}}}if(dw=="lineNumbers"||dw=="gutter"||dw=="firstLineNumber"||dw=="theme"||dw=="lineNumberFormatter"){bC();cJ(true)}},getOption:function(dv){return ct[dv]},getMode:function(){return cH},undo:aP(dq),redo:aP(de),indentLine:aP(function(dw,dv){if(typeof dv!="string"){if(dv==null){dv=ct.smartIndent?"smart":"prev"}else{dv=dv?"add":"subtract"}}if(bQ(dw)){b0(dw,dv)}}),indentSelection:aP(c6),historySize:function(){return{undo:bx.done.length,redo:bx.undone.length}},clearHistory:function(){bx=new F()},setHistory:function(dv){bx=new F();bx.done=dv.done;bx.undone=dv.undone},getHistory:function(){function dv(dB){for(var dA=0,dC=[],dD;dA<dB.length;++dA){dC.push(dD=[]);for(var dz=0,dy=dB[dA];dz<dy.length;++dz){var dw=[],dE=dy[dz];dD.push({start:dE.start,added:dE.added,old:dw});for(var dx=0;dx<dE.old.length;++dx){dw.push(au(dE.old[dx]))}}}return dC}return{done:dv(bx.done),undone:dv(bx.undone)}},matchBrackets:aP(function(){cK(true)}),getTokenAt:aP(function(dv){dv=bg(dv);return db(dv.line).getTokenAt(cH,cZ(dv.line),ct.tabSize,dv.ch)}),getStateAfter:function(dv){dv=cr(dv==null?c4.size-1:dv);return cZ(dv+1)},cursorCoords:function(dw,dv){if(dw==null){dw=dt.inverted}return this.charCoords(dw?dt.from:dt.to,dv)},charCoords:function(dw,dv){dw=bg(dw);if(dv=="local"){return dn(dw,false)}if(dv=="div"){return dn(dw,true)}return aM(dw)},coordsChar:function(dv){var dw=B(bU);return b9(dv.x-dw.left,dv.y-dw.top)},defaultTextHeight:function(){return ch()},markText:aP(b7),setBookmark:bh,findMarksAt:bL,setMarker:aP(cn),clearMarker:aP(aS),setLineClass:aP(bI),hideLine:aP(function(dv){return dg(dv,true)}),showLine:aP(function(dv){return dg(dv,false)}),onDeleteLine:function(dv,dw){if(typeof dv=="number"){if(!bQ(dv)){return null}dv=db(dv)}(dv.handlers||(dv.handlers=[])).push(dw);return dv},lineInfo:bi,getViewport:function(){return{from:dm,to:cc}},addWidget:function(dz,dx,dB,dy,dD){dz=dn(bg(dz));var dA=dz.yBot,dw=dz.x;dx.style.position="absolute";cC.appendChild(dx);if(dy=="over"){dA=dz.y}else{if(dy=="near"){var dv=Math.max(bH.offsetHeight,c4.height*ch()),dC=Math.max(cC.clientWidth,bU.clientWidth)-bt();if(dz.yBot+dx.offsetHeight>dv&&dz.y>dx.offsetHeight){dA=dz.y-dx.offsetHeight}if(dw+dx.offsetWidth>dC){dw=dC-dx.offsetWidth}}}dx.style.top=(dA+cX())+"px";dx.style.left=dx.style.right="";if(dD=="right"){dw=cC.clientWidth-dx.offsetWidth;dx.style.right="0px"}else{if(dD=="left"){dw=0}else{if(dD=="middle"){dw=(cC.clientWidth-dx.offsetWidth)/2}}dx.style.left=(dw+bt())+"px"}if(dB){aY(dw,dA,dw+dx.offsetWidth,dA+dx.offsetHeight)}},lineCount:function(){return c4.size},clipPos:bg,getCursor:function(dv){if(dv==null||dv=="head"){dv=dt.inverted}if(dv=="anchor"){dv=!dt.inverted}if(dv=="end"){dv=false}return aa(dv?dt.from:dt.to)},somethingSelected:function(){return !T(dt.from,dt.to)},setCursor:aP(function(dv,dx,dw){if(dx==null&&typeof dv.line=="number"){bv(dv.line,dv.ch,dw)}else{bv(dv,dx,dw)}}),setSelection:aP(function(dx,dw,dv){(dv?bZ:bX)(bg(dx),bg(dw||dx))}),getLine:function(dv){if(bQ(dv)){return db(dv).text}},getLineHandle:function(dv){if(bQ(dv)){return db(dv)}},setLine:aP(function(dv,dw){if(bQ(dv)){ci(dw,{line:dv,ch:0},{line:dv,ch:db(dv).text.length})}}),removeLine:aP(function(dv){if(bQ(dv)){ci("",{line:dv,ch:0},bg({line:dv+1,ch:0}))}}),replaceRange:aP(ci),getRange:function(dx,dw,dv){return dk(bg(dx),bg(dw),dv)},triggerOnKeyDown:aP(cI),execCommand:function(dv){return t[dv](cF)},moveH:aP(da),deleteH:aP(cS),moveV:aP(c3),toggleOverwrite:function(){if(cT){cT=false;bA.className=bA.className.replace(" CodeMirror-overwrite","")}else{cT=true;bA.className+=" CodeMirror-overwrite"}},posFromIndex:function(dw){var dx=0,dv;c4.iter(0,c4.size,function(dy){var dz=dy.text.length+1;if(dz>dw){dv=dw;return true}dw-=dz;++dx});return bg({line:dx,ch:dv})},indexFromPos:function(dw){if(dw.line<0||dw.ch<0){return 0}var dv=dw.ch;c4.iter(0,dw.line,function(dx){dv+=dx.text.length+1});return dv},scrollTo:function(dv,dw){if(dv!=null){bH.scrollLeft=dv}if(dw!=null){a8.scrollTop=bH.scrollTop=dw}cJ([])},getScrollInfo:function(){return{x:bH.scrollLeft,y:a8.scrollTop,height:a8.scrollHeight,width:bH.scrollWidth}},scrollIntoView:function(dw){var dv=dn(dw?bg(dw):dt.inverted?dt.from:dt.to);aY(dv.x,dv.y,dv.x,dv.yBot)},setSize:function(dx,dv){function dw(dy){dy=String(dy);return/^\d+$/.test(dy)?dy+"px":dy}if(dx!=null){a1.style.width=dw(dx)}if(dv!=null){bH.style.height=dw(dv)}cF.refresh()},operation:function(dv){return aP(dv)()},compoundChange:function(dv){return cg(dv)},refresh:function(){cJ(true,null,bW);if(a8.scrollHeight>bW){a8.scrollTop=bW}},getInputField:function(){return bJ},getWrapperElement:function(){return a1},getScrollerElement:function(){return bH},getGutterElement:function(){return a3}};function db(dv){return M(c4,dv)}function br(dw,dv){bf=true;var dx=dv-dw.height;for(var dy=dw;dy;dy=dy.parent){dy.height+=dx}}function ce(dv,dw){if(!dv.styles){dv.highlight(cH,dv.stateAfter=cZ(X(dv)),ct.tabSize)}return dv.getContent(ct.tabSize,dw,ct.lineWrapping)}function bj(dv){var dw={line:0,ch:0};bb(dw,{line:c4.size-1,ch:db(c4.size-1).text.length},h(dv),dw,dw);cV=true}function cu(dw){var dv=[];c4.iter(0,c4.size,function(dx){dv.push(dx.text)});return dv.join(dw||"\n")}function b2(dv){if(Math.abs(a8.scrollTop-bW)>1){bW=bH.scrollTop=a8.scrollTop;cJ([])}}function cE(dv){if(ct.fixedGutter&&a3.style.left!=bH.scrollLeft+"px"){a3.style.left=bH.scrollLeft+"px"}if(Math.abs(bH.scrollTop-bW)>1){bW=bH.scrollTop;if(a8.scrollTop!=bW){a8.scrollTop=bW}cJ([])}if(ct.onScroll){ct.onScroll(cF)}}function cP(dH){bs(ad(dH,"shiftKey"));for(var dB=ar(dH);dB!=a1;dB=dB.parentNode){if(dB.parentNode==cC&&dB!=cM){return}}for(var dB=ar(dH);dB!=a1;dB=dB.parentNode){if(dB.parentNode==bl){if(ct.onGutterClick){ct.onGutterClick(cF,u(bl.childNodes,dB)+dm,dH)}return f(dH)}}var dw=bq(dH);switch(E(dH)){case 3:if(x){bp(dH)}return;case 2:if(dw){bv(dw.line,dw.ch,true)}setTimeout(b1,20);f(dH);return}if(!dw){if(ar(dH)==bH){f(dH)}return}if(!cO){dr()}var dx=+new Date,dK="single";if(bn&&bn.time>dx-400&&T(bn.pos,dw)){dK="triple";f(dH);setTimeout(b1,20);a6(dw.line)}else{if(bO&&bO.time>dx-400&&T(bO.pos,dw)){dK="double";bn={time:dx,pos:dw};f(dH);var dv=bT(dw);bZ(dv.from,dv.to)}else{bO={time:dx,pos:dw}}}function dC(dM){if(m){bH.draggable=false}bz=false;dG();dA();if(Math.abs(dH.clientX-dM.clientX)+Math.abs(dH.clientY-dM.clientY)<10){f(dM);bv(dw.line,dw.ch,true);b1()}}var dL=dw,dz;if(ct.dragDrop&&ac&&!ct.readOnly&&!T(dt.from,dt.to)&&!D(dw,dt.from)&&!D(dt.to,dw)&&dK=="single"){if(m){bH.draggable=true}var dG=aE(document,"mouseup",aP(dC),true);var dA=aE(bH,"drop",aP(dC),true);bz=true;if(bH.dragDrop){bH.dragDrop()}return}f(dH);if(dK=="single"){bv(dw.line,dw.ch,true)}var dJ=dt.from,dy=dt.to;function dE(dN){if(dK=="single"){bZ(bg(dw),dN);return}dJ=bg(dJ);dy=bg(dy);if(dK=="double"){var dM=bT(dN);if(D(dN,dJ)){bZ(dM.from,dy)}else{bZ(dJ,dM.to)}}else{if(dK=="triple"){if(D(dN,dJ)){bZ(dy,bg({line:dN.line,ch:0}))}else{bZ(dJ,bg({line:dN.line+1,ch:0}))}}}}function dI(dM){var dO=bq(dM,true);if(dO&&!T(dO,dL)){if(!cO){dr()}dL=dO;dE(dO);cV=false;var dN=b3();if(dO.line>=dN.to||dO.line<dN.from){dz=setTimeout(aP(function(){dI(dM)}),150)}}}function dF(dM){clearTimeout(dz);var dN=bq(dM);if(dN){dE(dN)}f(dM);b1();cV=true;dD();dG()}var dD=aE(document,"mousemove",aP(function(dM){clearTimeout(dz);f(dM);if(!U&&!E(dM)){dF(dM)}else{dI(dM)}}),true);var dG=aE(document,"mouseup",aP(dF),true)}function co(dv){for(var dw=ar(dv);dw!=a1;dw=dw.parentNode){if(dw.parentNode==bl){return f(dv)}}f(dv)}function aK(dz){if(ct.onDragEvent&&ct.onDragEvent(cF,R(dz))){return}f(dz);var dC=bq(dz,true),dw=dz.dataTransfer.files;if(!dC||ct.readOnly){return}if(dw&&dw.length&&window.FileReader&&window.File){var dB=dw.length,dA=Array(dB),dx=0;var dy=function(dF,dE){var dD=new FileReader;dD.onload=function(){dA[dE]=dD.result;if(++dx==dB){dC=bg(dC);aP(function(){var dG=ci(dA.join(""),dC,dC);bZ(dC,dG)})()}};dD.readAsText(dF)};for(var dv=0;dv<dB;++dv){dy(dw[dv],dv)}}else{if(bz&&!(D(dC,dt.from)||D(dt.to,dC))){return}try{var dA=dz.dataTransfer.getData("Text");if(dA){cg(function(){var dE=dt.from,dD=dt.to;bZ(dC,dC);if(bz){ci("",dE,dD)}bR(dA);b1()})}}catch(dz){}}}function a4(dw){var dv=cv();dw.dataTransfer.setData("Text",dv);if(dw.dataTransfer.setDragImage){dw.dataTransfer.setDragImage(ak("img"),0,0)}}function bF(dx,dv){if(typeof dx=="string"){dx=t[dx];if(!dx){return false}}var dw=cN;try{if(ct.readOnly){cY=true}if(dv){cN=null}dx(cF)}catch(dy){if(dy!=aq){throw dy}return false}finally{cN=dw;cY=false}return true}var b4;function dh(dB){var dv=at(ct.keyMap),dy=dv.auto;clearTimeout(b4);if(dy&&!aj(dB)){b4=setTimeout(function(){if(at(ct.keyMap)==dv){ct.keyMap=(dy.call?dy.call(null,cF):dy)}},50)}var dw=w[ad(dB,"keyCode")],dA=false;if(dw==null||dB.altGraphKey){return false}if(ad(dB,"altKey")){dw="Alt-"+dw}if(ad(dB,d?"metaKey":"ctrlKey")){dw="Ctrl-"+dw}if(ad(dB,d?"ctrlKey":"metaKey")){dw="Cmd-"+dw}var dz=false;function dx(){dz=true}if(ad(dB,"shiftKey")){dA=av("Shift-"+dw,ct.extraKeys,ct.keyMap,function(dC){return bF(dC,true)},dx)||av(dw,ct.extraKeys,ct.keyMap,function(dC){if(typeof dC=="string"&&/^go[A-Z]/.test(dC)){return bF(dC)}},dx)}else{dA=av(dw,ct.extraKeys,ct.keyMap,bF,dx)}if(dz){dA=false}if(dA){f(dB);di();if(I){dB.oldKeyCode=dB.keyCode;dB.keyCode=0}}return dA}function cq(dx,dv){var dw=av("'"+dv+"'",ct.extraKeys,ct.keyMap,function(dy){return bF(dy,true)});if(dw){f(dx);di()}return dw}var dd=null;function cI(dx){if(!cO){dr()}if(U&&dx.keyCode==27){dx.returnValue=false}if(bS){if(cb()){bS=false}}if(ct.onKeyEvent&&ct.onKeyEvent(cF,R(dx))){return}var dv=ad(dx,"keyCode");bs(dv==16||ad(dx,"shiftKey"));var dw=dh(dx);if(ax){dd=dw?dv:null;if(!dw&&dv==88&&ad(dx,K?"metaKey":"ctrlKey")){bR("")}}}function bK(dy){if(bS){cb()}if(ct.onKeyEvent&&ct.onKeyEvent(cF,R(dy))){return}var dx=ad(dy,"keyCode"),dv=ad(dy,"charCode");if(ax&&dx==dd){dd=null;f(dy);return}if(((ax&&(!dy.which||dy.which<10))||ah)&&dh(dy)){return}var dw=String.fromCharCode(dv==null?dx:dv);if(ct.electricChars&&cH.electricChars&&ct.smartIndent&&!ct.readOnly){if(cH.electricChars.indexOf(dw)>-1){setTimeout(aP(function(){b0(dt.to.line,"smart")}),75)}}if(cq(dy,dw)){return}bd()}function cQ(dv){if(ct.onKeyEvent&&ct.onKeyEvent(cF,R(dv))){return}if(ad(dv,"keyCode")==16){cN=null}}function dr(){if(ct.readOnly=="nocursor"){return}if(!cO){if(ct.onFocus){ct.onFocus(cF)}cO=true;if(bH.className.search(/\bCodeMirror-focused\b/)==-1){bH.className+=" CodeMirror-focused"}}aJ();di()}function a2(){if(cO){if(ct.onBlur){ct.onBlur(cF)}cO=false;if(cw){aP(function(){if(cw){cw();cw=null}})()}bH.className=bH.className.replace(" CodeMirror-focused","")}clearInterval(dl);setTimeout(function(){if(!cO){cN=null}},150)}function bb(dB,dA,dz,dw,dv){if(cY){return}var dy=[];c4.iter(dB.line,dA.line+1,function(dC){dy.push(k(dC.text,dC.markedSpans))});if(bx){bx.addChange(dB.line,dz.length,dy);while(bx.done.length>ct.undoDepth){bx.done.shift()}}var dx=Y(e(dy[0]),e(P(dy)),dB.ch,dA.ch,dz);aQ(dB,dA,dx,dw,dv)}function cG(dA,dB){if(!dA.length){return}var dC=dA.pop(),dw=[];for(var dx=dC.length-1;dx>=0;dx-=1){var dz=dC[dx];var dD=[],dv=dz.start+dz.added;c4.iter(dz.start,dv,function(dE){dD.push(k(dE.text,dE.markedSpans))});dw.push({start:dz.start,added:dz.old.length,old:dD});var dy={line:dz.start+dz.old.length-1,ch:C(au(P(dD)),au(P(dz.old)))};aQ({line:dz.start,ch:0},{line:dv-1,ch:db(dv-1).text.length},dz.old,dy,dy)}cV=true;dB.push(dw)}function dq(){cG(bx.done,bx.undone)}function de(){cG(bx.undone,bx.done)}function aQ(dK,dz,dw,dv,dO){if(cY){return}var dN=false,dy=b6.text.length;if(!ct.lineWrapping){c4.iter(dK.line,dz.line+1,function(dP){if(!dP.hidden&&dP.text.length==dy){dN=true;return true}})}if(dK.line!=dz.line||dw.length>1){bf=true}var dI=dz.line-dK.line,dH=db(dK.line),dx=db(dz.line);var dE=P(dw);if(dK.ch==0&&dz.ch==0&&au(dE)==""){var dF=[],dG=null;for(var dL=0,dM=dw.length-1;dL<dM;++dL){dF.push(new J(au(dw[dL]),e(dw[dL])))}dx.update(dx.text,e(dE));if(dI){c4.remove(dK.line,dI,c5)}if(dF.length){c4.insert(dK.line,dF)}}else{if(dH==dx){if(dw.length==1){dH.update(dH.text.slice(0,dK.ch)+au(dw[0])+dH.text.slice(dz.ch),e(dw[0]))}else{for(var dF=[],dL=1,dM=dw.length-1;dL<dM;++dL){dF.push(new J(au(dw[dL]),e(dw[dL])))}dF.push(new J(au(dE)+dH.text.slice(dz.ch),e(dE)));dH.update(dH.text.slice(0,dK.ch)+au(dw[0]),e(dw[0]));c4.insert(dK.line+1,dF)}}else{if(dw.length==1){dH.update(dH.text.slice(0,dK.ch)+au(dw[0])+dx.text.slice(dz.ch),e(dw[0]));c4.remove(dK.line+1,dI,c5)}else{var dF=[];dH.update(dH.text.slice(0,dK.ch)+au(dw[0]),e(dw[0]));dx.update(au(dE)+dx.text.slice(dz.ch),e(dE));for(var dL=1,dM=dw.length-1;dL<dM;++dL){dF.push(new J(au(dw[dL]),e(dw[dL])))}if(dI>1){c4.remove(dK.line+1,dI-1,c5)}c4.insert(dK.line+1,dF)}}}if(ct.lineWrapping){var dB=Math.max(5,bH.clientWidth/bE()-3);c4.iter(dK.line,dK.line+dw.length,function(dP){if(dP.hidden){return}var dQ=Math.ceil(dP.text.length/dB)||1;if(dQ!=dP.height){br(dP,dQ)}})}else{c4.iter(dK.line,dK.line+dw.length,function(dQ){var dP=dQ.text;if(!dQ.hidden&&dP.length>dy){b6=dQ;dy=dP.length;bN=true;dN=false}});if(dN){c9=true}}df=Math.min(df,dK.line);b8(400);var dD=dw.length-dI-1;aZ.push({from:dK.line,to:dz.line+1,diff:dD});if(ct.onChange){for(var dL=0;dL<dw.length;++dL){if(typeof dw[dL]!="string"){dw[dL]=dw[dL].text}}var dC={from:dK,to:dz,text:dw};if(dj){for(var dA=dj;dA.next;dA=dA.next){}dA.next=dC}else{dj=dC}}function dJ(dP){return dP<=Math.min(dz.line,dz.line+dD)?dP:dP+dD}bX(bg(dv),bg(dO),dJ(dt.from.line),dJ(dt.to.line))}function aN(){var dv=c4.height*ch()+2*cX();return dv*0.99>bH.offsetHeight?dv:false}function aR(dw){var dv=aN();a8.style.display=dv?"block":"none";if(dv){cR.style.height=cC.style.minHeight=dv+"px";a8.style.height=bH.clientHeight+"px";if(dw!=null){a8.scrollTop=bH.scrollTop=dw;if(m){setTimeout(function(){if(a8.scrollTop!=dw){return}a8.scrollTop=dw+(dw?-1:1);a8.scrollTop=dw},0)}}}else{cC.style.minHeight=""}cM.style.top=bB*ch()+"px"}function bY(){b6=db(0);bN=true;var dv=b6.text.length;c4.iter(1,c4.size,function(dx){var dw=dx.text;if(!dx.hidden&&dw.length>dv){dv=dw.length;b6=dx}});c9=false}function ci(dw,dz,dy){dz=bg(dz);if(!dy){dy=dz}else{dy=bg(dy)}dw=h(dw);function dx(dC){if(D(dC,dz)){return dC}if(!D(dy,dC)){return dv}var dA=dC.line+dw.length-(dy.line-dz.line)-1;var dB=dC.ch;if(dC.line==dy.line){dB+=P(dw).length-(dy.ch-(dy.line==dz.line?dz.ch:0))}return{line:dA,ch:dB}}var dv;a0(dw,dz,dy,function(dA){dv=dA;return{from:dx(dt.from),to:dx(dt.to)}});return dv}function bR(dv,dw){a0(h(dv),dt.from,dt.to,function(dx){if(dw=="end"){return{from:dx,to:dx}}else{if(dw=="start"){return{from:dt.from,to:dt.from}}else{return{from:dt.from,to:dx}}}})}function a0(dy,dA,dz,dv){var dx=dy.length==1?dy[0].length+dA.ch:P(dy).length;var dw=dv({line:dA.line+dy.length-1,ch:dx});bb(dA,dz,dy,dw.from,dw.to)}function dk(dA,dz,dy){var dw=dA.line,dv=dz.line;if(dw==dv){return db(dw).text.slice(dA.ch,dz.ch)}var dx=[db(dw).text.slice(dA.ch)];c4.iter(dw+1,dv,function(dB){dx.push(dB.text)});dx.push(db(dv).text.slice(0,dz.ch));return dx.join(dy||"\n")}function cv(dv){return dk(dt.from,dt.to,dv)}function aJ(){if(bS){return}cA.set(ct.pollInterval,function(){cb();if(cO){aJ()}})}function bd(){var dv=false;bS=true;function dw(){var dx=cb();if(!dx&&!dv){dv=true;cA.set(60,dw)}else{bS=false;aJ()}}cA.set(20,dw)}var by="";function cb(){if(!cO||b(bJ)||ct.readOnly){return false}var dw=bJ.value;if(dw==by){return false}if(!cW){ba()}cN=null;var dx=0,dv=Math.min(by.length,dw.length);while(dx<dv&&by[dx]==dw[dx]){++dx}if(dx<by.length){dt.from={line:dt.from.line,ch:dt.from.ch-(by.length-dx)}}else{if(cT&&T(dt.from,dt.to)&&!cf){dt.to={line:dt.to.line,ch:Math.min(db(dt.to.line).text.length,dt.to.ch+(dw.length-dx))}}}bR(dw.slice(dx),"end");if(dw.length>1000){bJ.value=by=""}else{by=dw}if(!cW){aW()}cf=false;return true}function c7(dv){if(!T(dt.from,dt.to)){by="";bJ.value=cv();if(cO){aF(bJ)}}else{if(dv){by=bJ.value=""}}}function b1(){if(ct.readOnly!="nocursor"&&(I||document.activeElement!=bJ)){bJ.focus()}}function cL(){var dy=cj();aY(dy.x,dy.y,dy.x,dy.yBot);if(!cO){return}var dw=cC.getBoundingClientRect(),dv=null;if(dy.y+dw.top<0){dv=true}else{if(dy.y+dw.top+ch()>(window.innerHeight||document.documentElement.clientHeight)){dv=false}}if(dv!=null){var dx=bA.style.display=="none";if(dx){bA.style.display="";bA.style.left=dy.x+"px";bA.style.top=(dy.y-bB)+"px"}bA.scrollIntoView(dv);if(dx){bA.style.display="none"}}}function cj(){var dw=dn(dt.inverted?dt.from:dt.to);var dv=ct.lineWrapping?Math.min(dw.x,bU.offsetWidth):dw.x;return{x:dv,y:dw.y,yBot:dw.yBot}}function aY(dw,dy,dv,dx){var dz=bm(dw,dy,dv,dx);if(dz.scrollLeft!=null){bH.scrollLeft=dz.scrollLeft}if(dz.scrollTop!=null){a8.scrollTop=bH.scrollTop=dz.scrollTop}}function bm(dy,dF,dw,dE){var dB=bt(),dK=cX();dF+=dK;dE+=dK;dy+=dB;dw+=dB;var dH=bH.clientHeight,dz=a8.scrollTop,dJ={};var dx=aN()||Infinity;var dv=dF<dK+10,dD=dE+dK>dx-10;if(dF<dz){dJ.scrollTop=dv?0:Math.max(0,dF)}else{if(dE>dz+dH){dJ.scrollTop=(dD?dx:dE)-dH}}var dG=bH.clientWidth,dI=bH.scrollLeft;var dC=ct.fixedGutter?a3.clientWidth:0;var dA=dy<dC+dB+10;if(dy<dI+dC||dA){if(dA){dy=0}dJ.scrollLeft=Math.max(0,dy-10-dC)}else{if(dw>dG+dI-3){dJ.scrollLeft=dw+10-dG}}return dJ}function b3(dz){var dv=ch(),dy=(dz!=null?dz:a8.scrollTop)-cX();var dx=Math.max(0,Math.floor(dy/dv));var dw=Math.ceil((dy+bH.clientHeight)/dv);return{from:af(c4,dx),to:af(c4,dw)}}function cJ(dE,dA,dy){if(!bH.clientWidth){dm=cc=bB=0;return}var dz=b3(dy);if(dE!==true&&dE.length==0&&dz.from>dm&&dz.to<cc){aR(dy);return}var dF=Math.max(dz.from-100,0),dG=Math.min(c4.size,dz.to+100);if(dm<dF&&dF-dm<20){dF=dm}if(cc>dG&&cc-dG<20){dG=Math.min(c4.size,cc)}var dI=dE===true?[]:cs([{from:dm,to:cc,domStart:0}],dE);var dD=0;for(var dB=0;dB<dI.length;++dB){var dC=dI[dB];if(dC.from<dF){dC.domStart+=(dF-dC.from);dC.from=dF}if(dC.to>dG){dC.to=dG}if(dC.from>=dC.to){dI.splice(dB--,1)}else{dD+=dC.to-dC.from}}if(dD==dG-dF&&dF==dm&&dG==cc){aR(dy);return}dI.sort(function(dK,dJ){return dK.domStart-dJ.domStart});var dx=ch(),dv=a3.style.display;aO.style.display="none";be(dF,dG,dI);aO.style.display=a3.style.display="";var dw=dF!=dm||dG!=cc||cd!=bH.clientHeight+dx;if(dw){cd=bH.clientHeight+dx}if(dF!=dm||dG!=cc&&ct.onViewportChange){setTimeout(function(){if(ct.onViewportChange){ct.onViewportChange(cF,dF,dG)}})}dm=dF;cc=dG;bB=a(c4,dF);b8(100);if(aO.childNodes.length!=cc-dm){throw new Error("BAD PATCH! "+JSON.stringify(dI)+" size="+(cc-dm)+" nodes="+aO.childNodes.length)}function dH(){var dK=aO.firstChild,dJ=false;c4.iter(dm,cc,function(dM){if(!dK){return}if(!dM.hidden){var dL=Math.round(dK.offsetHeight/dx)||1;if(dM.height!=dL){br(dM,dL);bf=dJ=true}}dK=dK.nextSibling});return dJ}if(ct.lineWrapping){dH()}a3.style.display=dv;if(dw||bf){a7()&&ct.lineWrapping&&dH()&&a7()}aR(dy);ds();if(!dA&&ct.onUpdate){ct.onUpdate(cF)}return true}function cs(dE,dC){for(var dz=0,dx=dC.length||0;dz<dx;++dz){var dB=dC[dz],dv=[],dD=dB.diff||0;for(var dy=0,dw=dE.length;dy<dw;++dy){var dA=dE[dy];if(dB.to<=dA.from&&dB.diff){dv.push({from:dA.from+dD,to:dA.to+dD,domStart:dA.domStart})}else{if(dB.to<=dA.from||dB.from>=dA.to){dv.push(dA)}else{if(dB.from>dA.from){dv.push({from:dA.from,to:dB.from,domStart:dA.domStart})}if(dB.to<dA.to){dv.push({from:dB.to+dD,to:dA.to+dD,domStart:dA.domStart+(dB.to-dA.from)})}}}}dE=dv}return dE}function be(dD,dE,dG){function dv(dI){var dH=dI.nextSibling;dI.parentNode.removeChild(dI);return dH}if(!dG.length){aH(aO)}else{var dz=0,dx=aO.firstChild,dw;for(var dA=0;dA<dG.length;++dA){var dF=dG[dA];while(dF.domStart>dz){dx=dv(dx);dz++}for(var dy=0,dC=dF.to-dF.from;dy<dC;++dy){dx=dx.nextSibling;dz++}}while(dx){dx=dv(dx)}}var dB=dG.shift(),dx=aO.firstChild,dy=dD;c4.iter(dD,dE,function(dH){if(dB&&dB.to==dy){dB=dG.shift()}if(!dB||dB.from>dy){if(dH.hidden){var dI=ak("pre")}else{var dI=ce(dH);if(dH.className){dI.className=dH.className}if(dH.bgClassName){var dJ=ak("pre","\u00a0",dH.bgClassName,"position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2");dI=ak("div",[dJ,dI],null,"position: relative")}}aO.insertBefore(dI,dx)}else{dx=dx.nextSibling}++dy})}function a7(){if(!ct.gutter&&!ct.lineNumbers){return}var dw=cM.offsetHeight,dE=bH.clientHeight;a3.style.height=(dw-dE<2?dE:dw)+"px";var dC=document.createDocumentFragment(),dA=dm,dD;c4.iter(dm,Math.max(cc,dm+1),function(dG){if(dG.hidden){dC.appendChild(ak("pre"))}else{var dF=dG.gutterMarker;var dJ=ct.lineNumbers?ct.lineNumberFormatter(dA+ct.firstLineNumber):null;if(dF&&dF.text){dJ=dF.text.replace("%N%",dJ!=null?dJ:"")}else{if(dJ==null){dJ="\u00a0"}}var dI=dC.appendChild(ak("pre",null,dF&&dF.style));dI.innerHTML=dJ;for(var dH=1;dH<dG.height;++dH){dI.appendChild(ak("br"));dI.appendChild(document.createTextNode("\u00a0"))}if(!dF){dD=dA}}++dA});a3.style.display="none";s(bl,dC);if(dD!=null&&ct.lineNumbers){var dy=bl.childNodes[dD-dm];var dz=String(c4.size).length,dv=aB(dy.firstChild),dx="";while(dv.length+dx.length<dz){dx+="\u00a0"}if(dx){dy.insertBefore(document.createTextNode(dx),dy.firstChild)}}a3.style.display="";var dB=Math.abs((parseInt(bU.style.marginLeft)||0)-a3.offsetWidth)>2;bU.style.marginLeft=a3.offsetWidth+"px";bf=false;return dB}function ds(){var dy=T(dt.from,dt.to);var dJ=dn(dt.from,true);var dE=dy?dJ:dn(dt.to,true);var dC=dt.inverted?dJ:dE,dw=ch();var dv=B(a1),dx=B(aO);cp.style.top=Math.max(0,Math.min(bH.offsetHeight,dC.y+dx.top-dv.top))+"px";cp.style.left=Math.max(0,Math.min(bH.offsetWidth,dC.x+dx.left-dv.left))+"px";if(dy||ct.showCursorWhenSelecting){bA.style.top=dC.y+"px";bA.style.left=(ct.lineWrapping?Math.min(dC.x,bU.offsetWidth):dC.x)+"px";bA.style.display=""}else{bA.style.display="none"}if(!dy){var dH=dJ.y==dE.y,dB=document.createDocumentFragment();var dF=bU.clientWidth||bU.offsetWidth;var dA=bU.clientHeight||bU.offsetHeight;var dI=function(dO,dN,dM,dK){var dL=n?"width: "+(!dM?dF:dF-dM-dO)+"px":"right: "+(dM-1)+"px";dB.appendChild(ak("div",null,"CodeMirror-selected","position: absolute; left: "+dO+"px; top: "+dN+"px; "+dL+"; height: "+dK+"px"))};if(dt.from.ch&&dJ.y>=0){var dG=dH?dF-dE.x:0;dI(dJ.x,dJ.y,dG,dw)}var dz=Math.max(0,dJ.y+(dt.from.ch?dw:0));var dD=Math.min(dE.y,dA)-dz;if(dD>0.2*dw){dI(0,dz,0,dD)}if((!dH||!dt.from.ch)&&dE.y<dA-0.5*dw){dI(0,dE.y,dF-dE.x,dw)}s(bD,dB);bD.style.display=""}else{bD.style.display="none"}}function bs(dv){if(dv){cN=cN||(dt.inverted?dt.to:dt.from)}else{cN=null}}function bZ(dx,dw){var dv=cN&&bg(cN);if(dv){if(D(dv,dx)){dx=dv}else{if(D(dw,dv)){dw=dv}}}bX(dx,dw);cz=true}function bX(dC,dB,dv,dA){c0=null;if(dv==null){dv=dt.from.line;dA=dt.to.line}if(T(dt.from,dC)&&T(dt.to,dB)){return}if(D(dB,dC)){var dy=dB;dB=dC;dC=dy}if(dC.line!=dv){var dz=ck(dC,dv,dt.from.ch);if(!dz){dg(dC.line,false)}else{dC=dz}}if(dB.line!=dA){dB=ck(dB,dA,dt.to.ch)}if(T(dC,dB)){dt.inverted=false}else{if(T(dC,dt.to)){dt.inverted=false}else{if(T(dB,dt.from)){dt.inverted=true}}}if(ct.autoClearEmptyLines&&T(dt.from,dt.to)){var dx=dt.inverted?dC:dB;if(dx.line!=dt.from.line&&dt.from.line<c4.size){var dw=db(dt.from.line);if(/^\s+$/.test(dw.text)){setTimeout(aP(function(){if(dw.parent&&/^\s+$/.test(dw.text)){var dD=X(dw);ci("",{line:dD,ch:0},{line:dD,ch:dw.text.length})}},10))}}}dt.from=dC;dt.to=dB;bc=true}function ck(dA,dw,dx){function dz(dD){var dF=dA.line+dD,dC=dD==1?c4.size:-1;while(dF!=dC){var dB=db(dF);if(!dB.hidden){var dE=dA.ch;if(dy||dE>dx||dE>dB.text.length){dE=dB.text.length}return{line:dF,ch:dE}}dF+=dD}}var dv=db(dA.line);var dy=dA.ch==dv.text.length&&dA.ch!=dx;if(!dv.hidden){return dA}if(dA.line>=dw){return dz(1)||dz(-1)}else{return dz(-1)||dz(1)}}function bv(dv,dx,dw){var dy=bg({line:dv,ch:dx||0});(dw?bZ:bX)(dy,dy)}function cr(dv){return Math.max(0,Math.min(dv,c4.size-1))}function bg(dx){if(dx.line<0){return{line:0,ch:0}}if(dx.line>=c4.size){return{line:c4.size-1,ch:db(c4.size-1).text.length}}var dv=dx.ch,dw=db(dx.line).text.length;if(dv==null||dv>dw){return{line:dx.line,ch:dw}}else{if(dv<0){return{line:dx.line,ch:0}}else{return dx}}}function cU(dy,dC){var dz=dt.inverted?dt.from:dt.to,dD=dz.line,dv=dz.ch;var dB=db(dD);function dw(){for(var dE=dD+dy,dG=dy<0?-1:c4.size;dE!=dG;dE+=dy){var dF=db(dE);if(!dF.hidden){dD=dE;dB=dF;return true}}}function dA(dE){if(dv==(dy<0?0:dB.text.length)){if(!dE&&dw()){dv=dy<0?dB.text.length:0}else{return false}}else{dv+=dy}return true}if(dC=="char"){dA()}else{if(dC=="column"){dA(true)}else{if(dC=="word"){var dx=false;for(;;){if(dy<0){if(!dA()){break}}if(N(dB.text.charAt(dv))){dx=true}else{if(dx){if(dy<0){dy=1;dA()}break}}if(dy>0){if(!dA()){break}}}}}}return{line:dD,ch:dv}}function da(dv,dw){var dx=dv<0?dt.from:dt.to;if(cN||T(dt.from,dt.to)){dx=cU(dv,dw)}bv(dx.line,dx.ch,true)}function cS(dv,dw){if(!T(dt.from,dt.to)){ci("",dt.from,dt.to)}else{if(dv<0){ci("",cU(dv,dw),dt.to)}else{ci("",dt.from,cU(dv,dw))}}cz=true}function c3(dw,dy){var dA=0,dB=dn(dt.inverted?dt.from:dt.to,true);if(c0!=null){dB.x=c0}if(dy=="page"){var dv=Math.min(bH.clientHeight,window.innerHeight||document.documentElement.clientHeight);var dz=b9(dB.x,dB.y+dv*dw)}else{if(dy=="line"){var dx=ch();var dz=b9(dB.x,dB.y+0.5*dx+dw*dx)}}if(dy=="page"){a8.scrollTop+=dn(dz,true).y-dB.y}bv(dz.line,dz.ch,true);c0=dB.x}function bT(dA){var dy=db(dA.line).text;var dz=dA.ch,dx=dA.ch;if(dy){if(dA.after===false||dx==dy.length){--dz}else{++dx}var dw=dy.charAt(dz);var dv=N(dw)?N:/\s/.test(dw)?function(dB){return/\s/.test(dB)}:function(dB){return !/\s/.test(dB)&&N(dB)};while(dz>0&&dv(dy.charAt(dz-1))){--dz}while(dx<dy.length&&dv(dy.charAt(dx))){++dx}}return{from:{line:dA.line,ch:dz},to:{line:dA.line,ch:dx}}}function a6(dv){bZ({line:dv,ch:0},bg({line:dv+1,ch:0}))}function c6(dx){if(T(dt.from,dt.to)){return b0(dt.from.line,dx)}var dw=dt.to.line-(dt.to.ch?0:1);for(var dv=dt.from.line;dv<=dw;++dv){b0(dv,dx)}}function b0(dx,dE){if(!dE){dE="add"}if(dE=="smart"){if(!cH.indent){dE="prev"}else{var dv=cZ(dx)}}var dF=db(dx),dz=dF.indentation(ct.tabSize),dw=dF.text.match(/^\s*/)[0],dB;if(dE=="smart"){dB=cH.indent(dv,dF.text.slice(dw.length),dF.text);if(dB==aq){dE="prev"}}if(dE=="prev"){if(dx){dB=db(dx-1).indentation(ct.tabSize)}else{dB=0}}else{if(dE=="add"){dB=dz+ct.indentUnit}else{if(dE=="subtract"){dB=dz-ct.indentUnit}}}dB=Math.max(0,dB);var dD=dB-dz;var dC="",dA=0;if(ct.indentWithTabs){for(var dy=Math.floor(dB/ct.tabSize);dy;--dy){dA+=ct.tabSize;dC+="\t"}}if(dA<dB){dC+=az(dB-dA)}if(dC!=dw){ci(dC,{line:dx,ch:0},{line:dx,ch:dw.length})}dF.stateAfter=null}function cm(){cH=r.getMode(ct,ct.mode);c4.iter(0,c4.size,function(dv){dv.stateAfter=null});df=0;b8(100)}function bC(){var dv=ct.gutter||ct.lineNumbers;a3.style.display=dv?"":"none";if(dv){bf=true}else{aO.parentNode.style.marginLeft=0}}function dc(dx,dw){if(ct.lineWrapping){a1.className+=" CodeMirror-wrap";var dv=bH.clientWidth/bE()-3;c4.iter(0,c4.size,function(dy){if(dy.hidden){return}var dz=Math.ceil(dy.text.length/dv)||1;if(dz!=1){br(dy,dz)}});bU.style.minWidth=bu.style.left=""}else{a1.className=a1.className.replace(" CodeMirror-wrap","");bY();c4.iter(0,c4.size,function(dy){if(dy.height!=1&&!dy.hidden){br(dy,1)}})}aZ.push({from:0,to:c4.size})}function c8(){bH.className=bH.className.replace(/\s*cm-s-\S+/g,"")+ct.theme.replace(/(^|\s)\s*/g," cm-s-")}function c1(){var dv=g[ct.keyMap].style;a1.className=a1.className.replace(/\s*cm-keymap-\S+/g,"")+(dv?" cm-keymap-"+dv:"")}function du(dw,dv){this.lines=[];this.type=dw;if(dv){this.style=dv}}du.prototype.clear=aP(function(){var dy,dv;for(var dx=0;dx<this.lines.length;++dx){var dw=this.lines[dx];var dz=aI(dw.markedSpans,this);if(dz.from!=null){dy=X(dw)}if(dz.to!=null){dv=X(dw)}dw.markedSpans=aD(dw.markedSpans,dz)}if(dy!=null){aZ.push({from:dy,to:dv+1})}this.lines.length=0;this.explicitlyCleared=true});du.prototype.find=function(){var dA,dz;for(var dw=0;dw<this.lines.length;++dw){var dv=this.lines[dw];var dx=aI(dv.markedSpans,this);if(dx.from!=null||dx.to!=null){var dy=X(dv);if(dx.from!=null){dA={line:dy,ch:dx.from}}if(dx.to!=null){dz={line:dy,ch:dx.to}}}}if(this.type=="bookmark"){return dA}return dA&&{from:dA,to:dz}};function b7(dB,dA,dz,dx){dB=bg(dB);dA=bg(dA);var dw=new du("range",dz);if(dx){for(var dy in dx){if(dx.hasOwnProperty(dy)){dw[dy]=dx[dy]}}}var dv=dB.line;c4.iter(dv,dA.line+1,function(dC){var dD={from:dv==dB.line?dB.ch:null,to:dv==dA.line?dA.ch:null,marker:dw};dC.markedSpans=(dC.markedSpans||[]).concat([dD]);dw.lines.push(dC);++dv});aZ.push({from:dB.line,to:dA.line+1});return dw}function bh(dy){dy=bg(dy);var dw=new du("bookmark"),dv=db(dy.line);bx.addChange(dy.line,1,[k(dv.text,dv.markedSpans)],true);var dx={from:dy.ch,to:dy.ch,marker:dw};dv.markedSpans=(dv.markedSpans||[]).concat([dx]);dw.lines.push(dv);return dw}function bL(dz){dz=bg(dz);var dy=[],dw=db(dz.line).markedSpans;if(dw){for(var dv=0;dv<dw.length;++dv){var dx=dw[dv];if((dx.from==null||dx.from<=dz.ch)&&(dx.to==null||dx.to>=dz.ch)){dy.push(dx.marker)}}}return dy}function cn(dv,dx,dw){if(typeof dv=="number"){dv=db(cr(dv))}dv.gutterMarker={text:dx,style:dw};bf=true;return dv}function aS(dv){if(typeof dv=="number"){dv=db(cr(dv))}dv.gutterMarker=null;bf=true}function bk(dw,dy){var dx=dw,dv=dw;if(typeof dw=="number"){dv=db(cr(dw))}else{dx=X(dw)}if(dx==null){return null}if(dy(dv,dx)){aZ.push({from:dx,to:dx+1})}else{return null}return dv}function bI(dw,dv,dx){return bk(dw,function(dy){if(dy.className!=dv||dy.bgClassName!=dx){dy.className=dv;dy.bgClassName=dx;return true}})}function dg(dw,dv){return bk(dw,function(dx,dA){if(dx.hidden!=dv){dx.hidden=dv;if(!ct.lineWrapping){if(dv&&dx.text.length==b6.text.length){c9=true}else{if(!dv&&dx.text.length>b6.text.length){b6=dx;c9=false}}}br(dx,dv?0:1);var dz=dt.from.line,dy=dt.to.line;if(dv&&(dz==dA||dy==dA)){var dC=dz==dA?ck({line:dz,ch:0},dz,0):dt.from;var dB=dy==dA?ck({line:dy,ch:0},dy,0):dt.to;if(!dB){return}bX(dC,dB)}return(bf=true)}})}function bi(dw){if(typeof dw=="number"){if(!bQ(dw)){return null}var dx=dw;dw=db(dw);if(!dw){return null}}else{var dx=X(dw);if(dx==null){return null}}var dv=dw.gutterMarker;return{line:dx,handle:dw,text:dw.text,markerText:dv&&dv.text,markerClass:dv&&dv.style,lineClass:dw.className,bgClass:dw.bgClassName}}function cx(dv,dy){if(dy==0){return{top:0,left:0}}var dB=ce(dv,dy);s(aT,dB);var dx=dB.anchor;var dA=dx.offsetTop,dz=dx.offsetLeft;if(U&&dA==0&&dz==0){var dw=ak("span","x");dx.parentNode.insertBefore(dw,dx.nextSibling);dA=dw.offsetTop}return{top:dA,left:dz}}function dn(dA,dy){var dv,dw=ch(),dz=dw*(a(c4,dA.line)-(dy?bB:0));if(dA.ch==0){dv=0}else{var dx=cx(db(dA.line),dA.ch);dv=dx.left;if(ct.lineWrapping){dz+=Math.max(0,dx.top)}}return{x:dv,y:dz,yBot:dz+dw}}function b9(dG,dF){var dD=ch(),dA=bE(),dM=bB+Math.floor(dF/dD);if(dM<0){return{line:0,ch:0}}var dH=af(c4,dM);if(dH>=c4.size){return{line:c4.size-1,ch:db(c4.size-1).text.length}}var dw=db(dH),dJ=dw.text;var dO=ct.lineWrapping,dE=dO?dM-a(c4,dH):0;if(dG<=0&&dE==0){return{line:dH,ch:0}}var dB=false;function dN(dQ){var dR=cx(dw,dQ);if(dO){var dS=Math.round(dR.top/dD);dB=dS!=dE;return Math.max(0,dR.left+(dS-dE)*bH.clientWidth)}return dR.left}var dL=0,dK=0,dx=dJ.length,dv;var dI=Math.min(dx,Math.ceil((dG+dE*bH.clientWidth*0.9)/dA));for(;;){var dC=dN(dI);if(dC<=dG&&dI<dx){dI=Math.min(dx,Math.ceil(dI*1.2))}else{dv=dC;dx=dI;break}}if(dG>dv){return{line:dH,ch:dx}}dI=Math.floor(dx*0.8);dC=dN(dI);if(dC<dG){dL=dI;dK=dC}for(;;){if(dx-dL<=1){var dz=dG-dK<dv-dG;return{line:dH,ch:dz?dL:dx,after:dz}}var dP=Math.ceil((dL+dx)/2),dy=dN(dP);if(dy>dG){dx=dP;dv=dy;if(dB){dv+=1000}}else{dL=dP;dK=dy}}}function aM(dx){var dv=dn(dx,true),dw=B(bU);return{x:dw.left+dv.x,y:dw.top+dv.y,yBot:dw.top+dv.yBot}}var bo,aV,aL;function ch(){if(aL==null){aL=ak("pre");for(var dw=0;dw<49;++dw){aL.appendChild(document.createTextNode("x"));aL.appendChild(ak("br"))}aL.appendChild(document.createTextNode("x"))}var dv=aO.clientHeight;if(dv==aV){return bo}aV=dv;s(aT,aL.cloneNode(true));bo=aT.firstChild.offsetHeight/50||1;aH(aT);return bo}var dp,bV=0;function bE(){if(bH.clientWidth==bV){return dp}bV=bH.clientWidth;var dv=ak("span","x");var dw=ak("pre",[dv]);s(aT,dw);return(dp=dv.offsetWidth||10)}function cX(){return bU.offsetTop}function bt(){return bU.offsetLeft}function bq(dz,dy){var dx=B(bH,true),dv,dA;try{dv=dz.clientX;dA=dz.clientY}catch(dz){return null}if(!dy&&(dv-dx.left>bH.clientWidth||dA-dx.top>bH.clientHeight)){return null}var dw=B(bU,true);return b9(dv-dw.left,dA-dw.top)}var bP;function bp(dw){var dA=bq(dw),dz=a8.scrollTop;if(!dA||ax){return}if(T(dt.from,dt.to)||D(dA,dt.from)||!D(dA,dt.to)){aP(bv)(dA.line,dA.ch)}var dy=bJ.style.cssText;cp.style.position="absolute";bJ.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(dw.clientY-5)+"px; left: "+(dw.clientX-5)+"px; z-index: 1000; background: white; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";b1();c7(true);if(T(dt.from,dt.to)){bJ.value=by=" "}function dv(){cp.style.position="relative";bJ.style.cssText=dy;if(I){a8.scrollTop=dz}aJ();if(bJ.selectionStart!=null){clearTimeout(bP);var dC=bJ.value=" "+(T(dt.from,dt.to)?"":bJ.value),dB=0;by=" ";bJ.selectionStart=1;bJ.selectionEnd=dC.length;bP=setTimeout(function dD(){if(by==" "&&bJ.selectionStart==0){aP(t.selectAll)(cF)}else{if(dB++<10){bP=setTimeout(dD,500)}else{c7()}}},200)}}if(x){ae(dw);var dx=aE(window,"mouseup",function(){dx();setTimeout(dv,20)},true)}else{setTimeout(dv,50)}}function di(){clearInterval(dl);var dv=true;bA.style.visibility="";dl=setInterval(function(){bA.style.visibility=(dv=!dv)?"":"hidden"},ct.cursorBlinkRate)}var bM={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"};function cK(dB){var dv=dt.inverted?dt.from:dt.to,dD=db(dv.line),dw=dv.ch-1;var dA=(dw>=0&&bM[dD.text.charAt(dw)])||bM[dD.text.charAt(++dw)];if(!dA){return}var dE=dA.charAt(0),dC=dA.charAt(1)==">",dO=dC?1:-1,dJ=dD.styles;for(var dP=dw+1,dL=0,dN=dJ.length;dL<dN;dL+=2){if((dP-=dJ[dL].length)<=0){var dM=dJ[dL+1];break}}var dy=[dD.text.charAt(dw)],dI=/[(){}[\]]/;function dG(d1,dW,dX){if(!d1.text){return}var d0=d1.styles,dV=dC?0:d1.text.length-1,dY;for(var dS=dC?0:d0.length-2,dU=dC?d0.length:-2;dS!=dU;dS+=2*dO){var dZ=d0[dS];if(d0[dS+1]!=dM){dV+=dO*dZ.length;continue}for(var dR=dC?0:dZ.length-1,dQ=dC?dZ.length:-1;dR!=dQ;dR+=dO,dV+=dO){if(dV>=dW&&dV<dX&&dI.test(dY=dZ.charAt(dR))){var dT=bM[dY];if(dT.charAt(1)==">"==dC){dy.push(dY)}else{if(dy.pop()!=dT.charAt(0)){return{pos:dV,match:false}}else{if(!dy.length){return{pos:dV,match:true}}}}}}}}for(var dL=dv.line,dN=dC?Math.min(dL+100,c4.size):Math.max(-1,dL-100);dL!=dN;dL+=dO){var dD=db(dL),dz=dL==dv.line;var dF=dG(dD,dz&&dC?dw+1:0,dz&&!dC?dw:dD.text.length);if(dF){break}}if(!dF){dF={pos:null,match:false}}var dM=dF.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket";var dK=b7({line:dv.line,ch:dw},{line:dv.line,ch:dw+1},dM),dx=dF.pos!=null&&b7({line:dL,ch:dF.pos},{line:dL,ch:dF.pos+1},dM);var dH=aP(function(){dK.clear();dx&&dx.clear()});if(dB){setTimeout(dH,800)}else{cw=dH}}function bw(dB){var dA,dx;for(var dw=dB,dy=dB-40;dw>dy;--dw){if(dw==0){return 0}var dv=db(dw-1);if(dv.stateAfter){return dw}var dz=dv.indentation(ct.tabSize);if(dx==null||dA>dz){dx=dw-1;dA=dz}}return dx}function cZ(dx){var dw=bw(dx),dv=dw&&db(dw-1).stateAfter;if(!dv){dv=v(cH)}else{dv=o(cH,dv)}c4.iter(dw,dx,function(dy){dy.process(cH,dv,ct.tabSize);dy.stateAfter=(dw==dx-1||dw%5==0)?o(cH,dv):null});return dv}function cl(){if(df>=cc){return}var dv=+new Date+ct.workTime,dx=o(cH,cZ(df));var dw=df;c4.iter(df,cc,function(dy){if(df>=dm){dy.highlight(cH,dx,ct.tabSize);dy.stateAfter=o(cH,dx)}else{dy.process(cH,dx,ct.tabSize);dy.stateAfter=df%5==0?o(cH,dx):null}++df;if(+new Date>dv){b8(ct.workDelay);return true}});if(cc>dw&&df>=dm){aP(function(){aZ.push({from:dw,to:df})})()}}function b8(dv){if(df<cc){aU.set(dv,cl)}}function ba(){cV=cz=dj=null;aZ=[];bc=false;c5=[]}function aW(){if(c9){bY()}if(bN&&!ct.lineWrapping){var dv=bu.offsetWidth,dB=cx(b6,b6.text.length).left;if(!L){bu.style.left=dB+"px";bU.style.minWidth=(dB+dv)+"px"}bN=false}var dz,dw;if(bc){var dA=cj();dz=bm(dA.x,dA.y,dA.x,dA.yBot)}if(aZ.length||dz&&dz.scrollTop!=null){dw=cJ(aZ,true,dz&&dz.scrollTop)}if(!dw){if(bc){ds()}if(bf){a7()}}if(dz){cL()}if(bc){di()}if(cO&&(cV===true||(cV!==false&&bc))){c7(cz)}if(bc&&ct.matchBrackets){setTimeout(aP(function(){if(cw){cw();cw=null}if(T(dt.from,dt.to)){cK(false)}}),20)}var dC=bc,dx=c5;if(dj&&ct.onChange&&cF){ct.onChange(cF,dj)}if(dC&&ct.onCursorActivity){ct.onCursorActivity(cF)}for(var dy=0;dy<dx.length;++dy){dx[dy](cF)}if(dw&&ct.onUpdate){ct.onUpdate(cF)}}var cW=0;function aP(dv){return function(){if(!cW++){ba()}try{var dw=dv.apply(this,arguments)}finally{if(!--cW){aW()}}return dw}}function cg(dv){bx.startCompound();try{return dv()}finally{bx.endCompound()}}for(var ca in c){if(c.propertyIsEnumerable(ca)&&!cF.propertyIsEnumerable(ca)){cF[ca]=c[ca]}}for(var cy=0;cy<ay.length;++cy){ay[cy](cF)}return cF}r.defaults={value:"",mode:null,theme:"default",indentUnit:2,indentWithTabs:false,smartIndent:true,tabSize:4,keyMap:"default",extraKeys:null,electricChars:true,autoClearEmptyLines:false,onKeyEvent:null,onDragEvent:null,lineWrapping:false,lineNumbers:false,gutter:false,fixedGutter:false,firstLineNumber:1,showCursorWhenSelecting:false,readOnly:false,dragDrop:true,onChange:null,onCursorActivity:null,onViewportChange:null,onGutterClick:null,onUpdate:null,onFocus:null,onBlur:null,onScroll:null,matchBrackets:false,cursorBlinkRate:530,workTime:100,workDelay:200,pollInterval:100,undoDepth:40,tabindex:null,autofocus:null,lineNumberFormatter:function(aJ){return aJ}};var i=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\/\w+/.test(navigator.userAgent);var K=i||/Mac/.test(navigator.platform);var ag=/Win/.test(navigator.platform);var A=r.modes={},am=r.mimeModes={};r.defineMode=function(aJ,aL){if(!r.defaults.mode&&aJ!="null"){r.defaults.mode=aJ}if(arguments.length>2){aL.dependencies=[];for(var aK=2;aK<arguments.length;++aK){aL.dependencies.push(arguments[aK])}}A[aJ]=aL};r.defineMIME=function(aK,aJ){am[aK]=aJ};r.resolveMode=function(aJ){if(typeof aJ=="string"&&am.hasOwnProperty(aJ)){aJ=am[aJ]}else{if(typeof aJ=="string"&&/^[\w\-]+\/[\w\-]+\+xml$/.test(aJ)){return r.resolveMode("application/xml")}}if(typeof aJ=="string"){return{name:aJ}}else{return aJ||{name:"null"}}};r.getMode=function(aK,aJ){var aJ=r.resolveMode(aJ);var aM=A[aJ.name];if(!aM){return r.getMode(aK,"text/plain")}var aN=aM(aK,aJ);if(ab.hasOwnProperty(aJ.name)){var aL=ab[aJ.name];for(var aO in aL){if(!aL.hasOwnProperty(aO)){continue}if(aN.hasOwnProperty(aO)){aN["_"+aO]=aN[aO]}aN[aO]=aL[aO]}}aN.name=aJ.name;return aN};r.listModes=function(){var aK=[];for(var aJ in A){if(A.propertyIsEnumerable(aJ)){aK.push(aJ)}}return aK};r.listMIMEs=function(){var aK=[];for(var aJ in am){if(am.propertyIsEnumerable(aJ)){aK.push({mime:aJ,mode:am[aJ]})}}return aK};var c=r.extensions={};r.defineExtension=function(aJ,aK){c[aJ]=aK};var ay=[];r.defineInitHook=function(aJ){ay.push(aJ)};var ab=r.modeExtensions={};r.extendMode=function(aL,aK){var aJ=ab.hasOwnProperty(aL)?ab[aL]:(ab[aL]={});for(var aM in aK){if(aK.hasOwnProperty(aM)){aJ[aM]=aK[aM]}}};var t=r.commands={selectAll:function(aJ){aJ.setSelection({line:0,ch:0},{line:aJ.lineCount()-1})},killLine:function(aJ){var aM=aJ.getCursor(true),aL=aJ.getCursor(false),aK=!T(aM,aL);if(!aK&&aJ.getLine(aM.line).length==aM.ch){aJ.replaceRange("",aM,{line:aM.line+1,ch:0})}else{aJ.replaceRange("",aM,aK?aL:{line:aM.line})}},deleteLine:function(aJ){var aK=aJ.getCursor().line;aJ.replaceRange("",{line:aK,ch:0},{line:aK})},undo:function(aJ){aJ.undo()},redo:function(aJ){aJ.redo()},goDocStart:function(aJ){aJ.setCursor(0,0,true)},goDocEnd:function(aJ){aJ.setSelection({line:aJ.lineCount()-1},null,true)},goLineStart:function(aJ){aJ.setCursor(aJ.getCursor().line,0,true)},goLineStartSmart:function(aJ){var aM=aJ.getCursor();var aL=aJ.getLine(aM.line),aK=Math.max(0,aL.search(/\S/));aJ.setCursor(aM.line,aM.ch<=aK&&aM.ch?0:aK,true)},goLineEnd:function(aJ){aJ.setSelection({line:aJ.getCursor().line},null,true)},goLineUp:function(aJ){aJ.moveV(-1,"line")},goLineDown:function(aJ){aJ.moveV(1,"line")},goPageUp:function(aJ){aJ.moveV(-1,"page")},goPageDown:function(aJ){aJ.moveV(1,"page")},goCharLeft:function(aJ){aJ.moveH(-1,"char")},goCharRight:function(aJ){aJ.moveH(1,"char")},goColumnLeft:function(aJ){aJ.moveH(-1,"column")},goColumnRight:function(aJ){aJ.moveH(1,"column")},goWordLeft:function(aJ){aJ.moveH(-1,"word")},goWordRight:function(aJ){aJ.moveH(1,"word")},delCharLeft:function(aJ){aJ.deleteH(-1,"char")},delCharRight:function(aJ){aJ.deleteH(1,"char")},delWordLeft:function(aJ){aJ.deleteH(-1,"word")},delWordRight:function(aJ){aJ.deleteH(1,"word")},indentAuto:function(aJ){aJ.indentSelection("smart")},indentMore:function(aJ){aJ.indentSelection("add")},indentLess:function(aJ){aJ.indentSelection("subtract")},insertTab:function(aJ){aJ.replaceSelection("\t","end")},defaultTab:function(aJ){if(aJ.somethingSelected()){aJ.indentSelection("add")}else{aJ.replaceSelection("\t","end")}},transposeChars:function(aJ){var aL=aJ.getCursor(),aK=aJ.getLine(aL.line);if(aL.ch>0&&aL.ch<aK.length-1){aJ.replaceRange(aK.charAt(aL.ch)+aK.charAt(aL.ch-1),{line:aL.line,ch:aL.ch-1},{line:aL.line,ch:aL.ch+1})}},newlineAndIndent:function(aJ){aJ.replaceSelection("\n","end");aJ.indentLine(aJ.getCursor().line)},toggleOverwrite:function(aJ){aJ.toggleOverwrite()}};var g=r.keyMap={};g.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharRight",Backspace:"delCharLeft",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite"};g.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Alt-Up":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Down":"goDocEnd","Ctrl-Left":"goWordLeft","Ctrl-Right":"goWordRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delWordLeft","Ctrl-Delete":"delWordRight","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore",fallthrough:"basic"};g.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goWordLeft","Alt-Right":"goWordRight","Cmd-Left":"goLineStart","Cmd-Right":"goLineEnd","Alt-Backspace":"delWordLeft","Ctrl-Alt-Backspace":"delWordRight","Alt-Delete":"delWordRight","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore",fallthrough:["basic","emacsy"]};g["default"]=K?g.macDefault:g.pcDefault;g.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharRight","Ctrl-H":"delCharLeft","Alt-D":"delWordRight","Alt-Backspace":"delWordLeft","Ctrl-K":"killLine","Ctrl-T":"transposeChars"};function at(aJ){if(typeof aJ=="string"){return g[aJ]}else{return aJ}}function av(aK,aJ,aO,aM,aL){function aN(aT){aT=at(aT);var aR=aT[aK];if(aR===false){if(aL){aL()}return true}if(aR!=null&&aM(aR)){return true}if(aT.nofallthrough){if(aL){aL()}return true}var aQ=aT.fallthrough;if(aQ==null){return false}if(Object.prototype.toString.call(aQ)!="[object Array]"){return aN(aQ)}for(var aP=0,aS=aQ.length;aP<aS;++aP){if(aN(aQ[aP])){return true}}return false}if(aJ&&aN(aJ)){return true}return aN(aO)}function aj(aK){var aJ=w[ad(aK,"keyCode")];return aJ=="Ctrl"||aJ=="Alt"||aJ=="Shift"||aJ=="Mod"}r.isModifierKey=aj;r.fromTextArea=function(aQ,aS){if(!aS){aS={}}aS.value=aQ.value;if(!aS.tabindex&&aQ.tabindex){aS.tabindex=aQ.tabindex}if(aS.autofocus==null){var aJ=document.body;try{aJ=document.activeElement}catch(aM){}aS.autofocus=aJ==aQ||aQ.getAttribute("autofocus")!=null&&aJ==document.body}function aO(){aQ.value=aR.getValue()}if(aQ.form){var aL=aE(aQ.form,"submit",aO,true);var aK=aQ.form,aP=aK.submit;aQ.form.submit=function aN(){aO();aK.submit=aP;aK.submit();aK.submit=aN}}aQ.style.display="none";var aR=r(function(aT){aQ.parentNode.insertBefore(aT,aQ.nextSibling)},aS);aR.save=aO;aR.getTextArea=function(){return aQ};aR.toTextArea=function(){aO();aQ.parentNode.removeChild(aR.getWrapperElement());aQ.style.display="";if(aQ.form){aL();if(typeof aQ.form.submit=="function"){aQ.form.submit=aP}}};return aR};var x=/gecko\/\d/i.test(navigator.userAgent);var U=/MSIE \d/.test(navigator.userAgent);var L=/MSIE [1-7]\b/.test(navigator.userAgent);var I=/MSIE [1-8]\b/.test(navigator.userAgent);var n=U&&document.documentMode==5;var m=/WebKit\//.test(navigator.userAgent);var l=m&&/Qt\/\d+\.\d+/.test(navigator.userAgent);var p=/Chrome\//.test(navigator.userAgent);var ax=/Opera\//.test(navigator.userAgent);var G=/Apple Computer/.test(navigator.vendor);var ah=/KHTML\//.test(navigator.userAgent);var W=/Mac OS X 10\D([7-9]|\d\d)\D/.test(navigator.userAgent);var aG=ax&&navigator.userAgent.match(/Version\/(\d*\.\d*)/);if(aG){aG=Number(aG[1])}var d=K&&(l||ax&&(aG==null||aG<12.11));function o(aM,aJ){if(aJ===true){return aJ}if(aM.copyState){return aM.copyState(aJ)}var aL={};for(var aN in aJ){var aK=aJ[aN];if(aK instanceof Array){aK=aK.concat([])}aL[aN]=aK}return aL}r.copyState=o;function v(aL,aK,aJ){return aL.startState?aL.startState(aK,aJ):true}r.startState=v;r.innerMode=function(aL,aJ){while(aL.innerMode){var aK=aL.innerMode(aJ);aJ=aK.state;aL=aK.mode}return aK||{mode:aL,state:aJ}};function ai(aJ,aK){this.pos=this.start=0;this.string=aJ;this.tabSize=aK||8}ai.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return this.pos==0},peek:function(){return this.string.charAt(this.pos)||undefined},next:function(){if(this.pos<this.string.length){return this.string.charAt(this.pos++)}},eat:function(aJ){var aL=this.string.charAt(this.pos);if(typeof aJ=="string"){var aK=aL==aJ}else{var aK=aL&&(aJ.test?aJ.test(aL):aJ(aL))}if(aK){++this.pos;return aL}},eatWhile:function(aJ){var aK=this.pos;while(this.eat(aJ)){}return this.pos>aK},eatSpace:function(){var aJ=this.pos;while(/[\s\u00a0]/.test(this.string.charAt(this.pos))){++this.pos}return this.pos>aJ},skipToEnd:function(){this.pos=this.string.length},skipTo:function(aJ){var aK=this.string.indexOf(aJ,this.pos);if(aK>-1){this.pos=aK;return true}},backUp:function(aJ){this.pos-=aJ},column:function(){return ap(this.string,this.start,this.tabSize)},indentation:function(){return ap(this.string,null,this.tabSize)},match:function(aM,aK,aJ){if(typeof aM=="string"){var aN=function(aO){return aJ?aO.toLowerCase():aO};if(aN(this.string).indexOf(aN(aM),this.pos)==this.pos){if(aK!==false){this.pos+=aM.length}return true}}else{var aL=this.string.slice(this.pos).match(aM);if(aL&&aL.index>0){return null}if(aL&&aK!==false){this.pos+=aL[0].length}return aL}},current:function(){return this.string.slice(this.start,this.pos)}};r.StringStream=ai;function Z(aL,aK,aJ){this.from=aL;this.to=aK;this.marker=aJ}function aI(aL,aJ){if(aL){for(var aK=0;aK<aL.length;++aK){var aM=aL[aK];if(aM.marker==aJ){return aM}}}}function aD(aK,aL){var aM;for(var aJ=0;aJ<aK.length;++aJ){if(aK[aJ]!=aL){(aM||(aM=[])).push(aK[aJ])}}return aM}function V(aK,aL,aN){if(aK){for(var aO=0,aQ;aO<aK.length;++aO){var aR=aK[aO],aP=aR.marker;var aJ=aR.from==null||(aP.inclusiveLeft?aR.from<=aL:aR.from<aL);if(aJ||aP.type=="bookmark"&&aR.from==aL&&aR.from!=aN){var aM=aR.to==null||(aP.inclusiveRight?aR.to>=aL:aR.to>aL);(aQ||(aQ=[])).push({from:aR.from,to:aM?null:aR.to,marker:aP})}}}return aQ}function aw(aL,aO){if(aL){for(var aN=0,aK;aN<aL.length;++aN){var aP=aL[aN],aJ=aP.marker;var aQ=aP.to==null||(aJ.inclusiveRight?aP.to>=aO:aP.to>aO);if(aQ||aJ.type=="bookmark"&&aP.from==aO){var aM=aP.from==null||(aJ.inclusiveLeft?aP.from<=aO:aP.from<aO);(aK||(aK=[])).push({from:aM?null:aP.from-aO,to:aP.to==null?null:aP.to-aO,marker:aJ})}}}return aK}function Y(aR,aW,aK,aN,aQ){if(!aR&&!aW){return aQ}var aP=V(aR,aK);var aU=aw(aW,aN);var aV=aQ.length==1,aL=P(aQ).length+(aV?aK:0);if(aP){for(var aM=0;aM<aP.length;++aM){var aT=aP[aM];if(aT.to==null){var aX=aI(aU,aT.marker);if(!aX){aT.to=aK}else{if(aV){aT.to=aX.to==null?null:aX.to+aL}}}}}if(aU){for(var aM=0;aM<aU.length;++aM){var aT=aU[aM];if(aT.to!=null){aT.to+=aL}if(aT.from==null){var aX=aI(aP,aT.marker);if(!aX){aT.from=aL;if(aV){(aP||(aP=[])).push(aT)}}}else{aT.from+=aL;if(aV){(aP||(aP=[])).push(aT)}}}}var aO=[k(aQ[0],aP)];if(!aV){var aS=aQ.length-2,aJ;if(aS>0&&aP){for(var aM=0;aM<aP.length;++aM){if(aP[aM].to==null){(aJ||(aJ=[])).push({from:null,to:null,marker:aP[aM].marker})}}}for(var aM=0;aM<aS;++aM){aO.push(k(aQ[aM+1],aJ))}aO.push(k(P(aQ),aU))}return aO}function au(aJ){return typeof aJ=="string"?aJ:aJ.text}function e(aM){if(typeof aM=="string"){return null}var aL=aM.markedSpans,aJ=null;for(var aK=0;aK<aL.length;++aK){if(aL[aK].marker.explicitlyCleared){if(!aJ){aJ=aL.slice(0,aK)}}else{if(aJ){aJ.push(aL[aK])}}}return !aJ?aL:aJ.length?aJ:null}function k(aK,aJ){return aJ?{text:aK,markedSpans:aJ}:aK}function aA(aL){var aN=aL.markedSpans;if(!aN){return}for(var aM=0;aM<aN.length;++aM){var aK=aN[aM].marker.lines;var aJ=u(aK,aL);aK.splice(aJ,1)}aL.markedSpans=null}function aC(aK,aM){if(!aM){return}for(var aL=0;aL<aM.length;++aL){var aJ=aM[aL].marker.lines.push(aK)}aK.markedSpans=aM}var ao=" ";if(x||(U&&!L)){ao="\u200b"}else{if(ax){ao=""}}function J(aK,aJ){this.text=aK;this.height=1;aC(this,aJ)}J.prototype={update:function(aK,aJ){this.text=aK;this.stateAfter=this.styles=null;aA(this);aC(this,aJ)},highlight:function(aP,aM,aN){var aO=new ai(this.text,aN),aJ=this.styles||(this.styles=[]);var aQ=aJ.length=0;if(this.text==""&&aP.blankLine){aP.blankLine(aM)}while(!aO.eol()){var aK=aP.token(aO,aM),aL=aO.current();aO.start=aO.pos;if(aQ&&aJ[aQ-1]==aK){aJ[aQ-2]+=aL}else{if(aL){aJ[aQ++]=aL;aJ[aQ++]=aK}}if(aO.pos>5000){aJ[aQ++]=this.text.slice(aO.pos);aJ[aQ++]=null;break}}},process:function(aM,aJ,aK){var aL=new ai(this.text,aK);if(this.text==""&&aM.blankLine){aM.blankLine(aJ)}while(!aL.eol()&&aL.pos<=5000){aM.token(aL,aJ);aL.start=aL.pos}},getTokenAt:function(aP,aM,aN,aL){var aJ=this.text,aO=new ai(aJ,aN);while(aO.pos<aL&&!aO.eol()){aO.start=aO.pos;var aK=aP.token(aO,aM)}return{start:aO.start,end:aO.pos,string:aO.current(),className:aK||null,state:aM}},indentation:function(aJ){return ap(this.text,null,aJ)},getContent:function(aY,aJ,aU){var aP=true,aN=0,a5=/[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g;var aX=ak("pre");function a6(bk,bp,bh){if(!bp){return}if(aP&&U&&bp.charAt(0)==" "){bp="\u00a0"+bp.slice(1)}aP=false;if(!a5.test(bp)){aN+=bp.length;var bl=document.createTextNode(bp)}else{var bl=document.createDocumentFragment(),bn=0;while(true){a5.lastIndex=bn;var bi=a5.exec(bp);var bm=bi?bi.index-bn:bp.length-bn;if(bm){bl.appendChild(document.createTextNode(bp.slice(bn,bn+bm)));aN+=bm}if(!bi){break}bn+=bm+1;if(bi[0]=="\t"){var bo=aY-aN%aY;bl.appendChild(ak("span",az(bo),"cm-tab"));aN+=bo}else{var bj=ak("span","\u2022","cm-invalidchar");bj.title="\\u"+bi[0].charCodeAt(0).toString(16);bl.appendChild(bj);aN+=1}}}if(bh){bk.appendChild(ak("span",[bl],bh))}else{bk.appendChild(bl)}}var a9=a6;if(aJ!=null){var a3=0,aQ=aX.anchor=ak("span");a9=function(bj,bm,bk){var bi=bm.length;if(aJ>=a3&&aJ<a3+bi){var bl=aJ-a3;if(bl){a6(bj,bm.slice(0,bl),bk);if(aU){var bh=bm.slice(bl-1,bl+1);if(H.test(bh)){bj.appendChild(ak("wbr"))}else{if(!L&&/\w\w/.test(bh)){bj.appendChild(document.createTextNode("\u200d"))}}}}bj.appendChild(aQ);a6(aQ,ax?bm.slice(bl,bl+1):bm.slice(bl),bk);if(ax){a6(bj,bm.slice(bl+1),bk)}aJ--;a3+=bi}else{a3+=bi;a6(bj,bm,bk);if(a3==aJ&&a3==bd){y(aQ,ao);bj.appendChild(aQ)}else{if(a3>aJ+10&&/\s/.test(bm)){a9=function(){}}}}}}var a2=this.styles,aR=this.text,aZ=this.markedSpans;var bd=aR.length;function aM(bh){if(!bh){return null}return"cm-"+bh.replace(/ +/g," cm-")}if(!aR&&aJ==null){a9(aX," ")}else{if(!aZ||!aZ.length){for(var ba=0,aT=0;aT<bd;ba+=2){var a1=a2[ba],bc=a2[ba+1],a4=a1.length;if(aT+a4>bd){a1=a1.slice(0,bd-aT)}aT+=a4;a9(aX,a1,aM(bc))}}else{aZ.sort(function(bi,bh){return bi.from-bh.from});var aO=0,ba=0,aW="",bc,bg=0;var bf=aZ[0].from||0,a8=[],be=0;var bb=function(){var bh;while(be<aZ.length&&((bh=aZ[be]).from==aO||bh.from==null)){if(bh.marker.type=="range"){a8.push(bh)}++be}bf=be<aZ.length?aZ[be].from:Infinity;for(var bi=0;bi<a8.length;++bi){var bj=a8[bi].to;if(bj==null){bj=Infinity}if(bj==aO){a8.splice(bi--,1)}else{bf=Math.min(bj,bf)}}};var a0=0;while(aO<bd){if(bf==aO){bb()}var aV=Math.min(bd,bf);while(true){if(aW){var aL=aO+aW.length;var aK=bc;for(var a7=0;a7<a8.length;++a7){var aS=a8[a7];aK=(aK?aK+" ":"")+aS.marker.style;if(aS.marker.endStyle&&aS.to===Math.min(aL,aV)){aK+=" "+aS.marker.endStyle}if(aS.marker.startStyle&&aS.from===aO){aK+=" "+aS.marker.startStyle}}a9(aX,aL>aV?aW.slice(0,aV-aO):aW,aK);if(aL>=aV){aW=aW.slice(aV-aO);aO=aV;break}aO=aL}aW=a2[ba++];bc=aM(a2[ba++])}}}}return aX},cleanUp:function(){this.parent=null;aA(this)}};function Q(aK){this.lines=aK;this.parent=null;for(var aL=0,aM=aK.length,aJ=0;aL<aM;++aL){aK[aL].parent=this;aJ+=aK[aL].height}this.height=aJ}Q.prototype={chunkSize:function(){return this.lines.length},remove:function(aJ,aP,aN){for(var aM=aJ,aO=aJ+aP;aM<aO;++aM){var aK=this.lines[aM];this.height-=aK.height;aK.cleanUp();if(aK.handlers){for(var aL=0;aL<aK.handlers.length;++aL){aN.push(aK.handlers[aL])}}}this.lines.splice(aJ,aP)},collapse:function(aJ){aJ.splice.apply(aJ,[aJ.length,0].concat(this.lines))},insertHeight:function(aK,aL,aJ){this.height+=aJ;this.lines=this.lines.slice(0,aK).concat(aL).concat(this.lines.slice(aK));for(var aM=0,aN=aL.length;aM<aN;++aM){aL[aM].parent=this}},iterN:function(aJ,aM,aL){for(var aK=aJ+aM;aJ<aK;++aJ){if(aL(this.lines[aJ])){return true}}}};function al(aM){this.children=aM;var aL=0,aJ=0;for(var aK=0,aO=aM.length;aK<aO;++aK){var aN=aM[aK];aL+=aN.chunkSize();aJ+=aN.height;aN.parent=this}this.size=aL;this.height=aJ;this.parent=null}al.prototype={chunkSize:function(){return this.size},remove:function(aL,aK,aO){this.size-=aK;for(var aM=0;aM<this.children.length;++aM){var aJ=this.children[aM],aP=aJ.chunkSize();if(aL<aP){var aN=Math.min(aK,aP-aL),aQ=aJ.height;aJ.remove(aL,aN,aO);this.height-=aQ-aJ.height;if(aP==aN){this.children.splice(aM--,1);aJ.parent=null}if((aK-=aN)==0){break}aL=0}else{aL-=aP}}if(this.size-aK<25){var aR=[];this.collapse(aR);this.children=[new Q(aR)];this.children[0].parent=this}},collapse:function(aJ){for(var aK=0,aL=this.children.length;aK<aL;++aK){this.children[aK].collapse(aJ)}},insert:function(aK,aL){var aJ=0;for(var aM=0,aN=aL.length;aM<aN;++aM){aJ+=aL[aM].height}this.insertHeight(aK,aL,aJ)},insertHeight:function(aK,aR,aQ){this.size+=aR.length;this.height+=aQ;for(var aL=0,aN=this.children.length;aL<aN;++aL){var aJ=this.children[aL],aO=aJ.chunkSize();if(aK<=aO){aJ.insertHeight(aK,aR,aQ);if(aJ.lines&&aJ.lines.length>50){while(aJ.lines.length>50){var aM=aJ.lines.splice(aJ.lines.length-25,25);var aP=new Q(aM);aJ.height-=aP.height;this.children.splice(aL+1,0,aP);aP.parent=this}this.maybeSpill()}break}aK-=aO}},maybeSpill:function(){if(this.children.length<=10){return}var aM=this;do{var aK=aM.children.splice(aM.children.length-5,5);var aL=new al(aK);if(!aM.parent){var aN=new al(aM.children);aN.parent=aM;aM.children=[aN,aL];aM=aN}else{aM.size-=aL.size;aM.height-=aL.height;var aJ=u(aM.parent.children,aM);aM.parent.children.splice(aJ+1,0,aL)}aL.parent=aM.parent}while(aM.children.length>10);aM.parent.maybeSpill()},iter:function(aL,aK,aJ){this.iterN(aL,aK-aL,aJ)},iterN:function(aJ,aQ,aP){for(var aK=0,aN=this.children.length;aK<aN;++aK){var aO=this.children[aK],aM=aO.chunkSize();if(aJ<aM){var aL=Math.min(aQ,aM-aJ);if(aO.iterN(aJ,aL,aP)){return true}if((aQ-=aL)==0){break}aJ=0}else{aJ-=aM}}}};function M(aJ,aN){while(!aJ.lines){for(var aK=0;;++aK){var aM=aJ.children[aK],aL=aM.chunkSize();if(aN<aL){aJ=aM;break}aN-=aL}}return aJ.lines[aN]}function X(aJ){if(aJ.parent==null){return null}var aN=aJ.parent,aM=u(aN.lines,aJ);for(var aK=aN.parent;aK;aN=aK,aK=aK.parent){for(var aL=0;;++aL){if(aK.children[aL]==aN){break}aM+=aK.children[aL].chunkSize()}}return aM}function af(aP,aN){var aL=0;outer:do{for(var aM=0,aO=aP.children.length;aM<aO;++aM){var aK=aP.children[aM],aJ=aK.height;if(aN<aJ){aP=aK;continue outer}aN-=aJ;aL+=aK.chunkSize()}return aL}while(!aP.lines);for(var aM=0,aO=aP.lines.length;aM<aO;++aM){var aR=aP.lines[aM],aQ=aR.height;if(aN<aQ){break}aN-=aQ}return aL+aM}function a(aJ,aP){var aL=0;outer:do{for(var aK=0,aN=aJ.children.length;aK<aN;++aK){var aO=aJ.children[aK],aM=aO.chunkSize();if(aP<aM){aJ=aO;continue outer}aP-=aM;aL+=aO.height}return aL}while(!aJ.lines);for(var aK=0;aK<aP;++aK){aL+=aJ.lines[aK].height}return aL}function F(){this.time=0;this.done=[];this.undone=[];this.compound=0;this.closed=false}F.prototype={addChange:function(aJ,aO,aK){this.undone.length=0;var aL=+new Date,aQ=P(this.done),aR=aQ&&P(aQ);var aN=aL-this.time;if(aQ&&!this.closed&&this.compound){aQ.push({start:aJ,added:aO,old:aK})}else{if(aN>400||!aR||this.closed||aR.start>aJ+aK.length||aR.start+aR.added<aJ){this.done.push([{start:aJ,added:aO,old:aK}]);this.closed=false}else{var aP=Math.max(0,aR.start-aJ),aS=Math.max(0,(aJ+aK.length)-(aR.start+aR.added));for(var aM=aP;aM>0;--aM){aR.old.unshift(aK[aM-1])}for(var aM=aS;aM>0;--aM){aR.old.push(aK[aK.length-aM])}if(aP){aR.start=aJ}aR.added+=aO-(aK.length-aP-aS)}}this.time=aL},startCompound:function(){if(!this.compound++){this.closed=true}},endCompound:function(){if(!--this.compound){this.closed=true}}};function z(){ae(this)}function R(aJ){if(!aJ.stop){aJ.stop=z}return aJ}function f(aJ){if(aJ.preventDefault){aJ.preventDefault()}else{aJ.returnValue=false}}function q(aJ){if(aJ.stopPropagation){aJ.stopPropagation()}else{aJ.cancelBubble=true}}function ae(aJ){f(aJ);q(aJ)}r.e_stop=ae;r.e_preventDefault=f;r.e_stopPropagation=q;function ar(aJ){return aJ.target||aJ.srcElement}function E(aK){var aJ=aK.which;if(aJ==null){if(aK.button&1){aJ=1}else{if(aK.button&2){aJ=3}else{if(aK.button&4){aJ=2}}}}if(K&&aK.ctrlKey&&aJ==1){aJ=3}return aJ}function ad(aK,aL){var aJ=aK.override&&aK.override.hasOwnProperty(aL);return aJ?aK.override[aL]:aK[aL]}function aE(aM,aL,aK,aJ){if(typeof aM.addEventListener=="function"){aM.addEventListener(aL,aK,false);if(aJ){return function(){aM.removeEventListener(aL,aK,false)}}}else{var aN=function(aO){aK(aO||window.event)};aM.attachEvent("on"+aL,aN);if(aJ){return function(){aM.detachEvent("on"+aL,aN)}}}}r.connect=aE;function j(){this.id=null}j.prototype={set:function(aJ,aK){clearTimeout(this.id);this.id=setTimeout(aK,aJ)}};var aq=r.Pass={toString:function(){return"CodeMirror.Pass"}};var ac=function(){if(I){return false}var aJ=ak("div");return"draggable" in aJ||"dragDrop" in aJ}();var S=function(){var aJ=ak("textarea");aJ.value="foo\nbar";if(aJ.value.indexOf("\r")>-1){return"\r\n"}return"\n"}();var H=/^$/;if(x){H=/$'/}else{if(G){H=/\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/}else{if(p){H=/\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/}}}function ap(aK,aJ,aM){if(aJ==null){aJ=aK.search(/[^\s\u00a0]/);if(aJ==-1){aJ=aK.length}}for(var aL=0,aN=0;aL<aJ;++aL){if(aK.charAt(aL)=="\t"){aN+=aM-(aN%aM)}else{++aN}}return aN}function B(aM,aJ){try{var aL=aM.getBoundingClientRect();aL={top:aL.top,left:aL.left}}catch(aN){aL={top:0,left:0}}if(!aJ){if(window.pageYOffset==null){var aK=document.documentElement||document.body.parentNode;if(aK.scrollTop==null){aK=document.body}aL.top+=aK.scrollTop;aL.left+=aK.scrollLeft}else{aL.top+=window.pageYOffset;aL.left+=window.pageXOffset}}return aL}function aB(aJ){return aJ.textContent||aJ.innerText||aJ.nodeValue||""}var an=[""];function az(aJ){while(an.length<=aJ){an.push(P(an)+" ")}return an[aJ]}function P(aJ){return aJ[aJ.length-1]}function aF(aJ){if(i){aJ.selectionStart=0;aJ.selectionEnd=aJ.value.length}else{aJ.select()}}function T(aK,aJ){return aK.line==aJ.line&&aK.ch==aJ.ch}function D(aK,aJ){return aK.line<aJ.line||(aK.line==aJ.line&&aK.ch<aJ.ch)}function aa(aJ){return{line:aJ.line,ch:aJ.ch}}function ak(aJ,aN,aM,aL){var aO=document.createElement(aJ);if(aM){aO.className=aM}if(aL){aO.style.cssText=aL}if(typeof aN=="string"){y(aO,aN)}else{if(aN){for(var aK=0;aK<aN.length;++aK){aO.appendChild(aN[aK])}}}return aO}function aH(aJ){aJ.innerHTML="";return aJ}function s(aJ,aK){aH(aJ).appendChild(aK)}function y(aJ,aK){if(I){aJ.innerHTML="";aJ.appendChild(document.createTextNode(aK))}else{aJ.textContent=aK}}function C(aM,aL){if(!aL){return 0}if(!aM){return aL.length}for(var aK=aM.length,aJ=aL.length;aK>=0&&aJ>=0;--aK,--aJ){if(aM.charAt(aK)!=aL.charAt(aJ)){break}}return aJ+1}function u(aM,aJ){if(aM.indexOf){return aM.indexOf(aJ)}for(var aK=0,aL=aM.length;aK<aL;++aK){if(aM[aK]==aJ){return aK}}return -1}var O=/[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/;function N(aJ){return/\w/.test(aJ)||aJ>"\x80"&&(aJ.toUpperCase()!=aJ.toLowerCase()||O.test(aJ))}var h="\n\nb".split(/\n/).length!=3?function(aO){var aP=0,aJ=[],aN=aO.length;while(aP<=aN){var aM=aO.indexOf("\n",aP);if(aM==-1){aM=aO.length}var aL=aO.slice(aP,aO.charAt(aM-1)=="\r"?aM-1:aM);var aK=aL.indexOf("\r");if(aK!=-1){aJ.push(aL.slice(0,aK));aP+=aK+1}else{aJ.push(aL);aP=aM+1}}return aJ}:function(aJ){return aJ.split(/\r\n?|\n/)};r.splitLines=h;var b=window.getSelection?function(aK){try{return aK.selectionStart!=aK.selectionEnd}catch(aJ){return false}}:function(aL){try{var aJ=aL.ownerDocument.selection.createRange()}catch(aK){}if(!aJ||aJ.parentElement()!=aL){return false}return aJ.compareEndPoints("StartToEnd",aJ)!=0};r.defineMode("null",function(){return{token:function(aJ){aJ.skipToEnd()}}});r.defineMIME("text/plain","null");var w={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",91:"Mod",92:"Mod",93:"Mod",109:"-",107:"=",127:"Delete",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63276:"PageUp",63277:"PageDown",63275:"End",63273:"Home",63234:"Left",63232:"Up",63235:"Right",63233:"Down",63302:"Insert",63272:"Delete"};r.keyNames=w;(function(){for(var aJ=0;aJ<10;aJ++){w[aJ+48]=String(aJ)}for(var aJ=65;aJ<=90;aJ++){w[aJ]=String.fromCharCode(aJ)}for(var aJ=1;aJ<=12;aJ++){w[aJ+111]=w[aJ+63235]="F"+aJ}})();r.version="2.38";return r})();
 
 
b'\\ No newline at end of file'
 
1
// CodeMirror version 2.38
 
2
//
 
3
// All functions that need access to the editor's state live inside
 
4
// the CodeMirror function. Below that, at the bottom of the file,
 
5
// some utilities are defined.
 
6
 
 
7
// CodeMirror is the only global var we claim
 
8
window.CodeMirror = (function() {
 
9
  "use strict";
 
10
  // This is the function that produces an editor instance. Its
 
11
  // closure is used to store the editor state.
 
12
  function CodeMirror(place, givenOptions) {
 
13
    // Determine effective options based on given values and defaults.
 
14
    var options = {}, defaults = CodeMirror.defaults;
 
15
    for (var opt in defaults)
 
16
      if (defaults.hasOwnProperty(opt))
 
17
        options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
 
18
 
 
19
    var input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em");
 
20
    input.setAttribute("wrap", "off"); input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off");
 
21
    // Wraps and hides input textarea
 
22
    var inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
 
23
    // The empty scrollbar content, used solely for managing the scrollbar thumb.
 
24
    var scrollbarInner = elt("div", null, "CodeMirror-scrollbar-inner");
 
25
    // The vertical scrollbar. Horizontal scrolling is handled by the scroller itself.
 
26
    var scrollbar = elt("div", [scrollbarInner], "CodeMirror-scrollbar");
 
27
    // DIVs containing the selection and the actual code
 
28
    var lineDiv = elt("div"), selectionDiv = elt("div", null, null, "position: relative; z-index: -1");
 
29
    // Blinky cursor, and element used to ensure cursor fits at the end of a line
 
30
    var cursor = elt("pre", "\u00a0", "CodeMirror-cursor"), widthForcer = elt("pre", "\u00a0", "CodeMirror-cursor", "visibility: hidden");
 
31
    // Used to measure text size
 
32
    var measure = elt("div", null, null, "position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;");
 
33
    var lineSpace = elt("div", [measure, cursor, widthForcer, selectionDiv, lineDiv], null, "position: relative; z-index: 0");
 
34
    var gutterText = elt("div", null, "CodeMirror-gutter-text"), gutter = elt("div", [gutterText], "CodeMirror-gutter");
 
35
    // Moved around its parent to cover visible view
 
36
    var mover = elt("div", [gutter, elt("div", [lineSpace], "CodeMirror-lines")], null, "position: relative");
 
37
    // Set to the height of the text, causes scrolling
 
38
    var sizer = elt("div", [mover], null, "position: relative");
 
39
    // Provides scrolling
 
40
    var scroller = elt("div", [sizer], "CodeMirror-scroll");
 
41
    scroller.setAttribute("tabIndex", "-1");
 
42
    // The element in which the editor lives.
 
43
    var wrapper = elt("div", [inputDiv, scrollbar, scroller], "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : ""));
 
44
    if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
 
45
 
 
46
    themeChanged(); keyMapChanged();
 
47
    // Needed to hide big blue blinking cursor on Mobile Safari
 
48
    if (ios) input.style.width = "0px";
 
49
    if (!webkit) scroller.draggable = true;
 
50
    lineSpace.style.outline = "none";
 
51
    if (options.tabindex != null) input.tabIndex = options.tabindex;
 
52
    if (options.autofocus) focusInput();
 
53
    if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
 
54
    // Needed to handle Tab key in KHTML
 
55
    if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute";
 
56
 
 
57
    // Check for OS X >= 10.7. This has transparent scrollbars, so the
 
58
    // overlaying of one scrollbar with another won't work. This is a
 
59
    // temporary hack to simply turn off the overlay scrollbar. See
 
60
    // issue #727.
 
61
    if (mac_geLion) { scrollbar.style.zIndex = -2; scrollbar.style.visibility = "hidden"; }
 
62
    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
 
63
    else if (ie_lt8) scrollbar.style.minWidth = "18px";
 
64
 
 
65
    // Delayed object wrap timeouts, making sure only one is active. blinker holds an interval.
 
66
    var poll = new Delayed(), highlight = new Delayed(), blinker;
 
67
 
 
68
    // mode holds a mode API object. doc is the tree of Line objects,
 
69
    // frontier is the point up to which the content has been parsed,
 
70
    // and history the undo history (instance of History constructor).
 
71
    var mode, doc = new BranchChunk([new LeafChunk([new Line("")])]), frontier = 0, focused;
 
72
    loadMode();
 
73
    // The selection. These are always maintained to point at valid
 
74
    // positions. Inverted is used to remember that the user is
 
75
    // selecting bottom-to-top.
 
76
    var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
 
77
    // Selection-related flags. shiftSelecting obviously tracks
 
78
    // whether the user is holding shift.
 
79
    var shiftSelecting, lastClick, lastDoubleClick, lastScrollTop = 0, draggingText,
 
80
        overwrite = false, suppressEdits = false, pasteIncoming = false;
 
81
    // Variables used by startOperation/endOperation to track what
 
82
    // happened during the operation.
 
83
    var updateInput, userSelChange, changes, textChanged, selectionChanged,
 
84
        gutterDirty, callbacks;
 
85
    // Current visible range (may be bigger than the view window).
 
86
    var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
 
87
    // bracketHighlighted is used to remember that a bracket has been
 
88
    // marked.
 
89
    var bracketHighlighted;
 
90
    // Tracks the maximum line length so that the horizontal scrollbar
 
91
    // can be kept static when scrolling.
 
92
    var maxLine = getLine(0), updateMaxLine = false, maxLineChanged = true;
 
93
    var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll
 
94
    var goalColumn = null;
 
95
 
 
96
    // Initialize the content.
 
97
    operation(function(){setValue(options.value || ""); updateInput = false;})();
 
98
    var history = new History();
 
99
 
 
100
    // Register our event handlers.
 
101
    connect(scroller, "mousedown", operation(onMouseDown));
 
102
    connect(scroller, "dblclick", operation(onDoubleClick));
 
103
    connect(lineSpace, "selectstart", e_preventDefault);
 
104
    // Gecko browsers fire contextmenu *after* opening the menu, at
 
105
    // which point we can't mess with it anymore. Context menu is
 
106
    // handled in onMouseDown for Gecko.
 
107
    if (!gecko) connect(scroller, "contextmenu", onContextMenu);
 
108
    connect(scroller, "scroll", onScrollMain);
 
109
    connect(scrollbar, "scroll", onScrollBar);
 
110
    connect(scrollbar, "mousedown", function() {if (focused) setTimeout(focusInput, 0);});
 
111
    var resizeHandler = connect(window, "resize", function() {
 
112
      if (wrapper.parentNode) updateDisplay(true);
 
113
      else resizeHandler();
 
114
    }, true);
 
115
    connect(input, "keyup", operation(onKeyUp));
 
116
    connect(input, "input", fastPoll);
 
117
    connect(input, "keydown", operation(onKeyDown));
 
118
    connect(input, "keypress", operation(onKeyPress));
 
119
    connect(input, "focus", onFocus);
 
120
    connect(input, "blur", onBlur);
 
121
 
 
122
    function drag_(e) {
 
123
      if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
 
124
      e_stop(e);
 
125
    }
 
126
    if (options.dragDrop) {
 
127
      connect(scroller, "dragstart", onDragStart);
 
128
      connect(scroller, "dragenter", drag_);
 
129
      connect(scroller, "dragover", drag_);
 
130
      connect(scroller, "drop", operation(onDrop));
 
131
    }
 
132
    connect(scroller, "paste", function(){focusInput(); fastPoll();});
 
133
    connect(input, "paste", function(){pasteIncoming = true; fastPoll();});
 
134
    connect(input, "cut", operation(function(){
 
135
      if (!options.readOnly) replaceSelection("");
 
136
    }));
 
137
 
 
138
    // Needed to handle Tab key in KHTML
 
139
    if (khtml) connect(sizer, "mouseup", function() {
 
140
        if (document.activeElement == input) input.blur();
 
141
        focusInput();
 
142
    });
 
143
 
 
144
    // IE throws unspecified error in certain cases, when
 
145
    // trying to access activeElement before onload
 
146
    var hasFocus; try { hasFocus = (document.activeElement == input); } catch(e) { }
 
147
    if (hasFocus || options.autofocus) setTimeout(onFocus, 20);
 
148
    else onBlur();
 
149
 
 
150
    function isLine(l) {return l >= 0 && l < doc.size;}
 
151
    // The instance object that we'll return. Mostly calls out to
 
152
    // local functions in the CodeMirror function. Some do some extra
 
153
    // range checking and/or clipping. operation is used to wrap the
 
154
    // call so that changes it makes are tracked, and the display is
 
155
    // updated afterwards.
 
156
    var instance = wrapper.CodeMirror = {
 
157
      getValue: getValue,
 
158
      setValue: operation(setValue),
 
159
      getSelection: getSelection,
 
160
      replaceSelection: operation(replaceSelection),
 
161
      focus: function(){window.focus(); focusInput(); onFocus(); fastPoll();},
 
162
      setOption: function(option, value) {
 
163
        var oldVal = options[option];
 
164
        options[option] = value;
 
165
        if (option == "mode" || option == "indentUnit") loadMode();
 
166
        else if (option == "readOnly" && value == "nocursor") {onBlur(); input.blur();}
 
167
        else if (option == "readOnly" && !value) {resetInput(true);}
 
168
        else if (option == "theme") themeChanged();
 
169
        else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
 
170
        else if (option == "tabSize") updateDisplay(true);
 
171
        else if (option == "keyMap") keyMapChanged();
 
172
        else if (option == "tabindex") input.tabIndex = value;
 
173
        else if (option == "showCursorWhenSelecting") updateSelection();
 
174
        if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" ||
 
175
            option == "theme" || option == "lineNumberFormatter") {
 
176
          gutterChanged();
 
177
          updateDisplay(true);
 
178
        }
 
179
      },
 
180
      getOption: function(option) {return options[option];},
 
181
      getMode: function() {return mode;},
 
182
      undo: operation(undo),
 
183
      redo: operation(redo),
 
184
      indentLine: operation(function(n, dir) {
 
185
        if (typeof dir != "string") {
 
186
          if (dir == null) dir = options.smartIndent ? "smart" : "prev";
 
187
          else dir = dir ? "add" : "subtract";
 
188
        }
 
189
        if (isLine(n)) indentLine(n, dir);
 
190
      }),
 
191
      indentSelection: operation(indentSelected),
 
192
      historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
 
193
      clearHistory: function() {history = new History();},
 
194
      setHistory: function(histData) {
 
195
        history = new History();
 
196
        history.done = histData.done;
 
197
        history.undone = histData.undone;
 
198
      },
 
199
      getHistory: function() {
 
200
        function cp(arr) {
 
201
          for (var i = 0, nw = [], nwelt; i < arr.length; ++i) {
 
202
            nw.push(nwelt = []);
 
203
            for (var j = 0, elt = arr[i]; j < elt.length; ++j) {
 
204
              var old = [], cur = elt[j];
 
205
              nwelt.push({start: cur.start, added: cur.added, old: old});
 
206
              for (var k = 0; k < cur.old.length; ++k) old.push(hlText(cur.old[k]));
 
207
            }
 
208
          }
 
209
          return nw;
 
210
        }
 
211
        return {done: cp(history.done), undone: cp(history.undone)};
 
212
      },
 
213
      matchBrackets: operation(function(){matchBrackets(true);}),
 
214
      getTokenAt: operation(function(pos) {
 
215
        pos = clipPos(pos);
 
216
        return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), options.tabSize, pos.ch);
 
217
      }),
 
218
      getStateAfter: function(line) {
 
219
        line = clipLine(line == null ? doc.size - 1: line);
 
220
        return getStateBefore(line + 1);
 
221
      },
 
222
      cursorCoords: function(start, mode) {
 
223
        if (start == null) start = sel.inverted;
 
224
        return this.charCoords(start ? sel.from : sel.to, mode);
 
225
      },
 
226
      charCoords: function(pos, mode) {
 
227
        pos = clipPos(pos);
 
228
        if (mode == "local") return localCoords(pos, false);
 
229
        if (mode == "div") return localCoords(pos, true);
 
230
        return pageCoords(pos);
 
231
      },
 
232
      coordsChar: function(coords) {
 
233
        var off = eltOffset(lineSpace);
 
234
        return coordsChar(coords.x - off.left, coords.y - off.top);
 
235
      },
 
236
      defaultTextHeight: function() { return textHeight(); },
 
237
      markText: operation(markText),
 
238
      setBookmark: setBookmark,
 
239
      findMarksAt: findMarksAt,
 
240
      setMarker: operation(addGutterMarker),
 
241
      clearMarker: operation(removeGutterMarker),
 
242
      setLineClass: operation(setLineClass),
 
243
      hideLine: operation(function(h) {return setLineHidden(h, true);}),
 
244
      showLine: operation(function(h) {return setLineHidden(h, false);}),
 
245
      onDeleteLine: function(line, f) {
 
246
        if (typeof line == "number") {
 
247
          if (!isLine(line)) return null;
 
248
          line = getLine(line);
 
249
        }
 
250
        (line.handlers || (line.handlers = [])).push(f);
 
251
        return line;
 
252
      },
 
253
      lineInfo: lineInfo,
 
254
      getViewport: function() { return {from: showingFrom, to: showingTo};},
 
255
      addWidget: function(pos, node, scroll, vert, horiz) {
 
256
        pos = localCoords(clipPos(pos));
 
257
        var top = pos.yBot, left = pos.x;
 
258
        node.style.position = "absolute";
 
259
        sizer.appendChild(node);
 
260
        if (vert == "over") top = pos.y;
 
261
        else if (vert == "near") {
 
262
          var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()),
 
263
              hspace = Math.max(sizer.clientWidth, lineSpace.clientWidth) - paddingLeft();
 
264
          if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)
 
265
            top = pos.y - node.offsetHeight;
 
266
          if (left + node.offsetWidth > hspace)
 
267
            left = hspace - node.offsetWidth;
 
268
        }
 
269
        node.style.top = (top + paddingTop()) + "px";
 
270
        node.style.left = node.style.right = "";
 
271
        if (horiz == "right") {
 
272
          left = sizer.clientWidth - node.offsetWidth;
 
273
          node.style.right = "0px";
 
274
        } else {
 
275
          if (horiz == "left") left = 0;
 
276
          else if (horiz == "middle") left = (sizer.clientWidth - node.offsetWidth) / 2;
 
277
          node.style.left = (left + paddingLeft()) + "px";
 
278
        }
 
279
        if (scroll)
 
280
          scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight);
 
281
      },
 
282
 
 
283
      lineCount: function() {return doc.size;},
 
284
      clipPos: clipPos,
 
285
      getCursor: function(start) {
 
286
        if (start == null || start == "head") start = sel.inverted;
 
287
        if (start == "anchor") start = !sel.inverted;
 
288
        if (start == "end") start = false;
 
289
        return copyPos(start ? sel.from : sel.to);
 
290
      },
 
291
      somethingSelected: function() {return !posEq(sel.from, sel.to);},
 
292
      setCursor: operation(function(line, ch, user) {
 
293
        if (ch == null && typeof line.line == "number") setCursor(line.line, line.ch, user);
 
294
        else setCursor(line, ch, user);
 
295
      }),
 
296
      setSelection: operation(function(from, to, user) {
 
297
        (user ? setSelectionUser : setSelection)(clipPos(from), clipPos(to || from));
 
298
      }),
 
299
      getLine: function(line) {if (isLine(line)) return getLine(line).text;},
 
300
      getLineHandle: function(line) {if (isLine(line)) return getLine(line);},
 
301
      setLine: operation(function(line, text) {
 
302
        if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch: getLine(line).text.length});
 
303
      }),
 
304
      removeLine: operation(function(line) {
 
305
        if (isLine(line)) replaceRange("", {line: line, ch: 0}, clipPos({line: line+1, ch: 0}));
 
306
      }),
 
307
      replaceRange: operation(replaceRange),
 
308
      getRange: function(from, to, lineSep) {return getRange(clipPos(from), clipPos(to), lineSep);},
 
309
 
 
310
      triggerOnKeyDown: operation(onKeyDown),
 
311
      execCommand: function(cmd) {return commands[cmd](instance);},
 
312
      // Stuff used by commands, probably not much use to outside code.
 
313
      moveH: operation(moveH),
 
314
      deleteH: operation(deleteH),
 
315
      moveV: operation(moveV),
 
316
      toggleOverwrite: function() {
 
317
        if(overwrite){
 
318
          overwrite = false;
 
319
          cursor.className = cursor.className.replace(" CodeMirror-overwrite", "");
 
320
        } else {
 
321
          overwrite = true;
 
322
          cursor.className += " CodeMirror-overwrite";
 
323
        }
 
324
      },
 
325
 
 
326
      posFromIndex: function(off) {
 
327
        var lineNo = 0, ch;
 
328
        doc.iter(0, doc.size, function(line) {
 
329
          var sz = line.text.length + 1;
 
330
          if (sz > off) { ch = off; return true; }
 
331
          off -= sz;
 
332
          ++lineNo;
 
333
        });
 
334
        return clipPos({line: lineNo, ch: ch});
 
335
      },
 
336
      indexFromPos: function (coords) {
 
337
        if (coords.line < 0 || coords.ch < 0) return 0;
 
338
        var index = coords.ch;
 
339
        doc.iter(0, coords.line, function (line) {
 
340
          index += line.text.length + 1;
 
341
        });
 
342
        return index;
 
343
      },
 
344
      scrollTo: function(x, y) {
 
345
        if (x != null) scroller.scrollLeft = x;
 
346
        if (y != null) scrollbar.scrollTop = scroller.scrollTop = y;
 
347
        updateDisplay([]);
 
348
      },
 
349
      getScrollInfo: function() {
 
350
        return {x: scroller.scrollLeft, y: scrollbar.scrollTop,
 
351
                height: scrollbar.scrollHeight, width: scroller.scrollWidth};
 
352
      },
 
353
      scrollIntoView: function(pos) {
 
354
        var coords = localCoords(pos ? clipPos(pos) : sel.inverted ? sel.from : sel.to);
 
355
        scrollIntoView(coords.x, coords.y, coords.x, coords.yBot);
 
356
      },
 
357
 
 
358
      setSize: function(width, height) {
 
359
        function interpret(val) {
 
360
          val = String(val);
 
361
          return /^\d+$/.test(val) ? val + "px" : val;
 
362
        }
 
363
        if (width != null) wrapper.style.width = interpret(width);
 
364
        if (height != null) scroller.style.height = interpret(height);
 
365
        instance.refresh();
 
366
      },
 
367
 
 
368
      operation: function(f){return operation(f)();},
 
369
      compoundChange: function(f){return compoundChange(f);},
 
370
      refresh: function(){
 
371
        updateDisplay(true, null, lastScrollTop);
 
372
        if (scrollbar.scrollHeight > lastScrollTop)
 
373
          scrollbar.scrollTop = lastScrollTop;
 
374
      },
 
375
      getInputField: function(){return input;},
 
376
      getWrapperElement: function(){return wrapper;},
 
377
      getScrollerElement: function(){return scroller;},
 
378
      getGutterElement: function(){return gutter;}
 
379
    };
 
380
 
 
381
    function getLine(n) { return getLineAt(doc, n); }
 
382
    function updateLineHeight(line, height) {
 
383
      gutterDirty = true;
 
384
      var diff = height - line.height;
 
385
      for (var n = line; n; n = n.parent) n.height += diff;
 
386
    }
 
387
 
 
388
    function lineContent(line, wrapAt) {
 
389
      if (!line.styles)
 
390
        line.highlight(mode, line.stateAfter = getStateBefore(lineNo(line)), options.tabSize);
 
391
      return line.getContent(options.tabSize, wrapAt, options.lineWrapping);
 
392
    }
 
393
 
 
394
    function setValue(code) {
 
395
      var top = {line: 0, ch: 0};
 
396
      updateLines(top, {line: doc.size - 1, ch: getLine(doc.size-1).text.length},
 
397
                  splitLines(code), top, top);
 
398
      updateInput = true;
 
399
    }
 
400
    function getValue(lineSep) {
 
401
      var text = [];
 
402
      doc.iter(0, doc.size, function(line) { text.push(line.text); });
 
403
      return text.join(lineSep || "\n");
 
404
    }
 
405
 
 
406
    function onScrollBar(e) {
 
407
      if (Math.abs(scrollbar.scrollTop - lastScrollTop) > 1) {
 
408
        lastScrollTop = scroller.scrollTop = scrollbar.scrollTop;
 
409
        updateDisplay([]);
 
410
      }
 
411
    }
 
412
 
 
413
    function onScrollMain(e) {
 
414
      if (options.fixedGutter && gutter.style.left != scroller.scrollLeft + "px")
 
415
        gutter.style.left = scroller.scrollLeft + "px";
 
416
      if (Math.abs(scroller.scrollTop - lastScrollTop) > 1) {
 
417
        lastScrollTop = scroller.scrollTop;
 
418
        if (scrollbar.scrollTop != lastScrollTop)
 
419
          scrollbar.scrollTop = lastScrollTop;
 
420
        updateDisplay([]);
 
421
      }
 
422
      if (options.onScroll) options.onScroll(instance);
 
423
    }
 
424
 
 
425
    function onMouseDown(e) {
 
426
      setShift(e_prop(e, "shiftKey"));
 
427
      // Check whether this is a click in a widget
 
428
      for (var n = e_target(e); n != wrapper; n = n.parentNode)
 
429
        if (n.parentNode == sizer && n != mover) return;
 
430
 
 
431
      // See if this is a click in the gutter
 
432
      for (var n = e_target(e); n != wrapper; n = n.parentNode)
 
433
        if (n.parentNode == gutterText) {
 
434
          if (options.onGutterClick)
 
435
            options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e);
 
436
          return e_preventDefault(e);
 
437
        }
 
438
 
 
439
      var start = posFromMouse(e);
 
440
 
 
441
      switch (e_button(e)) {
 
442
      case 3:
 
443
        if (gecko) onContextMenu(e);
 
444
        return;
 
445
      case 2:
 
446
        if (start) setCursor(start.line, start.ch, true);
 
447
        setTimeout(focusInput, 20);
 
448
        e_preventDefault(e);
 
449
        return;
 
450
      }
 
451
      // For button 1, if it was clicked inside the editor
 
452
      // (posFromMouse returning non-null), we have to adjust the
 
453
      // selection.
 
454
      if (!start) {if (e_target(e) == scroller) e_preventDefault(e); return;}
 
455
 
 
456
      if (!focused) onFocus();
 
457
 
 
458
      var now = +new Date, type = "single";
 
459
      if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
 
460
        type = "triple";
 
461
        e_preventDefault(e);
 
462
        setTimeout(focusInput, 20);
 
463
        selectLine(start.line);
 
464
      } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
 
465
        type = "double";
 
466
        lastDoubleClick = {time: now, pos: start};
 
467
        e_preventDefault(e);
 
468
        var word = findWordAt(start);
 
469
        setSelectionUser(word.from, word.to);
 
470
      } else { lastClick = {time: now, pos: start}; }
 
471
 
 
472
      function dragEnd(e2) {
 
473
        if (webkit) scroller.draggable = false;
 
474
        draggingText = false;
 
475
        up(); drop();
 
476
        if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
 
477
          e_preventDefault(e2);
 
478
          setCursor(start.line, start.ch, true);
 
479
          focusInput();
 
480
        }
 
481
      }
 
482
      var last = start, going;
 
483
      if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
 
484
          !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
 
485
        // Let the drag handler handle this.
 
486
        if (webkit) scroller.draggable = true;
 
487
        var up = connect(document, "mouseup", operation(dragEnd), true);
 
488
        var drop = connect(scroller, "drop", operation(dragEnd), true);
 
489
        draggingText = true;
 
490
        // IE's approach to draggable
 
491
        if (scroller.dragDrop) scroller.dragDrop();
 
492
        return;
 
493
      }
 
494
      e_preventDefault(e);
 
495
      if (type == "single") setCursor(start.line, start.ch, true);
 
496
 
 
497
      var startstart = sel.from, startend = sel.to;
 
498
 
 
499
      function doSelect(cur) {
 
500
        if (type == "single") {
 
501
          setSelectionUser(clipPos(start), cur);
 
502
          return;
 
503
        }
 
504
        startstart = clipPos(startstart);
 
505
        startend = clipPos(startend);
 
506
        if (type == "double") {
 
507
          var word = findWordAt(cur);
 
508
          if (posLess(cur, startstart)) setSelectionUser(word.from, startend);
 
509
          else setSelectionUser(startstart, word.to);
 
510
        } else if (type == "triple") {
 
511
          if (posLess(cur, startstart)) setSelectionUser(startend, clipPos({line: cur.line, ch: 0}));
 
512
          else setSelectionUser(startstart, clipPos({line: cur.line + 1, ch: 0}));
 
513
        }
 
514
      }
 
515
 
 
516
      function extend(e) {
 
517
        var cur = posFromMouse(e, true);
 
518
        if (cur && !posEq(cur, last)) {
 
519
          if (!focused) onFocus();
 
520
          last = cur;
 
521
          doSelect(cur);
 
522
          updateInput = false;
 
523
          var visible = visibleLines();
 
524
          if (cur.line >= visible.to || cur.line < visible.from)
 
525
            going = setTimeout(operation(function(){extend(e);}), 150);
 
526
        }
 
527
      }
 
528
 
 
529
      function done(e) {
 
530
        clearTimeout(going);
 
531
        var cur = posFromMouse(e);
 
532
        if (cur) doSelect(cur);
 
533
        e_preventDefault(e);
 
534
        focusInput();
 
535
        updateInput = true;
 
536
        move(); up();
 
537
      }
 
538
      var move = connect(document, "mousemove", operation(function(e) {
 
539
        clearTimeout(going);
 
540
        e_preventDefault(e);
 
541
        if (!ie && !e_button(e)) done(e);
 
542
        else extend(e);
 
543
      }), true);
 
544
      var up = connect(document, "mouseup", operation(done), true);
 
545
    }
 
546
    function onDoubleClick(e) {
 
547
      for (var n = e_target(e); n != wrapper; n = n.parentNode)
 
548
        if (n.parentNode == gutterText) return e_preventDefault(e);
 
549
      e_preventDefault(e);
 
550
    }
 
551
    function onDrop(e) {
 
552
      if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
 
553
      e_preventDefault(e);
 
554
      var pos = posFromMouse(e, true), files = e.dataTransfer.files;
 
555
      if (!pos || options.readOnly) return;
 
556
      if (files && files.length && window.FileReader && window.File) {
 
557
        var n = files.length, text = Array(n), read = 0;
 
558
        var loadFile = function(file, i) {
 
559
          var reader = new FileReader;
 
560
          reader.onload = function() {
 
561
            text[i] = reader.result;
 
562
            if (++read == n) {
 
563
              pos = clipPos(pos);
 
564
              operation(function() {
 
565
                var end = replaceRange(text.join(""), pos, pos);
 
566
                setSelectionUser(pos, end);
 
567
              })();
 
568
            }
 
569
          };
 
570
          reader.readAsText(file);
 
571
        };
 
572
        for (var i = 0; i < n; ++i) loadFile(files[i], i);
 
573
      } else {
 
574
        // Don't do a replace if the drop happened inside of the selected text.
 
575
        if (draggingText && !(posLess(pos, sel.from) || posLess(sel.to, pos))) return;
 
576
        try {
 
577
          var text = e.dataTransfer.getData("Text");
 
578
          if (text) {
 
579
            compoundChange(function() {
 
580
              var curFrom = sel.from, curTo = sel.to;
 
581
              setSelectionUser(pos, pos);
 
582
              if (draggingText) replaceRange("", curFrom, curTo);
 
583
              replaceSelection(text);
 
584
              focusInput();
 
585
            });
 
586
          }
 
587
        }
 
588
        catch(e){}
 
589
      }
 
590
    }
 
591
    function onDragStart(e) {
 
592
      var txt = getSelection();
 
593
      e.dataTransfer.setData("Text", txt);
 
594
 
 
595
      // Use dummy image instead of default browsers image.
 
596
      if (e.dataTransfer.setDragImage)
 
597
        e.dataTransfer.setDragImage(elt('img'), 0, 0);
 
598
    }
 
599
 
 
600
    function doHandleBinding(bound, dropShift) {
 
601
      if (typeof bound == "string") {
 
602
        bound = commands[bound];
 
603
        if (!bound) return false;
 
604
      }
 
605
      var prevShift = shiftSelecting;
 
606
      try {
 
607
        if (options.readOnly) suppressEdits = true;
 
608
        if (dropShift) shiftSelecting = null;
 
609
        bound(instance);
 
610
      } catch(e) {
 
611
        if (e != Pass) throw e;
 
612
        return false;
 
613
      } finally {
 
614
        shiftSelecting = prevShift;
 
615
        suppressEdits = false;
 
616
      }
 
617
      return true;
 
618
    }
 
619
    var maybeTransition;
 
620
    function handleKeyBinding(e) {
 
621
      // Handle auto keymap transitions
 
622
      var startMap = getKeyMap(options.keyMap), next = startMap.auto;
 
623
      clearTimeout(maybeTransition);
 
624
      if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
 
625
        if (getKeyMap(options.keyMap) == startMap) {
 
626
          options.keyMap = (next.call ? next.call(null, instance) : next);
 
627
        }
 
628
      }, 50);
 
629
 
 
630
      var name = keyNames[e_prop(e, "keyCode")], handled = false;
 
631
      if (name == null || e.altGraphKey) return false;
 
632
      if (e_prop(e, "altKey")) name = "Alt-" + name;
 
633
      if (e_prop(e, flipCtrlCmd ? "metaKey" : "ctrlKey")) name = "Ctrl-" + name;
 
634
      if (e_prop(e, flipCtrlCmd ? "ctrlKey" : "metaKey")) name = "Cmd-" + name;
 
635
 
 
636
      var stopped = false;
 
637
      function stop() { stopped = true; }
 
638
 
 
639
      if (e_prop(e, "shiftKey")) {
 
640
        handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap,
 
641
                            function(b) {return doHandleBinding(b, true);}, stop)
 
642
               || lookupKey(name, options.extraKeys, options.keyMap, function(b) {
 
643
                 if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(b);
 
644
               }, stop);
 
645
      } else {
 
646
        handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding, stop);
 
647
      }
 
648
      if (stopped) handled = false;
 
649
      if (handled) {
 
650
        e_preventDefault(e);
 
651
        restartBlink();
 
652
        if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
 
653
      }
 
654
      return handled;
 
655
    }
 
656
    function handleCharBinding(e, ch) {
 
657
      var handled = lookupKey("'" + ch + "'", options.extraKeys,
 
658
                              options.keyMap, function(b) { return doHandleBinding(b, true); });
 
659
      if (handled) {
 
660
        e_preventDefault(e);
 
661
        restartBlink();
 
662
      }
 
663
      return handled;
 
664
    }
 
665
 
 
666
    var lastStoppedKey = null;
 
667
    function onKeyDown(e) {
 
668
      if (!focused) onFocus();
 
669
      if (ie && e.keyCode == 27) { e.returnValue = false; }
 
670
      if (pollingFast) { if (readInput()) pollingFast = false; }
 
671
      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
 
672
      var code = e_prop(e, "keyCode");
 
673
      // IE does strange things with escape.
 
674
      setShift(code == 16 || e_prop(e, "shiftKey"));
 
675
      // First give onKeyEvent option a chance to handle this.
 
676
      var handled = handleKeyBinding(e);
 
677
      if (opera) {
 
678
        lastStoppedKey = handled ? code : null;
 
679
        // Opera has no cut event... we try to at least catch the key combo
 
680
        if (!handled && code == 88 && e_prop(e, mac ? "metaKey" : "ctrlKey"))
 
681
          replaceSelection("");
 
682
      }
 
683
    }
 
684
    function onKeyPress(e) {
 
685
      if (pollingFast) readInput();
 
686
      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
 
687
      var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
 
688
      if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
 
689
      if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) return;
 
690
      var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
 
691
      if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
 
692
        if (mode.electricChars.indexOf(ch) > -1)
 
693
          setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 75);
 
694
      }
 
695
      if (handleCharBinding(e, ch)) return;
 
696
      fastPoll();
 
697
    }
 
698
    function onKeyUp(e) {
 
699
      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
 
700
      if (e_prop(e, "keyCode") == 16) shiftSelecting = null;
 
701
    }
 
702
 
 
703
    function onFocus() {
 
704
      if (options.readOnly == "nocursor") return;
 
705
      if (!focused) {
 
706
        if (options.onFocus) options.onFocus(instance);
 
707
        focused = true;
 
708
        if (scroller.className.search(/\bCodeMirror-focused\b/) == -1)
 
709
          scroller.className += " CodeMirror-focused";
 
710
      }
 
711
      slowPoll();
 
712
      restartBlink();
 
713
    }
 
714
    function onBlur() {
 
715
      if (focused) {
 
716
        if (options.onBlur) options.onBlur(instance);
 
717
        focused = false;
 
718
        if (bracketHighlighted)
 
719
          operation(function(){
 
720
            if (bracketHighlighted) { bracketHighlighted(); bracketHighlighted = null; }
 
721
          })();
 
722
        scroller.className = scroller.className.replace(" CodeMirror-focused", "");
 
723
      }
 
724
      clearInterval(blinker);
 
725
      setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);
 
726
    }
 
727
 
 
728
    // Replace the range from from to to by the strings in newText.
 
729
    // Afterwards, set the selection to selFrom, selTo.
 
730
    function updateLines(from, to, newText, selFrom, selTo) {
 
731
      if (suppressEdits) return;
 
732
      var old = [];
 
733
      doc.iter(from.line, to.line + 1, function(line) {
 
734
        old.push(newHL(line.text, line.markedSpans));
 
735
      });
 
736
      if (history) {
 
737
        history.addChange(from.line, newText.length, old);
 
738
        while (history.done.length > options.undoDepth) history.done.shift();
 
739
      }
 
740
      var lines = updateMarkedSpans(hlSpans(old[0]), hlSpans(lst(old)), from.ch, to.ch, newText);
 
741
      updateLinesNoUndo(from, to, lines, selFrom, selTo);
 
742
    }
 
743
    function unredoHelper(from, to) {
 
744
      if (!from.length) return;
 
745
      var set = from.pop(), out = [];
 
746
      for (var i = set.length - 1; i >= 0; i -= 1) {
 
747
        var change = set[i];
 
748
        var replaced = [], end = change.start + change.added;
 
749
        doc.iter(change.start, end, function(line) { replaced.push(newHL(line.text, line.markedSpans)); });
 
750
        out.push({start: change.start, added: change.old.length, old: replaced});
 
751
        var pos = {line: change.start + change.old.length - 1,
 
752
                   ch: editEnd(hlText(lst(replaced)), hlText(lst(change.old)))};
 
753
        updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length},
 
754
                          change.old, pos, pos);
 
755
      }
 
756
      updateInput = true;
 
757
      to.push(out);
 
758
    }
 
759
    function undo() {unredoHelper(history.done, history.undone);}
 
760
    function redo() {unredoHelper(history.undone, history.done);}
 
761
 
 
762
    function updateLinesNoUndo(from, to, lines, selFrom, selTo) {
 
763
      if (suppressEdits) return;
 
764
      var recomputeMaxLength = false, maxLineLength = maxLine.text.length;
 
765
      if (!options.lineWrapping)
 
766
        doc.iter(from.line, to.line + 1, function(line) {
 
767
          if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
 
768
        });
 
769
      if (from.line != to.line || lines.length > 1) gutterDirty = true;
 
770
 
 
771
      var nlines = to.line - from.line, firstLine = getLine(from.line), lastLine = getLine(to.line);
 
772
      var lastHL = lst(lines);
 
773
 
 
774
      // First adjust the line structure
 
775
      if (from.ch == 0 && to.ch == 0 && hlText(lastHL) == "") {
 
776
        // This is a whole-line replace. Treated specially to make
 
777
        // sure line objects move the way they are supposed to.
 
778
        var added = [], prevLine = null;
 
779
        for (var i = 0, e = lines.length - 1; i < e; ++i)
 
780
          added.push(new Line(hlText(lines[i]), hlSpans(lines[i])));
 
781
        lastLine.update(lastLine.text, hlSpans(lastHL));
 
782
        if (nlines) doc.remove(from.line, nlines, callbacks);
 
783
        if (added.length) doc.insert(from.line, added);
 
784
      } else if (firstLine == lastLine) {
 
785
        if (lines.length == 1) {
 
786
          firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]) + firstLine.text.slice(to.ch), hlSpans(lines[0]));
 
787
        } else {
 
788
          for (var added = [], i = 1, e = lines.length - 1; i < e; ++i)
 
789
            added.push(new Line(hlText(lines[i]), hlSpans(lines[i])));
 
790
          added.push(new Line(hlText(lastHL) + firstLine.text.slice(to.ch), hlSpans(lastHL)));
 
791
          firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0]));
 
792
          doc.insert(from.line + 1, added);
 
793
        }
 
794
      } else if (lines.length == 1) {
 
795
        firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]) + lastLine.text.slice(to.ch), hlSpans(lines[0]));
 
796
        doc.remove(from.line + 1, nlines, callbacks);
 
797
      } else {
 
798
        var added = [];
 
799
        firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0]));
 
800
        lastLine.update(hlText(lastHL) + lastLine.text.slice(to.ch), hlSpans(lastHL));
 
801
        for (var i = 1, e = lines.length - 1; i < e; ++i)
 
802
          added.push(new Line(hlText(lines[i]), hlSpans(lines[i])));
 
803
        if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks);
 
804
        doc.insert(from.line + 1, added);
 
805
      }
 
806
      if (options.lineWrapping) {
 
807
        var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3);
 
808
        doc.iter(from.line, from.line + lines.length, function(line) {
 
809
          if (line.hidden) return;
 
810
          var guess = Math.ceil(line.text.length / perLine) || 1;
 
811
          if (guess != line.height) updateLineHeight(line, guess);
 
812
        });
 
813
      } else {
 
814
        doc.iter(from.line, from.line + lines.length, function(line) {
 
815
          var l = line.text;
 
816
          if (!line.hidden && l.length > maxLineLength) {
 
817
            maxLine = line; maxLineLength = l.length; maxLineChanged = true;
 
818
            recomputeMaxLength = false;
 
819
          }
 
820
        });
 
821
        if (recomputeMaxLength) updateMaxLine = true;
 
822
      }
 
823
 
 
824
      // Adjust frontier, schedule worker
 
825
      frontier = Math.min(frontier, from.line);
 
826
      startWorker(400);
 
827
 
 
828
      var lendiff = lines.length - nlines - 1;
 
829
      // Remember that these lines changed, for updating the display
 
830
      changes.push({from: from.line, to: to.line + 1, diff: lendiff});
 
831
      if (options.onChange) {
 
832
        // Normalize lines to contain only strings, since that's what
 
833
        // the change event handler expects
 
834
        for (var i = 0; i < lines.length; ++i)
 
835
          if (typeof lines[i] != "string") lines[i] = lines[i].text;
 
836
        var changeObj = {from: from, to: to, text: lines};
 
837
        if (textChanged) {
 
838
          for (var cur = textChanged; cur.next; cur = cur.next) {}
 
839
          cur.next = changeObj;
 
840
        } else textChanged = changeObj;
 
841
      }
 
842
 
 
843
      // Update the selection
 
844
      function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}
 
845
      setSelection(clipPos(selFrom), clipPos(selTo),
 
846
                   updateLine(sel.from.line), updateLine(sel.to.line));
 
847
    }
 
848
 
 
849
    function needsScrollbar() {
 
850
      var realHeight = doc.height * textHeight() + 2 * paddingTop();
 
851
      return realHeight * .99 > scroller.offsetHeight ? realHeight : false;
 
852
    }
 
853
 
 
854
    function updateVerticalScroll(scrollTop) {
 
855
      var scrollHeight = needsScrollbar();
 
856
      scrollbar.style.display = scrollHeight ? "block" : "none";
 
857
      if (scrollHeight) {
 
858
        scrollbarInner.style.height = sizer.style.minHeight = scrollHeight + "px";
 
859
        scrollbar.style.height = scroller.clientHeight + "px";
 
860
        if (scrollTop != null) {
 
861
          scrollbar.scrollTop = scroller.scrollTop = scrollTop;
 
862
          // 'Nudge' the scrollbar to work around a Webkit bug where,
 
863
          // in some situations, we'd end up with a scrollbar that
 
864
          // reported its scrollTop (and looked) as expected, but
 
865
          // *behaved* as if it was still in a previous state (i.e.
 
866
          // couldn't scroll up, even though it appeared to be at the
 
867
          // bottom).
 
868
          if (webkit) setTimeout(function() {
 
869
            if (scrollbar.scrollTop != scrollTop) return;
 
870
            scrollbar.scrollTop = scrollTop + (scrollTop ? -1 : 1);
 
871
            scrollbar.scrollTop = scrollTop;
 
872
          }, 0);
 
873
        }
 
874
      } else {
 
875
        sizer.style.minHeight = "";
 
876
      }
 
877
      // Position the mover div to align with the current virtual scroll position
 
878
      mover.style.top = displayOffset * textHeight() + "px";
 
879
    }
 
880
 
 
881
    function computeMaxLength() {
 
882
      maxLine = getLine(0); maxLineChanged = true;
 
883
      var maxLineLength = maxLine.text.length;
 
884
      doc.iter(1, doc.size, function(line) {
 
885
        var l = line.text;
 
886
        if (!line.hidden && l.length > maxLineLength) {
 
887
          maxLineLength = l.length; maxLine = line;
 
888
        }
 
889
      });
 
890
      updateMaxLine = false;
 
891
    }
 
892
 
 
893
    function replaceRange(code, from, to) {
 
894
      from = clipPos(from);
 
895
      if (!to) to = from; else to = clipPos(to);
 
896
      code = splitLines(code);
 
897
      function adjustPos(pos) {
 
898
        if (posLess(pos, from)) return pos;
 
899
        if (!posLess(to, pos)) return end;
 
900
        var line = pos.line + code.length - (to.line - from.line) - 1;
 
901
        var ch = pos.ch;
 
902
        if (pos.line == to.line)
 
903
          ch += lst(code).length - (to.ch - (to.line == from.line ? from.ch : 0));
 
904
        return {line: line, ch: ch};
 
905
      }
 
906
      var end;
 
907
      replaceRange1(code, from, to, function(end1) {
 
908
        end = end1;
 
909
        return {from: adjustPos(sel.from), to: adjustPos(sel.to)};
 
910
      });
 
911
      return end;
 
912
    }
 
913
    function replaceSelection(code, collapse) {
 
914
      replaceRange1(splitLines(code), sel.from, sel.to, function(end) {
 
915
        if (collapse == "end") return {from: end, to: end};
 
916
        else if (collapse == "start") return {from: sel.from, to: sel.from};
 
917
        else return {from: sel.from, to: end};
 
918
      });
 
919
    }
 
920
    function replaceRange1(code, from, to, computeSel) {
 
921
      var endch = code.length == 1 ? code[0].length + from.ch : lst(code).length;
 
922
      var newSel = computeSel({line: from.line + code.length - 1, ch: endch});
 
923
      updateLines(from, to, code, newSel.from, newSel.to);
 
924
    }
 
925
 
 
926
    function getRange(from, to, lineSep) {
 
927
      var l1 = from.line, l2 = to.line;
 
928
      if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch);
 
929
      var code = [getLine(l1).text.slice(from.ch)];
 
930
      doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });
 
931
      code.push(getLine(l2).text.slice(0, to.ch));
 
932
      return code.join(lineSep || "\n");
 
933
    }
 
934
    function getSelection(lineSep) {
 
935
      return getRange(sel.from, sel.to, lineSep);
 
936
    }
 
937
 
 
938
    function slowPoll() {
 
939
      if (pollingFast) return;
 
940
      poll.set(options.pollInterval, function() {
 
941
        readInput();
 
942
        if (focused) slowPoll();
 
943
      });
 
944
    }
 
945
    function fastPoll() {
 
946
      var missed = false;
 
947
      pollingFast = true;
 
948
      function p() {
 
949
        var changed = readInput();
 
950
        if (!changed && !missed) {missed = true; poll.set(60, p);}
 
951
        else {pollingFast = false; slowPoll();}
 
952
      }
 
953
      poll.set(20, p);
 
954
    }
 
955
 
 
956
    // Previnput is a hack to work with IME. If we reset the textarea
 
957
    // on every change, that breaks IME. So we look for changes
 
958
    // compared to the previous content instead. (Modern browsers have
 
959
    // events that indicate IME taking place, but these are not widely
 
960
    // supported or compatible enough yet to rely on.)
 
961
    var prevInput = "";
 
962
    function readInput() {
 
963
      if (!focused || hasSelection(input) || options.readOnly) return false;
 
964
      var text = input.value;
 
965
      if (text == prevInput) return false;
 
966
      if (!nestedOperation) startOperation();
 
967
      shiftSelecting = null;
 
968
      var same = 0, l = Math.min(prevInput.length, text.length);
 
969
      while (same < l && prevInput[same] == text[same]) ++same;
 
970
      if (same < prevInput.length)
 
971
        sel.from = {line: sel.from.line, ch: sel.from.ch - (prevInput.length - same)};
 
972
      else if (overwrite && posEq(sel.from, sel.to) && !pasteIncoming)
 
973
        sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};
 
974
      replaceSelection(text.slice(same), "end");
 
975
      if (text.length > 1000) { input.value = prevInput = ""; }
 
976
      else prevInput = text;
 
977
      if (!nestedOperation) endOperation();
 
978
      pasteIncoming = false;
 
979
      return true;
 
980
    }
 
981
    function resetInput(user) {
 
982
      if (!posEq(sel.from, sel.to)) {
 
983
        prevInput = "";
 
984
        input.value = getSelection();
 
985
        if (focused) selectInput(input);
 
986
      } else if (user) prevInput = input.value = "";
 
987
    }
 
988
 
 
989
    function focusInput() {
 
990
      if (options.readOnly != "nocursor" && (ie_lt9 || document.activeElement != input))
 
991
        input.focus();
 
992
    }
 
993
 
 
994
    function scrollCursorIntoView() {
 
995
      var coords = calculateCursorCoords();
 
996
      scrollIntoView(coords.x, coords.y, coords.x, coords.yBot);
 
997
      if (!focused) return;
 
998
      var box = sizer.getBoundingClientRect(), doScroll = null;
 
999
      if (coords.y + box.top < 0) doScroll = true;
 
1000
      else if (coords.y + box.top + textHeight() > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
 
1001
      if (doScroll != null) {
 
1002
        var hidden = cursor.style.display == "none";
 
1003
        if (hidden) {
 
1004
          cursor.style.display = "";
 
1005
          cursor.style.left = coords.x + "px";
 
1006
          cursor.style.top = (coords.y - displayOffset) + "px";
 
1007
        }
 
1008
        cursor.scrollIntoView(doScroll);
 
1009
        if (hidden) cursor.style.display = "none";
 
1010
      }
 
1011
    }
 
1012
    function calculateCursorCoords() {
 
1013
      var cursor = localCoords(sel.inverted ? sel.from : sel.to);
 
1014
      var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x;
 
1015
      return {x: x, y: cursor.y, yBot: cursor.yBot};
 
1016
    }
 
1017
    function scrollIntoView(x1, y1, x2, y2) {
 
1018
      var scrollPos = calculateScrollPos(x1, y1, x2, y2);
 
1019
      if (scrollPos.scrollLeft != null) {scroller.scrollLeft = scrollPos.scrollLeft;}
 
1020
      if (scrollPos.scrollTop != null) {scrollbar.scrollTop = scroller.scrollTop = scrollPos.scrollTop;}
 
1021
    }
 
1022
    function calculateScrollPos(x1, y1, x2, y2) {
 
1023
      var pl = paddingLeft(), pt = paddingTop();
 
1024
      y1 += pt; y2 += pt; x1 += pl; x2 += pl;
 
1025
      var screen = scroller.clientHeight, screentop = scrollbar.scrollTop, result = {};
 
1026
      var docBottom = needsScrollbar() || Infinity;
 
1027
      var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10;
 
1028
      if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1);
 
1029
      else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen;
 
1030
 
 
1031
      var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
 
1032
      var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
 
1033
      var atLeft = x1 < gutterw + pl + 10;
 
1034
      if (x1 < screenleft + gutterw || atLeft) {
 
1035
        if (atLeft) x1 = 0;
 
1036
        result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
 
1037
      } else if (x2 > screenw + screenleft - 3) {
 
1038
        result.scrollLeft = x2 + 10 - screenw;
 
1039
      }
 
1040
      return result;
 
1041
    }
 
1042
 
 
1043
    function visibleLines(scrollTop) {
 
1044
      var lh = textHeight(), top = (scrollTop != null ? scrollTop : scrollbar.scrollTop) - paddingTop();
 
1045
      var fromHeight = Math.max(0, Math.floor(top / lh));
 
1046
      var toHeight = Math.ceil((top + scroller.clientHeight) / lh);
 
1047
      return {from: lineAtHeight(doc, fromHeight),
 
1048
              to: lineAtHeight(doc, toHeight)};
 
1049
    }
 
1050
    // Uses a set of changes plus the current scroll position to
 
1051
    // determine which DOM updates have to be made, and makes the
 
1052
    // updates.
 
1053
    function updateDisplay(changes, suppressCallback, scrollTop) {
 
1054
      if (!scroller.clientWidth) {
 
1055
        showingFrom = showingTo = displayOffset = 0;
 
1056
        return;
 
1057
      }
 
1058
      // Compute the new visible window
 
1059
      // If scrollTop is specified, use that to determine which lines
 
1060
      // to render instead of the current scrollbar position.
 
1061
      var visible = visibleLines(scrollTop);
 
1062
      // Bail out if the visible area is already rendered and nothing changed.
 
1063
      if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) {
 
1064
        updateVerticalScroll(scrollTop);
 
1065
        return;
 
1066
      }
 
1067
      var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100);
 
1068
      if (showingFrom < from && from - showingFrom < 20) from = showingFrom;
 
1069
      if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo);
 
1070
 
 
1071
      // Create a range of theoretically intact lines, and punch holes
 
1072
      // in that using the change info.
 
1073
      var intact = changes === true ? [] :
 
1074
        computeIntact([{from: showingFrom, to: showingTo, domStart: 0}], changes);
 
1075
      // Clip off the parts that won't be visible
 
1076
      var intactLines = 0;
 
1077
      for (var i = 0; i < intact.length; ++i) {
 
1078
        var range = intact[i];
 
1079
        if (range.from < from) {range.domStart += (from - range.from); range.from = from;}
 
1080
        if (range.to > to) range.to = to;
 
1081
        if (range.from >= range.to) intact.splice(i--, 1);
 
1082
        else intactLines += range.to - range.from;
 
1083
      }
 
1084
      if (intactLines == to - from && from == showingFrom && to == showingTo) {
 
1085
        updateVerticalScroll(scrollTop);
 
1086
        return;
 
1087
      }
 
1088
      intact.sort(function(a, b) {return a.domStart - b.domStart;});
 
1089
 
 
1090
      var th = textHeight(), gutterDisplay = gutter.style.display;
 
1091
      lineDiv.style.display = "none";
 
1092
      patchDisplay(from, to, intact);
 
1093
      lineDiv.style.display = gutter.style.display = "";
 
1094
 
 
1095
      var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th;
 
1096
      // This is just a bogus formula that detects when the editor is
 
1097
      // resized or the font size changes.
 
1098
      if (different) lastSizeC = scroller.clientHeight + th;
 
1099
      if (from != showingFrom || to != showingTo && options.onViewportChange)
 
1100
        setTimeout(function(){
 
1101
          if (options.onViewportChange) options.onViewportChange(instance, from, to);
 
1102
        });
 
1103
      showingFrom = from; showingTo = to;
 
1104
      displayOffset = heightAtLine(doc, from);
 
1105
      startWorker(100);
 
1106
 
 
1107
      // Since this is all rather error prone, it is honoured with the
 
1108
      // only assertion in the whole file.
 
1109
      if (lineDiv.childNodes.length != showingTo - showingFrom)
 
1110
        throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) +
 
1111
                        " nodes=" + lineDiv.childNodes.length);
 
1112
 
 
1113
      function checkHeights() {
 
1114
        var curNode = lineDiv.firstChild, heightChanged = false;
 
1115
        doc.iter(showingFrom, showingTo, function(line) {
 
1116
          // Work around bizarro IE7 bug where, sometimes, our curNode
 
1117
          // is magically replaced with a new node in the DOM, leaving
 
1118
          // us with a reference to an orphan (nextSibling-less) node.
 
1119
          if (!curNode) return;
 
1120
          if (!line.hidden) {
 
1121
            var height = Math.round(curNode.offsetHeight / th) || 1;
 
1122
            if (line.height != height) {
 
1123
              updateLineHeight(line, height);
 
1124
              gutterDirty = heightChanged = true;
 
1125
            }
 
1126
          }
 
1127
          curNode = curNode.nextSibling;
 
1128
        });
 
1129
        return heightChanged;
 
1130
      }
 
1131
 
 
1132
      if (options.lineWrapping) checkHeights();
 
1133
 
 
1134
      gutter.style.display = gutterDisplay;
 
1135
      if (different || gutterDirty) {
 
1136
        // If the gutter grew in size, re-check heights. If those changed, re-draw gutter.
 
1137
        updateGutter() && options.lineWrapping && checkHeights() && updateGutter();
 
1138
      }
 
1139
      updateVerticalScroll(scrollTop);
 
1140
      updateSelection();
 
1141
      if (!suppressCallback && options.onUpdate) options.onUpdate(instance);
 
1142
      return true;
 
1143
    }
 
1144
 
 
1145
    function computeIntact(intact, changes) {
 
1146
      for (var i = 0, l = changes.length || 0; i < l; ++i) {
 
1147
        var change = changes[i], intact2 = [], diff = change.diff || 0;
 
1148
        for (var j = 0, l2 = intact.length; j < l2; ++j) {
 
1149
          var range = intact[j];
 
1150
          if (change.to <= range.from && change.diff)
 
1151
            intact2.push({from: range.from + diff, to: range.to + diff,
 
1152
                          domStart: range.domStart});
 
1153
          else if (change.to <= range.from || change.from >= range.to)
 
1154
            intact2.push(range);
 
1155
          else {
 
1156
            if (change.from > range.from)
 
1157
              intact2.push({from: range.from, to: change.from, domStart: range.domStart});
 
1158
            if (change.to < range.to)
 
1159
              intact2.push({from: change.to + diff, to: range.to + diff,
 
1160
                            domStart: range.domStart + (change.to - range.from)});
 
1161
          }
 
1162
        }
 
1163
        intact = intact2;
 
1164
      }
 
1165
      return intact;
 
1166
    }
 
1167
 
 
1168
    function patchDisplay(from, to, intact) {
 
1169
      function killNode(node) {
 
1170
        var tmp = node.nextSibling;
 
1171
        node.parentNode.removeChild(node);
 
1172
        return tmp;
 
1173
      }
 
1174
      // The first pass removes the DOM nodes that aren't intact.
 
1175
      if (!intact.length) removeChildren(lineDiv);
 
1176
      else {
 
1177
        var domPos = 0, curNode = lineDiv.firstChild, n;
 
1178
        for (var i = 0; i < intact.length; ++i) {
 
1179
          var cur = intact[i];
 
1180
          while (cur.domStart > domPos) {curNode = killNode(curNode); domPos++;}
 
1181
          for (var j = 0, e = cur.to - cur.from; j < e; ++j) {curNode = curNode.nextSibling; domPos++;}
 
1182
        }
 
1183
        while (curNode) curNode = killNode(curNode);
 
1184
      }
 
1185
      // This pass fills in the lines that actually changed.
 
1186
      var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;
 
1187
      doc.iter(from, to, function(line) {
 
1188
        if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();
 
1189
        if (!nextIntact || nextIntact.from > j) {
 
1190
          if (line.hidden) var lineElement = elt("pre");
 
1191
          else {
 
1192
            var lineElement = lineContent(line);
 
1193
            if (line.className) lineElement.className = line.className;
 
1194
            // Kludge to make sure the styled element lies behind the selection (by z-index)
 
1195
            if (line.bgClassName) {
 
1196
              var pre = elt("pre", "\u00a0", line.bgClassName, "position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2");
 
1197
              lineElement = elt("div", [pre, lineElement], null, "position: relative");
 
1198
            }
 
1199
          }
 
1200
          lineDiv.insertBefore(lineElement, curNode);
 
1201
        } else {
 
1202
          curNode = curNode.nextSibling;
 
1203
        }
 
1204
        ++j;
 
1205
      });
 
1206
    }
 
1207
 
 
1208
    function updateGutter() {
 
1209
      if (!options.gutter && !options.lineNumbers) return;
 
1210
      var hText = mover.offsetHeight, hEditor = scroller.clientHeight;
 
1211
      gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
 
1212
      var fragment = document.createDocumentFragment(), i = showingFrom, normalNode;
 
1213
      doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {
 
1214
        if (line.hidden) {
 
1215
          fragment.appendChild(elt("pre"));
 
1216
        } else {
 
1217
          var marker = line.gutterMarker;
 
1218
          var text = options.lineNumbers ? options.lineNumberFormatter(i + options.firstLineNumber) : null;
 
1219
          if (marker && marker.text)
 
1220
            text = marker.text.replace("%N%", text != null ? text : "");
 
1221
          else if (text == null)
 
1222
            text = "\u00a0";
 
1223
          var markerElement = fragment.appendChild(elt("pre", null, marker && marker.style));
 
1224
          markerElement.innerHTML = text;
 
1225
          for (var j = 1; j < line.height; ++j) {
 
1226
            markerElement.appendChild(elt("br"));
 
1227
            markerElement.appendChild(document.createTextNode("\u00a0"));
 
1228
          }
 
1229
          if (!marker) normalNode = i;
 
1230
        }
 
1231
        ++i;
 
1232
      });
 
1233
      gutter.style.display = "none";
 
1234
      removeChildrenAndAdd(gutterText, fragment);
 
1235
      // Make sure scrolling doesn't cause number gutter size to pop
 
1236
      if (normalNode != null && options.lineNumbers) {
 
1237
        var node = gutterText.childNodes[normalNode - showingFrom];
 
1238
        var minwidth = String(doc.size).length, val = eltText(node.firstChild), pad = "";
 
1239
        while (val.length + pad.length < minwidth) pad += "\u00a0";
 
1240
        if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild);
 
1241
      }
 
1242
      gutter.style.display = "";
 
1243
      var resized = Math.abs((parseInt(lineSpace.style.marginLeft) || 0) - gutter.offsetWidth) > 2;
 
1244
      lineSpace.style.marginLeft = gutter.offsetWidth + "px";
 
1245
      gutterDirty = false;
 
1246
      return resized;
 
1247
    }
 
1248
    function updateSelection() {
 
1249
      var collapsed = posEq(sel.from, sel.to);
 
1250
      var fromPos = localCoords(sel.from, true);
 
1251
      var toPos = collapsed ? fromPos : localCoords(sel.to, true);
 
1252
      var headPos = sel.inverted ? fromPos : toPos, th = textHeight();
 
1253
      var wrapOff = eltOffset(wrapper), lineOff = eltOffset(lineDiv);
 
1254
      inputDiv.style.top = Math.max(0, Math.min(scroller.offsetHeight, headPos.y + lineOff.top - wrapOff.top)) + "px";
 
1255
      inputDiv.style.left = Math.max(0, Math.min(scroller.offsetWidth, headPos.x + lineOff.left - wrapOff.left)) + "px";
 
1256
      if (collapsed || options.showCursorWhenSelecting) {
 
1257
        cursor.style.top = headPos.y + "px";
 
1258
        cursor.style.left = (options.lineWrapping ? Math.min(headPos.x, lineSpace.offsetWidth) : headPos.x) + "px";
 
1259
        cursor.style.display = "";
 
1260
      } else {
 
1261
        cursor.style.display = "none";
 
1262
      }
 
1263
      if (!collapsed) {
 
1264
        var sameLine = fromPos.y == toPos.y, fragment = document.createDocumentFragment();
 
1265
        var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth;
 
1266
        var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight;
 
1267
        var add = function(left, top, right, height) {
 
1268
          var rstyle = quirksMode ? "width: " + (!right ? clientWidth : clientWidth - right - left) + "px"
 
1269
                                  : "right: " + (right - 1) + "px";
 
1270
          fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
 
1271
                                   "px; top: " + top + "px; " + rstyle + "; height: " + height + "px"));
 
1272
        };
 
1273
        if (sel.from.ch && fromPos.y >= 0) {
 
1274
          var right = sameLine ? clientWidth - toPos.x : 0;
 
1275
          add(fromPos.x, fromPos.y, right, th);
 
1276
        }
 
1277
        var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0));
 
1278
        var middleHeight = Math.min(toPos.y, clientHeight) - middleStart;
 
1279
        if (middleHeight > 0.2 * th)
 
1280
          add(0, middleStart, 0, middleHeight);
 
1281
        if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th)
 
1282
          add(0, toPos.y, clientWidth - toPos.x, th);
 
1283
        removeChildrenAndAdd(selectionDiv, fragment);
 
1284
        selectionDiv.style.display = "";
 
1285
      } else {
 
1286
        selectionDiv.style.display = "none";
 
1287
      }
 
1288
    }
 
1289
 
 
1290
    function setShift(val) {
 
1291
      if (val) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);
 
1292
      else shiftSelecting = null;
 
1293
    }
 
1294
    function setSelectionUser(from, to) {
 
1295
      var sh = shiftSelecting && clipPos(shiftSelecting);
 
1296
      if (sh) {
 
1297
        if (posLess(sh, from)) from = sh;
 
1298
        else if (posLess(to, sh)) to = sh;
 
1299
      }
 
1300
      setSelection(from, to);
 
1301
      userSelChange = true;
 
1302
    }
 
1303
    // Update the selection. Last two args are only used by
 
1304
    // updateLines, since they have to be expressed in the line
 
1305
    // numbers before the update.
 
1306
    function setSelection(from, to, oldFrom, oldTo) {
 
1307
      goalColumn = null;
 
1308
      if (oldFrom == null) {oldFrom = sel.from.line; oldTo = sel.to.line;}
 
1309
      if (posEq(sel.from, from) && posEq(sel.to, to)) return;
 
1310
      if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}
 
1311
 
 
1312
      // Skip over hidden lines.
 
1313
      if (from.line != oldFrom) {
 
1314
        var from1 = skipHidden(from, oldFrom, sel.from.ch);
 
1315
        // If there is no non-hidden line left, force visibility on current line
 
1316
        if (!from1) setLineHidden(from.line, false);
 
1317
        else from = from1;
 
1318
      }
 
1319
      if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch);
 
1320
 
 
1321
      if (posEq(from, to)) sel.inverted = false;
 
1322
      else if (posEq(from, sel.to)) sel.inverted = false;
 
1323
      else if (posEq(to, sel.from)) sel.inverted = true;
 
1324
 
 
1325
      if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) {
 
1326
        var head = sel.inverted ? from : to;
 
1327
        if (head.line != sel.from.line && sel.from.line < doc.size) {
 
1328
          var oldLine = getLine(sel.from.line);
 
1329
          if (/^\s+$/.test(oldLine.text))
 
1330
            setTimeout(operation(function() {
 
1331
              if (oldLine.parent && /^\s+$/.test(oldLine.text)) {
 
1332
                var no = lineNo(oldLine);
 
1333
                replaceRange("", {line: no, ch: 0}, {line: no, ch: oldLine.text.length});
 
1334
              }
 
1335
            }, 10));
 
1336
        }
 
1337
      }
 
1338
 
 
1339
      sel.from = from; sel.to = to;
 
1340
      selectionChanged = true;
 
1341
    }
 
1342
    function skipHidden(pos, oldLine, oldCh) {
 
1343
      function getNonHidden(dir) {
 
1344
        var lNo = pos.line + dir, end = dir == 1 ? doc.size : -1;
 
1345
        while (lNo != end) {
 
1346
          var line = getLine(lNo);
 
1347
          if (!line.hidden) {
 
1348
            var ch = pos.ch;
 
1349
            if (toEnd || ch > oldCh || ch > line.text.length) ch = line.text.length;
 
1350
            return {line: lNo, ch: ch};
 
1351
          }
 
1352
          lNo += dir;
 
1353
        }
 
1354
      }
 
1355
      var line = getLine(pos.line);
 
1356
      var toEnd = pos.ch == line.text.length && pos.ch != oldCh;
 
1357
      if (!line.hidden) return pos;
 
1358
      if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);
 
1359
      else return getNonHidden(-1) || getNonHidden(1);
 
1360
    }
 
1361
    function setCursor(line, ch, user) {
 
1362
      var pos = clipPos({line: line, ch: ch || 0});
 
1363
      (user ? setSelectionUser : setSelection)(pos, pos);
 
1364
    }
 
1365
 
 
1366
    function clipLine(n) {return Math.max(0, Math.min(n, doc.size-1));}
 
1367
    function clipPos(pos) {
 
1368
      if (pos.line < 0) return {line: 0, ch: 0};
 
1369
      if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc.size-1).text.length};
 
1370
      var ch = pos.ch, linelen = getLine(pos.line).text.length;
 
1371
      if (ch == null || ch > linelen) return {line: pos.line, ch: linelen};
 
1372
      else if (ch < 0) return {line: pos.line, ch: 0};
 
1373
      else return pos;
 
1374
    }
 
1375
 
 
1376
    function findPosH(dir, unit) {
 
1377
      var end = sel.inverted ? sel.from : sel.to, line = end.line, ch = end.ch;
 
1378
      var lineObj = getLine(line);
 
1379
      function findNextLine() {
 
1380
        for (var l = line + dir, e = dir < 0 ? -1 : doc.size; l != e; l += dir) {
 
1381
          var lo = getLine(l);
 
1382
          if (!lo.hidden) { line = l; lineObj = lo; return true; }
 
1383
        }
 
1384
      }
 
1385
      function moveOnce(boundToLine) {
 
1386
        if (ch == (dir < 0 ? 0 : lineObj.text.length)) {
 
1387
          if (!boundToLine && findNextLine()) ch = dir < 0 ? lineObj.text.length : 0;
 
1388
          else return false;
 
1389
        } else ch += dir;
 
1390
        return true;
 
1391
      }
 
1392
      if (unit == "char") moveOnce();
 
1393
      else if (unit == "column") moveOnce(true);
 
1394
      else if (unit == "word") {
 
1395
        var sawWord = false;
 
1396
        for (;;) {
 
1397
          if (dir < 0) if (!moveOnce()) break;
 
1398
          if (isWordChar(lineObj.text.charAt(ch))) sawWord = true;
 
1399
          else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;}
 
1400
          if (dir > 0) if (!moveOnce()) break;
 
1401
        }
 
1402
      }
 
1403
      return {line: line, ch: ch};
 
1404
    }
 
1405
    function moveH(dir, unit) {
 
1406
      var pos = dir < 0 ? sel.from : sel.to;
 
1407
      if (shiftSelecting || posEq(sel.from, sel.to)) pos = findPosH(dir, unit);
 
1408
      setCursor(pos.line, pos.ch, true);
 
1409
    }
 
1410
    function deleteH(dir, unit) {
 
1411
      if (!posEq(sel.from, sel.to)) replaceRange("", sel.from, sel.to);
 
1412
      else if (dir < 0) replaceRange("", findPosH(dir, unit), sel.to);
 
1413
      else replaceRange("", sel.from, findPosH(dir, unit));
 
1414
      userSelChange = true;
 
1415
    }
 
1416
    function moveV(dir, unit) {
 
1417
      var dist = 0, pos = localCoords(sel.inverted ? sel.from : sel.to, true);
 
1418
      if (goalColumn != null) pos.x = goalColumn;
 
1419
      if (unit == "page") {
 
1420
        var screen = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight);
 
1421
        var target = coordsChar(pos.x, pos.y + screen * dir);
 
1422
      } else if (unit == "line") {
 
1423
        var th = textHeight();
 
1424
        var target = coordsChar(pos.x, pos.y + .5 * th + dir * th);
 
1425
      }
 
1426
      if (unit == "page") scrollbar.scrollTop += localCoords(target, true).y - pos.y;
 
1427
      setCursor(target.line, target.ch, true);
 
1428
      goalColumn = pos.x;
 
1429
    }
 
1430
 
 
1431
    function findWordAt(pos) {
 
1432
      var line = getLine(pos.line).text;
 
1433
      var start = pos.ch, end = pos.ch;
 
1434
      if (line) {
 
1435
        if (pos.after === false || end == line.length) --start; else ++end;
 
1436
        var startChar = line.charAt(start);
 
1437
        var check = isWordChar(startChar) ? isWordChar :
 
1438
                    /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} :
 
1439
                    function(ch) {return !/\s/.test(ch) && isWordChar(ch);};
 
1440
        while (start > 0 && check(line.charAt(start - 1))) --start;
 
1441
        while (end < line.length && check(line.charAt(end))) ++end;
 
1442
      }
 
1443
      return {from: {line: pos.line, ch: start}, to: {line: pos.line, ch: end}};
 
1444
    }
 
1445
    function selectLine(line) {
 
1446
      setSelectionUser({line: line, ch: 0}, clipPos({line: line + 1, ch: 0}));
 
1447
    }
 
1448
    function indentSelected(mode) {
 
1449
      if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);
 
1450
      var e = sel.to.line - (sel.to.ch ? 0 : 1);
 
1451
      for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode);
 
1452
    }
 
1453
 
 
1454
    function indentLine(n, how) {
 
1455
      if (!how) how = "add";
 
1456
      if (how == "smart") {
 
1457
        if (!mode.indent) how = "prev";
 
1458
        else var state = getStateBefore(n);
 
1459
      }
 
1460
 
 
1461
      var line = getLine(n), curSpace = line.indentation(options.tabSize),
 
1462
          curSpaceString = line.text.match(/^\s*/)[0], indentation;
 
1463
      if (how == "smart") {
 
1464
        indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);
 
1465
        if (indentation == Pass) how = "prev";
 
1466
      }
 
1467
      if (how == "prev") {
 
1468
        if (n) indentation = getLine(n-1).indentation(options.tabSize);
 
1469
        else indentation = 0;
 
1470
      }
 
1471
      else if (how == "add") indentation = curSpace + options.indentUnit;
 
1472
      else if (how == "subtract") indentation = curSpace - options.indentUnit;
 
1473
      indentation = Math.max(0, indentation);
 
1474
      var diff = indentation - curSpace;
 
1475
 
 
1476
      var indentString = "", pos = 0;
 
1477
      if (options.indentWithTabs)
 
1478
        for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";}
 
1479
      if (pos < indentation) indentString += spaceStr(indentation - pos);
 
1480
 
 
1481
      if (indentString != curSpaceString)
 
1482
        replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});
 
1483
      line.stateAfter = null;
 
1484
    }
 
1485
 
 
1486
    function loadMode() {
 
1487
      mode = CodeMirror.getMode(options, options.mode);
 
1488
      doc.iter(0, doc.size, function(line) { line.stateAfter = null; });
 
1489
      frontier = 0;
 
1490
      startWorker(100);
 
1491
    }
 
1492
    function gutterChanged() {
 
1493
      var visible = options.gutter || options.lineNumbers;
 
1494
      gutter.style.display = visible ? "" : "none";
 
1495
      if (visible) gutterDirty = true;
 
1496
      else lineDiv.parentNode.style.marginLeft = 0;
 
1497
    }
 
1498
    function wrappingChanged(from, to) {
 
1499
      if (options.lineWrapping) {
 
1500
        wrapper.className += " CodeMirror-wrap";
 
1501
        var perLine = scroller.clientWidth / charWidth() - 3;
 
1502
        doc.iter(0, doc.size, function(line) {
 
1503
          if (line.hidden) return;
 
1504
          var guess = Math.ceil(line.text.length / perLine) || 1;
 
1505
          if (guess != 1) updateLineHeight(line, guess);
 
1506
        });
 
1507
        lineSpace.style.minWidth = widthForcer.style.left = "";
 
1508
      } else {
 
1509
        wrapper.className = wrapper.className.replace(" CodeMirror-wrap", "");
 
1510
        computeMaxLength();
 
1511
        doc.iter(0, doc.size, function(line) {
 
1512
          if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);
 
1513
        });
 
1514
      }
 
1515
      changes.push({from: 0, to: doc.size});
 
1516
    }
 
1517
    function themeChanged() {
 
1518
      scroller.className = scroller.className.replace(/\s*cm-s-\S+/g, "") +
 
1519
        options.theme.replace(/(^|\s)\s*/g, " cm-s-");
 
1520
    }
 
1521
    function keyMapChanged() {
 
1522
      var style = keyMap[options.keyMap].style;
 
1523
      wrapper.className = wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
 
1524
        (style ? " cm-keymap-" + style : "");
 
1525
    }
 
1526
 
 
1527
    function TextMarker(type, style) { this.lines = []; this.type = type; if (style) this.style = style; }
 
1528
    TextMarker.prototype.clear = operation(function() {
 
1529
      var min, max;
 
1530
      for (var i = 0; i < this.lines.length; ++i) {
 
1531
        var line = this.lines[i];
 
1532
        var span = getMarkedSpanFor(line.markedSpans, this);
 
1533
        if (span.from != null) min = lineNo(line);
 
1534
        if (span.to != null) max = lineNo(line);
 
1535
        line.markedSpans = removeMarkedSpan(line.markedSpans, span);
 
1536
      }
 
1537
      if (min != null) changes.push({from: min, to: max + 1});
 
1538
      this.lines.length = 0;
 
1539
      this.explicitlyCleared = true;
 
1540
    });
 
1541
    TextMarker.prototype.find = function() {
 
1542
      var from, to;
 
1543
      for (var i = 0; i < this.lines.length; ++i) {
 
1544
        var line = this.lines[i];
 
1545
        var span = getMarkedSpanFor(line.markedSpans, this);
 
1546
        if (span.from != null || span.to != null) {
 
1547
          var found = lineNo(line);
 
1548
          if (span.from != null) from = {line: found, ch: span.from};
 
1549
          if (span.to != null) to = {line: found, ch: span.to};
 
1550
        }
 
1551
      }
 
1552
      if (this.type == "bookmark") return from;
 
1553
      return from && {from: from, to: to};
 
1554
    };
 
1555
 
 
1556
    function markText(from, to, className, options) {
 
1557
      from = clipPos(from); to = clipPos(to);
 
1558
      var marker = new TextMarker("range", className);
 
1559
      if (options) for (var opt in options) if (options.hasOwnProperty(opt))
 
1560
        marker[opt] = options[opt];
 
1561
      var curLine = from.line;
 
1562
      doc.iter(curLine, to.line + 1, function(line) {
 
1563
        var span = {from: curLine == from.line ? from.ch : null,
 
1564
                    to: curLine == to.line ? to.ch : null,
 
1565
                    marker: marker};
 
1566
        line.markedSpans = (line.markedSpans || []).concat([span]);
 
1567
        marker.lines.push(line);
 
1568
        ++curLine;
 
1569
      });
 
1570
      changes.push({from: from.line, to: to.line + 1});
 
1571
      return marker;
 
1572
    }
 
1573
 
 
1574
    function setBookmark(pos) {
 
1575
      pos = clipPos(pos);
 
1576
      var marker = new TextMarker("bookmark"), line = getLine(pos.line);
 
1577
      history.addChange(pos.line, 1, [newHL(line.text, line.markedSpans)], true);
 
1578
      var span = {from: pos.ch, to: pos.ch, marker: marker};
 
1579
      line.markedSpans = (line.markedSpans || []).concat([span]);
 
1580
      marker.lines.push(line);
 
1581
      return marker;
 
1582
    }
 
1583
 
 
1584
    function findMarksAt(pos) {
 
1585
      pos = clipPos(pos);
 
1586
      var markers = [], spans = getLine(pos.line).markedSpans;
 
1587
      if (spans) for (var i = 0; i < spans.length; ++i) {
 
1588
        var span = spans[i];
 
1589
        if ((span.from == null || span.from <= pos.ch) &&
 
1590
            (span.to == null || span.to >= pos.ch))
 
1591
          markers.push(span.marker);
 
1592
      }
 
1593
      return markers;
 
1594
    }
 
1595
 
 
1596
    function addGutterMarker(line, text, className) {
 
1597
      if (typeof line == "number") line = getLine(clipLine(line));
 
1598
      line.gutterMarker = {text: text, style: className};
 
1599
      gutterDirty = true;
 
1600
      return line;
 
1601
    }
 
1602
    function removeGutterMarker(line) {
 
1603
      if (typeof line == "number") line = getLine(clipLine(line));
 
1604
      line.gutterMarker = null;
 
1605
      gutterDirty = true;
 
1606
    }
 
1607
 
 
1608
    function changeLine(handle, op) {
 
1609
      var no = handle, line = handle;
 
1610
      if (typeof handle == "number") line = getLine(clipLine(handle));
 
1611
      else no = lineNo(handle);
 
1612
      if (no == null) return null;
 
1613
      if (op(line, no)) changes.push({from: no, to: no + 1});
 
1614
      else return null;
 
1615
      return line;
 
1616
    }
 
1617
    function setLineClass(handle, className, bgClassName) {
 
1618
      return changeLine(handle, function(line) {
 
1619
        if (line.className != className || line.bgClassName != bgClassName) {
 
1620
          line.className = className;
 
1621
          line.bgClassName = bgClassName;
 
1622
          return true;
 
1623
        }
 
1624
      });
 
1625
    }
 
1626
    function setLineHidden(handle, hidden) {
 
1627
      return changeLine(handle, function(line, no) {
 
1628
        if (line.hidden != hidden) {
 
1629
          line.hidden = hidden;
 
1630
          if (!options.lineWrapping) {
 
1631
            if (hidden && line.text.length == maxLine.text.length) {
 
1632
              updateMaxLine = true;
 
1633
            } else if (!hidden && line.text.length > maxLine.text.length) {
 
1634
              maxLine = line; updateMaxLine = false;
 
1635
            }
 
1636
          }
 
1637
          updateLineHeight(line, hidden ? 0 : 1);
 
1638
          var fline = sel.from.line, tline = sel.to.line;
 
1639
          if (hidden && (fline == no || tline == no)) {
 
1640
            var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from;
 
1641
            var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to;
 
1642
            // Can't hide the last visible line, we'd have no place to put the cursor
 
1643
            if (!to) return;
 
1644
            setSelection(from, to);
 
1645
          }
 
1646
          return (gutterDirty = true);
 
1647
        }
 
1648
      });
 
1649
    }
 
1650
 
 
1651
    function lineInfo(line) {
 
1652
      if (typeof line == "number") {
 
1653
        if (!isLine(line)) return null;
 
1654
        var n = line;
 
1655
        line = getLine(line);
 
1656
        if (!line) return null;
 
1657
      } else {
 
1658
        var n = lineNo(line);
 
1659
        if (n == null) return null;
 
1660
      }
 
1661
      var marker = line.gutterMarker;
 
1662
      return {line: n, handle: line, text: line.text, markerText: marker && marker.text,
 
1663
              markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName};
 
1664
    }
 
1665
 
 
1666
    function measureLine(line, ch) {
 
1667
      if (ch == 0) return {top: 0, left: 0};
 
1668
      var pre = lineContent(line, ch);
 
1669
      removeChildrenAndAdd(measure, pre);
 
1670
      var anchor = pre.anchor;
 
1671
      var top = anchor.offsetTop, left = anchor.offsetLeft;
 
1672
      // Older IEs report zero offsets for spans directly after a wrap
 
1673
      if (ie && top == 0 && left == 0) {
 
1674
        var backup = elt("span", "x");
 
1675
        anchor.parentNode.insertBefore(backup, anchor.nextSibling);
 
1676
        top = backup.offsetTop;
 
1677
      }
 
1678
      return {top: top, left: left};
 
1679
    }
 
1680
    function localCoords(pos, inLineWrap) {
 
1681
      var x, lh = textHeight(), y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0));
 
1682
      if (pos.ch == 0) x = 0;
 
1683
      else {
 
1684
        var sp = measureLine(getLine(pos.line), pos.ch);
 
1685
        x = sp.left;
 
1686
        if (options.lineWrapping) y += Math.max(0, sp.top);
 
1687
      }
 
1688
      return {x: x, y: y, yBot: y + lh};
 
1689
    }
 
1690
    // Coords must be lineSpace-local
 
1691
    function coordsChar(x, y) {
 
1692
      var th = textHeight(), cw = charWidth(), heightPos = displayOffset + Math.floor(y / th);
 
1693
      if (heightPos < 0) return {line: 0, ch: 0};
 
1694
      var lineNo = lineAtHeight(doc, heightPos);
 
1695
      if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc.size - 1).text.length};
 
1696
      var lineObj = getLine(lineNo), text = lineObj.text;
 
1697
      var tw = options.lineWrapping, innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0;
 
1698
      if (x <= 0 && innerOff == 0) return {line: lineNo, ch: 0};
 
1699
      var wrongLine = false;
 
1700
      function getX(len) {
 
1701
        var sp = measureLine(lineObj, len);
 
1702
        if (tw) {
 
1703
          var off = Math.round(sp.top / th);
 
1704
          wrongLine = off != innerOff;
 
1705
          return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth);
 
1706
        }
 
1707
        return sp.left;
 
1708
      }
 
1709
      var from = 0, fromX = 0, to = text.length, toX;
 
1710
      // Guess a suitable upper bound for our search.
 
1711
      var estimated = Math.min(to, Math.ceil((x + innerOff * scroller.clientWidth * .9) / cw));
 
1712
      for (;;) {
 
1713
        var estX = getX(estimated);
 
1714
        if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));
 
1715
        else {toX = estX; to = estimated; break;}
 
1716
      }
 
1717
      if (x > toX) return {line: lineNo, ch: to};
 
1718
      // Try to guess a suitable lower bound as well.
 
1719
      estimated = Math.floor(to * 0.8); estX = getX(estimated);
 
1720
      if (estX < x) {from = estimated; fromX = estX;}
 
1721
      // Do a binary search between these bounds.
 
1722
      for (;;) {
 
1723
        if (to - from <= 1) {
 
1724
          var after = x - fromX < toX - x;
 
1725
          return {line: lineNo, ch: after ? from : to, after: after};
 
1726
        }
 
1727
        var middle = Math.ceil((from + to) / 2), middleX = getX(middle);
 
1728
        if (middleX > x) {to = middle; toX = middleX; if (wrongLine) toX += 1000; }
 
1729
        else {from = middle; fromX = middleX;}
 
1730
      }
 
1731
    }
 
1732
    function pageCoords(pos) {
 
1733
      var local = localCoords(pos, true), off = eltOffset(lineSpace);
 
1734
      return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot};
 
1735
    }
 
1736
 
 
1737
    var cachedHeight, cachedHeightFor, measurePre;
 
1738
    function textHeight() {
 
1739
      if (measurePre == null) {
 
1740
        measurePre = elt("pre");
 
1741
        for (var i = 0; i < 49; ++i) {
 
1742
          measurePre.appendChild(document.createTextNode("x"));
 
1743
          measurePre.appendChild(elt("br"));
 
1744
        }
 
1745
        measurePre.appendChild(document.createTextNode("x"));
 
1746
      }
 
1747
      var offsetHeight = lineDiv.clientHeight;
 
1748
      if (offsetHeight == cachedHeightFor) return cachedHeight;
 
1749
      cachedHeightFor = offsetHeight;
 
1750
      removeChildrenAndAdd(measure, measurePre.cloneNode(true));
 
1751
      cachedHeight = measure.firstChild.offsetHeight / 50 || 1;
 
1752
      removeChildren(measure);
 
1753
      return cachedHeight;
 
1754
    }
 
1755
    var cachedWidth, cachedWidthFor = 0;
 
1756
    function charWidth() {
 
1757
      if (scroller.clientWidth == cachedWidthFor) return cachedWidth;
 
1758
      cachedWidthFor = scroller.clientWidth;
 
1759
      var anchor = elt("span", "x");
 
1760
      var pre = elt("pre", [anchor]);
 
1761
      removeChildrenAndAdd(measure, pre);
 
1762
      return (cachedWidth = anchor.offsetWidth || 10);
 
1763
    }
 
1764
    function paddingTop() {return lineSpace.offsetTop;}
 
1765
    function paddingLeft() {return lineSpace.offsetLeft;}
 
1766
 
 
1767
    function posFromMouse(e, liberal) {
 
1768
      var offW = eltOffset(scroller, true), x, y;
 
1769
      // Fails unpredictably on IE[67] when mouse is dragged around quickly.
 
1770
      try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
 
1771
      // This is a mess of a heuristic to try and determine whether a
 
1772
      // scroll-bar was clicked or not, and to return null if one was
 
1773
      // (and !liberal).
 
1774
      if (!liberal && (x - offW.left > scroller.clientWidth || y - offW.top > scroller.clientHeight))
 
1775
        return null;
 
1776
      var offL = eltOffset(lineSpace, true);
 
1777
      return coordsChar(x - offL.left, y - offL.top);
 
1778
    }
 
1779
    var detectingSelectAll;
 
1780
    function onContextMenu(e) {
 
1781
      var pos = posFromMouse(e), scrollPos = scrollbar.scrollTop;
 
1782
      if (!pos || opera) return; // Opera is difficult.
 
1783
      if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
 
1784
        operation(setCursor)(pos.line, pos.ch);
 
1785
 
 
1786
      var oldCSS = input.style.cssText;
 
1787
      inputDiv.style.position = "absolute";
 
1788
      input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
 
1789
        "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; " +
 
1790
        "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
 
1791
      focusInput();
 
1792
      resetInput(true);
 
1793
      // Adds "Select all" to context menu in FF
 
1794
      if (posEq(sel.from, sel.to)) input.value = prevInput = " ";
 
1795
 
 
1796
      function rehide() {
 
1797
        inputDiv.style.position = "relative";
 
1798
        input.style.cssText = oldCSS;
 
1799
        if (ie_lt9) scrollbar.scrollTop = scrollPos;
 
1800
        slowPoll();
 
1801
 
 
1802
        // Try to detect the user choosing select-all 
 
1803
        if (input.selectionStart != null) {
 
1804
          clearTimeout(detectingSelectAll);
 
1805
          var extval = input.value = " " + (posEq(sel.from, sel.to) ? "" : input.value), i = 0;
 
1806
          prevInput = " ";
 
1807
          input.selectionStart = 1; input.selectionEnd = extval.length;
 
1808
          detectingSelectAll = setTimeout(function poll(){
 
1809
            if (prevInput == " " && input.selectionStart == 0)
 
1810
              operation(commands.selectAll)(instance);
 
1811
            else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
 
1812
            else resetInput();
 
1813
          }, 200);
 
1814
        }
 
1815
      }
 
1816
 
 
1817
      if (gecko) {
 
1818
        e_stop(e);
 
1819
        var mouseup = connect(window, "mouseup", function() {
 
1820
          mouseup();
 
1821
          setTimeout(rehide, 20);
 
1822
        }, true);
 
1823
      } else {
 
1824
        setTimeout(rehide, 50);
 
1825
      }
 
1826
    }
 
1827
 
 
1828
    // Cursor-blinking
 
1829
    function restartBlink() {
 
1830
      clearInterval(blinker);
 
1831
      var on = true;
 
1832
      cursor.style.visibility = "";
 
1833
      blinker = setInterval(function() {
 
1834
        cursor.style.visibility = (on = !on) ? "" : "hidden";
 
1835
      }, options.cursorBlinkRate);
 
1836
    }
 
1837
 
 
1838
    var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
 
1839
    function matchBrackets(autoclear) {
 
1840
      var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1;
 
1841
      var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
 
1842
      if (!match) return;
 
1843
      var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1, st = line.styles;
 
1844
      for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2)
 
1845
        if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;}
 
1846
 
 
1847
      var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
 
1848
      function scan(line, from, to) {
 
1849
        if (!line.text) return;
 
1850
        var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;
 
1851
        for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {
 
1852
          var text = st[i];
 
1853
          if (st[i+1] != style) {pos += d * text.length; continue;}
 
1854
          for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {
 
1855
            if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {
 
1856
              var match = matching[cur];
 
1857
              if (match.charAt(1) == ">" == forward) stack.push(cur);
 
1858
              else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
 
1859
              else if (!stack.length) return {pos: pos, match: true};
 
1860
            }
 
1861
          }
 
1862
        }
 
1863
      }
 
1864
      for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) {
 
1865
        var line = getLine(i), first = i == head.line;
 
1866
        var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length);
 
1867
        if (found) break;
 
1868
      }
 
1869
      if (!found) found = {pos: null, match: false};
 
1870
      var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
 
1871
      var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style),
 
1872
          two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style);
 
1873
      var clear = operation(function(){one.clear(); two && two.clear();});
 
1874
      if (autoclear) setTimeout(clear, 800);
 
1875
      else bracketHighlighted = clear;
 
1876
    }
 
1877
 
 
1878
    // Finds the line to start with when starting a parse. Tries to
 
1879
    // find a line with a stateAfter, so that it can start with a
 
1880
    // valid state. If that fails, it returns the line with the
 
1881
    // smallest indentation, which tends to need the least context to
 
1882
    // parse correctly.
 
1883
    function findStartLine(n) {
 
1884
      var minindent, minline;
 
1885
      for (var search = n, lim = n - 40; search > lim; --search) {
 
1886
        if (search == 0) return 0;
 
1887
        var line = getLine(search-1);
 
1888
        if (line.stateAfter) return search;
 
1889
        var indented = line.indentation(options.tabSize);
 
1890
        if (minline == null || minindent > indented) {
 
1891
          minline = search - 1;
 
1892
          minindent = indented;
 
1893
        }
 
1894
      }
 
1895
      return minline;
 
1896
    }
 
1897
    function getStateBefore(n) {
 
1898
      var pos = findStartLine(n), state = pos && getLine(pos-1).stateAfter;
 
1899
      if (!state) state = startState(mode);
 
1900
      else state = copyState(mode, state);
 
1901
      doc.iter(pos, n, function(line) {
 
1902
        line.process(mode, state, options.tabSize);
 
1903
        line.stateAfter = (pos == n - 1 || pos % 5 == 0) ? copyState(mode, state) : null;
 
1904
      });
 
1905
      return state;
 
1906
    }
 
1907
    function highlightWorker() {
 
1908
      if (frontier >= showingTo) return;
 
1909
      var end = +new Date + options.workTime, state = copyState(mode, getStateBefore(frontier));
 
1910
      var startFrontier = frontier;
 
1911
      doc.iter(frontier, showingTo, function(line) {
 
1912
        if (frontier >= showingFrom) { // Visible
 
1913
          line.highlight(mode, state, options.tabSize);
 
1914
          line.stateAfter = copyState(mode, state);
 
1915
        } else {
 
1916
          line.process(mode, state, options.tabSize);
 
1917
          line.stateAfter = frontier % 5 == 0 ? copyState(mode, state) : null;
 
1918
        }
 
1919
        ++frontier;
 
1920
        if (+new Date > end) {
 
1921
          startWorker(options.workDelay);
 
1922
          return true;
 
1923
        }
 
1924
      });
 
1925
      if (showingTo > startFrontier && frontier >= showingFrom)
 
1926
        operation(function() {changes.push({from: startFrontier, to: frontier});})();
 
1927
    }
 
1928
    function startWorker(time) {
 
1929
      if (frontier < showingTo)
 
1930
        highlight.set(time, highlightWorker);
 
1931
    }
 
1932
 
 
1933
    // Operations are used to wrap changes in such a way that each
 
1934
    // change won't have to update the cursor and display (which would
 
1935
    // be awkward, slow, and error-prone), but instead updates are
 
1936
    // batched and then all combined and executed at once.
 
1937
    function startOperation() {
 
1938
      updateInput = userSelChange = textChanged = null;
 
1939
      changes = []; selectionChanged = false; callbacks = [];
 
1940
    }
 
1941
    function endOperation() {
 
1942
      if (updateMaxLine) computeMaxLength();
 
1943
      if (maxLineChanged && !options.lineWrapping) {
 
1944
        var cursorWidth = widthForcer.offsetWidth, left = measureLine(maxLine, maxLine.text.length).left;
 
1945
        if (!ie_lt8) {
 
1946
          widthForcer.style.left = left + "px";
 
1947
          lineSpace.style.minWidth = (left + cursorWidth) + "px";
 
1948
        }
 
1949
        maxLineChanged = false;
 
1950
      }
 
1951
      var newScrollPos, updated;
 
1952
      if (selectionChanged) {
 
1953
        var coords = calculateCursorCoords();
 
1954
        newScrollPos = calculateScrollPos(coords.x, coords.y, coords.x, coords.yBot);
 
1955
      }
 
1956
      if (changes.length || newScrollPos && newScrollPos.scrollTop != null)
 
1957
        updated = updateDisplay(changes, true, newScrollPos && newScrollPos.scrollTop);
 
1958
      if (!updated) {
 
1959
        if (selectionChanged) updateSelection();
 
1960
        if (gutterDirty) updateGutter();
 
1961
      }
 
1962
      if (newScrollPos) scrollCursorIntoView();
 
1963
      if (selectionChanged) restartBlink();
 
1964
 
 
1965
      if (focused && (updateInput === true || (updateInput !== false && selectionChanged)))
 
1966
        resetInput(userSelChange);
 
1967
 
 
1968
      if (selectionChanged && options.matchBrackets)
 
1969
        setTimeout(operation(function() {
 
1970
          if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}
 
1971
          if (posEq(sel.from, sel.to)) matchBrackets(false);
 
1972
        }), 20);
 
1973
      var sc = selectionChanged, cbs = callbacks; // these can be reset by callbacks
 
1974
      if (textChanged && options.onChange && instance)
 
1975
        options.onChange(instance, textChanged);
 
1976
      if (sc && options.onCursorActivity)
 
1977
        options.onCursorActivity(instance);
 
1978
      for (var i = 0; i < cbs.length; ++i) cbs[i](instance);
 
1979
      if (updated && options.onUpdate) options.onUpdate(instance);
 
1980
    }
 
1981
    var nestedOperation = 0;
 
1982
    function operation(f) {
 
1983
      return function() {
 
1984
        if (!nestedOperation++) startOperation();
 
1985
        try {var result = f.apply(this, arguments);}
 
1986
        finally {if (!--nestedOperation) endOperation();}
 
1987
        return result;
 
1988
      };
 
1989
    }
 
1990
 
 
1991
    function compoundChange(f) {
 
1992
      history.startCompound();
 
1993
      try { return f(); } finally { history.endCompound(); }
 
1994
    }
 
1995
 
 
1996
    for (var ext in extensions)
 
1997
      if (extensions.propertyIsEnumerable(ext) &&
 
1998
          !instance.propertyIsEnumerable(ext))
 
1999
        instance[ext] = extensions[ext];
 
2000
    for (var i = 0; i < initHooks.length; ++i) initHooks[i](instance);
 
2001
    return instance;
 
2002
  } // (end of function CodeMirror)
 
2003
 
 
2004
  // The default configuration options.
 
2005
  CodeMirror.defaults = {
 
2006
    value: "",
 
2007
    mode: null,
 
2008
    theme: "default",
 
2009
    indentUnit: 2,
 
2010
    indentWithTabs: false,
 
2011
    smartIndent: true,
 
2012
    tabSize: 4,
 
2013
    keyMap: "default",
 
2014
    extraKeys: null,
 
2015
    electricChars: true,
 
2016
    autoClearEmptyLines: false,
 
2017
    onKeyEvent: null,
 
2018
    onDragEvent: null,
 
2019
    lineWrapping: false,
 
2020
    lineNumbers: false,
 
2021
    gutter: false,
 
2022
    fixedGutter: false,
 
2023
    firstLineNumber: 1,
 
2024
    showCursorWhenSelecting: false,
 
2025
    readOnly: false,
 
2026
    dragDrop: true,
 
2027
    onChange: null,
 
2028
    onCursorActivity: null,
 
2029
    onViewportChange: null,
 
2030
    onGutterClick: null,
 
2031
    onUpdate: null,
 
2032
    onFocus: null, onBlur: null, onScroll: null,
 
2033
    matchBrackets: false,
 
2034
    cursorBlinkRate: 530,
 
2035
    workTime: 100,
 
2036
    workDelay: 200,
 
2037
    pollInterval: 100,
 
2038
    undoDepth: 40,
 
2039
    tabindex: null,
 
2040
    autofocus: null,
 
2041
    lineNumberFormatter: function(integer) { return integer; }
 
2042
  };
 
2043
 
 
2044
  var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
 
2045
  var mac = ios || /Mac/.test(navigator.platform);
 
2046
  var win = /Win/.test(navigator.platform);
 
2047
 
 
2048
  // Known modes, by name and by MIME
 
2049
  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
 
2050
  CodeMirror.defineMode = function(name, mode) {
 
2051
    if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
 
2052
    if (arguments.length > 2) {
 
2053
      mode.dependencies = [];
 
2054
      for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
 
2055
    }
 
2056
    modes[name] = mode;
 
2057
  };
 
2058
  CodeMirror.defineMIME = function(mime, spec) {
 
2059
    mimeModes[mime] = spec;
 
2060
  };
 
2061
  CodeMirror.resolveMode = function(spec) {
 
2062
    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
 
2063
      spec = mimeModes[spec];
 
2064
    else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec))
 
2065
      return CodeMirror.resolveMode("application/xml");
 
2066
    if (typeof spec == "string") return {name: spec};
 
2067
    else return spec || {name: "null"};
 
2068
  };
 
2069
  CodeMirror.getMode = function(options, spec) {
 
2070
    var spec = CodeMirror.resolveMode(spec);
 
2071
    var mfactory = modes[spec.name];
 
2072
    if (!mfactory) return CodeMirror.getMode(options, "text/plain");
 
2073
    var modeObj = mfactory(options, spec);
 
2074
    if (modeExtensions.hasOwnProperty(spec.name)) {
 
2075
      var exts = modeExtensions[spec.name];
 
2076
      for (var prop in exts) {
 
2077
        if (!exts.hasOwnProperty(prop)) continue;
 
2078
        if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
 
2079
        modeObj[prop] = exts[prop];
 
2080
      }
 
2081
    }
 
2082
    modeObj.name = spec.name;
 
2083
    return modeObj;
 
2084
  };
 
2085
  CodeMirror.listModes = function() {
 
2086
    var list = [];
 
2087
    for (var m in modes)
 
2088
      if (modes.propertyIsEnumerable(m)) list.push(m);
 
2089
    return list;
 
2090
  };
 
2091
  CodeMirror.listMIMEs = function() {
 
2092
    var list = [];
 
2093
    for (var m in mimeModes)
 
2094
      if (mimeModes.propertyIsEnumerable(m)) list.push({mime: m, mode: mimeModes[m]});
 
2095
    return list;
 
2096
  };
 
2097
 
 
2098
  var extensions = CodeMirror.extensions = {};
 
2099
  CodeMirror.defineExtension = function(name, func) {
 
2100
    extensions[name] = func;
 
2101
  };
 
2102
 
 
2103
  var initHooks = [];
 
2104
  CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
 
2105
 
 
2106
  var modeExtensions = CodeMirror.modeExtensions = {};
 
2107
  CodeMirror.extendMode = function(mode, properties) {
 
2108
    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
 
2109
    for (var prop in properties) if (properties.hasOwnProperty(prop))
 
2110
      exts[prop] = properties[prop];
 
2111
  };
 
2112
 
 
2113
  var commands = CodeMirror.commands = {
 
2114
    selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});},
 
2115
    killLine: function(cm) {
 
2116
      var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
 
2117
      if (!sel && cm.getLine(from.line).length == from.ch) cm.replaceRange("", from, {line: from.line + 1, ch: 0});
 
2118
      else cm.replaceRange("", from, sel ? to : {line: from.line});
 
2119
    },
 
2120
    deleteLine: function(cm) {var l = cm.getCursor().line; cm.replaceRange("", {line: l, ch: 0}, {line: l});},
 
2121
    undo: function(cm) {cm.undo();},
 
2122
    redo: function(cm) {cm.redo();},
 
2123
    goDocStart: function(cm) {cm.setCursor(0, 0, true);},
 
2124
    goDocEnd: function(cm) {cm.setSelection({line: cm.lineCount() - 1}, null, true);},
 
2125
    goLineStart: function(cm) {cm.setCursor(cm.getCursor().line, 0, true);},
 
2126
    goLineStartSmart: function(cm) {
 
2127
      var cur = cm.getCursor();
 
2128
      var text = cm.getLine(cur.line), firstNonWS = Math.max(0, text.search(/\S/));
 
2129
      cm.setCursor(cur.line, cur.ch <= firstNonWS && cur.ch ? 0 : firstNonWS, true);
 
2130
    },
 
2131
    goLineEnd: function(cm) {cm.setSelection({line: cm.getCursor().line}, null, true);},
 
2132
    goLineUp: function(cm) {cm.moveV(-1, "line");},
 
2133
    goLineDown: function(cm) {cm.moveV(1, "line");},
 
2134
    goPageUp: function(cm) {cm.moveV(-1, "page");},
 
2135
    goPageDown: function(cm) {cm.moveV(1, "page");},
 
2136
    goCharLeft: function(cm) {cm.moveH(-1, "char");},
 
2137
    goCharRight: function(cm) {cm.moveH(1, "char");},
 
2138
    goColumnLeft: function(cm) {cm.moveH(-1, "column");},
 
2139
    goColumnRight: function(cm) {cm.moveH(1, "column");},
 
2140
    goWordLeft: function(cm) {cm.moveH(-1, "word");},
 
2141
    goWordRight: function(cm) {cm.moveH(1, "word");},
 
2142
    delCharLeft: function(cm) {cm.deleteH(-1, "char");},
 
2143
    delCharRight: function(cm) {cm.deleteH(1, "char");},
 
2144
    delWordLeft: function(cm) {cm.deleteH(-1, "word");},
 
2145
    delWordRight: function(cm) {cm.deleteH(1, "word");},
 
2146
    indentAuto: function(cm) {cm.indentSelection("smart");},
 
2147
    indentMore: function(cm) {cm.indentSelection("add");},
 
2148
    indentLess: function(cm) {cm.indentSelection("subtract");},
 
2149
    insertTab: function(cm) {cm.replaceSelection("\t", "end");},
 
2150
    defaultTab: function(cm) {
 
2151
      if (cm.somethingSelected()) cm.indentSelection("add");
 
2152
      else cm.replaceSelection("\t", "end");
 
2153
    },
 
2154
    transposeChars: function(cm) {
 
2155
      var cur = cm.getCursor(), line = cm.getLine(cur.line);
 
2156
      if (cur.ch > 0 && cur.ch < line.length - 1)
 
2157
        cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
 
2158
                        {line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1});
 
2159
    },
 
2160
    newlineAndIndent: function(cm) {
 
2161
      cm.replaceSelection("\n", "end");
 
2162
      cm.indentLine(cm.getCursor().line);
 
2163
    },
 
2164
    toggleOverwrite: function(cm) {cm.toggleOverwrite();}
 
2165
  };
 
2166
 
 
2167
  var keyMap = CodeMirror.keyMap = {};
 
2168
  keyMap.basic = {
 
2169
    "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
 
2170
    "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
 
2171
    "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
 
2172
    "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
 
2173
  };
 
2174
  // Note that the save and find-related commands aren't defined by
 
2175
  // default. Unknown commands are simply ignored.
 
2176
  keyMap.pcDefault = {
 
2177
    "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
 
2178
    "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
 
2179
    "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
 
2180
    "Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find",
 
2181
    "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
 
2182
    "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
 
2183
    fallthrough: "basic"
 
2184
  };
 
2185
  keyMap.macDefault = {
 
2186
    "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
 
2187
    "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft",
 
2188
    "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft",
 
2189
    "Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find",
 
2190
    "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
 
2191
    "Cmd-[": "indentLess", "Cmd-]": "indentMore",
 
2192
    fallthrough: ["basic", "emacsy"]
 
2193
  };
 
2194
  keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
 
2195
  keyMap.emacsy = {
 
2196
    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
 
2197
    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
 
2198
    "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharRight", "Ctrl-H": "delCharLeft",
 
2199
    "Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
 
2200
  };
 
2201
 
 
2202
  function getKeyMap(val) {
 
2203
    if (typeof val == "string") return keyMap[val];
 
2204
    else return val;
 
2205
  }
 
2206
  function lookupKey(name, extraMap, map, handle, stop) {
 
2207
    function lookup(map) {
 
2208
      map = getKeyMap(map);
 
2209
      var found = map[name];
 
2210
      if (found === false) {
 
2211
        if (stop) stop();
 
2212
        return true;
 
2213
      }
 
2214
      if (found != null && handle(found)) return true;
 
2215
      if (map.nofallthrough) {
 
2216
        if (stop) stop();
 
2217
        return true;
 
2218
      }
 
2219
      var fallthrough = map.fallthrough;
 
2220
      if (fallthrough == null) return false;
 
2221
      if (Object.prototype.toString.call(fallthrough) != "[object Array]")
 
2222
        return lookup(fallthrough);
 
2223
      for (var i = 0, e = fallthrough.length; i < e; ++i) {
 
2224
        if (lookup(fallthrough[i])) return true;
 
2225
      }
 
2226
      return false;
 
2227
    }
 
2228
    if (extraMap && lookup(extraMap)) return true;
 
2229
    return lookup(map);
 
2230
  }
 
2231
  function isModifierKey(event) {
 
2232
    var name = keyNames[e_prop(event, "keyCode")];
 
2233
    return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
 
2234
  }
 
2235
  CodeMirror.isModifierKey = isModifierKey;
 
2236
 
 
2237
  CodeMirror.fromTextArea = function(textarea, options) {
 
2238
    if (!options) options = {};
 
2239
    options.value = textarea.value;
 
2240
    if (!options.tabindex && textarea.tabindex)
 
2241
      options.tabindex = textarea.tabindex;
 
2242
    // Set autofocus to true if this textarea is focused, or if it has
 
2243
    // autofocus and no other element is focused.
 
2244
    if (options.autofocus == null) {
 
2245
      var hasFocus = document.body;
 
2246
      // doc.activeElement occasionally throws on IE
 
2247
      try { hasFocus = document.activeElement; } catch(e) {}
 
2248
      options.autofocus = hasFocus == textarea ||
 
2249
        textarea.getAttribute("autofocus") != null && hasFocus == document.body;
 
2250
    }
 
2251
 
 
2252
    function save() {textarea.value = instance.getValue();}
 
2253
    if (textarea.form) {
 
2254
      // Deplorable hack to make the submit method do the right thing.
 
2255
      var rmSubmit = connect(textarea.form, "submit", save, true);
 
2256
      var form = textarea.form, realSubmit = form.submit;
 
2257
      textarea.form.submit = function wrappedSubmit() {
 
2258
        save();
 
2259
        form.submit = realSubmit;
 
2260
        form.submit();
 
2261
        form.submit = wrappedSubmit;
 
2262
      };
 
2263
    }
 
2264
 
 
2265
    textarea.style.display = "none";
 
2266
    var instance = CodeMirror(function(node) {
 
2267
      textarea.parentNode.insertBefore(node, textarea.nextSibling);
 
2268
    }, options);
 
2269
    instance.save = save;
 
2270
    instance.getTextArea = function() { return textarea; };
 
2271
    instance.toTextArea = function() {
 
2272
      save();
 
2273
      textarea.parentNode.removeChild(instance.getWrapperElement());
 
2274
      textarea.style.display = "";
 
2275
      if (textarea.form) {
 
2276
        rmSubmit();
 
2277
        if (typeof textarea.form.submit == "function")
 
2278
          textarea.form.submit = realSubmit;
 
2279
      }
 
2280
    };
 
2281
    return instance;
 
2282
  };
 
2283
 
 
2284
  var gecko = /gecko\/\d/i.test(navigator.userAgent);
 
2285
  var ie = /MSIE \d/.test(navigator.userAgent);
 
2286
  var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
 
2287
  var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
 
2288
  var quirksMode = ie && document.documentMode == 5;
 
2289
  var webkit = /WebKit\//.test(navigator.userAgent);
 
2290
  var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
 
2291
  var chrome = /Chrome\//.test(navigator.userAgent);
 
2292
  var opera = /Opera\//.test(navigator.userAgent);
 
2293
  var safari = /Apple Computer/.test(navigator.vendor);
 
2294
  var khtml = /KHTML\//.test(navigator.userAgent);
 
2295
  var mac_geLion = /Mac OS X 10\D([7-9]|\d\d)\D/.test(navigator.userAgent);
 
2296
 
 
2297
  var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
 
2298
  if (opera_version) opera_version = Number(opera_version[1]);
 
2299
  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
 
2300
  var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
 
2301
 
 
2302
  // Utility functions for working with state. Exported because modes
 
2303
  // sometimes need to do this.
 
2304
  function copyState(mode, state) {
 
2305
    if (state === true) return state;
 
2306
    if (mode.copyState) return mode.copyState(state);
 
2307
    var nstate = {};
 
2308
    for (var n in state) {
 
2309
      var val = state[n];
 
2310
      if (val instanceof Array) val = val.concat([]);
 
2311
      nstate[n] = val;
 
2312
    }
 
2313
    return nstate;
 
2314
  }
 
2315
  CodeMirror.copyState = copyState;
 
2316
  function startState(mode, a1, a2) {
 
2317
    return mode.startState ? mode.startState(a1, a2) : true;
 
2318
  }
 
2319
  CodeMirror.startState = startState;
 
2320
  CodeMirror.innerMode = function(mode, state) {
 
2321
    while (mode.innerMode) {
 
2322
      var info = mode.innerMode(state);
 
2323
      state = info.state;
 
2324
      mode = info.mode;
 
2325
    }
 
2326
    return info || {mode: mode, state: state};
 
2327
  };
 
2328
 
 
2329
  // The character stream used by a mode's parser.
 
2330
  function StringStream(string, tabSize) {
 
2331
    this.pos = this.start = 0;
 
2332
    this.string = string;
 
2333
    this.tabSize = tabSize || 8;
 
2334
  }
 
2335
  StringStream.prototype = {
 
2336
    eol: function() {return this.pos >= this.string.length;},
 
2337
    sol: function() {return this.pos == 0;},
 
2338
    peek: function() {return this.string.charAt(this.pos) || undefined;},
 
2339
    next: function() {
 
2340
      if (this.pos < this.string.length)
 
2341
        return this.string.charAt(this.pos++);
 
2342
    },
 
2343
    eat: function(match) {
 
2344
      var ch = this.string.charAt(this.pos);
 
2345
      if (typeof match == "string") var ok = ch == match;
 
2346
      else var ok = ch && (match.test ? match.test(ch) : match(ch));
 
2347
      if (ok) {++this.pos; return ch;}
 
2348
    },
 
2349
    eatWhile: function(match) {
 
2350
      var start = this.pos;
 
2351
      while (this.eat(match)){}
 
2352
      return this.pos > start;
 
2353
    },
 
2354
    eatSpace: function() {
 
2355
      var start = this.pos;
 
2356
      while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
 
2357
      return this.pos > start;
 
2358
    },
 
2359
    skipToEnd: function() {this.pos = this.string.length;},
 
2360
    skipTo: function(ch) {
 
2361
      var found = this.string.indexOf(ch, this.pos);
 
2362
      if (found > -1) {this.pos = found; return true;}
 
2363
    },
 
2364
    backUp: function(n) {this.pos -= n;},
 
2365
    column: function() {return countColumn(this.string, this.start, this.tabSize);},
 
2366
    indentation: function() {return countColumn(this.string, null, this.tabSize);},
 
2367
    match: function(pattern, consume, caseInsensitive) {
 
2368
      if (typeof pattern == "string") {
 
2369
        var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
 
2370
        if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
 
2371
          if (consume !== false) this.pos += pattern.length;
 
2372
          return true;
 
2373
        }
 
2374
      } else {
 
2375
        var match = this.string.slice(this.pos).match(pattern);
 
2376
        if (match && match.index > 0) return null;
 
2377
        if (match && consume !== false) this.pos += match[0].length;
 
2378
        return match;
 
2379
      }
 
2380
    },
 
2381
    current: function(){return this.string.slice(this.start, this.pos);}
 
2382
  };
 
2383
  CodeMirror.StringStream = StringStream;
 
2384
 
 
2385
  function MarkedSpan(from, to, marker) {
 
2386
    this.from = from; this.to = to; this.marker = marker;
 
2387
  }
 
2388
 
 
2389
  function getMarkedSpanFor(spans, marker) {
 
2390
    if (spans) for (var i = 0; i < spans.length; ++i) {
 
2391
      var span = spans[i];
 
2392
      if (span.marker == marker) return span;
 
2393
    }
 
2394
  }
 
2395
 
 
2396
  function removeMarkedSpan(spans, span) {
 
2397
    var r;
 
2398
    for (var i = 0; i < spans.length; ++i)
 
2399
      if (spans[i] != span) (r || (r = [])).push(spans[i]);
 
2400
    return r;
 
2401
  }
 
2402
 
 
2403
  function markedSpansBefore(old, startCh, endCh) {
 
2404
    if (old) for (var i = 0, nw; i < old.length; ++i) {
 
2405
      var span = old[i], marker = span.marker;
 
2406
      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
 
2407
      if (startsBefore || marker.type == "bookmark" && span.from == startCh && span.from != endCh) {
 
2408
        var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
 
2409
        (nw || (nw = [])).push({from: span.from,
 
2410
                                to: endsAfter ? null : span.to,
 
2411
                                marker: marker});
 
2412
      }
 
2413
    }
 
2414
    return nw;
 
2415
  }
 
2416
 
 
2417
  function markedSpansAfter(old, endCh) {
 
2418
    if (old) for (var i = 0, nw; i < old.length; ++i) {
 
2419
      var span = old[i], marker = span.marker;
 
2420
      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
 
2421
      if (endsAfter || marker.type == "bookmark" && span.from == endCh) {
 
2422
        var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
 
2423
        (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
 
2424
                                to: span.to == null ? null : span.to - endCh,
 
2425
                                marker: marker});
 
2426
      }
 
2427
    }
 
2428
    return nw;
 
2429
  }
 
2430
 
 
2431
  function updateMarkedSpans(oldFirst, oldLast, startCh, endCh, newText) {
 
2432
    if (!oldFirst && !oldLast) return newText;
 
2433
    // Get the spans that 'stick out' on both sides
 
2434
    var first = markedSpansBefore(oldFirst, startCh);
 
2435
    var last = markedSpansAfter(oldLast, endCh);
 
2436
 
 
2437
    // Next, merge those two ends
 
2438
    var sameLine = newText.length == 1, offset = lst(newText).length + (sameLine ? startCh : 0);
 
2439
    if (first) {
 
2440
      // Fix up .to properties of first
 
2441
      for (var i = 0; i < first.length; ++i) {
 
2442
        var span = first[i];
 
2443
        if (span.to == null) {
 
2444
          var found = getMarkedSpanFor(last, span.marker);
 
2445
          if (!found) span.to = startCh;
 
2446
          else if (sameLine) span.to = found.to == null ? null : found.to + offset;
 
2447
        }
 
2448
      }
 
2449
    }
 
2450
    if (last) {
 
2451
      // Fix up .from in last (or move them into first in case of sameLine)
 
2452
      for (var i = 0; i < last.length; ++i) {
 
2453
        var span = last[i];
 
2454
        if (span.to != null) span.to += offset;
 
2455
        if (span.from == null) {
 
2456
          var found = getMarkedSpanFor(first, span.marker);
 
2457
          if (!found) {
 
2458
            span.from = offset;
 
2459
            if (sameLine) (first || (first = [])).push(span);
 
2460
          }
 
2461
        } else {
 
2462
          span.from += offset;
 
2463
          if (sameLine) (first || (first = [])).push(span);
 
2464
        }
 
2465
      }
 
2466
    }
 
2467
 
 
2468
    var newMarkers = [newHL(newText[0], first)];
 
2469
    if (!sameLine) {
 
2470
      // Fill gap with whole-line-spans
 
2471
      var gap = newText.length - 2, gapMarkers;
 
2472
      if (gap > 0 && first)
 
2473
        for (var i = 0; i < first.length; ++i)
 
2474
          if (first[i].to == null)
 
2475
            (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
 
2476
      for (var i = 0; i < gap; ++i)
 
2477
        newMarkers.push(newHL(newText[i+1], gapMarkers));
 
2478
      newMarkers.push(newHL(lst(newText), last));
 
2479
    }
 
2480
    return newMarkers;
 
2481
  }
 
2482
 
 
2483
  // hl stands for history-line, a data structure that can be either a
 
2484
  // string (line without markers) or a {text, markedSpans} object.
 
2485
  function hlText(val) { return typeof val == "string" ? val : val.text; }
 
2486
  function hlSpans(val) {
 
2487
    if (typeof val == "string") return null;
 
2488
    var spans = val.markedSpans, out = null;
 
2489
    for (var i = 0; i < spans.length; ++i) {
 
2490
      if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
 
2491
      else if (out) out.push(spans[i]);
 
2492
    }
 
2493
    return !out ? spans : out.length ? out : null;
 
2494
  }
 
2495
  function newHL(text, spans) { return spans ? {text: text, markedSpans: spans} : text; }
 
2496
 
 
2497
  function detachMarkedSpans(line) {
 
2498
    var spans = line.markedSpans;
 
2499
    if (!spans) return;
 
2500
    for (var i = 0; i < spans.length; ++i) {
 
2501
      var lines = spans[i].marker.lines;
 
2502
      var ix = indexOf(lines, line);
 
2503
      lines.splice(ix, 1);
 
2504
    }
 
2505
    line.markedSpans = null;
 
2506
  }
 
2507
 
 
2508
  function attachMarkedSpans(line, spans) {
 
2509
    if (!spans) return;
 
2510
    for (var i = 0; i < spans.length; ++i)
 
2511
      var marker = spans[i].marker.lines.push(line);
 
2512
    line.markedSpans = spans;
 
2513
  }
 
2514
 
 
2515
  // When measuring the position of the end of a line, different
 
2516
  // browsers require different approaches. If an empty span is added,
 
2517
  // many browsers report bogus offsets. Of those, some (Webkit,
 
2518
  // recent IE) will accept a space without moving the whole span to
 
2519
  // the next line when wrapping it, others work with a zero-width
 
2520
  // space.
 
2521
  var eolSpanContent = " ";
 
2522
  if (gecko || (ie && !ie_lt8)) eolSpanContent = "\u200b";
 
2523
  else if (opera) eolSpanContent = "";
 
2524
 
 
2525
  // Line objects. These hold state related to a line, including
 
2526
  // highlighting info (the styles array).
 
2527
  function Line(text, markedSpans) {
 
2528
    this.text = text;
 
2529
    this.height = 1;
 
2530
    attachMarkedSpans(this, markedSpans);
 
2531
  }
 
2532
  Line.prototype = {
 
2533
    update: function(text, markedSpans) {
 
2534
      this.text = text;
 
2535
      this.stateAfter = this.styles = null;
 
2536
      detachMarkedSpans(this);
 
2537
      attachMarkedSpans(this, markedSpans);
 
2538
    },
 
2539
    // Run the given mode's parser over a line, update the styles
 
2540
    // array, which contains alternating fragments of text and CSS
 
2541
    // classes.
 
2542
    highlight: function(mode, state, tabSize) {
 
2543
      var stream = new StringStream(this.text, tabSize), st = this.styles || (this.styles = []);
 
2544
      var pos = st.length = 0;
 
2545
      if (this.text == "" && mode.blankLine) mode.blankLine(state);
 
2546
      while (!stream.eol()) {
 
2547
        var style = mode.token(stream, state), substr = stream.current();
 
2548
        stream.start = stream.pos;
 
2549
        if (pos && st[pos-1] == style) {
 
2550
          st[pos-2] += substr;
 
2551
        } else if (substr) {
 
2552
          st[pos++] = substr; st[pos++] = style;
 
2553
        }
 
2554
        // Give up when line is ridiculously long
 
2555
        if (stream.pos > 5000) {
 
2556
          st[pos++] = this.text.slice(stream.pos); st[pos++] = null;
 
2557
          break;
 
2558
        }
 
2559
      }
 
2560
    },
 
2561
    process: function(mode, state, tabSize) {
 
2562
      var stream = new StringStream(this.text, tabSize);
 
2563
      if (this.text == "" && mode.blankLine) mode.blankLine(state);
 
2564
      while (!stream.eol() && stream.pos <= 5000) {
 
2565
        mode.token(stream, state);
 
2566
        stream.start = stream.pos;
 
2567
      }
 
2568
    },
 
2569
    // Fetch the parser token for a given character. Useful for hacks
 
2570
    // that want to inspect the mode state (say, for completion).
 
2571
    getTokenAt: function(mode, state, tabSize, ch) {
 
2572
      var txt = this.text, stream = new StringStream(txt, tabSize);
 
2573
      while (stream.pos < ch && !stream.eol()) {
 
2574
        stream.start = stream.pos;
 
2575
        var style = mode.token(stream, state);
 
2576
      }
 
2577
      return {start: stream.start,
 
2578
              end: stream.pos,
 
2579
              string: stream.current(),
 
2580
              className: style || null,
 
2581
              state: state};
 
2582
    },
 
2583
    indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
 
2584
    // Produces an HTML fragment for the line, taking selection,
 
2585
    // marking, and highlighting into account.
 
2586
    getContent: function(tabSize, wrapAt, compensateForWrapping) {
 
2587
      var first = true, col = 0, specials = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g;
 
2588
      var pre = elt("pre");
 
2589
      function span_(html, text, style) {
 
2590
        if (!text) return;
 
2591
        // Work around a bug where, in some compat modes, IE ignores leading spaces
 
2592
        if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
 
2593
        first = false;
 
2594
        if (!specials.test(text)) {
 
2595
          col += text.length;
 
2596
          var content = document.createTextNode(text);
 
2597
        } else {
 
2598
          var content = document.createDocumentFragment(), pos = 0;
 
2599
          while (true) {
 
2600
            specials.lastIndex = pos;
 
2601
            var m = specials.exec(text);
 
2602
            var skipped = m ? m.index - pos : text.length - pos;
 
2603
            if (skipped) {
 
2604
              content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
 
2605
              col += skipped;
 
2606
            }
 
2607
            if (!m) break;
 
2608
            pos += skipped + 1;
 
2609
            if (m[0] == "\t") {
 
2610
              var tabWidth = tabSize - col % tabSize;
 
2611
              content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
 
2612
              col += tabWidth;
 
2613
            } else {
 
2614
              var token = elt("span", "\u2022", "cm-invalidchar");
 
2615
              token.title = "\\u" + m[0].charCodeAt(0).toString(16);
 
2616
              content.appendChild(token);
 
2617
              col += 1;
 
2618
            }
 
2619
          }
 
2620
        }
 
2621
        if (style) html.appendChild(elt("span", [content], style));
 
2622
        else html.appendChild(content);
 
2623
      }
 
2624
      var span = span_;
 
2625
      if (wrapAt != null) {
 
2626
        var outPos = 0, anchor = pre.anchor = elt("span");
 
2627
        span = function(html, text, style) {
 
2628
          var l = text.length;
 
2629
          if (wrapAt >= outPos && wrapAt < outPos + l) {
 
2630
            var cut = wrapAt - outPos;
 
2631
            if (cut) {
 
2632
              span_(html, text.slice(0, cut), style);
 
2633
              // See comment at the definition of spanAffectsWrapping
 
2634
              if (compensateForWrapping) {
 
2635
                var view = text.slice(cut - 1, cut + 1);
 
2636
                if (spanAffectsWrapping.test(view)) html.appendChild(elt("wbr"));
 
2637
                else if (!ie_lt8 && /\w\w/.test(view)) html.appendChild(document.createTextNode("\u200d"));
 
2638
              }
 
2639
            }
 
2640
            html.appendChild(anchor);
 
2641
            span_(anchor, opera ? text.slice(cut, cut + 1) : text.slice(cut), style);
 
2642
            if (opera) span_(html, text.slice(cut + 1), style);
 
2643
            wrapAt--;
 
2644
            outPos += l;
 
2645
          } else {
 
2646
            outPos += l;
 
2647
            span_(html, text, style);
 
2648
            if (outPos == wrapAt && outPos == len) {
 
2649
              setTextContent(anchor, eolSpanContent);
 
2650
              html.appendChild(anchor);
 
2651
            }
 
2652
            // Stop outputting HTML when gone sufficiently far beyond measure
 
2653
            else if (outPos > wrapAt + 10 && /\s/.test(text)) span = function(){};
 
2654
          }
 
2655
        };
 
2656
      }
 
2657
 
 
2658
      var st = this.styles, allText = this.text, marked = this.markedSpans;
 
2659
      var len = allText.length;
 
2660
      function styleToClass(style) {
 
2661
        if (!style) return null;
 
2662
        return "cm-" + style.replace(/ +/g, " cm-");
 
2663
      }
 
2664
      if (!allText && wrapAt == null) {
 
2665
        span(pre, " ");
 
2666
      } else if (!marked || !marked.length) {
 
2667
        for (var i = 0, ch = 0; ch < len; i+=2) {
 
2668
          var str = st[i], style = st[i+1], l = str.length;
 
2669
          if (ch + l > len) str = str.slice(0, len - ch);
 
2670
          ch += l;
 
2671
          span(pre, str, styleToClass(style));
 
2672
        }
 
2673
      } else {
 
2674
        marked.sort(function(a, b) { return a.from - b.from; });
 
2675
        var pos = 0, i = 0, text = "", style, sg = 0;
 
2676
        var nextChange = marked[0].from || 0, marks = [], markpos = 0;
 
2677
        var advanceMarks = function() {
 
2678
          var m;
 
2679
          while (markpos < marked.length &&
 
2680
                 ((m = marked[markpos]).from == pos || m.from == null)) {
 
2681
            if (m.marker.type == "range") marks.push(m);
 
2682
            ++markpos;
 
2683
          }
 
2684
          nextChange = markpos < marked.length ? marked[markpos].from : Infinity;
 
2685
          for (var i = 0; i < marks.length; ++i) {
 
2686
            var to = marks[i].to;
 
2687
            if (to == null) to = Infinity;
 
2688
            if (to == pos) marks.splice(i--, 1);
 
2689
            else nextChange = Math.min(to, nextChange);
 
2690
          }
 
2691
        };
 
2692
        var m = 0;
 
2693
        while (pos < len) {
 
2694
          if (nextChange == pos) advanceMarks();
 
2695
          var upto = Math.min(len, nextChange);
 
2696
          while (true) {
 
2697
            if (text) {
 
2698
              var end = pos + text.length;
 
2699
              var appliedStyle = style;
 
2700
              for (var j = 0; j < marks.length; ++j) {
 
2701
                var mark = marks[j];
 
2702
                appliedStyle = (appliedStyle ? appliedStyle + " " : "") + mark.marker.style;
 
2703
                if (mark.marker.endStyle && mark.to === Math.min(end, upto)) appliedStyle += " " + mark.marker.endStyle;
 
2704
                if (mark.marker.startStyle && mark.from === pos) appliedStyle += " " + mark.marker.startStyle;
 
2705
              }
 
2706
              span(pre, end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
 
2707
              if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
 
2708
              pos = end;
 
2709
            }
 
2710
            text = st[i++]; style = styleToClass(st[i++]);
 
2711
          }
 
2712
        }
 
2713
      }
 
2714
      return pre;
 
2715
    },
 
2716
    cleanUp: function() {
 
2717
      this.parent = null;
 
2718
      detachMarkedSpans(this);
 
2719
    }
 
2720
  };
 
2721
 
 
2722
  // Data structure that holds the sequence of lines.
 
2723
  function LeafChunk(lines) {
 
2724
    this.lines = lines;
 
2725
    this.parent = null;
 
2726
    for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
 
2727
      lines[i].parent = this;
 
2728
      height += lines[i].height;
 
2729
    }
 
2730
    this.height = height;
 
2731
  }
 
2732
  LeafChunk.prototype = {
 
2733
    chunkSize: function() { return this.lines.length; },
 
2734
    remove: function(at, n, callbacks) {
 
2735
      for (var i = at, e = at + n; i < e; ++i) {
 
2736
        var line = this.lines[i];
 
2737
        this.height -= line.height;
 
2738
        line.cleanUp();
 
2739
        if (line.handlers)
 
2740
          for (var j = 0; j < line.handlers.length; ++j) callbacks.push(line.handlers[j]);
 
2741
      }
 
2742
      this.lines.splice(at, n);
 
2743
    },
 
2744
    collapse: function(lines) {
 
2745
      lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
 
2746
    },
 
2747
    insertHeight: function(at, lines, height) {
 
2748
      this.height += height;
 
2749
      this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
 
2750
      for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
 
2751
    },
 
2752
    iterN: function(at, n, op) {
 
2753
      for (var e = at + n; at < e; ++at)
 
2754
        if (op(this.lines[at])) return true;
 
2755
    }
 
2756
  };
 
2757
  function BranchChunk(children) {
 
2758
    this.children = children;
 
2759
    var size = 0, height = 0;
 
2760
    for (var i = 0, e = children.length; i < e; ++i) {
 
2761
      var ch = children[i];
 
2762
      size += ch.chunkSize(); height += ch.height;
 
2763
      ch.parent = this;
 
2764
    }
 
2765
    this.size = size;
 
2766
    this.height = height;
 
2767
    this.parent = null;
 
2768
  }
 
2769
  BranchChunk.prototype = {
 
2770
    chunkSize: function() { return this.size; },
 
2771
    remove: function(at, n, callbacks) {
 
2772
      this.size -= n;
 
2773
      for (var i = 0; i < this.children.length; ++i) {
 
2774
        var child = this.children[i], sz = child.chunkSize();
 
2775
        if (at < sz) {
 
2776
          var rm = Math.min(n, sz - at), oldHeight = child.height;
 
2777
          child.remove(at, rm, callbacks);
 
2778
          this.height -= oldHeight - child.height;
 
2779
          if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
 
2780
          if ((n -= rm) == 0) break;
 
2781
          at = 0;
 
2782
        } else at -= sz;
 
2783
      }
 
2784
      if (this.size - n < 25) {
 
2785
        var lines = [];
 
2786
        this.collapse(lines);
 
2787
        this.children = [new LeafChunk(lines)];
 
2788
        this.children[0].parent = this;
 
2789
      }
 
2790
    },
 
2791
    collapse: function(lines) {
 
2792
      for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
 
2793
    },
 
2794
    insert: function(at, lines) {
 
2795
      var height = 0;
 
2796
      for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
 
2797
      this.insertHeight(at, lines, height);
 
2798
    },
 
2799
    insertHeight: function(at, lines, height) {
 
2800
      this.size += lines.length;
 
2801
      this.height += height;
 
2802
      for (var i = 0, e = this.children.length; i < e; ++i) {
 
2803
        var child = this.children[i], sz = child.chunkSize();
 
2804
        if (at <= sz) {
 
2805
          child.insertHeight(at, lines, height);
 
2806
          if (child.lines && child.lines.length > 50) {
 
2807
            while (child.lines.length > 50) {
 
2808
              var spilled = child.lines.splice(child.lines.length - 25, 25);
 
2809
              var newleaf = new LeafChunk(spilled);
 
2810
              child.height -= newleaf.height;
 
2811
              this.children.splice(i + 1, 0, newleaf);
 
2812
              newleaf.parent = this;
 
2813
            }
 
2814
            this.maybeSpill();
 
2815
          }
 
2816
          break;
 
2817
        }
 
2818
        at -= sz;
 
2819
      }
 
2820
    },
 
2821
    maybeSpill: function() {
 
2822
      if (this.children.length <= 10) return;
 
2823
      var me = this;
 
2824
      do {
 
2825
        var spilled = me.children.splice(me.children.length - 5, 5);
 
2826
        var sibling = new BranchChunk(spilled);
 
2827
        if (!me.parent) { // Become the parent node
 
2828
          var copy = new BranchChunk(me.children);
 
2829
          copy.parent = me;
 
2830
          me.children = [copy, sibling];
 
2831
          me = copy;
 
2832
        } else {
 
2833
          me.size -= sibling.size;
 
2834
          me.height -= sibling.height;
 
2835
          var myIndex = indexOf(me.parent.children, me);
 
2836
          me.parent.children.splice(myIndex + 1, 0, sibling);
 
2837
        }
 
2838
        sibling.parent = me.parent;
 
2839
      } while (me.children.length > 10);
 
2840
      me.parent.maybeSpill();
 
2841
    },
 
2842
    iter: function(from, to, op) { this.iterN(from, to - from, op); },
 
2843
    iterN: function(at, n, op) {
 
2844
      for (var i = 0, e = this.children.length; i < e; ++i) {
 
2845
        var child = this.children[i], sz = child.chunkSize();
 
2846
        if (at < sz) {
 
2847
          var used = Math.min(n, sz - at);
 
2848
          if (child.iterN(at, used, op)) return true;
 
2849
          if ((n -= used) == 0) break;
 
2850
          at = 0;
 
2851
        } else at -= sz;
 
2852
      }
 
2853
    }
 
2854
  };
 
2855
 
 
2856
  function getLineAt(chunk, n) {
 
2857
    while (!chunk.lines) {
 
2858
      for (var i = 0;; ++i) {
 
2859
        var child = chunk.children[i], sz = child.chunkSize();
 
2860
        if (n < sz) { chunk = child; break; }
 
2861
        n -= sz;
 
2862
      }
 
2863
    }
 
2864
    return chunk.lines[n];
 
2865
  }
 
2866
  function lineNo(line) {
 
2867
    if (line.parent == null) return null;
 
2868
    var cur = line.parent, no = indexOf(cur.lines, line);
 
2869
    for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
 
2870
      for (var i = 0; ; ++i) {
 
2871
        if (chunk.children[i] == cur) break;
 
2872
        no += chunk.children[i].chunkSize();
 
2873
      }
 
2874
    }
 
2875
    return no;
 
2876
  }
 
2877
  function lineAtHeight(chunk, h) {
 
2878
    var n = 0;
 
2879
    outer: do {
 
2880
      for (var i = 0, e = chunk.children.length; i < e; ++i) {
 
2881
        var child = chunk.children[i], ch = child.height;
 
2882
        if (h < ch) { chunk = child; continue outer; }
 
2883
        h -= ch;
 
2884
        n += child.chunkSize();
 
2885
      }
 
2886
      return n;
 
2887
    } while (!chunk.lines);
 
2888
    for (var i = 0, e = chunk.lines.length; i < e; ++i) {
 
2889
      var line = chunk.lines[i], lh = line.height;
 
2890
      if (h < lh) break;
 
2891
      h -= lh;
 
2892
    }
 
2893
    return n + i;
 
2894
  }
 
2895
  function heightAtLine(chunk, n) {
 
2896
    var h = 0;
 
2897
    outer: do {
 
2898
      for (var i = 0, e = chunk.children.length; i < e; ++i) {
 
2899
        var child = chunk.children[i], sz = child.chunkSize();
 
2900
        if (n < sz) { chunk = child; continue outer; }
 
2901
        n -= sz;
 
2902
        h += child.height;
 
2903
      }
 
2904
      return h;
 
2905
    } while (!chunk.lines);
 
2906
    for (var i = 0; i < n; ++i) h += chunk.lines[i].height;
 
2907
    return h;
 
2908
  }
 
2909
 
 
2910
  // The history object 'chunks' changes that are made close together
 
2911
  // and at almost the same time into bigger undoable units.
 
2912
  function History() {
 
2913
    this.time = 0;
 
2914
    this.done = []; this.undone = [];
 
2915
    this.compound = 0;
 
2916
    this.closed = false;
 
2917
  }
 
2918
  History.prototype = {
 
2919
    addChange: function(start, added, old) {
 
2920
      this.undone.length = 0;
 
2921
      var time = +new Date, cur = lst(this.done), last = cur && lst(cur);
 
2922
      var dtime = time - this.time;
 
2923
 
 
2924
      if (cur && !this.closed && this.compound) {
 
2925
        cur.push({start: start, added: added, old: old});
 
2926
      } else if (dtime > 400 || !last || this.closed ||
 
2927
                 last.start > start + old.length || last.start + last.added < start) {
 
2928
        this.done.push([{start: start, added: added, old: old}]);
 
2929
        this.closed = false;
 
2930
      } else {
 
2931
        var startBefore = Math.max(0, last.start - start),
 
2932
            endAfter = Math.max(0, (start + old.length) - (last.start + last.added));
 
2933
        for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]);
 
2934
        for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]);
 
2935
        if (startBefore) last.start = start;
 
2936
        last.added += added - (old.length - startBefore - endAfter);
 
2937
      }
 
2938
      this.time = time;
 
2939
    },
 
2940
    startCompound: function() {
 
2941
      if (!this.compound++) this.closed = true;
 
2942
    },
 
2943
    endCompound: function() {
 
2944
      if (!--this.compound) this.closed = true;
 
2945
    }
 
2946
  };
 
2947
 
 
2948
  function stopMethod() {e_stop(this);}
 
2949
  // Ensure an event has a stop method.
 
2950
  function addStop(event) {
 
2951
    if (!event.stop) event.stop = stopMethod;
 
2952
    return event;
 
2953
  }
 
2954
 
 
2955
  function e_preventDefault(e) {
 
2956
    if (e.preventDefault) e.preventDefault();
 
2957
    else e.returnValue = false;
 
2958
  }
 
2959
  function e_stopPropagation(e) {
 
2960
    if (e.stopPropagation) e.stopPropagation();
 
2961
    else e.cancelBubble = true;
 
2962
  }
 
2963
  function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
 
2964
  CodeMirror.e_stop = e_stop;
 
2965
  CodeMirror.e_preventDefault = e_preventDefault;
 
2966
  CodeMirror.e_stopPropagation = e_stopPropagation;
 
2967
 
 
2968
  function e_target(e) {return e.target || e.srcElement;}
 
2969
  function e_button(e) {
 
2970
    var b = e.which;
 
2971
    if (b == null) {
 
2972
      if (e.button & 1) b = 1;
 
2973
      else if (e.button & 2) b = 3;
 
2974
      else if (e.button & 4) b = 2;
 
2975
    }
 
2976
    if (mac && e.ctrlKey && b == 1) b = 3;
 
2977
    return b;
 
2978
  }
 
2979
 
 
2980
  // Allow 3rd-party code to override event properties by adding an override
 
2981
  // object to an event object.
 
2982
  function e_prop(e, prop) {
 
2983
    var overridden = e.override && e.override.hasOwnProperty(prop);
 
2984
    return overridden ? e.override[prop] : e[prop];
 
2985
  }
 
2986
 
 
2987
  // Event handler registration. If disconnect is true, it'll return a
 
2988
  // function that unregisters the handler.
 
2989
  function connect(node, type, handler, disconnect) {
 
2990
    if (typeof node.addEventListener == "function") {
 
2991
      node.addEventListener(type, handler, false);
 
2992
      if (disconnect) return function() {node.removeEventListener(type, handler, false);};
 
2993
    } else {
 
2994
      var wrapHandler = function(event) {handler(event || window.event);};
 
2995
      node.attachEvent("on" + type, wrapHandler);
 
2996
      if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);};
 
2997
    }
 
2998
  }
 
2999
  CodeMirror.connect = connect;
 
3000
 
 
3001
  function Delayed() {this.id = null;}
 
3002
  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
 
3003
 
 
3004
  var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
 
3005
 
 
3006
  // Detect drag-and-drop
 
3007
  var dragAndDrop = function() {
 
3008
    // There is *some* kind of drag-and-drop support in IE6-8, but I
 
3009
    // couldn't get it to work yet.
 
3010
    if (ie_lt9) return false;
 
3011
    var div = elt('div');
 
3012
    return "draggable" in div || "dragDrop" in div;
 
3013
  }();
 
3014
 
 
3015
  // Feature-detect whether newlines in textareas are converted to \r\n
 
3016
  var lineSep = function () {
 
3017
    var te = elt("textarea");
 
3018
    te.value = "foo\nbar";
 
3019
    if (te.value.indexOf("\r") > -1) return "\r\n";
 
3020
    return "\n";
 
3021
  }();
 
3022
 
 
3023
  // For a reason I have yet to figure out, some browsers disallow
 
3024
  // word wrapping between certain characters *only* if a new inline
 
3025
  // element is started between them. This makes it hard to reliably
 
3026
  // measure the position of things, since that requires inserting an
 
3027
  // extra span. This terribly fragile set of regexps matches the
 
3028
  // character combinations that suffer from this phenomenon on the
 
3029
  // various browsers.
 
3030
  var spanAffectsWrapping = /^$/; // Won't match any two-character string
 
3031
  if (gecko) spanAffectsWrapping = /$'/;
 
3032
  else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
 
3033
  else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/;
 
3034
 
 
3035
  // Counts the column offset in a string, taking tabs into account.
 
3036
  // Used mostly to find indentation.
 
3037
  function countColumn(string, end, tabSize) {
 
3038
    if (end == null) {
 
3039
      end = string.search(/[^\s\u00a0]/);
 
3040
      if (end == -1) end = string.length;
 
3041
    }
 
3042
    for (var i = 0, n = 0; i < end; ++i) {
 
3043
      if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
 
3044
      else ++n;
 
3045
    }
 
3046
    return n;
 
3047
  }
 
3048
 
 
3049
  function eltOffset(node, screen) {
 
3050
    // Take the parts of bounding client rect that we are interested in so we are able to edit if need be,
 
3051
    // since the returned value cannot be changed externally (they are kept in sync as the element moves within the page)
 
3052
    try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; }
 
3053
    catch(e) { box = {top: 0, left: 0}; }
 
3054
    if (!screen) {
 
3055
      // Get the toplevel scroll, working around browser differences.
 
3056
      if (window.pageYOffset == null) {
 
3057
        var t = document.documentElement || document.body.parentNode;
 
3058
        if (t.scrollTop == null) t = document.body;
 
3059
        box.top += t.scrollTop; box.left += t.scrollLeft;
 
3060
      } else {
 
3061
        box.top += window.pageYOffset; box.left += window.pageXOffset;
 
3062
      }
 
3063
    }
 
3064
    return box;
 
3065
  }
 
3066
 
 
3067
  function eltText(node) {
 
3068
    return node.textContent || node.innerText || node.nodeValue || "";
 
3069
  }
 
3070
 
 
3071
  var spaceStrs = [""];
 
3072
  function spaceStr(n) {
 
3073
    while (spaceStrs.length <= n)
 
3074
      spaceStrs.push(lst(spaceStrs) + " ");
 
3075
    return spaceStrs[n];
 
3076
  }
 
3077
 
 
3078
  function lst(arr) { return arr[arr.length-1]; }
 
3079
 
 
3080
  function selectInput(node) {
 
3081
    if (ios) { // Mobile Safari apparently has a bug where select() is broken.
 
3082
      node.selectionStart = 0;
 
3083
      node.selectionEnd = node.value.length;
 
3084
    } else node.select();
 
3085
  }
 
3086
 
 
3087
  // Operations on {line, ch} objects.
 
3088
  function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
 
3089
  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
 
3090
  function copyPos(x) {return {line: x.line, ch: x.ch};}
 
3091
 
 
3092
  function elt(tag, content, className, style) {
 
3093
    var e = document.createElement(tag);
 
3094
    if (className) e.className = className;
 
3095
    if (style) e.style.cssText = style;
 
3096
    if (typeof content == "string") setTextContent(e, content);
 
3097
    else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
 
3098
    return e;
 
3099
  }
 
3100
  function removeChildren(e) {
 
3101
    e.innerHTML = "";
 
3102
    return e;
 
3103
  }
 
3104
  function removeChildrenAndAdd(parent, e) {
 
3105
    removeChildren(parent).appendChild(e);
 
3106
  }
 
3107
  function setTextContent(e, str) {
 
3108
    if (ie_lt9) {
 
3109
      e.innerHTML = "";
 
3110
      e.appendChild(document.createTextNode(str));
 
3111
    } else e.textContent = str;
 
3112
  }
 
3113
 
 
3114
  // Used to position the cursor after an undo/redo by finding the
 
3115
  // last edited character.
 
3116
  function editEnd(from, to) {
 
3117
    if (!to) return 0;
 
3118
    if (!from) return to.length;
 
3119
    for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j)
 
3120
      if (from.charAt(i) != to.charAt(j)) break;
 
3121
    return j + 1;
 
3122
  }
 
3123
 
 
3124
  function indexOf(collection, elt) {
 
3125
    if (collection.indexOf) return collection.indexOf(elt);
 
3126
    for (var i = 0, e = collection.length; i < e; ++i)
 
3127
      if (collection[i] == elt) return i;
 
3128
    return -1;
 
3129
  }
 
3130
  var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/;
 
3131
  function isWordChar(ch) {
 
3132
    return /\w/.test(ch) || ch > "\x80" &&
 
3133
      (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
 
3134
  }
 
3135
 
 
3136
  // See if "".split is the broken IE version, if so, provide an
 
3137
  // alternative way to split lines.
 
3138
  var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
 
3139
    var pos = 0, result = [], l = string.length;
 
3140
    while (pos <= l) {
 
3141
      var nl = string.indexOf("\n", pos);
 
3142
      if (nl == -1) nl = string.length;
 
3143
      var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
 
3144
      var rt = line.indexOf("\r");
 
3145
      if (rt != -1) {
 
3146
        result.push(line.slice(0, rt));
 
3147
        pos += rt + 1;
 
3148
      } else {
 
3149
        result.push(line);
 
3150
        pos = nl + 1;
 
3151
      }
 
3152
    }
 
3153
    return result;
 
3154
  } : function(string){return string.split(/\r\n?|\n/);};
 
3155
  CodeMirror.splitLines = splitLines;
 
3156
 
 
3157
  var hasSelection = window.getSelection ? function(te) {
 
3158
    try { return te.selectionStart != te.selectionEnd; }
 
3159
    catch(e) { return false; }
 
3160
  } : function(te) {
 
3161
    try {var range = te.ownerDocument.selection.createRange();}
 
3162
    catch(e) {}
 
3163
    if (!range || range.parentElement() != te) return false;
 
3164
    return range.compareEndPoints("StartToEnd", range) != 0;
 
3165
  };
 
3166
 
 
3167
  CodeMirror.defineMode("null", function() {
 
3168
    return {token: function(stream) {stream.skipToEnd();}};
 
3169
  });
 
3170
  CodeMirror.defineMIME("text/plain", "null");
 
3171
 
 
3172
  var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
 
3173
                  19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
 
3174
                  36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
 
3175
                  46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
 
3176
                  186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
 
3177
                  221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
 
3178
                  63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
 
3179
  CodeMirror.keyNames = keyNames;
 
3180
  (function() {
 
3181
    // Number keys
 
3182
    for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
 
3183
    // Alphabetic keys
 
3184
    for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
 
3185
    // Function keys
 
3186
    for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
 
3187
  })();
 
3188
 
 
3189
  CodeMirror.version = "2.38";
 
3190
 
 
3191
  return CodeMirror;
 
3192
})();