1 import { IInputHandler, ITerminal } from './Interfaces';
2 import { C0 } from './EscapeSequences';
4 export class InputHandler implements IInputHandler {
5 // TODO: We want to type _terminal when it's pulled into TS
6 constructor(private _terminal: any) { }
13 if (!this._terminal.visualBell) {
16 this._terminal.element.style.borderColor = 'white';
17 setTimeout(() => this._terminal.element.style.borderColor = '', 10);
18 if (this._terminal.popOnBell) {
19 this._terminal.focus();
25 * Line Feed or New Line (NL). (LF is Ctrl-J).
27 public lineFeed(): void {
28 if (this._terminal.convertEol) {
32 if (this._terminal.y > this._terminal.scrollBottom) {
34 this._terminal.scroll();
40 * Carriage Return (Ctrl-M).
42 public carriageReturn(): void {
50 public backspace(): void {
51 if (this._terminal.x > 0) {
58 * Horizontal Tab (HT) (Ctrl-I).
61 this._terminal.x = this._terminal.nextStop();
66 * Shift Out (Ctrl-N) -> Switch to Alternate Character Set. This invokes the
69 public shiftOut(): void {
70 this._terminal.setgLevel(1);
75 * Shift In (Ctrl-O) -> Switch to Standard Character Set. This invokes the G0
76 * character set (the default).
78 public shiftIn(): void {
79 this._terminal.setgLevel(0);
84 * Insert Ps (Blank) Character(s) (default = 1) (ICH).
86 public insertChars(params: number[]): void {
87 let param, row, j, ch;
90 if (param < 1) param = 1;
92 row = this._terminal.y + this._terminal.ybase;
94 ch = [this._terminal.eraseAttr(), ' ', 1]; // xterm
96 while (param-- && j < this._terminal.cols) {
97 this._terminal.lines.get(row).splice(j++, 0, ch);
98 this._terminal.lines.get(row).pop();
104 * Cursor Up Ps Times (default = 1) (CUU).
106 public cursorUp(params: number[]): void {
107 let param = params[0];
111 this._terminal.y -= param;
112 if (this._terminal.y < 0) {
113 this._terminal.y = 0;
119 * Cursor Down Ps Times (default = 1) (CUD).
121 public cursorDown(params: number[]) {
122 let param = params[0];
126 this._terminal.y += param;
127 if (this._terminal.y >= this._terminal.rows) {
128 this._terminal.y = this._terminal.rows - 1;
134 * Cursor Forward Ps Times (default = 1) (CUF).
136 public cursorForward(params: number[]) {
137 let param = params[0];
141 this._terminal.x += param;
142 if (this._terminal.x >= this._terminal.cols) {
143 this._terminal.x = this._terminal.cols - 1;
149 * Cursor Backward Ps Times (default = 1) (CUB).
151 public cursorBackward(params: number[]) {
152 let param = params[0];
156 this._terminal.x -= param;
157 if (this._terminal.x < 0) {
158 this._terminal.x = 0;
164 * Cursor Next Line Ps Times (default = 1) (CNL).
167 public cursorNextLine(params: number[]): void {
168 let param = params[0];
172 this._terminal.y += param;
173 if (this._terminal.y >= this._terminal.rows) {
174 this._terminal.y = this._terminal.rows - 1;
176 this._terminal.x = 0;
182 * Cursor Preceding Line Ps Times (default = 1) (CNL).
185 public cursorPrecedingLine(params: number[]): void {
186 let param = params[0];
190 this._terminal.y -= param;
191 if (this._terminal.y < 0) {
192 this._terminal.y = 0;
194 this._terminal.x = 0;
200 * Cursor Character Absolute [column] (default = [row,1]) (CHA).
202 public cursorCharAbsolute(params: number[]): void {
203 let param = params[0];
207 this._terminal.x = param - 1;
212 * Cursor Position [row;column] (default = [1,1]) (CUP).
214 public cursorPosition(params: number[]): void {
219 if (params.length >= 2) {
227 } else if (row >= this._terminal.rows) {
228 row = this._terminal.rows - 1;
233 } else if (col >= this._terminal.cols) {
234 col = this._terminal.cols - 1;
237 this._terminal.x = col;
238 this._terminal.y = row;
242 * CSI Ps J Erase in Display (ED).
243 * Ps = 0 -> Erase Below (default).
244 * Ps = 1 -> Erase Above.
245 * Ps = 2 -> Erase All.
246 * Ps = 3 -> Erase Saved Lines (xterm).
248 * Erase in Display (DECSED).
249 * Ps = 0 -> Selective Erase Below (default).
250 * Ps = 1 -> Selective Erase Above.
251 * Ps = 2 -> Selective Erase All.
253 public eraseInDisplay(params: number[]): void {
257 this._terminal.eraseRight(this._terminal.x, this._terminal.y);
258 j = this._terminal.y + 1;
259 for (; j < this._terminal.rows; j++) {
260 this._terminal.eraseLine(j);
264 this._terminal.eraseLeft(this._terminal.x, this._terminal.y);
265 j = this._terminal.y;
267 this._terminal.eraseLine(j);
271 j = this._terminal.rows;
272 while (j--) this._terminal.eraseLine(j);
281 * CSI Ps K Erase in Line (EL).
282 * Ps = 0 -> Erase to Right (default).
283 * Ps = 1 -> Erase to Left.
284 * Ps = 2 -> Erase All.
286 * Erase in Line (DECSEL).
287 * Ps = 0 -> Selective Erase to Right (default).
288 * Ps = 1 -> Selective Erase to Left.
289 * Ps = 2 -> Selective Erase All.
291 public eraseInLine(params: number[]): void {
294 this._terminal.eraseRight(this._terminal.x, this._terminal.y);
297 this._terminal.eraseLeft(this._terminal.x, this._terminal.y);
300 this._terminal.eraseLine(this._terminal.y);
306 * CSI Pm m Character Attributes (SGR).
307 * Ps = 0 -> Normal (default).
309 * Ps = 4 -> Underlined.
310 * Ps = 5 -> Blink (appears as Bold).
312 * Ps = 8 -> Invisible, i.e., hidden (VT300).
313 * Ps = 2 2 -> Normal (neither bold nor faint).
314 * Ps = 2 4 -> Not underlined.
315 * Ps = 2 5 -> Steady (not blinking).
316 * Ps = 2 7 -> Positive (not inverse).
317 * Ps = 2 8 -> Visible, i.e., not hidden (VT300).
318 * Ps = 3 0 -> Set foreground color to Black.
319 * Ps = 3 1 -> Set foreground color to Red.
320 * Ps = 3 2 -> Set foreground color to Green.
321 * Ps = 3 3 -> Set foreground color to Yellow.
322 * Ps = 3 4 -> Set foreground color to Blue.
323 * Ps = 3 5 -> Set foreground color to Magenta.
324 * Ps = 3 6 -> Set foreground color to Cyan.
325 * Ps = 3 7 -> Set foreground color to White.
326 * Ps = 3 9 -> Set foreground color to default (original).
327 * Ps = 4 0 -> Set background color to Black.
328 * Ps = 4 1 -> Set background color to Red.
329 * Ps = 4 2 -> Set background color to Green.
330 * Ps = 4 3 -> Set background color to Yellow.
331 * Ps = 4 4 -> Set background color to Blue.
332 * Ps = 4 5 -> Set background color to Magenta.
333 * Ps = 4 6 -> Set background color to Cyan.
334 * Ps = 4 7 -> Set background color to White.
335 * Ps = 4 9 -> Set background color to default (original).
337 * If 16-color support is compiled, the following apply. Assume
338 * that xterm's resources are set so that the ISO color codes are
339 * the first 8 of a set of 16. Then the aixterm colors are the
340 * bright versions of the ISO colors:
341 * Ps = 9 0 -> Set foreground color to Black.
342 * Ps = 9 1 -> Set foreground color to Red.
343 * Ps = 9 2 -> Set foreground color to Green.
344 * Ps = 9 3 -> Set foreground color to Yellow.
345 * Ps = 9 4 -> Set foreground color to Blue.
346 * Ps = 9 5 -> Set foreground color to Magenta.
347 * Ps = 9 6 -> Set foreground color to Cyan.
348 * Ps = 9 7 -> Set foreground color to White.
349 * Ps = 1 0 0 -> Set background color to Black.
350 * Ps = 1 0 1 -> Set background color to Red.
351 * Ps = 1 0 2 -> Set background color to Green.
352 * Ps = 1 0 3 -> Set background color to Yellow.
353 * Ps = 1 0 4 -> Set background color to Blue.
354 * Ps = 1 0 5 -> Set background color to Magenta.
355 * Ps = 1 0 6 -> Set background color to Cyan.
356 * Ps = 1 0 7 -> Set background color to White.
358 * If xterm is compiled with the 16-color support disabled, it
359 * supports the following, from rxvt:
360 * Ps = 1 0 0 -> Set foreground and background color to
363 * If 88- or 256-color support is compiled, the following apply.
364 * Ps = 3 8 ; 5 ; Ps -> Set foreground color to the second
366 * Ps = 4 8 ; 5 ; Ps -> Set background color to the second
369 public charAttributes(params: number[]): void {
370 // Optimize a single SGR0.
371 if (params.length === 1 && params[0] === 0) {
372 this._terminal.curAttr = this._terminal.defAttr;
376 let l = params.length
378 , flags = this._terminal.curAttr >> 18
379 , fg = (this._terminal.curAttr >> 9) & 0x1ff
380 , bg = this._terminal.curAttr & 0x1ff
385 if (p >= 30 && p <= 37) {
388 } else if (p >= 40 && p <= 47) {
391 } else if (p >= 90 && p <= 97) {
395 } else if (p >= 100 && p <= 107) {
399 } else if (p === 0) {
401 flags = this._terminal.defAttr >> 18;
402 fg = (this._terminal.defAttr >> 9) & 0x1ff;
403 bg = this._terminal.defAttr & 0x1ff;
407 } else if (p === 1) {
410 } else if (p === 4) {
413 } else if (p === 5) {
416 } else if (p === 7) {
417 // inverse and positive
418 // test with: echo -e '\e[31m\e[42mhello\e[7mworld\e[27mhi\e[m'
420 } else if (p === 8) {
423 } else if (p === 22) {
426 } else if (p === 24) {
429 } else if (p === 25) {
432 } else if (p === 27) {
435 } else if (p === 28) {
438 } else if (p === 39) {
440 fg = (this._terminal.defAttr >> 9) & 0x1ff;
441 } else if (p === 49) {
443 bg = this._terminal.defAttr & 0x1ff;
444 } else if (p === 38) {
446 if (params[i + 1] === 2) {
448 fg = this._terminal.matchColor(
450 params[i + 1] & 0xff,
451 params[i + 2] & 0xff);
452 if (fg === -1) fg = 0x1ff;
454 } else if (params[i + 1] === 5) {
456 p = params[i] & 0xff;
459 } else if (p === 48) {
461 if (params[i + 1] === 2) {
463 bg = this._terminal.matchColor(
465 params[i + 1] & 0xff,
466 params[i + 2] & 0xff);
467 if (bg === -1) bg = 0x1ff;
469 } else if (params[i + 1] === 5) {
471 p = params[i] & 0xff;
474 } else if (p === 100) {
476 fg = (this._terminal.defAttr >> 9) & 0x1ff;
477 bg = this._terminal.defAttr & 0x1ff;
479 this._terminal.error('Unknown SGR attribute: %d.', p);
483 this._terminal.curAttr = (flags << 18) | (fg << 9) | bg;
487 * CSI Ps n Device Status Report (DSR).
488 * Ps = 5 -> Status Report. Result (``OK'') is
490 * Ps = 6 -> Report Cursor Position (CPR) [row;column].
494 * Device Status Report (DSR, DEC-specific).
495 * Ps = 6 -> Report Cursor Position (CPR) [row;column] as CSI
496 * ? r ; c R (assumes page is zero).
497 * Ps = 1 5 -> Report Printer status as CSI ? 1 0 n (ready).
498 * or CSI ? 1 1 n (not ready).
499 * Ps = 2 5 -> Report UDK status as CSI ? 2 0 n (unlocked)
500 * or CSI ? 2 1 n (locked).
501 * Ps = 2 6 -> Report Keyboard status as
502 * CSI ? 2 7 ; 1 ; 0 ; 0 n (North American).
503 * The last two parameters apply to VT400 & up, and denote key-
504 * board ready and LK01 respectively.
505 * Ps = 5 3 -> Report Locator status as
506 * CSI ? 5 3 n Locator available, if compiled-in, or
507 * CSI ? 5 0 n No Locator, if not.
509 public deviceStatus(params: number[]): void {
510 if (!this._terminal.prefix) {
514 this._terminal.send(C0.ESC + '[0n');
518 this._terminal.send(C0.ESC + '['
519 + (this._terminal.y + 1)
521 + (this._terminal.x + 1)
525 } else if (this._terminal.prefix === '?') {
526 // modern xterm doesnt seem to
527 // respond to any of these except ?6, 6, and 5
531 this._terminal.send(C0.ESC + '[?'
532 + (this._terminal.y + 1)
534 + (this._terminal.x + 1)
539 // this.send(C0.ESC + '[?11n');
542 // dont support user defined keys
543 // this.send(C0.ESC + '[?21n');
546 // north american keyboard
547 // this.send(C0.ESC + '[?27;1;0;0n');
550 // no dec locator/mouse
551 // this.send(C0.ESC + '[?50n');