From 9a6f1b790d41b854bbe318e13ac8f8129649e778 Mon Sep 17 00:00:00 2001 From: jvanbroe Date: Thu, 13 Feb 2014 13:46:52 -0500 Subject: [PATCH 1/4] * Added Function keys support * Erasing parts of screen done in current bgcolor * added eraseChars escape code * Fixed hardcoded maxColWidth/ lineHeight * Fixed variable names eg. lineheight -> lineHeight * Fixed carriageReturn in Linefeed --- src/parser/AnsiParser.js | 1 - src/parser/CharacterCodes.js | 2 +- src/parser/EscapeSequencer.js | 81 ++++++++++++++++++++++++++++++----- src/parser/Keyboard.js | 16 +++++++ src/viewer/AnsiViewer.js | 63 ++++++++++++++++----------- src/viewer/Cursor.js | 6 +-- 6 files changed, 129 insertions(+), 40 deletions(-) diff --git a/src/parser/AnsiParser.js b/src/parser/AnsiParser.js index 7444771..700a54f 100644 --- a/src/parser/AnsiParser.js +++ b/src/parser/AnsiParser.js @@ -68,7 +68,6 @@ TERM.AnsiParser = function (viewer){ break; case LINE_FEED: - viewer.carriageReturn(); viewer.moveDown(1); break; diff --git a/src/parser/CharacterCodes.js b/src/parser/CharacterCodes.js index e1684af..8f65b06 100644 --- a/src/parser/CharacterCodes.js +++ b/src/parser/CharacterCodes.js @@ -2,7 +2,7 @@ * @author Peter Nitsch */ -const NULL = 0 +const NULL = 0; const START_OF_HEADING = 1; const START_OF_TEXT = 2; const END_OF_TEXT = 3; diff --git a/src/parser/EscapeSequencer.js b/src/parser/EscapeSequencer.js index 50e32f7..cbeec2b 100644 --- a/src/parser/EscapeSequencer.js +++ b/src/parser/EscapeSequencer.js @@ -14,7 +14,8 @@ TERM.EscapeSequencer = function (viewer){ this.init = function() { this.actionCharacterLib[ LATIN_CAPITAL_LETTER_H ] = this.cursorPosition; - this.actionCharacterLib[ LATIN_SMALL_LETTER_F ] = this.cursorPosition; + this.actionCharacterLib[ LATIN_SMALL_LETTER_F ] = this.cursorPosition; + this.actionCharacterLib[ LATIN_CAPITAL_LETTER_G ] = this.cursorPosition; this.actionCharacterLib[ LATIN_CAPITAL_LETTER_A ] = this.cursorUp; this.actionCharacterLib[ LATIN_CAPITAL_LETTER_B ] = this.cursorDown; this.actionCharacterLib[ LATIN_CAPITAL_LETTER_C] = this.cursorForward; @@ -30,6 +31,7 @@ TERM.EscapeSequencer = function (viewer){ this.actionCharacterLib[ LATIN_SMALL_LETTER_P ] = this.setKeyboardStrings; this.actionCharacterLib[ LATIN_CAPITAL_LETTER_M ] = this.scrollUp; this.actionCharacterLib[ LATIN_SMALL_LETTER_R ] = this.scrollScreen; + this.actionCharacterLib[ LATIN_CAPITAL_LETTER_X ] = this.eraseChars; // TO DO this.actionCharacterLib[ LATIN_SMALL_LETTER_A ] = this.unused; @@ -116,22 +118,47 @@ TERM.EscapeSequencer = function (viewer){ } column = parseInt(columnStr); + column = (column>0) ? column-1 : 0; + line = (line>0) ? line-1 : 0; + + viewer.reposition(column, line); + } else if(params.slice(2, params.indexOf(lastCharacter)).length > 0){ - lineArray = params.slice(2, params.length-1); - for( i=0; i0) ? column-1 : 0; + line = (line>0) ? line-1 : 0; + + viewer.reposition(column, line); + + } else if (lastCharacter == LATIN_CAPITAL_LETTER_G) { + columnArray = params.slice(2, params.length-1); + for( i=0; i0) ? column-1 : 0; + + viewer.repositionColumn(column); } - line = parseInt(lineStr); } - column = (column>0) ? column-1 : 0; - line = (line>0) ? line-1 : 0; - viewer.reposition(column, line); } }; + this.cursorUp = function(params) { + if (params[1] == LEFT_PARENTHESIS|| params[1] == RIGHT_PARENTHESIS ) + { + //Set Alternate char set A + return; + } var valueArray = params.slice(2, params.length-1); var valueStr = ""; for( i=0; i 0) ? parseInt(valueStr) : 1; + viewer.eraseChars(value); + }; + + this.eraseDisplay = function(params) { if( params[2]==DIGIT_ONE ){ viewer.eraseUp(); diff --git a/src/parser/Keyboard.js b/src/parser/Keyboard.js index 0854a13..4cf7833 100644 --- a/src/parser/Keyboard.js +++ b/src/parser/Keyboard.js @@ -9,3 +9,19 @@ const KEYBOARD_DOWN = 40; const KEYBOARD_PAGE_UP = 33; const KEYBOARD_PAGE_DOWN = 34; const KEYBOARD_HOME = 36; +const KEYBOARD_ENTER = 13; +const KEYBOARD_BACKSPACE=8; +const KEYBOARD_TAB=9; +const KEYBOARD_ESC=23; +const KEYBOARD_F1 = 112; +const KEYBOARD_F2 = 113; +const KEYBOARD_F3 = 114; +const KEYBOARD_F4 = 115; +const KEYBOARD_F5 = 116; +const KEYBOARD_F6 = 117; +const KEYBOARD_F7 = 118; +const KEYBOARD_F8 = 119; +const KEYBOARD_F9 = 120; +const KEYBOARD_F10 = 121; +const KEYBOARD_F11 = 122; +const KEYBOARD_F12 = 123; diff --git a/src/viewer/AnsiViewer.js b/src/viewer/AnsiViewer.js index 47510bc..687772a 100644 --- a/src/viewer/AnsiViewer.js +++ b/src/viewer/AnsiViewer.js @@ -53,7 +53,7 @@ TERM.AnsiViewer = function (fontmap){ this.draw(character); this.cursor.moveForward(1); - if(!this.cursor.infinitewidth && this.cursor.x + this.cursor.columnwidth > this.cursor.maxColumnwidth * this.cursor.columnwidth){ + if(!this.cursor.infiniteWidth && this.cursor.x + this.cursor.columnWidth > this.cursor.maxColumnWidth * this.cursor.columnWidth){ this.moveDown(1); this.cursor.carriageReturn(); } @@ -90,8 +90,8 @@ TERM.AnsiViewer = function (fontmap){ }; this.moveDown = function(val) { - if(this.cursor.y >= this.cursor.lineheight*(botMargin-1) && scroll){ - this.scrollUp(1); + if(this.cursor.y >= this.cursor.lineHeight*(this.cursor.maxLineHeight-val) && scroll){ + this.scrollUp(val); } else { this.cursor.moveDown(val); } @@ -106,9 +106,14 @@ TERM.AnsiViewer = function (fontmap){ }; this.reposition = function(x, y) { - this.cursor.x = x * this.cursor.columnwidth; - this.cursor.y = y * this.cursor.lineheight; + this.cursor.x = x * this.cursor.columnWidth; + this.cursor.y = y * this.cursor.lineHeight; }; + + this.repositionColumn = function(x) { + this.cursor.x = x * this.cursor.columnWidth; + }; + this.restorePosition = function() { this.cursor.x = _savedPosition.x; @@ -121,41 +126,49 @@ TERM.AnsiViewer = function (fontmap){ }; this.displayCleared = function() { - ctx.fillStyle = BLACK_NORMAL; - ctx.fillRect(0, 0, this.cursor.maxColumnwidth * this.cursor.columnwidth, this.cursor.maxLineheight * this.cursor.lineheight); + ctx.fillStyle = this.cursor.backgroundColor; + ctx.fillRect(0, 0, this.cursor.maxColumnWidth * this.cursor.columnWidth, this.cursor.maxLineHeight * this.cursor.lineHeight); }; + this.eraseUp = function() { - ctx.fillStyle = BLACK_NORMAL; - ctx.fillRect(0, 0, this.cursor.maxColumnwidth * this.cursor.columnwidth, this.cursor.y); + ctx.fillStyle = this.cursor.backgroundColor; + ctx.fillRect(0, 0, this.cursor.maxColumnWidth * this.cursor.columnWidth, this.cursor.y); }; this.eraseScreen = function() { ctx.fillStyle = this.cursor.backgroundColor; - ctx.fillRect(0, 0, this.cursor.maxColumnwidth * this.cursor.columnwidth, this.cursor.maxLineheight * this.cursor.lineheight); + ctx.fillRect(0, 0, this.cursor.maxColumnWidth * this.cursor.columnWidth, this.cursor.maxLineHeight * this.cursor.lineHeight); }; this.eraseDown = function() { - ctx.fillStyle = BLACK_NORMAL; - ctx.fillRect(0, this.cursor.y, this.cursor.maxColumnwidth * this.cursor.columnwidth, (this.cursor.maxLineheight * this.cursor.lineheight) - this.cursor.y); + ctx.fillStyle = this.cursor.backgroundColor; + ctx.fillRect(0, this.cursor.y, this.cursor.maxColumnWidth * this.cursor.columnWidth, (this.cursor.maxLineHeight * this.cursor.lineHeight) - this.cursor.y); }; this.eraseEndOfLine = function() { - ctx.fillStyle = BLACK_NORMAL; - var w = (this.cursor.maxColumnwidth * this.cursor.columnwidth) - (this.cursor.x - this.cursor.columnwidth); - ctx.fillRect(this.cursor.x, this.cursor.y, w, this.cursor.lineheight); + ctx.fillStyle = this.cursor.backgroundColor; + var w = (this.cursor.maxColumnWidth * this.cursor.columnWidth) - (this.cursor.x - this.cursor.columnWidth); + ctx.fillRect(this.cursor.x, this.cursor.y, w, this.cursor.lineHeight); }; this.eraseStartOfLine = function() { - ctx.fillStyle = BLACK_NORMAL; - ctx.fillRect(0, this.cursor.y, this.cursor.x, this.cursor.lineheight); + ctx.fillStyle = this.cursor.backgroundColor; + ctx.fillRect(0, this.cursor.y, this.cursor.x, this.cursor.lineHeight); }; this.eraseLine = function() { - ctx.fillStyle = BLACK_NORMAL; - ctx.fillRect(0, this.cursor.y, this.cursor.maxColumnwidth * this.cursor.columnwidth, this.cursor.lineheight); + ctx.fillStyle = this.cursor.backgroundColor; + ctx.fillRect(0, this.cursor.y, this.cursor.maxColumnWidth * this.cursor.columnWidth, this.cursor.lineHeight); }; + this.eraseChars = function(val) { + ctx.fillStyle = this.cursor.backgroundColor; + var w = val * this.cursor.columnWidth; + ctx.fillRect(this.cursor.x, this.cursor.y, w, this.cursor.lineHeight); + }; + + this.backgroundColorChanged = function(color) { this.cursor.backgroundColor = color; }; @@ -166,20 +179,22 @@ TERM.AnsiViewer = function (fontmap){ this.home = function() { this.cursor.x = 0; - this.cursor.y = (topMargin-1) * this.cursor.maxLineHeight; + this.cursor.y = 0; }; this.scrollScreen = function(start, end) { topMargin = start; botMargin = end; - - handleHome(); }; this.scrollUp = function(val) { - var canvasData = ctx.getImageData(0, topMargin * this.cursor.lineheight, this.cursor.maxColumnwidth*this.cursor.columnwidth, this.cursor.lineheight * (botMargin-topMargin)); + var x=0; + var y= topMargin * this.cursor.lineHeight; + var width = canvas.width ; + var height = this.cursor.lineHeight * (this.cursor.maxLineHeight -1); + var canvasData = ctx.getImageData(x,y ,width , height ); this.displayCleared(); - ctx.putImageData(canvasData, 0, this.cursor.lineheight*(topMargin-1)); + ctx.putImageData(canvasData, 0, 0 ); }; this.clearCanvas(); diff --git a/src/viewer/Cursor.js b/src/viewer/Cursor.js index ad5d9af..eb18f5c 100644 --- a/src/viewer/Cursor.js +++ b/src/viewer/Cursor.js @@ -7,11 +7,11 @@ TERM.Cursor = function (){ this.foregroundColor = WHITE_NORMAL; this.backgroundColor = BLACK_NORMAL; this.position = new TERM.Point(); - this.maxColumnWidth = 80; - this.maxLineHeight = 25; this.columnWidth = 8; this.lineHeight = 16; - this.maxColumns = 80; + this.maxColumns = Math.floor(width / this.columnWidth); + this.maxColumnWidth = this.maxColumns; + this.maxLineHeight = Math.floor(height / this.lineHeight); this.infiniteWidth = false; this.infiniteHeight = false; From dfc9264bc943484e6a2950b411a4ba4090914cb0 Mon Sep 17 00:00:00 2001 From: jvanbroe Date: Thu, 13 Feb 2014 13:58:22 -0500 Subject: [PATCH 2/4] Added keydown event for support Function keys and other special keys. --- src/telnet/Session.js | 235 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 193 insertions(+), 42 deletions(-) diff --git a/src/telnet/Session.js b/src/telnet/Session.js index ce15dcb..3a1fc67 100644 --- a/src/telnet/Session.js +++ b/src/telnet/Session.js @@ -8,64 +8,215 @@ TERM.Session = function (fontMapURL){ var commands; function initKeyboard() { + document.addEventListener("keypress", function(event) { + var char = null; + if (event.which == null) + char = event.keyCode; // old IE + else if (event.which != 0 && event.charCode != 0) + char = event.which; // All others + + if (char === KEYBOARD_ENTER) { + return; // do not process keyboard enter here, its being done in + // keydown. (ff doesnt enter in here, but chrome does) + } + if (char != null) { + TERM.socket.writeByte( char ); + } + event.preventDefault(); + + }, false); + + document.addEventListener("keydown", function(e) { - var key = e.keyCode; - + var key = e.keyCode; + Util.Debug("keycode : " + key); + var handled= false; switch (key) { - case KEYBOARD_LEFT : - TERM.socket.writeByte(ESCAPE); - TERM.socket.writeByte(LEFT_SQUARE_BRACKET); - TERM.socket.writeByte(LATIN_CAPITAL_LETTER_D); + case KEYBOARD_ENTER: + TERM.socket.writeByte(KEYBOARD_ENTER); + handled = true; break; - - case KEYBOARD_RIGHT : - TERM.socket.writeByte(ESCAPE); - TERM.socket.writeByte(LEFT_SQUARE_BRACKET); - TERM.socket.writeByte(LATIN_CAPITAL_LETTER_C); + case KEYBOARD_LEFT: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_O); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_D); + handled = true; break; - - case KEYBOARD_UP : - TERM.socket.writeByte(ESCAPE); - TERM.socket.writeByte(LEFT_SQUARE_BRACKET); - TERM.socket.writeByte(LATIN_CAPITAL_LETTER_A); + case KEYBOARD_RIGHT: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_O); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_C); + handled = true; break; - - case KEYBOARD_DOWN : - TERM.socket.writeByte(ESCAPE); - TERM.socket.writeByte(LEFT_SQUARE_BRACKET); - TERM.socket.writeByte(LATIN_CAPITAL_LETTER_B); + case KEYBOARD_UP: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_O); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_A); + handled = true; + break; + case KEYBOARD_DOWN: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_O); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_B); + handled = true; + break; + case KEYBOARD_TAB: + TERM.socket.writeByte(KEYBOARD_TAB); + handled=true; break; - case KEYBOARD_PAGE_UP : - TERM.socket.writeByte(ESCAPE); - TERM.socket.writeByte(LEFT_SQUARE_BRACKET); - TERM.socket.writeByte(LATIN_CAPITAL_LETTER_M); + case KEYBOARD_PAGE_UP: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_M); + handled = true; break; - case KEYBOARD_PAGE_DOWN : - TERM.socket.writeByte(ESCAPE); - TERM.socket.writeByte(LEFT_SQUARE_BRACKET); - TERM.socket.writeByte(LATIN_CAPITAL_LETTER_H); - TERM.socket.writeByte(SEMICOLON); - TERM.socket.writeByte(ESCAPE); - TERM.socket.writeByte(LEFT_SQUARE_BRACKET); - TERM.socket.writeByte(DIGIT_TWO); - TERM.socket.writeByte(LATIN_CAPITAL_LETTER_J); + case KEYBOARD_PAGE_DOWN: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_H); + TERM.socket.writeByte(SEMICOLON); + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_TWO); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_J); + handled = true; break; - case KEYBOARD_HOME : + case KEYBOARD_HOME: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(LATIN_CAPITAL_LETTER_H); + handled = true; + break; + case BACKSPACE: + TERM.socket.writeByte(DELETE); + handled = true; + break; + case LATIN_CAPITAL_LETTER_C: + if (e.ctrlKey) { + // Ctrl-C pressed TERM.socket.writeByte(ESCAPE); - TERM.socket.writeByte(LEFT_SQUARE_BRACKET); - TERM.socket.writeByte(LATIN_CAPITAL_LETTER_H); + TERM.socket.writeByte(LM_SLC_IP); + handled = true; + } break; - - default: - TERM.socket.writeByte( key ); + case KEYBOARD_ESC: + TERM.socket.writeByte(KEYBOARD_ESC); + TERM.socket.writeByte(KEYBOARD_ESC); + handled = true; + break; + case KEYBOARD_F1: + //^[[11~ + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_ONE); + TERM.socket.writeByte(DIGIT_ONE); + TERM.socket.writeByte(TILDE); + handled = true; + break; + case KEYBOARD_F2: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_ONE); + TERM.socket.writeByte(DIGIT_TWO); + TERM.socket.writeByte(TILDE); + handled = true; + break; + case KEYBOARD_F3: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_ONE); + TERM.socket.writeByte(DIGIT_THREE); + TERM.socket.writeByte(TILDE); + handled = true; + break; + case KEYBOARD_F4: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_ONE); + TERM.socket.writeByte(DIGIT_FOUR); + TERM.socket.writeByte(TILDE); + handled = true; + break; + case KEYBOARD_F5: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_ONE); + TERM.socket.writeByte(DIGIT_FIVE); + TERM.socket.writeByte(TILDE); + handled = true; + break; + case KEYBOARD_F6: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_ONE); + TERM.socket.writeByte(DIGIT_SEVEN); //Not a mistake + TERM.socket.writeByte(TILDE); + handled = true; + break; + case KEYBOARD_F7: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_ONE); + TERM.socket.writeByte(DIGIT_EIGHT); + TERM.socket.writeByte(TILDE); + handled = true; break; + case KEYBOARD_F8: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_ONE); + TERM.socket.writeByte(DIGIT_NINE); + TERM.socket.writeByte(TILDE); + handled = true; + break; + case KEYBOARD_F9: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_TWO); + TERM.socket.writeByte(DIGIT_ZERO); + TERM.socket.writeByte(TILDE); + handled = true; + break; + case KEYBOARD_F10: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_TWO); + TERM.socket.writeByte(DIGIT_ONE); + TERM.socket.writeByte(TILDE); + handled = true; + break; + case KEYBOARD_F11: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_TWO); + TERM.socket.writeByte(DIGIT_THREE); //not a mistake + TERM.socket.writeByte(TILDE); + handled = true; + break; + case KEYBOARD_F12: + TERM.socket.writeByte(ESCAPE); + TERM.socket.writeByte(LEFT_SQUARE_BRACKET); + TERM.socket.writeByte(DIGIT_TWO); + TERM.socket.writeByte(DIGIT_FOUR); + TERM.socket.writeByte(TILDE); + handled = true; + break; + default: + break; + } + if (handled) { + if (event.preventDefault !== undefined ) + event.preventDefault(); + if (event.stopPropagation !== undefined ) + event.stopPropagation(); } - }, false); - }; + } + ; + var fontmap = new Image(); fontmap.onload = function (){ From 8a2f5c5727760af34aafbccc8bf87536f934a356 Mon Sep 17 00:00:00 2001 From: Jimmy Van Broeck Date: Fri, 27 Jun 2014 14:09:51 -0400 Subject: [PATCH 3/4] Added Cursor blinking on screen Added Reverse Index control char Fixed some screen control chars --- src/parser/AnsiParser.js | 14 ++-- src/parser/EscapeSequencer.js | 54 +++++++++++---- src/parser/Keyboard.js | 2 +- src/telnet/Session.js | 43 ++++++++++-- src/viewer/AnsiViewer.js | 124 ++++++++++++++++++++++++++++++---- src/viewer/Cursor.js | 2 +- 6 files changed, 198 insertions(+), 41 deletions(-) diff --git a/src/parser/AnsiParser.js b/src/parser/AnsiParser.js index 700a54f..9a2a3b8 100644 --- a/src/parser/AnsiParser.js +++ b/src/parser/AnsiParser.js @@ -45,7 +45,6 @@ TERM.AnsiParser = function (viewer){ }; this.readByte = function (b) { - if(b == ESCAPE) { escapeCommand = []; escapeCommand.push(b); @@ -64,21 +63,18 @@ TERM.AnsiParser = function (viewer){ } else { switch(b) { case BACKSPACE: - viewer.moveBackward(1, true); - break; - + viewer.moveBackward(1, false); + break; case LINE_FEED: viewer.moveDown(1); - break; - + break; case CARRIAGE_RETURN: viewer.carriageReturn(); - break; - + break; case FORM_FEED: viewer.eraseScreen(); viewer.reposition(0, 0); - break; + break; } } } diff --git a/src/parser/EscapeSequencer.js b/src/parser/EscapeSequencer.js index cbeec2b..22a8879 100644 --- a/src/parser/EscapeSequencer.js +++ b/src/parser/EscapeSequencer.js @@ -29,11 +29,15 @@ TERM.EscapeSequencer = function (viewer){ this.actionCharacterLib[ LATIN_SMALL_LETTER_H ] = this.setMode; this.actionCharacterLib[ LATIN_SMALL_LETTER_L ] = this.resetMode; this.actionCharacterLib[ LATIN_SMALL_LETTER_P ] = this.setKeyboardStrings; - this.actionCharacterLib[ LATIN_CAPITAL_LETTER_M ] = this.scrollUp; + this.actionCharacterLib[ LATIN_CAPITAL_LETTER_M ] = this.reverseIndex; this.actionCharacterLib[ LATIN_SMALL_LETTER_R ] = this.scrollScreen; this.actionCharacterLib[ LATIN_CAPITAL_LETTER_X ] = this.eraseChars; + this.actionCharacterLib[ LATIN_SMALL_LETTER_N ] = this.reportCursorPos; // TO DO + this.actionCharacterLib[ LESS_THAN_SIGN ] = this.unused; + this.actionCharacterLib[ GREATER_THAN_SIGN ] = this.unused; + this.actionCharacterLib[ EQUALS_SIGN ] = this.unused; this.actionCharacterLib[ LATIN_SMALL_LETTER_A ] = this.unused; this.actionCharacterLib[ LATIN_SMALL_LETTER_D ] = this.unused; this.actionCharacterLib[ LATIN_SMALL_LETTER_E ] = this.unused; @@ -41,7 +45,6 @@ TERM.EscapeSequencer = function (viewer){ this.actionCharacterLib[ LATIN_CAPITAL_LETTER_P ] = this.unused; this.actionCharacterLib[ LATIN_CAPITAL_LETTER_E ] = this.unused; this.actionCharacterLib[ LATIN_CAPITAL_LETTER_F ] = this.unused; - this.actionCharacterLib[ LATIN_CAPITAL_LETTER_X ] = this.unused; }; @@ -181,11 +184,10 @@ TERM.EscapeSequencer = function (viewer){ valueStr += (valueArray[i] - 48).toString(); } var value = (valueStr.length > 0) ? parseInt(valueStr) : 1; - viewer.moveDown(value); }; - this.cursorForward = function(params) { + this.cursorForward = function(params) { if (params[1] == LEFT_PARENTHESIS|| params[1] == RIGHT_PARENTHESIS ) { //Set Alternate char set C @@ -383,8 +385,8 @@ TERM.EscapeSequencer = function (viewer){ } }; - this.scrollUp = function(params) { - viewer.scrollUp(1); + this.reverseIndex = function(params) { + viewer.reverseIndex(); }; this.eraseLine = function(params) { @@ -392,7 +394,7 @@ TERM.EscapeSequencer = function (viewer){ viewer.eraseStartOfLine(); } else if( params[2]==DIGIT_TWO ) { viewer.eraseLine(); - } else if ( params[2]==DIGIT_ZERO || params[2]==LATIN_CAPITAL_LETTER_K ){ + } else if ( params[2]==DIGIT_ONE || params[2]==LATIN_CAPITAL_LETTER_K ){ viewer.eraseEndOfLine(); } }; @@ -420,17 +422,45 @@ TERM.EscapeSequencer = function (viewer){ } }; + this.reportCursorPos = function(params) { + if (params[2] == DIGIT_SIX){ + var x = (viewer.cursor.x / viewer.cursor.columnWidth).toString(); + var y = (viewer.cursor.y / viewer.cursor.lineHeight).toString(); + var cmd=[]; + cmd.push(ESCAPE); + cmd.push(LEFT_SQUARE_BRACKET); + for(var i=0;i= 32 && key <= 127) { + if (event.ctrlKey) { + switch (key) { + // For historic reasons, some control characters are treated specially + case /* 3 */ 51: key = 27; break; + case /* 4 */ 52: key = 28; break; + case /* 5 */ 53: key = 29; break; + case /* 6 */ 54: key = 30; break; + case /* 7 */ 55: key = 31; break; + case /* 8 */ 56: key = 127; break; + case /* ? */ 63: key = 127; break; + default: key &= 31; break; + } + TERM.socket.writeByte(key); + handled = true; + } + } } if (handled) { if (event.preventDefault !== undefined ) diff --git a/src/viewer/AnsiViewer.js b/src/viewer/AnsiViewer.js index 687772a..ac36386 100644 --- a/src/viewer/AnsiViewer.js +++ b/src/viewer/AnsiViewer.js @@ -4,7 +4,6 @@ TERM.AnsiViewer = function (fontmap){ - this.cursor = new TERM.Cursor(); this.parser = new TERM.AnsiParser(this); var fontmap = fontmap; @@ -12,6 +11,7 @@ TERM.AnsiViewer = function (fontmap){ var canvas = document.getElementById("canvas"); var width = canvas.width; var height = canvas.height; + this.cursor = new TERM.Cursor(width,height); var topMargin = 1; var botMargin = 25; var ctx = canvas.getContext("2d"); @@ -70,6 +70,69 @@ TERM.AnsiViewer = function (fontmap){ this.cursor.x, this.cursor.y, font.width, font.height); }; + this.drawCursor = function() { + if (this.currentCursorPosX != this.cursor.x || this.currentCursorPosY != this.cursor.y ) { + + origCursorImg = ctx.getImageData(this.cursor.x, this.cursor.y, 8, 16 ); + var pix = origCursorImg.data; + blinkCursorImg = ctx.createImageData(8, 16); + var newPix = blinkCursorImg.data; + this.currentCursorPosX = this.cursor.x; + this.currentCursorPosY = this.cursor.y; + + var bgColorR = pix[0]; + var bgColorG = pix[1]; + var bgColorB = pix[2]; + + var fgColorR,fgColorG,fgColorB; + for (var i = 256; i < 288; i+=4) { + if (pix[i] != bgColorR || pix[i+1] != bgColorG ||pix[i+2] != bgColorB) { + fgColorR=pix[i]; + fgColorG=pix[i+1]; + fgColorB=pix[i+2]; + break; + } + } + + if (i>=288) { + // we didnt find fgcolor + fgColorR=168; + fgColorG=168; + fgColorB=168; + } + + for ( var i = 0, n = pix.length; i < n; i +=4) { + if (pix[i] == bgColorR && pix[i+1] == bgColorG && pix[i+2] == bgColorB) { + newPix[i] = fgColorR; + newPix[i+1] = fgColorG; + newPix[i+2] = fgColorB; + newPix[i+3] = 255; + } else { + newPix[i] = bgColorR; + newPix[i+1] = bgColorG; + newPix[i+2] = bgColorB; + newPix[i+3] = 255; + } + + } + } + + + if (cursorBlink) { + ctx.putImageData(origCursorImg,this.cursor.x, this.cursor.y); + } else { + ctx.putImageData(blinkCursorImg,this.cursor.x, this.cursor.y); + } + cursorBlink = !cursorBlink; + }; + + this.undrawCursor = function() { + if (cursorBlink) { + ctx.putImageData(origCursorImg,this.currentCursorPosX, this.currentCursorPosY); + cursorBlink = false; + } + }; + this.carriageReturn = function() { this.cursor.carriageReturn(); }; @@ -90,7 +153,8 @@ TERM.AnsiViewer = function (fontmap){ }; this.moveDown = function(val) { - if(this.cursor.y >= this.cursor.lineHeight*(this.cursor.maxLineHeight-val) && scroll){ + var scrollMax = Math.min(botMargin-1,this.cursor.maxLines); + if(this.cursor.y >= this.cursor.lineHeight*(scrollMax-val) && scroll){ this.scrollUp(val); } else { this.cursor.moveDown(val); @@ -106,8 +170,16 @@ TERM.AnsiViewer = function (fontmap){ }; this.reposition = function(x, y) { - this.cursor.x = x * this.cursor.columnWidth; - this.cursor.y = y * this.cursor.lineHeight; + if (x < this.cursor.maxColumns) { + this.cursor.x = x * this.cursor.columnWidth; + } else { + this.cursor.x = (this.cursor.maxColumns - 1) * this.cursor.columnWidth; + } + if (y < this.cursor.maxLines) { + this.cursor.y = y * this.cursor.lineHeight; + } else { + this.cursor.y = (this.cursor.maxLines - 1) * this.cursor.lineHeight; + } }; this.repositionColumn = function(x) { @@ -127,7 +199,7 @@ TERM.AnsiViewer = function (fontmap){ this.displayCleared = function() { ctx.fillStyle = this.cursor.backgroundColor; - ctx.fillRect(0, 0, this.cursor.maxColumnWidth * this.cursor.columnWidth, this.cursor.maxLineHeight * this.cursor.lineHeight); + ctx.fillRect(0, (topMargin - 1) * this.cursor.lineHeight, this.cursor.maxColumnWidth * this.cursor.columnWidth, botMargin * this.cursor.lineHeight); }; @@ -138,12 +210,12 @@ TERM.AnsiViewer = function (fontmap){ this.eraseScreen = function() { ctx.fillStyle = this.cursor.backgroundColor; - ctx.fillRect(0, 0, this.cursor.maxColumnWidth * this.cursor.columnWidth, this.cursor.maxLineHeight * this.cursor.lineHeight); + ctx.fillRect(0, 0, this.cursor.maxColumnWidth * this.cursor.columnWidth, this.cursor.maxLines * this.cursor.lineHeight); }; this.eraseDown = function() { ctx.fillStyle = this.cursor.backgroundColor; - ctx.fillRect(0, this.cursor.y, this.cursor.maxColumnWidth * this.cursor.columnWidth, (this.cursor.maxLineHeight * this.cursor.lineHeight) - this.cursor.y); + ctx.fillRect(0, this.cursor.y, this.cursor.maxColumnWidth * this.cursor.columnWidth, (this.cursor.maxLines * this.cursor.lineHeight) - this.cursor.y); }; this.eraseEndOfLine = function() { @@ -168,7 +240,6 @@ TERM.AnsiViewer = function (fontmap){ ctx.fillRect(this.cursor.x, this.cursor.y, w, this.cursor.lineHeight); }; - this.backgroundColorChanged = function(color) { this.cursor.backgroundColor = color; }; @@ -183,20 +254,49 @@ TERM.AnsiViewer = function (fontmap){ }; this.scrollScreen = function(start, end) { - topMargin = start; - botMargin = end; + if (start!=undefined && end!=undefined) { + topMargin = start; + botMargin = end; + } + this.home(); + }; + + this.reverseIndex = function() { + if (this.cursor.y <= ((topMargin - 1) * this.cursor.lineHeight)) { + this.scrollDown(1); + } else { + this.cursor.y = this.cursor.y - this.cursor.lineHeight; + } + }; + + this.scrollDown = function(val) { + var x=0; + var y= (topMargin-1)* this.cursor.lineHeight; + var width = canvas.width ; + var height = this.cursor.lineHeight * (botMargin - topMargin); + var canvasData = ctx.getImageData(x,y ,width , height ); + this.displayCleared(); + ctx.putImageData(canvasData, 0, this.cursor.lineHeight*(topMargin-1) + (val * this.cursor.lineHeight) ); }; this.scrollUp = function(val) { var x=0; var y= topMargin * this.cursor.lineHeight; var width = canvas.width ; - var height = this.cursor.lineHeight * (this.cursor.maxLineHeight -1); + var height = this.cursor.lineHeight * (botMargin - topMargin); var canvasData = ctx.getImageData(x,y ,width , height ); this.displayCleared(); - ctx.putImageData(canvasData, 0, 0 ); + ctx.putImageData(canvasData, 0, this.cursor.lineHeight*(topMargin-1) ); + }; + + this.cursorKeyToAppMode = function(mode) { + cursorKeyAppMode = mode; }; this.clearCanvas(); + var inst = this; + this.intervalCursorFunction = setInterval(function() { + inst.drawCursor(); + }, 500); }; \ No newline at end of file diff --git a/src/viewer/Cursor.js b/src/viewer/Cursor.js index eb18f5c..5ab1a4c 100644 --- a/src/viewer/Cursor.js +++ b/src/viewer/Cursor.js @@ -2,7 +2,7 @@ * @author Peter Nitsch */ -TERM.Cursor = function (){ +TERM.Cursor = function (width,height){ this.foregroundColor = WHITE_NORMAL; this.backgroundColor = BLACK_NORMAL; From 38306eef884b92c6cc0ab3ca751911913105a3fb Mon Sep 17 00:00:00 2001 From: Jimmy Van Broeck Date: Thu, 17 Jul 2014 18:35:00 -0400 Subject: [PATCH 4/4] Fixed bug with cursor Down and clearing of display when bottom margin and/or top margin was set. --- src/parser/EscapeSequencer.js | 11 +++++++++-- src/viewer/AnsiViewer.js | 26 +++++++++++++++++++++----- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/parser/EscapeSequencer.js b/src/parser/EscapeSequencer.js index 22a8879..2bf32e9 100644 --- a/src/parser/EscapeSequencer.js +++ b/src/parser/EscapeSequencer.js @@ -442,12 +442,15 @@ TERM.EscapeSequencer = function (viewer){ } }; - // Terminal functions this.setMode = function(params){ Util.Debug("Set Mode function : " + params[3]); if (params[3] == DIGIT_ONE) { Util.Debug("Set Cursor Keys to Application Mode"); viewer.cursorKeyToAppMode(true); + } + if (params[3] == DIGIT_SEVEN) { + Util.Debug("AutoWrap mode on"); + viewer.setAutoWrap(true); } }; @@ -457,6 +460,10 @@ TERM.EscapeSequencer = function (viewer){ Util.Debug("Reset Cursor Keys from Application Mode back to Cursor Mode"); viewer.cursorKeyToAppMode(false); } + if (params[3] == DIGIT_SEVEN) { + Util.Debug("AutoWrap mode off"); + viewer.setAutoWrap(false); + } }; this.setKeyboardStrings = function(){ @@ -465,4 +472,4 @@ TERM.EscapeSequencer = function (viewer){ this.init(); -}; \ No newline at end of file +}; diff --git a/src/viewer/AnsiViewer.js b/src/viewer/AnsiViewer.js index ac36386..ed1e97f 100644 --- a/src/viewer/AnsiViewer.js +++ b/src/viewer/AnsiViewer.js @@ -17,9 +17,21 @@ TERM.AnsiViewer = function (fontmap){ var ctx = canvas.getContext("2d"); var scroll = true; var _savedPosition = new TERM.Point(); + var cursorKeyAppMode = false; + var autoWrapMode = true; + var currentCursorPosX,currentCursorPosy; + var origCursorImg,blinkCursorImg; + var cursorBlink = false; + var intervalCursorFunction; this.readBytes = function (bytes) { + clearInterval(this.intervalCursorFunction); + this.undrawCursor(); this.parser.parse(bytes); + var inst = this; + this.intervalCursorFunction = setInterval(function() { + inst.drawCursor(); + }, 500); }; this.clearCanvas = function(){ @@ -53,7 +65,7 @@ TERM.AnsiViewer = function (fontmap){ this.draw(character); this.cursor.moveForward(1); - if(!this.cursor.infiniteWidth && this.cursor.x + this.cursor.columnWidth > this.cursor.maxColumnWidth * this.cursor.columnWidth){ + if(autoWrapMode && !this.cursor.infiniteWidth && this.cursor.x + this.cursor.columnWidth > this.cursor.maxColumnWidth * this.cursor.columnWidth){ this.moveDown(1); this.cursor.carriageReturn(); } @@ -153,8 +165,8 @@ TERM.AnsiViewer = function (fontmap){ }; this.moveDown = function(val) { - var scrollMax = Math.min(botMargin-1,this.cursor.maxLines); - if(this.cursor.y >= this.cursor.lineHeight*(scrollMax-val) && scroll){ + var scrollMax = Math.min(botMargin-1,this.cursor.maxLines); + if(this.cursor.y > this.cursor.lineHeight*(scrollMax-val) && scroll){ this.scrollUp(val); } else { this.cursor.moveDown(val); @@ -199,7 +211,7 @@ TERM.AnsiViewer = function (fontmap){ this.displayCleared = function() { ctx.fillStyle = this.cursor.backgroundColor; - ctx.fillRect(0, (topMargin - 1) * this.cursor.lineHeight, this.cursor.maxColumnWidth * this.cursor.columnWidth, botMargin * this.cursor.lineHeight); + ctx.fillRect(0, (topMargin - 1) * this.cursor.lineHeight, this.cursor.maxColumnWidth * this.cursor.columnWidth, ((botMargin +1) * this.cursor.lineHeight) - (topMargin * this.cursor.lineHeight) ); // calculate the height correctly, botMArgin - topMargin }; @@ -292,6 +304,10 @@ TERM.AnsiViewer = function (fontmap){ this.cursorKeyToAppMode = function(mode) { cursorKeyAppMode = mode; }; + + this.setAutoWrap = function(mode) { + autoWrapMode = mode; + }; this.clearCanvas(); var inst = this; @@ -299,4 +315,4 @@ TERM.AnsiViewer = function (fontmap){ inst.drawCursor(); }, 500); -}; \ No newline at end of file +};