1 | /* |
2 | SPDX-FileCopyrightText: 2002-2005 Hamish Rodda <rodda@kde.org> |
3 | SPDX-FileCopyrightText: 2003 Anakim Border <aborder@sources.sourceforge.net> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #include "katetextlayout.h" |
9 | |
10 | #include "katepartdebug.h" |
11 | |
12 | KateTextLayout::KateTextLayout(KateLineLayout *line, int viewLine) |
13 | : m_lineLayout(line) |
14 | , m_viewLine(viewLine) |
15 | , m_startX(m_viewLine ? -1 : 0) |
16 | { |
17 | if (isValid()) { |
18 | m_textLayout = m_lineLayout->layout()->lineAt(i: m_viewLine); |
19 | } |
20 | } |
21 | |
22 | bool KateTextLayout::isDirty() const |
23 | { |
24 | if (!isValid()) { |
25 | return m_invalidDirty; |
26 | } |
27 | |
28 | return m_lineLayout->isDirty(viewLine: viewLine()); |
29 | } |
30 | |
31 | bool KateTextLayout::setDirty(bool dirty) |
32 | { |
33 | if (!isValid()) { |
34 | return (m_invalidDirty = dirty); |
35 | } |
36 | |
37 | return m_lineLayout->setDirty(viewLine: viewLine(), dirty); |
38 | } |
39 | |
40 | bool KateTextLayout::includesCursor(const KTextEditor::Cursor realCursor) const |
41 | { |
42 | return realCursor.line() == line() && realCursor.column() >= startCol() && (!wrap() || realCursor.column() < endCol()); |
43 | } |
44 | |
45 | int KateTextLayout::xOffset() const |
46 | { |
47 | if (!isValid()) { |
48 | return 0; |
49 | } |
50 | |
51 | return startX() ? m_lineLayout->shiftX : 0; |
52 | } |
53 | |
54 | void KateTextLayout::debugOutput() const |
55 | { |
56 | qCDebug(LOG_KTE) << "KateTextLayout: " << m_lineLayout << " valid " << isValid() << " line " << m_lineLayout->line() << " (" << line() << ") cols [" |
57 | << startCol() << " -> " << endCol() << "] x [" << startX() << " -> " << endX() << " off " << m_lineLayout->shiftX << "] wrap " << wrap(); |
58 | } |
59 | |
60 | bool operator>(const KateTextLayout &r, const KTextEditor::Cursor c) |
61 | { |
62 | return r.line() > c.line() || r.endCol() > c.column(); |
63 | } |
64 | |
65 | bool operator>=(const KateTextLayout &r, const KTextEditor::Cursor c) |
66 | { |
67 | return r.line() > c.line() || r.endCol() >= c.column(); |
68 | } |
69 | |
70 | bool operator<(const KateTextLayout &r, const KTextEditor::Cursor c) |
71 | { |
72 | return r.line() < c.line() || r.startCol() < c.column(); |
73 | } |
74 | |
75 | bool operator<=(const KateTextLayout &r, const KTextEditor::Cursor c) |
76 | { |
77 | return r.line() < c.line() || r.startCol() <= c.column(); |
78 | } |
79 | |
80 | bool KateTextLayout::isValid() const |
81 | { |
82 | return m_lineLayout && m_lineLayout->isValid() && m_viewLine >= 0 && m_viewLine < m_lineLayout->viewLineCount(); |
83 | } |
84 | |
85 | int KateTextLayout::line() const |
86 | { |
87 | if (!isValid()) { |
88 | return -1; |
89 | } |
90 | |
91 | return m_lineLayout->line(); |
92 | } |
93 | |
94 | int KateTextLayout::virtualLine() const |
95 | { |
96 | if (!isValid()) { |
97 | return -1; |
98 | } |
99 | |
100 | return m_lineLayout->virtualLine(); |
101 | } |
102 | |
103 | int KateTextLayout::viewLine() const |
104 | { |
105 | if (!isValid()) { |
106 | return 0; |
107 | } |
108 | |
109 | return m_viewLine; |
110 | } |
111 | |
112 | const QTextLine &KateTextLayout::lineLayout() const |
113 | { |
114 | return m_textLayout; |
115 | } |
116 | |
117 | KateLineLayout *KateTextLayout::kateLineLayout() const |
118 | { |
119 | return m_lineLayout; |
120 | } |
121 | |
122 | int KateTextLayout::startCol() const |
123 | { |
124 | if (!isValid()) { |
125 | return 0; |
126 | } |
127 | |
128 | return lineLayout().textStart(); |
129 | } |
130 | |
131 | KTextEditor::Cursor KateTextLayout::start() const |
132 | { |
133 | return KTextEditor::Cursor(line(), startCol()); |
134 | } |
135 | |
136 | int KateTextLayout::endCol(bool indicateEOL) const |
137 | { |
138 | if (!isValid()) { |
139 | return 0; |
140 | } |
141 | |
142 | if (indicateEOL) { |
143 | if (viewLine() == kateLineLayout()->viewLineCount() - 1) { |
144 | return -1; |
145 | } |
146 | } |
147 | |
148 | return startCol() + m_textLayout.textLength(); |
149 | } |
150 | |
151 | KTextEditor::Cursor KateTextLayout::end(bool indicateEOL) const |
152 | { |
153 | return KTextEditor::Cursor(line(), endCol(indicateEOL)); |
154 | } |
155 | |
156 | int KateTextLayout::length() const |
157 | { |
158 | if (!isValid()) { |
159 | return 0; |
160 | } |
161 | |
162 | return m_textLayout.textLength(); |
163 | } |
164 | |
165 | bool KateTextLayout::isEmpty() const |
166 | { |
167 | if (!isValid()) { |
168 | return true; |
169 | } |
170 | |
171 | return startCol() == 0 && endCol() == 0; |
172 | } |
173 | |
174 | bool KateTextLayout::wrap() const |
175 | { |
176 | if (!isValid()) { |
177 | return false; |
178 | } |
179 | |
180 | return viewLine() < m_lineLayout->viewLineCount() - 1; |
181 | } |
182 | |
183 | int KateTextLayout::startX() const |
184 | { |
185 | if (!isValid()) { |
186 | return 0; |
187 | } |
188 | |
189 | if (m_startX == -1) { |
190 | // viewLine is already > 0, from the constructor |
191 | for (int i = 0; i < viewLine(); ++i) { |
192 | m_startX += (int)m_lineLayout->layout()->lineAt(i).naturalTextWidth(); |
193 | } |
194 | } |
195 | |
196 | return m_startX; |
197 | } |
198 | |
199 | int KateTextLayout::endX() const |
200 | { |
201 | if (!isValid()) { |
202 | return 0; |
203 | } |
204 | |
205 | return startX() + (int)m_textLayout.naturalTextWidth(); |
206 | } |
207 | |
208 | int KateTextLayout::width() const |
209 | { |
210 | if (!isValid()) { |
211 | return 0; |
212 | } |
213 | |
214 | return (int)m_textLayout.naturalTextWidth(); |
215 | } |
216 | |
217 | KateTextLayout KateTextLayout::invalid() |
218 | { |
219 | return KateTextLayout(); |
220 | } |
221 | |
222 | bool KateTextLayout::isRightToLeft() const |
223 | { |
224 | if (m_lineLayout) { |
225 | return m_lineLayout->isRightToLeft(); |
226 | } |
227 | |
228 | return false; |
229 | } |
230 | |