diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 4313e934..06efb71a 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -56,7 +56,6 @@ var EditSession = function(text, mode) { this.$backMarkers = {}; this.$markerId = 1; this.$rowCache = []; - this.$rowCacheSize = 1000; this.$wrapData = []; this.$foldData = []; this.$foldData.toString = function() { @@ -1352,6 +1351,9 @@ var EditSession = function(text, mode) { return [screenColumn, column]; } + /** + * Returns the number of rows required to render this row on the screen + */ this.getRowLength = function(row) { if (!this.$useWrapMode || !this.$wrapData[row]) { return 1; @@ -1360,14 +1362,14 @@ var EditSession = function(text, mode) { } } + /** + * Returns the height in pixels required to render this row on the screen + **/ this.getRowHeight = function(config, row) { return this.getRowLength(row) * config.lineHeight; } this.getScreenLastRowColumn = function(screenRow) { - // Note: This won't work if someone has more then - // 1.7976931348623158e+307 characters in one row. But I think we can - // live with this limitation ;) return this.screenToDocumentColumn(screenRow, Number.MAX_VALUE / 10) }; @@ -1405,6 +1407,13 @@ var EditSession = function(text, mode) { }; this.screenToDocumentPosition = function(screenRow, screenColumn) { + if (screenRow < 0) { + return { + row: 0, + column: 0 + } + } + var line; var docRow = 0; var docColumn = 0; @@ -1412,7 +1421,6 @@ var EditSession = function(text, mode) { var foldLineRowLength; var row = 0; var rowLength = 0; - var splits = null; var rowCache = this.$rowCache; var doCache = !rowCache.length; @@ -1423,21 +1431,18 @@ var EditSession = function(text, mode) { doCache = i == rowCache.length - 1; } } - var docRowCacheLast = docRow; // clamp row before clamping column, for selection on last line var maxRow = this.getLength() - 1; var foldLine = this.getNextFold(docRow); - var foldStart = foldLine ?foldLine.start.row :Infinity; + var foldStart = foldLine ? foldLine.start.row : Infinity; while (row <= screenRow) { - if (doCache - && docRow - docRowCacheLast > this.$rowCacheSize) { + if (doCache) { rowCache.push({ docRow: docRow, screenRow: row }); - docRowCacheLast = docRow; } rowLength = this.getRowLength(docRow); if (row + rowLength - 1 >= screenRow || docRow >= maxRow) { @@ -1445,10 +1450,10 @@ var EditSession = function(text, mode) { } else { row += rowLength; docRow++; - if(docRow > foldStart) { + if (docRow > foldStart) { docRow = foldLine.end.row+1; foldLine = this.getNextFold(docRow); - foldStart = foldLine ?foldLine.start.row :Infinity; + foldStart = foldLine ? foldLine.start.row : Infinity; } } } @@ -1460,6 +1465,7 @@ var EditSession = function(text, mode) { foldLine = null; } + var splits = []; if (this.$useWrapMode) { splits = this.$wrapData[docRow]; if (splits) { @@ -1473,6 +1479,10 @@ var EditSession = function(text, mode) { docColumn += this.$getStringScreenWidth(line, screenColumn)[1]; + // clip row at the end of the documen + if (row + splits.length < screenRow) + docColumn = Number.MAX_VALUE; + // Need to do some clamping action here. if (this.$useWrapMode) { if (docColumn >= column) { @@ -1539,7 +1549,6 @@ var EditSession = function(text, mode) { doCache = i == rowCache.length - 1; } } - var docRowCacheLast = row; var foldLine = this.getNextFold(row); var foldStart = foldLine ?foldLine.start.row :Infinity; @@ -1554,13 +1563,11 @@ var EditSession = function(text, mode) { } else { rowEnd = row + 1; } - if (doCache - && row - docRowCacheLast > this.$rowCacheSize) { + if (doCache) { rowCache.push({ docRow: row, screenRow: screenRow }); - docRowCacheLast = row; } screenRow += this.getRowLength(row); @@ -1586,7 +1593,8 @@ var EditSession = function(text, mode) { screenRowOffset++; } textLine = textLine.substring( - wrapRow[screenRowOffset - 1] || 0, textLine.length); + wrapRow[screenRowOffset - 1] || 0, textLine.length + ); } return { diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index 8efd0d60..ea74ed07 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -233,9 +233,7 @@ module.exports = { assert.equal(session.screenToDocumentColumn(0, 14), 13); }, - "test: screenToDocument with soft wrap and multi byte characters": function() { - var tabSize = 4; - var wrapLimit = 12; + "test: screenToDocument with soft wrap": function() { var session = new EditSession(["foo bar foo bar"]); session.setUseWrapMode(true); session.setWrapLimitRange(12, 12); @@ -246,7 +244,9 @@ module.exports = { // Check if the position is clamped the right way. assert.position(session.screenToDocumentPosition(0, 12), 0, 11); assert.position(session.screenToDocumentPosition(0, 20), 0, 11); - + }, + + "test: screenToDocument with soft wrap and multi byte characters": function() { session = new EditSession(["ぁ a"]); session.setUseWrapMode(true); session.adjustWrapLimit(80); @@ -257,6 +257,16 @@ module.exports = { assert.position(session.screenToDocumentPosition(0, 4), 0, 3); assert.position(session.screenToDocumentPosition(0, 5), 0, 3); }, + + "test: screenToDocument should clip position to the document boundaries": function() { + var session = new EditSession("foo bar\njuhu kinners"); + + assert.position(session.screenToDocumentPosition(-1, 4), 0, 0); + assert.position(session.screenToDocumentPosition(0, -1), 0, 0); + assert.position(session.screenToDocumentPosition(0, 30), 0, 7); + assert.position(session.screenToDocumentPosition(2, 4), 1, 12); + assert.position(session.screenToDocumentPosition(1, 30), 1, 12); + }, "test: wrapLine split function" : function() { var splits; diff --git a/lib/ace/selection.js b/lib/ace/selection.js index 4318d0e7..ee19fa99 100644 --- a/lib/ace/selection.js +++ b/lib/ace/selection.js @@ -297,7 +297,8 @@ var Selection = function(session) { fold; if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) { this.moveCursorTo(fold.end.row, fold.end.column); - } else if (this.selectionLead.column == this.doc.getLine(this.selectionLead.row).length) { + } + else if (this.selectionLead.column == this.doc.getLine(this.selectionLead.row).length) { if (this.selectionLead.row < this.doc.getLength() - 1) { this.moveCursorTo(this.selectionLead.row + 1, 0); } diff --git a/lib/ace/selection_test.js b/lib/ace/selection_test.js index 3ed1d99a..40336444 100644 --- a/lib/ace/selection_test.js +++ b/lib/ace/selection_test.js @@ -368,6 +368,26 @@ module.exports = { selection.moveCursorLineStart(); assert.position(selection.getCursor(), 1, 4); + }, + + "test go line up when in the middle of the first line should go to document start": function() { + var session = new EditSession("juhu kinners"); + var selection = session.getSelection(); + + selection.moveCursorTo(0, 4); + selection.moveCursorUp(); + + assert.position(selection.getCursor(), 0, 0); + }, + + "test go line down when in the middle of the last line should go to document end": function() { + var session = new EditSession("juhu kinners"); + var selection = session.getSelection(); + + selection.moveCursorTo(0, 4); + selection.moveCursorDown(); + + assert.position(selection.getCursor(), 0, 12); } };