15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// CodeMirror is the only global var we claim 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)window.CodeMirror = (function() { 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "use strict"; 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // BROWSER SNIFFING 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Crude, but necessary to handle a number of hard-to-feature-detect 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // bugs and behavior differences. 9926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var gecko = /gecko\/\d/i.test(navigator.userAgent); 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var ie = /MSIE \d/.test(navigator.userAgent); 11926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8); 12926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9); 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var webkit = /WebKit\//.test(navigator.userAgent); 14926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent); 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var chrome = /Chrome\//.test(navigator.userAgent); 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var opera = /Opera\//.test(navigator.userAgent); 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var safari = /Apple Computer/.test(navigator.vendor); 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var khtml = /KHTML\//.test(navigator.userAgent); 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent); 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent); 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var phantom = /PhantomJS/.test(navigator.userAgent); 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent); 24926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // This is woefully incomplete. Suggestions for alternative methods welcome. 25926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent); 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var mac = ios || /Mac/.test(navigator.platform); 27926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var windows = /windows/i.test(navigator.platform); 28926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 29926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/); 30926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (opera_version) opera_version = Number(opera_version[1]); 31f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (opera_version && opera_version >= 15) { opera = false; webkit = true; } 32926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Some browsers use the wrong event properties to signal cmd/ctrl on OS X 33926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11)); 34926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var captureMiddleClick = gecko || (ie && !ie_lt9); 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Optimize some code when these features are not used 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var sawReadOnlySpans = false, sawCollapsedSpans = false; 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // CONSTRUCTOR 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function CodeMirror(place, options) { 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!(this instanceof CodeMirror)) return new CodeMirror(place, options); 43926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.options = options = options || {}; 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Determine effective options based on given values and defaults. 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt)) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) options[opt] = defaults[opt]; 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setGuttersForLineNumbers(options); 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 50926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var docStart = typeof options.value == "string" ? 0 : options.value.first; 51926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var display = this.display = makeDisplay(place, docStart); 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.wrapper.CodeMirror = this; 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) updateGutters(this); 54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (options.autofocus && !mobile) focusInput(this); 55926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 56926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.state = {keyMaps: [], 57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) overlays: [], 58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) modeGen: 0, 59926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) overwrite: false, focused: false, 60926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) suppressEdits: false, pasteIncoming: false, 61926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) draggingText: false, 62926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) highlight: new Delayed()}; 63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) themeChanged(this); 65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (options.lineWrapping) 66926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.display.wrapper.className += " CodeMirror-wrap"; 67926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 68926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = options.value; 69926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (typeof doc == "string") doc = new Doc(options.value, options.mode); 70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) operation(this, attachDoc)(this, doc); 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Override magic textarea content restore that IE sometimes does 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // on our hidden textarea on reload 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ie) setTimeout(bind(resetInput, this, true), 20); 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) registerEventHandlers(this); 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // IE throws unspecified error in certain cases, when 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // trying to access activeElement before onload 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { } 80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20); 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else onBlur(this); 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) operation(this, function() { 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var opt in optionHandlers) 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (optionHandlers.propertyIsEnumerable(opt)) 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) optionHandlers[opt](this, options[opt], Init); 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < initHooks.length; ++i) initHooks[i](this); 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) })(); 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // DISPLAY CONSTRUCTOR 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function makeDisplay(place, docStart) { 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var d = {}; 95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 9653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;"); 97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (webkit) input.style.width = "1000px"; 98926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else input.setAttribute("wrap", "off"); 99926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // if border: 0; -- iOS fails to open keyboard (issue #1287) 100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (ios) input.style.border = "1px solid black"; 10193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false"); 102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Wraps and hides input textarea 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The actual fake scrollbars. 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar"); 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar"); 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); 10993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // DIVs containing the selection and the actual code 11193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) d.lineDiv = elt("div", null, "CodeMirror-code"); 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Blinky cursor, and element used to ensure cursor fits at the end of a line 114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.cursor = elt("div", "\u00a0", "CodeMirror-cursor"); 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Secondary cursor, shown when on a 'jump' in bi-directional text 116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.otherCursor = elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"); 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Used to measure text size 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.measure = elt("div", null, "CodeMirror-measure"); 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Wraps everything that needs to exist inside the vertically-padded coordinate system 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor], 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) null, "position: relative; outline: none"); 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Moved around its parent to cover visible view 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative"); 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Set to the height of the text, causes scrolling 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers 127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;"); 128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Will contain the gutters, if any 129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.gutters = elt("div", null, "CodeMirror-gutters"); 130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.lineGutter = null; 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Provides scrolling 13293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scroller.setAttribute("tabIndex", "-1"); 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The element in which the editor lives. 135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV, 13693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Work around IE7 z-index bug 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper); 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Needed to hide big blue blinking cursor on Mobile Safari 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ios) input.style.width = "0px"; 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!webkit) d.scroller.draggable = true; 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Needed to handle Tab key in KHTML 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; } 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px"; 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Current visible range (may be bigger than the view window). 150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.viewOffset = d.lastSizeC = 0; 151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.showingFrom = d.showingTo = docStart; 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Used to only resize the line number gutter when necessary (when 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the amount of lines crosses a boundary that makes its width change) 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // See readInput and resetInput 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.prevInput = ""; 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Set to true when a non-horizontal-scrolling widget is added. As 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // an optimization, widget aligning is skipped when d is false. 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.alignWidgets = false; 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Flag that indicates whether we currently expect input to appear 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // (after some event like 'keypress' or 'input') and are polling 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // intensively. 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.pollingFast = false; 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Self-resetting timeout for the poller 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.poll = new Delayed(); 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.cachedCharWidth = d.cachedTextHeight = null; 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.measureLineCache = []; 170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.measureLineCachePos = 0; 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Tracks when resetInput has punted to just putting a short 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // string instead of the (large) selection. 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.inaccurateSelection = false; 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Tracks the maximum line length so that the horizontal scrollbar 177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // can be kept static when scrolling. 178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.maxLine = null; 179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.maxLineLength = 0; 180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.maxLineChanged = false; 181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Used for measuring wheel scrolling granularity 183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return d; 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // STATE UPDATES 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Used to get the editor into a consistent state again when options change. 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function loadMode(cm) { 193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption); 194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.doc.iter(function(line) { 195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (line.stateAfter) line.stateAfter = null; 196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (line.styles) line.styles = null; 197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.doc.frontier = cm.doc.first; 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startWorker(cm, 100); 200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.state.modeGen++; 201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.curOp) regChange(cm); 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function wrappingChanged(cm) { 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.options.lineWrapping) { 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.wrapper.className += " CodeMirror-wrap"; 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.sizer.style.minWidth = ""; 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", ""); 210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) computeMaxLength(cm); 211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) estimateLineHeights(cm); 213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) regChange(cm); 214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) clearCaches(cm); 21593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) setTimeout(function(){updateScrollbars(cm);}, 100); 216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function estimateHeight(cm) { 219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; 220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); 221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return function(line) { 222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (lineIsHidden(cm.doc, line)) 223926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return 0; 224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (wrapping) 225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return (Math.ceil(line.text.length / perLine) || 1) * th; 226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else 227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return th; 228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function estimateLineHeights(cm) { 232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = cm.doc, est = estimateHeight(cm); 233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.iter(function(line) { 234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var estHeight = est(line); 235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (estHeight != line.height) updateLineHeight(line, estHeight); 236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function keyMapChanged(cm) { 2405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var map = keyMap[cm.options.keyMap], style = map.style; 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") + 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (style ? " cm-keymap-" + style : ""); 2435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) cm.state.disableInput = map.disableInput; 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function themeChanged(cm) { 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); 249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) clearCaches(cm); 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function guttersChanged(cm) { 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) updateGutters(cm); 254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) regChange(cm); 25593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) setTimeout(function(){alignHorizontally(cm);}, 20); 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function updateGutters(cm) { 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var gutters = cm.display.gutters, specs = cm.options.gutters; 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) removeChildren(gutters); 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < specs.length; ++i) { 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var gutterClass = specs[i]; 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)); 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (gutterClass == "CodeMirror-linenumbers") { 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.lineGutter = gElt; 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gElt.style.width = (cm.display.lineNumWidth || 1) + "px"; 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gutters.style.display = i ? "" : "none"; 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function lineLength(doc, line) { 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (line.height == 0) return 0; 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var len = line.text.length, merged, cur = line; 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (merged = collapsedSpanAtStart(cur)) { 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var found = merged.find(); 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cur = getLine(doc, found.from.line); 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) len += found.from.ch - found.to.ch; 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cur = line; 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (merged = collapsedSpanAtEnd(cur)) { 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var found = merged.find(); 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) len -= cur.text.length - found.from.ch; 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cur = getLine(doc, found.to.line); 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) len += cur.text.length - found.to.ch; 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return len; 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function computeMaxLength(cm) { 291926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var d = cm.display, doc = cm.doc; 292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.maxLine = getLine(doc, doc.first); 293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.maxLineLength = lineLength(doc, d.maxLine); 294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.maxLineChanged = true; 295926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.iter(function(line) { 296926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var len = lineLength(doc, line); 297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (len > d.maxLineLength) { 298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.maxLineLength = len; 299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.maxLine = line; 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Make sure the gutters options contains the element 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // "CodeMirror-linenumbers" when the lineNumbers option is true. 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function setGuttersForLineNumbers(options) { 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var found = false; 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < options.gutters.length; ++i) { 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (options.gutters[i] == "CodeMirror-linenumbers") { 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (options.lineNumbers) found = true; 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else options.gutters.splice(i--, 1); 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!found && options.lineNumbers) 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) options.gutters.push("CodeMirror-linenumbers"); 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // SCROLLBARS 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Re-synchronize the fake scrollbars with the actual size of the 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // content. Optionally force a scrollTop. 32293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) function updateScrollbars(cm) { 32393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var d = cm.display, docHeight = cm.doc.height; 324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var totalHeight = docHeight + paddingVert(d); 325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px"; 32693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px"; 327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight); 3285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1); 3295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var needsV = scrollHeight > (d.scroller.clientHeight + 1); 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (needsV) { 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scrollbarV.style.display = "block"; 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0"; 333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) d.scrollbarV.firstChild.style.height = 334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px"; 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else d.scrollbarV.style.display = ""; 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (needsH) { 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scrollbarH.style.display = "block"; 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0"; 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scrollbarH.firstChild.style.width = 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px"; 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else d.scrollbarH.style.display = ""; 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (needsH && needsV) { 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scrollbarFiller.style.display = "block"; 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px"; 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else d.scrollbarFiller.style.display = ""; 34693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { 34793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) d.gutterFiller.style.display = "block"; 34893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px"; 34993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) d.gutterFiller.style.width = d.gutters.offsetWidth + "px"; 35093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } else d.gutterFiller.style.display = ""; 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (mac_geLion && scrollbarWidth(d.measure) === 0) 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px"; 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function visibleLines(display, doc, viewPort) { 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var top = display.scroller.scrollTop, height = display.wrapper.clientHeight; 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (typeof viewPort == "number") top = viewPort; 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;} 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) top = Math.floor(top - paddingTop(display)); 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var bottom = Math.ceil(top + height); 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)}; 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // LINE NUMBERS 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function alignHorizontally(cm) { 368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var display = cm.display; 369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return; 370926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; 371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var gutterW = display.gutters.offsetWidth, l = comp + "px"; 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) { 3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l; 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.options.fixedGutter) 376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.gutters.style.left = (comp + gutterW) + "px"; 3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function maybeUpdateLineNumberWidth(cm) { 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!cm.options.lineNumbers) return false; 381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (last.length != display.lineNumChars) { 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var test = display.measure.appendChild(elt("div", [elt("div", last)], 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "CodeMirror-linenumber CodeMirror-gutter-elt")); 3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.lineGutter.style.width = ""; 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding); 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.lineNumWidth = display.lineNumInnerWidth + padding; 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.lineGutter.style.width = display.lineNumWidth + "px"; 3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function lineNumberFor(options, i) { 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return String(options.lineNumberFormatter(i + options.firstLineNumber)); 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function compensateForHScroll(display) { 400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return getRect(display.scroller).left - getRect(display.sizer).left; 4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // DISPLAY DRAWING 4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 405f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) function updateDisplay(cm, changes, viewPort, forced) { 40653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated; 40753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var visible = visibleLines(cm.display, cm.doc, viewPort); 40853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) for (;;) { 409f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (!updateDisplayInner(cm, changes, visible, forced)) break; 410f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) forced = false; 41193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) updated = true; 41253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) updateSelection(cm); 41393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) updateScrollbars(cm); 41453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 41553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // Clip forced viewport to actual scrollable area 41653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (viewPort) 41753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, 41853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) typeof viewPort == "number" ? viewPort : viewPort.top); 41953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) visible = visibleLines(cm.display, cm.doc, viewPort); 42053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo) 42153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) break; 42253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) changes = []; 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 42593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (updated) { 42693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) signalLater(cm, "update", cm); 42793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo) 42893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo); 42993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return updated; 4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Uses a set of changes plus the current scroll position to 4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // determine which DOM updates have to be made, and makes the 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // updates. 436f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) function updateDisplayInner(cm, changes, visible, forced) { 437926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var display = cm.display, doc = cm.doc; 4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!display.wrapper.clientWidth) { 439926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.showingFrom = display.showingTo = doc.first; 440926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.viewOffset = 0; 4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Bail out if the visible area is already rendered and nothing changed. 445f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (!forced && changes.length == 0 && 4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) visible.from > display.showingFrom && visible.to < display.showingTo) 4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (maybeUpdateLineNumberWidth(cm)) 450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) changes = [{from: doc.first, to: doc.first + doc.size}]; 451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px"; 452926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0"; 4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Used to determine which lines need their line numbers updated 455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var positionsChangedFrom = Infinity; 456926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.options.lineNumbers) 4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < changes.length; ++i) 4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; } 4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var end = doc.first + doc.size; 461926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var from = Math.max(visible.from - cm.options.viewportMargin, doc.first); 462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var to = Math.min(end, visible.to + cm.options.viewportMargin); 463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom); 464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo); 465926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (sawCollapsedSpans) { 466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) from = lineNo(visualLine(doc, getLine(doc, from))); 467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to; 468926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Create a range of theoretically intact lines, and punch holes 4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // in that using the change info. 472926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var intact = [{from: Math.max(display.showingFrom, doc.first), 473926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) to: Math.min(display.showingTo, end)}]; 474926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (intact[0].from >= intact[0].to) intact = []; 475926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else intact = computeIntact(intact, changes); 476926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // When merged lines are present, we might have to reduce the 477926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // intact ranges because changes in continued fragments of the 478926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // intact lines do require the lines to be redrawn. 479926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (sawCollapsedSpans) 480926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < intact.length; ++i) { 481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var range = intact[i], merged; 482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) { 483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var newTo = merged.find().from.line; 484926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (newTo > range.from) range.to = newTo; 485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else { intact.splice(i--, 1); break; } 486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Clip off the parts that won't be visible 4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var intactLines = 0; 4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < intact.length; ++i) { 4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var range = intact[i]; 493926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (range.from < from) range.from = from; 4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (range.to > to) range.to = to; 4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (range.from >= range.to) intact.splice(i--, 1); 4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else intactLines += range.to - range.from; 4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 498f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) { 499926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateViewOffset(cm); 5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 501926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 502926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) intact.sort(function(a, b) {return a.from - b.from;}); 5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 50453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // Avoid crashing on IE's "unspecified error" when in iframes 50553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) try { 50653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var focused = document.activeElement; 50753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } catch(e) {} 5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none"; 5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) patchDisplay(cm, from, to, intact, positionsChangedFrom); 5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.lineDiv.style.display = ""; 51153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus(); 5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var different = from != display.showingFrom || to != display.showingTo || 5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.lastSizeC != display.wrapper.clientHeight; 5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This is just a bogus formula that detects when the editor is 5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // resized or the font size changes. 5175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (different) { 5185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) display.lastSizeC = display.wrapper.clientHeight; 5195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) startWorker(cm, 400); 5205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.showingFrom = from; display.showingTo = to; 5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 523f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) updateHeightsInViewport(cm); 524f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) updateViewOffset(cm); 525f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) 526f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) return true; 527f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) } 528f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) 529f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) function updateHeightsInViewport(cm) { 530f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) var display = cm.display; 531926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var prevBottom = display.lineDiv.offsetTop; 532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) { 533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (ie_lt8) { 534926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var bot = node.offsetTop + node.offsetHeight; 535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) height = bot - prevBottom; 536926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) prevBottom = bot; 537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var box = getRect(node); 539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) height = box.bottom - box.top; 5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var diff = node.lineObj.height - height; 542926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (height < 2) height = textHeight(display); 543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (diff > .001 || diff < -.001) { 544926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateLineHeight(node.lineObj, height); 545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var widgets = node.lineObj.widgets; 546926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (widgets) for (var i = 0; i < widgets.length; ++i) 547926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) widgets[i].height = widgets[i].node.offsetHeight; 548926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 549926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 552926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function updateViewOffset(cm) { 553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom)); 554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Position the mover div to align with the current virtual scroll position 555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.mover.style.top = off + "px"; 556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 557926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function computeIntact(intact, changes) { 5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, l = changes.length || 0; i < l; ++i) { 5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var change = changes[i], intact2 = [], diff = change.diff || 0; 5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var j = 0, l2 = intact.length; j < l2; ++j) { 5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var range = intact[j]; 563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (change.to <= range.from && change.diff) { 564926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) intact2.push({from: range.from + diff, to: range.to + diff}); 565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (change.to <= range.from || change.from >= range.to) { 5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) intact2.push(range); 567926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (change.from > range.from) 569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) intact2.push({from: range.from, to: change.from}); 5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (change.to < range.to) 571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) intact2.push({from: change.to + diff, to: range.to + diff}); 5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) intact = intact2; 5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return intact; 5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function getDimensions(cm) { 5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var d = cm.display, left = {}, width = {}; 5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { 5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left[cm.options.gutters[i]] = n.offsetLeft; 5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width[cm.options.gutters[i]] = n.offsetWidth; 5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return {fixedPos: compensateForHScroll(d), 5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gutterTotalWidth: d.gutters.offsetWidth, 5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gutterLeft: left, 5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gutterWidth: width, 5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) wrapperWidth: d.wrapper.clientWidth}; 5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function patchDisplay(cm, from, to, intact, updateNumbersFrom) { 5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var dims = getDimensions(cm); 5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var display = cm.display, lineNumbers = cm.options.lineNumbers; 595926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!intact.length && (!webkit || !cm.display.currentWheelTarget)) 596926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removeChildren(display.lineDiv); 597926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var container = display.lineDiv, cur = container.firstChild; 598926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 599926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function rm(node) { 600926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var next = node.nextSibling; 601926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (webkit && mac && cm.display.currentWheelTarget == node) { 602926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) node.style.display = "none"; 603926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) node.lineObj = null; 604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 605926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) node.parentNode.removeChild(node); 6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 607926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return next; 608926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 609926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var nextIntact = intact.shift(), lineN = from; 611926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.doc.iter(from, to, function(line) { 612926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift(); 613926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (lineIsHidden(cm.doc, line)) { 614926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (line.height != 0) updateLineHeight(line, 0); 6155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) { 6165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var w = line.widgets[i]; 6175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (w.showIfHidden) { 618926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var prev = cur.previousSibling; 619926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (/pre/i.test(prev.nodeName)) { 620926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var wrap = elt("div", null, null, "position: relative"); 621926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) prev.parentNode.replaceChild(wrap, prev); 622926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) wrap.appendChild(prev); 623926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) prev = wrap; 624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 6255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget")); 6265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!w.handleMouseEvents) wnode.ignoreEvents = true; 6275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) positionLineWidget(w, wnode, prev, dims); 628926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 6295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 630926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) { 631926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // This line is intact. Skip to the actual node. Update its 632926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // line number if needed. 633926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) while (cur.lineObj != line) cur = rm(cur); 634926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber) 635926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN)); 636926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cur = cur.nextSibling; 637926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 638926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // For lines with widgets, make an attempt to find and reuse 639926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // the existing element, so that widgets aren't needlessly 640926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // removed and re-inserted into the dom 641926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling) 642926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; } 643926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // This line needs to be generated. 644926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var lineNode = buildLineElement(cm, line, lineN, dims, reuse); 645926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (lineNode != reuse) { 646926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) container.insertBefore(lineNode, cur); 647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 648926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) while (cur != reuse) cur = rm(cur); 649926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cur = cur.nextSibling; 650926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 652926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) lineNode.lineObj = line; 653926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 654926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ++lineN; 6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 656926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) while (cur) cur = rm(cur); 6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 659926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function buildLineElement(cm, line, lineNo, dims, reuse) { 660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var lineElement = lineContent(cm, line); 661926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var markers = line.gutterMarkers, display = cm.display, wrap; 6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets) 664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return lineElement; 6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 666926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Lines with gutter elements, widgets or a background class need 667926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // to be wrapped again, and have the extra elements added to the 668926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // wrapper div 6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (reuse) { 671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) reuse.alignable = null; 6725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var isOk = true, widgetsSeen = 0, insertBefore = null; 673926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var n = reuse.firstChild, next; n; n = next) { 674926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) next = n.nextSibling; 675926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!/\bCodeMirror-linewidget\b/.test(n.className)) { 676926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) reuse.removeChild(n); 677926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 678e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch for (var i = 0; i < line.widgets.length; ++i) { 6795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var widget = line.widgets[i]; 680926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (widget.node == n.firstChild) { 681e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (!widget.above && !insertBefore) insertBefore = n; 682926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) positionLineWidget(widget, n, reuse, dims); 683926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ++widgetsSeen; 684926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) break; 685926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 686926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 687926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (i == line.widgets.length) { isOk = false; break; } 688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 689926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 6905267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) reuse.insertBefore(lineElement, insertBefore); 691926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (isOk && widgetsSeen == line.widgets.length) { 692926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) wrap = reuse; 693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) reuse.className = line.wrapClass || ""; 694926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 695926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 696926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!wrap) { 697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) wrap = elt("div", null, line.wrapClass, "position: relative"); 698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) wrap.appendChild(lineElement); 699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 700926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Kludge to make sure the styled element lies behind the selection (by z-index) 701926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (line.bgClass) 702926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild); 7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.options.lineNumbers || markers) { 704926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " + 705926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"), 706926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) wrap.firstChild); 707926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap); 708926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) 709926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) wrap.lineNumber = gutterWrap.appendChild( 710926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) elt("div", lineNumberFor(cm.options, lineNo), 711926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) "CodeMirror-linenumber CodeMirror-gutter-elt", 712926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: " 713926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) + display.lineNumInnerWidth + "px")); 7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (markers) 7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var k = 0; k < cm.options.gutters.length; ++k) { 7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]; 717926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (found) 7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " + 7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px")); 7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ie_lt8) wrap.style.zIndex = 2; 723926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) { 724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget"); 7255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!widget.handleMouseEvents) node.ignoreEvents = true; 726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) positionLineWidget(widget, node, wrap, dims); 727926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (widget.above) 728926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement); 729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else 730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) wrap.appendChild(node); 731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) signalLater(widget, "redraw"); 732926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return wrap; 7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 736926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function positionLineWidget(widget, node, wrap, dims) { 737926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (widget.noHScroll) { 738926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (wrap.alignable || (wrap.alignable = [])).push(node); 739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var width = dims.wrapperWidth; 740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) node.style.left = dims.fixedPos + "px"; 741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!widget.coverGutter) { 742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) width -= dims.gutterTotalWidth; 743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) node.style.paddingLeft = dims.gutterTotalWidth + "px"; 744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 745926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) node.style.width = width + "px"; 746926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (widget.coverGutter) { 748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) node.style.zIndex = 5; 749926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) node.style.position = "relative"; 750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px"; 751926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 754926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // SELECTION / CURSOR 755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 7565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function updateSelection(cm) { 7575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var display = cm.display; 758926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to); 759926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (collapsed || cm.options.showCursorWhenSelecting) 760926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateSelectionCursor(cm); 761926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else 762926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.cursor.style.display = display.otherCursor.style.display = "none"; 763926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!collapsed) 764926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateSelectionRange(cm); 765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else 766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.selectionDiv.style.display = "none"; 767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 7685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Move the hidden textarea near the cursor to prevent scrolling artifacts 76953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (cm.options.moveInputWithCursor) { 77053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var headPos = cursorCoords(cm, cm.doc.sel.head, "div"); 77153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv); 77253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10, 77353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) headPos.top + lineOff.top - wrapOff.top)) + "px"; 77453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10, 77553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) headPos.left + lineOff.left - wrapOff.left)) + "px"; 77653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // No selection, plain cursor 7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function updateSelectionCursor(cm) { 781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div"); 7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.cursor.style.left = pos.left + "px"; 7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.cursor.style.top = pos.top + "px"; 7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; 7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.cursor.style.display = ""; 7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (pos.other) { 7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.otherCursor.style.display = ""; 7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.otherCursor.style.left = pos.other.left + "px"; 7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.otherCursor.style.top = pos.other.top + "px"; 7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; 7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { display.otherCursor.style.display = "none"; } 7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Highlight selection 7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function updateSelectionRange(cm) { 797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var display = cm.display, doc = cm.doc, sel = cm.doc.sel; 7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var fragment = document.createDocumentFragment(); 7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display); 8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function add(left, top, width, bottom) { 8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (top < 0) top = 0; 8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + 8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) + 8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "px; height: " + (bottom - top) + "px")); 8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 808591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch function drawForLine(line, fromArg, toArg) { 8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var lineObj = getLine(doc, line); 810591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var lineLen = lineObj.text.length; 811591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var start, end; 8125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) function coords(ch, bias) { 8135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return charCoords(cm, Pos(line, ch), "div", lineObj, bias); 8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) { 8175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var leftPos = coords(from, "left"), rightPos, left, right; 81853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (from == to) { 81953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) rightPos = leftPos; 82053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) left = right = leftPos.left; 82153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else { 8225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) rightPos = coords(to - 1, "right"); 82353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; } 82453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) left = leftPos.left; 82553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) right = rightPos.right; 82653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 827591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (fromArg == null && from == 0) left = pl; 8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part 8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) add(left, leftPos.top, null, leftPos.bottom); 8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left = pl; 8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top); 8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (toArg == null && to == lineLen) right = clientWidth; 834591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) 835591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch start = leftPos; 836591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) 837591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch end = rightPos; 8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (left < pl + 1) left = pl; 8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) add(left, rightPos.top, right - left, rightPos.bottom); 8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 841591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return {start: start, end: end}; 8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sel.from.line == sel.to.line) { 8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) drawForLine(sel.from.line, sel.from.ch, sel.to.ch); 8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 847591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line); 848591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine); 849591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end; 850591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start; 851591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (singleVLine) { 852591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (leftEnd.top < rightStart.top - 2) { 853591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); 854591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch add(pl, rightStart.top, rightStart.left, rightStart.bottom); 855591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } else { 856591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); 8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 859591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (leftEnd.bottom < rightStart.top) 860591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch add(pl, leftEnd.bottom, null, rightStart.top); 8615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) removeChildrenAndAdd(display.selectionDiv, fragment); 8645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.selectionDiv.style.display = ""; 8655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Cursor-blinking 8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function restartBlink(cm) { 86953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!cm.state.focused) return; 8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var display = cm.display; 8715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clearInterval(display.blinker); 8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var on = true; 8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.cursor.style.visibility = display.otherCursor.style.visibility = ""; 8745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.blinker = setInterval(function() { 8755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden"; 8765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, cm.options.cursorBlinkRate); 8775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // HIGHLIGHT WORKER 8805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function startWorker(cm, time) { 882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo) 883926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.state.highlight.set(time, bind(highlightWorker, cm)); 8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function highlightWorker(cm) { 887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = cm.doc; 888926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.frontier < doc.first) doc.frontier = doc.first; 889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.frontier >= cm.display.showingTo) return; 8905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var end = +new Date + cm.options.workTime; 891926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var state = copyState(doc.mode, getStateBefore(cm, doc.frontier)); 8925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var changed = [], prevChange; 893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) { 894926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.frontier >= cm.display.showingFrom) { // Visible 895926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var oldStyles = line.styles; 896926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) line.styles = highlightLine(cm, line, state); 897926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var ischange = !oldStyles || oldStyles.length != line.styles.length; 898926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i]; 899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (ischange) { 900926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (prevChange && prevChange.end == doc.frontier) prevChange.end++; 901926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1}); 9025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) line.stateAfter = copyState(doc.mode, state); 9045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 9055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) processLine(cm, line, state); 906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null; 9075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ++doc.frontier; 9095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (+new Date > end) { 9105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startWorker(cm, cm.options.workDelay); 9115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 9125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 9145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (changed.length) 9155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) operation(cm, function() { 9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < changed.length; ++i) 9175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) regChange(this, changed[i].start, changed[i].end); 9185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) })(); 9195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Finds the line to start with when starting a parse. Tries to 9225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // find a line with a stateAfter, so that it can start with a 9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // valid state. If that fails, it returns the line with the 9245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // smallest indentation, which tends to need the least context to 9255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // parse correctly. 926591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch function findStartLine(cm, n, precise) { 927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var minindent, minline, doc = cm.doc; 9285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var search = n, lim = n - 100; search > lim; --search) { 929926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (search <= doc.first) return doc.first; 930926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var line = getLine(doc, search - 1); 931591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (line.stateAfter && (!precise || search <= doc.frontier)) return search; 9325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var indented = countColumn(line.text, null, cm.options.tabSize); 9335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (minline == null || minindent > indented) { 9345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) minline = search - 1; 9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) minindent = indented; 9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return minline; 9395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 941591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch function getStateBefore(cm, n, precise) { 942926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = cm.doc, display = cm.display; 943926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!doc.mode.startState) return true; 944591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter; 945926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!state) state = startState(doc.mode); 946926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else state = copyState(doc.mode, state); 947926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.iter(pos, n, function(line) { 9485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) processLine(cm, line, state); 949926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo; 950926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) line.stateAfter = save ? copyState(doc.mode, state) : null; 9515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++pos; 9525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 9535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return state; 9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // POSITION MEASUREMENT 957926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 9585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function paddingTop(display) {return display.lineSpace.offsetTop;} 959926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;} 9605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function paddingLeft(display) { 961926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x")); 9625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return e.offsetLeft; 9635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) function measureChar(cm, line, ch, data, bias) { 966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var dir = -1; 967926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) data = data || measureLine(cm, line); 968926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 9695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var pos = ch;; pos += dir) { 970591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var r = data.get(pos); 9715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (r) break; 9725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (dir < 0 && pos == 0) dir = 1; 9735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 974e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch bias = pos > ch ? "left" : pos < ch ? "right" : bias; 975e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (bias == "left" && r.leftSide) r = r.leftSide; 976e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch else if (bias == "right" && r.rightSide) r = r.rightSide; 9775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return {left: pos < ch ? r.right : r.left, 9785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) right: pos > ch ? r.left : r.right, 979e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch top: r.top, 980e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch bottom: r.bottom}; 9815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 983926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function findCachedMeasurement(cm, line) { 984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var cache = cm.display.measureLineCache; 9855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < cache.length; ++i) { 9865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var memo = cache[i]; 9875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (memo.text == line.text && memo.markedSpans == line.markedSpans && 988926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.scroller.clientWidth == memo.width && 989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass) 99093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return memo; 9915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 99493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) function clearCachedMeasurement(cm, line) { 99593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var exists = findCachedMeasurement(cm, line); 99693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (exists) exists.text = exists.measure = exists.markedSpans = null; 99793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 99893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function measureLine(cm, line) { 1000926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // First look in the cache 100193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var cached = findCachedMeasurement(cm, line); 100293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (cached) return cached.measure; 100393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 100493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // Failing that, recompute and store result in cache 1005591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var measure = measureLineInner(cm, line, 0, 10); 1006591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch measure.get = function(num) { 1007591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (this[num]) return this[num]; 1008591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (num < 0 || num >= line.text.length) return null; 1009591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch measureLineInner(cm, line, Math.max(num - 50, 0), Math.min(num + 50, line.text.length), this); 1010591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return this[num]; 1011591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch }; 101293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var cache = cm.display.measureLineCache; 101393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var memo = {text: line.text, width: cm.display.scroller.clientWidth, 101493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) markedSpans: line.markedSpans, measure: measure, 101593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass}; 101693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo; 101793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) else cache.push(memo); 10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return measure; 10195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 10205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1021591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch function measureLineInner(cm, line, from, to, oldMeasure) { 10225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var display = cm.display, measure = emptyArray(line.text.length); 1023f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) var pre = lineContent(cm, line, measure, true, from, to); 1024926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1025926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // IE does not cache element positions of inline elements between 1026926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // calls to getBoundingClientRect. This makes the loop below, 1027926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // which gathers the positions of all the characters on the line, 1028926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // do an amount of layout work quadratic to the number of 1029926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // characters. When line wrapping is off, we try to improve things 1030926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // by first subdividing the line into a bunch of inline blocks, so 1031926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // that IE can reuse most of the layout information from caches 1032926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // for those blocks. This does interfere with line wrapping, so it 1033926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // doesn't work when wrapping is on, but in that case the 1034926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // situation is slightly better, since IE does cache line-wrapping 1035926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // information and only recomputes per-line. 1036926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) { 1037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var fragment = document.createDocumentFragment(); 1038926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var chunk = 10, n = pre.childNodes.length; 1039926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) { 1040926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var wrap = elt("div", null, null, "display: inline-block"); 1041926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var j = 0; j < chunk && n; ++j) { 1042926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) wrap.appendChild(pre.firstChild); 1043926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) --n; 1044926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1045926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) fragment.appendChild(wrap); 1046926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1047926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pre.appendChild(fragment); 1048926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1049926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 10505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) removeChildrenAndAdd(display.measure, pre); 10515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1052926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var outer = getRect(display.lineDiv); 1053591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var vranges = [], data = oldMeasure || emptyArray(line.text.length), maxBot = pre.offsetHeight; 1054926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Work around an IE7/8 bug where it will sometimes have randomly 1055926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // replaced our pre with a clone at this point. 1056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (ie_lt9 && display.measure.first != pre) 1057926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removeChildrenAndAdd(display.measure, pre); 1058926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1059e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch function measureRect(rect) { 1060e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var top = rect.top - outer.top, bot = rect.bottom - outer.top; 10615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (bot > maxBot) bot = maxBot; 10625267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (top < 0) top = 0; 1063e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch for (var i = vranges.length - 2; i >= 0; i -= 2) { 1064e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var rtop = vranges[i], rbot = vranges[i+1]; 10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rtop > bot || rbot < top) continue; 10665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rtop <= top && rbot >= bot || 10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) top <= rtop && bot >= rbot || 10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) { 1069e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch vranges[i] = Math.min(top, rtop); 1070e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch vranges[i+1] = Math.max(bot, rbot); 1071e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch break; 10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 10735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1074e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (i < 0) { i = vranges.length; vranges.push(top, bot); } 1075e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch return {left: rect.left - outer.left, 1076e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch right: rect.right - outer.left, 1077e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch top: i, bottom: null}; 1078e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch } 1079e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch function finishRect(rect) { 1080e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch rect.bottom = vranges[rect.top+1]; 1081e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch rect.top = vranges[rect.top]; 10825267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 10835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 10845267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) { 1085e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var node = cur, rect = null; 10865267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // A widget might wrap, needs special care 10875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) { 1088591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (cur.firstChild.nodeType == 1) node = cur.firstChild; 1089e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var rects = node.getClientRects(); 1090591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (rects.length > 1) { 1091e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch rect = data[i] = measureRect(rects[0]); 1092e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch rect.rightSide = measureRect(rects[rects.length - 1]); 10935267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 1094591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 1095e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (!rect) rect = data[i] = measureRect(getRect(node)); 1096e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (cur.measureRight) rect.right = getRect(cur.measureRight).left; 1097e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide)); 10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1099591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch for (var i = 0, cur; i < data.length; ++i) if (measure[i] && (cur = data[i])) { 1100e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch finishRect(cur); 1101e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (cur.leftSide) finishRect(cur.leftSide); 1102e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (cur.rightSide) finishRect(cur.rightSide); 11035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 11045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return data; 11055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 11065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function measureLineWidth(cm, line) { 1108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var hasBadSpan = false; 1109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) { 1110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sp = line.markedSpans[i]; 1111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true; 1112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var cached = !hasBadSpan && findCachedMeasurement(cm, line); 11145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right; 1115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1116f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) var pre = lineContent(cm, line, null, true); 1117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var end = pre.appendChild(zeroWidthElement(cm.display.measure)); 1118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removeChildrenAndAdd(cm.display.measure, pre); 1119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return getRect(end).right - getRect(cm.display.lineDiv).left; 1120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function clearCaches(cm) { 1123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0; 1124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.cachedCharWidth = cm.display.cachedTextHeight = null; 112553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!cm.options.lineWrapping) cm.display.maxLineChanged = true; 1126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.lineNumChars = null; 1127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 11295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; } 11305267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; } 11315267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 11325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page" 1133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function intoCoordSystem(cm, lineObj, rect, context) { 11345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) { 1135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var size = widgetHeight(lineObj.widgets[i]); 11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect.top += size; rect.bottom += size; 11375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 11385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (context == "line") return rect; 11395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!context) context = "local"; 11405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var yOff = heightAtLine(cm, lineObj); 11415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (context == "local") yOff += paddingTop(cm.display); 11425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) else yOff -= cm.display.viewOffset; 11435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (context == "page" || context == "window") { 1144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var lOff = getRect(cm.display.lineSpace); 11455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) yOff += lOff.top + (context == "window" ? 0 : pageScrollY()); 11465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()); 11475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect.left += xOff; rect.right += xOff; 11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 11495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect.top += yOff; rect.bottom += yOff; 11505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return rect; 11515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 11525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Context may be "window", "page", "div", or "local"/null 115453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // Result is in "div" coords 1155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function fromCoordSystem(cm, coords, context) { 1156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (context == "div") return coords; 1157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var left = coords.left, top = coords.top; 11585267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // First move into "page" coordinate system 1159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (context == "page") { 11605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) left -= pageScrollX(); 11615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) top -= pageScrollY(); 11625267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } else if (context == "local" || !context) { 11635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var localBox = getRect(cm.display.sizer); 11645267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) left += localBox.left; 11655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) top += localBox.top; 1166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 11675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 1168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var lineSpaceBox = getRect(cm.display.lineSpace); 11695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}; 1170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 11725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) function charCoords(cm, pos, context, lineObj, bias) { 1173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!lineObj) lineObj = getLine(cm.doc, pos.line); 11745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context); 11755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function cursorCoords(cm, pos, context, lineObj, measurement) { 1178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) lineObj = lineObj || getLine(cm.doc, pos.line); 11795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!measurement) measurement = measureLine(cm, lineObj); 11805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function get(ch, right) { 11815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var m = measureChar(cm, lineObj, ch, measurement, right ? "right" : "left"); 11825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (right) m.left = m.right; else m.right = m.left; 1183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return intoCoordSystem(cm, lineObj, m, context); 11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 118593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) function getBidi(ch, partPos) { 118693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var part = order[partPos], right = part.level % 2; 118793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) { 118893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) part = order[--partPos]; 118993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) ch = bidiRight(part) - (part.level % 2 ? 0 : 1); 119093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) right = true; 119193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) { 119293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) part = order[++partPos]; 119393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) ch = bidiLeft(part) - part.level % 2; 119493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) right = false; 11955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 119693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (right && ch == part.to && ch > part.from) return get(ch - 1); 119793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return get(ch, right); 11985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 119993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var order = getOrder(lineObj), ch = pos.ch; 120093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (!order) return get(ch); 120193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var partPos = getBidiPartAt(order, ch); 120293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var val = getBidi(ch, partPos); 120393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (bidiOther != null) val.other = getBidi(ch, bidiOther); 120493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return val; 12055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1207591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch function PosWithInfo(line, ch, outside, xRel) { 1208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var pos = new Pos(line, ch); 1209591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch pos.xRel = xRel; 1210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (outside) pos.outside = true; 1211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return pos; 1212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 12145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Coords must be lineSpace-local 12155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function coordsChar(cm, x, y) { 1216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = cm.doc; 12175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) y += cm.display.viewOffset; 1218591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (y < 0) return PosWithInfo(doc.first, 0, true, -1); 1219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1; 1220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (lineNo > last) 1221591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1); 12225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (x < 0) x = 0; 12235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (;;) { 12255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var lineObj = getLine(doc, lineNo); 12265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var found = coordsCharInner(cm, lineObj, lineNo, x, y); 12275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var merged = collapsedSpanAtEnd(lineObj); 1228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var mergedPos = merged && merged.find(); 1229591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) 1230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) lineNo = mergedPos.to.line; 12315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 12325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return found; 12335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function coordsCharInner(cm, lineObj, lineNo, x, y) { 12375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var innerOff = y - heightAtLine(cm, lineObj); 1238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth; 12395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var measurement = measureLine(cm, lineObj); 12405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function getX(ch) { 1242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sp = cursorCoords(cm, Pos(lineNo, ch), "line", 12435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lineObj, measurement); 12445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) wrongLine = true; 1245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (innerOff > sp.bottom) return sp.left - adjust; 1246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (innerOff < sp.top) return sp.left + adjust; 12475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else wrongLine = false; 12485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return sp.left; 12495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var bidi = getOrder(lineObj), dist = lineObj.text.length; 1252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var from = lineLeft(lineObj), to = lineRight(lineObj); 1253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine; 1254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1255591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1); 12565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Do a binary search between these bounds. 12575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (;;) { 12585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) { 1259591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var ch = x < fromX || x - fromX <= toX - x ? from : to; 1260591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var xDiff = x - (ch == from ? fromX : toX); 12615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch; 1262591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside, 1263591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch xDiff < 0 ? -1 : xDiff ? 1 : 0); 1264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return pos; 12655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var step = Math.ceil(dist / 2), middle = from + step; 12675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (bidi) { 12685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) middle = from; 12695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1); 12705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var middleX = getX(middle); 127253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;} 127353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;} 12745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var measureText; 12785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function textHeight(display) { 12795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (display.cachedTextHeight != null) return display.cachedTextHeight; 12805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (measureText == null) { 12815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) measureText = elt("pre"); 12825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Measure a bunch of lines, for browsers that compute 12835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // fractional heights. 12845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < 49; ++i) { 12855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) measureText.appendChild(document.createTextNode("x")); 12865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) measureText.appendChild(elt("br")); 12875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) measureText.appendChild(document.createTextNode("x")); 12895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) removeChildrenAndAdd(display.measure, measureText); 12915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var height = measureText.offsetHeight / 50; 12925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (height > 3) display.cachedTextHeight = height; 12935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) removeChildren(display.measure); 12945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return height || 1; 12955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function charWidth(display) { 12985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (display.cachedCharWidth != null) return display.cachedCharWidth; 12995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var anchor = elt("span", "x"); 13005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var pre = elt("pre", [anchor]); 13015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) removeChildrenAndAdd(display.measure, pre); 13025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var width = anchor.offsetWidth; 13035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (width > 2) display.cachedCharWidth = width; 13045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return width || 10; 13055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 13065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // OPERATIONS 13085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Operations are used to wrap changes in such a way that each 13105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // change won't have to update the cursor and display (which would 13115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // be awkward, slow, and error-prone), but instead updates are 13125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // batched and then all combined and executed at once. 13135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var nextOpId = 0; 13155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function startOperation(cm) { 1316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.curOp = { 13175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // An array of ranges of lines that have to be updated. See 13185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // updateDisplay. 13195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) changes: [], 1320f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) forceUpdate: false, 13215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) updateInput: null, 13225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) userSelChange: null, 13235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) textChanged: null, 13245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) selectionChanged: false, 132553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) cursorActivity: false, 1326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateMaxLine: false, 1327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateScrollPos: false, 1328926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) id: ++nextOpId 13295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 1330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!delayedCallbackDepth++) delayedCallbacks = []; 13315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 13325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function endOperation(cm) { 1334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var op = cm.curOp, doc = cm.doc, display = cm.display; 13355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.curOp = null; 1336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (op.updateMaxLine) computeMaxLength(cm); 133853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) { 1339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var width = measureLineWidth(cm, display.maxLine); 1340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px"; 1341926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.maxLineChanged = false; 1342926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth); 1343926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos) 1344926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true); 13455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 13465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var newScrollPos, updated; 1347926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (op.updateScrollPos) { 1348926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) newScrollPos = op.updateScrollPos; 1349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible 1350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var coords = cursorCoords(cm, doc.sel.head); 1351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom); 13525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1353f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) { 1354f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate); 1355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop; 1356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 13575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!updated && op.selectionChanged) updateSelection(cm); 1358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (op.updateScrollPos) { 1359926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop; 1360926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft; 1361926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) alignHorizontally(cm); 136253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (op.scrollToPos) 136353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin); 1364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (newScrollPos) { 1365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) scrollCursorIntoView(cm); 1366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 13675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (op.selectionChanged) restartBlink(cm); 13685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.state.focused && op.updateInput) 13705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) resetInput(cm, op.userSelChange); 13715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; 1373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (hidden) for (var i = 0; i < hidden.length; ++i) 1374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!hidden[i].lines.length) signal(hidden[i], "hide"); 1375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (unhidden) for (var i = 0; i < unhidden.length; ++i) 1376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (unhidden[i].lines.length) signal(unhidden[i], "unhide"); 1377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1378926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var delayed; 1379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!--delayedCallbackDepth) { 1380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) delayed = delayedCallbacks; 1381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) delayedCallbacks = null; 1382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 13835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (op.textChanged) 13845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) signal(cm, "change", cm, op.textChanged); 138553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (op.cursorActivity) signal(cm, "cursorActivity", cm); 1386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i](); 13875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 13885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Wraps a function in an operation. Returns the wrapped function. 13905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function operation(cm1, f) { 13915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return function() { 1392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var cm = cm1 || this, withOp = !cm.curOp; 1393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (withOp) startOperation(cm); 1394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) try { var result = f.apply(cm, arguments); } 1395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) finally { if (withOp) endOperation(cm); } 1396926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return result; 1397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 1398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function docOperation(f) { 1400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return function() { 1401926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var withOp = this.cm && !this.cm.curOp, result; 1402926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (withOp) startOperation(this.cm); 1403926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) try { result = f.apply(this, arguments); } 1404926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) finally { if (withOp) endOperation(this.cm); } 14055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return result; 14065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 14075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function runInOp(cm, f) { 1409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var withOp = !cm.curOp, result; 1410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (withOp) startOperation(cm); 1411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) try { result = f(); } 1412926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) finally { if (withOp) endOperation(cm); } 1413926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return result; 1414926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 14155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function regChange(cm, from, to, lendiff) { 1417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (from == null) from = cm.doc.first; 1418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (to == null) to = cm.doc.first + cm.doc.size; 14195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.curOp.changes.push({from: from, to: to, diff: lendiff}); 14205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 14215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // INPUT HANDLING 14235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function slowPoll(cm) { 1425926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.display.pollingFast) return; 14265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.poll.set(cm.options.pollInterval, function() { 14275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) readInput(cm); 1428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.state.focused) slowPoll(cm); 14295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 14305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 14315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function fastPoll(cm) { 14335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var missed = false; 14345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.pollingFast = true; 14355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function p() { 14365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var changed = readInput(cm); 14375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);} 14385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else {cm.display.pollingFast = false; slowPoll(cm);} 14395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 14405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.poll.set(20, p); 14415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 14425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // prevInput is a hack to work with IME. If we reset the textarea 14445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // on every change, that breaks IME. So we look for changes 14455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // compared to the previous content instead. (Modern browsers have 14465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // events that indicate IME taking place, but these are not widely 14475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // supported or compatible enough yet to rely on.) 14485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function readInput(cm) { 1449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel; 14505267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false; 1451f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (cm.state.pasteIncoming && cm.state.fakedLastChar) { 1452f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) input.value = input.value.substring(0, input.value.length - 1); 1453f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) cm.state.fakedLastChar = false; 1454f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) } 14555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var text = input.value; 14565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (text == prevInput && posEq(sel.from, sel.to)) return false; 145753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (ie && !ie_lt9 && cm.display.inputHasSelection === text) { 1458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) resetInput(cm, true); 1459926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return false; 1460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 146153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 1462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var withOp = !cm.curOp; 1463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (withOp) startOperation(cm); 1464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sel.shift = false; 14655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var same = 0, l = Math.min(prevInput.length, text.length); 146653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same; 1467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var from = sel.from, to = sel.to; 14685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (same < prevInput.length) 1469926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) from = Pos(from.line, from.ch - (prevInput.length - same)); 1470926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming) 1471926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same))); 1472926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 14735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var updateInput = cm.curOp.updateInput; 14745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)), 14755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) origin: cm.state.pasteIncoming ? "paste" : "+input"}; 14765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) makeChange(cm.doc, changeEvent, "end"); 14775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.curOp.updateInput = updateInput; 14785267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) signalLater(cm, "inputRead", cm, changeEvent); 14795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 148053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = ""; 14815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else cm.display.prevInput = text; 1482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (withOp) endOperation(cm); 1483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.state.pasteIncoming = false; 14845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 14855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 14865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function resetInput(cm, user) { 1488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var minimal, selected, doc = cm.doc; 1489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!posEq(doc.sel.from, doc.sel.to)) { 14905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.prevInput = ""; 14915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) minimal = hasCopyEvent && 1492926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000); 149353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var content = minimal ? "-" : selected || cm.getSelection(); 149453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) cm.display.input.value = content; 1495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.state.focused) selectInput(cm.display.input); 149653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (ie && !ie_lt9) cm.display.inputHasSelection = content; 149753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else if (user) { 149853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) cm.display.prevInput = cm.display.input.value = ""; 149953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (ie && !ie_lt9) cm.display.inputHasSelection = null; 150053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 15015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.inaccurateSelection = minimal; 15025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 15035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function focusInput(cm) { 1505926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input)) 1506926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.input.focus(); 15075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 15085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function isReadOnly(cm) { 1510926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return cm.options.readOnly || cm.doc.cantEdit; 15115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 15125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // EVENT HANDLERS 15145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function registerEventHandlers(cm) { 15165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var d = cm.display; 15175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scroller, "mousedown", operation(cm, onMouseDown)); 151853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (ie) 151953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) on(d.scroller, "dblclick", operation(cm, function(e) { 1520591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (signalDOMEvent(cm, e)) return; 152153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var pos = posFromMouse(cm, e); 152253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return; 152353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) e_preventDefault(e); 152453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var word = findWordAt(getLine(cm.doc, pos.line).text, pos); 152553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) extendSelection(cm.doc, word.from, word.to); 152653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) })); 152753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else 1528591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); }); 15295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.lineSpace, "selectstart", function(e) { 1530926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!eventInWidget(d, e)) e_preventDefault(e); 15315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 15325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Gecko browsers fire contextmenu *after* opening the menu, at 15335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // which point we can't mess with it anymore. Context menu is 15345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // handled in onMouseDown for Gecko. 1535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);}); 15365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scroller, "scroll", function() { 1538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (d.scroller.clientHeight) { 1539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setScrollTop(cm, d.scroller.scrollTop); 1540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setScrollLeft(cm, d.scroller.scrollLeft, true); 1541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) signal(cm, "scroll", cm); 1542926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 15435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 15445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scrollbarV, "scroll", function() { 1545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop); 15465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 15475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scrollbarH, "scroll", function() { 1548926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft); 15495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 15505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);}); 15525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);}); 15535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); } 15555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scrollbarH, "mousedown", reFocus); 15565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scrollbarV, "mousedown", reFocus); 15575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Prevent wrapper from ever scrolling 15585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); 1559926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 15605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var resizeTimer; 1561926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function onResize() { 15625267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (resizeTimer == null) resizeTimer = setTimeout(function() { 15635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) resizeTimer = null; 156493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // Might be a text scaling operation, clear size caches. 15655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null; 156693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) clearCaches(cm); 156793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) runInOp(cm, bind(regChange, cm)); 15685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) }, 100); 1569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1570926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) on(window, "resize", onResize); 1571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Above handler holds on to the editor and its data structures. 1572926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Here we poll to unregister it when the editor is no longer in 1573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // the document, so that it can be garbage-collected. 1574926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function unregister() { 1575926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {} 1576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (p) setTimeout(unregister, 5000); 1577926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else off(window, "resize", onResize); 1578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1579926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setTimeout(unregister, 5000); 15805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.input, "keyup", operation(cm, function(e) { 1582591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; 1583926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (e.keyCode == 16) cm.doc.sel.shift = false; 15845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) })); 15855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.input, "input", bind(fastPoll, cm)); 15865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.input, "keydown", operation(cm, onKeyDown)); 15875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.input, "keypress", operation(cm, onKeyPress)); 15885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.input, "focus", bind(onFocus, cm)); 15895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.input, "blur", bind(onBlur, cm)); 15905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function drag_(e) { 1592591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return; 15935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e_stop(e); 15945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 15955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.options.dragDrop) { 15965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scroller, "dragstart", function(e){onDragStart(cm, e);}); 15975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scroller, "dragenter", drag_); 15985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scroller, "dragover", drag_); 15995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.scroller, "drop", operation(cm, onDrop)); 16005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1601926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) on(d.scroller, "paste", function(e){ 1602926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (eventInWidget(d, e)) return; 1603926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) focusInput(cm); 1604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) fastPoll(cm); 1605926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 16065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.input, "paste", function() { 1607f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206 1608f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) // Add a char to the end of textarea before paste occur so that 1609f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) // selection doesn't span to the end of textarea. 1610f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (webkit && !cm.state.fakedLastChar) { 1611f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) var start = d.input.selectionStart, end = d.input.selectionEnd; 1612f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) d.input.value += "$"; 1613f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) d.input.selectionStart = start; 1614f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) d.input.selectionEnd = end; 1615f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) cm.state.fakedLastChar = true; 1616f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) } 1617926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.state.pasteIncoming = true; 16185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fastPoll(cm); 16195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 16205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function prepareCopy() { 16225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (d.inaccurateSelection) { 16235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.prevInput = ""; 16245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.inaccurateSelection = false; 16255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d.input.value = cm.getSelection(); 16265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) selectInput(d.input); 16275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.input, "cut", prepareCopy); 16305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(d.input, "copy", prepareCopy); 16315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Needed to handle Tab key in KHTML 16335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (khtml) on(d.sizer, "mouseup", function() { 16345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (document.activeElement == d.input) d.input.blur(); 16355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) focusInput(cm); 16365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 16375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1639926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function eventInWidget(display, e) { 1640926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { 16415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true; 1642926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 16435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function posFromMouse(cm, e, liberal) { 16465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var display = cm.display; 16475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!liberal) { 16485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var target = e_target(e); 16495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (target == display.scrollbarH || target == display.scrollbarH.firstChild || 16505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) target == display.scrollbarV || target == display.scrollbarV.firstChild || 165193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) target == display.scrollbarFiller || target == display.gutterFiller) return null; 16525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1653926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var x, y, space = getRect(display.lineSpace); 16545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Fails unpredictably on IE[67] when mouse is dragged around quickly. 16555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try { x = e.clientX; y = e.clientY; } catch (e) { return null; } 16565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return coordsChar(cm, x - space.left, y - space.top); 16575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var lastClick, lastDoubleClick; 16605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function onMouseDown(e) { 1661591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (signalDOMEvent(this, e)) return; 1662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel; 1663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sel.shift = e.shiftKey; 16645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1665926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (eventInWidget(display, e)) { 16665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!webkit) { 16675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.scroller.draggable = false; 16685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setTimeout(function(){display.scroller.draggable = true;}, 100); 16695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 16715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1672926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (clickInGutter(cm, e)) return; 16735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var start = posFromMouse(cm, e); 16745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (e_button(e)) { 16765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case 3: 1677926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (captureMiddleClick) onContextMenu.call(cm, cm, e); 16785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 16795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case 2: 1680926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (start) extendSelection(cm.doc, start); 16815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setTimeout(bind(focusInput, cm), 20); 16825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e_preventDefault(e); 16835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 16845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For button 1, if it was clicked inside the editor 16865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // (posFromMouse returning non-null), we have to adjust the 16875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // selection. 16885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;} 16895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1690926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!cm.state.focused) onFocus(cm); 16915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var now = +new Date, type = "single"; 16935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) { 16945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) type = "triple"; 16955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e_preventDefault(e); 16965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setTimeout(bind(focusInput, cm), 20); 16975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) selectLine(cm, start.line); 16985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) { 16995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) type = "double"; 17005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lastDoubleClick = {time: now, pos: start}; 17015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e_preventDefault(e); 17025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var word = findWordAt(getLine(doc, start.line).text, start); 1703926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) extendSelection(cm.doc, word.from, word.to); 17045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { lastClick = {time: now, pos: start}; } 17055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var last = start; 17075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) && 17085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") { 17095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var dragEnd = operation(cm, function(e2) { 17105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (webkit) display.scroller.draggable = false; 1711926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.state.draggingText = false; 17125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) off(document, "mouseup", dragEnd); 17135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) off(display.scroller, "drop", dragEnd); 17145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { 17155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e_preventDefault(e2); 1716926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) extendSelection(cm.doc, start); 17175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) focusInput(cm); 17185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 17205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Let the drag handler handle this. 17215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (webkit) display.scroller.draggable = true; 1722926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.state.draggingText = dragEnd; 17235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // IE's approach to draggable 17245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (display.scroller.dragDrop) display.scroller.dragDrop(); 17255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(document, "mouseup", dragEnd); 17265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(display.scroller, "drop", dragEnd); 17275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 17285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e_preventDefault(e); 1730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (type == "single") extendSelection(cm.doc, clipPos(doc, start)); 17315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 173253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var startstart = sel.from, startend = sel.to, lastPos = start; 17335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function doSelect(cur) { 173553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (posEq(lastPos, cur)) return; 173653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) lastPos = cur; 173753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 17385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (type == "single") { 1739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) extendSelection(cm.doc, clipPos(doc, start), cur); 1740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 1741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) startstart = clipPos(doc, startstart); 1744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) startend = clipPos(doc, startend); 1745926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (type == "double") { 17465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var word = findWordAt(getLine(doc, cur.line).text, cur); 1747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend); 1748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else extendSelection(cm.doc, startstart, word.to); 17495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (type == "triple") { 1750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0))); 1751926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0))); 17525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var editorSize = getRect(display.wrapper); 17565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Used to ensure timeout re-tries don't fire when another extend 17575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // happened in the meantime (clearTimeout isn't reliable -- at 17585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // least on Chrome, the timeouts still happen even when cleared, 17595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // if the clear happens after their scheduled firing time). 17605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var counter = 0; 17615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function extend(e) { 17635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var curCount = ++counter; 17645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cur = posFromMouse(cm, e, true); 17655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!cur) return; 17665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!posEq(cur, last)) { 1767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!cm.state.focused) onFocus(cm); 17685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) last = cur; 17695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) doSelect(cur); 17705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var visible = visibleLines(display, doc); 17715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cur.line >= visible.to || cur.line < visible.from) 17725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150); 17735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 17745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; 17755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (outside) setTimeout(operation(cm, function() { 17765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (counter != curCount) return; 17775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.scroller.scrollTop += outside; 17785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) extend(e); 17795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 50); 17805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function done(e) { 17845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) counter = Infinity; 17855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e_preventDefault(e); 17865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) focusInput(cm); 17875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) off(document, "mousemove", move); 17885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) off(document, "mouseup", up); 17895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var move = operation(cm, function(e) { 17925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!ie && !e_button(e)) done(e); 17935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else extend(e); 17945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 17955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var up = operation(cm, done); 17965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(document, "mousemove", move); 17975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(document, "mouseup", up); 17985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) function clickInGutter(cm, e) { 18015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var display = cm.display; 18025267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) try { var mX = e.clientX, mY = e.clientY; } 18035267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) catch(e) { return false; } 18045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 18055267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (mX >= Math.floor(getRect(display.gutters).right)) return false; 18065267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) e_preventDefault(e); 18075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!hasHandler(cm, "gutterClick")) return true; 18085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 18095267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var lineBox = getRect(display.lineDiv); 18105267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (mY > lineBox.bottom) return true; 18115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) mY -= lineBox.top - display.viewOffset; 18125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 18135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) for (var i = 0; i < cm.options.gutters.length; ++i) { 18145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var g = display.gutters.childNodes[i]; 18155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (g && getRect(g).right >= mX) { 18165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var line = lineAtHeight(cm.doc, mY); 18175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var gutter = cm.options.gutters[i]; 18185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) signalLater(cm, "gutterClick", cm, line, gutter, e); 18195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) break; 18205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 18215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 18225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return true; 18235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 18245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 18255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // Kludge to work around strange IE behavior where it'll sometimes 18265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // re-fire a series of drag-related events right after the drop (#1551) 18275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var lastDrop = 0; 18285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 18295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function onDrop(e) { 18305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cm = this; 1831591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e)))) 1832926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 18335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e_preventDefault(e); 18345267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (ie) lastDrop = +new Date; 18355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; 18365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!pos || isReadOnly(cm)) return; 18375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (files && files.length && window.FileReader && window.File) { 18385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var n = files.length, text = Array(n), read = 0; 18395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var loadFile = function(file, i) { 18405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var reader = new FileReader; 18415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) reader.onload = function() { 18425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) text[i] = reader.result; 18435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (++read == n) { 1844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos = clipPos(cm.doc, pos); 1845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"}, "around"); 18465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 18485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) reader.readAsText(file); 18495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 18505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < n; ++i) loadFile(files[i], i); 18515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 18525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Don't do a replace if the drop happened inside of the selected text. 1853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) { 1854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.state.draggingText(e); 1855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Ensure the editor is re-focused 1856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setTimeout(bind(focusInput, cm), 20); 18575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 18585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try { 18605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var text = e.dataTransfer.getData("Text"); 18615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (text) { 1862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to; 1863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setSelection(cm.doc, pos, pos); 1864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste"); 1865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.replaceSelection(text, null, "paste"); 1866926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) focusInput(cm); 1867926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) onFocus(cm); 18685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) catch(e){} 18715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function onDragStart(cm, e) { 18755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; } 1876591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return; 1877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 18785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var txt = cm.getSelection(); 18795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e.dataTransfer.setData("Text", txt); 18805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Use dummy image instead of default browsers image. 1882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. 18835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (e.dataTransfer.setDragImage && !safari) { 1884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); 1885926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (opera) { 1886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) img.width = img.height = 1; 1887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.wrapper.appendChild(img); 1888926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Force a relayout, or Opera won't use our image for some obscure reason 1889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) img._top = img.offsetTop; 1890926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1891926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) e.dataTransfer.setDragImage(img, 0, 0); 1892926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (opera) img.parentNode.removeChild(img); 1893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 18945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function setScrollTop(cm, val) { 1897926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (Math.abs(cm.doc.scrollTop - val) < 2) return; 1898926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.doc.scrollTop = val; 18995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!gecko) updateDisplay(cm, [], val); 19005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val; 19015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val; 19025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (gecko) updateDisplay(cm, []); 19035267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) startWorker(cm, 100); 19045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1905926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function setScrollLeft(cm, val, isScroller) { 1906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return; 1907926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth); 1908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.doc.scrollLeft = val; 1909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) alignHorizontally(cm); 19105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val; 19115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val; 19125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 19135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Since the delta values reported on mouse wheel events are 19155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // unstandardized between browsers and even browser versions, and 19165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // generally horribly unpredictable, this code starts by measuring 19175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the scroll effect that the first few mouse wheel events have, 19185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // and, from that, detects the way it can convert deltas to pixel 19195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // offsets afterwards. 19205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // 19215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The reason we want to know the amount a wheel event will scroll 19225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // is that it gives us a chance to update the display before the 19235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // actual scrolling happens, reducing flickering. 19245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var wheelSamples = 0, wheelPixelsPerUnit = null; 19265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Fill in a browser-detected starting value on browsers where we 19275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // know one. These don't have to be accurate -- the result of them 19285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // being wrong would just be a slight flicker on the first wheel 19295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // scroll (if it is large enough). 19305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ie) wheelPixelsPerUnit = -.53; 19315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (gecko) wheelPixelsPerUnit = 15; 19325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (chrome) wheelPixelsPerUnit = -.7; 19335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (safari) wheelPixelsPerUnit = -1/3; 19345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function onScrollWheel(cm, e) { 19365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var dx = e.wheelDeltaX, dy = e.wheelDeltaY; 19375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail; 19385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail; 19395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (dy == null) dy = e.wheelDelta; 19405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 194153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var display = cm.display, scroll = display.scroller; 194253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // Quit if there's nothing to scroll here 194353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!(dx && scroll.scrollWidth > scroll.clientWidth || 194453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) dy && scroll.scrollHeight > scroll.clientHeight)) return; 194553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 1946926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Webkit browsers on OS X abort momentum scrolls when the target 1947926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // of the scroll event is removed from the scrollable element. 1948926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // This hack (see related code in patchDisplay) makes sure the 1949926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // element is kept around. 1950926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (dy && mac && webkit) { 1951926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var cur = e.target; cur != scroll; cur = cur.parentNode) { 1952926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cur.lineObj) { 1953926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.currentWheelTarget = cur; 1954926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) break; 1955926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1956926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1957926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1958926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1959926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // On some browsers, horizontal scrolling will cause redraws to 1960926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // happen before the gutter has been realigned, causing it to 1961926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // wriggle around in a most unseemly way. When we have an 1962926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // estimated pixels/delta value, we just handle horizontal 1963926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // scrolling entirely here. It'll be slightly off from native, but 1964926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // better than glitching out. 1965926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (dx && !gecko && !opera && wheelPixelsPerUnit != null) { 1966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (dy) 1967926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))); 1968926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth))); 1969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) e_preventDefault(e); 1970926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.wheelStartX = null; // Abort measurement, if in progress 1971926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 1972926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1973926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1974926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (dy && wheelPixelsPerUnit != null) { 19755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var pixels = dy * wheelPixelsPerUnit; 1976926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; 1977926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (pixels < 0) top = Math.max(0, top + pixels - 50); 1978926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else bot = Math.min(cm.doc.height, bot + pixels + 50); 19795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) updateDisplay(cm, [], {top: top, bottom: bot}); 19805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1981926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 19825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (wheelSamples < 20) { 1983926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (display.wheelStartX == null) { 1984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; 1985926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.wheelDX = dx; display.wheelDY = dy; 19865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setTimeout(function() { 1987926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (display.wheelStartX == null) return; 1988926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var movedX = scroll.scrollLeft - display.wheelStartX; 1989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var movedY = scroll.scrollTop - display.wheelStartY; 1990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || 1991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (movedX && display.wheelDX && movedX / display.wheelDX); 1992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.wheelStartX = display.wheelStartY = null; 19935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sample) return; 19945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); 19955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++wheelSamples; 19965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 200); 19975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 1998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.wheelDX += dx; display.wheelDY += dy; 19995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function doHandleBinding(cm, bound, dropShift) { 20045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (typeof bound == "string") { 20055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bound = commands[bound]; 20065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!bound) return false; 20075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2008926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Ensure previous input has been read, so that the handler sees a 2009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // consistent view of the document 2010926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false; 2011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = cm.doc, prevShift = doc.sel.shift, done = false; 20125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try { 2013926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (isReadOnly(cm)) cm.state.suppressEdits = true; 2014926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (dropShift) doc.sel.shift = false; 2015926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) done = bound(cm) != Pass; 20165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } finally { 2017926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.sel.shift = prevShift; 2018926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.state.suppressEdits = false; 20195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2020926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return done; 2021926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2022926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2023926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function allKeyMaps(cm) { 2024926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var maps = cm.state.keyMaps.slice(0); 202553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (cm.options.extraKeys) maps.push(cm.options.extraKeys); 2026926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) maps.push(cm.options.keyMap); 2027926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return maps; 20285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var maybeTransition; 20315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function handleKeyBinding(cm, e) { 20325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Handle auto keymap transitions 20335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto; 20345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clearTimeout(maybeTransition); 20355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() { 20365267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (getKeyMap(cm.options.keyMap) == startMap) { 20375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.options.keyMap = (next.call ? next.call(null, cm) : next); 20385267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) keyMapChanged(cm); 20395267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 20405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 50); 20415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2042926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var name = keyName(e, true), handled = false; 2043926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!name) return false; 2044926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var keymaps = allKeyMaps(cm); 2045926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2046926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (e.shiftKey) { 2047926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // First try to resolve full name (including 'Shift-'). Failing 2048926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // that, see if there is a cursor-motion command (starting with 2049926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // 'go') bound to the keyname without 'Shift-'. 2050926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);}) 2051926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) || lookupKey(name, keymaps, function(b) { 20525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) 20535267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return doHandleBinding(cm, b); 2054926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 20555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 2056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); }); 20575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2058926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 20595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (handled) { 20605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e_preventDefault(e); 20615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) restartBlink(cm); 20625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; } 20635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) signalLater(cm, "keyHandled", cm, name, e); 20645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return handled; 20665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function handleCharBinding(cm, e, ch) { 2069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var handled = lookupKey("'" + ch + "'", allKeyMaps(cm), 20705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function(b) { return doHandleBinding(cm, b, true); }); 20715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (handled) { 20725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e_preventDefault(e); 20735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) restartBlink(cm); 20745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) signalLater(cm, "keyHandled", cm, "'" + ch + "'", e); 20755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return handled; 20775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var lastStoppedKey = null; 20805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function onKeyDown(e) { 20815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cm = this; 2082926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!cm.state.focused) onFocus(cm); 20835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ie && e.keyCode == 27) { e.returnValue = false; } 2084591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; 2085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var code = e.keyCode; 20865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // IE does strange things with escape. 2087926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.doc.sel.shift = code == 16 || e.shiftKey; 20885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // First give onKeyEvent option a chance to handle this. 20895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var handled = handleKeyBinding(cm, e); 20905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (opera) { 20915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lastStoppedKey = handled ? code : null; 20925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Opera has no cut event... we try to at least catch the key combo 2093926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) 20945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.replaceSelection(""); 20955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function onKeyPress(e) { 20995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cm = this; 2100591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; 2101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var keyCode = e.keyCode, charCode = e.charCode; 21025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} 21035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return; 21045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var ch = String.fromCharCode(charCode == null ? keyCode : charCode); 2105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (this.options.electricChars && this.doc.mode.electricChars && 21065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.options.smartIndent && !isReadOnly(this) && 2107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.doc.mode.electricChars.indexOf(ch) > -1) 2108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75); 21095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (handleCharBinding(cm, e, ch)) return; 211053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (ie && !ie_lt9) cm.display.inputHasSelection = null; 21115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fastPoll(cm); 21125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 21135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 21145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function onFocus(cm) { 21155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.options.readOnly == "nocursor") return; 2116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!cm.state.focused) { 21175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) signal(cm, "focus", cm); 2118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.state.focused = true; 2119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1) 2120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.wrapper.className += " CodeMirror-focused"; 21215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) resetInput(cm, true); 21225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 21235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) slowPoll(cm); 21245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) restartBlink(cm); 21255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 21265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function onBlur(cm) { 2127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm.state.focused) { 21285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) signal(cm, "blur", cm); 2129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.state.focused = false; 2130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", ""); 21315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 21325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clearInterval(cm.display.blinker); 2133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150); 21345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 21355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 21365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var detectingSelectAll; 21375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function onContextMenu(cm, e) { 2138e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (signalDOMEvent(cm, e, "contextmenu")) return; 2139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var display = cm.display, sel = cm.doc.sel; 2140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (eventInWidget(display, e)) return; 2141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 21425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; 21435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!pos || opera) return; // Opera is difficult. 21445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)) 2145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) operation(cm, setSelection)(cm.doc, pos, pos); 21465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 21475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var oldCSS = display.input.style.cssText; 21485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.inputDiv.style.position = "absolute"; 21495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) + 21505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" + 2151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);"; 21525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) focusInput(cm); 21535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) resetInput(cm, true); 21545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Adds "Select all" to context menu in FF 21555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " "; 21565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 215793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) function prepareSelectAllHack() { 215893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (display.input.selectionStart != null) { 215993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value); 216093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) display.prevInput = " "; 216193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) display.input.selectionStart = 1; display.input.selectionEnd = extval.length; 216293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 216393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 21645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function rehide() { 21655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.inputDiv.style.position = "relative"; 21665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.input.style.cssText = oldCSS; 21675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos; 21685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) slowPoll(cm); 21695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Try to detect the user choosing select-all 217193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (display.input.selectionStart != null) { 217293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (!ie || ie_lt9) prepareSelectAllHack(); 21735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clearTimeout(detectingSelectAll); 217493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var i = 0, poll = function(){ 21755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (display.prevInput == " " && display.input.selectionStart == 0) 21765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) operation(cm, commands.selectAll)(cm); 21775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500); 21785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else resetInput(cm); 2179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 2180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) detectingSelectAll = setTimeout(poll, 200); 21815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 21825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 21835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 218493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (ie && !ie_lt9) prepareSelectAllHack(); 2185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (captureMiddleClick) { 21865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e_stop(e); 2187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var mouseup = function() { 21885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) off(window, "mouseup", mouseup); 21895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setTimeout(rehide, 20); 2190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 2191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) on(window, "mouseup", mouseup); 21925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 21935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setTimeout(rehide, 50); 21945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 21955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 21965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 21975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // UPDATING 21985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2199591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var changeEnd = CodeMirror.changeEnd = function(change) { 220053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!change.text) return change.to; 2201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return Pos(change.from.line + change.text.length - 1, 2202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)); 2203591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch }; 2204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Make sure a position will be valid after the given change. 2206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function clipPostChange(doc, change, pos) { 2207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!posLess(change.from, pos)) return clipPos(doc, pos); 2208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var diff = (change.text.length - 1) - (change.to.line - change.from.line); 2209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (pos.line > change.to.line + diff) { 2210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1; 2211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length); 2212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return clipToLen(pos, getLine(doc, preLine).text.length); 2213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (pos.line == change.to.line + diff) 2215926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) + 2216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getLine(doc, change.to.line).text.length - change.to.ch); 2217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var inside = pos.line - change.from.line; 2218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch)); 2219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Hint can be null|"end"|"start"|"around"|{anchor,head} 2222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function computeSelAfterChange(doc, change, hint) { 2223926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (hint && typeof hint == "object") // Assumed to be {anchor, head} object 2224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return {anchor: clipPostChange(doc, change, hint.anchor), 2225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) head: clipPostChange(doc, change, hint.head)}; 2226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (hint == "start") return {anchor: change.from, head: change.from}; 2228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var end = changeEnd(change); 2230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (hint == "around") return {anchor: change.from, head: end}; 2231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (hint == "end") return {anchor: end, head: end}; 2232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // hint is null, leave the selection alone as much as possible 2234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var adjustPos = function(pos) { 2235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (posLess(pos, change.from)) return pos; 2236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!posLess(change.to, pos)) return end; 2237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; 2239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (pos.line == change.to.line) ch += end.ch - change.to.ch; 2240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return Pos(line, ch); 2241926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 2242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)}; 2243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 224593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) function filterChange(doc, change, update) { 2246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var obj = { 2247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) canceled: false, 2248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) from: change.from, 2249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) to: change.to, 2250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) text: change.text, 2251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) origin: change.origin, 2252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cancel: function() { this.canceled = true; } 2253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 225493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (update) obj.update = function(from, to, text, origin) { 225593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (from) this.from = clipPos(doc, from); 225693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (to) this.to = clipPos(doc, to); 225793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (text) this.text = text; 225893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (origin !== undefined) this.origin = origin; 225993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) }; 2260926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) signal(doc, "beforeChange", doc, obj); 2261926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj); 2262926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2263926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (obj.canceled) return null; 2264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}; 2265926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2266926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2267926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Replace the range from from to to by the strings in replacement. 2268926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // change is a {from, to, text [, origin]} object 2269926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function makeChange(doc, change, selUpdate, ignoreReadOnly) { 2270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.cm) { 2271926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly); 2272926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.cm.state.suppressEdits) return; 2273926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2274926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2275926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { 227693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) change = filterChange(doc, change, true); 2277926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!change) return; 2278926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 22805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Possibly split or suppress the update based on the presence 22815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // of read-only spans in its range. 2282926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); 22835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (split) { 22845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = split.length - 1; i >= 1; --i) 2285926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]}); 22865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (split.length) 2287926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate); 22885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 2289926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) makeChangeNoReadonly(doc, change, selUpdate); 22905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 22915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 22925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function makeChangeNoReadonly(doc, change, selUpdate) { 2294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var selAfter = computeSelAfterChange(doc, change, selUpdate); 2295926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); 22965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); 2298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var rebased = []; 2299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) linkedDocs(doc, function(doc, sharedHist) { 2301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!sharedHist && indexOf(rebased, doc.history) == -1) { 2302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) rebaseHist(doc.history, change); 2303926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) rebased.push(doc.history); 2304926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2305926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); 23065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 2307926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2308926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2309926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function makeChangeFromHistory(doc, type) { 231053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (doc.cm && doc.cm.state.suppressEdits) return; 231153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 2312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var hist = doc.history; 2313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var event = (type == "undo" ? hist.done : hist.undone).pop(); 2314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!event) return; 2315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter, 23175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) anchorAfter: event.anchorBefore, headAfter: event.headBefore, 23185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) generation: hist.generation}; 2319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (type == "undo" ? hist.undone : hist.done).push(anti); 23205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) hist.generation = event.generation || ++hist.maxGeneration; 2321926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 232293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); 232393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 2324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = event.changes.length - 1; i >= 0; --i) { 2325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var change = event.changes[i]; 2326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) change.origin = type; 232793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (filter && !filterChange(doc, change, false)) { 232893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) (type == "undo" ? hist.done : hist.undone).length = 0; 232993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return; 233093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 233193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 2332926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) anti.changes.push(historyChangeFromChange(doc, change)); 2333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var after = i ? computeSelAfterChange(doc, change, null) 2335926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) : {anchor: event.anchorBefore, head: event.headBefore}; 2336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); 2337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var rebased = []; 2338926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) linkedDocs(doc, function(doc, sharedHist) { 2340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!sharedHist && indexOf(rebased, doc.history) == -1) { 2341926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) rebaseHist(doc.history, change); 2342926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) rebased.push(doc.history); 2343926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2344926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); 2345926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 23465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 23475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 23485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function shiftDoc(doc, distance) { 2350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);} 2351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.first += distance; 2352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance); 2353926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor); 2354926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to); 2355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2357926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function makeChangeSingleDoc(doc, change, selAfter, spans) { 2358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.cm && !doc.cm.curOp) 2359926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans); 2360926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2361926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (change.to.line < doc.first) { 2362926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); 2363926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 2364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (change.from.line > doc.lastLine()) return; 2366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Clip the change to the size of this doc 2368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (change.from.line < doc.first) { 2369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var shift = change.text.length - 1 - (doc.first - change.from.line); 2370926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) shiftDoc(doc, shift); 2371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), 2372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) text: [lst(change.text)], origin: change.origin}; 2373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var last = doc.lastLine(); 2375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (change.to.line > last) { 2376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), 2377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) text: [change.text[0]], origin: change.origin}; 23785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) change.removed = getBetween(doc, change.from, change.to); 2381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!selAfter) selAfter = computeSelAfterChange(doc, change, null); 2383926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter); 2384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else updateDoc(doc, change, spans, selAfter); 23855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 23865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function makeChangeSingleDocInEditor(cm, change, spans, selAfter) { 2388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = cm.doc, display = cm.display, from = change.from, to = change.to; 23895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var recomputeMaxLength = false, checkWidthStart = from.line; 23915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!cm.options.lineWrapping) { 2392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line))); 23935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) doc.iter(checkWidthStart, to.line + 1, function(line) { 2394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (line == display.maxLine) { 23955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) recomputeMaxLength = true; 23965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 23975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 23985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 23995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 24005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 240153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!posLess(doc.sel.head, change.from) && !posLess(change.to, doc.sel.head)) 240253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) cm.curOp.cursorActivity = true; 240353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 2404926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateDoc(doc, change, spans, selAfter, estimateHeight(cm)); 24055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2406926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!cm.options.lineWrapping) { 2407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.iter(checkWidthStart, from.line + change.text.length, function(line) { 24085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var len = lineLength(doc, line); 2409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (len > display.maxLineLength) { 2410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.maxLine = line; 2411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.maxLineLength = len; 2412926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) display.maxLineChanged = true; 24135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) recomputeMaxLength = false; 24145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 24155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 24165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (recomputeMaxLength) cm.curOp.updateMaxLine = true; 24175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 24185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Adjust frontier, schedule worker 2420926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.frontier = Math.min(doc.frontier, from.line); 24215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startWorker(cm, 400); 24225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var lendiff = change.text.length - (to.line - from.line) - 1; 24245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Remember that these lines changed, for updating the display 24255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) regChange(cm, from.line, to.line + 1, lendiff); 2426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 24275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (hasHandler(cm, "change")) { 2428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var changeObj = {from: from, to: to, 2429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) text: change.text, 2430926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removed: change.removed, 2431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) origin: change.origin}; 24325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.curOp.textChanged) { 24335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {} 24345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cur.next = changeObj; 24355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else cm.curOp.textChanged = changeObj; 24365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 24375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 24385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2439926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function replaceRange(doc, code, from, to, origin) { 24405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!to) to = from; 24415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (posLess(to, from)) { var tmp = to; to = from; from = tmp; } 2442926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (typeof code == "string") code = splitLines(code); 2443926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) makeChange(doc, {from: from, to: to, text: code, origin: origin}, null); 24445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 24455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2446926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // POSITION OBJECT 2447926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2448926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function Pos(line, ch) { 2449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!(this instanceof Pos)) return new Pos(line, ch); 2450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.line = line; this.ch = ch; 2451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2452926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) CodeMirror.Pos = Pos; 24535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function posEq(a, b) {return a.line == b.line && a.ch == b.ch;} 24555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);} 2456926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function copyPos(x) {return Pos(x.line, x.ch);} 24575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // SELECTION 2459926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));} 24615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function clipPos(doc, pos) { 2462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (pos.line < doc.first) return Pos(doc.first, 0); 2463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var last = doc.first + doc.size - 1; 2464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (pos.line > last) return Pos(last, getLine(doc, last).text.length); 2465926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return clipToLen(pos, getLine(doc, pos.line).text.length); 2466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function clipToLen(pos, linelen) { 2468926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var ch = pos.ch; 2469926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (ch == null || ch > linelen) return Pos(pos.line, linelen); 2470926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (ch < 0) return Pos(pos.line, 0); 24715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else return pos; 24725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2473926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;} 2474926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2475926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // If shift is held, this will move the selection anchor. Otherwise, 2476926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // it'll set the whole selection. 2477926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function extendSelection(doc, pos, other, bias) { 2478926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.sel.shift || doc.sel.extend) { 2479926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var anchor = doc.sel.anchor; 2480926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (other) { 2481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var posBefore = posLess(pos, anchor); 2482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (posBefore != posLess(other, anchor)) { 2483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) anchor = pos; 2484926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos = other; 2485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (posBefore != posLess(pos, other)) { 2486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos = other; 2487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setSelection(doc, anchor, pos, bias); 2490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 2491926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setSelection(doc, pos, other || pos, bias); 24925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2493926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.cm) doc.cm.curOp.userSelChange = true; 2494926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2496926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function filterSelectionChange(doc, anchor, head) { 2497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var obj = {anchor: anchor, head: head}; 2498926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) signal(doc, "beforeSelectionChange", doc, obj); 2499926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj); 2500926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head); 2501926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return obj; 25025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 25045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Update the selection. Last two args are only used by 25055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // updateDoc, since they have to be expressed in the line 25065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // numbers before the update. 2507926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function setSelection(doc, anchor, head, bias, checkAtomic) { 2508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!checkAtomic && hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) { 2509926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var filtered = filterSelectionChange(doc, anchor, head); 2510926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) head = filtered.head; 2511926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) anchor = filtered.anchor; 2512926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 25135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2514926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sel = doc.sel; 2515926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sel.goalColumn = null; 25165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Skip over atomic spans. 2517926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (checkAtomic || !posEq(anchor, sel.anchor)) 2518926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push"); 2519926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (checkAtomic || !posEq(head, sel.head)) 2520926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) head = skipAtomic(doc, head, bias, checkAtomic != "push"); 2521926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return; 2523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2524926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sel.anchor = anchor; sel.head = head; 2525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var inv = posLess(head, anchor); 2526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sel.from = inv ? head : anchor; 2527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sel.to = inv ? anchor : head; 2528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2529926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.cm) 253053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = 253153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) doc.cm.curOp.cursorActivity = true; 25325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) signalLater(doc, "cursorActivity", doc); 25345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 25365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function reCheckSelection(cm) { 2537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push"); 25385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function skipAtomic(doc, pos, bias, mayClear) { 2541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var flipped = false, curPos = pos; 25425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var dir = bias || 1; 2543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.cantEdit = false; 25445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) search: for (;;) { 254553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var line = getLine(doc, curPos.line); 25465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (line.markedSpans) { 25475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < line.markedSpans.length; ++i) { 25485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var sp = line.markedSpans[i], m = sp.marker; 25495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) && 25505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) { 255153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (mayClear) { 255253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) signal(m, "beforeCursorEnter"); 255353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (m.explicitlyCleared) { 255453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!line.markedSpans) break; 255553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else {--i; continue;} 255653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 255753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 255853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!m.atomic) continue; 25595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var newPos = m.find()[dir < 0 ? "from" : "to"]; 25605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (posEq(newPos, curPos)) { 25615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newPos.ch += dir; 25625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (newPos.ch < 0) { 2563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1)); 25645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else newPos = null; 25655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (newPos.ch > line.text.length) { 2566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0); 25675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else newPos = null; 25685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!newPos) { 25705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (flipped) { 25715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Driven in a corner -- no valid cursor position found at all 25725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // -- try again *with* clearing, if we didn't already 2573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!mayClear) return skipAtomic(doc, pos, bias, true); 25745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Otherwise, turn off editing until further notice, and return the start of the doc 2575926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.cantEdit = true; 2576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return Pos(doc.first, 0); 25775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) flipped = true; newPos = pos; dir = -dir; 25795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) curPos = newPos; 25825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue search; 25835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return curPos; 25875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 25905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // SCROLLING 25915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 25925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function scrollCursorIntoView(cm) { 259393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin); 2594926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!cm.state.focused) return; 25955267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var display = cm.display, box = getRect(display.sizer), doScroll = null; 25965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (coords.top + box.top < 0) doScroll = true; 25975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; 25985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (doScroll != null && !phantom) { 25995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var hidden = display.cursor.style.display == "none"; 26005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (hidden) { 26015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.cursor.style.display = ""; 26025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.cursor.style.left = coords.left + "px"; 26035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.cursor.style.top = (coords.top - display.viewOffset) + "px"; 26045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.cursor.scrollIntoView(doScroll); 26065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (hidden) display.cursor.style.display = "none"; 26075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function scrollPosIntoView(cm, pos, margin) { 2611926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (margin == null) margin = 0; 2612926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (;;) { 2613926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var changed = false, coords = cursorCoords(cm, pos); 2614926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin); 2615926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; 2616926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (scrollPos.scrollTop != null) { 2617926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setScrollTop(cm, scrollPos.scrollTop); 2618926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true; 2619926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2620926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (scrollPos.scrollLeft != null) { 2621926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setScrollLeft(cm, scrollPos.scrollLeft); 2622926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true; 2623926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!changed) return coords; 2625926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2626926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2627926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2628926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function scrollIntoView(cm, x1, y1, x2, y2) { 2629926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2); 2630926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop); 2631926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft); 26325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2634926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function calculateScrollPos(cm, x1, y1, x2, y2) { 26355267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var display = cm.display, snapMargin = textHeight(cm.display); 263653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (y1 < 0) y1 = 0; 26375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {}; 2638926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var docBottom = cm.doc.height + paddingVert(display); 26395267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin; 264053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (y1 < screentop) { 264153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) result.scrollTop = atTop ? 0 : y1; 264253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else if (y2 > screentop + screen) { 264353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen); 264453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (newTop != screentop) result.scrollTop = newTop; 264553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 26465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft; 26485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth; 26495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var gutterw = display.gutters.offsetWidth; 26505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var atLeft = x1 < gutterw + 10; 26515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (x1 < screenleft + gutterw || atLeft) { 26525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (atLeft) x1 = 0; 26535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.scrollLeft = Math.max(0, x1 - 10 - gutterw); 26545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (x2 > screenw + screenleft - 3) { 26555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.scrollLeft = x2 + 10 - screenw; 26565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return result; 26585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function updateScrollPos(cm, left, top) { 266153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) cm.curOp.updateScrollPos = {scrollLeft: left == null ? cm.doc.scrollLeft : left, 266253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) scrollTop: top == null ? cm.doc.scrollTop : top}; 2663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2665926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function addToScrollPos(cm, left, top) { 2666926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var pos = cm.curOp.updateScrollPos || (cm.curOp.updateScrollPos = {scrollLeft: cm.doc.scrollLeft, scrollTop: cm.doc.scrollTop}); 2667926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var scroll = cm.display.scroller; 2668926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos.scrollTop = Math.max(0, Math.min(scroll.scrollHeight - scroll.clientHeight, pos.scrollTop + top)); 2669926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos.scrollLeft = Math.max(0, Math.min(scroll.scrollWidth - scroll.clientWidth, pos.scrollLeft + left)); 2670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 26725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // API UTILITIES 26735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2674926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function indentLine(cm, n, how, aggressive) { 2675926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = cm.doc; 26765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (how == null) how = "add"; 26775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (how == "smart") { 2678926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!cm.doc.mode.indent) how = "prev"; 26795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else var state = getStateBefore(cm, n); 26805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var tabSize = cm.options.tabSize; 26835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); 26845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var curSpaceString = line.text.match(/^\s*/)[0], indentation; 26855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (how == "smart") { 2686926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); 2687926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (indentation == Pass) { 2688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!aggressive) return; 2689926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) how = "prev"; 2690926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 26915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (how == "prev") { 2693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize); 26945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else indentation = 0; 2695926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (how == "add") { 2696926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) indentation = curSpace + cm.options.indentUnit; 2697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (how == "subtract") { 2698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) indentation = curSpace - cm.options.indentUnit; 26995267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } else if (typeof how == "number") { 27005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) indentation = curSpace + how; 27015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 27025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) indentation = Math.max(0, indentation); 27035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var indentString = "", pos = 0; 27055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.options.indentWithTabs) 27065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} 27075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (pos < indentation) indentString += spaceStr(indentation - pos); 27085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (indentString != curSpaceString) 2710926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); 27115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) line.stateAfter = null; 27125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 27135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function changeLine(cm, handle, op) { 2715926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var no = handle, line = handle, doc = cm.doc; 27165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle)); 27175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else no = lineNo(handle); 27185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (no == null) return null; 27195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (op(line, no)) regChange(cm, no, no + 1); 27205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else return null; 27215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return line; 27225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 27235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function findPosH(doc, pos, dir, unit, visually) { 272593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var line = pos.line, ch = pos.ch, origDir = dir; 27265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var lineObj = getLine(doc, line); 2727926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var possible = true; 27285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function findNextLine() { 27295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var l = line + dir; 2730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (l < doc.first || l >= doc.first + doc.size) return (possible = false); 27315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) line = l; 27325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return lineObj = getLine(doc, l); 27335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 27345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function moveOnce(boundToLine) { 27355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true); 27365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (next == null) { 27375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!boundToLine && findNextLine()) { 27385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj); 27395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else ch = dir < 0 ? lineObj.text.length : 0; 2740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else return (possible = false); 27415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else ch = next; 27425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 27435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 27455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (unit == "char") moveOnce(); 27465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (unit == "column") moveOnce(true); 2747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (unit == "word" || unit == "group") { 2748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sawType = null, group = unit == "group"; 2749926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var first = true;; first = false) { 2750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (dir < 0 && !moveOnce(!first)) break; 2751926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var cur = lineObj.text.charAt(ch) || "\n"; 2752926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var type = isWordChar(cur) ? "w" 2753926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) : !group ? null 2754926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) : /\s/.test(cur) ? null 2755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) : "p"; 2756926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (sawType && sawType != type) { 2757926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (dir < 0) {dir = 1; moveOnce();} 2758926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) break; 2759926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2760926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (type) sawType = type; 2761926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (dir > 0 && !moveOnce(!first)) break; 27625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 27635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 276493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var result = skipAtomic(doc, Pos(line, ch), origDir, true); 2765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!possible) result.hitSide = true; 2766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return result; 2767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2768926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2769926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function findPosV(cm, pos, dir, unit) { 2770926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = cm.doc, x = pos.left, y; 2771926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (unit == "page") { 2772926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); 2773926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display)); 2774926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (unit == "line") { 2775926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) y = dir > 0 ? pos.bottom + 3 : pos.top - 3; 2776926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2777926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (;;) { 2778926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var target = coordsChar(cm, x, y); 2779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!target.outside) break; 2780926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; } 2781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) y += dir * 5; 2782926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2783926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return target; 27845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 27855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function findWordAt(line, pos) { 27875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var start = pos.ch, end = pos.ch; 27885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (line) { 2789e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end; 27905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var startChar = line.charAt(start); 2791926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var check = isWordChar(startChar) ? isWordChar 2792926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} 2793926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);}; 27945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (start > 0 && check(line.charAt(start - 1))) --start; 27955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (end < line.length && check(line.charAt(end))) ++end; 27965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return {from: Pos(pos.line, start), to: Pos(pos.line, end)}; 27985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 27995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function selectLine(cm, line) { 2801926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0))); 28025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 28035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // PROTOTYPE 28055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The publicly visible API. Note that operation(null, f) means 28075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // 'wrap f in an operation, performed on its `this` parameter' 28085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.prototype = { 281093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) constructor: CodeMirror, 28115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);}, 28125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setOption: function(option, value) { 28145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var options = this.options, old = options[option]; 28155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (options[option] == value && option != "mode") return; 28165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) options[option] = value; 28175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (optionHandlers.hasOwnProperty(option)) 28185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) operation(this, optionHandlers[option])(this, value, old); 28195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 28205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getOption: function(option) {return this.options[option];}, 2822926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getDoc: function() {return this.doc;}, 28235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 282453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) addKeyMap: function(map, bottom) { 282553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) this.state.keyMaps[bottom ? "push" : "unshift"](map); 2826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 2827926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removeKeyMap: function(map) { 2828926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var maps = this.state.keyMaps; 2829926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < maps.length; ++i) 2830e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) { 2831926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) maps.splice(i, 1); 2832926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return true; 2833926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2834926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 28355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) addOverlay: operation(null, function(spec, options) { 2837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); 2838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (mode.startState) throw new Error("Overlays may not be stateful."); 2839926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque}); 2840926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.state.modeGen++; 2841926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) regChange(this); 28425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 2843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removeOverlay: operation(null, function(spec) { 2844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var overlays = this.state.overlays; 2845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < overlays.length; ++i) { 284693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var cur = overlays[i].modeSpec; 284793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (cur == spec || typeof spec == "string" && cur.name == spec) { 2848926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) overlays.splice(i, 1); 2849926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.state.modeGen++; 2850926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) regChange(this); 2851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 2852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 28545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 28555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) indentLine: operation(null, function(n, dir, aggressive) { 28575267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (typeof dir != "string" && typeof dir != "number") { 28585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (dir == null) dir = this.options.smartIndent ? "smart" : "prev"; 28595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else dir = dir ? "add" : "subtract"; 28605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive); 28625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 28635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) indentSelection: operation(null, function(how) { 2864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sel = this.doc.sel; 28655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how); 28665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var e = sel.to.line - (sel.to.ch ? 0 : 1); 28675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how); 28685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 28695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2870926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Fetch the parser token for a given character. Useful for hacks 2871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // that want to inspect the mode state (say, for completion). 2872591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch getTokenAt: function(pos, precise) { 2873926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = this.doc; 28745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pos = clipPos(doc, pos); 2875591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode; 2876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var line = getLine(doc, pos.line); 2877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var stream = new StringStream(line.text, this.options.tabSize); 2878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) while (stream.pos < pos.ch && !stream.eol()) { 2879926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) stream.start = stream.pos; 2880926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var style = mode.token(stream, state); 2881926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 2882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return {start: stream.start, 2883926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) end: stream.pos, 2884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) string: stream.current(), 2885926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) className: style || null, // Deprecated, use 'type' instead 2886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) type: style || null, 2887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) state: state}; 28885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 28895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2890591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch getTokenTypeAt: function(pos) { 2891591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch pos = clipPos(this.doc, pos); 2892591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var styles = getLineStyles(this, getLine(this.doc, pos.line)); 2893591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; 2894e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (ch == 0) return styles[2]; 2895591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch for (;;) { 2896591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var mid = (before + after) >> 1; 2897591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid; 2898591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch else if (styles[mid * 2 + 1] < ch) before = mid + 1; 2899591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch else return styles[mid * 2 + 2]; 2900591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 2901591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch }, 2902591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 2903e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch getModeAt: function(pos) { 2904e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var mode = this.doc.mode; 2905e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (!mode.innerMode) return mode; 2906e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode; 2907e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch }, 2908e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch 2909e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch getHelper: function(pos, type) { 2910e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (!helpers.hasOwnProperty(type)) return; 2911e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var help = helpers[type], mode = this.getModeAt(pos); 2912e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch return mode[type] && help[mode[type]] || 2913e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch mode.helperType && help[mode.helperType] || 2914e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch help[mode.name]; 2915e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch }, 2916e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch 2917591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch getStateAfter: function(line, precise) { 2918926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = this.doc; 2919926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); 2920591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return getStateBefore(this, line + 1, precise); 29215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 29225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cursorCoords: function(start, mode) { 2924926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var pos, sel = this.doc.sel; 2925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (start == null) pos = sel.head; 2926926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (typeof start == "object") pos = clipPos(this.doc, start); 29275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else pos = start ? sel.from : sel.to; 29285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return cursorCoords(this, pos, mode || "page"); 29295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 29305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) charCoords: function(pos, mode) { 2932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return charCoords(this, clipPos(this.doc, pos), mode || "page"); 29335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 29345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2935926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) coordsChar: function(coords, mode) { 2936926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) coords = fromCoordSystem(this, coords, mode || "page"); 2937926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return coordsChar(this, coords.left, coords.top); 29385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 29395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) lineAtHeight: function(height, mode) { 29415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; 29425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return lineAtHeight(this.doc, height + this.display.viewOffset); 29435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) }, 2944591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch heightAtLine: function(line, mode) { 2945591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var end = false, last = this.doc.first + this.doc.size - 1; 2946591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (line < this.doc.first) line = this.doc.first; 2947591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch else if (line > last) { line = last; end = true; } 2948591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var lineObj = getLine(this.doc, line); 2949591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return intoCoordSystem(this, getLine(this.doc, line), {top: 0, left: 0}, mode || "page").top + 2950591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch (end ? lineObj.height : 0); 2951591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch }, 29525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 29535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) defaultTextHeight: function() { return textHeight(this.display); }, 2954926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) defaultCharWidth: function() { return charWidth(this.display); }, 29555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setGutterMarker: operation(null, function(line, gutterID, value) { 29575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return changeLine(this, line, function(line) { 29585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var markers = line.gutterMarkers || (line.gutterMarkers = {}); 29595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) markers[gutterID] = value; 29605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!value && isEmpty(markers)) line.gutterMarkers = null; 29615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 29625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 29635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 29645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clearGutter: operation(null, function(gutterID) { 2966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var cm = this, doc = cm.doc, i = doc.first; 2967926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.iter(function(line) { 29685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (line.gutterMarkers && line.gutterMarkers[gutterID]) { 29695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) line.gutterMarkers[gutterID] = null; 29705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) regChange(cm, i, i + 1); 29715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null; 29725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 29735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++i; 29745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 29755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 29765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) addLineClass: operation(null, function(handle, where, cls) { 29785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return changeLine(this, handle, function(line) { 29795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass"; 29805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!line[prop]) line[prop] = cls; 2981591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false; 29825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else line[prop] += " " + cls; 29835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 29845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 29855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 29865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) removeLineClass: operation(null, function(handle, where, cls) { 29885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return changeLine(this, handle, function(line) { 29895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass"; 29905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cur = line[prop]; 29915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!cur) return false; 29925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (cls == null) line[prop] = null; 29935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 2994591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)")); 2995591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!found) return false; 2996591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var end = found.index + found[0].length; 2997591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; 29985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 29995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 30005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 30015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 30025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3003926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) addLineWidget: operation(null, function(handle, node, options) { 3004926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return addLineWidget(this, handle, node, options); 30055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 30065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3007926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removeLineWidget: function(widget) { widget.clear(); }, 30085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 30095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lineInfo: function(line) { 30105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (typeof line == "number") { 3011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!isLine(this.doc, line)) return null; 30125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var n = line; 3013926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) line = getLine(this.doc, line); 30145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!line) return null; 30155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 30165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var n = lineNo(line); 30175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (n == null) return null; 30185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 30195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, 30205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, 30215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) widgets: line.widgets}; 30225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 30235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 30245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};}, 30255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 30265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) addWidget: function(pos, node, scroll, vert, horiz) { 30275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var display = this.display; 3028926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos = cursorCoords(this, clipPos(this.doc, pos)); 3029926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var top = pos.bottom, left = pos.left; 30305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) node.style.position = "absolute"; 30315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display.sizer.appendChild(node); 3032926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (vert == "over") { 3033926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) top = pos.top; 3034926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (vert == "above" || vert == "near") { 3035926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), 30365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); 3037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Default to positioning above (if specified and possible); otherwise default to positioning below 3038926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) 30395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) top = pos.top - node.offsetHeight; 3040926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (pos.bottom + node.offsetHeight <= vspace) 3041926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) top = pos.bottom; 30425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (left + node.offsetWidth > hspace) 30435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left = hspace - node.offsetWidth; 30445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 30455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) node.style.top = top + "px"; 30465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) node.style.left = node.style.right = ""; 30475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (horiz == "right") { 30485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left = display.sizer.clientWidth - node.offsetWidth; 30495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) node.style.right = "0px"; 30505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 30515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (horiz == "left") left = 0; 30525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2; 30535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) node.style.left = left + "px"; 30545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 30555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (scroll) 3056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight); 30575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 30585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 30595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triggerOnKeyDown: operation(null, onKeyDown), 30605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 30615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) execCommand: function(cmd) {return commands[cmd](this);}, 30625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3063926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) findPosH: function(from, amount, unit, visually) { 3064926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var dir = 1; 3065926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (amount < 0) { dir = -1; amount = -amount; } 3066926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { 3067926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cur = findPosH(this.doc, cur, dir, unit, visually); 3068926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cur.hitSide) break; 3069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 3070926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return cur; 3071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 3072926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 30735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) moveH: operation(null, function(dir, unit) { 3074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sel = this.doc.sel, pos; 3075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (sel.shift || sel.extend || posEq(sel.from, sel.to)) 3076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually); 3077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else 3078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos = dir < 0 ? sel.from : sel.to; 3079926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) extendSelection(this.doc, pos, pos, dir); 30805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 30815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 30825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deleteH: operation(null, function(dir, unit) { 3083926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sel = this.doc.sel; 3084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete"); 3085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else replaceRange(this.doc, "", sel.from, findPosH(this.doc, sel.head, dir, unit, false), "+delete"); 30865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.curOp.userSelChange = true; 30875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 30885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3089926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) findPosV: function(from, amount, unit, goalColumn) { 3090926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var dir = 1, x = goalColumn; 3091926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (amount < 0) { dir = -1; amount = -amount; } 3092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { 3093926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var coords = cursorCoords(this, cur, "div"); 3094926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (x == null) x = coords.left; 3095926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else coords.left = x; 3096926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cur = findPosV(this, coords, dir, unit); 3097926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cur.hitSide) break; 30985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3099926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return cur; 3100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 31015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) moveV: operation(null, function(dir, unit) { 3103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sel = this.doc.sel; 3104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var pos = cursorCoords(this, sel.head, "div"); 3105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (sel.goalColumn != null) pos.left = sel.goalColumn; 3106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var target = findPosV(this, pos, dir, unit); 3107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top); 3109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) extendSelection(this.doc, target, target, dir); 3110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sel.goalColumn = pos.left; 31115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }), 31125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 311393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) toggleOverwrite: function(value) { 311493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (value != null && value == this.state.overwrite) return; 3115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (this.state.overwrite = !this.state.overwrite) 31165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.display.cursor.className += " CodeMirror-overwrite"; 31175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 31185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", ""); 31195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 3120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) hasFocus: function() { return this.state.focused; }, 31215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) scrollTo: operation(null, function(x, y) { 3123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateScrollPos(this, x, y); 3124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }), 31255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getScrollInfo: function() { 31265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var scroller = this.display.scroller, co = scrollerCutOff; 31275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return {left: scroller.scrollLeft, top: scroller.scrollTop, 31285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) height: scroller.scrollHeight - co, width: scroller.scrollWidth - co, 31295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co}; 31305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 31315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 313253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) scrollIntoView: operation(null, function(pos, margin) { 3133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (typeof pos == "number") pos = Pos(pos, 0); 313453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!margin) margin = 0; 313553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var coords = pos; 313653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 3137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!pos || pos.line != null) { 313853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head; 313953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) this.curOp.scrollToPosMargin = margin; 314053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) coords = cursorCoords(this, this.curOp.scrollToPos); 3141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 314253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin); 314353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop); 314453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) }), 31455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3146f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) setSize: operation(null, function(width, height) { 31475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function interpret(val) { 31485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; 31495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 31505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (width != null) this.display.wrapper.style.width = interpret(width); 31515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (height != null) this.display.wrapper.style.height = interpret(height); 3152f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (this.options.lineWrapping) 3153f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) this.display.measureLineCache.length = this.display.measureLineCachePos = 0; 3154f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) this.curOp.forceUpdate = true; 3155f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) }), 31565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) operation: function(f){return runInOp(this, f);}, 31585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) refresh: operation(null, function() { 3160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) clearCaches(this); 3161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop); 3162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) regChange(this); 3163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }), 3164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) swapDoc: operation(null, function(doc) { 3166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var old = this.doc; 3167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) old.cm = null; 3168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) attachDoc(this, doc); 3169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) clearCaches(this); 317053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) resetInput(this, true); 3171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateScrollPos(this, doc.scrollLeft, doc.scrollTop); 3172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return old; 3173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }), 31745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getInputField: function(){return this.display.input;}, 31765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getWrapperElement: function(){return this.display.wrapper;}, 31775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getScrollerElement: function(){return this.display.scroller;}, 31785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getGutterElement: function(){return this.display.gutters;} 31795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 3180e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch eventMixin(CodeMirror); 31815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // OPTION DEFAULTS 31835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var optionHandlers = CodeMirror.optionHandlers = {}; 31855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The default configuration options. 31875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var defaults = CodeMirror.defaults = {}; 31885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function option(name, deflt, handle, notOnInit) { 31905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.defaults[name] = deflt; 31915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (handle) optionHandlers[name] = 31925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle; 31935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 31945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}}; 31965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // These two are, on init, called from the constructor because they 31985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // have to be initialized before the editor can start at all. 3199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) option("value", "", function(cm, val) { 3200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.setValue(val); 3201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, true); 3202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) option("mode", null, function(cm, val) { 3203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.doc.modeOption = val; 3204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) loadMode(cm); 3205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, true); 32065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("indentUnit", 2, loadMode, true); 32085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("indentWithTabs", false); 32095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("smartIndent", true); 3210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) option("tabSize", 4, function(cm) { 3211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) loadMode(cm); 3212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) clearCaches(cm); 3213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) regChange(cm); 3214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, true); 32155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("electricChars", true); 3216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) option("rtlMoveVisually", !windows); 32175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) option("theme", "default", function(cm) { 32195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) themeChanged(cm); 3220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) guttersChanged(cm); 3221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, true); 32225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("keyMap", "default", keyMapChanged); 32235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("extraKeys", null); 32245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("onKeyEvent", null); 32265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("onDragEvent", null); 32275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) option("lineWrapping", false, wrappingChanged, true); 32295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("gutters", [], function(cm) { 32305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setGuttersForLineNumbers(cm.options); 32315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) guttersChanged(cm); 32325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, true); 3233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) option("fixedGutter", true, function(cm, val) { 3234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; 3235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.refresh(); 3236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, true); 323793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) option("coverGutterNextToScrollbar", false, updateScrollbars, true); 32385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("lineNumbers", false, function(cm) { 32395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setGuttersForLineNumbers(cm.options); 32405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) guttersChanged(cm); 32415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, true); 3242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) option("firstLineNumber", 1, guttersChanged, true); 3243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true); 3244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) option("showCursorWhenSelecting", false, updateSelection, true); 3245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 32465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("readOnly", false, function(cm, val) { 32475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (val == "nocursor") {onBlur(cm); cm.display.input.blur();} 32485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (!val) resetInput(cm, true); 32495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 32505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("dragDrop", true); 32515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("cursorBlinkRate", 530); 325393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) option("cursorScrollMargin", 0); 32545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("cursorHeight", 1); 32555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("workTime", 100); 32565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("workDelay", 100); 32575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("flattenSpans", true); 32585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("pollInterval", 100); 3259926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;}); 326053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) option("historyEventDelay", 500); 32615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("viewportMargin", 10, function(cm){cm.refresh();}, true); 326253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true); 326353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) option("moveInputWithCursor", true, function(cm, val) { 326453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0; 326553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) }); 32665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("tabindex", null, function(cm, val) { 32685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.display.input.tabIndex = val || ""; 32695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 32705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) option("autofocus", null); 32715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // MODE DEFINITION AND QUERYING 32735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Known modes, by name and by MIME 32755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; 32765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.defineMode = function(name, mode) { 32785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; 32795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (arguments.length > 2) { 32805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mode.dependencies = []; 32815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]); 32825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 32835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) modes[name] = mode; 32845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 32855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.defineMIME = function(mime, spec) { 32875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mimeModes[mime] = spec; 32885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 32895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.resolveMode = function(spec) { 329193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { 32925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) spec = mimeModes[spec]; 329393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { 329493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var found = mimeModes[spec.name]; 329593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) spec = createObj(found, spec); 329693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) spec.name = found.name; 329793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { 32985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return CodeMirror.resolveMode("application/xml"); 329993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 33005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (typeof spec == "string") return {name: spec}; 33015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else return spec || {name: "null"}; 33025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 33035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.getMode = function(options, spec) { 3305e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var spec = CodeMirror.resolveMode(spec); 33065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var mfactory = modes[spec.name]; 33075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!mfactory) return CodeMirror.getMode(options, "text/plain"); 33085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var modeObj = mfactory(options, spec); 33095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (modeExtensions.hasOwnProperty(spec.name)) { 33105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var exts = modeExtensions[spec.name]; 3311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var prop in exts) { 3312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!exts.hasOwnProperty(prop)) continue; 3313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop]; 3314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) modeObj[prop] = exts[prop]; 3315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 33165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 33175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) modeObj.name = spec.name; 3318e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch 33195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return modeObj; 33205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 33215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.defineMode("null", function() { 33235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return {token: function(stream) {stream.skipToEnd();}}; 33245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 33255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.defineMIME("text/plain", "null"); 33265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var modeExtensions = CodeMirror.modeExtensions = {}; 33285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.extendMode = function(mode, properties) { 33295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); 3330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) copyObj(properties, exts); 33315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 33325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // EXTENSIONS 33345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.defineExtension = function(name, func) { 33365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.prototype[name] = func; 33375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 333853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) CodeMirror.defineDocExtension = function(name, func) { 333953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) Doc.prototype[name] = func; 334053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) }; 33415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.defineOption = option; 33425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var initHooks = []; 33445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.defineInitHook = function(f) {initHooks.push(f);}; 33455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3346e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var helpers = CodeMirror.helpers = {}; 3347e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch CodeMirror.registerHelper = function(type, name, value) { 3348e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {}; 3349e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch helpers[type][name] = value; 3350e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch }; 3351e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch 3352e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch // UTILITIES 3353e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch 3354e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch CodeMirror.isWordChar = isWordChar; 3355e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch 33565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // MODE STATE HANDLING 33575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Utility functions for working with state. Exported because modes 33595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // sometimes need to do this. 33605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function copyState(mode, state) { 33615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (state === true) return state; 33625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (mode.copyState) return mode.copyState(state); 33635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var nstate = {}; 33645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var n in state) { 33655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var val = state[n]; 33665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (val instanceof Array) val = val.concat([]); 33675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) nstate[n] = val; 33685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 33695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return nstate; 33705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 33715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.copyState = copyState; 33725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function startState(mode, a1, a2) { 33745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return mode.startState ? mode.startState(a1, a2) : true; 33755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 33765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.startState = startState; 33775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.innerMode = function(mode, state) { 33795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (mode.innerMode) { 33805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var info = mode.innerMode(state); 3381f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (!info || info.mode == mode) break; 33825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) state = info.state; 33835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mode = info.mode; 33845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 33855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return info || {mode: mode, state: state}; 33865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 33875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // STANDARD COMMANDS 33895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var commands = CodeMirror.commands = { 3391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));}, 33925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) killLine: function(cm) { 33935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to); 33945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sel && cm.getLine(from.line).length == from.ch) 3395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete"); 3396926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete"); 3397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 3398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) deleteLine: function(cm) { 3399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var l = cm.getCursor().line; 3400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.replaceRange("", Pos(l, 0), Pos(l), "+delete"); 34015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 3402591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch delLineLeft: function(cm) { 3403591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var cur = cm.getCursor(); 3404591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch cm.replaceRange("", Pos(cur.line, 0), cur, "+delete"); 3405591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch }, 34065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) undo: function(cm) {cm.undo();}, 34075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) redo: function(cm) {cm.redo();}, 3408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));}, 3409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));}, 34105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goLineStart: function(cm) { 3411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.extendSelection(lineStart(cm, cm.getCursor().line)); 34125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 34135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goLineStartSmart: function(cm) { 34145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cur = cm.getCursor(), start = lineStart(cm, cur.line); 34155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var line = cm.getLineHandle(start.line); 34165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var order = getOrder(line); 34175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!order || order[0].level == 0) { 34185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var firstNonWS = Math.max(0, line.text.search(/\S/)); 34195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch; 3420926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS)); 3421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else cm.extendSelection(start); 34225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 34235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goLineEnd: function(cm) { 3424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.extendSelection(lineEnd(cm, cm.getCursor().line)); 3425926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 3426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) goLineRight: function(cm) { 3427926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var top = cm.charCoords(cm.getCursor(), "div").top + 5; 3428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.extendSelection(cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div")); 3429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 3430926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) goLineLeft: function(cm) { 3431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var top = cm.charCoords(cm.getCursor(), "div").top + 5; 3432926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.extendSelection(cm.coordsChar({left: 0, top: top}, "div")); 34335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 34345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goLineUp: function(cm) {cm.moveV(-1, "line");}, 34355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goLineDown: function(cm) {cm.moveV(1, "line");}, 34365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goPageUp: function(cm) {cm.moveV(-1, "page");}, 34375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goPageDown: function(cm) {cm.moveV(1, "page");}, 34385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goCharLeft: function(cm) {cm.moveH(-1, "char");}, 34395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goCharRight: function(cm) {cm.moveH(1, "char");}, 34405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goColumnLeft: function(cm) {cm.moveH(-1, "column");}, 34415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goColumnRight: function(cm) {cm.moveH(1, "column");}, 34425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goWordLeft: function(cm) {cm.moveH(-1, "word");}, 3443926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) goGroupRight: function(cm) {cm.moveH(1, "group");}, 3444926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) goGroupLeft: function(cm) {cm.moveH(-1, "group");}, 34455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goWordRight: function(cm) {cm.moveH(1, "word");}, 34465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) delCharBefore: function(cm) {cm.deleteH(-1, "char");}, 34475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) delCharAfter: function(cm) {cm.deleteH(1, "char");}, 34485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) delWordBefore: function(cm) {cm.deleteH(-1, "word");}, 34495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) delWordAfter: function(cm) {cm.deleteH(1, "word");}, 3450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) delGroupBefore: function(cm) {cm.deleteH(-1, "group");}, 3451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) delGroupAfter: function(cm) {cm.deleteH(1, "group");}, 34525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) indentAuto: function(cm) {cm.indentSelection("smart");}, 34535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) indentMore: function(cm) {cm.indentSelection("add");}, 34545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) indentLess: function(cm) {cm.indentSelection("subtract");}, 3455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");}, 34565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) defaultTab: function(cm) { 34575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cm.somethingSelected()) cm.indentSelection("add"); 3458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else cm.replaceSelection("\t", "end", "+input"); 34595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 34605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) transposeChars: function(cm) { 34615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cur = cm.getCursor(), line = cm.getLine(cur.line); 34625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cur.ch > 0 && cur.ch < line.length - 1) 34635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1), 3464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1)); 34655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 34665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newlineAndIndent: function(cm) { 3467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) operation(cm, function() { 3468926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.replaceSelection("\n", "end", "+input"); 3469926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.indentLine(cm.getCursor().line, null, true); 3470926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) })(); 34715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 34725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) toggleOverwrite: function(cm) {cm.toggleOverwrite();} 34735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 34745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 34755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // STANDARD KEYMAPS 34765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 34775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var keyMap = CodeMirror.keyMap = {}; 34785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) keyMap.basic = { 34795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", 34805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", 34815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto", 34825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Enter": "newlineAndIndent", "Insert": "toggleOverwrite" 34835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 34845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Note that the save and find-related commands aren't defined by 34855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // default. Unknown commands are simply ignored. 34865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) keyMap.pcDefault = { 34875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", 34885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd", 3489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", 3490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", 34915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", 34925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", 34935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fallthrough: "basic" 34945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 34955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) keyMap.macDefault = { 34965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", 3497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", 3498926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore", 3499926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", 35005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", 3501591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft", 35025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fallthrough: ["basic", "emacsy"] 35035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 35045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; 35055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) keyMap.emacsy = { 35065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", 35075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", 3508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", 35095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars" 35105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 35115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // KEYMAP DISPATCH 35135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function getKeyMap(val) { 35155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (typeof val == "string") return keyMap[val]; 35165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else return val; 35175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 35185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3519926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function lookupKey(name, maps, handle) { 35205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function lookup(map) { 35215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) map = getKeyMap(map); 35225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var found = map[name]; 3523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (found === false) return "stop"; 35245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (found != null && handle(found)) return true; 3525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (map.nofallthrough) return "stop"; 3526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 35275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var fallthrough = map.fallthrough; 35285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (fallthrough == null) return false; 35295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (Object.prototype.toString.call(fallthrough) != "[object Array]") 35305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return lookup(fallthrough); 35315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, e = fallthrough.length; i < e; ++i) { 3532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var done = lookup(fallthrough[i]); 3533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (done) return done; 35345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 35355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 35365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < maps.length; ++i) { 3539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var done = lookup(maps[i]); 35405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (done) return done != "stop"; 3541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 35425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 35435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function isModifierKey(event) { 3544926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var name = keyNames[event.keyCode]; 35455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; 35465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3547926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function keyName(event, noShift) { 354853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (opera && event.keyCode == 34 && event["char"]) return false; 3549926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var name = keyNames[event.keyCode]; 3550926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (name == null || event.altGraphKey) return false; 3551926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (event.altKey) name = "Alt-" + name; 3552926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name; 3553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name; 3554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!noShift && event.shiftKey) name = "Shift-" + name; 3555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return name; 3556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 3557926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) CodeMirror.lookupKey = lookupKey; 35585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.isModifierKey = isModifierKey; 3559926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) CodeMirror.keyName = keyName; 35605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FROMTEXTAREA 35625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.fromTextArea = function(textarea, options) { 35645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!options) options = {}; 35655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) options.value = textarea.value; 35665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!options.tabindex && textarea.tabindex) 35675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) options.tabindex = textarea.tabindex; 3568926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!options.placeholder && textarea.placeholder) 3569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) options.placeholder = textarea.placeholder; 35705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Set autofocus to true if this textarea is focused, or if it has 35715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // autofocus and no other element is focused. 35725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (options.autofocus == null) { 35735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var hasFocus = document.body; 35745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // doc.activeElement occasionally throws on IE 35755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try { hasFocus = document.activeElement; } catch(e) {} 35765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) options.autofocus = hasFocus == textarea || 35775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) textarea.getAttribute("autofocus") != null && hasFocus == document.body; 35785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 35795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function save() {textarea.value = cm.getValue();} 35815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (textarea.form) { 35825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) on(textarea.form, "submit", save); 3583926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Deplorable hack to make the submit method do the right thing. 3584926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!options.leaveSubmitMethodAlone) { 3585926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var form = textarea.form, realSubmit = form.submit; 3586926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) try { 3587926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var wrappedSubmit = form.submit = function() { 3588926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) save(); 3589926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) form.submit = realSubmit; 3590926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) form.submit(); 3591926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) form.submit = wrappedSubmit; 3592926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 3593926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } catch(e) {} 35945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 35955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 35965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) textarea.style.display = "none"; 35985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cm = CodeMirror(function(node) { 35995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) textarea.parentNode.insertBefore(node, textarea.nextSibling); 36005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, options); 36015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.save = save; 36025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.getTextArea = function() { return textarea; }; 36035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cm.toTextArea = function() { 36045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) save(); 36055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) textarea.parentNode.removeChild(cm.getWrapperElement()); 36065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) textarea.style.display = ""; 36075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (textarea.form) { 36085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) off(textarea.form, "submit", save); 36095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (typeof textarea.form.submit == "function") 36105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) textarea.form.submit = realSubmit; 36115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 36125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 36135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return cm; 36145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 36155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 36165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // STRING STREAM 36175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 36185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Fed to the mode parsers, provides helper functions to make 36195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // parsers more succinct. 36205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 36215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The character stream used by a mode's parser. 36225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function StringStream(string, tabSize) { 36235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.pos = this.start = 0; 36245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.string = string; 36255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.tabSize = tabSize || 8; 3626926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.lastColumnPos = this.lastColumnValue = 0; 36275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 36285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 36295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) StringStream.prototype = { 36305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) eol: function() {return this.pos >= this.string.length;}, 36315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sol: function() {return this.pos == 0;}, 36325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) peek: function() {return this.string.charAt(this.pos) || undefined;}, 36335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) next: function() { 36345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (this.pos < this.string.length) 36355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return this.string.charAt(this.pos++); 36365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 36375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) eat: function(match) { 36385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var ch = this.string.charAt(this.pos); 36395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (typeof match == "string") var ok = ch == match; 36405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else var ok = ch && (match.test ? match.test(ch) : match(ch)); 36415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ok) {++this.pos; return ch;} 36425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 36435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) eatWhile: function(match) { 36445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var start = this.pos; 36455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (this.eat(match)){} 36465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return this.pos > start; 36475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 36485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) eatSpace: function() { 36495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var start = this.pos; 36505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; 36515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return this.pos > start; 36525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 36535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipToEnd: function() {this.pos = this.string.length;}, 36545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipTo: function(ch) { 36555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var found = this.string.indexOf(ch, this.pos); 36565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (found > -1) {this.pos = found; return true;} 36575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 36585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) backUp: function(n) {this.pos -= n;}, 3659926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) column: function() { 3660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (this.lastColumnPos < this.start) { 3661926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); 3662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.lastColumnPos = this.start; 3663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 3664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return this.lastColumnValue; 3665926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 36665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) indentation: function() {return countColumn(this.string, null, this.tabSize);}, 36675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) match: function(pattern, consume, caseInsensitive) { 36685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (typeof pattern == "string") { 36695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; 3670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var substr = this.string.substr(this.pos, pattern.length); 3671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cased(substr) == cased(pattern)) { 36725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (consume !== false) this.pos += pattern.length; 36735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 36745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 36755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 36765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var match = this.string.slice(this.pos).match(pattern); 36775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (match && match.index > 0) return null; 36785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (match && consume !== false) this.pos += match[0].length; 36795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return match; 36805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 36815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 36825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) current: function(){return this.string.slice(this.start, this.pos);} 36835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 36845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.StringStream = StringStream; 36855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 36865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // TEXTMARKERS 36875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function TextMarker(doc, type) { 36895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.lines = []; 36905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.type = type; 3691926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.doc = doc; 36925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) CodeMirror.TextMarker = TextMarker; 3694e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch eventMixin(TextMarker); 36955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 36965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) TextMarker.prototype.clear = function() { 36975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (this.explicitlyCleared) return; 3698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var cm = this.doc.cm, withOp = cm && !cm.curOp; 3699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (withOp) startOperation(cm); 3700f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (hasHandler(this, "clear")) { 3701f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) var found = this.find(); 3702f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (found) signalLater(this, "clear", found.from, found.to); 3703f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) } 37045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var min = null, max = null; 37055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < this.lines.length; ++i) { 37065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var line = this.lines[i]; 37075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var span = getMarkedSpanFor(line.markedSpans, this); 37085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (span.to != null) max = lineNo(line); 37095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) line.markedSpans = removeMarkedSpan(line.markedSpans, span); 37105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (span.from != null) 37115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) min = lineNo(line); 3712926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (this.collapsed && !lineIsHidden(this.doc, line) && cm) 3713926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateLineHeight(line, textHeight(cm.display)); 3714926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 3715926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) { 3716926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual); 3717926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (len > cm.display.maxLineLength) { 3718926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.maxLine = visual; 3719926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.maxLineLength = len; 3720926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.display.maxLineChanged = true; 3721926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 37225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3723926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (min != null && cm) regChange(cm, min, max + 1); 37255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.lines.length = 0; 37265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.explicitlyCleared = true; 37275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (this.atomic && this.doc.cantEdit) { 3728926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.doc.cantEdit = false; 3729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm) reCheckSelection(cm); 37305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (withOp) endOperation(cm); 37325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 37335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 37345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) TextMarker.prototype.find = function() { 37355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var from, to; 37365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < this.lines.length; ++i) { 37375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var line = this.lines[i]; 37385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var span = getMarkedSpanFor(line.markedSpans, this); 37395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (span.from != null || span.to != null) { 37405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var found = lineNo(line); 3741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (span.from != null) from = Pos(found, span.from); 3742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (span.to != null) to = Pos(found, span.to); 37435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 37445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 37455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (this.type == "bookmark") return from; 37465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return from && {from: from, to: to}; 37475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 37485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 374993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) TextMarker.prototype.changed = function() { 375093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var pos = this.find(), cm = this.doc.cm; 375193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (!pos || !cm) return; 3752f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (this.type != "bookmark") pos = pos.from; 3753f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) var line = getLine(this.doc, pos.line); 375493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) clearCachedMeasurement(cm, line); 3755f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (pos.line >= cm.display.showingFrom && pos.line < cm.display.showingTo) { 375693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) { 375793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight); 375893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) break; 375993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 3760f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) runInOp(cm, function() { 3761f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true; 3762f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) }); 376393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 3764926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 3765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) TextMarker.prototype.attachLine = function(line) { 3767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!this.lines.length && this.doc.cm) { 3768926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var op = this.doc.cm.curOp; 3769926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) 3770926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); 3771926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 3772926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.lines.push(line); 3773926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 3774926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) TextMarker.prototype.detachLine = function(line) { 3775926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.lines.splice(indexOf(this.lines, line), 1); 3776926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!this.lines.length && this.doc.cm) { 3777926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var op = this.doc.cm.curOp; 3778926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); 3779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 3780926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 3781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3782926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function markText(doc, from, to, options, type) { 3783926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (options && options.shared) return markTextShared(doc, from, to, options, type); 3784926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type); 3785926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3786926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var marker = new TextMarker(doc, type); 37875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (type == "range" && !posLess(from, to)) return marker; 3788926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (options) copyObj(options, marker); 37895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (marker.replacedWith) { 37905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) marker.collapsed = true; 37915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget"); 37925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true; 37935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 37945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (marker.collapsed) sawCollapsedSpans = true; 37955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 379653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (marker.addToHistory) 379753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) addToHistory(doc, {from: from, to: to, origin: "markText"}, 379853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) {head: doc.sel.head, anchor: doc.sel.anchor}, NaN); 379953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 3800926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine; 38015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) doc.iter(curLine, to.line + 1, function(line) { 3802926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine) 3803926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateMaxLine = true; 38045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var span = {from: null, to: null, marker: marker}; 38055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size += line.text.length; 38065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (curLine == from.line) {span.from = from.ch; size -= from.ch;} 38075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;} 38085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (marker.collapsed) { 38095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch); 38105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch); 38115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else updateLineHeight(line, 0); 38125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 38135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) addMarkedSpan(line, span); 38145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++curLine; 38155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 3816926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) { 3817926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (lineIsHidden(doc, line)) updateLineHeight(line, 0); 3818926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 38195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 382053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); }); 382153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 38225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (marker.readOnly) { 38235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sawReadOnlySpans = true; 3824926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.history.done.length || doc.history.undone.length) 3825926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.clearHistory(); 38265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 38275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (marker.collapsed) { 38285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (collapsedAtStart != collapsedAtEnd) 38295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) throw new Error("Inserting collapsed marker overlapping an existing one"); 38305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) marker.size = size; 38315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) marker.atomic = true; 38325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3833926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cm) { 3834926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (updateMaxLine) cm.curOp.updateMaxLine = true; 3835e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed) 3836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) regChange(cm, from.line, to.line + 1); 3837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (marker.atomic) reCheckSelection(cm); 3838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 38395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return marker; 38405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 38415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3842926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // SHARED TEXTMARKERS 3843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function SharedTextMarker(markers, primary) { 3845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.markers = markers; 3846926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.primary = primary; 3847926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, me = this; i < markers.length; ++i) { 3848926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) markers[i].parent = this; 3849926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) on(markers[i], "clear", function(){me.clear();}); 3850926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 3851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 3852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) CodeMirror.SharedTextMarker = SharedTextMarker; 3853e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch eventMixin(SharedTextMarker); 3854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) SharedTextMarker.prototype.clear = function() { 3856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (this.explicitlyCleared) return; 3857926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.explicitlyCleared = true; 3858926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < this.markers.length; ++i) 3859926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.markers[i].clear(); 3860926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) signalLater(this, "clear"); 3861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 3862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) SharedTextMarker.prototype.find = function() { 3863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return this.primary.find(); 3864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 3865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3866926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function markTextShared(doc, from, to, options, type) { 3867926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) options = copyObj(options); 3868926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) options.shared = false; 3869926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var markers = [markText(doc, from, to, options, type)], primary = markers[0]; 3870926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var widget = options.replacedWith; 3871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) linkedDocs(doc, function(doc) { 3872926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (widget) options.replacedWith = widget.cloneNode(true); 3873926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); 3874926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < doc.linked.length; ++i) 3875926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.linked[i].isParent) return; 3876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) primary = lst(markers); 3877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 3878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return new SharedTextMarker(markers, primary); 3879926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 3880926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 38815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // TEXTMARKER SPANS 38825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 38835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function getMarkedSpanFor(spans, marker) { 38845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (spans) for (var i = 0; i < spans.length; ++i) { 38855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var span = spans[i]; 38865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (span.marker == marker) return span; 38875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 38885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 38895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function removeMarkedSpan(spans, span) { 38905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var r, i = 0; i < spans.length; ++i) 38915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (spans[i] != span) (r || (r = [])).push(spans[i]); 38925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return r; 38935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 38945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function addMarkedSpan(line, span) { 38955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; 3896926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) span.marker.attachLine(line); 38975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 38985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function markedSpansBefore(old, startCh, isInsert) { 39005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (old) for (var i = 0, nw; i < old.length; ++i) { 39015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var span = old[i], marker = span.marker; 39025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); 3903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) { 39045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); 39055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (nw || (nw = [])).push({from: span.from, 39065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) to: endsAfter ? null : span.to, 39075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) marker: marker}); 39085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return nw; 39115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function markedSpansAfter(old, endCh, isInsert) { 39145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (old) for (var i = 0, nw; i < old.length; ++i) { 39155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var span = old[i], marker = span.marker; 39165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); 3917926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) { 39185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); 39195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh, 39205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) to: span.to == null ? null : span.to - endCh, 39215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) marker: marker}); 39225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return nw; 39255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function stretchSpansOverChange(doc, change) { 3928926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; 3929926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; 3930926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!oldFirst && !oldLast) return null; 3931926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to); 39335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Get the spans that 'stick out' on both sides 3934926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var first = markedSpansBefore(oldFirst, startCh, isInsert); 3935926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var last = markedSpansAfter(oldLast, endCh, isInsert); 39365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 39375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Next, merge those two ends 3938926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); 39395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (first) { 39405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Fix up .to properties of first 39415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < first.length; ++i) { 39425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var span = first[i]; 39435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (span.to == null) { 39445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var found = getMarkedSpanFor(last, span.marker); 39455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!found) span.to = startCh; 39465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (sameLine) span.to = found.to == null ? null : found.to + offset; 39475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (last) { 39515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Fix up .from in last (or move them into first in case of sameLine) 39525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < last.length; ++i) { 39535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var span = last[i]; 39545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (span.to != null) span.to += offset; 39555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (span.from == null) { 39565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var found = getMarkedSpanFor(first, span.marker); 39575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!found) { 39585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) span.from = offset; 39595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sameLine) (first || (first = [])).push(span); 39605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 39625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) span.from += offset; 39635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sameLine) (first || (first = [])).push(span); 39645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (sameLine && first) { 39685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // Make sure we didn't create any zero-length spans 39695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) for (var i = 0; i < first.length; ++i) 39705267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (first[i].from != null && first[i].from == first[i].to && first[i].marker.type != "bookmark") 39715267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) first.splice(i--, 1); 39725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!first.length) first = null; 39735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 39745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3975926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var newMarkers = [first]; 39765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sameLine) { 39775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Fill gap with whole-line-spans 3978926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var gap = change.text.length - 2, gapMarkers; 39795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (gap > 0 && first) 39805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < first.length; ++i) 39815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (first[i].to == null) 39825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker}); 39835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < gap; ++i) 3984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) newMarkers.push(gapMarkers); 3985926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) newMarkers.push(last); 39865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return newMarkers; 39885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 39895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function mergeOldSpans(doc, change) { 3991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var old = getOldSpans(doc, change); 3992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var stretched = stretchSpansOverChange(doc, change); 3993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!old) return stretched; 3994926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!stretched) return old; 3995926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 3996926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < old.length; ++i) { 3997926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var oldCur = old[i], stretchCur = stretched[i]; 3998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (oldCur && stretchCur) { 3999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) spans: for (var j = 0; j < stretchCur.length; ++j) { 4000926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var span = stretchCur[j]; 4001926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var k = 0; k < oldCur.length; ++k) 4002926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (oldCur[k].marker == span.marker) continue spans; 4003926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) oldCur.push(span); 4004926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4005926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (stretchCur) { 4006926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) old[i] = stretchCur; 4007926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4008926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return old; 4010926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 40125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function removeReadOnlyRanges(doc, from, to) { 40135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var markers = null; 40145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) doc.iter(from.line, to.line + 1, function(line) { 40155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) { 40165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var mark = line.markedSpans[i].marker; 40175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) 40185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (markers || (markers = [])).push(mark); 40195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 40205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }); 40215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!markers) return null; 40225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var parts = [{from: from, to: to}]; 40235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < markers.length; ++i) { 4024926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var mk = markers[i], m = mk.find(); 40255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var j = 0; j < parts.length; ++j) { 40265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var p = parts[j]; 4027926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue; 40285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var newParts = [j, 1]; 4029926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from)) 4030926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) newParts.push({from: p.from, to: m.from}); 4031926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to)) 4032926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) newParts.push({from: m.to, to: p.to}); 40335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) parts.splice.apply(parts, newParts); 40345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) j += newParts.length - 1; 40355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 40365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 40375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return parts; 40385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 40395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 40405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function collapsedSpanAt(line, ch) { 40415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var sps = sawCollapsedSpans && line.markedSpans, found; 40425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sps) for (var sp, i = 0; i < sps.length; ++i) { 40435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sp = sps[i]; 40445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sp.marker.collapsed) continue; 40455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((sp.from == null || sp.from < ch) && 40465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (sp.to == null || sp.to > ch) && 40475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (!found || found.width < sp.marker.width)) 40485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) found = sp.marker; 40495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 40505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return found; 40515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 40525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); } 40535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); } 40545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4055926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function visualLine(doc, line) { 4056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var merged; 4057926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) while (merged = collapsedSpanAtStart(line)) 4058926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) line = getLine(doc, merged.find().from.line); 4059926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return line; 4060926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4061926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4062926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function lineIsHidden(doc, line) { 40635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var sps = sawCollapsedSpans && line.markedSpans; 40645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sps) for (var sp, i = 0; i < sps.length; ++i) { 40655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sp = sps[i]; 40665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sp.marker.collapsed) continue; 40675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sp.from == null) return true; 40685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (sp.marker.replacedWith) continue; 4069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) 40705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 40715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 40725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4073926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function lineIsHiddenInner(doc, line, span) { 4074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (span.to == null) { 4075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var end = span.marker.find().to, endLine = getLine(doc, end.line); 4076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker)); 4077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (span.marker.inclusiveRight && span.to == line.text.length) 40795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 40805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var sp, i = 0; i < line.markedSpans.length; ++i) { 40815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sp = line.markedSpans[i]; 40825267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to && 40835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && 4084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) lineIsHiddenInner(doc, line, sp)) return true; 40855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 40865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 40875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 40885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function detachMarkedSpans(line) { 40895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var spans = line.markedSpans; 40905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!spans) return; 4091926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < spans.length; ++i) 4092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) spans[i].marker.detachLine(line); 40935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) line.markedSpans = null; 40945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 40955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 40965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function attachMarkedSpans(line, spans) { 40975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!spans) return; 40985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < spans.length; ++i) 4099926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) spans[i].marker.attachLine(line); 41005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) line.markedSpans = spans; 41015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 41025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // LINE WIDGETS 4104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var LineWidget = CodeMirror.LineWidget = function(cm, node, options) { 4106e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (options) for (var opt in options) if (options.hasOwnProperty(opt)) 4107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this[opt] = options[opt]; 4108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.cm = cm; 4109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.node = node; 4110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 4111e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch eventMixin(LineWidget); 4112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function widgetOperation(f) { 4113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return function() { 4114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var withOp = !this.cm.curOp; 4115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (withOp) startOperation(this.cm); 4116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) try {var result = f.apply(this, arguments);} 4117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) finally {if (withOp) endOperation(this.cm);} 4118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return result; 4119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 4120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) LineWidget.prototype.clear = widgetOperation(function() { 4122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var ws = this.line.widgets, no = lineNo(this.line); 4123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (no == null || !ws) return; 4124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1); 4125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!ws.length) this.line.widgets = null; 4126e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop; 4127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this))); 4128e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (aboveVisible) addToScrollPos(this.cm, 0, -this.height); 4129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) regChange(this.cm, no, no + 1); 4130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 4131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) LineWidget.prototype.changed = widgetOperation(function() { 4132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var oldH = this.height; 4133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.height = null; 4134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var diff = widgetHeight(this) - oldH; 4135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!diff) return; 4136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateLineHeight(this.line, this.line.height + diff); 4137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var no = lineNo(this.line); 4138926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) regChange(this.cm, no, no + 1); 4139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 4140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function widgetHeight(widget) { 4142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (widget.height != null) return widget.height; 4143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1) 4144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative")); 4145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return widget.height = widget.node.offsetHeight; 4146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function addLineWidget(cm, handle, node, options) { 4149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var widget = new LineWidget(cm, node, options); 4150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (widget.noHScroll) cm.display.alignWidgets = true; 4151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) changeLine(cm, handle, function(line) { 4152e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var widgets = line.widgets || (line.widgets = []); 4153e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (widget.insertAt == null) widgets.push(widget); 4154e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); 4155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) widget.line = line; 4156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) { 4157e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop; 4158926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateLineHeight(line, line.height + widgetHeight(widget)); 4159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (aboveVisible) addToScrollPos(cm, 0, widget.height); 4160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return true; 4162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 4163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return widget; 4164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 41665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // LINE DATA STRUCTURE 41675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 41685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Line objects. These hold state related to a line, including 41695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // highlighting info (the styles array). 4170e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) { 4171e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch this.text = text; 4172e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch attachMarkedSpans(this, markedSpans); 4173e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch this.height = estimateHeight ? estimateHeight(this) : 1; 4174e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch }; 4175e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch eventMixin(Line); 41765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function updateLine(line, text, markedSpans, estimateHeight) { 41785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) line.text = text; 4179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (line.stateAfter) line.stateAfter = null; 4180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (line.styles) line.styles = null; 41815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (line.order != null) line.order = null; 41825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) detachMarkedSpans(line); 41835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) attachMarkedSpans(line, markedSpans); 4184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var estHeight = estimateHeight ? estimateHeight(line) : 1; 4185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (estHeight != line.height) updateLineHeight(line, estHeight); 41865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 41875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 41885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function cleanUpLine(line) { 41895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) line.parent = null; 41905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) detachMarkedSpans(line); 41915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 41925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 41935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Run the given mode's parser over a line, update the styles 41945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // array, which contains alternating fragments of text and CSS 41955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // classes. 4196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function runMode(cm, text, mode, state, f) { 4197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var flattenSpans = mode.flattenSpans; 4198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (flattenSpans == null) flattenSpans = cm.options.flattenSpans; 4199591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var curStart = 0, curStyle = null; 420053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) var stream = new StringStream(text, cm.options.tabSize), style; 4201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (text == "" && mode.blankLine) mode.blankLine(state); 42025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (!stream.eol()) { 420353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (stream.pos > cm.options.maxHighlightLength) { 4204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) flattenSpans = false; 4205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Webkit seems to refuse to render text nodes longer than 57444 characters 4206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) stream.pos = Math.min(text.length, stream.start + 50000); 4207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) style = null; 420853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else { 420953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) style = mode.token(stream, state); 4210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 42115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!flattenSpans || curStyle != style) { 4212591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (curStart < stream.start) f(stream.start, curStyle); 4213591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch curStart = stream.start; curStyle = style; 4214591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 4215591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch stream.start = stream.pos; 42165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4217591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (curStart < stream.pos) f(stream.pos, curStyle); 4218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function highlightLine(cm, line, state) { 4221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // A styles array always starts with a number identifying the 4222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // mode/overlays that it is based on (for easy invalidation). 4223926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var st = [cm.state.modeGen]; 4224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Compute the base array of styles 4225591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);}); 4226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Run overlays, adjust style array. 4228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var o = 0; o < cm.state.overlays.length; ++o) { 4229591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var overlay = cm.state.overlays[o], i = 1, at = 0; 4230591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch runMode(cm, line.text, overlay.mode, true, function(end, style) { 4231591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var start = i; 4232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Ensure there's a token end at the current position, and that i points at it 4233591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch while (at < end) { 4234591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var i_end = st[i]; 4235591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (i_end > end) 4236591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch st.splice(i, 1, end, st[i+1], i_end); 4237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) i += 2; 4238591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch at = Math.min(end, i_end); 4239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!style) return; 4241926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (overlay.opaque) { 4242591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch st.splice(start, i - start, end, style); 4243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) i = start + 2; 4244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 4245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (; start < i; start += 2) { 4246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var cur = st[start+1]; 4247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) st[start+1] = cur ? cur + " " + style : style; 4248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 42515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return st; 4254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4256926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function getLineStyles(cm, line) { 4257926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!line.styles || line.styles[0] != cm.state.modeGen) 4258926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line))); 4259926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return line.styles; 42605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 42615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 42625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Lightweight form of highlight -- proceed over this line and 42635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // update state, but don't save a style array. 42645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function processLine(cm, line, state) { 4265926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var mode = cm.doc.mode; 42665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var stream = new StringStream(line.text, cm.options.tabSize); 42675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (line.text == "" && mode.blankLine) mode.blankLine(state); 426853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) { 42695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mode.token(stream, state); 42705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stream.start = stream.pos; 42715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 42725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 42735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 42745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var styleToClassCache = {}; 42755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function styleToClass(style) { 42765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!style) return null; 42775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return styleToClassCache[style] || 42785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-")); 42795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 42805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4281f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) function lineContent(cm, realLine, measure, copyWidgets, from, to) { 4282591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var merged, line = realLine, empty = true; 4283591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch while (merged = collapsedSpanAtStart(line)) 4284926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) line = getLine(cm.doc, merged.find().from.line); 42855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4286f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) var builder = {pre: elt("pre"), col: 0, pos: 0, 4287f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) measure: null, measuredSomething: false, cm: cm, from: from, to: to, 4288f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) copyWidgets: copyWidgets}; 42895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (line.textClass) builder.pre.className = line.textClass; 42905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 42915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) do { 42925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (line.text) empty = false; 42935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder.measure = line == realLine && measure; 42945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder.pos = 0; 42955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder.addToken = builder.measure ? buildTokenMeasure : buildToken; 4296926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if ((ie || webkit) && cm.getOption("lineWrapping")) 4297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) builder.addToken = buildTokenSplitSpaces(builder.addToken); 4298591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var next = insertLineContent(line, builder, getLineStyles(cm, line)); 4299591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (measure && line == realLine && !builder.measuredSomething) { 4300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure)); 4301591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch builder.measuredSomething = true; 43025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 43035267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (next) line = getLine(cm.doc, next.to.line); 43045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } while (next); 43055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4306591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (measure && !builder.measuredSomething && !measure[0]) 43075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) measure[0] = builder.pre.appendChild(empty ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure)); 4308926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine)) 43095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder.pre.appendChild(document.createTextNode("\u00a0")); 43105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var order; 4312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Work around problem with the reported dimensions of single-char 4313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // direction spans on IE (issue #1129). See also the comment in 4314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // cursorCoords. 4315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (measure && ie && (order = getOrder(line))) { 4316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var l = order.length - 1; 4317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (order[l].from == order[l].to) --l; 4318926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var last = order[l], prev = order[l - 1]; 4319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (last.from + 1 == last.to && prev && last.level < prev.level) { 4320926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var span = measure[builder.pos - 1]; 4321926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure), 4322926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) span.nextSibling); 4323926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) signal(cm, "renderLine", cm, realLine, builder.pre); 43275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return builder.pre; 43285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 43295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g; 4331e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch function buildToken(builder, text, style, startStyle, endStyle, title) { 43325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!text) return; 43335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!tokenSpecialChars.test(text)) { 43345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder.col += text.length; 43355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var content = document.createTextNode(text); 43365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 43375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var content = document.createDocumentFragment(), pos = 0; 43385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (true) { 43395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) tokenSpecialChars.lastIndex = pos; 43405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var m = tokenSpecialChars.exec(text); 43415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var skipped = m ? m.index - pos : text.length - pos; 43425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (skipped) { 43435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) content.appendChild(document.createTextNode(text.slice(pos, pos + skipped))); 43445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder.col += skipped; 43455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 43465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m) break; 43475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pos += skipped + 1; 43485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m[0] == "\t") { 43495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; 43505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); 43515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder.col += tabWidth; 43525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 43535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var token = elt("span", "\u2022", "cm-invalidchar"); 43545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) token.title = "\\u" + m[0].charCodeAt(0).toString(16); 43555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) content.appendChild(token); 43565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder.col += 1; 43575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 43585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 43595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 43605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style || startStyle || endStyle || builder.measure) { 43615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var fullStyle = style || ""; 43625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (startStyle) fullStyle += startStyle; 43635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (endStyle) fullStyle += endStyle; 4364e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var token = elt("span", [content], fullStyle); 4365e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (title) token.title = title; 4366e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch return builder.pre.appendChild(token); 43675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 43685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder.pre.appendChild(content); 43695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 43705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 43715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function buildTokenMeasure(builder, text, style, startStyle, endStyle) { 4372591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch //FIXME consider 2-byte chars 4373591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (builder.from || builder.to) { 4374591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (builder.from >= builder.pos + text.length) { 4375591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch buildToken(builder, text, style, startStyle, endStyle); 4376591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch builder.pos += text.length; 4377591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return; 4378591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 4379591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 4380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var wrapping = builder.cm.options.lineWrapping; 43815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < text.length; ++i) { 4382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var ch = text.charAt(i), start = i == 0; 4383926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) { 4384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ch = text.slice(i, i + 2); 4385926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ++i; 438693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } else if (i && wrapping && spanAffectsWrapping(text, i)) { 43875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder.pre.appendChild(elt("wbr")); 4388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4389e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var old = builder.measure[builder.pos]; 4390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var span = builder.measure[builder.pos] = 4391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) buildToken(builder, ch, style, 4392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) start && startStyle, i == text.length - 1 && endStyle); 4393e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (old) span.leftSide = old.leftSide || old; 4394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // In IE single-space nodes wrap differently than spaces 4395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // embedded in larger text nodes, except when set to 4396926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // white-space: normal (issue #1268). 4397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) && 4398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) i < text.length - 1 && !/\s/.test(text.charAt(i + 1))) 4399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) span.style.whiteSpace = "normal"; 4400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) builder.pos += ch.length; 44015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4402591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (text.length) builder.measuredSomething = true; 44035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 44045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4405926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function buildTokenSplitSpaces(inner) { 4406926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function split(old) { 4407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var out = " "; 4408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0"; 4409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) out += " "; 4410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return out; 4411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4412e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch return function(builder, text, style, startStyle, endStyle, title) { 4413e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title); 4414926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 4415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4417e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch function buildCollapsedSpan(builder, size, marker, ignoreWidget) { 4418e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var widget = !ignoreWidget && marker.replacedWith; 44195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (widget) { 4420f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (builder.copyWidgets) widget = widget.cloneNode(true); 4421e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch builder.pre.appendChild(widget); 4422591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (builder.measure) { 4423e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (size) { 4424e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch builder.measure[builder.pos] = widget; 4425e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch } else { 4426e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var elt = builder.measure[builder.pos] = zeroWidthElement(builder.cm.display.measure); 4427e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (marker.type != "bookmark" || marker.insertLeft) 4428e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch builder.pre.insertBefore(elt, widget); 4429e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch else 4430e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch builder.pre.appendChild(elt); 4431e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch } 4432591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch builder.measuredSomething = true; 44335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 44345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 44355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) builder.pos += size; 44365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 44375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 44385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Outputs a number of spans to make up a line, taking highlighting 44395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // and marked text into account. 4440926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function insertLineContent(line, builder, styles) { 4441591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var spans = line.markedSpans, allText = line.text, at = 0; 44425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!spans) { 4443591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (builder.to || builder.from) { 4444591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch for (var i = 1; i < styles.length && (!builder.to || builder.pos < builder.to); i+=2) { 4445591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var text = allText.slice(at, at = styles[i]); 4446591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var textLength = text.length; 4447591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var resolvedStyles = styleToClass(styles[i+1]); 4448591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (builder.pos + textLength <= builder.from) { 4449591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch builder.addToken(builder, text, resolvedStyles); 4450591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch continue; 4451591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 4452591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // if we are not inside, but will get over it 4453591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (builder.pos < builder.from && builder.pos + textLength > builder.from) { 4454591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var overlap = builder.from - builder.pos; 4455591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch builder.addToken(builder, text.substring(0, overlap), resolvedStyles); 4456591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch text = text.substring(overlap); 4457591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 4458591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch builder.addToken(builder, text.substr(0, Math.min(builder.to - builder.from, text.length)), resolvedStyles); 4459591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 4460591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } else { 4461591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch for (var i = 1; i < styles.length; i+=2) 4462591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch builder.addToken(builder, allText.slice(at, at = styles[i]), styleToClass(styles[i+1])); 4463591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 44645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 44655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 44665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4467591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch var len = allText.length, pos = 0, i = 1, text = "", style; 4468e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed; 44695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (;;) { 44705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (nextChange == pos) { // Update current marker set 4471e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch spanStyle = spanEndStyle = spanStartStyle = title = ""; 44725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) collapsed = null; nextChange = Infinity; 4473f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) var foundBookmarks = []; 44745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var j = 0; j < spans.length; ++j) { 44755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var sp = spans[j], m = sp.marker; 44765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sp.from <= pos && (sp.to == null || sp.to > pos)) { 44775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; } 44785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m.className) spanStyle += " " + m.className; 44795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle; 44805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle; 4481e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (m.title && !title) title = m.title; 4482591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (m.collapsed && (!collapsed || collapsed.marker.size < m.size)) 44835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) collapsed = sp; 44845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (sp.from > pos && nextChange > sp.from) { 44855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) nextChange = sp.from; 44865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4487f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmarks.push(m); 44885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 44895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (collapsed && (collapsed.from || 0) == pos) { 44905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos, 4491e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch collapsed.marker, collapsed.from == null); 44925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (collapsed.to == null) return collapsed.marker.find(); 44935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4494f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j) 4495f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) buildCollapsedSpan(builder, 0, foundBookmarks[j]); 44965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 44975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (pos >= len) break; 44985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 44995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var upto = Math.min(len, nextChange); 45005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (true) { 45015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (text) { 45025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var end = pos + text.length; 45035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!collapsed) { 45045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var tokenText = end > upto ? text.slice(0, upto - pos) : text; 4505926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, 4506e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title); 4507591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (builder.to && builder.pos >= builder.to) 4508591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return; 45095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 45105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;} 45115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pos = end; 45125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) spanStartStyle = ""; 45135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4514591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch text = allText.slice(at, at = styles[i++]); 4515591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch style = styleToClass(styles[i++]); 45165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 45175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 45185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 45195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 45205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // DOCUMENT DATA STRUCTURE 45215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) { 4523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function spansFor(n) {return markedSpans ? markedSpans[n] : null;} 4524926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function update(line, text, spans) { 4525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateLine(line, text, spans, estimateHeight); 4526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) signalLater(line, "change", line, change); 4527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4529926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var from = change.from, to = change.to, text = change.text; 4530926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); 4531926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; 4532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // First adjust the line structure 4534926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (from.ch == 0 && to.ch == 0 && lastText == "") { 4535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // This is a whole-line replace. Treated specially to make 4536926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // sure line objects move the way they are supposed to. 4537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, e = text.length - 1, added = []; i < e; ++i) 4538e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch added.push(new Line(text[i], spansFor(i), estimateHeight)); 4539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) update(lastLine, lastLine.text, lastSpans); 4540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (nlines) doc.remove(from.line, nlines); 4541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (added.length) doc.insert(from.line, added); 4542926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (firstLine == lastLine) { 4543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (text.length == 1) { 4544926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); 4545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 4546926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var added = [], i = 1, e = text.length - 1; i < e; ++i) 4547e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch added.push(new Line(text[i], spansFor(i), estimateHeight)); 4548e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)); 4549926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); 4550926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.insert(from.line + 1, added); 4551926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4552926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (text.length == 1) { 4553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); 4554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.remove(from.line + 1, nlines); 4555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 4556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); 4557926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); 4558926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 1, e = text.length - 1, added = []; i < e; ++i) 4559e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch added.push(new Line(text[i], spansFor(i), estimateHeight)); 4560926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (nlines > 1) doc.remove(from.line + 1, nlines - 1); 4561926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.insert(from.line + 1, added); 4562926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4564926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) signalLater(doc, "change", doc, change); 4565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setSelection(doc, selAfter.anchor, selAfter.head, null, true); 4566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4567926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 45685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function LeafChunk(lines) { 45695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.lines = lines; 45705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.parent = null; 45715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, e = lines.length, height = 0; i < e; ++i) { 45725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lines[i].parent = this; 45735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) height += lines[i].height; 45745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 45755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.height = height; 45765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 45775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 45785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LeafChunk.prototype = { 45795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) chunkSize: function() { return this.lines.length; }, 4580926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removeInner: function(at, n) { 45815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = at, e = at + n; i < e; ++i) { 45825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var line = this.lines[i]; 45835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.height -= line.height; 45845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cleanUpLine(line); 4585926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) signalLater(line, "delete"); 45865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 45875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.lines.splice(at, n); 45885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 45895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) collapse: function(lines) { 45905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lines.splice.apply(lines, [lines.length, 0].concat(this.lines)); 45915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 4592926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) insertInner: function(at, lines, height) { 45935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.height += height; 45945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); 45955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this; 45965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 45975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) iterN: function(at, n, op) { 45985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var e = at + n; at < e; ++at) 45995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (op(this.lines[at])) return true; 46005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 46025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 46035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function BranchChunk(children) { 46045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.children = children; 46055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var size = 0, height = 0; 46065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, e = children.length; i < e; ++i) { 46075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var ch = children[i]; 46085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size += ch.chunkSize(); height += ch.height; 46095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ch.parent = this; 46105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.size = size; 46125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.height = height; 46135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.parent = null; 46145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 46165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BranchChunk.prototype = { 46175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) chunkSize: function() { return this.size; }, 4618926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removeInner: function(at, n) { 46195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.size -= n; 46205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < this.children.length; ++i) { 46215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var child = this.children[i], sz = child.chunkSize(); 46225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (at < sz) { 46235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var rm = Math.min(n, sz - at), oldHeight = child.height; 4624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) child.removeInner(at, rm); 46255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.height -= oldHeight - child.height; 46265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } 46275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((n -= rm) == 0) break; 46285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) at = 0; 46295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else at -= sz; 46305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (this.size - n < 25) { 46325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var lines = []; 46335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.collapse(lines); 46345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.children = [new LeafChunk(lines)]; 46355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.children[0].parent = this; 46365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 46385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) collapse: function(lines) { 46395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines); 46405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 4641926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) insertInner: function(at, lines, height) { 46425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.size += lines.length; 46435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.height += height; 46445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, e = this.children.length; i < e; ++i) { 46455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var child = this.children[i], sz = child.chunkSize(); 46465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (at <= sz) { 4647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) child.insertInner(at, lines, height); 46485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (child.lines && child.lines.length > 50) { 46495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (child.lines.length > 50) { 46505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var spilled = child.lines.splice(child.lines.length - 25, 25); 46515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var newleaf = new LeafChunk(spilled); 46525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) child.height -= newleaf.height; 46535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.children.splice(i + 1, 0, newleaf); 46545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newleaf.parent = this; 46555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.maybeSpill(); 46575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 46595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) at -= sz; 46615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 46635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) maybeSpill: function() { 46645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (this.children.length <= 10) return; 46655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var me = this; 46665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) do { 46675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var spilled = me.children.splice(me.children.length - 5, 5); 46685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var sibling = new BranchChunk(spilled); 46695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!me.parent) { // Become the parent node 46705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var copy = new BranchChunk(me.children); 46715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) copy.parent = me; 46725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) me.children = [copy, sibling]; 46735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) me = copy; 46745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 46755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) me.size -= sibling.size; 46765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) me.height -= sibling.height; 46775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var myIndex = indexOf(me.parent.children, me); 46785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) me.parent.children.splice(myIndex + 1, 0, sibling); 46795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sibling.parent = me.parent; 46815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } while (me.children.length > 10); 46825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) me.parent.maybeSpill(); 46835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }, 46845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) iterN: function(at, n, op) { 46855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, e = this.children.length; i < e; ++i) { 46865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var child = this.children[i], sz = child.chunkSize(); 46875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (at < sz) { 46885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var used = Math.min(n, sz - at); 46895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (child.iterN(at, used, op)) return true; 46905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((n -= used) == 0) break; 46915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) at = 0; 46925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else at -= sz; 46935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 46955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 46965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var nextDocId = 0; 4698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var Doc = CodeMirror.Doc = function(text, mode, firstLine) { 4699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!(this instanceof Doc)) return new Doc(text, mode, firstLine); 4700926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (firstLine == null) firstLine = 0; 4701926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4702e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); 4703926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.first = firstLine; 4704926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.scrollTop = this.scrollLeft = 0; 4705926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.cantEdit = false; 4706926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.history = makeHistory(); 47075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) this.cleanGeneration = 1; 4708926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.frontier = firstLine; 4709926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var start = Pos(firstLine, 0); 4710926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null}; 4711926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.id = ++nextDocId; 4712926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.modeOption = mode; 4713926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4714926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (typeof text == "string") text = splitLines(text); 4715926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start}); 4716926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 47175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4718926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) Doc.prototype = createObj(BranchChunk.prototype, { 471993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) constructor: Doc, 4720926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) iter: function(from, to, op) { 4721926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (op) this.iterN(from - this.first, to - from, op); 4722926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else this.iterN(this.first, this.first + this.size, from); 4723926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4725926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) insert: function(at, lines) { 4726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var height = 0; 4727926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height; 4728926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.insertInner(at - this.first, lines, height); 4729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) remove: function(at, n) { this.removeInner(at - this.first, n); }, 4731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4732926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getValue: function(lineSep) { 4733926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var lines = getLines(this, this.first, this.first + this.size); 4734926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (lineSep === false) return lines; 4735926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return lines.join(lineSep || "\n"); 4736926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4737926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setValue: function(code) { 4738926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var top = Pos(this.first, 0), last = this.first + this.size - 1; 4739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), 4740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) text: splitLines(code), origin: "setValue"}, 4741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) {head: top, anchor: top}, true); 4742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) replaceRange: function(code, from, to, origin) { 4744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) from = clipPos(this, from); 4745926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) to = to ? clipPos(this, to) : from; 4746926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) replaceRange(this, code, from, to, origin); 4747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getRange: function(from, to, lineSep) { 4749926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); 4750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (lineSep === false) return lines; 4751926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return lines.join(lineSep || "\n"); 4752926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4753926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4754926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;}, 4755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setLine: function(line, text) { 4756926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (isLine(this, line)) 4757926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line))); 4758926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4759926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removeLine: function(line) { 476053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (line) replaceRange(this, "", clipPos(this, Pos(line - 1)), clipPos(this, Pos(line))); 476153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else replaceRange(this, "", Pos(0, 0), clipPos(this, Pos(1, 0))); 4762926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4763926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4764926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);}, 4765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getLineNumber: function(line) {return lineNo(line);}, 4766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4767e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch getLineHandleVisualStart: function(line) { 4768e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (typeof line == "number") line = getLine(this, line); 4769e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch return visualLine(this, line); 4770e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch }, 4771e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch 4772926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) lineCount: function() {return this.size;}, 4773926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) firstLine: function() {return this.first;}, 4774926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) lastLine: function() {return this.first + this.size - 1;}, 4775926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4776926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) clipPos: function(pos) {return clipPos(this, pos);}, 4777926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4778926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getCursor: function(start) { 4779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sel = this.sel, pos; 4780926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (start == null || start == "head") pos = sel.head; 4781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (start == "anchor") pos = sel.anchor; 4782926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (start == "end" || start === false) pos = sel.to; 4783926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else pos = sel.from; 4784926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return copyPos(pos); 4785926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4786926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);}, 4787926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4788926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setCursor: docOperation(function(line, ch, extend) { 4789926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line); 4790926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (extend) extendSelection(this, pos); 4791926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else setSelection(this, pos, pos); 4792926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }), 4793926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setSelection: docOperation(function(anchor, head) { 4794926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor)); 4795926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }), 4796926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) extendSelection: docOperation(function(from, to) { 4797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) extendSelection(this, clipPos(this, from), to && clipPos(this, to)); 4798926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }), 4799926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4800926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);}, 4801926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) replaceSelection: function(code, collapse, origin) { 4802926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around"); 4803926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4804926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) undo: docOperation(function() {makeChangeFromHistory(this, "undo");}), 4805926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) redo: docOperation(function() {makeChangeFromHistory(this, "redo");}), 4806926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4807926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setExtending: function(val) {this.sel.extend = val;}, 4808926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4809926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) historySize: function() { 4810926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var hist = this.history; 4811926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return {undo: hist.done.length, redo: hist.undone.length}; 4812926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 48135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);}, 4814926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4815926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) markClean: function() { 48165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) this.cleanGeneration = this.changeGeneration(); 48175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) }, 48185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) changeGeneration: function() { 4819926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.history.lastOp = this.history.lastOrigin = null; 48205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return this.history.generation; 48215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) }, 48225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) isClean: function (gen) { 48235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return this.history.generation == (gen || this.cleanGeneration); 4824926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4825926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getHistory: function() { 4827926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return {done: copyHistoryArray(this.history.done), 4828926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) undone: copyHistoryArray(this.history.undone)}; 4829926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4830926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setHistory: function(histData) { 48315267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) var hist = this.history = makeHistory(this.history.maxGeneration); 4832926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) hist.done = histData.done.slice(0); 4833926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) hist.undone = histData.undone.slice(0); 4834926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4835926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) markText: function(from, to, options) { 4837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return markText(this, clipPos(this, from), clipPos(this, to), options, "range"); 4838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4839926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setBookmark: function(pos, options) { 4840926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), 4841926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) insertLeft: options && options.insertLeft}; 4842926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos = clipPos(this, pos); 4843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return markText(this, pos, pos, realOpts, "bookmark"); 4844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) findMarksAt: function(pos) { 4846926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos = clipPos(this, pos); 4847926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var markers = [], spans = getLine(this, pos.line).markedSpans; 4848926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (spans) for (var i = 0; i < spans.length; ++i) { 4849926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var span = spans[i]; 4850926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if ((span.from == null || span.from <= pos.ch) && 4851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (span.to == null || span.to >= pos.ch)) 4852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) markers.push(span.marker.parent || span.marker); 4853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return markers; 4855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getAllMarks: function() { 4857926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var markers = []; 4858926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.iter(function(line) { 4859926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sps = line.markedSpans; 4860926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (sps) for (var i = 0; i < sps.length; ++i) 4861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (sps[i].from != null) markers.push(sps[i].marker); 4862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 4863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return markers; 4864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4866926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) posFromIndex: function(off) { 4867926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var ch, lineNo = this.first; 4868926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.iter(function(line) { 4869926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sz = line.text.length + 1; 4870926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (sz > off) { ch = off; return true; } 4871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) off -= sz; 4872926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ++lineNo; 4873926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 4874926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return clipPos(this, Pos(lineNo, ch)); 4875926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) indexFromPos: function (coords) { 4877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) coords = clipPos(this, coords); 4878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var index = coords.ch; 4879926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (coords.line < this.first || coords.ch < 0) return 0; 4880926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.iter(this.first, coords.line, function (line) { 4881926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) index += line.text.length + 1; 4882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 4883926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return index; 4884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4885926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) copy: function(copyHistory) { 4887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first); 4888926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; 4889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor, 4890926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn}; 4891926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (copyHistory) { 4892926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.history.undoDepth = this.history.undoDepth; 4893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.setHistory(this.getHistory()); 4894926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4895926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return doc; 4896926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4897926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4898926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) linkedDoc: function(options) { 4899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!options) options = {}; 4900926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var from = this.first, to = this.first + this.size; 4901926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (options.from != null && options.from > from) from = options.from; 4902926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (options.to != null && options.to < to) to = options.to; 4903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from); 4904926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (options.sharedHist) copy.history = this.history; 4905926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); 4906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; 4907926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return copy; 4908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) unlinkDoc: function(other) { 4910926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (other instanceof CodeMirror) other = other.doc; 4911926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (this.linked) for (var i = 0; i < this.linked.length; ++i) { 4912926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var link = this.linked[i]; 4913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (link.doc != other) continue; 4914926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) this.linked.splice(i, 1); 4915926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) other.unlinkDoc(this); 4916926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) break; 4917926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4918926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // If the histories were shared, split them again 4919926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (other.history == this.history) { 4920926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var splitIds = [other.id]; 4921926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true); 4922926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) other.history = makeHistory(); 4923926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) other.history.done = copyHistoryArray(this.history.done, splitIds); 4924926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) other.history.undone = copyHistoryArray(this.history.undone, splitIds); 4925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4926926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }, 4927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) iterLinkedDocs: function(f) {linkedDocs(this, f);}, 4928926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4929926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getMode: function() {return this.mode;}, 4930926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) getEditor: function() {return this.cm;} 4931926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 4932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4933926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) Doc.prototype.eachLine = Doc.prototype.iter; 4934926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4935926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // The Doc methods that should be available on CodeMirror instances 4936926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var dontDelegate = "iter insert remove copy getEditor".split(" "); 4937926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) 4938926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) CodeMirror.prototype[prop] = (function(method) { 4939926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return function() {return method.apply(this.doc, arguments);}; 4940926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) })(Doc.prototype[prop]); 4941926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4942e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch eventMixin(Doc); 4943e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch 4944926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function linkedDocs(doc, f, sharedHistOnly) { 4945926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function propagate(doc, skip, sharedHist) { 4946926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) { 4947926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var rel = doc.linked[i]; 4948926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (rel.doc == skip) continue; 4949926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var shared = sharedHist && rel.sharedHist; 4950926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (sharedHistOnly && !shared) continue; 4951926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) f(rel.doc, shared); 4952926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) propagate(rel.doc, doc, shared); 4953926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4954926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4955926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) propagate(doc, null, true); 4956926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4957926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 4958926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function attachDoc(cm, doc) { 4959926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (doc.cm) throw new Error("This document is already in use."); 4960926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.doc = doc; 4961926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.cm = cm; 4962926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) estimateLineHeights(cm); 4963926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) loadMode(cm); 4964926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!cm.options.lineWrapping) computeMaxLength(cm); 4965926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cm.options.mode = doc.modeOption; 4966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) regChange(cm); 49675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 49685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // LINE UTILITIES 4970926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 49715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function getLine(chunk, n) { 4972926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) n -= chunk.first; 49735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (!chunk.lines) { 49745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0;; ++i) { 49755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var child = chunk.children[i], sz = child.chunkSize(); 49765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (n < sz) { chunk = child; break; } 49775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) n -= sz; 49785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 49795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 49805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return chunk.lines[n]; 49815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 49825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4983926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function getBetween(doc, start, end) { 4984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var out = [], n = start.line; 4985926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.iter(start.line, end.line + 1, function(line) { 4986926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var text = line.text; 4987926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (n == end.line) text = text.slice(0, end.ch); 4988926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (n == start.line) text = text.slice(start.ch); 4989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) out.push(text); 4990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ++n; 4991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 4992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return out; 4993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4994926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function getLines(doc, from, to) { 4995926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var out = []; 4996926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.iter(from, to, function(line) { out.push(line.text); }); 4997926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return out; 4998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 4999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 50005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function updateLineHeight(line, height) { 50015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var diff = height - line.height; 50025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var n = line; n; n = n.parent) n.height += diff; 50035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 50045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 50055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function lineNo(line) { 50065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (line.parent == null) return null; 50075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cur = line.parent, no = indexOf(cur.lines, line); 50085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { 5009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0;; ++i) { 50105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (chunk.children[i] == cur) break; 50115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) no += chunk.children[i].chunkSize(); 50125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 50135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5014926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return no + cur.first; 50155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 50165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 50175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function lineAtHeight(chunk, h) { 5018926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var n = chunk.first; 50195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outer: do { 50205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, e = chunk.children.length; i < e; ++i) { 50215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var child = chunk.children[i], ch = child.height; 50225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (h < ch) { chunk = child; continue outer; } 50235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) h -= ch; 50245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) n += child.chunkSize(); 50255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 50265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return n; 50275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } while (!chunk.lines); 50285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, e = chunk.lines.length; i < e; ++i) { 50295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var line = chunk.lines[i], lh = line.height; 50305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (h < lh) break; 50315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) h -= lh; 50325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 50335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return n + i; 50345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 50355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 50365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function heightAtLine(cm, lineObj) { 5037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) lineObj = visualLine(cm.doc, lineObj); 50385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 50395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var h = 0, chunk = lineObj.parent; 50405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < chunk.lines.length; ++i) { 50415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var line = chunk.lines[i]; 50425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (line == lineObj) break; 50435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else h += line.height; 50445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 50455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { 50465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < p.children.length; ++i) { 50475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cur = p.children[i]; 50485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cur == chunk) break; 50495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else h += cur.height; 50505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 50515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 50525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return h; 50535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 50545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 50555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function getOrder(line) { 50565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var order = line.order; 50575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (order == null) order = line.order = bidiOrdering(line.text); 50585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return order; 50595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 50605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 50615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // HISTORY 50625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 50635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) function makeHistory(startGen) { 5064926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return { 5065926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Arrays of history events. Doing something adds an event to 5066926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // done and clears undo. Undoing moves events from done to 5067926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // undone, redoing moves them in the other direction. 5068926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) done: [], undone: [], undoDepth: Infinity, 5069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Used to track when changes can be merged into a single undo 5070926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // event 5071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) lastTime: 0, lastOp: null, lastOrigin: null, 5072926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Used by the isClean() method 50735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) generation: startGen || 1, maxGeneration: startGen || 1 5074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }; 5075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function attachLocalSpans(doc, change, from, to) { 5078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var existing = change["spans_" + doc.id], n = 0; 5079926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) { 5080926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (line.markedSpans) 5081926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; 5082926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ++n; 5083926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) }); 5084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5086926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function historyChangeFromChange(doc, change) { 5087e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var from = { line: change.from.line, ch: change.from.ch }; 5088e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var histChange = {from: from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; 5089926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); 5090926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true); 5091926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return histChange; 5092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5093926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5094926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function addToHistory(doc, change, selAfter, opId) { 5095926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var hist = doc.history; 5096926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) hist.undone.length = 0; 5097926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var time = +new Date, cur = lst(hist.done); 5098926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5099926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (cur && 5100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (hist.lastOp == opId || 5101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) hist.lastOrigin == change.origin && change.origin && 510253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ((change.origin.charAt(0) == "+" && doc.cm && hist.lastTime > time - doc.cm.options.historyEventDelay) || 510353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) change.origin.charAt(0) == "*"))) { 5104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Merge this change into the last event 5105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var last = lst(cur.changes); 5106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (posEq(change.from, change.to) && posEq(change.from, last.to)) { 5107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Optimized case for simple insertion -- don't want to add 5108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // new changesets for every character typed 5109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) last.to = changeEnd(change); 5110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 5111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Add new sub-event 5112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cur.changes.push(historyChangeFromChange(doc, change)); 51135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head; 5115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 5116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Can not be merged, start a new event. 5117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cur = {changes: [historyChangeFromChange(doc, change)], 51185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) generation: hist.generation, 5119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) anchorBefore: doc.sel.anchor, headBefore: doc.sel.head, 5120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) anchorAfter: selAfter.anchor, headAfter: selAfter.head}; 5121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) hist.done.push(cur); 51225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) hist.generation = ++hist.maxGeneration; 5123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) while (hist.done.length > hist.undoDepth) 5124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) hist.done.shift(); 51255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) hist.lastTime = time; 5127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) hist.lastOp = opId; 5128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) hist.lastOrigin = change.origin; 5129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 51305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function removeClearedSpans(spans) { 5132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!spans) return null; 5133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, out; i < spans.length; ++i) { 5134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); } 5135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (out) out.push(spans[i]); 51365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return !out ? spans : out.length ? out : null; 51385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 51395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function getOldSpans(doc, change) { 5141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var found = change["spans_" + doc.id]; 5142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!found) return null; 5143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, nw = []; i < change.text.length; ++i) 5144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) nw.push(removeClearedSpans(found[i])); 5145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return nw; 5146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Used both to provide a JSON-safe object in .getHistory, and, when 5149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // detaching a document, to split the history in two 5150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function copyHistoryArray(events, newGroup) { 5151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, copy = []; i < events.length; ++i) { 5152926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var event = events[i], changes = event.changes, newChanges = []; 5153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore, 5154926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) anchorAfter: event.anchorAfter, headAfter: event.headAfter}); 5155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var j = 0; j < changes.length; ++j) { 5156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var change = changes[j], m; 5157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) newChanges.push({from: change.from, to: change.to, text: change.text}); 5158926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) { 5159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (indexOf(newGroup, Number(m[1])) > -1) { 5160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) lst(newChanges)[prop] = change[prop]; 5161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) delete change[prop]; 5162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return copy; 5167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Rebasing/resetting history to deal with externally-sourced changes 5170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function rebaseHistSel(pos, from, to, diff) { 5172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (to < pos.line) { 5173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos.line += diff; 5174926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (from < pos.line) { 5175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos.line = from; 5176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pos.ch = 0; 5177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Tries to rebase an array of history events given a change in the 5181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // document. If the change touches the same lines as the event, the 5182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // event, and everything 'behind' it, is discarded. If the change is 5183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // before the event, the event's positions are updated. Uses a 5184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // copy-on-write scheme for the positions, to avoid having to 5185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // reallocate them all on every rebase, but also avoid problems with 5186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // shared position objects being unsafely updated. 5187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function rebaseHistArray(array, from, to, diff) { 5188926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < array.length; ++i) { 5189926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var sub = array[i], ok = true; 5190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var j = 0; j < sub.changes.length; ++j) { 5191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var cur = sub.changes[j]; 5192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); } 5193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (to < cur.from.line) { 5194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cur.from.line += diff; 5195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cur.to.line += diff; 5196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (from <= cur.to.line) { 5197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ok = false; 5198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) break; 5199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!sub.copied) { 5202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore); 5203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter); 5204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sub.copied = true; 5205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!ok) { 5207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) array.splice(0, i + 1); 5208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) i = 0; 5209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 5210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore); 5211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter); 5212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5215926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function rebaseHist(hist, change) { 5217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; 5218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) rebaseHistArray(hist.done, from, to, diff); 5219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) rebaseHistArray(hist.undone, from, to, diff); 52205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 52215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 52225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // EVENT OPERATORS 52235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 52245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function stopMethod() {e_stop(this);} 52255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Ensure an event has a stop method. 52265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function addStop(event) { 52275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!event.stop) event.stop = stopMethod; 52285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return event; 52295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 52305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 52315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function e_preventDefault(e) { 52325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (e.preventDefault) e.preventDefault(); 52335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else e.returnValue = false; 52345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 52355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function e_stopPropagation(e) { 52365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (e.stopPropagation) e.stopPropagation(); 52375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else e.cancelBubble = true; 52385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5239591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch function e_defaultPrevented(e) { 5240591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false; 5241591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 52425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} 52435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.e_stop = e_stop; 52445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.e_preventDefault = e_preventDefault; 52455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.e_stopPropagation = e_stopPropagation; 52465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 52475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function e_target(e) {return e.target || e.srcElement;} 52485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function e_button(e) { 52495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var b = e.which; 52505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (b == null) { 52515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (e.button & 1) b = 1; 52525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (e.button & 2) b = 3; 52535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (e.button & 4) b = 2; 52545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 52555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (mac && e.ctrlKey && b == 1) b = 3; 52565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return b; 52575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 52585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 52595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // EVENT HANDLING 52605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 52615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function on(emitter, type, f) { 52625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (emitter.addEventListener) 52635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) emitter.addEventListener(type, f, false); 52645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (emitter.attachEvent) 52655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) emitter.attachEvent("on" + type, f); 52665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 52675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var map = emitter._handlers || (emitter._handlers = {}); 52685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var arr = map[type] || (map[type] = []); 52695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) arr.push(f); 52705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 52715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 52725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 52735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function off(emitter, type, f) { 52745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (emitter.removeEventListener) 52755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) emitter.removeEventListener(type, f, false); 52765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (emitter.detachEvent) 52775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) emitter.detachEvent("on" + type, f); 52785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 52795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var arr = emitter._handlers && emitter._handlers[type]; 52805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!arr) return; 52815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < arr.length; ++i) 52825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (arr[i] == f) { arr.splice(i, 1); break; } 52835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 52845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 52855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 52865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function signal(emitter, type /*, values...*/) { 52875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var arr = emitter._handlers && emitter._handlers[type]; 52885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!arr) return; 52895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var args = Array.prototype.slice.call(arguments, 2); 52905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args); 52915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 52925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var delayedCallbacks, delayedCallbackDepth = 0; 5294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function signalLater(emitter, type /*, values...*/) { 52955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var arr = emitter._handlers && emitter._handlers[type]; 52965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!arr) return; 5297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var args = Array.prototype.slice.call(arguments, 2); 5298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!delayedCallbacks) { 5299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ++delayedCallbackDepth; 5300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) delayedCallbacks = []; 5301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setTimeout(fireDelayed, 0); 5302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 53035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function bnd(f) {return function(){f.apply(null, args);};}; 53045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < arr.length; ++i) 5305926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) delayedCallbacks.push(bnd(arr[i])); 5306926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5307926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5308e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch function signalDOMEvent(cm, e, override) { 5309e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch signal(cm, override || e.type, cm, e); 5310f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) return e_defaultPrevented(e) || e.codemirrorIgnore; 5311591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 5312591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 5313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function fireDelayed() { 5314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) --delayedCallbackDepth; 5315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var delayed = delayedCallbacks; 5316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) delayedCallbacks = null; 5317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0; i < delayed.length; ++i) delayed[i](); 53185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 53195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function hasHandler(emitter, type) { 53215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var arr = emitter._handlers && emitter._handlers[type]; 53225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return arr && arr.length > 0; 53235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 53245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal; 53265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5327e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch function eventMixin(ctor) { 5328e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch ctor.prototype.on = function(type, f) {on(this, type, f);}; 5329e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch ctor.prototype.off = function(type, f) {off(this, type, f);}; 5330e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch } 5331e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch 53325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // MISC UTILITIES 53335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Number of pixels added to scroller and sizer to hide scrollbar 53355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var scrollerCutOff = 30; 53365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Returned or thrown by various protocols to signal 'I'm not 53385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // handling this'. 53395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}}; 53405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function Delayed() {this.id = null;} 53425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}}; 53435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Counts the column offset in a string, taking tabs into account. 53455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Used mostly to find indentation. 5346926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function countColumn(string, end, tabSize, startIndex, startValue) { 53475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (end == null) { 53485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) end = string.search(/[^\s\u00a0]/); 53495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (end == -1) end = string.length; 53505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = startIndex || 0, n = startValue || 0; i < end; ++i) { 53525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (string.charAt(i) == "\t") n += tabSize - (n % tabSize); 53535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else ++n; 53545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 53555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return n; 53565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 53575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.countColumn = countColumn; 53585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var spaceStrs = [""]; 53605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function spaceStr(n) { 53615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (spaceStrs.length <= n) 53625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) spaceStrs.push(lst(spaceStrs) + " "); 53635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return spaceStrs[n]; 53645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 53655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function lst(arr) { return arr[arr.length-1]; } 53675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function selectInput(node) { 53695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ios) { // Mobile Safari apparently has a bug where select() is broken. 53705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) node.selectionStart = 0; 53715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) node.selectionEnd = node.value.length; 5372591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } else { 5373591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // Suppress mysterious IE10 errors 5374591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch try { node.select(); } 5375591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch catch(_e) {} 5376591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 53775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 53785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function indexOf(collection, elt) { 53805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (collection.indexOf) return collection.indexOf(elt); 53815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0, e = collection.length; i < e; ++i) 53825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (collection[i] == elt) return i; 53835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return -1; 53845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 53855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function createObj(base, props) { 5387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function Obj() {} 5388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) Obj.prototype = base; 5389926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var inst = new Obj(); 5390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (props) copyObj(props, inst); 5391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return inst; 5392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 5394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function copyObj(obj, target) { 5395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!target) target = {}; 5396926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop]; 5397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return target; 5398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 54005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function emptyArray(size) { 54015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var a = [], i = 0; i < size; ++i) a.push(undefined); 54025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return a; 54035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 54045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 54055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function bind(f) { 54065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var args = Array.prototype.slice.call(arguments, 1); 54075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return function(){return f.apply(null, args);}; 54085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 54095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 541093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; 54115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function isWordChar(ch) { 54125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return /\w/.test(ch) || ch > "\x80" && 54135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); 54145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 54155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 54165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function isEmpty(obj) { 5417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false; 5418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return true; 54195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 54205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/; 54225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 54235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // DOM UTILITIES 54245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 54255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function elt(tag, content, className, style) { 54265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var e = document.createElement(tag); 54275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (className) e.className = className; 54285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style) e.style.cssText = style; 54295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (typeof content == "string") setTextContent(e, content); 54305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]); 54315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return e; 54325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 54335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 54345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function removeChildren(e) { 543553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) for (var count = e.childNodes.length; count > 0; --count) 543653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) e.removeChild(e.firstChild); 54375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return e; 54385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 54395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 54405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function removeChildrenAndAdd(parent, e) { 54415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return removeChildren(parent).appendChild(e); 54425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 54435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 54445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function setTextContent(e, str) { 54455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ie_lt9) { 54465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e.innerHTML = ""; 54475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e.appendChild(document.createTextNode(str)); 54485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else e.textContent = str; 54495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 54505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function getRect(node) { 5452926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return node.getBoundingClientRect(); 5453926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5454926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) CodeMirror.replaceGetRect = function(f) { getRect = f; }; 5455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 54565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FEATURE DETECTION 54575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 54585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Detect drag-and-drop 54595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var dragAndDrop = function() { 54605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // There is *some* kind of drag-and-drop support in IE6-8, but I 54615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // couldn't get it to work yet. 54625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ie_lt9) return false; 54635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var div = elt('div'); 54645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return "draggable" in div || "dragDrop" in div; 54655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }(); 54665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 54675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For a reason I have yet to figure out, some browsers disallow 54685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // word wrapping between certain characters *only* if a new inline 54695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // element is started between them. This makes it hard to reliably 54705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // measure the position of things, since that requires inserting an 547193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // extra span. This terribly fragile set of tests matches the 54725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // character combinations that suffer from this phenomenon on the 54735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // various browsers. 547493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) function spanAffectsWrapping() { return false; } 547593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (gecko) // Only for "$'" 547693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) spanAffectsWrapping = function(str, i) { 547793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return str.charCodeAt(i - 1) == 36 && str.charCodeAt(i) == 39; 547893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) }; 547993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent)) 548093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) spanAffectsWrapping = function(str, i) { 548193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1)); 548293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) }; 5483e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch else if (webkit && !/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent)) 548493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) spanAffectsWrapping = function(str, i) { 5485e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (i > 1 && str.charCodeAt(i - 1) == 45) { 5486e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true; 5487e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false; 5488e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch } 54895267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1)); 549093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) }; 54915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 54925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var knownScrollbarWidth; 54935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function scrollbarWidth(measure) { 54945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (knownScrollbarWidth != null) return knownScrollbarWidth; 54955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll"); 54965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) removeChildrenAndAdd(measure, test); 54975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (test.offsetWidth) 54985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) knownScrollbarWidth = test.offsetHeight - test.clientHeight; 54995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return knownScrollbarWidth || 0; 55005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 55015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5502926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var zwspSupported; 5503926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function zeroWidthElement(measure) { 5504926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (zwspSupported == null) { 5505926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var test = elt("span", "\u200b"); 5506926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); 5507926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (measure.firstChild.offsetHeight != 0) 5508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8; 5509926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5510926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (zwspSupported) return elt("span", "\u200b"); 5511926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); 5512926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5513926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 55145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // See if "".split is the broken IE version, if so, provide an 55155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // alternative way to split lines. 55165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { 55175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var pos = 0, result = [], l = string.length; 55185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (pos <= l) { 55195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var nl = string.indexOf("\n", pos); 55205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (nl == -1) nl = string.length; 55215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); 55225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var rt = line.indexOf("\r"); 55235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rt != -1) { 55245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.push(line.slice(0, rt)); 55255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pos += rt + 1; 55265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 55275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.push(line); 55285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pos = nl + 1; 55295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 55305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 55315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return result; 55325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } : function(string){return string.split(/\r\n?|\n/);}; 55335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.splitLines = splitLines; 55345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var hasSelection = window.getSelection ? function(te) { 55365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try { return te.selectionStart != te.selectionEnd; } 55375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) catch(e) { return false; } 55385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } : function(te) { 55395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try {var range = te.ownerDocument.selection.createRange();} 55405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) catch(e) {} 55415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!range || range.parentElement() != te) return false; 55425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return range.compareEndPoints("StartToEnd", range) != 0; 55435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 55445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var hasCopyEvent = (function() { 55465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var e = elt("div"); 55475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ("oncopy" in e) return true; 55485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) e.setAttribute("oncopy", "return;"); 55495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return typeof e.oncopy == 'function'; 55505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) })(); 55515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // KEY NAMING 55535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", 55555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", 55565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", 55575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete", 55585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 55595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home", 55605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"}; 55615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodeMirror.keyNames = keyNames; 55625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (function() { 55635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Number keys 55645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i); 55655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Alphabetic keys 55665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); 55675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Function keys 55685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; 55695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) })(); 55705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // BIDI HELPERS 55725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function iterateBidiSections(order, from, to, f) { 55745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!order) return f(from, to, "ltr"); 5575e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch var found = false; 55765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < order.length; ++i) { 55775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var part = order[i]; 5578e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (part.from < to && part.to > from || from == to && part.to == from) { 55795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr"); 5580e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch found = true; 5581e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch } 55825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5583e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (!found) f(from, to, "ltr"); 55845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 55855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function bidiLeft(part) { return part.level % 2 ? part.to : part.from; } 55875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function bidiRight(part) { return part.level % 2 ? part.from : part.to; } 55885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; } 55905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function lineRight(line) { 55915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var order = getOrder(line); 55925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!order) return line.text.length; 55935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return bidiRight(lst(order)); 55945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 55955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5596926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function lineStart(cm, lineN) { 5597926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var line = getLine(cm.doc, lineN); 5598926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var visual = visualLine(cm.doc, line); 5599926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (visual != line) lineN = lineNo(visual); 5600926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var order = getOrder(visual); 5601926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual); 5602926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return Pos(lineN, ch); 56035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) function lineEnd(cm, lineN) { 56055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var merged, line; 5606926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN))) 5607926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) lineN = merged.find().to.line; 56085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var order = getOrder(line); 56095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line); 5610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return Pos(lineN, ch); 56115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 56125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 561393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) function compareBidiLevel(order, a, b) { 561493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var linedir = order[0].level; 561593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (a == linedir) return true; 561693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (b == linedir) return false; 561793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return a < b; 561893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 561993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var bidiOther; 562093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) function getBidiPartAt(order, pos) { 562193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) for (var i = 0, found; i < order.length; ++i) { 562293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var cur = order[i]; 562393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; } 562493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (cur.from == pos || cur.to == pos) { 562593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (found == null) { 562693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) found = i; 562793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } else if (compareBidiLevel(order, cur.level, order[found].level)) { 562893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) bidiOther = found; 562993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return i; 563093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } else { 563193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) bidiOther = i; 563293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return found; 563393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 563493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 563593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 563693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) bidiOther = null; 563793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return found; 563893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 563993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 564093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) function moveInLine(line, pos, dir, byUnit) { 564193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (!byUnit) return pos + dir; 564293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) do pos += dir; 564393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) while (pos > 0 && isExtendingChar.test(line.text.charAt(pos))); 564493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return pos; 564593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 564693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 56475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This is somewhat involved. It is needed in order to move 56485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // 'visually' through bi-directional text -- i.e., pressing left 56495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // should make the cursor go left, even when in RTL text. The 56505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // tricky part is the 'jumps', where RTL and LTR text touch each 56515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // other. This often requires the cursor offset to move more than 56525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // one unit, in order to visually move one unit. 56535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function moveVisually(line, start, dir, byUnit) { 56545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var bidi = getOrder(line); 56555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!bidi) return moveLogically(line, start, dir, byUnit); 565693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var pos = getBidiPartAt(bidi, start), part = bidi[pos]; 565793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit); 565893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 565993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) for (;;) { 566093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (target > part.from && target < part.to) return target; 566193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (target == part.from || target == part.to) { 566293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (getBidiPartAt(bidi, target) == pos) return target; 566393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) part = bidi[pos += dir]; 566493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return (dir > 0) == part.level % 2 ? part.to : part.from; 56655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 566693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) part = bidi[pos += dir]; 566793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (!part) return null; 566893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if ((dir > 0) == part.level % 2) 566993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) target = moveInLine(line, part.to, -1, byUnit); 567093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) else 567193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) target = moveInLine(line, part.from, 1, byUnit); 56725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 56735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 56745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 56755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 56765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function moveLogically(line, start, dir, byUnit) { 56775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var target = start + dir; 56785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir; 56795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return target < 0 || target > line.text.length ? null : target; 56805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 56815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 56825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Bidirectional ordering algorithm 56835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm 56845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // that this (partially) implements. 56855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 56865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // One-char codes used for character types: 56875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // L (L): Left-to-Right 56885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // R (R): Right-to-Left 56895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // r (AL): Right-to-Left Arabic 56905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // 1 (EN): European Number 56915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // + (ES): European Number Separator 56925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // % (ET): European Number Terminator 56935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // n (AN): Arabic Number 56945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // , (CS): Common Number Separator 56955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // m (NSM): Non-Spacing Mark 56965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // b (BN): Boundary Neutral 56975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // s (B): Paragraph Separator 56985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // t (S): Segment Separator 56995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // w (WS): Whitespace 57005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // N (ON): Other Neutrals 57015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 57025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Returns null if characters are ordered as they appear 57035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // (left-to-right), or an array of sections ({from, to, level} 57045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // objects) in the order in which they occur visually. 57055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var bidiOrdering = (function() { 57065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Character types for codepoints 0 to 0xff 57075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL"; 57085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Character types for codepoints 0x600 to 0x6ff 57095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr"; 57105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function charType(code) { 57115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (code <= 0xff) return lowTypes.charAt(code); 57125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (0x590 <= code && code <= 0x5f4) return "R"; 57135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600); 57145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (0x700 <= code && code <= 0x8ac) return "r"; 57155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else return "L"; 57165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 57175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 57185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; 57195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; 5720926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Browsers seem to always treat the boundaries of block elements as being L. 5721926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var outerType = "L"; 57225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5723926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return function(str) { 57245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!bidiRE.test(str)) return false; 5725926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var len = str.length, types = []; 5726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, type; i < len; ++i) 57275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) types.push(type = charType(str.charCodeAt(i))); 57285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 57295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // W1. Examine each non-spacing mark (NSM) in the level run, and 57305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // change the type of the NSM to the type of the previous 57315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // character. If the NSM is at the start of the level run, it will 57325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // get the type of sor. 5733926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, prev = outerType; i < len; ++i) { 57345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var type = types[i]; 57355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (type == "m") types[i] = prev; 57365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else prev = type; 57375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 57385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 57395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // W2. Search backwards from each instance of a European number 57405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // until the first strong type (R, L, AL, or sor) is found. If an 57415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // AL is found, change the type of the European number to Arabic 57425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // number. 57435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // W3. Change all ALs to R. 5744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, cur = outerType; i < len; ++i) { 57455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var type = types[i]; 57465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (type == "1" && cur == "r") types[i] = "n"; 57475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; } 57485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 57495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 57505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // W4. A single European separator between two European numbers 57515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // changes to a European number. A single common separator between 57525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // two numbers of the same type changes to that type. 57535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 1, prev = types[0]; i < len - 1; ++i) { 57545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var type = types[i]; 57555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1"; 57565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (type == "," && prev == types[i+1] && 57575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (prev == "1" || prev == "n")) types[i] = prev; 57585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) prev = type; 57595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 57605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 57615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // W5. A sequence of European terminators adjacent to European 57625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // numbers changes to all European numbers. 57635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // W6. Otherwise, separators and terminators change to Other 57645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Neutral. 57655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < len; ++i) { 57665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var type = types[i]; 57675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (type == ",") types[i] = "N"; 57685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (type == "%") { 57695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var end = i + 1; end < len && types[end] == "%"; ++end) {} 57705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N"; 57715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var j = i; j < end; ++j) types[j] = replace; 57725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) i = end - 1; 57735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 57745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 57755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 57765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // W7. Search backwards from each instance of a European number 57775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // until the first strong type (R, L, or sor) is found. If an L is 57785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // found, then change the type of the European number to L. 5779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (var i = 0, cur = outerType; i < len; ++i) { 57805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var type = types[i]; 57815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (cur == "L" && type == "1") types[i] = "L"; 57825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (isStrong.test(type)) cur = type; 57835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 57845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 57855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // N1. A sequence of neutrals takes the direction of the 57865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // surrounding strong text if the text on both sides has the same 57875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // direction. European and Arabic numbers act as if they were R in 57885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // terms of their influence on neutrals. Start-of-level-run (sor) 57895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // and end-of-level-run (eor) are used at level run boundaries. 57905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // N2. Any remaining neutrals take the embedding direction. 57915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < len; ++i) { 57925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isNeutral.test(types[i])) { 57935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {} 5794926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var before = (i ? types[i-1] : outerType) == "L"; 5795926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) var after = (end < len - 1 ? types[end] : outerType) == "L"; 57965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var replace = before || after ? "L" : "R"; 57975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var j = i; j < end; ++j) types[j] = replace; 57985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) i = end - 1; 57995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 58005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 58015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 58025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Here we depart from the documented algorithm, in order to avoid 58035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // building up an actual levels array. Since there are only three 58045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // levels (0, 1, 2) in an implementation that doesn't take 58055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // explicit embedding into account, we can build up the order on 58065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the fly, without following the level-based algorithm. 58075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var order = [], m; 58085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < len;) { 58095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (countsAsLeft.test(types[i])) { 58105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var start = i; 58115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (++i; i < len && countsAsLeft.test(types[i]); ++i) {} 58125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) order.push({from: start, to: i, level: 0}); 58135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 58145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var pos = i, at = order.length; 58155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (++i; i < len && types[i] != "L"; ++i) {} 58165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var j = pos; j < i;) { 58175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (countsAsNum.test(types[j])) { 58185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1}); 58195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var nstart = j; 58205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (++j; j < i && countsAsNum.test(types[j]); ++j) {} 58215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) order.splice(at, 0, {from: nstart, to: j, level: 2}); 58225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pos = j; 58235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else ++j; 58245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 58255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1}); 58265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 58275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 58285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (order[0].level == 1 && (m = str.match(/^\s+/))) { 58295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) order[0].from = m[0].length; 58305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) order.unshift({from: 0, to: m[0].length, level: 0}); 58315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 58325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (lst(order).level == 1 && (m = str.match(/\s+$/))) { 58335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lst(order).to -= m[0].length; 58345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) order.push({from: len - m[0].length, to: len, level: 0}); 58355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 58365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (order[0].level != lst(order).level) 58375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) order.push({from: len, to: len, level: order[0].level}); 58385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 58395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return order; 58405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 58415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) })(); 58425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 58435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // THE END 58445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5845f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) CodeMirror.version = "3.15.1"; 58465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 58475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return CodeMirror; 58485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)})(); 5849