Commit adb4796796a073d782d0be3566f91e2489dc7065
1 parent
dabd98dd
Improved console handling, thanks Stefan Weil.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2322 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
155 additions
and
18 deletions
console.c
... | ... | @@ -121,6 +121,7 @@ struct TextConsole { |
121 | 121 | int total_height; |
122 | 122 | int backscroll_height; |
123 | 123 | int x, y; |
124 | + int x_saved, y_saved; | |
124 | 125 | int y_displayed; |
125 | 126 | int y_base; |
126 | 127 | TextAttributes t_attrib_default; /* default text attributes */ |
... | ... | @@ -147,7 +148,7 @@ static int nb_consoles = 0; |
147 | 148 | |
148 | 149 | void vga_hw_update(void) |
149 | 150 | { |
150 | - if (active_console->hw_update) | |
151 | + if (active_console && active_console->hw_update) | |
151 | 152 | active_console->hw_update(active_console->hw); |
152 | 153 | } |
153 | 154 | |
... | ... | @@ -659,10 +660,6 @@ static void console_handle_escape(TextConsole *s) |
659 | 660 | { |
660 | 661 | int i; |
661 | 662 | |
662 | - if (s->nb_esc_params == 0) { /* ESC[m sets all attributes to default */ | |
663 | - s->t_attrib = s->t_attrib_default; | |
664 | - return; | |
665 | - } | |
666 | 663 | for (i=0; i<s->nb_esc_params; i++) { |
667 | 664 | switch (s->esc_params[i]) { |
668 | 665 | case 0: /* reset all console attributes to default */ |
... | ... | @@ -752,10 +749,21 @@ static void console_handle_escape(TextConsole *s) |
752 | 749 | } |
753 | 750 | } |
754 | 751 | |
752 | +static void console_clear_xy(TextConsole *s, int x, int y) | |
753 | +{ | |
754 | + int y1 = (s->y_base + y) % s->total_height; | |
755 | + TextCell *c = &s->cells[y1 * s->width + x]; | |
756 | + c->ch = ' '; | |
757 | + c->t_attrib = s->t_attrib_default; | |
758 | + c++; | |
759 | + update_xy(s, x, y); | |
760 | +} | |
761 | + | |
755 | 762 | static void console_putchar(TextConsole *s, int ch) |
756 | 763 | { |
757 | 764 | TextCell *c; |
758 | - int y1, i, x; | |
765 | + int y1, i; | |
766 | + int x, y; | |
759 | 767 | |
760 | 768 | switch(s->state) { |
761 | 769 | case TTY_STATE_NORM: |
... | ... | @@ -781,20 +789,31 @@ static void console_putchar(TextConsole *s, int ch) |
781 | 789 | case '\a': /* alert aka. bell */ |
782 | 790 | /* TODO: has to be implemented */ |
783 | 791 | break; |
792 | + case 14: | |
793 | + /* SI (shift in), character set 0 (ignored) */ | |
794 | + break; | |
795 | + case 15: | |
796 | + /* SO (shift out), character set 1 (ignored) */ | |
797 | + break; | |
784 | 798 | case 27: /* esc (introducing an escape sequence) */ |
785 | 799 | s->state = TTY_STATE_ESC; |
786 | 800 | break; |
787 | 801 | default: |
802 | + if (s->x >= s->width - 1) { | |
803 | + break; | |
804 | + } | |
788 | 805 | y1 = (s->y_base + s->y) % s->total_height; |
789 | 806 | c = &s->cells[y1 * s->width + s->x]; |
790 | 807 | c->ch = ch; |
791 | 808 | c->t_attrib = s->t_attrib; |
792 | 809 | update_xy(s, s->x, s->y); |
793 | 810 | s->x++; |
811 | +#if 0 /* line wrap disabled */ | |
794 | 812 | if (s->x >= s->width) { |
795 | 813 | s->x = 0; |
796 | 814 | console_put_lf(s); |
797 | 815 | } |
816 | +#endif | |
798 | 817 | break; |
799 | 818 | } |
800 | 819 | break; |
... | ... | @@ -818,32 +837,150 @@ static void console_putchar(TextConsole *s, int ch) |
818 | 837 | s->nb_esc_params++; |
819 | 838 | if (ch == ';') |
820 | 839 | break; |
840 | +#ifdef DEBUG_CONSOLE | |
841 | + fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n", | |
842 | + s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params); | |
843 | +#endif | |
821 | 844 | s->state = TTY_STATE_NORM; |
822 | 845 | switch(ch) { |
823 | - case 'D': | |
824 | - if (s->x > 0) | |
825 | - s->x--; | |
846 | + case 'A': | |
847 | + /* move cursor up */ | |
848 | + if (s->esc_params[0] == 0) { | |
849 | + s->esc_params[0] = 1; | |
850 | + } | |
851 | + s->y -= s->esc_params[0]; | |
852 | + if (s->y < 0) { | |
853 | + s->y = 0; | |
854 | + } | |
855 | + break; | |
856 | + case 'B': | |
857 | + /* move cursor down */ | |
858 | + if (s->esc_params[0] == 0) { | |
859 | + s->esc_params[0] = 1; | |
860 | + } | |
861 | + s->y += s->esc_params[0]; | |
862 | + if (s->y >= s->height) { | |
863 | + s->y = s->height - 1; | |
864 | + } | |
826 | 865 | break; |
827 | 866 | case 'C': |
828 | - if (s->x < (s->width - 1)) | |
829 | - s->x++; | |
867 | + /* move cursor right */ | |
868 | + if (s->esc_params[0] == 0) { | |
869 | + s->esc_params[0] = 1; | |
870 | + } | |
871 | + s->x += s->esc_params[0]; | |
872 | + if (s->x >= s->width) { | |
873 | + s->x = s->width - 1; | |
874 | + } | |
830 | 875 | break; |
876 | + case 'D': | |
877 | + /* move cursor left */ | |
878 | + if (s->esc_params[0] == 0) { | |
879 | + s->esc_params[0] = 1; | |
880 | + } | |
881 | + s->x -= s->esc_params[0]; | |
882 | + if (s->x < 0) { | |
883 | + s->x = 0; | |
884 | + } | |
885 | + break; | |
886 | + case 'G': | |
887 | + /* move cursor to column */ | |
888 | + s->x = s->esc_params[0] - 1; | |
889 | + if (s->x < 0) { | |
890 | + s->x = 0; | |
891 | + } | |
892 | + break; | |
893 | + case 'f': | |
894 | + case 'H': | |
895 | + /* move cursor to row, column */ | |
896 | + s->x = s->esc_params[1] - 1; | |
897 | + if (s->x < 0) { | |
898 | + s->x = 0; | |
899 | + } | |
900 | + s->y = s->esc_params[0] - 1; | |
901 | + if (s->y < 0) { | |
902 | + s->y = 0; | |
903 | + } | |
904 | + break; | |
905 | + case 'J': | |
906 | + switch (s->esc_params[0]) { | |
907 | + case 0: | |
908 | + /* clear to end of screen */ | |
909 | + for (y = s->y; y < s->height; y++) { | |
910 | + for (x = 0; x < s->width; x++) { | |
911 | + if (y == s->y && x < s->x) { | |
912 | + continue; | |
913 | + } | |
914 | + console_clear_xy(s, x, y); | |
915 | + } | |
916 | + } | |
917 | + break; | |
918 | + case 1: | |
919 | + /* clear from beginning of screen */ | |
920 | + for (y = 0; y <= s->y; y++) { | |
921 | + for (x = 0; x < s->width; x++) { | |
922 | + if (y == s->y && x > s->x) { | |
923 | + break; | |
924 | + } | |
925 | + console_clear_xy(s, x, y); | |
926 | + } | |
927 | + } | |
928 | + break; | |
929 | + case 2: | |
930 | + /* clear entire screen */ | |
931 | + for (y = 0; y <= s->height; y++) { | |
932 | + for (x = 0; x < s->width; x++) { | |
933 | + console_clear_xy(s, x, y); | |
934 | + } | |
935 | + } | |
936 | + break; | |
937 | + } | |
831 | 938 | case 'K': |
939 | + switch (s->esc_params[0]) { | |
940 | + case 0: | |
832 | 941 | /* clear to eol */ |
833 | - y1 = (s->y_base + s->y) % s->total_height; | |
834 | 942 | for(x = s->x; x < s->width; x++) { |
835 | - c = &s->cells[y1 * s->width + x]; | |
836 | - c->ch = ' '; | |
837 | - c->t_attrib = s->t_attrib_default; | |
838 | - c++; | |
839 | - update_xy(s, x, s->y); | |
943 | + console_clear_xy(s, x, s->y); | |
840 | 944 | } |
841 | 945 | break; |
842 | - default: | |
946 | + case 1: | |
947 | + /* clear from beginning of line */ | |
948 | + for (x = 0; x <= s->x; x++) { | |
949 | + console_clear_xy(s, x, s->y); | |
950 | + } | |
951 | + break; | |
952 | + case 2: | |
953 | + /* clear entire line */ | |
954 | + for(x = 0; x < s->width; x++) { | |
955 | + console_clear_xy(s, x, s->y); | |
956 | + } | |
843 | 957 | break; |
844 | 958 | } |
959 | + break; | |
960 | + case 'm': | |
845 | 961 | console_handle_escape(s); |
846 | 962 | break; |
963 | + case 'n': | |
964 | + /* report cursor position */ | |
965 | + /* TODO: send ESC[row;colR */ | |
966 | + break; | |
967 | + case 's': | |
968 | + /* save cursor position */ | |
969 | + s->x_saved = s->x; | |
970 | + s->y_saved = s->y; | |
971 | + break; | |
972 | + case 'u': | |
973 | + /* restore cursor position */ | |
974 | + s->x = s->x_saved; | |
975 | + s->y = s->y_saved; | |
976 | + break; | |
977 | + default: | |
978 | +#ifdef DEBUG_CONSOLE | |
979 | + fprintf(stderr, "unhandled escape character '%c'\n", ch); | |
980 | +#endif | |
981 | + break; | |
982 | + } | |
983 | + break; | |
847 | 984 | } |
848 | 985 | } |
849 | 986 | } | ... | ... |