From 25133923e3006faf5f8fb0f53290991c43febc2a Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 24 Jul 2013 21:21:20 -0500 Subject: [PATCH] allow text to be obfuscated within child elements during a scroll. --- lib/widget.js | 84 ++++++++++++--------------------- test/widget-scrollable-boxes.js | 17 +------ 2 files changed, 33 insertions(+), 68 deletions(-) diff --git a/lib/widget.js b/lib/widget.js index b15a629..48e0d29 100644 --- a/lib/widget.js +++ b/lib/widget.js @@ -1867,22 +1867,21 @@ Element.prototype.parseContent = function() { || this._clines.width !== width || this._clines.content !== this.content) { var content = this.content; - // Possibly keep this for set/get/insert/etcLine - // Although, it may not work since the lines handled - // by those methods need to be wrapped. If the line - // indexes were only within the context of the box - // (e.g. line 0 is always the top of the box) like they - // were before, this may be feasible. - // this._oclines = content.split('\n'); - // Could move these 2 lines back to setContent (?) - content = content.replace(/\x1b(?!\[[\d;]*m)/g, ''); - content = content.replace(/\r/g, ''); + content = content + .replace(/[\x00-\x08\x0b-\x0c\x0e-\x1a\x1c-\x1f\x7f]/g, '') + .replace(/\x1b(?!\[[\d;]*m)/g, '') + .replace(/\r\n|\r/g, '\n') + .replace(/\t/g, this.screen.tabc); content = this._parseTags(content); - content = content.replace(/\t/g, this.screen.tabc); this._clines = this._wrapContent(content, width); this._clines.width = width; this._clines.content = this.content; this._clines.attr = this._parseAttr(this._clines); + this._clines.ci = []; + this._clines.reduce(function(total, line) { + this._clines.ci.push(total); + return total + line.length + 1; + }.bind(this), 0); this._pcontent = this._clines.join('\n'); this.emit('parsed content'); return true; @@ -1925,7 +1924,7 @@ Element.prototype._parseAttr = function(lines) { } if (!this.scrollable) { - return; + //return; } for (j = 0; j < lines.length; j++) { @@ -2638,7 +2637,8 @@ Element.prototype._getCoords = function(get) { , ryl , visible , coords - , v; + , v + , base; // Find a scrollable ancestor if we have one. var el = this; @@ -2657,10 +2657,10 @@ Element.prototype._getCoords = function(get) { // a scrollable box are screwy unless we do this. // We only do this when `get` is true, because that gets this.parent.lpos. // If it's false, the parent's position is calculated on the spot. - var cb = el.childBase; + var _cb = el.childBase; if (get) { - yi += this.parent.lpos.cb; - yl += this.parent.lpos.cb; + yi += this.parent.lpos._cb; + yl += this.parent.lpos._cb; } ryi = yi - el._getTop(get) - el.itop; @@ -2671,8 +2671,9 @@ Element.prototype._getCoords = function(get) { if (ryl > el.childBase) { // Is partially covered above. v = ryl - el.childBase; - yi += (ryl - ryi) - v; - return; + v = (ryl - ryi) - v; + base = (this.childBase || 0) + v; + yi += v; } else { // Is above. return; @@ -2684,7 +2685,6 @@ Element.prototype._getCoords = function(get) { // Is partially covered below. v = el.childBase + visible + (yl - yi) - ryl; yl = yi + v; - return; } yi -= el.childBase; @@ -2704,7 +2704,8 @@ Element.prototype._getCoords = function(get) { xl: xl, yi: yi, yl: yl, - cb: cb || 0 + _cb: _cb || 0, + base: base || this.childBase || 0 }; }; @@ -2727,7 +2728,7 @@ Element.prototype.render = function() { , attr , ch , content = this._pcontent - , ci = this.contentIndex || 0 + , ci = this._clines.ci[coords.base] , battr , dattr , c @@ -2735,6 +2736,10 @@ Element.prototype.render = function() { , visible , i; + if (coords.base >= this._clines.ci.length) { + ci = this._pcontent.length; + } + this.lpos = coords; dattr = this.sattr(this.style, this.style.fg, this.style.bg); @@ -2742,8 +2747,8 @@ Element.prototype.render = function() { // If we're in a scrollable text box, check to // see which attributes this line starts with. - if (this.scrollable) { - attr = this._clines.attr[Math.min(this.childBase, this._clines.length - 1)]; + if (ci > 0) { + attr = this._clines.attr[Math.min(coords.base, this._clines.length - 1)]; } if (this.border) xi++, xl--, yi++, yl--; @@ -2798,7 +2803,7 @@ Element.prototype.render = function() { // Handle newlines. if (ch === '\t') ch = ' '; - if (ch === '\n' || ch === '\r') { + if (ch === '\n') { // If we're on the first cell and we find a newline and the last cell // of the last line was not a newline, let's just treat this like the // newline was already "counted". @@ -3222,7 +3227,6 @@ function ScrollableBox(options) { this.scrollable = true; this.childOffset = 0; this.childBase = 0; - this.contentIndex = 0; this.baseLimit = options.baseLimit || Infinity; this.alwaysScroll = options.alwaysScroll; @@ -3346,10 +3350,8 @@ ScrollableBox.prototype.scroll = function(offset, always) { , p , t , b - , i , max - , emax - , l; + , emax; if (this.alwaysScroll || always) { // Semi-workaround @@ -3401,19 +3403,6 @@ ScrollableBox.prototype.scroll = function(offset, always) { this.childBase = this.baseLimit; } - if (this.childBase > base) { - l = Math.min(this.childBase, this._clines.length); - for (i = base; i < l; i++) { - this.contentIndex += this._clines[i].length + 1; - } - } else if (this.childBase < base) { - b = Math.min(base, this._clines.length); - l = Math.min(this.childBase, this._clines.length); - for (i = b - 1; i >= l; i--) { - this.contentIndex -= this._clines[i].length + 1; - } - } - // Optimize scrolling with CSR + IL/DL. p = this.lpos; // Only really need _getCoords() if we want @@ -3440,10 +3429,9 @@ ScrollableBox.prototype.scroll = function(offset, always) { }; ScrollableBox.prototype._recalculateIndex = function() { - var max, emax, i, t, l; + var max, emax; if (this.detached || !this.scrollable) { - this.contentIndex = 0; return 0; } @@ -3459,20 +3447,10 @@ ScrollableBox.prototype._recalculateIndex = function() { } else if (this.childBase > this.baseLimit) { this.childBase = this.baseLimit; } - - l = Math.min(this.childBase, this._clines.length); - for (i = 0, t = 0; i < l; i++) { - t += this._clines[i].length + 1; - } - - this.contentIndex = t; - - return t; }; ScrollableBox.prototype.resetScroll = function() { if (!this.scrollable) return; - this.contentIndex = 0; this.childOffset = 0; this.childBase = 0; return this.emit('scroll'); diff --git a/test/widget-scrollable-boxes.js b/test/widget-scrollable-boxes.js index c801951..24bf5da 100644 --- a/test/widget-scrollable-boxes.js +++ b/test/widget-scrollable-boxes.js @@ -24,14 +24,14 @@ var box = blessed.scrollablebox({ var text = blessed.box({ parent: box, - content: 'hello', + content: 'hello1\nhello2\nhello3\nhello4', style: { bg: 'red' }, left: 2, top: 30, width: '50%', - height: 4 + height: 6 }); var text2 = blessed.box({ @@ -50,19 +50,6 @@ screen.key('q', function() { return process.exit(0); }); -box.on('keypress', function(ch, key) { - if (key.name === 'up' || key.name === 'k') { - box.scroll(-1); - screen.render(); - return; - } - if (key.name === 'down' || key.name === 'j') { - box.scroll(1); - screen.render(); - return; - } -}); - box.focus(); screen.render();