File indexing completed on 2024-05-19 05:28:14

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