Mercurial > hg > rlgwebd
comparison termemu.js @ 211:d60063a674e1
Terminal emulation: implement the CSI b sequence.
CSI b repeats the previous character, if it was printable and not an
escape sequence.
author | John "Elwin" Edwards |
---|---|
date | Thu, 05 Sep 2019 15:19:27 -0400 |
parents | 1d3cfe10974a |
children |
comparison
equal
deleted
inserted
replaced
210:b04313038a0b | 211:d60063a674e1 |
---|---|
69 bgColor: "black", // Default background color | 69 bgColor: "black", // Default background color |
70 scrT: 0, // top and bottom of scrolling region | 70 scrT: 0, // top and bottom of scrolling region |
71 scrB: 0, // init() will set this properly | 71 scrB: 0, // init() will set this properly |
72 c: null, // Contains cursor position and text attributes | 72 c: null, // Contains cursor position and text attributes |
73 offedge: false, // Going off the edge doesn't mean adding a new line | 73 offedge: false, // Going off the edge doesn't mean adding a new line |
74 lastcode: 0, // Last printed character | |
74 clearAttrs: function () { | 75 clearAttrs: function () { |
75 /* Make sure to reset ALL attribute properties and NOTHING else. */ | 76 /* Make sure to reset ALL attribute properties and NOTHING else. */ |
76 this.c.bold = false; | 77 this.c.bold = false; |
77 this.c.inverse = false; | 78 this.c.inverse = false; |
78 this.c.uline = false; | 79 this.c.uline = false; |
458 } | 459 } |
459 for (var i = 0; i < this.h; i++) { | 460 for (var i = 0; i < this.h; i++) { |
460 this.screen.replaceChild(this.makeRow(), this.screen.childNodes[i]); | 461 this.screen.replaceChild(this.makeRow(), this.screen.childNodes[i]); |
461 } | 462 } |
462 this.flipCursor(); // make it appear in the new row | 463 this.flipCursor(); // make it appear in the new row |
464 this.lastcode = 0; | |
463 return; | 465 return; |
464 }, | 466 }, |
465 write: function (codes) { | 467 write: function (codes) { |
466 //dchunk(codes); | 468 //dchunk(codes); |
467 for (var i = 0; i < codes.length; i++) { | 469 for (var i = 0; i < codes.length; i++) { |
528 } | 530 } |
529 else { | 531 else { |
530 /* Nothing else is implemented yet. */ | 532 /* Nothing else is implemented yet. */ |
531 debug(1, "Unrecognized sequence ESC " + codes[i].toString(16)); | 533 debug(1, "Unrecognized sequence ESC " + codes[i].toString(16)); |
532 this.comseq = []; | 534 this.comseq = []; |
535 } | |
536 if (this.comseq.length == 0) { | |
537 // A complete sequence was processed, clear lastcode. | |
538 this.lastcode = 0; | |
533 } | 539 } |
534 } | 540 } |
535 else if (this.comseq.length == 2 && this.comseq[0] == 27) { | 541 else if (this.comseq.length == 2 && this.comseq[0] == 27) { |
536 /* An ESC C N sequence. Not implemented. Doesn't check validity | 542 /* An ESC C N sequence. Not implemented. Doesn't check validity |
537 * of N. */ | 543 * of N. */ |
553 else | 559 else |
554 debug(1, "Unknown sequence ESC " + | 560 debug(1, "Unknown sequence ESC " + |
555 String.fromCharCode(this.comseq[1]) + " 0x" + | 561 String.fromCharCode(this.comseq[1]) + " 0x" + |
556 codes[i].toString(16)); | 562 codes[i].toString(16)); |
557 this.comseq = []; | 563 this.comseq = []; |
564 this.lastcode = 0; | |
558 } | 565 } |
559 else if (this.comseq[0] == 157) { | 566 else if (this.comseq[0] == 157) { |
560 /* Commands beginning with OSC */ | 567 /* Commands beginning with OSC */ |
561 /* Check for string terminator */ | 568 /* Check for string terminator */ |
562 if (codes[i] == 7 || codes[i] == 156 || (codes[i] == 92 && | 569 if (codes[i] == 7 || codes[i] == 156 || (codes[i] == 92 && |
564 if (codes[i] == 92 && this.comseq[this.comseq.length - 1] == 27) | 571 if (codes[i] == 92 && this.comseq[this.comseq.length - 1] == 27) |
565 this.comseq.pop(); | 572 this.comseq.pop(); |
566 debug(0, "Got " + (this.comseq.length - 1) + "-byte OSC sequence"); | 573 debug(0, "Got " + (this.comseq.length - 1) + "-byte OSC sequence"); |
567 this.oscProcess(); | 574 this.oscProcess(); |
568 this.comseq = []; | 575 this.comseq = []; |
576 this.lastcode = 0; | |
569 } | 577 } |
570 else | 578 else |
571 this.comseq.push(codes[i]); | 579 this.comseq.push(codes[i]); |
572 } | 580 } |
573 else if (this.comseq[0] == 155) { | 581 else if (this.comseq[0] == 155) { |
580 if (csiPre.indexOf(codes[i]) >= 0) { | 588 if (csiPre.indexOf(codes[i]) >= 0) { |
581 if (this.comseq.length > 1) { | 589 if (this.comseq.length > 1) { |
582 /* Chars in csiPre can only occur right after the CSI */ | 590 /* Chars in csiPre can only occur right after the CSI */ |
583 debug(1, "Invalid CSI sequence: misplaced prefix"); | 591 debug(1, "Invalid CSI sequence: misplaced prefix"); |
584 this.comseq = []; | 592 this.comseq = []; |
593 this.lastcode = 0; | |
585 } | 594 } |
586 else | 595 else |
587 this.comseq.push(codes[i]); | 596 this.comseq.push(codes[i]); |
588 } | 597 } |
589 else if (csiPost.indexOf(this.comseq[this.comseq.length - 1]) >= 0 && | 598 else if (csiPost.indexOf(this.comseq[this.comseq.length - 1]) >= 0 && |
590 !csiFinal(codes[i])) { | 599 !csiFinal(codes[i])) { |
591 /* Chars is csiPost must come right before the final char */ | 600 /* Chars in csiPost must come right before the final char */ |
592 debug(1, "Invalid CSI sequence: misplaced postfix"); | 601 debug(1, "Invalid CSI sequence: misplaced postfix"); |
593 this.comseq = []; | 602 this.comseq = []; |
603 this.lastcode = 0; | |
594 } | 604 } |
595 else if ((codes[i] >= 48 && codes[i] <= 57) || codes[i] == 59 || | 605 else if ((codes[i] >= 48 && codes[i] <= 57) || codes[i] == 59 || |
596 csiPost.indexOf(codes[i]) >= 0) { | 606 csiPost.indexOf(codes[i]) >= 0) { |
597 /* Numbers and ; can go anywhere */ | 607 /* Numbers and ; can go anywhere */ |
598 this.comseq.push(codes[i]); | 608 this.comseq.push(codes[i]); |
603 this.comseq = []; | 613 this.comseq = []; |
604 } | 614 } |
605 else { | 615 else { |
606 debug(1, "Invalid CSI sequence: unknown code " + codes[i].toString(16)); | 616 debug(1, "Invalid CSI sequence: unknown code " + codes[i].toString(16)); |
607 this.comseq = []; | 617 this.comseq = []; |
618 this.lastcode = 0; | |
608 } | 619 } |
609 } | 620 } |
610 else { | 621 else { |
611 debug(1, "Unknown sequence with " + this.comseq[0].toString(16)); | 622 debug(1, "Unknown sequence with " + this.comseq[0].toString(16)); |
612 this.comseq = []; | 623 this.comseq = []; |
613 } | 624 this.lastcode = 0; |
614 continue; | 625 } |
615 } | 626 } |
616 /* Treat it as a single character. */ | 627 else if ((codes[i] >= 32 && codes[i] < 127) || codes[i] >= 160) { |
617 if (codes[i] == 5) { | |
618 sendback("06"); | |
619 } | |
620 else if (codes[i] == 7) { | |
621 /* bell */ | |
622 bell(true); | |
623 } | |
624 else if (codes[i] == 8) { | |
625 /* backspace */ | |
626 if (this.offedge) | |
627 this.offedge = false; | |
628 else if (this.c.x > 0) | |
629 this.cmove(null, this.c.x - 1); | |
630 } | |
631 else if (codes[i] == 9) { | |
632 /* tab */ | |
633 var xnew; | |
634 if (this.c.x < this.w - 1) { | |
635 xnew = 8 * (Math.floor(this.c.x / 8) + 1); | |
636 if (xnew >= this.w) | |
637 xnew = this.w - 1; | |
638 this.cmove(null, xnew); | |
639 } | |
640 else { | |
641 this.offedge = true; | |
642 } | |
643 } | |
644 else if (codes[i] >= 10 && codes[i] <= 12) { | |
645 /* newline, vertical tab, form feed */ | |
646 if (this.offedge) | |
647 this.newline(true); | |
648 else | |
649 this.newline(false); | |
650 } | |
651 else if (codes[i] == 13) { | |
652 /* carriage return \r */ | |
653 this.cmove(null, 0); | |
654 } | |
655 else if (codes[i] == 14) { | |
656 /* shift out */ | |
657 // Currently assuming that G1 is DEC Special & Line Drawing | |
658 this.c.cset = "0"; | |
659 debug(0, "Using DEC graphics charset."); | |
660 } | |
661 else if (codes[i] == 15) { | |
662 /* shift in */ | |
663 // Currently assuming that G0 is ASCII | |
664 this.c.cset = "B"; | |
665 debug(0, "Using ASCII charset."); | |
666 } | |
667 else if (codes[i] == 27) { | |
668 /* escape */ | |
669 this.comseq.push(codes[i]); | |
670 } | |
671 else if (codes[i] < 32 || (codes[i] >= 127 && codes[i] < 160)) { | |
672 /* Some kind of control character. */ | |
673 debug(1, "Unprintable character 0x" + codes[i].toString(16)); | |
674 } | |
675 else { | |
676 /* If it's ASCII, it's printable; take a risk on anything higher */ | 628 /* If it's ASCII, it's printable; take a risk on anything higher */ |
677 if ((this.c.cset == "0") && (codes[i] in decChars)) { | 629 if ((this.c.cset == "0") && (codes[i] in decChars)) { |
678 // DEC special character set | 630 // DEC special character set |
679 this.placechar(String.fromCharCode(decChars[codes[i]])); | 631 this.lastcode = decChars[codes[i]]; |
680 } | 632 } |
681 else { | 633 else { |
682 this.placechar(String.fromCharCode(codes[i])); | 634 this.lastcode = codes[i]; |
683 } | 635 } |
636 this.placechar(String.fromCharCode(this.lastcode)); | |
637 } | |
638 else { | |
639 /* Treat it as a single control character. */ | |
640 this.singleCtl(codes[i]); | |
684 } | 641 } |
685 } | 642 } |
686 return; | 643 return; |
644 }, | |
645 singleCtl: function (ctlcode) { | |
646 if (ctlcode == 5) { | |
647 sendback("06"); | |
648 } | |
649 else if (ctlcode == 7) { | |
650 /* bell */ | |
651 bell(true); | |
652 } | |
653 else if (ctlcode == 8) { | |
654 /* backspace */ | |
655 if (this.offedge) | |
656 this.offedge = false; | |
657 else if (this.c.x > 0) | |
658 this.cmove(null, this.c.x - 1); | |
659 } | |
660 else if (ctlcode == 9) { | |
661 /* tab */ | |
662 var xnew; | |
663 if (this.c.x < this.w - 1) { | |
664 xnew = 8 * (Math.floor(this.c.x / 8) + 1); | |
665 if (xnew >= this.w) | |
666 xnew = this.w - 1; | |
667 this.cmove(null, xnew); | |
668 } | |
669 else { | |
670 this.offedge = true; | |
671 } | |
672 } | |
673 else if (ctlcode >= 10 && ctlcode <= 12) { | |
674 /* newline, vertical tab, form feed */ | |
675 if (this.offedge) | |
676 this.newline(true); | |
677 else | |
678 this.newline(false); | |
679 } | |
680 else if (ctlcode == 13) { | |
681 /* carriage return \r */ | |
682 this.cmove(null, 0); | |
683 } | |
684 else if (ctlcode == 14) { | |
685 /* shift out */ | |
686 // Currently assuming that G1 is DEC Special & Line Drawing | |
687 this.c.cset = "0"; | |
688 debug(0, "Using DEC graphics charset."); | |
689 } | |
690 else if (ctlcode == 15) { | |
691 /* shift in */ | |
692 // Currently assuming that G0 is ASCII | |
693 this.c.cset = "B"; | |
694 debug(0, "Using ASCII charset."); | |
695 } | |
696 else if (ctlcode == 27) { | |
697 /* escape */ | |
698 this.comseq.push(27); | |
699 } | |
700 else { | |
701 debug(1, "Unprintable character 0x" + ctlcode.toString(16)); | |
702 } | |
703 if (ctlcode != 27) { | |
704 // Sequences should preserve lastcode until they are completed | |
705 this.lastcode = 0; | |
706 } | |
687 }, | 707 }, |
688 csiProcess: function () { | 708 csiProcess: function () { |
689 /* Processes the CSI sequence in this.comseq */ | 709 /* Processes the CSI sequence in this.comseq */ |
690 var c = this.comseq[this.comseq.length - 1]; | 710 var c = this.comseq[this.comseq.length - 1]; |
691 if (this.comseq[0] != 155 || !csiFinal(c)) | 711 if (this.comseq[0] != 155 || !csiFinal(c)) |
692 return; | 712 return; |
713 var printed = false; | |
693 var comstr = ""; | 714 var comstr = ""; |
694 for (var i = 1; i < this.comseq.length; i++) | 715 for (var i = 1; i < this.comseq.length; i++) |
695 comstr += String.fromCharCode(this.comseq[i]); | 716 comstr += String.fromCharCode(this.comseq[i]); |
696 debug(0, "CSI sequence: " + comstr); | 717 debug(0, "CSI sequence: " + comstr); |
697 var reCSI = /^([>?!])?([0-9;]*)([ "$'])?([A-Za-z@`{|])$/; | 718 var reCSI = /^([>?!])?([0-9;]*)([ "$'])?([A-Za-z@`{|])$/; |
698 var matchCSI = comstr.match(reCSI); | 719 var matchCSI = comstr.match(reCSI); |
699 if (!matchCSI) { | 720 if (!matchCSI) { |
700 debug(1, "Unrecognized CSI sequence: " + comstr); | 721 debug(1, "Unrecognized CSI sequence: " + comstr); |
722 this.lastcode = 0; | |
701 return; | 723 return; |
702 } | 724 } |
703 var prefix = null; | 725 var prefix = null; |
704 if (matchCSI[1]) | 726 if (matchCSI[1]) |
705 prefix = matchCSI[1]; | 727 prefix = matchCSI[1]; |
723 /* The final character determines the action. */ | 745 /* The final character determines the action. */ |
724 if (c == 64) { | 746 if (c == 64) { |
725 /* @ - insert spaces at cursor */ | 747 /* @ - insert spaces at cursor */ |
726 if (prefix || postfix) { | 748 if (prefix || postfix) { |
727 debug(1, "Invalid CSI @ sequence: " + comstr); | 749 debug(1, "Invalid CSI @ sequence: " + comstr); |
750 this.lastcode = 0; | |
728 return; | 751 return; |
729 } | 752 } |
730 /* The cursor stays still, but characters move out from under it. */ | 753 /* The cursor stays still, but characters move out from under it. */ |
731 this.flipCursor(); | 754 this.flipCursor(); |
732 var rowdiv = this.screen.childNodes[this.c.y]; | 755 var rowdiv = this.screen.childNodes[this.c.y]; |
743 else if (c >= 65 && c <= 71) { | 766 else if (c >= 65 && c <= 71) { |
744 /* A - up, B - down, C - forward, D - backward */ | 767 /* A - up, B - down, C - forward, D - backward */ |
745 /* E - next line, F - previous line, G - to column */ | 768 /* E - next line, F - previous line, G - to column */ |
746 if (prefix || postfix) { | 769 if (prefix || postfix) { |
747 debug(1, "Invalid CSI sequence: " + comstr); | 770 debug(1, "Invalid CSI sequence: " + comstr); |
771 this.lastcode = 0; | |
748 return; | 772 return; |
749 } | 773 } |
750 /* These may be out of range, but cmove will take care of that. */ | 774 /* These may be out of range, but cmove will take care of that. */ |
751 if (c == 65) | 775 if (c == 65) |
752 this.cmove(this.c.y - count, null); | 776 this.cmove(this.c.y - count, null); |
767 /* H - move */ | 791 /* H - move */ |
768 var x = 0; | 792 var x = 0; |
769 var y = 0; | 793 var y = 0; |
770 if (prefix || postfix) { | 794 if (prefix || postfix) { |
771 debug(1, "Invalid CSI H sequence: " + comstr); | 795 debug(1, "Invalid CSI H sequence: " + comstr); |
796 this.lastcode = 0; | |
772 return; | 797 return; |
773 } | 798 } |
774 if (params[0]) | 799 if (params[0]) |
775 y = params[0] - 1; | 800 y = params[0] - 1; |
776 if (params[1]) | 801 if (params[1]) |
785 else if (c == 73) { | 810 else if (c == 73) { |
786 /* I - move forward by tabs */ | 811 /* I - move forward by tabs */ |
787 var x = this.c.x; | 812 var x = this.c.x; |
788 if (prefix || postfix) { | 813 if (prefix || postfix) { |
789 debug(1, "Invalid CSI I sequence: " + comstr); | 814 debug(1, "Invalid CSI I sequence: " + comstr); |
815 this.lastcode = 0; | |
790 return; | 816 return; |
791 } | 817 } |
792 while (count > 0) { | 818 while (count > 0) { |
793 x = 8 * (Math.floor(x / 8) + 1); | 819 x = 8 * (Math.floor(x / 8) + 1); |
794 if (x >= this.w) { | 820 if (x >= this.w) { |
806 var cols; | 832 var cols; |
807 if (prefix == '?') | 833 if (prefix == '?') |
808 debug(1, "Warning: CSI ?J not implemented"); | 834 debug(1, "Warning: CSI ?J not implemented"); |
809 else if (prefix || postfix) { | 835 else if (prefix || postfix) { |
810 debug(1, "Invalid CSI J sequence: " + comstr); | 836 debug(1, "Invalid CSI J sequence: " + comstr); |
837 this.lastcode = 0; | |
811 return; | 838 return; |
812 } | 839 } |
813 if (!params[0]) { | 840 if (!params[0]) { |
814 /* Either 0 or not given */ | 841 /* Either 0 or not given */ |
815 start = this.c.y + 1; | 842 start = this.c.y + 1; |
826 end = this.h - 1; | 853 end = this.h - 1; |
827 cols = 0; | 854 cols = 0; |
828 } | 855 } |
829 else { | 856 else { |
830 debug(1, "Unimplemented parameter in CSI J sequence: " + comstr); | 857 debug(1, "Unimplemented parameter in CSI J sequence: " + comstr); |
858 this.lastcode = 0; | |
831 return; | 859 return; |
832 } | 860 } |
833 for (var nrow = start; nrow <= end; nrow++) { | 861 for (var nrow = start; nrow <= end; nrow++) { |
834 this.screen.replaceChild(this.makeRow(), this.screen.childNodes[nrow]); | 862 this.screen.replaceChild(this.makeRow(), this.screen.childNodes[nrow]); |
835 } | 863 } |
853 var end; | 881 var end; |
854 if (prefix == '?') | 882 if (prefix == '?') |
855 debug(1, "Warning: CSI ?K not implemented"); | 883 debug(1, "Warning: CSI ?K not implemented"); |
856 else if (prefix || postfix) { | 884 else if (prefix || postfix) { |
857 debug(1, "Invalid CSI K sequence: " + comstr); | 885 debug(1, "Invalid CSI K sequence: " + comstr); |
886 this.lastcode = 0; | |
858 return; | 887 return; |
859 } | 888 } |
860 /* 0 (default): right, 1: left, 2: all. Include cursor position. */ | 889 /* 0 (default): right, 1: left, 2: all. Include cursor position. */ |
861 if (params[0] == 1) { | 890 if (params[0] == 1) { |
862 start = 0; | 891 start = 0; |
883 else if (c == 76 || c == 77) { | 912 else if (c == 76 || c == 77) { |
884 /* L - insert lines at the current position. | 913 /* L - insert lines at the current position. |
885 * M - delete current lines */ | 914 * M - delete current lines */ |
886 if (prefix || postfix) { | 915 if (prefix || postfix) { |
887 debug(1, "Invalid CSI sequence: " + comstr); | 916 debug(1, "Invalid CSI sequence: " + comstr); |
917 this.lastcode = 0; | |
888 return; | 918 return; |
889 } | 919 } |
890 /* CSI LM have no effect outside of the scrolling region */ | 920 /* CSI LM have no effect outside of the scrolling region */ |
891 if (this.c.y < this.scrT || this.c.y > this.scrB) | 921 if (this.c.y < this.scrT || this.c.y > this.scrB) { |
892 return; | 922 this.lastcode = 0; |
923 return; | |
924 } | |
893 this.flipCursor(); | 925 this.flipCursor(); |
894 while (count > 0) { | 926 while (count > 0) { |
895 var blankrow = this.makeRow(); | 927 var blankrow = this.makeRow(); |
896 if (c == 76) { | 928 if (c == 76) { |
897 this.historize(this.scrB); | 929 this.historize(this.scrB); |
913 } | 945 } |
914 else if (c == 80) { | 946 else if (c == 80) { |
915 /* P - delete at active position, causing cells on the right to shift. */ | 947 /* P - delete at active position, causing cells on the right to shift. */ |
916 if (prefix || postfix) { | 948 if (prefix || postfix) { |
917 debug(1, "Invalid CSI P sequence: " + comstr); | 949 debug(1, "Invalid CSI P sequence: " + comstr); |
950 this.lastcode = 0; | |
918 return; | 951 return; |
919 } | 952 } |
920 var cursrow = this.screen.childNodes[this.c.y]; | 953 var cursrow = this.screen.childNodes[this.c.y]; |
921 while (count > 0) { | 954 while (count > 0) { |
922 cursrow.removeChild(cursrow.childNodes[this.c.x]); | 955 cursrow.removeChild(cursrow.childNodes[this.c.x]); |
928 } | 961 } |
929 else if (c == 83 || c == 84) { | 962 else if (c == 83 || c == 84) { |
930 /* S - scroll up, T - scroll down */ | 963 /* S - scroll up, T - scroll down */ |
931 if (prefix || postfix) { | 964 if (prefix || postfix) { |
932 debug(1, "Invalid CSI sequence: " + comstr); | 965 debug(1, "Invalid CSI sequence: " + comstr); |
966 this.lastcode = 0; | |
933 return; | 967 return; |
934 } | 968 } |
935 if (c == 83) | 969 if (c == 83) |
936 this.scroll(count); | 970 this.scroll(count); |
937 else | 971 else |
939 } | 973 } |
940 else if (c == 88) { | 974 else if (c == 88) { |
941 /* X - erase characters */ | 975 /* X - erase characters */ |
942 if (prefix || postfix) { | 976 if (prefix || postfix) { |
943 debug(1, "Invalid CSI sequence: " + comstr); | 977 debug(1, "Invalid CSI sequence: " + comstr); |
978 this.lastcode = 0; | |
944 return; | 979 return; |
945 } | 980 } |
946 var row = this.screen.childNodes[this.c.y]; | 981 var row = this.screen.childNodes[this.c.y]; |
947 for (var i = 0; i < count && this.c.x + i < this.w; i++) { | 982 for (var i = 0; i < count && this.c.x + i < this.w; i++) { |
948 row.replaceChild(this.makeCell(' '), row.childNodes[this.c.x + i]); | 983 row.replaceChild(this.makeCell(' '), row.childNodes[this.c.x + i]); |
952 else if (c == 90) { | 987 else if (c == 90) { |
953 /* Z - tab backwards */ | 988 /* Z - tab backwards */ |
954 var x = this.c.x; | 989 var x = this.c.x; |
955 if (prefix || postfix) { | 990 if (prefix || postfix) { |
956 debug(1, "Invalid CSI Z sequence: " + comstr); | 991 debug(1, "Invalid CSI Z sequence: " + comstr); |
992 this.lastcode = 0; | |
957 return; | 993 return; |
958 } | 994 } |
959 while (count > 0) { | 995 while (count > 0) { |
960 x = 8 * (Math.ceil(x / 8) - 1); | 996 x = 8 * (Math.ceil(x / 8) - 1); |
961 if (x < 0) { | 997 if (x < 0) { |
968 } | 1004 } |
969 else if (c == 96) { | 1005 else if (c == 96) { |
970 /* ` - go to col */ | 1006 /* ` - go to col */ |
971 if (prefix || postfix) { | 1007 if (prefix || postfix) { |
972 debug(1, "Invalid CSI ` sequence: " + comstr); | 1008 debug(1, "Invalid CSI ` sequence: " + comstr); |
1009 this.lastcode = 0; | |
973 return; | 1010 return; |
974 } | 1011 } |
975 this.cmove(null, count - 1); | 1012 this.cmove(null, count - 1); |
1013 } | |
1014 else if (c == 98) { | |
1015 /* b - repeat previous character */ | |
1016 if (this.lastcode !== 0) { | |
1017 while (count > 0) { | |
1018 this.placechar(String.fromCharCode(this.lastcode)); | |
1019 count--; | |
1020 } | |
1021 printed = true; | |
1022 } | |
976 } | 1023 } |
977 else if (c == 99) { | 1024 else if (c == 99) { |
978 /* c - query terminal attributes */ | 1025 /* c - query terminal attributes */ |
979 if (prefix !== null) { | 1026 if (prefix !== null) { |
980 debug(1, "Unimplemented CSI sequence: " + comstr); | 1027 debug(1, "Unimplemented CSI sequence: " + comstr); |
1028 this.lastcode = 0; | |
981 return; | 1029 return; |
982 } | 1030 } |
983 /* "CSI ? 1 ; 2 c" - VT100 */ | 1031 /* "CSI ? 1 ; 2 c" - VT100 */ |
984 sendback("1b5b3f313b3263"); | 1032 sendback("1b5b3f313b3263"); |
985 } | 1033 } |
986 else if (c == 100) { | 1034 else if (c == 100) { |
987 /* d - go to row */ | 1035 /* d - go to row */ |
988 if (prefix || postfix) { | 1036 if (prefix || postfix) { |
989 debug(1, "Invalid CSI d sequence: " + comstr); | 1037 debug(1, "Invalid CSI d sequence: " + comstr); |
1038 this.lastcode = 0; | |
990 return; | 1039 return; |
991 } | 1040 } |
992 this.cmove(count - 1, null); | 1041 this.cmove(count - 1, null); |
993 } | 1042 } |
994 else if (c == 102) { | 1043 else if (c == 102) { |
995 /* f - move */ | 1044 /* f - move */ |
996 var x = 0; | 1045 var x = 0; |
997 var y = 0; | 1046 var y = 0; |
998 if (prefix || postfix) { | 1047 if (prefix || postfix) { |
999 debug(1, "Invalid CSI f sequence: " + comstr); | 1048 debug(1, "Invalid CSI f sequence: " + comstr); |
1049 this.lastcode = 0; | |
1000 return; | 1050 return; |
1001 } | 1051 } |
1002 if (params[0]) | 1052 if (params[0]) |
1003 y = params[0] - 1; | 1053 y = params[0] - 1; |
1004 if (params[1]) | 1054 if (params[1]) |
1007 } | 1057 } |
1008 else if (c == 104) { | 1058 else if (c == 104) { |
1009 /* h - set modes */ | 1059 /* h - set modes */ |
1010 if (prefix != '?') { | 1060 if (prefix != '?') { |
1011 debug(1, "Unimplemented CSI sequence: " + comstr); | 1061 debug(1, "Unimplemented CSI sequence: " + comstr); |
1062 this.lastcode = 0; | |
1012 return; | 1063 return; |
1013 } | 1064 } |
1014 for (var i = 0; i < params.length; i++) { | 1065 for (var i = 0; i < params.length; i++) { |
1015 if (params[i] == 1) { | 1066 if (params[i] == 1) { |
1016 keyHexCodes.appCursor(true); | 1067 keyHexCodes.appCursor(true); |
1045 /* Insert mode is not implemented. */ | 1096 /* Insert mode is not implemented. */ |
1046 debug(0, "Replace mode"); | 1097 debug(0, "Replace mode"); |
1047 } | 1098 } |
1048 else { | 1099 else { |
1049 debug(1, "Unimplemented CSI sequence: " + comstr); | 1100 debug(1, "Unimplemented CSI sequence: " + comstr); |
1101 this.lastcode = 0; | |
1050 return; | 1102 return; |
1051 } | 1103 } |
1052 } | 1104 } |
1053 for (var i = 0; i < params.length; i++) { | 1105 for (var i = 0; i < params.length; i++) { |
1054 if (params[i] == 1) { | 1106 if (params[i] == 1) { |
1078 } | 1130 } |
1079 else if (c == 109) { | 1131 else if (c == 109) { |
1080 /* m - character attributes */ | 1132 /* m - character attributes */ |
1081 if (prefix !== null) { | 1133 if (prefix !== null) { |
1082 debug(1, "Unimplemented CSI sequence: " + comstr); | 1134 debug(1, "Unimplemented CSI sequence: " + comstr); |
1135 this.lastcode = 0; | |
1083 return; | 1136 return; |
1084 } | 1137 } |
1085 if (params.length == 0) | 1138 if (params.length == 0) |
1086 this.clearAttrs(); | 1139 this.clearAttrs(); |
1087 for (var i = 0; i < params.length; i++) { | 1140 for (var i = 0; i < params.length; i++) { |
1131 var b = this.h - 1; | 1184 var b = this.h - 1; |
1132 if (params[0] && params[0] <= this.h - 1) | 1185 if (params[0] && params[0] <= this.h - 1) |
1133 t = params[0] - 1; | 1186 t = params[0] - 1; |
1134 if (params[1] && params[1] <= this.h) | 1187 if (params[1] && params[1] <= this.h) |
1135 b = params[1] - 1; | 1188 b = params[1] - 1; |
1136 if (b <= t) | 1189 if (b > t) { |
1137 return; | 1190 this.scrT = t; |
1138 this.scrT = t; | 1191 this.scrB = b; |
1139 this.scrB = b; | 1192 this.cmove(0, 0); |
1140 this.cmove(0, 0); | 1193 } |
1141 } | 1194 } |
1142 else { | 1195 else { |
1143 debug(1, "Unimplemented CSI sequence: " + comstr); | 1196 debug(1, "Unimplemented CSI sequence: " + comstr); |
1197 } | |
1198 if (!printed) { | |
1199 this.lastcode = 0; | |
1144 } | 1200 } |
1145 return; | 1201 return; |
1146 }, | 1202 }, |
1147 oscProcess: function () { | 1203 oscProcess: function () { |
1148 var numstr = ""; | 1204 var numstr = ""; |