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 "katelinelayout.h"
9#include "katetextfolding.h"
10#include "katetextlayout.h"
11
12#include <QTextLine>
13
14#include "katepartdebug.h"
15
16#include "katedocument.h"
17#include "katerenderer.h"
18
19KateLineLayout::KateLineLayout(KateRenderer &renderer)
20 : m_renderer(renderer)
21 , m_line(-1)
22 , m_virtualLine(-1)
23 , m_layout(nullptr)
24{
25}
26
27void KateLineLayout::clear()
28{
29 m_textLine.reset();
30 m_line = -1;
31 m_virtualLine = -1;
32 shiftX = 0;
33 // not touching dirty
34 m_layout.reset();
35 // not touching layout dirty
36}
37
38bool KateLineLayout::includesCursor(const KTextEditor::Cursor realCursor) const
39{
40 return realCursor.line() == line();
41}
42
43const Kate::TextLine &KateLineLayout::textLine(bool reloadForce) const
44{
45 if (reloadForce || !m_textLine) {
46 m_textLine.reset();
47 if (m_line >= 0 && m_line < m_renderer.doc()->lines()) {
48 m_textLine = usePlainTextLine ? m_renderer.doc()->plainKateTextLine(i: m_line) : m_renderer.doc()->kateTextLine(i: m_line);
49 }
50 }
51
52 Q_ASSERT(m_textLine);
53
54 return *m_textLine;
55}
56
57int KateLineLayout::line() const
58{
59 return m_line;
60}
61
62void KateLineLayout::setLine(int line, int virtualLine)
63{
64 m_line = line;
65 m_virtualLine = (virtualLine == -1) ? m_renderer.folding().lineToVisibleLine(line) : virtualLine;
66 m_textLine.reset();
67}
68
69int KateLineLayout::virtualLine() const
70{
71 return m_virtualLine;
72}
73
74void KateLineLayout::setVirtualLine(int virtualLine)
75{
76 m_virtualLine = virtualLine;
77}
78
79bool KateLineLayout::startsInvisibleBlock() const
80{
81 if (!isValid()) {
82 return false;
83 }
84
85 return (virtualLine() + 1) != m_renderer.folding().lineToVisibleLine(line: line() + 1);
86}
87
88bool KateLineLayout::isValid() const
89{
90 return line() != -1 && layout() && (textLine(), m_textLine);
91}
92
93QTextLayout *KateLineLayout::layout() const
94{
95 return m_layout.get();
96}
97
98void KateLineLayout::setLayout(QTextLayout *layout)
99{
100 if (m_layout.get() != layout) {
101 m_layout.reset(p: layout);
102 }
103
104 layoutDirty = !m_layout;
105 m_dirtyList.clear();
106 if (m_layout) {
107 for (int i = 0; i < qMax(a: 1, b: m_layout->lineCount()); ++i) {
108 m_dirtyList.append(t: true);
109 }
110 }
111}
112
113void KateLineLayout::invalidateLayout()
114{
115 setLayout(nullptr);
116}
117
118bool KateLineLayout::isDirty(int viewLine) const
119{
120 Q_ASSERT(isValid() && viewLine >= 0 && viewLine < viewLineCount());
121 return m_dirtyList[viewLine];
122}
123
124bool KateLineLayout::setDirty(int viewLine, bool dirty)
125{
126 Q_ASSERT(isValid() && viewLine >= 0 && viewLine < viewLineCount());
127 m_dirtyList[viewLine] = dirty;
128 return dirty;
129}
130
131KTextEditor::Cursor KateLineLayout::start() const
132{
133 return KTextEditor::Cursor(line(), 0);
134}
135
136int KateLineLayout::length() const
137{
138 return textLine().length();
139}
140
141int KateLineLayout::viewLineCount() const
142{
143 return m_layout->lineCount();
144}
145
146KateTextLayout KateLineLayout::viewLine(int viewLine)
147{
148 if (viewLine < 0) {
149 viewLine += viewLineCount();
150 }
151 Q_ASSERT(isValid());
152 Q_ASSERT(viewLine >= 0 && viewLine < viewLineCount());
153 return KateTextLayout(this, viewLine);
154}
155
156int KateLineLayout::width() const
157{
158 int width = 0;
159
160 for (int i = 0; i < m_layout->lineCount(); ++i) {
161 width = qMax(a: (int)m_layout->lineAt(i).naturalTextWidth(), b: width);
162 }
163
164 return width;
165}
166
167int KateLineLayout::widthOfLastLine()
168{
169 const KateTextLayout &lastLine = viewLine(viewLine: viewLineCount() - 1);
170 return lastLine.width() + lastLine.xOffset();
171}
172
173bool KateLineLayout::isOutsideDocument() const
174{
175 return line() < 0 || line() >= m_renderer.doc()->lines();
176}
177
178void KateLineLayout::debugOutput() const
179{
180 qCDebug(LOG_KTE) << "KateLineLayout: " << this << " valid " << isValid() << " line " << line() << " length " << length() << " width " << width()
181 << " viewLineCount " << viewLineCount();
182}
183
184int KateLineLayout::viewLineForColumn(int column) const
185{
186 int len = 0;
187 int i = 0;
188 for (; i < m_layout->lineCount() - 1; ++i) {
189 len += m_layout->lineAt(i).textLength();
190 if (column < len) {
191 return i;
192 }
193 }
194 return i;
195}
196
197bool KateLineLayout::isRightToLeft() const
198{
199 if (!m_layout) {
200 return false;
201 }
202
203 return m_layout->textOption().textDirection() == Qt::RightToLeft;
204}
205

source code of ktexteditor/src/render/katelinelayout.cpp