Changeset View
Changeset View
Standalone View
Standalone View
src/TerminalDisplay.cpp
1 | /* | 1 | /* | ||
---|---|---|---|---|---|
hindenburg: Accidentally deleted? | |||||
2 | This file is part of Konsole, a terminal emulator for KDE. | 2 | This file is part of Konsole, a terminal emulator for KDE. | ||
3 | 3 | | |||
4 | Copyright 2006-2008 by Robert Knight <robertknight@gmail.com> | 4 | Copyright 2006-2008 by Robert Knight <robertknight@gmail.com> | ||
5 | Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de> | 5 | Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de> | ||
6 | 6 | | |||
7 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | 8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | 9 | the Free Software Foundation; either version 2 of the License, or | ||
Show All 30 Lines | |||||
40 | #include <QPainter> | 40 | #include <QPainter> | ||
41 | #include <QPixmap> | 41 | #include <QPixmap> | ||
42 | #include <QScrollBar> | 42 | #include <QScrollBar> | ||
43 | #include <QStyle> | 43 | #include <QStyle> | ||
44 | #include <QTimer> | 44 | #include <QTimer> | ||
45 | #include <QDrag> | 45 | #include <QDrag> | ||
46 | #include <QDesktopServices> | 46 | #include <QDesktopServices> | ||
47 | #include <QAccessible> | 47 | #include <QAccessible> | ||
48 | #include <QtMath> | ||||
48 | 49 | | |||
49 | // KDE | 50 | // KDE | ||
50 | #include <KShell> | 51 | #include <KShell> | ||
51 | #include <KColorScheme> | 52 | #include <KColorScheme> | ||
52 | #include <KCursor> | 53 | #include <KCursor> | ||
53 | #include <KLocalizedString> | 54 | #include <KLocalizedString> | ||
54 | #include <KNotification> | 55 | #include <KNotification> | ||
55 | #include <KIO/DropJob> | 56 | #include <KIO/DropJob> | ||
56 | #include <KJobWidgets> | 57 | #include <KJobWidgets> | ||
57 | #include <KMessageBox> | 58 | #include <KMessageBox> | ||
58 | #include <KMessageWidget> | 59 | #include <KMessageWidget> | ||
59 | #include <KIO/StatJob> | 60 | #include <KIO/StatJob> | ||
60 | 61 | | |||
61 | // Konsole | 62 | // Konsole | ||
62 | #include "Filter.h" | 63 | #include "Filter.h" | ||
63 | #include "konsoledebug.h" | 64 | #include "konsoledebug.h" | ||
64 | #include "TerminalCharacterDecoder.h" | 65 | #include "TerminalCharacterDecoder.h" | ||
65 | #include "Screen.h" | 66 | #include "Screen.h" | ||
66 | #include "LineFont.h" | | |||
67 | #include "SessionController.h" | 67 | #include "SessionController.h" | ||
68 | #include "ExtendedCharTable.h" | 68 | #include "ExtendedCharTable.h" | ||
69 | #include "TerminalDisplayAccessible.h" | 69 | #include "TerminalDisplayAccessible.h" | ||
70 | #include "SessionManager.h" | 70 | #include "SessionManager.h" | ||
71 | #include "Session.h" | 71 | #include "Session.h" | ||
72 | #include "WindowSystemInfo.h" | 72 | #include "WindowSystemInfo.h" | ||
73 | #include "IncrementalSearchBar.h" | 73 | #include "IncrementalSearchBar.h" | ||
74 | #include "LineBlockCharacters.h" | ||||
74 | 75 | | |||
75 | using namespace Konsole; | 76 | using namespace Konsole; | ||
76 | 77 | | |||
77 | #define REPCHAR "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ | 78 | #define REPCHAR "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ | ||
78 | "abcdefgjijklmnopqrstuvwxyz" \ | 79 | "abcdefgjijklmnopqrstuvwxyz" \ | ||
79 | "0123456789./+@" | 80 | "0123456789./+@" | ||
80 | 81 | | |||
81 | // we use this to force QPainter to display text in LTR mode | 82 | // we use this to force QPainter to display text in LTR mode | ||
▲ Show 20 Lines • Show All 122 Lines • ▼ Show 20 Line(s) | |||||
204 | /* ------------------------------------------------------------------------- */ | 205 | /* ------------------------------------------------------------------------- */ | ||
205 | 206 | | |||
206 | static inline bool isLineCharString(const QString& string) | 207 | static inline bool isLineCharString(const QString& string) | ||
207 | { | 208 | { | ||
208 | if (string.length() == 0) { | 209 | if (string.length() == 0) { | ||
209 | return false; | 210 | return false; | ||
210 | } | 211 | } | ||
211 | 212 | | |||
212 | return isSupportedLineChar(string.at(0).unicode()); | 213 | return LineBlockCharacters::canDraw(string.at(0).unicode()); | ||
213 | } | 214 | } | ||
214 | 215 | | |||
215 | void TerminalDisplay::fontChange(const QFont&) | 216 | void TerminalDisplay::fontChange(const QFont&) | ||
216 | { | 217 | { | ||
217 | QFontMetrics fm(font()); | 218 | QFontMetrics fm(font()); | ||
218 | _fontHeight = fm.height() + _lineSpacing; | 219 | _fontHeight = fm.height() + _lineSpacing; | ||
219 | 220 | | |||
220 | Q_ASSERT(_fontHeight > 0); | 221 | Q_ASSERT(_fontHeight > 0); | ||
▲ Show 20 Lines • Show All 338 Lines • ▼ Show 20 Line(s) | |||||
559 | } | 560 | } | ||
560 | 561 | | |||
561 | /* ------------------------------------------------------------------------- */ | 562 | /* ------------------------------------------------------------------------- */ | ||
562 | /* */ | 563 | /* */ | ||
563 | /* Display Operations */ | 564 | /* Display Operations */ | ||
564 | /* */ | 565 | /* */ | ||
565 | /* ------------------------------------------------------------------------- */ | 566 | /* ------------------------------------------------------------------------- */ | ||
566 | 567 | | |||
567 | /** | | |||
568 | A table for emulating the simple (single width) unicode drawing chars. | | |||
569 | It represents the 250x - 257x glyphs. If it's zero, we can't use it. | | |||
570 | if it's not, it's encoded as follows: imagine a 5x5 grid where the points are numbered | | |||
571 | 0 to 24 left to top, top to bottom. Each point is represented by the corresponding bit. | | |||
572 | | ||||
573 | Then, the pixels basically have the following interpretation: | | |||
574 | _|||_ | | |||
575 | -...- | | |||
576 | -...- | | |||
577 | -...- | | |||
578 | _|||_ | | |||
579 | | ||||
580 | where _ = none | | |||
581 | | = vertical line. | | |||
582 | - = horizontal line. | | |||
583 | */ | | |||
584 | | ||||
585 | enum LineEncode { | | |||
586 | TopL = (1 << 1), | | |||
587 | TopC = (1 << 2), | | |||
588 | TopR = (1 << 3), | | |||
589 | | ||||
590 | LeftT = (1 << 5), | | |||
591 | Int11 = (1 << 6), | | |||
592 | Int12 = (1 << 7), | | |||
593 | Int13 = (1 << 8), | | |||
594 | RightT = (1 << 9), | | |||
595 | | ||||
596 | LeftC = (1 << 10), | | |||
597 | Int21 = (1 << 11), | | |||
598 | Int22 = (1 << 12), | | |||
599 | Int23 = (1 << 13), | | |||
600 | RightC = (1 << 14), | | |||
601 | | ||||
602 | LeftB = (1 << 15), | | |||
603 | Int31 = (1 << 16), | | |||
604 | Int32 = (1 << 17), | | |||
605 | Int33 = (1 << 18), | | |||
606 | RightB = (1 << 19), | | |||
607 | | ||||
608 | BotL = (1 << 21), | | |||
609 | BotC = (1 << 22), | | |||
610 | BotR = (1 << 23) | | |||
611 | }; | | |||
612 | | ||||
613 | static void drawLineChar(QPainter& paint, int x, int y, int w, int h, uchar code) | | |||
614 | { | | |||
615 | //Calculate cell midpoints, end points. | | |||
616 | const int cx = x + w / 2; | | |||
617 | const int cy = y + h / 2. - 0.5; | | |||
618 | const int ex = x + w - 1; | | |||
619 | const int ey = y + h - 1; | | |||
620 | | ||||
621 | const quint32 toDraw = LineChars[code]; | | |||
622 | | ||||
623 | //Top _lines: | | |||
624 | if ((toDraw & TopL) != 0u) { | | |||
625 | paint.drawLine(cx - 1, y, cx - 1, cy - 2); | | |||
626 | } | | |||
627 | if ((toDraw & TopC) != 0u) { | | |||
628 | paint.drawLine(cx, y, cx, cy - 2); | | |||
629 | } | | |||
630 | if ((toDraw & TopR) != 0u) { | | |||
631 | paint.drawLine(cx + 1, y, cx + 1, cy - 2); | | |||
632 | } | | |||
633 | | ||||
634 | //Bot _lines: | | |||
635 | if ((toDraw & BotL) != 0u) { | | |||
636 | paint.drawLine(cx - 1, cy + 2, cx - 1, ey); | | |||
637 | } | | |||
638 | if ((toDraw & BotC) != 0u) { | | |||
639 | paint.drawLine(cx, cy + 2, cx, ey); | | |||
640 | } | | |||
641 | if ((toDraw & BotR) != 0u) { | | |||
642 | paint.drawLine(cx + 1, cy + 2, cx + 1, ey); | | |||
643 | } | | |||
644 | | ||||
645 | //Left _lines: | | |||
646 | if ((toDraw & LeftT) != 0u) { | | |||
647 | paint.drawLine(x, cy - 1, cx - 2, cy - 1); | | |||
648 | } | | |||
649 | if ((toDraw & LeftC) != 0u) { | | |||
650 | paint.drawLine(x, cy, cx - 2, cy); | | |||
651 | } | | |||
652 | if ((toDraw & LeftB) != 0u) { | | |||
653 | paint.drawLine(x, cy + 1, cx - 2, cy + 1); | | |||
654 | } | | |||
655 | | ||||
656 | //Right _lines: | | |||
657 | if ((toDraw & RightT) != 0u) { | | |||
658 | paint.drawLine(cx + 2, cy - 1, ex, cy - 1); | | |||
659 | } | | |||
660 | if ((toDraw & RightC) != 0u) { | | |||
661 | paint.drawLine(cx + 2, cy, ex, cy); | | |||
662 | } | | |||
663 | if ((toDraw & RightB) != 0u) { | | |||
664 | paint.drawLine(cx + 2, cy + 1, ex, cy + 1); | | |||
665 | } | | |||
666 | | ||||
667 | //Intersection points. | | |||
668 | if ((toDraw & Int11) != 0u) { | | |||
669 | paint.drawPoint(cx - 2, cy - 2); | | |||
670 | } | | |||
671 | if ((toDraw & Int12) != 0u) { | | |||
672 | paint.drawPoint(cx - 1, cy - 2); | | |||
673 | } | | |||
674 | if ((toDraw & Int13) != 0u) { | | |||
675 | paint.drawPoint(cx - 0, cy - 2); | | |||
676 | } | | |||
677 | | ||||
678 | if ((toDraw & Int21) != 0u) { | | |||
679 | paint.drawPoint(cx - 2, cy - 1); | | |||
680 | } | | |||
681 | if ((toDraw & Int22) != 0u) { | | |||
682 | paint.drawPoint(cx - 1, cy - 1); | | |||
683 | } | | |||
684 | if ((toDraw & Int23) != 0u) { | | |||
685 | paint.drawPoint(cx - 0, cy - 1); | | |||
686 | } | | |||
687 | | ||||
688 | if ((toDraw & Int31) != 0u) { | | |||
689 | paint.drawPoint(cx - 2, cy); | | |||
690 | } | | |||
691 | if ((toDraw & Int32) != 0u) { | | |||
692 | paint.drawPoint(cx - 1, cy); | | |||
693 | } | | |||
694 | if ((toDraw & Int33) != 0u) { | | |||
695 | paint.drawPoint(cx - 0, cy); | | |||
696 | } | | |||
697 | } | | |||
698 | | ||||
699 | static void drawOtherChar(QPainter& paint, int x, int y, int w, int h, uchar code) | | |||
700 | { | | |||
701 | //Calculate cell midpoints, end points. | | |||
702 | const int cx = x + w / 2; | | |||
703 | const int cy = y + h / 2. - 0.5; // Compensate for the translation, to match fonts | | |||
704 | const int ex = x + w - 1; | | |||
705 | const int ey = y + h - 1; | | |||
706 | | ||||
707 | // Double dashes | | |||
708 | if (0x4C <= code && code <= 0x4F) { | | |||
709 | const int xHalfGap = qMax(w / 15, 1); | | |||
710 | const int yHalfGap = qMax(h / 15, 1); | | |||
711 | switch (code) { | | |||
712 | case 0x4D: // BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL | | |||
713 | paint.drawLine(x, cy - 1, cx - xHalfGap - 1, cy - 1); | | |||
714 | paint.drawLine(x, cy + 1, cx - xHalfGap - 1, cy + 1); | | |||
715 | paint.drawLine(cx + xHalfGap, cy - 1, ex, cy - 1); | | |||
716 | paint.drawLine(cx + xHalfGap, cy + 1, ex, cy + 1); | | |||
717 | // No break! | | |||
718 | Q_FALLTHROUGH(); | | |||
719 | case 0x4C: // BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL | | |||
720 | paint.drawLine(x, cy, cx - xHalfGap - 1, cy); | | |||
721 | paint.drawLine(cx + xHalfGap, cy, ex, cy); | | |||
722 | break; | | |||
723 | case 0x4F: // BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL | | |||
724 | paint.drawLine(cx - 1, y, cx - 1, cy - yHalfGap - 1); | | |||
725 | paint.drawLine(cx + 1, y, cx + 1, cy - yHalfGap - 1); | | |||
726 | paint.drawLine(cx - 1, cy + yHalfGap, cx - 1, ey); | | |||
727 | paint.drawLine(cx + 1, cy + yHalfGap, cx + 1, ey); | | |||
728 | // No break! | | |||
729 | Q_FALLTHROUGH(); | | |||
730 | case 0x4E: // BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL | | |||
731 | paint.drawLine(cx, y, cx, cy - yHalfGap - 1); | | |||
732 | paint.drawLine(cx, cy + yHalfGap, cx, ey); | | |||
733 | break; | | |||
734 | } | | |||
735 | } | | |||
736 | | ||||
737 | // Rounded corner characters | | |||
738 | else if (0x6D <= code && code <= 0x70) { | | |||
739 | const int r = w * 3 / 8; | | |||
740 | const int d = 2 * r; | | |||
741 | switch (code) { | | |||
742 | case 0x6D: // BOX DRAWINGS LIGHT ARC DOWN AND RIGHT | | |||
743 | paint.drawLine(cx, cy + r, cx, ey); | | |||
744 | paint.drawLine(cx + r, cy, ex, cy); | | |||
745 | paint.drawArc(cx, cy, d, d, 90 * 16, 90 * 16); | | |||
746 | break; | | |||
747 | case 0x6E: // BOX DRAWINGS LIGHT ARC DOWN AND LEFT | | |||
748 | paint.drawLine(cx, cy + r, cx, ey); | | |||
749 | paint.drawLine(x, cy, cx - r, cy); | | |||
750 | paint.drawArc(cx - d, cy, d, d, 0 * 16, 90 * 16); | | |||
751 | break; | | |||
752 | case 0x6F: // BOX DRAWINGS LIGHT ARC UP AND LEFT | | |||
753 | paint.drawLine(cx, y, cx, cy - r); | | |||
754 | paint.drawLine(x, cy, cx - r, cy); | | |||
755 | paint.drawArc(cx - d, cy - d, d, d, 270 * 16, 90 * 16); | | |||
756 | break; | | |||
757 | case 0x70: // BOX DRAWINGS LIGHT ARC UP AND RIGHT | | |||
758 | paint.drawLine(cx, y, cx, cy - r); | | |||
759 | paint.drawLine(cx + r, cy, ex, cy); | | |||
760 | paint.drawArc(cx, cy - d, d, d, 180 * 16, 90 * 16); | | |||
761 | break; | | |||
762 | } | | |||
763 | } | | |||
764 | | ||||
765 | // Diagonals | | |||
766 | else if (0x71 <= code && code <= 0x73) { | | |||
767 | switch (code) { | | |||
768 | case 0x71: // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT | | |||
769 | paint.drawLine(ex, y, x, ey); | | |||
770 | break; | | |||
771 | case 0x72: // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT | | |||
772 | paint.drawLine(x, y, ex, ey); | | |||
773 | break; | | |||
774 | case 0x73: // BOX DRAWINGS LIGHT DIAGONAL CROSS | | |||
775 | paint.drawLine(ex, y, x, ey); | | |||
776 | paint.drawLine(x, y, ex, ey); | | |||
777 | break; | | |||
778 | } | | |||
779 | } | | |||
780 | } | | |||
781 | | ||||
782 | static void drawBlockChar(QPainter& paint, int x, int y, int w, int h, uchar code) | | |||
783 | { | | |||
784 | const QColor color = paint.pen().color(); | | |||
785 | | ||||
786 | const float left = x - 0.5; | | |||
787 | const float top = y - 0.5; | | |||
788 | | ||||
789 | const float cx = left + w / 2; | | |||
790 | const float cy = top + h / 2; | | |||
791 | const float right = x + w - 0.5; | | |||
792 | const float bottom = y + h - 0.5; | | |||
793 | | ||||
794 | // Default rect fills entire cell | | |||
795 | QRectF rect(left, top, w, h); | | |||
796 | | ||||
797 | // LOWER ONE EIGHTH BLOCK to LEFT ONE EIGHTH BLOCK | | |||
798 | if (code >= 0x81 && code <= 0x8f) { | | |||
799 | if (code < 0x88) { // Horizontal | | |||
800 | const int height = h * (0x88 - code) / 8; | | |||
801 | rect.setY(top + height); | | |||
802 | rect.setHeight(h - height); | | |||
803 | } else if (code > 0x88) { // Vertical | | |||
804 | const int width = w * (0x90 - code) / 8; | | |||
805 | rect.setWidth(width); | | |||
806 | } | | |||
807 | | ||||
808 | paint.fillRect(rect, color); | | |||
809 | | ||||
810 | return; | | |||
811 | } | | |||
812 | | ||||
813 | // Combinations of quarter squares | | |||
814 | // LEFT ONE EIGHTH BLOCK to QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT | | |||
815 | if (code >= 0x96 && code <= 0x9F) { | | |||
816 | bool upperLeft = false, upperRight = false, | | |||
817 | lowerLeft = false, lowerRight = false; | | |||
818 | | ||||
819 | switch(code) { | | |||
820 | case 0x96: | | |||
821 | lowerLeft = true; | | |||
822 | break; | | |||
823 | case 0x97: | | |||
824 | lowerRight = true; | | |||
825 | break; | | |||
826 | case 0x98: | | |||
827 | upperLeft = true; | | |||
828 | break; | | |||
829 | case 0x99: | | |||
830 | upperLeft = true; | | |||
831 | lowerLeft = true; | | |||
832 | lowerRight = true; | | |||
833 | break; | | |||
834 | case 0x9a: | | |||
835 | upperLeft = true; | | |||
836 | lowerRight = true; | | |||
837 | break; | | |||
838 | case 0x9b: | | |||
839 | upperLeft = true; | | |||
840 | upperRight = true; | | |||
841 | lowerLeft = true; | | |||
842 | break; | | |||
843 | case 0x9c: | | |||
844 | upperLeft = true; | | |||
845 | upperRight = true; | | |||
846 | lowerRight = true; | | |||
847 | break; | | |||
848 | case 0x9d: | | |||
849 | upperRight = true; | | |||
850 | break; | | |||
851 | case 0x9e: | | |||
852 | upperRight = true; | | |||
853 | lowerLeft = true; | | |||
854 | break; | | |||
855 | case 0x9f: | | |||
856 | upperRight = true; | | |||
857 | lowerLeft = true; | | |||
858 | lowerRight = true; | | |||
859 | break; | | |||
860 | default: | | |||
861 | break; | | |||
862 | } | | |||
863 | | ||||
864 | if (upperLeft) { | | |||
865 | paint.fillRect(QRectF(QPointF(left, top), QPointF(cx, cy)), color); | | |||
866 | } | | |||
867 | if (upperRight) { | | |||
868 | paint.fillRect(QRectF(QPointF(cx, top), QPointF(right, cy)), color); | | |||
869 | } | | |||
870 | if (lowerLeft) { | | |||
871 | paint.fillRect(QRectF(QPointF(left, cy), QPointF(cx, bottom)), color); | | |||
872 | } | | |||
873 | if (lowerRight) { | | |||
874 | paint.fillRect(QRectF(QPointF(cx, cy), QPointF(right, bottom)), color); | | |||
875 | } | | |||
876 | | ||||
877 | return; | | |||
878 | } | | |||
879 | | ||||
880 | // And the random stuff | | |||
881 | switch(code) { | | |||
882 | case 0x80: // Top half block | | |||
883 | rect.setHeight(h / 2); | | |||
884 | paint.fillRect(rect, color); | | |||
885 | return; | | |||
886 | case 0x90: // Right half block | | |||
887 | paint.fillRect(QRectF(QPointF(cx, top), QPointF(right, bottom)), color); | | |||
888 | return; | | |||
889 | case 0x94: // Top one eighth block | | |||
890 | rect.setHeight(h / 8); | | |||
891 | paint.fillRect(rect, color); | | |||
892 | return; | | |||
893 | case 0x95: { // Right one eighth block | | |||
894 | const float width = 7 * w / 8; | | |||
895 | rect.setX(left + width); | | |||
896 | rect.setWidth(w - width); | | |||
897 | paint.fillRect(rect, color); | | |||
898 | return; | | |||
899 | } | | |||
900 | case 0x91: // Light shade | | |||
901 | paint.fillRect(rect, QBrush(color, Qt::Dense6Pattern)); | | |||
902 | return; | | |||
903 | case 0x92: // Medium shade | | |||
904 | paint.fillRect(rect, QBrush(color, Qt::Dense4Pattern)); | | |||
905 | return; | | |||
906 | case 0x93: // Dark shade | | |||
907 | paint.fillRect(rect, QBrush(color, Qt::Dense2Pattern)); | | |||
908 | return; | | |||
909 | | ||||
910 | default: | | |||
911 | break; | | |||
912 | } | | |||
913 | } | | |||
914 | | ||||
915 | void TerminalDisplay::drawLineCharString(QPainter& painter, int x, int y, const QString& str, | 568 | void TerminalDisplay::drawLineCharString(QPainter& painter, int x, int y, const QString& str, | ||
916 | const Character* attributes) | 569 | const Character* attributes) | ||
917 | { | 570 | { | ||
918 | painter.save(); | 571 | const bool useBoldPen = (attributes->rendition & RE_BOLD) != 0 && _boldIntense; | ||
919 | | ||||
920 | // For antialiasing, we need to shift it so the single pixel width is in the middle | | |||
921 | painter.translate(0.5, 0.5); | | |||
922 | | ||||
923 | if (((attributes->rendition & RE_BOLD) != 0) && _boldIntense) { | | |||
924 | QPen boldPen(painter.pen()); | | |||
925 | boldPen.setWidth(4); | | |||
926 | painter.setPen(boldPen); | | |||
927 | } | | |||
928 | | ||||
929 | 572 | | |||
573 | QRect cellRect = {x, y, _fontWidth, _fontHeight}; | ||||
930 | for (int i = 0 ; i < str.length(); i++) { | 574 | for (int i = 0 ; i < str.length(); i++) { | ||
931 | const uchar code = str[i].cell(); | 575 | LineBlockCharacters::draw(painter, cellRect.translated(i * _fontWidth, 0), str[i], | ||
932 | 576 | useBoldPen); | |||
933 | if (code >= 0x80 && code <= 0x9F) { // UPPER HALF BLOCK to QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT | | |||
934 | drawBlockChar(painter, x + (_fontWidth * i), y, _fontWidth, _fontHeight, code); | | |||
935 | } else if (LineChars[code] != 0u) { | | |||
936 | drawLineChar(painter, x + (_fontWidth * i), y, _fontWidth, _fontHeight, code); | | |||
937 | } else { | | |||
938 | drawOtherChar(painter, x + (_fontWidth * i), y, _fontWidth, _fontHeight, code); | | |||
939 | } | 577 | } | ||
940 | } | 578 | } | ||
941 | 579 | | |||
942 | painter.restore(); | | |||
943 | } | | |||
944 | | ||||
945 | void TerminalDisplay::setKeyboardCursorShape(Enum::CursorShapeEnum shape) | 580 | void TerminalDisplay::setKeyboardCursorShape(Enum::CursorShapeEnum shape) | ||
946 | { | 581 | { | ||
947 | _cursorShape = shape; | 582 | _cursorShape = shape; | ||
948 | } | 583 | } | ||
949 | Enum::CursorShapeEnum TerminalDisplay::keyboardCursorShape() const | 584 | Enum::CursorShapeEnum TerminalDisplay::keyboardCursorShape() const | ||
950 | { | 585 | { | ||
951 | return _cursorShape; | 586 | return _cursorShape; | ||
952 | } | 587 | } | ||
▲ Show 20 Lines • Show All 186 Lines • ▼ Show 20 Line(s) | 741 | { | |||
1139 | const CharacterColor& textColor = (invertCharacterColor ? style->backgroundColor : style->foregroundColor); | 774 | const CharacterColor& textColor = (invertCharacterColor ? style->backgroundColor : style->foregroundColor); | ||
1140 | const QColor color = textColor.color(_colorTable); | 775 | const QColor color = textColor.color(_colorTable); | ||
1141 | QPen pen = painter.pen(); | 776 | QPen pen = painter.pen(); | ||
1142 | if (pen.color() != color) { | 777 | if (pen.color() != color) { | ||
1143 | pen.setColor(color); | 778 | pen.setColor(color); | ||
1144 | painter.setPen(color); | 779 | painter.setPen(color); | ||
1145 | } | 780 | } | ||
1146 | 781 | | |||
782 | const bool origClipping = painter.hasClipping(); | ||||
783 | const auto origClipRegion = painter.clipRegion(); | ||||
no idea what these types are, isn't the first one just a bool? auto feels unnecessary (and I'm allergic to auto). sandsmark: no idea what these types are, isn't the first one just a bool? auto feels unnecessary (and I'm… | |||||
The thing to do here is to store some values using getters, and restore them later using respective setters. const auto is nice in such cases - types are not important, as the variables should not be touched. However, there were no const, so this was not so obvious. mglb: The thing to do here is to store some values using getters, and restore them later using… | |||||
784 | painter.setClipRect(rect); | ||||
1147 | // draw text | 785 | // draw text | ||
1148 | if (isLineCharString(text) && !_useFontLineCharacters) { | 786 | if (isLineCharString(text) && !_useFontLineCharacters) { | ||
1149 | drawLineCharString(painter, rect.x(), rect.y(), text, style); | 787 | drawLineCharString(painter, rect.x(), rect.y(), text, style); | ||
1150 | } else { | 788 | } else { | ||
1151 | // Force using LTR as the document layout for the terminal area, because | 789 | // Force using LTR as the document layout for the terminal area, because | ||
1152 | // there is no use cases for RTL emulator and RTL terminal application. | 790 | // there is no use cases for RTL emulator and RTL terminal application. | ||
1153 | // | 791 | // | ||
1154 | // This still allows RTL characters to be rendered in the RTL way. | 792 | // This still allows RTL characters to be rendered in the RTL way. | ||
1155 | painter.setLayoutDirection(Qt::LeftToRight); | 793 | painter.setLayoutDirection(Qt::LeftToRight); | ||
1156 | 794 | | |||
1157 | painter.setClipRect(rect); | | |||
1158 | if (_bidiEnabled) { | 795 | if (_bidiEnabled) { | ||
1159 | painter.drawText(rect.x(), rect.y() + _fontAscent + _lineSpacing, text); | 796 | painter.drawText(rect.x(), rect.y() + _fontAscent + _lineSpacing, text); | ||
1160 | } else { | 797 | } else { | ||
1161 | painter.drawText(rect.x(), rect.y() + _fontAscent + _lineSpacing, LTR_OVERRIDE_CHAR + text); | 798 | painter.drawText(rect.x(), rect.y() + _fontAscent + _lineSpacing, LTR_OVERRIDE_CHAR + text); | ||
1162 | } | 799 | } | ||
1163 | painter.setClipping(false); | | |||
1164 | } | 800 | } | ||
801 | painter.setClipRegion(origClipRegion); | ||||
802 | painter.setClipping(origClipping); | ||||
1165 | } | 803 | } | ||
1166 | 804 | | |||
1167 | void TerminalDisplay::drawTextFragment(QPainter& painter , | 805 | void TerminalDisplay::drawTextFragment(QPainter& painter , | ||
1168 | const QRect& rect, | 806 | const QRect& rect, | ||
1169 | const QString& text, | 807 | const QString& text, | ||
1170 | const Character* style) | 808 | const Character* style) | ||
1171 | { | 809 | { | ||
1172 | // setup painter | 810 | // setup painter | ||
▲ Show 20 Lines • Show All 284 Lines • ▼ Show 20 Line(s) | 1093 | for (x = 0; x < columnsToUpdate; ++x) { | |||
1457 | 1095 | | |||
1458 | // Start drawing if this character or the next one differs. | 1096 | // Start drawing if this character or the next one differs. | ||
1459 | // We also take the next one into account to handle the situation | 1097 | // We also take the next one into account to handle the situation | ||
1460 | // where characters exceed their cell width. | 1098 | // where characters exceed their cell width. | ||
1461 | if (dirtyMask[x] != 0) { | 1099 | if (dirtyMask[x] != 0) { | ||
1462 | if (newLine[x + 0].character == 0u) { | 1100 | if (newLine[x + 0].character == 0u) { | ||
1463 | continue; | 1101 | continue; | ||
1464 | } | 1102 | } | ||
1465 | const bool lineDraw = newLine[x + 0].isLineChar(); | 1103 | const bool lineDraw = LineBlockCharacters::canDraw(newLine[x + 0].character); | ||
1466 | const bool doubleWidth = (x + 1 == columnsToUpdate) ? false : (newLine[x + 1].character == 0); | 1104 | const bool doubleWidth = (x + 1 == columnsToUpdate) ? false : (newLine[x + 1].character == 0); | ||
1467 | const RenditionFlags cr = newLine[x].rendition; | 1105 | const RenditionFlags cr = newLine[x].rendition; | ||
1468 | const CharacterColor clipboard = newLine[x].backgroundColor; | 1106 | const CharacterColor clipboard = newLine[x].backgroundColor; | ||
1469 | if (newLine[x].foregroundColor != cf) { | 1107 | if (newLine[x].foregroundColor != cf) { | ||
1470 | cf = newLine[x].foregroundColor; | 1108 | cf = newLine[x].foregroundColor; | ||
1471 | } | 1109 | } | ||
1472 | const int lln = columnsToUpdate - x; | 1110 | const int lln = columnsToUpdate - x; | ||
1473 | for (len = 1; len < lln; ++len) { | 1111 | for (len = 1; len < lln; ++len) { | ||
1474 | const Character& ch = newLine[x + len]; | 1112 | const Character& ch = newLine[x + len]; | ||
1475 | 1113 | | |||
1476 | if (ch.character == 0u) { | 1114 | if (ch.character == 0u) { | ||
1477 | continue; // Skip trailing part of multi-col chars. | 1115 | continue; // Skip trailing part of multi-col chars. | ||
1478 | } | 1116 | } | ||
1479 | 1117 | | |||
1480 | const bool nextIsDoubleWidth = (x + len + 1 == columnsToUpdate) ? false : (newLine[x + len + 1].character == 0); | 1118 | const bool nextIsDoubleWidth = (x + len + 1 == columnsToUpdate) ? false : (newLine[x + len + 1].character == 0); | ||
1481 | 1119 | | |||
1482 | if (ch.foregroundColor != cf || | 1120 | if (ch.foregroundColor != cf || | ||
1483 | ch.backgroundColor != clipboard || | 1121 | ch.backgroundColor != clipboard || | ||
1484 | (ch.rendition & ~RE_EXTENDED_CHAR) != (cr & ~RE_EXTENDED_CHAR) || | 1122 | (ch.rendition & ~RE_EXTENDED_CHAR) != (cr & ~RE_EXTENDED_CHAR) || | ||
1485 | (dirtyMask[x + len] == 0) || | 1123 | (dirtyMask[x + len] == 0) || | ||
1486 | ch.isLineChar() != lineDraw || | 1124 | LineBlockCharacters::canDraw(ch.character) != lineDraw || | ||
1487 | nextIsDoubleWidth != doubleWidth) { | 1125 | nextIsDoubleWidth != doubleWidth) { | ||
1488 | break; | 1126 | break; | ||
1489 | } | 1127 | } | ||
1490 | } | 1128 | } | ||
1491 | 1129 | | |||
1492 | const bool saveFixedFont = _fixedFont; | 1130 | const bool saveFixedFont = _fixedFont; | ||
1493 | if (lineDraw) { | 1131 | if (lineDraw) { | ||
1494 | _fixedFont = false; | 1132 | _fixedFont = false; | ||
▲ Show 20 Lines • Show All 386 Lines • ▼ Show 20 Line(s) | 1518 | } else { | |||
1881 | // single character | 1519 | // single character | ||
1882 | const uint c = _image[loc(x, y)].character; | 1520 | const uint c = _image[loc(x, y)].character; | ||
1883 | if (c != 0u) { | 1521 | if (c != 0u) { | ||
1884 | Q_ASSERT(p < bufferSize); | 1522 | Q_ASSERT(p < bufferSize); | ||
1885 | disstrU[p++] = c; | 1523 | disstrU[p++] = c; | ||
1886 | } | 1524 | } | ||
1887 | } | 1525 | } | ||
1888 | 1526 | | |||
1889 | const bool lineDraw = _image[loc(x, y)].isLineChar(); | 1527 | const bool lineDraw = LineBlockCharacters::canDraw(_image[loc(x, y)].character); | ||
1890 | const bool doubleWidth = (_image[qMin(loc(x, y) + 1, _imageSize - 1)].character == 0); | 1528 | const bool doubleWidth = (_image[qMin(loc(x, y) + 1, _imageSize - 1)].character == 0); | ||
1891 | const CharacterColor currentForeground = _image[loc(x, y)].foregroundColor; | 1529 | const CharacterColor currentForeground = _image[loc(x, y)].foregroundColor; | ||
1892 | const CharacterColor currentBackground = _image[loc(x, y)].backgroundColor; | 1530 | const CharacterColor currentBackground = _image[loc(x, y)].backgroundColor; | ||
1893 | const RenditionFlags currentRendition = _image[loc(x, y)].rendition; | 1531 | const RenditionFlags currentRendition = _image[loc(x, y)].rendition; | ||
1894 | const bool rtl = isRtl(_image[loc(x, y)]); | 1532 | const bool rtl = isRtl(_image[loc(x, y)]); | ||
1895 | 1533 | | |||
1896 | if(_image[loc(x, y)].character <= 0x7e || rtl) { | 1534 | if(_image[loc(x, y)].character <= 0x7e || rtl) { | ||
1897 | while (x + len <= rect.right() && | 1535 | while (x + len <= rect.right() && | ||
1898 | _image[loc(x + len, y)].foregroundColor == currentForeground && | 1536 | _image[loc(x + len, y)].foregroundColor == currentForeground && | ||
1899 | _image[loc(x + len, y)].backgroundColor == currentBackground && | 1537 | _image[loc(x + len, y)].backgroundColor == currentBackground && | ||
1900 | (_image[loc(x + len, y)].rendition & ~RE_EXTENDED_CHAR) == (currentRendition & ~RE_EXTENDED_CHAR) && | 1538 | (_image[loc(x + len, y)].rendition & ~RE_EXTENDED_CHAR) == (currentRendition & ~RE_EXTENDED_CHAR) && | ||
1901 | (_image[qMin(loc(x + len, y) + 1, _imageSize - 1)].character == 0) == doubleWidth && | 1539 | (_image[qMin(loc(x + len, y) + 1, _imageSize - 1)].character == 0) == doubleWidth && | ||
1902 | _image[loc(x + len, y)].isLineChar() == lineDraw && | 1540 | LineBlockCharacters::canDraw(_image[loc(x + len, y)].character) == lineDraw && | ||
1903 | (_image[loc(x + len, y)].character <= 0x7e || rtl)) { | 1541 | (_image[loc(x + len, y)].character <= 0x7e || rtl)) { | ||
1904 | const uint c = _image[loc(x + len, y)].character; | 1542 | const uint c = _image[loc(x + len, y)].character; | ||
1905 | if ((_image[loc(x + len, y)].rendition & RE_EXTENDED_CHAR) != 0) { | 1543 | if ((_image[loc(x + len, y)].rendition & RE_EXTENDED_CHAR) != 0) { | ||
1906 | // sequence of characters | 1544 | // sequence of characters | ||
1907 | ushort extendedCharLength = 0; | 1545 | ushort extendedCharLength = 0; | ||
1908 | const uint* chars = ExtendedCharTable::instance.lookupExtendedChar(c, extendedCharLength); | 1546 | const uint* chars = ExtendedCharTable::instance.lookupExtendedChar(c, extendedCharLength); | ||
1909 | if (chars != nullptr) { | 1547 | if (chars != nullptr) { | ||
1910 | Q_ASSERT(extendedCharLength > 1); | 1548 | Q_ASSERT(extendedCharLength > 1); | ||
▲ Show 20 Lines • Show All 2285 Lines • Show Last 20 Lines |
Accidentally deleted?