1 /*
2     SPDX-FileCopyrightText: 2007-2008 Robert Knight <robertknight@gmail.com>
3     SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
4 
5     SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #ifndef CHARACTER_H
9 #define CHARACTER_H
10 
11 // Konsole
12 #include "CharacterColor.h"
13 #include "CharacterWidth.h"
14 
15 // Qt
16 #include <QVector>
17 
18 namespace Konsole
19 {
20 typedef unsigned char LineProperty;
21 
22 typedef quint16 RenditionFlags;
23 
24 /* clang-format off */
25 const int LINE_DEFAULT              = 0;
26 const int LINE_WRAPPED              = (1 << 0);
27 const int LINE_DOUBLEWIDTH          = (1 << 1);
28 const int LINE_DOUBLEHEIGHT_TOP     = (1 << 2);
29 const int LINE_DOUBLEHEIGHT_BOTTOM  = (1 << 3);
30 
31 const RenditionFlags DEFAULT_RENDITION  = 0;
32 const RenditionFlags RE_BOLD            = (1 << 0);
33 const RenditionFlags RE_BLINK           = (1 << 1);
34 const RenditionFlags RE_UNDERLINE       = (1 << 2);
35 const RenditionFlags RE_REVERSE         = (1 << 3); // Screen only
36 const RenditionFlags RE_ITALIC          = (1 << 4);
37 const RenditionFlags RE_CURSOR          = (1 << 5);
38 const RenditionFlags RE_EXTENDED_CHAR   = (1 << 6);
39 const RenditionFlags RE_FAINT           = (1 << 7);
40 const RenditionFlags RE_STRIKEOUT       = (1 << 8);
41 const RenditionFlags RE_CONCEAL         = (1 << 9);
42 const RenditionFlags RE_OVERLINE        = (1 << 10);
43 const RenditionFlags RE_BLEND_SELECTION_COLORS = (1 << 11);
44 /* clang-format on */
45 
46 /**
47  * A single character in the terminal which consists of a unicode character
48  * value, foreground and background colors and a set of rendition attributes
49  * which specify how it should be drawn.
50  */
51 class Character
52 {
53 public:
54     /**
55      * Constructs a new character.
56      *
57      * @param _c The unicode character value of this character.
58      * @param _f The foreground color used to draw the character.
59      * @param _b The color used to draw the character's background.
60      * @param _r A set of rendition flags which specify how this character
61      *           is to be drawn.
62      * @param _real Indicate whether this character really exists, or exists
63      *              simply as place holder.
64      */
65     explicit inline Character(uint _c = ' ',
66                               CharacterColor _f = CharacterColor(COLOR_SPACE_DEFAULT, DEFAULT_FORE_COLOR),
67                               CharacterColor _b = CharacterColor(COLOR_SPACE_DEFAULT, DEFAULT_BACK_COLOR),
68                               RenditionFlags _r = DEFAULT_RENDITION,
69                               bool _real = true)
character(_c)70         : character(_c)
71         , rendition(_r)
72         , foregroundColor(_f)
73         , backgroundColor(_b)
74         , isRealCharacter(_real)
75     {
76     }
77 
78     /** The unicode character value for this character.
79      *
80      * if RE_EXTENDED_CHAR is set, character is a hash code which can be used to
81      * look up the unicode character sequence in the ExtendedCharTable used to
82      * create the sequence.
83      */
84     uint character;
85 
86     /** A combination of RENDITION flags which specify options for drawing the character. */
87     RenditionFlags rendition;
88 
89     /** The foreground color used to draw this character. */
90     CharacterColor foregroundColor;
91 
92     /** The color used to draw this character's background. */
93     CharacterColor backgroundColor;
94 
95     /** Indicate whether this character really exists, or exists simply as place holder.
96      *
97      *  TODO: this boolean filed can be further improved to become a enum filed, which
98      *  indicates different roles:
99      *
100      *    RealCharacter: a character which really exists
101      *    PlaceHolderCharacter: a character which exists as place holder
102      *    TabStopCharacter: a special place holder for HT("\t")
103      */
104     bool isRealCharacter;
105 
106     /**
107      * returns true if the format (color, rendition flag) of the compared characters is equal
108      */
109     bool equalsFormat(const Character &other) const;
110 
111     /**
112      * Compares two characters and returns true if they have the same unicode character value,
113      * rendition and colors.
114      */
115     friend bool operator==(const Character &a, const Character &b);
116 
117     /**
118      * Compares two characters and returns true if they have different unicode character values,
119      * renditions or colors.
120      */
121     friend bool operator!=(const Character &a, const Character &b);
122 
isSpace()123     inline bool isSpace() const
124     {
125         if (rendition & RE_EXTENDED_CHAR) {
126             return false;
127         } else {
128             return QChar(character).isSpace();
129         }
130     }
131 
width()132     inline int width() const
133     {
134         return width(character);
135     }
136 
width(uint ucs4)137     static int width(uint ucs4)
138     {
139         return characterWidth(ucs4);
140     }
141 
stringWidth(const uint * ucs4Str,int len)142     static int stringWidth(const uint *ucs4Str, int len)
143     {
144         int w = 0;
145         for (int i = 0; i < len; ++i) {
146             w += width(ucs4Str[i]);
147         }
148         return w;
149     }
150 
stringWidth(const QString & str)151     inline static int stringWidth(const QString &str)
152     {
153         QVector<uint> ucs4Str = str.toUcs4();
154         return stringWidth(ucs4Str.constData(), ucs4Str.length());
155     }
156 };
157 
158 inline bool operator==(const Character &a, const Character &b)
159 {
160     return a.character == b.character && a.equalsFormat(b);
161 }
162 
163 inline bool operator!=(const Character &a, const Character &b)
164 {
165     return !operator==(a, b);
166 }
167 
equalsFormat(const Character & other)168 inline bool Character::equalsFormat(const Character &other) const
169 {
170     return backgroundColor == other.backgroundColor && foregroundColor == other.foregroundColor && rendition == other.rendition;
171 }
172 }
173 Q_DECLARE_TYPEINFO(Konsole::Character, Q_MOVABLE_TYPE);
174 
175 #endif // CHARACTER_H
176