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