hterm 1.43: Implement reverse wraparound.
* Implement reverse wraparound, add a test.
BUG=chromium:393737
Change-Id: I00841d6553408abbeae90d8d51fac9d6b1c7b003
Reviewed-on: https://chromium-review.googlesource.com/208551
Reviewed-by: Marvelous Marius <mschilder@chromium.org>
Tested-by: Robert Ginda <rginda@chromium.org>
diff --git a/hterm/doc/changelog.txt b/hterm/doc/changelog.txt
index a2d5487..ca86cc3 100644
--- a/hterm/doc/changelog.txt
+++ b/hterm/doc/changelog.txt
@@ -1,3 +1,7 @@
+1.43, 2014-07-15, Implement reverse wraparound.
+
+* Implement reverse wraparound, add a test.
+
1.42, 2014-06-25, Stop requesting notification permission.
* This code depended on a user action, but the preference observers aren't
diff --git a/hterm/js/hterm_terminal.js b/hterm/js/hterm_terminal.js
index 2849faf..35f96ea 100644
--- a/hterm/js/hterm_terminal.js
+++ b/hterm/js/hterm_terminal.js
@@ -2036,10 +2036,37 @@
/**
* Move the cursor left a specified number of columns.
*
+ * If reverse wraparound mode is enabled and the previous row wrapped into
+ * the current row then we back up through the wraparound as well.
+ *
* @param {integer} count The number of columns to move the cursor.
*/
hterm.Terminal.prototype.cursorLeft = function(count) {
- return this.cursorRight(-(count || 1));
+ count = count || 1;
+
+ if (count < 1)
+ return;
+
+ var currentColumn = this.screen_.cursorPosition.column;
+ var newColumn = currentColumn - count;
+ if (newColumn < 0) {
+ if (this.options_.reverseWraparound) {
+ var currentRow = this.screen_.cursorPosition.row;
+ if (currentRow > 0 &&
+ this.screen_.rowsArray[currentRow - 1].getAttribute(
+ 'line-overflow')) {
+ this.setCursorPosition(currentRow - 1, this.screenSize.width - 1);
+ if (count - currentColumn - 1)
+ this.cursorLeft(count - currentColumn - 1);
+ return;
+ }
+ }
+
+ newColumn = 0;
+ }
+
+ this.setCursorColumn(newColumn);
+ return;
};
/**
@@ -2049,6 +2076,10 @@
*/
hterm.Terminal.prototype.cursorRight = function(count) {
count = count || 1;
+
+ if (count < 1)
+ return;
+
var column = lib.f.clamp(this.screen_.cursorPosition.column + count,
0, this.screenSize.width - 1);
this.setCursorColumn(column);
diff --git a/hterm/js/hterm_vt_tests.js b/hterm/js/hterm_vt_tests.js
index d0041dc..811c458 100644
--- a/hterm/js/hterm_vt_tests.js
+++ b/hterm/js/hterm_vt_tests.js
@@ -882,7 +882,7 @@
result.assertEQ(row.childNodes[1].nodeName, 'SPAN', 'i: ' + i);
result.assert(!!row.childNodes[1].style.color, 'i: ' + i);
result.assert(!!row.childNodes[1].style.fontWeight == (i > 2), 'i: ' + i);
- result.assert(
+ result.assertEQ(
row.childNodes[1].style.fontStyle, (i == 1 ? 'italic' : ''),
'i: ' + i);
}
@@ -1250,6 +1250,49 @@
});
/**
+ * Test reverse wraparound.
+ */
+hterm.VT.Tests.addTest('reverse-wrap', function(result, cx) {
+ // A line ending with a hard CRLF.
+ var str = 'AAAA\r\n';
+
+ // Enough X's to wrap once and leave the cursor in the overflow state at
+ // the end of the third row.
+ for (var i = 0; i < this.visibleColumnCount * 2; i++)
+ str += 'X';
+
+ // CR to put us at col 0, backspace to put us at the last column of the
+ // previous row, if reverse wraparound is enabled.
+ str += '\r\bBB';
+
+ // Without reverse wraparound, we should get stuck at column 0 of the third
+ // row.
+ this.terminal.interpret(str);
+
+ result.assertEQ(this.terminal.getRowText(0), 'AAAA');
+ result.assertEQ(this.terminal.getRowText(1), 'XXXXXXXXXXXXXXX');
+ result.assertEQ(this.terminal.getRowText(2), 'BBXXXXXXXXXXXXX');
+
+ // With reverse wraparound, we'll back up to the previous row.
+ this.terminal.clearHome();
+ this.terminal.interpret('\x1b[?45h' + str);
+
+ result.assertEQ(this.terminal.getRowText(0), 'AAAA');
+ result.assertEQ(this.terminal.getRowText(1), 'XXXXXXXXXXXXXXB');
+ result.assertEQ(this.terminal.getRowText(2), 'BXXXXXXXXXXXXXX');
+
+ // But reverse wraparound shouldn't extend to the "AAAA" row, which ended
+ // with a \r\n rather than a soft column wrap.
+ this.terminal.interpret('\r\b\r\bCC');
+
+ result.assertEQ(this.terminal.getRowText(0), 'AAAA');
+ result.assertEQ(this.terminal.getRowText(1), 'CCXXXXXXXXXXXXB');
+ result.assertEQ(this.terminal.getRowText(2), 'BXXXXXXXXXXXXXX');
+
+ result.pass();
+ });
+
+/**
* Test interactions between the cursor overflow bit and various
* escape sequences.
*/