| 1 | /** |
| 2 | * @description Remote Terminal |
| 3 | * @author Ylian Saint-Hilaire |
| 4 | * @version v0.0.2c |
| 5 | */ |
| 6 | |
| 7 | // https://invisible-island.net/xterm/ctlseqs/ctlseqs.html |
| 8 | // https://www.x.org/docs/xterm/ctlseqs.pdf |
| 9 | |
| 10 | // Construct a MeshServer object |
| 11 | var CreateAmtRemoteTerminal = function (divid, options) { |
| 12 | var obj = {}; |
| 13 | obj.DivId = divid; |
| 14 | obj.DivElement = document.getElementById(divid); |
| 15 | obj.protocol = 1; // SOL |
| 16 | if (options.protocol) { obj.protocol = options.protocol; } // 1 = Normal, 6 = PowerShell |
| 17 | // ###BEGIN###{Terminal-Enumation-All} |
| 18 | obj.terminalEmulation = 1; |
| 19 | // ###END###{Terminal-Enumation-All} |
| 20 | obj.fxEmulation = 0; |
| 21 | obj.lineFeed = '\r\n'; |
| 22 | obj.debugmode = 0; |
| 23 | |
| 24 | obj.width = 80; // 80 or 100 |
| 25 | obj.height = 25; // 25 or 30 |
| 26 | obj.heightLock = 0; |
| 27 | |
| 28 | var _Terminal_CellHeight = 21; |
| 29 | var _Terminal_CellWidth = 13; |
| 30 | var _TermColors = ['000000', 'BB0000', '00BB00', 'BBBB00', '0000BB', 'BB00BB', '00BBBB', 'BBBBBB', '555555', 'FF5555', '55FF55', 'FFFF55', '5555FF', 'FF55FF', '55FFFF', 'FFFFFF']; |
| 31 | var _TermCurrentReverse = 0; |
| 32 | var _TermCurrentFColor = 7; |
| 33 | var _TermCurrentBColor = 0; |
| 34 | var _TermLineWrap = true; |
| 35 | var _termx = 0; |
| 36 | var _termy = 0; |
| 37 | var _termsavex = 0; |
| 38 | var _termsavey = 0; |
| 39 | var _termstate = 0; |
| 40 | var _escNumber = []; |
| 41 | var _escNumberPtr = 0; |
| 42 | var _escNumberMode = 0; |
| 43 | var _scratt = []; |
| 44 | var _tscreen = []; |
| 45 | var _VTUNDERLINE = 1; |
| 46 | var _VTREVERSE = 2; |
| 47 | var _backSpaceErase = false; |
| 48 | var _cursorVisible = true; |
| 49 | var _scrollRegion; |
| 50 | var _altKeypadMode = false; |
| 51 | var scrollBackBuffer = []; |
| 52 | // ###BEGIN###{Terminal-Enumation-UTF8} |
| 53 | //var utf8decodeBuffer = ''; |
| 54 | // ###END###{Terminal-Enumation-UTF8} |
| 55 | // ###BEGIN###{Terminal-Enumation-All} |
| 56 | var utf8decodeBuffer = ''; |
| 57 | // ###END###{Terminal-Enumation-All} |
| 58 | obj.title = null; |
| 59 | obj.onTitleChange = null; |
| 60 | |
| 61 | obj.Start = function () { } |
| 62 | |
| 63 | obj.Init = function (width, height) { |
| 64 | obj.width = width ? width : 80; |
| 65 | obj.height = height ? height : 25; |
| 66 | for (var y = 0; y < obj.height; y++) { |
| 67 | _tscreen[y] = []; |
| 68 | _scratt[y] = []; |
| 69 | for (var x = 0; x < obj.width; x++) { _tscreen[y][x] = ' '; _scratt[y][x] = (7 << 6); } |
| 70 | } |
| 71 | obj.TermInit(); |
| 72 | obj.TermDraw(); |
| 73 | } |
| 74 | |
| 75 | obj.xxStateChange = function (newstate) { |
| 76 | //if ((newstate == 3) && (options != null) && (options.xterm == true)) { obj.TermSendKeys(' stty rows ' + obj.height + ' cols ' + obj.width + ';clear\n'); } |
| 77 | } |
| 78 | |
| 79 | obj.ProcessData = function (str) { |
| 80 | if (obj.debugmode == 2) { console.log("TRecv(" + str.length + "): " + rstr2hex(str)); } |
| 81 | // ###BEGIN###{Terminal-Enumation-UTF8} |
| 82 | //try { str = decode_utf8(utf8decodeBuffer + str); } catch (ex) { utf8decodeBuffer += str; return; } // If we get data in the middle of a UTF-8 code, buffer it for next time. |
| 83 | //utf8decodeBuffer = ''; |
| 84 | // ###END###{Terminal-Enumation-UTF8} |
| 85 | // ###BEGIN###{Terminal-Enumation-All} |
| 86 | if (obj.terminalEmulation == 0) { try { str = decode_utf8(utf8decodeBuffer + str); } catch (ex) { utf8decodeBuffer += str; return; } } // If we get data in the middle of a UTF-8 code, buffer it for next time. |
| 87 | utf8decodeBuffer = ''; |
| 88 | // ###END###{Terminal-Enumation-All} |
| 89 | if (obj.capture != null) obj.capture += str; _ProcessVt100EscString(str); obj.TermDraw(); |
| 90 | } |
| 91 | |
| 92 | function _ProcessVt100EscString(str) { for (var i = 0; i < str.length; i++) _ProcessVt100EscChar(String.fromCharCode(str.charCodeAt(i)), str.charCodeAt(i)); } |
| 93 | |
| 94 | function _ProcessVt100EscChar(b, c) { |
| 95 | switch (_termstate) { |
| 96 | case 0: // Normal Term State |
| 97 | switch (c) { |
| 98 | case 27: // ESC |
| 99 | _termstate = 1; |
| 100 | _escNumber = []; |
| 101 | _escNumberPtr = 0; |
| 102 | _escNumberMode = 0; |
| 103 | break; |
| 104 | default: |
| 105 | // Process a single char |
| 106 | _ProcessVt100Char(b); |
| 107 | break; |
| 108 | } |
| 109 | break; |
| 110 | case 1: |
| 111 | switch (b) { |
| 112 | case '[': |
| 113 | _termstate = 2; |
| 114 | break; |
| 115 | case '(': |
| 116 | _termstate = 4; |
| 117 | break; |
| 118 | case ')': |
| 119 | _termstate = 5; |
| 120 | break; |
| 121 | case ']': |
| 122 | _termstate = 6; // xterm strings |
| 123 | break; |
| 124 | case '=': |
| 125 | // Set alternate keypad mode |
| 126 | _altKeypadMode = true; |
| 127 | _termstate = 0; |
| 128 | break; |
| 129 | case '>': |
| 130 | // Set numeric keypad mode |
| 131 | _altKeypadMode = false; |
| 132 | _termstate = 0; |
| 133 | break; |
| 134 | case '7': |
| 135 | // Save Cursor |
| 136 | _termsavex = _termx; |
| 137 | _termsavey = _termy; |
| 138 | _termstate = 0; |
| 139 | break; |
| 140 | case '8': |
| 141 | // Restore Cursor |
| 142 | _termx = _termsavex; |
| 143 | _termy = _termsavey; |
| 144 | _termstate = 0; |
| 145 | break; |
| 146 | case 'M': |
| 147 | // Scroll down one |
| 148 | var x = 1; |
| 149 | for (var y = _scrollRegion[1]; y >= _scrollRegion[0] + x; y--) { |
| 150 | for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = _tscreen[y - x][z]; _scratt[y][z] = _scratt[y - x][z]; } |
| 151 | } |
| 152 | for (var y = _scrollRegion[0] + x - 1; y > _scrollRegion[0] - 1; y--) { |
| 153 | for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = ' '; _scratt[y][z] = (7 << 6); } |
| 154 | } |
| 155 | _termstate = 0; |
| 156 | break; |
| 157 | default: |
| 158 | console.log('unknown terminal short code', b); |
| 159 | _termstate = 0; |
| 160 | break; |
| 161 | } |
| 162 | break; |
| 163 | case 2: |
| 164 | if (b >= '0' && b <= '9') { |
| 165 | // This is a number |
| 166 | if (!_escNumber[_escNumberPtr]) { _escNumber[_escNumberPtr] = (b - '0'); } |
| 167 | else { _escNumber[_escNumberPtr] = ((_escNumber[_escNumberPtr] * 10) + (b - '0')); } |
| 168 | break; |
| 169 | } else if (b == ';') { |
| 170 | // New number |
| 171 | _escNumberPtr++; |
| 172 | break; |
| 173 | } else if (b == '?') { |
| 174 | _escNumberMode = 1; |
| 175 | break; |
| 176 | } else { |
| 177 | // Process Escape Sequence |
| 178 | if (!_escNumber[0]) _escNumber[0] = 0; |
| 179 | _ProcessEscapeHandler(b, _escNumber, _escNumberPtr + 1, _escNumberMode); |
| 180 | _termstate = 0; |
| 181 | } |
| 182 | break; |
| 183 | case 4: // '(' Code |
| 184 | _termstate = 0; |
| 185 | break; |
| 186 | case 5: // ')' Code |
| 187 | _termstate = 0; |
| 188 | break; |
| 189 | case 6: // ']' Code, xterm |
| 190 | var bx = b.charCodeAt(0); |
| 191 | if (b == ';') { |
| 192 | _escNumberPtr++; |
| 193 | } else if (bx == 7) { |
| 194 | _ProcessXTermHandler(_escNumber); |
| 195 | _termstate = 0; |
| 196 | } else { |
| 197 | if (!_escNumber[_escNumberPtr]) { _escNumber[_escNumberPtr] = b; } |
| 198 | else { _escNumber[_escNumberPtr] += b; } |
| 199 | } |
| 200 | break; |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | function _ProcessXTermHandler(_escNumber) { |
| 205 | if (_escNumber.length == 0) return; |
| 206 | var cmd = parseInt(_escNumber[0]); |
| 207 | if ((cmd == 0 || cmd == 2) && (_escNumber.length > 1) && (_escNumber[1] != '?')) { |
| 208 | if (obj.onTitleChange) { obj.onTitleChange(obj, obj.title = _escNumber[1]); } |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | function _ProcessEscapeHandler(code, args, argslen, mode) { |
| 213 | //console.log('process', code, args, mode); |
| 214 | if (mode == 1) { |
| 215 | switch (code) { |
| 216 | case 'l': // Hide the cursor |
| 217 | if (args[0] == 25) { _cursorVisible = false; } |
| 218 | break; |
| 219 | case 'h': // Show the cursor |
| 220 | if (args[0] == 25) { _cursorVisible = true; } |
| 221 | break; |
| 222 | } |
| 223 | } else if (mode == 0) { |
| 224 | var i; |
| 225 | switch (code) { |
| 226 | case 'c': // ResetDevice |
| 227 | // Reset |
| 228 | obj.TermResetScreen(); |
| 229 | break; |
| 230 | case 'A': // Move cursor up n lines |
| 231 | if (argslen == 1) { |
| 232 | if (args[0] == 0) { _termy--; } else { _termy -= args[0]; } |
| 233 | if (_termy < 0) _termy = 0; |
| 234 | } |
| 235 | break; |
| 236 | case 'B': // Move cursor down n lines |
| 237 | if (argslen == 1) { |
| 238 | if (args[0] == 0) { _termy++; } else { _termy += args[0]; } |
| 239 | if (_termy > obj.height) _termy = obj.height; |
| 240 | } |
| 241 | break; |
| 242 | case 'C': // Move cursor right n lines |
| 243 | if (argslen == 1) { |
| 244 | if (args[0] == 0) { _termx++; } else { _termx += args[0]; } |
| 245 | if (_termx > obj.width) _termx = obj.width; |
| 246 | } |
| 247 | break; |
| 248 | case 'D': // Move cursor left n lines |
| 249 | if (argslen == 1) { |
| 250 | if (args[0] == 0) { _termx--; } else { _termx -= args[0]; } |
| 251 | if (_termx < 0) _termx = 0; |
| 252 | } |
| 253 | break; |
| 254 | case 'd': // Set cursor to line n |
| 255 | if (argslen == 1) { |
| 256 | _termy = args[0] - 1; |
| 257 | if (_termy > obj.height) _termy = obj.height; |
| 258 | if (_termy < 0) _termy = 0; |
| 259 | } |
| 260 | break; |
| 261 | case 'G': // Set cursor to col n |
| 262 | if (argslen == 1) { |
| 263 | _termx = args[0] - 1; |
| 264 | if (_termx < 0) _termx = 0; |
| 265 | if (_termx > (obj.width - 1)) _termx = (obj.width - 1); |
| 266 | } |
| 267 | break; |
| 268 | case 'P': // Delete X Character(s), default 1 char |
| 269 | var x = 1; |
| 270 | if (argslen == 1) { x = args[0]; } |
| 271 | for (i = _termx; i < obj.width - x; i++) { _tscreen[_termy][i] = _tscreen[_termy][i + x]; _scratt[_termy][i] = _scratt[_termy][i + x]; } |
| 272 | for (i = (obj.width - x); i < obj.width; i++) { _tscreen[_termy][i] = ' '; _scratt[_termy][i] = (7 << 6); } |
| 273 | break; |
| 274 | case 'L': // Insert X Line(s), default 1 char |
| 275 | var linecount = 1; |
| 276 | if (argslen == 1) { linecount = args[0]; } |
| 277 | if (linecount == 0) { linecount = 1; } |
| 278 | for (y = _scrollRegion[1]; y >= _termy + linecount; y--) { |
| 279 | _tscreen[y] = _tscreen[y - linecount]; |
| 280 | _scratt[y] = _scratt[y - linecount]; |
| 281 | } |
| 282 | for (y = _termy; y < _termy + linecount; y++) { |
| 283 | _tscreen[y] = []; |
| 284 | _scratt[y] = []; |
| 285 | for (x = 0; x < obj.width; x++) { _tscreen[y][x] = ' '; _scratt[y][x] = (7 << 6); } |
| 286 | } |
| 287 | break; |
| 288 | case 'J': // ClearScreen: |
| 289 | if (argslen == 1 && args[0] == 2) { |
| 290 | obj.TermClear((_TermCurrentBColor << 12) + (_TermCurrentFColor << 6)); // Erase entire screen |
| 291 | _termx = 0; |
| 292 | _termy = 0; |
| 293 | scrollBackBuffer = []; |
| 294 | } |
| 295 | else if (argslen == 0 || argslen == 1 && args[0] == 0) // Erase cursor down |
| 296 | { |
| 297 | _EraseCursorToEol(); |
| 298 | for (i = _termy + 1; i < obj.height; i++) _EraseLine(i); |
| 299 | } |
| 300 | else if (argslen == 1 && args[0] == 1) // Erase cursor up |
| 301 | { |
| 302 | _EraseCursorToEol(); |
| 303 | for (i = 0; i < _termy - 1; i++) _EraseLine(i); |
| 304 | } |
| 305 | break; |
| 306 | case 'H': // MoveCursor: |
| 307 | if (argslen == 2) { |
| 308 | if (args[0] < 1) args[0] = 1; |
| 309 | if (args[1] < 1) args[1] = 1; |
| 310 | if (args[0] > obj.height) args[0] = obj.height; |
| 311 | if (args[1] > obj.width) args[1] = obj.width; |
| 312 | _termy = args[0] - 1; |
| 313 | _termx = args[1] - 1; |
| 314 | } else { |
| 315 | _termy = 0; |
| 316 | _termx = 0; |
| 317 | } |
| 318 | break; |
| 319 | case 'm': // ScreenAttribs: |
| 320 | // Change attributes |
| 321 | for (i = 0; i < argslen; i++) { |
| 322 | if (!args[i] || args[i] == 0) { |
| 323 | // Reset Attributes |
| 324 | _TermCurrentBColor = 0; |
| 325 | _TermCurrentFColor = 7; |
| 326 | _TermCurrentReverse = 0; |
| 327 | } |
| 328 | else if (args[i] == 1) { |
| 329 | // Bright |
| 330 | if (_TermCurrentFColor < 8) _TermCurrentFColor += 8; |
| 331 | } |
| 332 | else if (args[i] == 2 || args[i] == 22) { |
| 333 | // Dim |
| 334 | if (_TermCurrentFColor >= 8) _TermCurrentFColor -= 8; |
| 335 | } |
| 336 | else if (args[i] == 7) { |
| 337 | // Set Reverse attribute true |
| 338 | _TermCurrentReverse = 2; |
| 339 | } |
| 340 | else if (args[i] == 27) { |
| 341 | // Set Reverse attribute false |
| 342 | _TermCurrentReverse = 0; |
| 343 | } |
| 344 | else if (args[i] >= 30 && args[i] <= 37) { |
| 345 | // Set Foreground Color |
| 346 | var bright = (_TermCurrentFColor >= 8); |
| 347 | _TermCurrentFColor = (args[i] - 30); |
| 348 | if (bright && _TermCurrentFColor <= 8) _TermCurrentFColor += 8; |
| 349 | } |
| 350 | else if (args[i] >= 40 && args[i] <= 47) { |
| 351 | // Set Background Color |
| 352 | _TermCurrentBColor = (args[i] - 40); |
| 353 | } |
| 354 | else if (args[i] >= 90 && args[i] <= 99) { |
| 355 | // Set Bright Foreground Color |
| 356 | _TermCurrentFColor = (args[i] - 82); |
| 357 | } |
| 358 | else if (args[i] >= 100 && args[i] <= 109) { |
| 359 | // Set Bright Background Color |
| 360 | _TermCurrentBColor = (args[i] - 92); |
| 361 | } |
| 362 | } |
| 363 | break; |
| 364 | case 'K': // EraseLine: |
| 365 | if (argslen == 0 || (argslen == 1 && (!args[0] || args[0] == 0))) { |
| 366 | _EraseCursorToEol(); // Erase from the cursor to the end of the line |
| 367 | } else if (argslen == 1) { |
| 368 | if (args[0] == 1) { // Erase from the beginning of the line to the cursor |
| 369 | _EraseBolToCursor(); |
| 370 | } else if (args[0] == 2) { // Erase the line with the cursor |
| 371 | _EraseLine(_termy); |
| 372 | } |
| 373 | } |
| 374 | break; |
| 375 | case 'h': // EnableLineWrap: |
| 376 | _TermLineWrap = true; |
| 377 | break; |
| 378 | case 'l': // DisableLineWrap: |
| 379 | _TermLineWrap = false; |
| 380 | break; |
| 381 | case 'r': // Set the scroll region |
| 382 | if (argslen == 2) { _scrollRegion = [args[0] - 1, args[1] - 1]; } |
| 383 | if (_scrollRegion[0] < 0) { _scrollRegion[0] = 0; } |
| 384 | if (_scrollRegion[0] > (obj.height - 1)) { _scrollRegion[0] = (obj.height - 1); } |
| 385 | if (_scrollRegion[1] < 0) { _scrollRegion[1] = 0; } |
| 386 | if (_scrollRegion[1] > (obj.height - 1)) { _scrollRegion[1] = (obj.height - 1); } |
| 387 | if (_scrollRegion[0] > _scrollRegion[1]) { _scrollRegion[0] = _scrollRegion[1]; } |
| 388 | break; |
| 389 | case 'S': // Scroll up the scroll region X lines, default 1 |
| 390 | var x = 1; |
| 391 | if (argslen == 1) { x = args[0] } |
| 392 | for (var y = _scrollRegion[0]; y <= _scrollRegion[1] - x; y++) { |
| 393 | for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = _tscreen[y + x][z]; _scratt[y][z] = _scratt[y + x][z]; } |
| 394 | } |
| 395 | for (var y = _scrollRegion[1] - x + 1; y < _scrollRegion[1]; y++) { |
| 396 | for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = ' '; _scratt[y][z] = (7 << 6); } |
| 397 | } |
| 398 | break; |
| 399 | case 'M': // Delete X lines, default 1 |
| 400 | var x = 1; |
| 401 | if (argslen == 1) { x = args[0] } |
| 402 | for (var y = _termy; y <= _scrollRegion[1] - x; y++) { |
| 403 | for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = _tscreen[y + x][z]; _scratt[y][z] = _scratt[y + x][z]; } |
| 404 | } |
| 405 | for (var y = _scrollRegion[1] - x + 1; y < _scrollRegion[1]; y++) { |
| 406 | for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = ' '; _scratt[y][z] = (7 << 6); } |
| 407 | } |
| 408 | break; |
| 409 | case 'T': // Scroll down the scroll region X lines, default 1 |
| 410 | var x = 1; |
| 411 | if (argslen == 1) { x = args[0] } |
| 412 | for (var y = _scrollRegion[1]; y > _scrollRegion[0] + x; y--) { |
| 413 | for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = _tscreen[y - x][z]; _scratt[y][z] = _scratt[y - x][z]; } |
| 414 | } |
| 415 | for (var y = _scrollRegion[0] + x; y > _scrollRegion[0]; y--) { |
| 416 | for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = ' '; _scratt[y][z] = (7 << 6); } |
| 417 | } |
| 418 | break; |
| 419 | case 'X': // Erase X characters, default 1 |
| 420 | var x = 1, xx = _termx, yy = _termy; |
| 421 | if (argslen == 1) { x = args[0] } |
| 422 | while ((x > 0) && (yy < obj.height)) { _tscreen[yy][xx] = ' '; xx++; x--; if (xx >= obj.width) { xx = 0; yy++; } } |
| 423 | break; |
| 424 | default: |
| 425 | //if (code != '@') alert(code); |
| 426 | console.log('Unknown terminal code', code, args, mode); |
| 427 | break; |
| 428 | } |
| 429 | } |
| 430 | } |
| 431 | |
| 432 | obj.ProcessVt100String = function (str) { |
| 433 | for (var i = 0; i < str.length; i++) _ProcessVt100Char(String.fromCharCode(str.charCodeAt(i))); |
| 434 | } |
| 435 | |
| 436 | // ###BEGIN###{Terminal-Enumation-All} |
| 437 | var AsciiToUnicode = [ |
| 438 | 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, |
| 439 | 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, |
| 440 | 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, |
| 441 | 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, |
| 442 | 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00da, |
| 443 | 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, |
| 444 | 0x2593, 0x2592, 0x2591, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, |
| 445 | 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, |
| 446 | 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, |
| 447 | 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, |
| 448 | 0x2568, 0x2564, 0x2565, 0x2568, 0x2558, 0x2552, 0x2553, 0x256b, |
| 449 | 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258b, 0x2590, 0x2580, |
| 450 | 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, |
| 451 | 0x03c6, 0x03b8, 0x2126, 0x03b4, 0x221e, 0x00f8, 0x03b5, 0x220f, |
| 452 | 0x2261, 0x00b1, 0x2265, 0x2266, 0x2320, 0x2321, 0x00f7, 0x2248, |
| 453 | 0x00b0, 0x2022, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x220e, 0x00a0 |
| 454 | ]; |
| 455 | |
| 456 | var AsciiToUnicodeIntel = [ |
| 457 | 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, |
| 458 | 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, |
| 459 | 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, |
| 460 | 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, |
| 461 | 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00da, |
| 462 | 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ae, 0x00bb, |
| 463 | 0x2593, 0x2592, 0x2591, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, |
| 464 | 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, |
| 465 | 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, |
| 466 | 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, |
| 467 | 0x2568, 0x2564, 0x2565, 0x2568, 0x2558, 0x2552, 0x2553, 0x256b, |
| 468 | 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258b, 0x2590, 0x2580, |
| 469 | 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, |
| 470 | 0x03c6, 0x03b8, 0x2126, 0x03b4, 0x221e, 0x00f8, 0x03b5, 0x220f, |
| 471 | 0x2261, 0x00b1, 0x2265, 0x2266, 0x2320, 0x2321, 0x00f7, 0x2248, |
| 472 | 0x00b0, 0x2022, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x220e, 0x00a0 |
| 473 | ]; |
| 474 | // ###END###{Terminal-Enumation-All} |
| 475 | |
| 476 | // ###BEGIN###{Terminal-Enumation-ASCII} |
| 477 | var AsciiToUnicode = [ |
| 478 | 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, |
| 479 | 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, |
| 480 | 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, |
| 481 | 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, |
| 482 | 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00da, |
| 483 | 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, |
| 484 | 0x2593, 0x2592, 0x2591, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, |
| 485 | 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, |
| 486 | 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, |
| 487 | 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, |
| 488 | 0x2568, 0x2564, 0x2565, 0x2568, 0x2558, 0x2552, 0x2553, 0x256b, |
| 489 | 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258b, 0x2590, 0x2580, |
| 490 | 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, |
| 491 | 0x03c6, 0x03b8, 0x2126, 0x03b4, 0x221e, 0x00f8, 0x03b5, 0x220f, |
| 492 | 0x2261, 0x00b1, 0x2265, 0x2266, 0x2320, 0x2321, 0x00f7, 0x2248, |
| 493 | 0x00b0, 0x2022, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x220e, 0x00a0 |
| 494 | ]; |
| 495 | // ###END###{Terminal-Enumation-ASCII} |
| 496 | |
| 497 | // ###BEGIN###{Terminal-Enumation-Intel} |
| 498 | var AsciiToUnicodeIntel = [ |
| 499 | 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, |
| 500 | 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, |
| 501 | 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, |
| 502 | 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, |
| 503 | 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00da, |
| 504 | 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ae, 0x00bb, |
| 505 | 0x2593, 0x2592, 0x2591, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, |
| 506 | 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, |
| 507 | 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, |
| 508 | 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, |
| 509 | 0x2568, 0x2564, 0x2565, 0x2568, 0x2558, 0x2552, 0x2553, 0x256b, |
| 510 | 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258b, 0x2590, 0x2580, |
| 511 | 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, |
| 512 | 0x03c6, 0x03b8, 0x2126, 0x03b4, 0x221e, 0x00f8, 0x03b5, 0x220f, |
| 513 | 0x2261, 0x00b1, 0x2265, 0x2266, 0x2320, 0x2321, 0x00f7, 0x2248, |
| 514 | 0x00b0, 0x2022, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x220e, 0x00a0 |
| 515 | ]; |
| 516 | // ###END###{Terminal-Enumation-Intel} |
| 517 | |
| 518 | function _ProcessVt100Char(c) { |
| 519 | if (c == '\0' || c.charCodeAt() == 7) return; // Ignore null & bell |
| 520 | var ch = c.charCodeAt(); |
| 521 | //console.log('_ProcessVt100Char', ch, c); |
| 522 | |
| 523 | // ###BEGIN###{Terminal-Enumation-All} |
| 524 | // UTF8 Terminal |
| 525 | if (obj.terminalEmulation == 1) { |
| 526 | // ANSI - Extended ASCII emulation. |
| 527 | if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicode[ch & 0x7F]); } |
| 528 | } else if (obj.terminalEmulation == 2) { |
| 529 | // ANSI - Intel Extended ASCII emulation. |
| 530 | if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicodeIntel[ch & 0x7F]); } |
| 531 | } |
| 532 | // ###END###{Terminal-Enumation-All} |
| 533 | |
| 534 | // ###BEGIN###{Terminal-Enumation-ASCII} |
| 535 | // ANSI - Extended ASCII emulation. |
| 536 | //if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicode[ch & 0x7F]); } |
| 537 | // ###END###{Terminal-Enumation-ASCII} |
| 538 | |
| 539 | // ###BEGIN###{Terminal-Enumation-Intel} |
| 540 | // ANSI - Intel Extended ASCII emulation. |
| 541 | //if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicodeIntel[ch & 0x7F]); } |
| 542 | // ###END###{Terminal-Enumation-Intel} |
| 543 | |
| 544 | //if (ch < 32 && ch != 10 && ch != 13) alert(ch); |
| 545 | switch (ch) { |
| 546 | case 16: { c = ' '; break; } // This is an odd char that show up on Intel BIOS's. |
| 547 | case 24: { c = '↑'; break; } |
| 548 | case 25: { c = '↓'; break; } |
| 549 | } |
| 550 | |
| 551 | if (_termx > obj.width) _termx = obj.width; |
| 552 | if (_termy > (obj.height - 1)) _termy = (obj.height - 1); |
| 553 | |
| 554 | switch (c) { |
| 555 | case '\b': // Backspace |
| 556 | if (_termx > 0) { |
| 557 | _termx--; |
| 558 | if (_backSpaceErase) { _TermDrawChar(' '); } |
| 559 | } |
| 560 | break; |
| 561 | case '\t': // tab |
| 562 | var tab = 8 - (_termx % 8) |
| 563 | for (var x = 0; x < tab; x++) _ProcessVt100Char(" "); |
| 564 | break; |
| 565 | case '\n': // Linefeed |
| 566 | _termy++; |
| 567 | if (_termy > _scrollRegion[1]) { |
| 568 | // Move everything up one line |
| 569 | obj.recordLineTobackBuffer(0); |
| 570 | _TermMoveUp(1); |
| 571 | _termy = _scrollRegion[1]; |
| 572 | } |
| 573 | if (obj.lineFeed = '\r') { _termx = 0; } // *** If we are in Linux mode, \n will also return the cursor to the first col |
| 574 | break; |
| 575 | case '\r': // Carriage Return |
| 576 | _termx = 0; |
| 577 | break; |
| 578 | default: |
| 579 | if (_termx >= obj.width) { |
| 580 | _termx = 0; |
| 581 | if (_TermLineWrap) { _termy++; } |
| 582 | if (_termy >= (obj.height - 1)) { _TermMoveUp(1); _termy = (obj.height - 1); } |
| 583 | } |
| 584 | _TermDrawChar(c); |
| 585 | _termx++; |
| 586 | break; |
| 587 | } |
| 588 | } |
| 589 | |
| 590 | function _TermDrawChar(c) { |
| 591 | _tscreen[_termy][_termx] = c; |
| 592 | _scratt[_termy][_termx] = (_TermCurrentFColor << 6) + (_TermCurrentBColor << 12) + _TermCurrentReverse; |
| 593 | } |
| 594 | |
| 595 | obj.TermClear = function(TermColor) { |
| 596 | for (var y = 0; y < obj.height; y++) { |
| 597 | for (var x = 0; x < obj.width; x++) { |
| 598 | _tscreen[y][x] = ' '; |
| 599 | _scratt[y][x] = TermColor; |
| 600 | } |
| 601 | } |
| 602 | scrollBackBuffer = []; |
| 603 | } |
| 604 | |
| 605 | obj.TermResetScreen = function () { |
| 606 | _TermCurrentReverse = 0; |
| 607 | _TermCurrentFColor = 7; |
| 608 | _TermCurrentBColor = 0; |
| 609 | _TermLineWrap = _cursorVisible = true; |
| 610 | _termx = _termy = 0; |
| 611 | _backSpaceErase = false; |
| 612 | _scrollRegion = [0, (obj.height - 1)]; |
| 613 | _altKeypadMode = false; |
| 614 | obj.TermClear(7 << 6); |
| 615 | // ###BEGIN###{Terminal-Enumation-UTF8} |
| 616 | //utf8decodeBuffer = ''; |
| 617 | // ###END###{Terminal-Enumation-UTF8} |
| 618 | // ###BEGIN###{Terminal-Enumation-All} |
| 619 | utf8decodeBuffer = ''; |
| 620 | // ###END###{Terminal-Enumation-All} |
| 621 | } |
| 622 | |
| 623 | function _EraseCursorToEol() { |
| 624 | var t = (_TermCurrentFColor << 6) + (_TermCurrentBColor << 12) + _TermCurrentReverse; |
| 625 | for (var x = _termx; x < obj.width; x++) { |
| 626 | _tscreen[_termy][x] = ' '; |
| 627 | _scratt[_termy][x] = t; |
| 628 | } |
| 629 | } |
| 630 | |
| 631 | function _EraseBolToCursor() { |
| 632 | var t = (_TermCurrentFColor << 6) + (_TermCurrentBColor << 12) + _TermCurrentReverse; |
| 633 | for (var x = 0; x < _termx; x++) { |
| 634 | _tscreen[_termy][x] = ' '; |
| 635 | _scratt[_termy][x] = t; |
| 636 | } |
| 637 | } |
| 638 | |
| 639 | function _EraseLine(line) { |
| 640 | var t = (_TermCurrentFColor << 6) + (_TermCurrentBColor << 12) + _TermCurrentReverse; |
| 641 | for (var x = 0; x < obj.width; x++) { |
| 642 | _tscreen[line][x] = ' '; |
| 643 | _scratt[line][x] = t; |
| 644 | } |
| 645 | } |
| 646 | |
| 647 | obj.TermSendKeys = function (keys) { if (obj.debugmode == 2) { console.log("TSend(" + keys.length + "): " + rstr2hex(keys), keys); } obj.parent.send(keys); } |
| 648 | obj.TermSendKey = function (key) { if (obj.debugmode == 2) { console.log("TSend(1): " + rstr2hex(String.fromCharCode(key)), key); } obj.parent.send(String.fromCharCode(key)); } |
| 649 | |
| 650 | function _TermMoveUp(linecount) { |
| 651 | var x, y; |
| 652 | for (y = _scrollRegion[0]; y <= _scrollRegion[1] - linecount; y++) { |
| 653 | _tscreen[y] = _tscreen[y + linecount]; |
| 654 | _scratt[y] = _scratt[y + linecount]; |
| 655 | } |
| 656 | for (y = _scrollRegion[1] - linecount + 1; y <= _scrollRegion[1]; y++) { |
| 657 | _tscreen[y] = []; |
| 658 | _scratt[y] = []; |
| 659 | for (x = 0; x < obj.width; x++) { |
| 660 | _tscreen[y][x] = ' '; |
| 661 | _scratt[y][x] = (7 << 6); |
| 662 | } |
| 663 | } |
| 664 | } |
| 665 | |
| 666 | obj.TermHandleKeys = function (e) { |
| 667 | if (!e.ctrlKey) { |
| 668 | if (e.which == 127) obj.TermSendKey(8); |
| 669 | else if (e.which == 13) { obj.TermSendKeys(obj.lineFeed); } |
| 670 | else if (e.which != 0) obj.TermSendKey(e.which); |
| 671 | return false; |
| 672 | } |
| 673 | if (e.preventDefault) e.preventDefault(); |
| 674 | if (e.stopPropagation) e.stopPropagation(); |
| 675 | } |
| 676 | |
| 677 | obj.TermHandleKeyUp = function (e) { |
| 678 | if ((e.which != 8) && (e.which != 32) && (e.which != 9)) return true; |
| 679 | if (e.preventDefault) e.preventDefault(); |
| 680 | if (e.stopPropagation) e.stopPropagation(); |
| 681 | return false; |
| 682 | } |
| 683 | |
| 684 | obj.TermHandleKeyDown = function (e) { |
| 685 | if ((e.which >= 65) && (e.which <= 90) && (e.ctrlKey == true)) { |
| 686 | obj.TermSendKey(e.which - 64); |
| 687 | if (e.preventDefault) e.preventDefault(); |
| 688 | if (e.stopPropagation) e.stopPropagation(); |
| 689 | return; |
| 690 | } |
| 691 | if (e.which == 27) { obj.TermSendKeys(String.fromCharCode(27)); return true; }; // ESC |
| 692 | |
| 693 | if (_altKeypadMode == true) { |
| 694 | if (e.which == 37) { obj.TermSendKeys(String.fromCharCode(27, 79, 68)); return true; }; // Left |
| 695 | if (e.which == 38) { obj.TermSendKeys(String.fromCharCode(27, 79, 65)); return true; }; // Up |
| 696 | if (e.which == 39) { obj.TermSendKeys(String.fromCharCode(27, 79, 67)); return true; }; // Right |
| 697 | if (e.which == 40) { obj.TermSendKeys(String.fromCharCode(27, 79, 66)); return true; }; // Down |
| 698 | } else { |
| 699 | if (e.which == 37) { obj.TermSendKeys(String.fromCharCode(27, 91, 68)); return true; }; // Left |
| 700 | if (e.which == 38) { obj.TermSendKeys(String.fromCharCode(27, 91, 65)); return true; }; // Up |
| 701 | if (e.which == 39) { obj.TermSendKeys(String.fromCharCode(27, 91, 67)); return true; }; // Right |
| 702 | if (e.which == 40) { obj.TermSendKeys(String.fromCharCode(27, 91, 66)); return true; }; // Down |
| 703 | } |
| 704 | |
| 705 | if (e.which == 33) { obj.TermSendKeys(String.fromCharCode(27, 91, 53, 126)); return true; }; // PageUp |
| 706 | if (e.which == 34) { obj.TermSendKeys(String.fromCharCode(27, 91, 54, 126)); return true; }; // PageDown |
| 707 | if (e.which == 35) { obj.TermSendKeys(String.fromCharCode(27, 91, 70)); return true; }; // End |
| 708 | if (e.which == 36) { obj.TermSendKeys(String.fromCharCode(27, 91, 72)); return true; }; // Home |
| 709 | if (e.which == 45) { obj.TermSendKeys(String.fromCharCode(27, 91, 50, 126)); return true; }; // Insert |
| 710 | if (e.which == 46) { obj.TermSendKeys(String.fromCharCode(27, 91, 51, 126)); return true; }; // Delete |
| 711 | |
| 712 | if (e.which == 9) { obj.TermSendKeys("\t"); if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return true; }; // TAB |
| 713 | |
| 714 | // F1 to F12 keys |
| 715 | // ###BEGIN###{Terminal-FxEnumation-All} |
| 716 | var fx0 = [80, 81, 119, 120, 116, 117, 113, 114, 112, 77]; |
| 717 | var fx1 = [49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 33, 64]; |
| 718 | var fx2 = [80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91]; |
| 719 | if (e.which > 111 & e.which < 124 && e.repeat == false) { // F1 to F12 keys |
| 720 | if (obj.fxEmulation == 0 && e.which < 122) { obj.TermSendKeys(String.fromCharCode(27, 91, 79, fx0[e.which - 112])); return true; } // 'Intel (F10 = ESC+[OM)' |
| 721 | if (obj.fxEmulation == 1) { obj.TermSendKeys(String.fromCharCode(27, fx1[e.which - 112])); return true; } // 'Alternate (F10 = ESC+0)' |
| 722 | if (obj.fxEmulation == 2) { obj.TermSendKeys(String.fromCharCode(27, 79, fx2[e.which - 112])); return true; } // 'VT100+ (F10 = ESC+[OY)' |
| 723 | } |
| 724 | // ###END###{Terminal-FxEnumation-All} |
| 725 | // ###BEGIN###{Terminal-FxEnumation-Intel} |
| 726 | var fx0 = [80, 81, 119, 120, 116, 117, 113, 114, 112, 77]; |
| 727 | if (e.which > 111 & e.which < 122 && e.repeat == false) { obj.TermSendKeys(String.fromCharCode(27, 91, 79, fx0[e.which - 112])); return true; } // 'Intel (F10 = ESC+[OM)' |
| 728 | // ###END###{Terminal-FxEnumation-Intel} |
| 729 | // ###BEGIN###{Terminal-FxEnumation-Alternate} |
| 730 | var fx1 = [49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 33, 64]; |
| 731 | if (e.which > 111 & e.which < 124 && e.repeat == false) { obj.TermSendKeys(String.fromCharCode(27, fx1[e.which - 112])); return true; } // 'Alternate (F10 = ESC+0)' |
| 732 | // ###END###{Terminal-FxEnumation-Alternate} |
| 733 | // ###BEGIN###{Terminal-FxEnumation-VT100Plus} |
| 734 | var fx2 = [80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91]; |
| 735 | if (e.which > 111 & e.which < 124 && e.repeat == false) { obj.TermSendKeys(String.fromCharCode(27, 79, fx2[e.which - 112])); return true; } // 'VT100+ (F10 = ESC+[OY)' |
| 736 | // ###END###{Terminal-FxEnumation-VT100Plus} |
| 737 | |
| 738 | if (e.which != 8 && e.which != 32 && e.which != 9) return true; |
| 739 | obj.TermSendKey(e.which); |
| 740 | if (e.preventDefault) e.preventDefault(); |
| 741 | if (e.stopPropagation) e.stopPropagation(); |
| 742 | return false; |
| 743 | } |
| 744 | |
| 745 | obj.recordLineTobackBuffer = function(y) { |
| 746 | var closetag = '', buf = ''; |
| 747 | var r = obj.TermDrawLine(buf, y, closetag); |
| 748 | buf = r[0]; |
| 749 | closetag = r[1]; |
| 750 | scrollBackBuffer.push(buf + closetag + '<br>'); |
| 751 | } |
| 752 | |
| 753 | obj.TermDrawLine = function (buf, y, closetag) { |
| 754 | var newat, c, oldat = 1, x1, x2; |
| 755 | for (var x = 0; x < obj.width; ++x) { |
| 756 | newat = _scratt[y][x]; |
| 757 | if (_termx == x && _termy == y && _cursorVisible) { newat |= _VTREVERSE; } // If this is the cursor location, reverse the color. |
| 758 | if (newat != oldat) { |
| 759 | buf += closetag; |
| 760 | closetag = ''; |
| 761 | x1 = 6; x2 = 12; |
| 762 | if (newat & _VTREVERSE) { x1 = 12; x2 = 6; } |
| 763 | buf += '<span style="color:#' + _TermColors[(newat >> x1) & 0x3F] + ';background-color:#' + _TermColors[(newat >> x2) & 0x3F]; |
| 764 | if (newat & _VTUNDERLINE) buf += ';text-decoration:underline'; |
| 765 | buf += ';">'; |
| 766 | closetag = "</span>" + closetag; |
| 767 | oldat = newat; |
| 768 | } |
| 769 | |
| 770 | c = _tscreen[y][x]; |
| 771 | switch (c) { |
| 772 | case '&': buf += '&'; break; |
| 773 | case '<': buf += '<'; break; |
| 774 | case '>': buf += '>'; break; |
| 775 | case ' ': buf += ' '; break; |
| 776 | default: buf += c; break; |
| 777 | } |
| 778 | } |
| 779 | return [buf, closetag]; |
| 780 | } |
| 781 | |
| 782 | obj.TermDraw = function() { |
| 783 | var closetag = '', buf = ''; |
| 784 | for (var y = 0; y < obj.height; ++y) { |
| 785 | var r = obj.TermDrawLine(buf, y, closetag); |
| 786 | buf = r[0]; |
| 787 | closetag = r[1]; |
| 788 | if (y != (obj.height - 1)) buf += '<br>'; |
| 789 | } |
| 790 | |
| 791 | if (scrollBackBuffer.length > 800) { scrollBackBuffer = scrollBackBuffer.slice(scrollBackBuffer.length - 800); } |
| 792 | var backbuffer = scrollBackBuffer.join(''); |
| 793 | obj.DivElement.innerHTML = "<font size='4'><b>" + backbuffer + buf + closetag + "</b></font>"; |
| 794 | obj.DivElement.scrollTop = obj.DivElement.scrollHeight; |
| 795 | if (obj.heightLock == 0) { setTimeout(obj.TermLockHeight, 10); } |
| 796 | } |
| 797 | |
| 798 | obj.TermLockHeight = function () { |
| 799 | obj.heightLock = obj.DivElement.clientHeight; |
| 800 | obj.DivElement.style['height'] = obj.DivElement.parentNode.style['height'] = obj.heightLock + 'px'; |
| 801 | obj.DivElement.style['overflow-y'] = 'scroll'; |
| 802 | } |
| 803 | |
| 804 | obj.TermInit = function () { obj.TermResetScreen(); } |
| 805 | |
| 806 | obj.heightLock = 0; |
| 807 | obj.DivElement.style['height'] = ''; |
| 808 | if ((options != null) && (options.cols != null) && (options.rows != null)) { obj.Init(options.cols, options.rows); } else { obj.Init(); } |
| 809 | return obj; |
| 810 | } |