File indexing completed on 2024-04-28 15:30:35
0001 /* 0002 SPDX-FileCopyrightText: 2002-2005 Hamish Rodda <rodda@kde.org> 0003 SPDX-FileCopyrightText: 2003 Anakim Border <aborder@sources.sourceforge.net> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "katelinelayout.h" 0009 #include "katetextfolding.h" 0010 #include "katetextlayout.h" 0011 0012 #include <QTextLine> 0013 0014 #include "katepartdebug.h" 0015 0016 #include "katedocument.h" 0017 #include "katerenderer.h" 0018 0019 KateLineLayout::KateLineLayout(KateRenderer &renderer) 0020 : m_renderer(renderer) 0021 , m_textLine() 0022 , m_line(-1) 0023 , m_virtualLine(-1) 0024 , m_shiftX(0) 0025 , m_layout(nullptr) 0026 , m_layoutDirty(true) 0027 , m_usePlainTextLine(false) 0028 { 0029 } 0030 0031 void KateLineLayout::clear() 0032 { 0033 m_textLine = Kate::TextLine(); 0034 m_line = -1; 0035 m_virtualLine = -1; 0036 m_shiftX = 0; 0037 // not touching dirty 0038 m_layout.reset(); 0039 // not touching layout dirty 0040 } 0041 0042 bool KateLineLayout::includesCursor(const KTextEditor::Cursor realCursor) const 0043 { 0044 return realCursor.line() == line(); 0045 } 0046 0047 const Kate::TextLine &KateLineLayout::textLine(bool reloadForce) const 0048 { 0049 if (reloadForce || !m_textLine) { 0050 m_textLine = usePlainTextLine() ? m_renderer.doc()->plainKateTextLine(line()) : m_renderer.doc()->kateTextLine(line()); 0051 } 0052 0053 Q_ASSERT(m_textLine); 0054 0055 return m_textLine; 0056 } 0057 0058 int KateLineLayout::line() const 0059 { 0060 return m_line; 0061 } 0062 0063 void KateLineLayout::setLine(int line, int virtualLine) 0064 { 0065 m_line = line; 0066 m_virtualLine = (virtualLine == -1) ? m_renderer.folding().lineToVisibleLine(line) : virtualLine; 0067 m_textLine = Kate::TextLine(); 0068 } 0069 0070 int KateLineLayout::virtualLine() const 0071 { 0072 return m_virtualLine; 0073 } 0074 0075 void KateLineLayout::setVirtualLine(int virtualLine) 0076 { 0077 m_virtualLine = virtualLine; 0078 } 0079 0080 bool KateLineLayout::startsInvisibleBlock() const 0081 { 0082 if (!isValid()) { 0083 return false; 0084 } 0085 0086 return (virtualLine() + 1) != m_renderer.folding().lineToVisibleLine(line() + 1); 0087 } 0088 0089 int KateLineLayout::shiftX() const 0090 { 0091 return m_shiftX; 0092 } 0093 0094 void KateLineLayout::setShiftX(int shiftX) 0095 { 0096 m_shiftX = shiftX; 0097 } 0098 0099 KTextEditor::DocumentPrivate *KateLineLayout::doc() const 0100 { 0101 return m_renderer.doc(); 0102 } 0103 0104 bool KateLineLayout::isValid() const 0105 { 0106 return line() != -1 && layout() && textLine(); 0107 } 0108 0109 QTextLayout *KateLineLayout::layout() const 0110 { 0111 return m_layout.get(); 0112 } 0113 0114 void KateLineLayout::setLayout(QTextLayout *layout) 0115 { 0116 if (m_layout.get() != layout) { 0117 m_layout.reset(layout); 0118 } 0119 0120 m_layoutDirty = !m_layout; 0121 m_dirtyList.clear(); 0122 if (m_layout) { 0123 for (int i = 0; i < qMax(1, m_layout->lineCount()); ++i) { 0124 m_dirtyList.append(true); 0125 } 0126 } 0127 } 0128 0129 void KateLineLayout::invalidateLayout() 0130 { 0131 setLayout(nullptr); 0132 } 0133 0134 bool KateLineLayout::isDirty(int viewLine) const 0135 { 0136 Q_ASSERT(isValid() && viewLine >= 0 && viewLine < viewLineCount()); 0137 return m_dirtyList[viewLine]; 0138 } 0139 0140 bool KateLineLayout::setDirty(int viewLine, bool dirty) 0141 { 0142 Q_ASSERT(isValid() && viewLine >= 0 && viewLine < viewLineCount()); 0143 m_dirtyList[viewLine] = dirty; 0144 return dirty; 0145 } 0146 0147 KTextEditor::Cursor KateLineLayout::start() const 0148 { 0149 return KTextEditor::Cursor(line(), 0); 0150 } 0151 0152 int KateLineLayout::length() const 0153 { 0154 return textLine()->length(); 0155 } 0156 0157 int KateLineLayout::viewLineCount() const 0158 { 0159 return m_layout->lineCount(); 0160 } 0161 0162 KateTextLayout KateLineLayout::viewLine(int viewLine) const 0163 { 0164 if (viewLine < 0) { 0165 viewLine += viewLineCount(); 0166 } 0167 Q_ASSERT(isValid()); 0168 Q_ASSERT(viewLine >= 0 && viewLine < viewLineCount()); 0169 return KateTextLayout(KateLineLayoutPtr(const_cast<KateLineLayout *>(this)), viewLine); 0170 } 0171 0172 int KateLineLayout::width() const 0173 { 0174 int width = 0; 0175 0176 for (int i = 0; i < m_layout->lineCount(); ++i) { 0177 width = qMax((int)m_layout->lineAt(i).naturalTextWidth(), width); 0178 } 0179 0180 return width; 0181 } 0182 0183 int KateLineLayout::widthOfLastLine() const 0184 { 0185 const KateTextLayout &lastLine = viewLine(viewLineCount() - 1); 0186 return lastLine.width() + lastLine.xOffset(); 0187 } 0188 0189 bool KateLineLayout::isOutsideDocument() const 0190 { 0191 return line() < 0 || line() >= m_renderer.doc()->lines(); 0192 } 0193 0194 void KateLineLayout::debugOutput() const 0195 { 0196 qCDebug(LOG_KTE) << "KateLineLayout: " << this << " valid " << isValid() << " line " << line() << " length " << length() << " width " << width() 0197 << " viewLineCount " << viewLineCount(); 0198 } 0199 0200 int KateLineLayout::viewLineForColumn(int column) const 0201 { 0202 int len = 0; 0203 int i = 0; 0204 for (; i < m_layout->lineCount() - 1; ++i) { 0205 len += m_layout->lineAt(i).textLength(); 0206 if (column < len) { 0207 return i; 0208 } 0209 } 0210 return i; 0211 } 0212 0213 bool KateLineLayout::isLayoutDirty() const 0214 { 0215 return m_layoutDirty; 0216 } 0217 0218 void KateLineLayout::setLayoutDirty(bool dirty) 0219 { 0220 m_layoutDirty = dirty; 0221 } 0222 0223 bool KateLineLayout::usePlainTextLine() const 0224 { 0225 return m_usePlainTextLine; 0226 } 0227 0228 void KateLineLayout::setUsePlainTextLine(bool plain) 0229 { 0230 m_usePlainTextLine = plain; 0231 } 0232 0233 bool KateLineLayout::isRightToLeft() const 0234 { 0235 if (!m_layout) { 0236 return false; 0237 } 0238 0239 return m_layout->textOption().textDirection() == Qt::RightToLeft; 0240 }