File indexing completed on 2025-03-16 08:11:24
0001 /* 0002 This file is part of Konsole, KDE's terminal. 0003 0004 SPDX-FileCopyrightText: 2007-2008 Robert Knight <robertknight@gmail.com> 0005 SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 GNU General Public License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program; if not, write to the Free Software 0016 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0017 02110-1301 USA. 0018 */ 0019 0020 #ifndef CHARACTER_H 0021 #define CHARACTER_H 0022 0023 // Qt 0024 #include <QHash> 0025 #include <span> 0026 0027 // Local 0028 #include "CharacterColor.h" 0029 0030 // std 0031 #include <unordered_map> 0032 0033 namespace Konsole 0034 { 0035 0036 typedef unsigned char LineProperty; 0037 0038 constexpr auto LINE_DEFAULT = 0; 0039 constexpr auto LINE_WRAPPED = (1 << 0); 0040 constexpr auto LINE_DOUBLEWIDTH = (1 << 1); 0041 constexpr auto LINE_DOUBLEHEIGHT = (1 << 2); 0042 0043 constexpr auto DEFAULT_RENDITION = 0; 0044 constexpr auto RE_BOLD = (1 << 0); 0045 constexpr auto RE_BLINK = (1 << 1); 0046 constexpr auto RE_UNDERLINE = (1 << 2); 0047 constexpr auto RE_REVERSE = (1 << 3); // Screen only 0048 constexpr auto RE_INTENSIVE = (1 << 3); // Widget only 0049 constexpr auto RE_ITALIC = (1 << 4); 0050 constexpr auto RE_CURSOR = (1 << 5); 0051 constexpr auto RE_EXTENDED_CHAR = (1 << 6); 0052 constexpr auto RE_FAINT = (1 << 7); 0053 constexpr auto RE_STRIKEOUT = (1 << 8); 0054 constexpr auto RE_CONCEAL = (1 << 9); 0055 constexpr auto RE_OVERLINE = (1 << 10); 0056 0057 /** 0058 * A single character in the terminal which consists of a unicode character 0059 * value, foreground and background colors and a set of rendition attributes 0060 * which specify how it should be drawn. 0061 */ 0062 class Character 0063 { 0064 public: 0065 /** 0066 * Constructs a new character. 0067 * 0068 * @param _c The unicode character value of this character. 0069 * @param _f The foreground color used to draw the character. 0070 * @param _b The color used to draw the character's background. 0071 * @param _r A set of rendition flags which specify how this character is to be drawn. 0072 */ 0073 constexpr inline Character(quint16 _c = ' ', 0074 CharacterColor _f = CharacterColor(COLOR_SPACE_DEFAULT, DEFAULT_FORE_COLOR), 0075 CharacterColor _b = CharacterColor(COLOR_SPACE_DEFAULT, DEFAULT_BACK_COLOR), 0076 quint8 _r = DEFAULT_RENDITION) 0077 : character(_c) 0078 , rendition(_r) 0079 , foregroundColor(_f) 0080 , backgroundColor(_b) 0081 { 0082 } 0083 0084 union { 0085 /** The unicode character value for this character. */ 0086 QChar character; 0087 /** 0088 * Experimental addition which allows a single Character instance to contain more than 0089 * one unicode character. 0090 * 0091 * charSequence is a hash code which can be used to look up the unicode 0092 * character sequence in the ExtendedCharTable used to create the sequence. 0093 */ 0094 quint16 charSequence; 0095 }; 0096 0097 /** A combination of RENDITION flags which specify options for drawing the character. */ 0098 quint8 rendition; 0099 0100 /** The foreground color used to draw this character. */ 0101 CharacterColor foregroundColor; 0102 /** The color used to draw this character's background. */ 0103 CharacterColor backgroundColor; 0104 0105 /** 0106 * Returns true if this character has a transparent background when 0107 * it is drawn with the specified @p palette. 0108 */ 0109 bool isTransparent(const ColorEntry *palette) const; 0110 /** 0111 * Returns true if this character should always be drawn in bold when 0112 * it is drawn with the specified @p palette, independent of whether 0113 * or not the character has the RE_BOLD rendition flag. 0114 */ 0115 ColorEntry::FontWeight fontWeight(const ColorEntry *base) const; 0116 0117 /** 0118 * returns true if the format (color, rendition flag) of the compared characters is equal 0119 */ 0120 bool equalsFormat(const Character &other) const; 0121 0122 /** 0123 * Compares two characters and returns true if they have the same unicode character value, 0124 * rendition and colors. 0125 */ 0126 friend bool operator==(const Character &a, const Character &b); 0127 /** 0128 * Compares two characters and returns true if they have different unicode character values, 0129 * renditions or colors. 0130 */ 0131 friend bool operator!=(const Character &a, const Character &b); 0132 }; 0133 0134 inline bool operator==(const Character &a, const Character &b) 0135 { 0136 return a.character == b.character && a.rendition == b.rendition && a.foregroundColor == b.foregroundColor && a.backgroundColor == b.backgroundColor; 0137 } 0138 0139 inline bool operator!=(const Character &a, const Character &b) 0140 { 0141 return a.character != b.character || a.rendition != b.rendition || a.foregroundColor != b.foregroundColor || a.backgroundColor != b.backgroundColor; 0142 } 0143 0144 inline bool Character::isTransparent(const ColorEntry *base) const 0145 { 0146 return ((backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) && base[backgroundColor._u + 0 + (backgroundColor._v ? BASE_COLORS : 0)].transparent) 0147 || ((backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) && base[backgroundColor._u + 2 + (backgroundColor._v ? BASE_COLORS : 0)].transparent); 0148 } 0149 0150 inline bool Character::equalsFormat(const Character &other) const 0151 { 0152 return backgroundColor == other.backgroundColor && foregroundColor == other.foregroundColor && rendition == other.rendition; 0153 } 0154 0155 inline ColorEntry::FontWeight Character::fontWeight(const ColorEntry *base) const 0156 { 0157 if (backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) 0158 return base[backgroundColor._u + 0 + (backgroundColor._v ? BASE_COLORS : 0)].fontWeight; 0159 else if (backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) 0160 return base[backgroundColor._u + 2 + (backgroundColor._v ? BASE_COLORS : 0)].fontWeight; 0161 else 0162 return ColorEntry::UseCurrentFormat; 0163 } 0164 0165 /** 0166 * A table which stores sequences of unicode characters, referenced 0167 * by hash keys. The hash key itself is the same size as a unicode 0168 * character ( ushort ) so that it can occupy the same space in 0169 * a structure. 0170 */ 0171 class ExtendedCharTable 0172 { 0173 public: 0174 /** Constructs a new character table. */ 0175 ExtendedCharTable(); 0176 ~ExtendedCharTable(); 0177 0178 /** 0179 * Adds a sequences of unicode characters to the table and returns 0180 * a hash code which can be used later to look up the sequence 0181 * using lookupExtendedChar() 0182 * 0183 * If the same sequence already exists in the table, the hash 0184 * of the existing sequence will be returned. 0185 * 0186 * @param unicodePoints An array of unicode character points 0187 * @param length Length of @p unicodePoints 0188 */ 0189 ushort createExtendedChar(ushort *unicodePoints, ushort length); 0190 /** 0191 * Looks up and returns a pointer to a sequence of unicode characters 0192 * which was added to the table using createExtendedChar(). 0193 * 0194 * @param hash The hash key returned by createExtendedChar() 0195 * @param length This variable is set to the length of the 0196 * character sequence. 0197 * 0198 * @return A unicode character sequence of size @p length. 0199 */ 0200 std::span<const ushort> lookupExtendedChar(ushort hash, ushort &length) const; 0201 0202 /** The global ExtendedCharTable instance. */ 0203 static ExtendedCharTable instance; 0204 0205 private: 0206 // calculates the hash key of a sequence of unicode points of size 'length' 0207 ushort extendedCharHash(ushort *unicodePoints, ushort length) const; 0208 // tests whether the entry in the table specified by 'hash' matches the 0209 // character sequence 'unicodePoints' of size 'length' 0210 bool extendedCharMatch(ushort hash, ushort *unicodePoints, ushort length) const; 0211 // internal, maps hash keys to character sequence buffers. The first ushort 0212 // in each value is the length of the buffer, followed by the ushorts in the buffer 0213 // themselves. 0214 std::unordered_map<ushort, std::vector<ushort>> extendedCharTable; 0215 }; 0216 0217 } 0218 Q_DECLARE_TYPEINFO(Konsole::Character, Q_MOVABLE_TYPE); 0219 0220 #endif // CHARACTER_H