]> git.proxmox.com Git - mirror_xterm.js.git/commitdiff
fixing #147 and #162
authorJörg Breitbart <jerch@rockborn.de>
Tue, 5 Jul 2016 21:54:15 +0000 (23:54 +0200)
committerJörg Breitbart <jerch@rockborn.de>
Tue, 5 Jul 2016 21:54:15 +0000 (23:54 +0200)
src/xterm.js
test/test.js

index 51357afbd5699a5da78b72da6274c2f588aa07a7..497f0a775f16d3e1c907ea96bb3cf5a6a1889e38 100644 (file)
       this.applicationCursor = false;
       this.originMode = false;
       this.insertMode = false;
-      this.wraparoundMode = false;
+      this.wraparoundMode = true; // defaults: xterm - true, vt100 - false
       this.normal = null;
 
       // charset
      * @public
      */
     Terminal.prototype.write = function(data) {
-      var l = data.length, i = 0, j, cs, ch, code, low, ch_width;
+      var l = data.length, i = 0, j, cs, ch, code, low, ch_width, row;
 
       this.refreshStart = this.y;
       this.refreshEnd = this.y;
                     ch = this.charset[ch];
                   }
 
+                  row = this.y + this.ybase;
+
                   // insert combining char in last cell
                   // FIXME: needs handling after cursor jumps
                   if (!ch_width && this.x) {
                     
                     // dont overflow left
-                    if (this.lines[this.y + this.ybase][this.x-1]) {
-                      if (!this.lines[this.y + this.ybase][this.x-1][2]) {
+                    if (this.lines[row][this.x-1]) {
+                      if (!this.lines[row][this.x-1][2]) {
 
                         // found empty cell after fullwidth, need to go 2 cells back
-                        if (this.lines[this.y + this.ybase][this.x-2])
-                          this.lines[this.y + this.ybase][this.x-2][1] += ch;
+                        if (this.lines[row][this.x-2])
+                          this.lines[row][this.x-2][1] += ch;
 
                       } else {
-                        this.lines[this.y + this.ybase][this.x-1][1] += ch;
+                        this.lines[row][this.x-1][1] += ch;
                       }
                       this.updateRange(this.y);
                     }
                   // goto next line if ch would overflow
                   // TODO: needs a global min terminal width of 2
                   if (this.x+ch_width-1 >= this.cols) {
-                    this.x = 0;
-                    this.y++;
-                    if (this.y > this.scrollBottom) {
-                      this.y--;
-                      this.scroll();
+                    // autowrap - DECAWM
+                    if (this.wraparoundMode) {
+                      this.x = 0;
+                      this.y++;
+                      if (this.y > this.scrollBottom) {
+                        this.y--;
+                        this.scroll();
+                      }
+                    } else {
+                      this.x = this.cols-1;
+                      if(ch_width===2)  // FIXME: check for xterm behavior
+                        continue;
+                    }
+                  }
+                  row = this.y + this.ybase;
+
+                  // insert mode: move characters to right
+                  if (this.insertMode) {
+                    // do this twice for a fullwidth char
+                    for (var moves=0; moves<ch_width; ++moves) {
+                      // remove last cell, if it's width is 0
+                      // we have to adjust the second last cell as well
+                      var removed = this.lines[this.y + this.ybase].pop();
+                      if (removed[2]===0
+                          && this.lines[row][this.cols-2]
+                          && this.lines[row][this.cols-2][2]===2)
+                        this.lines[row][this.cols-2] = [this.curAttr, ' ', 1];
+
+                      // insert empty cell at cursor
+                      this.lines[row].splice(this.x, 0, [this.curAttr, ' ', 1]);
                     }
                   }
 
-                  this.lines[this.y + this.ybase][this.x] = [this.curAttr, ch, ch_width];
+                  this.lines[row][this.x] = [this.curAttr, ch, ch_width];
                   this.x++;
                   this.updateRange(this.y);
 
                   // fullwidth char - set next cell width to zero and advance cursor
-                  if (ch_width==2) {
-                    this.lines[this.y + this.ybase][this.x] = [this.curAttr, '', 0];
+                  if (ch_width===2) {
+                    this.lines[row][this.x] = [this.curAttr, '', 0];
                     this.x++;
                   }
                 }
 
       row = this.y + this.ybase;
       j = this.x;
-      ch = [this.eraseAttr(), ' ']; // xterm
+      ch = [this.eraseAttr(), ' ', 1]; // xterm
 
       while (param-- && j < this.cols) {
         this.lines[row].splice(j++, 0, ch);
       if (param < 1) param = 1;
 
       row = this.y + this.ybase;
-      ch = [this.eraseAttr(), ' ']; // xterm
+      ch = [this.eraseAttr(), ' ', 1]; // xterm
 
       while (param--) {
         this.lines[row].splice(this.x, 1);
 
       row = this.y + this.ybase;
       j = this.x;
-      ch = [this.eraseAttr(), ' ']; // xterm
+      ch = [this.eraseAttr(), ' ', 1]; // xterm
 
       while (param-- && j < this.cols) {
         this.lines[row][j++] = ch;
     Terminal.prototype.repeatPrecedingCharacter = function(params) {
       var param = params[0] || 1
         , line = this.lines[this.ybase + this.y]
-        , ch = line[this.x - 1] || [this.defAttr, ' '];
+        , ch = line[this.x - 1] || [this.defAttr, ' ', 1];
 
       while (param--) line[this.x++] = ch;
     };
         , i
         , ch;
 
-      ch = [this.eraseAttr(), ' ']; // xterm?
+      ch = [this.eraseAttr(), ' ', 1]; // xterm?
 
       for (; t < b + 1; t++) {
         line = this.lines[this.ybase + t];
     Terminal.prototype.insertColumns = function() {
       var param = params[0]
         , l = this.ybase + this.rows
-        , ch = [this.eraseAttr(), ' '] // xterm?
+        , ch = [this.eraseAttr(), ' ', 1] // xterm?
         , i;
 
       while (param--) {
     Terminal.prototype.deleteColumns = function() {
       var param = params[0]
         , l = this.ybase + this.rows
-        , ch = [this.eraseAttr(), ' '] // xterm?
+        , ch = [this.eraseAttr(), ' ', 1] // xterm?
         , i;
 
       while (param--) {
index 57bfd90b2bd56d9b989887a7fbe9240760953e8e..4b3dd79f49da1ffa9da81fc6524e601836ffe177 100644 (file)
@@ -1,5 +1,5 @@
 var assert = require('chai').assert;
-var chai = require('chai');
+var expect = require('chai').expect;
 var Terminal = require('../src/xterm');
 
 describe('xterm.js', function() {
@@ -192,260 +192,307 @@ describe('xterm.js', function() {
     });
   });
 
-describe('unicode - surrogates', function() {
+  describe('unicode - surrogates', function() {
     it('2 characters per cell', function () {
-        var high = '\uD800';
-        for (var i=0xDC00; i<=0xDCFF; ++i) {
-            xterm.write(high + String.fromCharCode(i));
-            var tchar = xterm.lines[0][0];
-            chai.expect(tchar[1]).eql(high + String.fromCharCode(i));
-            chai.expect(tchar[1].length).eql(2);
-            chai.expect(tchar[2]).eql(1);
-            chai.expect(xterm.lines[0][1][1]).eql(' ');
-            xterm.reset();
-        }
+      var high = '\uD800';
+      for (var i=0xDC00; i<=0xDCFF; ++i) {
+        xterm.write(high + String.fromCharCode(i));
+        var tchar = xterm.lines[0][0];
+        expect(tchar[1]).eql(high + String.fromCharCode(i));
+        expect(tchar[1].length).eql(2);
+        expect(tchar[2]).eql(1);
+        expect(xterm.lines[0][1][1]).eql(' ');
+        xterm.reset();
+      }
     });
-    it('2 characters at last cell', function () {
-        var high = '\uD800';
-        for (var i=0xDC00; i<=0xDCFF; ++i) {
-            xterm.x = xterm.cols - 1;
-            xterm.write(high + String.fromCharCode(i));
-            chai.expect(xterm.lines[0][xterm.x-1][1]).eql(high + String.fromCharCode(i));
-            chai.expect(xterm.lines[0][xterm.x-1][1].length).eql(2);
-            chai.expect(xterm.lines[1][0][1]).eql(' ');
-            xterm.reset();
-        }
+    it('2 characters at last cell', function() {
+      var high = '\uD800';
+      for (var i=0xDC00; i<=0xDCFF; ++i) {
+        xterm.x = xterm.cols - 1;
+        xterm.write(high + String.fromCharCode(i));
+        expect(xterm.lines[0][xterm.x-1][1]).eql(high + String.fromCharCode(i));
+        expect(xterm.lines[0][xterm.x-1][1].length).eql(2);
+        expect(xterm.lines[1][0][1]).eql(' ');
+        xterm.reset();
+      }
     });
-    it('2 characters per cell over line end with autowrap', function () {
-        var high = '\uD800';
-        for (var i=0xDC00; i<=0xDCFF; ++i) {
-            xterm.x = xterm.cols - 1;
-            xterm.wraparoundMode = true;
-            xterm.write('a' + high + String.fromCharCode(i));
-            chai.expect(xterm.lines[0][xterm.cols-1][1]).eql('a');
-            chai.expect(xterm.lines[1][0][1]).eql(high + String.fromCharCode(i));
-            chai.expect(xterm.lines[1][0][1].length).eql(2);
-            chai.expect(xterm.lines[1][1][1]).eql(' ');
-            xterm.reset();
-        }
+    it('2 characters per cell over line end with autowrap', function() {
+      var high = '\uD800';
+      for (var i=0xDC00; i<=0xDCFF; ++i) {
+        xterm.x = xterm.cols - 1;
+        xterm.wraparoundMode = true;
+        xterm.write('a' + high + String.fromCharCode(i));
+        expect(xterm.lines[0][xterm.cols-1][1]).eql('a');
+        expect(xterm.lines[1][0][1]).eql(high + String.fromCharCode(i));
+        expect(xterm.lines[1][0][1].length).eql(2);
+        expect(xterm.lines[1][1][1]).eql(' ');
+        xterm.reset();
+      }
     });
-    /** FIXME - wrap is not respected in default state */
-    /*
-    it('2 characters per cell over line end without autowrap', function () {
-        var high = '\uD800';
-        for (var i=0xDC00; i<=0xDCFF; ++i) {
-            xterm.x = xterm.cols - 1;
-            xterm.wraparoundMode = false;
-            xterm.write('a' + high + String.fromCharCode(i));
-            chai.expect(xterm.lines[0][xterm.cols-1][1]).eql(high + String.fromCharCode(i));
-            chai.expect(xterm.lines[0][xterm.cols-1][1].length).eql(2);
-            chai.expect(xterm.lines[1][1][1]).eql(' ');
-            xterm.reset();
-        }
+    it('2 characters per cell over line end without autowrap', function() {
+      var high = '\uD800';
+      for (var i=0xDC00; i<=0xDCFF; ++i) {
+        xterm.x = xterm.cols - 1;
+        xterm.wraparoundMode = false;
+        xterm.write('a' + high + String.fromCharCode(i));
+        expect(xterm.lines[0][xterm.cols-1][1]).eql(high + String.fromCharCode(i));
+        expect(xterm.lines[0][xterm.cols-1][1].length).eql(2);
+        expect(xterm.lines[1][1][1]).eql(' ');
+        xterm.reset();
+      }
     });
-    */
-    it('splitted surrogates', function () {
-        var high = '\uD800';
-        for (var i=0xDC00; i<=0xDCFF; ++i) {
-            xterm.write(high);
-            xterm.write(String.fromCharCode(i));
-            var tchar = xterm.lines[0][0];
-            chai.expect(tchar[1]).eql(high + String.fromCharCode(i));
-            chai.expect(tchar[1].length).eql(2);
-            chai.expect(tchar[2]).eql(1);
-            chai.expect(xterm.lines[0][1][1]).eql(' ');
-            xterm.reset();
-        }
+    it('splitted surrogates', function() {
+      var high = '\uD800';
+      for (var i=0xDC00; i<=0xDCFF; ++i) {
+        xterm.write(high);
+        xterm.write(String.fromCharCode(i));
+        var tchar = xterm.lines[0][0];
+        expect(tchar[1]).eql(high + String.fromCharCode(i));
+        expect(tchar[1].length).eql(2);
+        expect(tchar[2]).eql(1);
+        expect(xterm.lines[0][1][1]).eql(' ');
+        xterm.reset();
+      }
     });
-});
-describe('unicode - combining characters', function() {
+  });
+
+  describe('unicode - combining characters', function() {
     it('café', function () {
-        xterm.write('cafe\u0301');
-        chai.expect(xterm.lines[0][3][1]).eql('e\u0301');
-        chai.expect(xterm.lines[0][3][1].length).eql(2);
-        chai.expect(xterm.lines[0][3][2]).eql(1);
+      xterm.write('cafe\u0301');
+      expect(xterm.lines[0][3][1]).eql('e\u0301');
+      expect(xterm.lines[0][3][1].length).eql(2);
+      expect(xterm.lines[0][3][2]).eql(1);
     });
-    it('café - end of line', function () {
-        xterm.x = xterm.cols - 1 - 3;
-        xterm.write('cafe\u0301');
-        chai.expect(xterm.lines[0][xterm.cols-1][1]).eql('e\u0301');
-        chai.expect(xterm.lines[0][xterm.cols-1][1].length).eql(2);
-        chai.expect(xterm.lines[0][xterm.cols-1][2]).eql(1);
-        chai.expect(xterm.lines[0][1][1]).eql(' ');
-        chai.expect(xterm.lines[0][1][1].length).eql(1);
-        chai.expect(xterm.lines[0][1][2]).eql(1);
+    it('café - end of line', function() {
+      xterm.x = xterm.cols - 1 - 3;
+      xterm.write('cafe\u0301');
+      expect(xterm.lines[0][xterm.cols-1][1]).eql('e\u0301');
+      expect(xterm.lines[0][xterm.cols-1][1].length).eql(2);
+      expect(xterm.lines[0][xterm.cols-1][2]).eql(1);
+      expect(xterm.lines[0][1][1]).eql(' ');
+      expect(xterm.lines[0][1][1].length).eql(1);
+      expect(xterm.lines[0][1][2]).eql(1);
     });
-    it('multiple combined é', function () {
-        xterm.write(Array(100).join('e\u0301'));
-        for (var i=0; i<xterm.cols; ++i) {
-            var tchar = xterm.lines[0][i];
-            chai.expect(tchar[1]).eql('e\u0301');
-            chai.expect(tchar[1].length).eql(2);
-            chai.expect(tchar[2]).eql(1);
-        }
-        tchar = xterm.lines[1][0];
-        chai.expect(tchar[1]).eql('e\u0301');
-        chai.expect(tchar[1].length).eql(2);
-        chai.expect(tchar[2]).eql(1);
+    it('multiple combined é', function() {
+      xterm.wraparoundMode = true;
+      xterm.write(Array(100).join('e\u0301'));
+      for (var i=0; i<xterm.cols; ++i) {
+        var tchar = xterm.lines[0][i];
+        expect(tchar[1]).eql('e\u0301');
+        expect(tchar[1].length).eql(2);
+        expect(tchar[2]).eql(1);
+      }
+      tchar = xterm.lines[1][0];
+      expect(tchar[1]).eql('e\u0301');
+      expect(tchar[1].length).eql(2);
+      expect(tchar[2]).eql(1);
     });
-    it('multiple surrogate with combined', function () {
-        xterm.write(Array(100).join('\uD800\uDC00\u0301'));
-        for (var i=0; i<xterm.cols; ++i) {
-            var tchar = xterm.lines[0][i];
-            chai.expect(tchar[1]).eql('\uD800\uDC00\u0301');
-            chai.expect(tchar[1].length).eql(3);
-            chai.expect(tchar[2]).eql(1);
-        }
-        tchar = xterm.lines[1][0];
-        chai.expect(tchar[1]).eql('\uD800\uDC00\u0301');
-        chai.expect(tchar[1].length).eql(3);
-        chai.expect(tchar[2]).eql(1);
+    it('multiple surrogate with combined', function() {
+      xterm.wraparoundMode = true;
+      xterm.write(Array(100).join('\uD800\uDC00\u0301'));
+      for (var i=0; i<xterm.cols; ++i) {
+        var tchar = xterm.lines[0][i];
+        expect(tchar[1]).eql('\uD800\uDC00\u0301');
+        expect(tchar[1].length).eql(3);
+        expect(tchar[2]).eql(1);
+      }
+      tchar = xterm.lines[1][0];
+      expect(tchar[1]).eql('\uD800\uDC00\u0301');
+      expect(tchar[1].length).eql(3);
+      expect(tchar[2]).eql(1);
     });
-});
+  });
 
-describe('unicode - fullwidth characters', function() {
-    it('cursor movement even', function () {
-        chai.expect(xterm.x).eql(0);
-        xterm.write('¥');
-        chai.expect(xterm.x).eql(2);
+  describe('unicode - fullwidth characters', function() {
+    it('cursor movement even', function() {
+      expect(xterm.x).eql(0);
+      xterm.write('¥');
+      expect(xterm.x).eql(2);
     });
-    it('cursor movement odd', function () {
-        xterm.x = 1;
-        chai.expect(xterm.x).eql(1);
-        xterm.write('¥');
-        chai.expect(xterm.x).eql(3);
+    it('cursor movement odd', function() {
+      xterm.x = 1;
+      expect(xterm.x).eql(1);
+      xterm.write('¥');
+      expect(xterm.x).eql(3);
     });
-    it('line of ¥ even', function () {
-        xterm.write(Array(50).join('¥'));
-        for (var i=0; i<xterm.cols; ++i) {
-            var tchar = xterm.lines[0][i];
-            if (i % 2) {
-                chai.expect(tchar[1]).eql('');
-                chai.expect(tchar[1].length).eql(0);
-                chai.expect(tchar[2]).eql(0);
-            } else {
-                chai.expect(tchar[1]).eql('¥');
-                chai.expect(tchar[1].length).eql(1);
-                chai.expect(tchar[2]).eql(2);
-            }
+    it('line of ¥ even', function() {
+      xterm.wraparoundMode = true;
+      xterm.write(Array(50).join('¥'));
+      for (var i=0; i<xterm.cols; ++i) {
+        var tchar = xterm.lines[0][i];
+        if (i % 2) {
+          expect(tchar[1]).eql('');
+          expect(tchar[1].length).eql(0);
+          expect(tchar[2]).eql(0);
+        } else {
+          expect(tchar[1]).eql('¥');
+          expect(tchar[1].length).eql(1);
+          expect(tchar[2]).eql(2);
         }
-        tchar = xterm.lines[1][0];
-        chai.expect(tchar[1]).eql('¥');
-        chai.expect(tchar[1].length).eql(1);
-        chai.expect(tchar[2]).eql(2);
+      }
+      tchar = xterm.lines[1][0];
+      expect(tchar[1]).eql('¥');
+      expect(tchar[1].length).eql(1);
+      expect(tchar[2]).eql(2);
     });
-    it('line of ¥ odd', function () {
-        xterm.x = 1;
-        xterm.write(Array(50).join('¥'));
-        for (var i=1; i<xterm.cols-1; ++i) {
-            var tchar = xterm.lines[0][i];
-            if (!(i % 2)) {
-                chai.expect(tchar[1]).eql('');
-                chai.expect(tchar[1].length).eql(0);
-                chai.expect(tchar[2]).eql(0);
-            } else {
-                chai.expect(tchar[1]).eql('¥');
-                chai.expect(tchar[1].length).eql(1);
-                chai.expect(tchar[2]).eql(2);
-            }
+    it('line of ¥ odd', function() {
+      xterm.wraparoundMode = true;
+      xterm.x = 1;
+      xterm.write(Array(50).join('¥'));
+      for (var i=1; i<xterm.cols-1; ++i) {
+        var tchar = xterm.lines[0][i];
+        if (!(i % 2)) {
+          expect(tchar[1]).eql('');
+          expect(tchar[1].length).eql(0);
+          expect(tchar[2]).eql(0);
+        } else {
+          expect(tchar[1]).eql('¥');
+          expect(tchar[1].length).eql(1);
+          expect(tchar[2]).eql(2);
         }
-        tchar = xterm.lines[0][xterm.cols-1];
-        chai.expect(tchar[1]).eql(' ');
-        chai.expect(tchar[1].length).eql(1);
-        chai.expect(tchar[2]).eql(1);
-        tchar = xterm.lines[1][0];
-        chai.expect(tchar[1]).eql('¥');
-        chai.expect(tchar[1].length).eql(1);
-        chai.expect(tchar[2]).eql(2);
+      }
+      tchar = xterm.lines[0][xterm.cols-1];
+      expect(tchar[1]).eql(' ');
+      expect(tchar[1].length).eql(1);
+      expect(tchar[2]).eql(1);
+      tchar = xterm.lines[1][0];
+      expect(tchar[1]).eql('¥');
+      expect(tchar[1].length).eql(1);
+      expect(tchar[2]).eql(2);
     });
-    it('line of ¥ with combining odd', function () {
-        xterm.x = 1;
-        xterm.write(Array(50).join('¥\u0301'));
-        for (var i=1; i<xterm.cols-1; ++i) {
-            var tchar = xterm.lines[0][i];
-            if (!(i % 2)) {
-                chai.expect(tchar[1]).eql('');
-                chai.expect(tchar[1].length).eql(0);
-                chai.expect(tchar[2]).eql(0);
-            } else {
-                chai.expect(tchar[1]).eql('¥\u0301');
-                chai.expect(tchar[1].length).eql(2);
-                chai.expect(tchar[2]).eql(2);
-            }
+    it('line of ¥ with combining odd', function() {
+      xterm.wraparoundMode = true;
+      xterm.x = 1;
+      xterm.write(Array(50).join('¥\u0301'));
+      for (var i=1; i<xterm.cols-1; ++i) {
+        var tchar = xterm.lines[0][i];
+        if (!(i % 2)) {
+          expect(tchar[1]).eql('');
+          expect(tchar[1].length).eql(0);
+          expect(tchar[2]).eql(0);
+        } else {
+          expect(tchar[1]).eql('¥\u0301');
+          expect(tchar[1].length).eql(2);
+          expect(tchar[2]).eql(2);
         }
-        tchar = xterm.lines[0][xterm.cols-1];
-        chai.expect(tchar[1]).eql(' ');
-        chai.expect(tchar[1].length).eql(1);
-        chai.expect(tchar[2]).eql(1);
-        tchar = xterm.lines[1][0];
-        chai.expect(tchar[1]).eql('¥\u0301');
-        chai.expect(tchar[1].length).eql(2);
-        chai.expect(tchar[2]).eql(2);
+      }
+      tchar = xterm.lines[0][xterm.cols-1];
+      expect(tchar[1]).eql(' ');
+      expect(tchar[1].length).eql(1);
+      expect(tchar[2]).eql(1);
+      tchar = xterm.lines[1][0];
+      expect(tchar[1]).eql('¥\u0301');
+      expect(tchar[1].length).eql(2);
+      expect(tchar[2]).eql(2);
     });
-    it('line of ¥ with combining even', function () {
-        xterm.write(Array(50).join('¥\u0301'));
-        for (var i=0; i<xterm.cols; ++i) {
-            var tchar = xterm.lines[0][i];
-            if (i % 2) {
-                chai.expect(tchar[1]).eql('');
-                chai.expect(tchar[1].length).eql(0);
-                chai.expect(tchar[2]).eql(0);
-            } else {
-                chai.expect(tchar[1]).eql('¥\u0301');
-                chai.expect(tchar[1].length).eql(2);
-                chai.expect(tchar[2]).eql(2);
-            }
+    it('line of ¥ with combining even', function() {
+      xterm.wraparoundMode = true;
+      xterm.write(Array(50).join('¥\u0301'));
+      for (var i=0; i<xterm.cols; ++i) {
+        var tchar = xterm.lines[0][i];
+        if (i % 2) {
+          expect(tchar[1]).eql('');
+          expect(tchar[1].length).eql(0);
+          expect(tchar[2]).eql(0);
+        } else {
+          expect(tchar[1]).eql('¥\u0301');
+          expect(tchar[1].length).eql(2);
+          expect(tchar[2]).eql(2);
         }
-        tchar = xterm.lines[1][0];
-        chai.expect(tchar[1]).eql('¥\u0301');
-        chai.expect(tchar[1].length).eql(2);
-        chai.expect(tchar[2]).eql(2);
+      }
+      tchar = xterm.lines[1][0];
+      expect(tchar[1]).eql('¥\u0301');
+      expect(tchar[1].length).eql(2);
+      expect(tchar[2]).eql(2);
     });
-    it('line of surrogate fullwidth with combining odd', function () {
-        xterm.x = 1;
-        xterm.write(Array(50).join('\ud843\ude6d\u0301'));
-        for (var i=1; i<xterm.cols-1; ++i) {
-            var tchar = xterm.lines[0][i];
-            if (!(i % 2)) {
-                chai.expect(tchar[1]).eql('');
-                chai.expect(tchar[1].length).eql(0);
-                chai.expect(tchar[2]).eql(0);
-            } else {
-                chai.expect(tchar[1]).eql('\ud843\ude6d\u0301');
-                chai.expect(tchar[1].length).eql(3);
-                chai.expect(tchar[2]).eql(2);
-            }
+    it('line of surrogate fullwidth with combining odd', function() {
+      xterm.wraparoundMode = true;
+      xterm.x = 1;
+      xterm.write(Array(50).join('\ud843\ude6d\u0301'));
+      for (var i=1; i<xterm.cols-1; ++i) {
+        var tchar = xterm.lines[0][i];
+        if (!(i % 2)) {
+          expect(tchar[1]).eql('');
+          expect(tchar[1].length).eql(0);
+          expect(tchar[2]).eql(0);
+        } else {
+          expect(tchar[1]).eql('\ud843\ude6d\u0301');
+          expect(tchar[1].length).eql(3);
+          expect(tchar[2]).eql(2);
         }
-        tchar = xterm.lines[0][xterm.cols-1];
-        chai.expect(tchar[1]).eql(' ');
-        chai.expect(tchar[1].length).eql(1);
-        chai.expect(tchar[2]).eql(1);
-        tchar = xterm.lines[1][0];
-        chai.expect(tchar[1]).eql('\ud843\ude6d\u0301');
-        chai.expect(tchar[1].length).eql(3);
-        chai.expect(tchar[2]).eql(2);
+      }
+      tchar = xterm.lines[0][xterm.cols-1];
+      expect(tchar[1]).eql(' ');
+      expect(tchar[1].length).eql(1);
+      expect(tchar[2]).eql(1);
+      tchar = xterm.lines[1][0];
+      expect(tchar[1]).eql('\ud843\ude6d\u0301');
+      expect(tchar[1].length).eql(3);
+      expect(tchar[2]).eql(2);
     });
-    it('line of surrogate fullwidth with combining even', function () {
-        xterm.write(Array(50).join('\ud843\ude6d\u0301'));
-        for (var i=0; i<xterm.cols; ++i) {
-            var tchar = xterm.lines[0][i];
-            if (i % 2) {
-                chai.expect(tchar[1]).eql('');
-                chai.expect(tchar[1].length).eql(0);
-                chai.expect(tchar[2]).eql(0);
-            } else {
-                chai.expect(tchar[1]).eql('\ud843\ude6d\u0301');
-                chai.expect(tchar[1].length).eql(3);
-                chai.expect(tchar[2]).eql(2);
-            }
+    it('line of surrogate fullwidth with combining even', function() {
+      xterm.wraparoundMode = true;
+      xterm.write(Array(50).join('\ud843\ude6d\u0301'));
+      for (var i=0; i<xterm.cols; ++i) {
+        var tchar = xterm.lines[0][i];
+        if (i % 2) {
+          expect(tchar[1]).eql('');
+          expect(tchar[1].length).eql(0);
+          expect(tchar[2]).eql(0);
+        } else {
+          expect(tchar[1]).eql('\ud843\ude6d\u0301');
+          expect(tchar[1].length).eql(3);
+          expect(tchar[2]).eql(2);
         }
-        tchar = xterm.lines[1][0];
-        chai.expect(tchar[1]).eql('\ud843\ude6d\u0301');
-        chai.expect(tchar[1].length).eql(3);
-        chai.expect(tchar[2]).eql(2);
+      }
+      tchar = xterm.lines[1][0];
+      expect(tchar[1]).eql('\ud843\ude6d\u0301');
+      expect(tchar[1].length).eql(3);
+      expect(tchar[2]).eql(2);
     });
-});
-
-
+  });
 
+  describe('insert mode', function() {
+    it('halfwidth - all', function () {
+      xterm.write(Array(9).join('0123456789').slice(-80));
+      xterm.x = 10;
+      xterm.y = 0;
+      xterm.insertMode = true;
+      xterm.write('abcde');
+      expect(xterm.lines[0].length).eql(xterm.cols);
+      expect(xterm.lines[0][10][1]).eql('a');
+      expect(xterm.lines[0][14][1]).eql('e');
+      expect(xterm.lines[0][15][1]).eql('0');
+      expect(xterm.lines[0][79][1]).eql('4');
+    });
+    it('fullwidth - insert', function() {
+      xterm.write(Array(9).join('0123456789').slice(-80));
+      xterm.x = 10;
+      xterm.y = 0;
+      xterm.insertMode = true;
+      xterm.write('¥¥¥');
+      expect(xterm.lines[0].length).eql(xterm.cols);
+      expect(xterm.lines[0][10][1]).eql('¥');
+      expect(xterm.lines[0][11][1]).eql('');
+      expect(xterm.lines[0][14][1]).eql('¥');
+      expect(xterm.lines[0][15][1]).eql('');
+      expect(xterm.lines[0][79][1]).eql('3');
+    });
+    it('fullwidth - right border', function() {
+      xterm.write(Array(41).join('¥'));
+      xterm.x = 10;
+      xterm.y = 0;
+      xterm.insertMode = true;
+      xterm.write('a');
+      expect(xterm.lines[0].length).eql(xterm.cols);
+      expect(xterm.lines[0][10][1]).eql('a');
+      expect(xterm.lines[0][11][1]).eql('¥');
+      expect(xterm.lines[0][79][1]).eql(' ');  // fullwidth char got replaced
+      xterm.write('b');
+      expect(xterm.lines[0].length).eql(xterm.cols);
+      expect(xterm.lines[0][11][1]).eql('b');
+      expect(xterm.lines[0][12][1]).eql('¥');
+      expect(xterm.lines[0][79][1]).eql('');  // empty cell after fullwidth
+    });
+  });
 });