1 | ;
|
2 |
|
3 | var states = require('./states');
|
4 |
|
5 | function fixLinefeed(data) {
|
6 | return data.replace(/([^\r])\n/g, '$1\r\n');
|
7 | }
|
8 |
|
9 | function fixIndent(data) {
|
10 | if (!/(^|\n) /.test(data)) return data;
|
11 |
|
12 | // not very efficient, but works and would only become a problem
|
13 | // once we render huge amounts of data
|
14 | return data
|
15 | .split('\n')
|
16 | .map(function (line) {
|
17 | var count = 0;
|
18 | while(line.charAt(0) === ' '){
|
19 | line = line.slice(1);
|
20 | count++;
|
21 | }
|
22 | while(count--) {
|
23 | line = ' ' + line;
|
24 | }
|
25 | return line;
|
26 | })
|
27 | .join('\r\n');
|
28 | }
|
29 |
|
30 | module.exports = function(Terminal) {
|
31 |
|
32 | Terminal.prototype.write = function(data) {
|
33 |
|
34 | data = fixLinefeed(data);
|
35 | data = fixIndent(data);
|
36 |
|
37 | var l = data.length,
|
38 | i = 0,
|
39 | cs, ch;
|
40 |
|
41 | this.refreshStart = this.y;
|
42 | this.refreshEnd = this.y;
|
43 |
|
44 | if (this.ybase !== this.ydisp) {
|
45 | this.ydisp = this.ybase;
|
46 | this.maxRange();
|
47 | }
|
48 |
|
49 | // this.log(JSON.stringify(data.replace(/\x1b/g, '^[')));
|
50 |
|
51 | for (; i < l; i++) {
|
52 | ch = data[i];
|
53 | switch (this.state) {
|
54 | case states.normal:
|
55 | switch (ch) {
|
56 | // '\0'
|
57 | // case '\0':
|
58 | // break;
|
59 |
|
60 | // '\a'
|
61 | case '\x07':
|
62 | this.bell();
|
63 | break;
|
64 |
|
65 | // '\n', '\v', '\f'
|
66 | case '\n':
|
67 | case '\x0b':
|
68 | case '\x0c':
|
69 | if (this.convertEol) {
|
70 | this.x = 0;
|
71 | }
|
72 | this.y++;
|
73 | break;
|
74 |
|
75 | // '\r'
|
76 | case '\r':
|
77 | this.x = 0;
|
78 | break;
|
79 |
|
80 | // '\b'
|
81 | case '\x08':
|
82 | if (this.x > 0) {
|
83 | this.x--;
|
84 | }
|
85 | break;
|
86 |
|
87 | // '\t'
|
88 | case '\t':
|
89 | this.x = this.nextStop();
|
90 | break;
|
91 |
|
92 | // shift out
|
93 | case '\x0e':
|
94 | this.setgLevel(1);
|
95 | break;
|
96 |
|
97 | // shift in
|
98 | case '\x0f':
|
99 | this.setgLevel(0);
|
100 | break;
|
101 |
|
102 | // '\e'
|
103 | case '\x1b':
|
104 | this.state = states.escaped;
|
105 | break;
|
106 |
|
107 | default:
|
108 | // ' '
|
109 | if (ch >= ' ') {
|
110 | if (this.charset && this.charset[ch]) {
|
111 | ch = this.charset[ch];
|
112 | }
|
113 | if (this.x >= this.cols) {
|
114 | this.x = 0;
|
115 | this.y++;
|
116 | }
|
117 | this.lines[this.y + this.ybase][this.x] = [this.curAttr, ch];
|
118 | this.x++;
|
119 | this.updateRange(this.y);
|
120 | }
|
121 | break;
|
122 | }
|
123 | break;
|
124 | case states.escaped:
|
125 | switch (ch) {
|
126 | // ESC [ Control Sequence Introducer ( CSI is 0x9b).
|
127 | case '[':
|
128 | this.params = [];
|
129 | this.currentParam = 0;
|
130 | this.state = states.csi;
|
131 | break;
|
132 |
|
133 | // ESC ] Operating System Command ( OSC is 0x9d).
|
134 | case ']':
|
135 | this.params = [];
|
136 | this.currentParam = 0;
|
137 | this.state = states.osc;
|
138 | break;
|
139 |
|
140 | // ESC P Device Control String ( DCS is 0x90).
|
141 | case 'P':
|
142 | this.params = [];
|
143 | this.currentParam = 0;
|
144 | this.state = states.dcs;
|
145 | break;
|
146 |
|
147 | // ESC _ Application Program Command ( APC is 0x9f).
|
148 | case '_':
|
149 | this.stateType = 'apc';
|
150 | this.state = states.ignore;
|
151 | break;
|
152 |
|
153 | // ESC ^ Privacy Message ( PM is 0x9e).
|
154 | case '^':
|
155 | this.stateType = 'pm';
|
156 | this.state = states.ignore;
|
157 | break;
|
158 |
|
159 | // ESC c Full Reset (RIS).
|
160 | case 'c':
|
161 | this.reset();
|
162 | break;
|
163 |
|
164 | // ESC E Next Line ( NEL is 0x85).
|
165 | // ESC D Index ( IND is 0x84).
|
166 | case 'E':
|
167 | this.x = 0;
|
168 | break;
|
169 | case 'D':
|
170 | this.index();
|
171 | break;
|
172 |
|
173 | // ESC M Reverse Index ( RI is 0x8d).
|
174 | case 'M':
|
175 | this.reverseIndex();
|
176 | break;
|
177 |
|
178 | // ESC % Select default/utf-8 character set.
|
179 | // @ = default, G = utf-8
|
180 | case '%':
|
181 | //this.charset = null;
|
182 | this.setgLevel(0);
|
183 | this.setgCharset(0, Terminal.charsets.US);
|
184 | this.state = states.normal;
|
185 | i++;
|
186 | break;
|
187 |
|
188 | // ESC (,),*,+,-,. Designate G0-G2 Character Set.
|
189 | case '(':
|
190 | // <-- this seems to get all the attention
|
191 | case ')':
|
192 | case '*':
|
193 | case '+':
|
194 | case '-':
|
195 | case '.':
|
196 | switch (ch) {
|
197 | case '(':
|
198 | this.gcharset = 0;
|
199 | break;
|
200 | case ')':
|
201 | this.gcharset = 1;
|
202 | break;
|
203 | case '*':
|
204 | this.gcharset = 2;
|
205 | break;
|
206 | case '+':
|
207 | this.gcharset = 3;
|
208 | break;
|
209 | case '-':
|
210 | this.gcharset = 1;
|
211 | break;
|
212 | case '.':
|
213 | this.gcharset = 2;
|
214 | break;
|
215 | }
|
216 | this.state = states.charset;
|
217 | break;
|
218 |
|
219 | // Designate G3 Character Set (VT300).
|
220 | // A = ISO Latin-1 Supplemental.
|
221 | // Not implemented.
|
222 | case '/':
|
223 | this.gcharset = 3;
|
224 | this.state = states.charset;
|
225 | i--;
|
226 | break;
|
227 |
|
228 | // ESC N
|
229 | // Single Shift Select of G2 Character Set
|
230 | // ( SS2 is 0x8e). This affects next character only.
|
231 | case 'N':
|
232 | break;
|
233 | // ESC O
|
234 | // Single Shift Select of G3 Character Set
|
235 | // ( SS3 is 0x8f). This affects next character only.
|
236 | case 'O':
|
237 | break;
|
238 | // ESC n
|
239 | // Invoke the G2 Character Set as GL (LS2).
|
240 | case 'n':
|
241 | this.setgLevel(2);
|
242 | break;
|
243 | // ESC o
|
244 | // Invoke the G3 Character Set as GL (LS3).
|
245 | case 'o':
|
246 | this.setgLevel(3);
|
247 | break;
|
248 | // ESC |
|
249 | // Invoke the G3 Character Set as GR (LS3R).
|
250 | case '|':
|
251 | this.setgLevel(3);
|
252 | break;
|
253 | // ESC }
|
254 | // Invoke the G2 Character Set as GR (LS2R).
|
255 | case '}':
|
256 | this.setgLevel(2);
|
257 | break;
|
258 | // ESC ~
|
259 | // Invoke the G1 Character Set as GR (LS1R).
|
260 | case '~':
|
261 | this.setgLevel(1);
|
262 | break;
|
263 |
|
264 | // ESC 7 Save Cursor (DECSC).
|
265 | case '7':
|
266 | this.saveCursor();
|
267 | this.state = states.normal;
|
268 | break;
|
269 |
|
270 | // ESC 8 Restore Cursor (DECRC).
|
271 | case '8':
|
272 | this.restoreCursor();
|
273 | this.state = states.normal;
|
274 | break;
|
275 |
|
276 | // ESC # 3 DEC line height/width
|
277 | case '#':
|
278 | this.state = states.normal;
|
279 | i++;
|
280 | break;
|
281 |
|
282 | // ESC H Tab Set (HTS is 0x88).
|
283 | case 'H':
|
284 | this.tabSet();
|
285 | break;
|
286 |
|
287 | // ESC = Application Keypad (DECPAM).
|
288 | case '=':
|
289 | this.log('Serial port requested application keypad.');
|
290 | this.applicationKeypad = true;
|
291 | this.state = states.normal;
|
292 | break;
|
293 |
|
294 | // ESC > Normal Keypad (DECPNM).
|
295 | case '>':
|
296 | this.log('Switching back to normal keypad.');
|
297 | this.applicationKeypad = false;
|
298 | this.state = states.normal;
|
299 | break;
|
300 |
|
301 | default:
|
302 | this.state = states.normal;
|
303 | this.error('Unknown ESC control: %s.', ch);
|
304 | break;
|
305 | }
|
306 | break;
|
307 |
|
308 | case states.charset:
|
309 | switch (ch) {
|
310 | case '0':
|
311 | // DEC Special Character and Line Drawing Set.
|
312 | cs = Terminal.charsets.SCLD;
|
313 | break;
|
314 | case 'A':
|
315 | // UK
|
316 | cs = Terminal.charsets.UK;
|
317 | break;
|
318 | case 'B':
|
319 | // United States (USASCII).
|
320 | cs = Terminal.charsets.US;
|
321 | break;
|
322 | case '4':
|
323 | // Dutch
|
324 | cs = Terminal.charsets.Dutch;
|
325 | break;
|
326 | case 'C':
|
327 | // Finnish
|
328 | case '5':
|
329 | cs = Terminal.charsets.Finnish;
|
330 | break;
|
331 | case 'R':
|
332 | // French
|
333 | cs = Terminal.charsets.French;
|
334 | break;
|
335 | case 'Q':
|
336 | // FrenchCanadian
|
337 | cs = Terminal.charsets.FrenchCanadian;
|
338 | break;
|
339 | case 'K':
|
340 | // German
|
341 | cs = Terminal.charsets.German;
|
342 | break;
|
343 | case 'Y':
|
344 | // Italian
|
345 | cs = Terminal.charsets.Italian;
|
346 | break;
|
347 | case 'E':
|
348 | // NorwegianDanish
|
349 | case '6':
|
350 | cs = Terminal.charsets.NorwegianDanish;
|
351 | break;
|
352 | case 'Z':
|
353 | // Spanish
|
354 | cs = Terminal.charsets.Spanish;
|
355 | break;
|
356 | case 'H':
|
357 | // Swedish
|
358 | case '7':
|
359 | cs = Terminal.charsets.Swedish;
|
360 | break;
|
361 | case '=':
|
362 | // Swiss
|
363 | cs = Terminal.charsets.Swiss;
|
364 | break;
|
365 | case '/':
|
366 | // ISOLatin (actually /A)
|
367 | cs = Terminal.charsets.ISOLatin;
|
368 | i++;
|
369 | break;
|
370 | default:
|
371 | // Default
|
372 | cs = Terminal.charsets.US;
|
373 | break;
|
374 | }
|
375 | this.setgCharset(this.gcharset, cs);
|
376 | this.gcharset = null;
|
377 | this.state = states.normal;
|
378 | break;
|
379 |
|
380 | case states.osc:
|
381 | // OSC Ps ; Pt ST
|
382 | // OSC Ps ; Pt BEL
|
383 | // Set Text Parameters.
|
384 | if (ch === '\x1b' || ch === '\x07') {
|
385 | if (ch === '\x1b') i++;
|
386 |
|
387 | this.params.push(this.currentParam);
|
388 |
|
389 | switch (this.params[0]) {
|
390 | case 0:
|
391 | case 1:
|
392 | case 2:
|
393 | if (this.params[1]) {
|
394 | this.title = this.params[1];
|
395 | this.handleTitle(this.title);
|
396 | }
|
397 | break;
|
398 | case 3:
|
399 | // set X property
|
400 | break;
|
401 | case 4:
|
402 | case 5:
|
403 | // change dynamic colors
|
404 | break;
|
405 | case 10:
|
406 | case 11:
|
407 | case 12:
|
408 | case 13:
|
409 | case 14:
|
410 | case 15:
|
411 | case 16:
|
412 | case 17:
|
413 | case 18:
|
414 | case 19:
|
415 | // change dynamic ui colors
|
416 | break;
|
417 | case 46:
|
418 | // change log file
|
419 | break;
|
420 | case 50:
|
421 | // dynamic font
|
422 | break;
|
423 | case 51:
|
424 | // emacs shell
|
425 | break;
|
426 | case 52:
|
427 | // manipulate selection data
|
428 | break;
|
429 | case 104:
|
430 | case 105:
|
431 | case 110:
|
432 | case 111:
|
433 | case 112:
|
434 | case 113:
|
435 | case 114:
|
436 | case 115:
|
437 | case 116:
|
438 | case 117:
|
439 | case 118:
|
440 | // reset colors
|
441 | break;
|
442 | }
|
443 |
|
444 | this.params = [];
|
445 | this.currentParam = 0;
|
446 | this.state = states.normal;
|
447 | } else {
|
448 | if (!this.params.length) {
|
449 | if (ch >= '0' && ch <= '9') {
|
450 | this.currentParam = this.currentParam * 10 + ch.charCodeAt(0) - 48;
|
451 | } else if (ch === ';') {
|
452 | this.params.push(this.currentParam);
|
453 | this.currentParam = '';
|
454 | }
|
455 | } else {
|
456 | this.currentParam += ch;
|
457 | }
|
458 | }
|
459 | break;
|
460 |
|
461 | case states.csi:
|
462 | // '?', '>', '!'
|
463 | if (ch === '?' || ch === '>' || ch === '!') {
|
464 | this.prefix = ch;
|
465 | break;
|
466 | }
|
467 |
|
468 | // 0 - 9
|
469 | if (ch >= '0' && ch <= '9') {
|
470 | this.currentParam = this.currentParam * 10 + ch.charCodeAt(0) - 48;
|
471 | break;
|
472 | }
|
473 |
|
474 | // '$', '"', ' ', '\''
|
475 | if (ch === '$' || ch === '"' || ch === ' ' || ch === '\'') {
|
476 | this.postfix = ch;
|
477 | break;
|
478 | }
|
479 |
|
480 | this.params.push(this.currentParam);
|
481 | this.currentParam = 0;
|
482 |
|
483 | // ';'
|
484 | if (ch === ';') break;
|
485 |
|
486 | this.state = states.normal;
|
487 |
|
488 | switch (ch) {
|
489 | // CSI Ps A
|
490 | // Cursor Up Ps Times (default = 1) (CUU).
|
491 | case 'A':
|
492 | this.cursorUp(this.params);
|
493 | break;
|
494 |
|
495 | // CSI Ps B
|
496 | // Cursor Down Ps Times (default = 1) (CUD).
|
497 | case 'B':
|
498 | this.cursorDown(this.params);
|
499 | break;
|
500 |
|
501 | // CSI Ps C
|
502 | // Cursor Forward Ps Times (default = 1) (CUF).
|
503 | case 'C':
|
504 | this.cursorForward(this.params);
|
505 | break;
|
506 |
|
507 | // CSI Ps D
|
508 | // Cursor Backward Ps Times (default = 1) (CUB).
|
509 | case 'D':
|
510 | this.cursorBackward(this.params);
|
511 | break;
|
512 |
|
513 | // CSI Ps ; Ps H
|
514 | // Cursor Position [row;column] (default = [1,1]) (CUP).
|
515 | case 'H':
|
516 | this.cursorPos(this.params);
|
517 | break;
|
518 |
|
519 | // CSI Ps J Erase in Display (ED).
|
520 | case 'J':
|
521 | this.eraseInDisplay(this.params);
|
522 | break;
|
523 |
|
524 | // CSI Ps K Erase in Line (EL).
|
525 | case 'K':
|
526 | this.eraseInLine(this.params);
|
527 | break;
|
528 |
|
529 | // CSI Pm m Character Attributes (SGR).
|
530 | case 'm':
|
531 | this.charAttributes(this.params);
|
532 | break;
|
533 |
|
534 | // CSI Ps n Device Status Report (DSR).
|
535 | case 'n':
|
536 | this.deviceStatus(this.params);
|
537 | break;
|
538 |
|
539 | /**
|
540 | * Additions
|
541 | */
|
542 |
|
543 | // CSI Ps @
|
544 | // Insert Ps (Blank) Character(s) (default = 1) (ICH).
|
545 | case '@':
|
546 | this.insertChars(this.params);
|
547 | break;
|
548 |
|
549 | // CSI Ps E
|
550 | // Cursor Next Line Ps Times (default = 1) (CNL).
|
551 | case 'E':
|
552 | this.cursorNextLine(this.params);
|
553 | break;
|
554 |
|
555 | // CSI Ps F
|
556 | // Cursor Preceding Line Ps Times (default = 1) (CNL).
|
557 | case 'F':
|
558 | this.cursorPrecedingLine(this.params);
|
559 | break;
|
560 |
|
561 | // CSI Ps G
|
562 | // Cursor Character Absolute [column] (default = [row,1]) (CHA).
|
563 | case 'G':
|
564 | this.cursorCharAbsolute(this.params);
|
565 | break;
|
566 |
|
567 | // CSI Ps L
|
568 | // Insert Ps Line(s) (default = 1) (IL).
|
569 | case 'L':
|
570 | this.insertLines(this.params);
|
571 | break;
|
572 |
|
573 | // CSI Ps M
|
574 | // Delete Ps Line(s) (default = 1) (DL).
|
575 | case 'M':
|
576 | this.deleteLines(this.params);
|
577 | break;
|
578 |
|
579 | // CSI Ps P
|
580 | // Delete Ps Character(s) (default = 1) (DCH).
|
581 | case 'P':
|
582 | this.deleteChars(this.params);
|
583 | break;
|
584 |
|
585 | // CSI Ps X
|
586 | // Erase Ps Character(s) (default = 1) (ECH).
|
587 | case 'X':
|
588 | this.eraseChars(this.params);
|
589 | break;
|
590 |
|
591 | // CSI Pm ` Character Position Absolute
|
592 | // [column] (default = [row,1]) (HPA).
|
593 | case '`':
|
594 | this.charPosAbsolute(this.params);
|
595 | break;
|
596 |
|
597 | // 141 61 a * HPR -
|
598 | // Horizontal Position Relative
|
599 | case 'a':
|
600 | this.HPositionRelative(this.params);
|
601 | break;
|
602 |
|
603 | // CSI P s c
|
604 | // Send Device Attributes (Primary DA).
|
605 | // CSI > P s c
|
606 | // Send Device Attributes (Secondary DA)
|
607 | case 'c':
|
608 | //- this.sendDeviceAttributes(this.params);
|
609 | break;
|
610 |
|
611 | // CSI Pm d
|
612 | // Line Position Absolute [row] (default = [1,column]) (VPA).
|
613 | case 'd':
|
614 | this.linePosAbsolute(this.params);
|
615 | break;
|
616 |
|
617 | // 145 65 e * VPR - Vertical Position Relative
|
618 | case 'e':
|
619 | this.VPositionRelative(this.params);
|
620 | break;
|
621 |
|
622 | // CSI Ps ; Ps f
|
623 | // Horizontal and Vertical Position [row;column] (default =
|
624 | // [1,1]) (HVP).
|
625 | case 'f':
|
626 | this.HVPosition(this.params);
|
627 | break;
|
628 |
|
629 | // CSI Pm h Set Mode (SM).
|
630 | // CSI ? Pm h - mouse escape codes, cursor escape codes
|
631 | case 'h':
|
632 | //- this.setMode(this.params);
|
633 | break;
|
634 |
|
635 | // CSI Pm l Reset Mode (RM).
|
636 | // CSI ? Pm l
|
637 | case 'l':
|
638 | //- this.resetMode(this.params);
|
639 | break;
|
640 |
|
641 | // CSI Ps ; Ps r
|
642 | // Set Scrolling Region [top;bottom] (default = full size of win-
|
643 | // dow) (DECSTBM).
|
644 | // CSI ? Pm r
|
645 | case 'r':
|
646 | //- this.setScrollRegion(this.params);
|
647 | break;
|
648 |
|
649 | // CSI s
|
650 | // Save cursor (ANSI.SYS).
|
651 | case 's':
|
652 | this.saveCursor(this.params);
|
653 | break;
|
654 |
|
655 | // CSI u
|
656 | // Restore cursor (ANSI.SYS).
|
657 | case 'u':
|
658 | this.restoreCursor(this.params);
|
659 | break;
|
660 |
|
661 | /**
|
662 | * Lesser Used
|
663 | */
|
664 |
|
665 | // CSI Ps I
|
666 | // Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).
|
667 | case 'I':
|
668 | this.cursorForwardTab(this.params);
|
669 | break;
|
670 |
|
671 | // CSI Ps S Scroll up Ps lines (default = 1) (SU).
|
672 | case 'S':
|
673 | //- this.scrollUp(this.params);
|
674 | break;
|
675 |
|
676 | // CSI Ps T Scroll down Ps lines (default = 1) (SD).
|
677 | // CSI Ps ; Ps ; Ps ; Ps ; Ps T
|
678 | // CSI > Ps; Ps T
|
679 | case 'T':
|
680 | if (this.params.length < 2 && !this.prefix) {
|
681 | //- this.scrollDown(this.params);
|
682 | }
|
683 | break;
|
684 |
|
685 | // CSI Ps Z
|
686 | // Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).
|
687 | case 'Z':
|
688 | this.cursorBackwardTab(this.params);
|
689 | break;
|
690 |
|
691 | // CSI Ps b Repeat the preceding graphic character Ps times (REP).
|
692 | case 'b':
|
693 | this.repeatPrecedingCharacter(this.params);
|
694 | break;
|
695 |
|
696 | // CSI Ps g Tab Clear (TBC).
|
697 | case 'g':
|
698 | this.tabClear(this.params);
|
699 | break;
|
700 | case 'p':
|
701 | switch (this.prefix) {
|
702 | case '!':
|
703 | this.softReset(this.params);
|
704 | break;
|
705 | }
|
706 | break;
|
707 |
|
708 | default:
|
709 | this.error('Unknown CSI code: %s.', ch);
|
710 | break;
|
711 | }
|
712 |
|
713 | this.prefix = '';
|
714 | this.postfix = '';
|
715 | break;
|
716 |
|
717 | case states.dcs:
|
718 | if (ch === '\x1b' || ch === '\x07') {
|
719 | if (ch === '\x1b') i++;
|
720 |
|
721 | switch (this.prefix) {
|
722 | // User-Defined Keys (DECUDK).
|
723 | case '':
|
724 | break;
|
725 |
|
726 | // Request Status String (DECRQSS).
|
727 | // test: echo -e '\eP$q"p\e\\'
|
728 | case '$q':
|
729 | var pt = this.currentParam,
|
730 | valid = false;
|
731 |
|
732 | switch (pt) {
|
733 | // DECSCA
|
734 | case '"q':
|
735 | pt = '0"q';
|
736 | break;
|
737 |
|
738 | // DECSCL
|
739 | case '"p':
|
740 | pt = '61"p';
|
741 | break;
|
742 |
|
743 | // DECSTBM
|
744 | case 'r':
|
745 | pt = '' + (this.scrollTop + 1) + ';' + (this.scrollBottom + 1) + 'r';
|
746 | break;
|
747 |
|
748 | // SGR
|
749 | case 'm':
|
750 | pt = '0m';
|
751 | break;
|
752 |
|
753 | default:
|
754 | this.error('Unknown DCS Pt: %s.', pt);
|
755 | pt = '';
|
756 | break;
|
757 | }
|
758 |
|
759 | //- this.send('\x1bP' + valid + '$r' + pt + '\x1b\\');
|
760 | break;
|
761 |
|
762 | // Set Termcap/Terminfo Data (xterm, experimental).
|
763 | case '+p':
|
764 | break;
|
765 |
|
766 | default:
|
767 | this.error('Unknown DCS prefix: %s.', this.prefix);
|
768 | break;
|
769 | }
|
770 |
|
771 | this.currentParam = 0;
|
772 | this.prefix = '';
|
773 | this.state = states.normal;
|
774 | } else if (!this.currentParam) {
|
775 | if (!this.prefix && ch !== '$' && ch !== '+') {
|
776 | this.currentParam = ch;
|
777 | } else if (this.prefix.length === 2) {
|
778 | this.currentParam = ch;
|
779 | } else {
|
780 | this.prefix += ch;
|
781 | }
|
782 | } else {
|
783 | this.currentParam += ch;
|
784 | }
|
785 | break;
|
786 |
|
787 | case states.ignore:
|
788 | // For PM and APC.
|
789 | if (ch === '\x1b' || ch === '\x07') {
|
790 | if (ch === '\x1b') i++;
|
791 | this.stateData = '';
|
792 | this.state = states.normal;
|
793 | } else {
|
794 | if (!this.stateData) this.stateData = '';
|
795 | this.stateData += ch;
|
796 | }
|
797 | break;
|
798 | }
|
799 | }
|
800 |
|
801 | this.updateRange(this.y);
|
802 | this.refresh(this.refreshStart, this.refreshEnd);
|
803 | };
|
804 |
|
805 | Terminal.prototype.writeln = function(data) {
|
806 | // properly render empty lines
|
807 | if (!data.trim().length) data = ' ';
|
808 | this.write(data + '\r\n');
|
809 |
|
810 | // fix newlines not properly respected otherwise
|
811 | if (data.charAt(data.length - 1) === '\r\n') this.writeln(' ');
|
812 | };
|
813 | };
|