diff --git a/lib/widgets/textarea.js b/lib/widgets/textarea.js index dc94609c..0c3245a0 100644 --- a/lib/widgets/textarea.js +++ b/lib/widgets/textarea.js @@ -34,6 +34,9 @@ function Textarea(options) { this.screen._listenKeys(this); + this.offsetY = 0; + this.offsetX = 0; + this.value = options.value || ''; this.__updateCursor = this._updateCursor.bind(this); @@ -69,15 +72,44 @@ Textarea.prototype.__proto__ = Input.prototype; Textarea.prototype.type = 'textarea'; +Textarea.prototype.getCursor = function(){ + return {x: this.offsetX, y: this.offsetY}; +} + +Textarea.prototype.moveCursor = function(x, y){ + var prevLine = (this._clines.length - 1) + this.offsetY; + let sync = false; + if (y <= 0 && y > (this._clines.length * -1)){ + sync = this.offsetY !== y; + this.offsetY = y; + } + var currentLine = (this._clines.length - 1) + this.offsetY; + var currentText = this._clines[currentLine]; + + if (sync){ + var prevText = this._clines[prevLine]; + var positionFromBegin = this.strWidth(prevText) + this.offsetX; + x = (Math.max(0, this.strWidth(currentText) - positionFromBegin)) * -1; + } + if (x <= 0 && x >= (this.strWidth(currentText) * -1)){ + this.offsetX = x; + } + this._updateCursor(true); + + this.screen.render(); +} + Textarea.prototype._updateCursor = function(get) { if (this.screen.focused !== this) { return; } var lpos = get ? this.lpos : this._getCoords(); + if (!lpos) return; - var last = this._clines[this._clines.length - 1] + const currentLine = (this._clines.length - 1) + this.offsetY + var currentText = this._clines[currentLine] , program = this.screen.program , line , cx @@ -87,12 +119,12 @@ Textarea.prototype._updateCursor = function(get) { // and the last cline appears to always be empty from the // _typeScroll `+ '\n'` thing. // Maybe not necessary anymore? - if (last === '' && this.value[this.value.length - 1] !== '\n') { - last = this._clines[this._clines.length - 2] || ''; + if (currentText === '' && this.value[this.value.length - 1] !== '\n') { + currentText = this._clines[currentLine - 1] || ''; } line = Math.min( - this._clines.length - 1 - (this.childBase || 0), + currentLine - (this.childBase || 0), (lpos.yl - lpos.yi) - this.iheight - 1); // When calling clearValue() on a full textarea with a border, the first @@ -101,7 +133,7 @@ Textarea.prototype._updateCursor = function(get) { line = Math.max(0, line); cy = lpos.yi + this.itop + line; - cx = lpos.xi + this.ileft + this.strWidth(last); + cx = this.offsetX + lpos.xi + this.ileft + this.strWidth(currentText); // XXX Not sure, but this may still sometimes // cause problems when leaving editor. @@ -218,7 +250,20 @@ Textarea.prototype._listener = function(ch, key) { // TODO: Handle directional keys. if (key.name === 'left' || key.name === 'right' || key.name === 'up' || key.name === 'down') { - ; + var cursor = this.getCursor(); + + if (key.name === "left") { + cursor.x--; + } else if (key.name === "right") { + cursor.x++; + } + if (key.name === "up") { + cursor.y--; + } else if (key.name === "down") { + cursor.y++; + } + + this.moveCursor(cursor.x, cursor.y); } if (this.options.keys && key.ctrl && key.name === 'e') { @@ -239,12 +284,28 @@ Textarea.prototype._listener = function(ch, key) { this.value = this.value.slice(0, -1); } } else { - this.value = this.value.slice(0, -1); + if (this.offsetX === 0 && this.offsetY === 0){ + this.value = this.value.slice(0, -1); + } else if (this.offsetX > (this.value.length * -1)) { + const currentLine = (this._clines.length - 1) + this.offsetY + const copy = this._clines.slice(); + const cursorPosition = copy[currentLine].length + this.offsetX; + copy[currentLine] = copy[currentLine].slice(0, cursorPosition - 1) + copy[currentLine].slice(cursorPosition); + this.value = copy.join('\n'); + } } } } else if (ch) { if (!/^[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]$/.test(ch)) { - this.value += ch; + if (this.offsetX === 0 && this.offsetY === 0){ + this.value += ch; + } else if (this.offsetX >= (this.value.length * -1)) { + const currentLine = (this._clines.length - 1) + this.offsetY + const copy = this._clines.slice(); + const cursorPosition = copy[currentLine].length + this.offsetX; + copy[currentLine] = copy[currentLine].slice(0, cursorPosition) + ch + copy[currentLine].slice(cursorPosition); + this.value = copy.join('\n'); + } } } @@ -257,7 +318,8 @@ Textarea.prototype._typeScroll = function() { // XXX Workaround var height = this.height - this.iheight; if (this._clines.length - this.childBase > height) { - this.scroll(this._clines.length); + const currentLine = (this._clines.length) + this.offsetY + this.scroll(currentLine); } };