File indexing completed on 2024-04-21 03:57:33
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_line(-1) 0022 , m_virtualLine(-1) 0023 , m_layout(nullptr) 0024 { 0025 } 0026 0027 void KateLineLayout::clear() 0028 { 0029 m_textLine.reset(); 0030 m_line = -1; 0031 m_virtualLine = -1; 0032 shiftX = 0; 0033 // not touching dirty 0034 m_layout.reset(); 0035 // not touching layout dirty 0036 } 0037 0038 bool KateLineLayout::includesCursor(const KTextEditor::Cursor realCursor) const 0039 { 0040 return realCursor.line() == line(); 0041 } 0042 0043 const Kate::TextLine &KateLineLayout::textLine(bool reloadForce) const 0044 { 0045 if (reloadForce || !m_textLine) { 0046 m_textLine.reset(); 0047 if (m_line >= 0 && m_line < m_renderer.doc()->lines()) { 0048 m_textLine = usePlainTextLine ? m_renderer.doc()->plainKateTextLine(m_line) : m_renderer.doc()->kateTextLine(m_line); 0049 } 0050 } 0051 0052 Q_ASSERT(m_textLine); 0053 0054 return *m_textLine; 0055 } 0056 0057 int KateLineLayout::line() const 0058 { 0059 return m_line; 0060 } 0061 0062 void KateLineLayout::setLine(int line, int virtualLine) 0063 { 0064 m_line = line; 0065 m_virtualLine = (virtualLine == -1) ? m_renderer.folding().lineToVisibleLine(line) : virtualLine; 0066 m_textLine.reset(); 0067 } 0068 0069 int KateLineLayout::virtualLine() const 0070 { 0071 return m_virtualLine; 0072 } 0073 0074 void KateLineLayout::setVirtualLine(int virtualLine) 0075 { 0076 m_virtualLine = virtualLine; 0077 } 0078 0079 bool KateLineLayout::startsInvisibleBlock() const 0080 { 0081 if (!isValid()) { 0082 return false; 0083 } 0084 0085 return (virtualLine() + 1) != m_renderer.folding().lineToVisibleLine(line() + 1); 0086 } 0087 0088 bool KateLineLayout::isValid() const 0089 { 0090 return line() != -1 && layout() && (textLine(), m_textLine); 0091 } 0092 0093 QTextLayout *KateLineLayout::layout() const 0094 { 0095 return m_layout.get(); 0096 } 0097 0098 void KateLineLayout::setLayout(QTextLayout *layout) 0099 { 0100 if (m_layout.get() != layout) { 0101 m_layout.reset(layout); 0102 } 0103 0104 layoutDirty = !m_layout; 0105 m_dirtyList.clear(); 0106 if (m_layout) { 0107 for (int i = 0; i < qMax(1, m_layout->lineCount()); ++i) { 0108 m_dirtyList.append(true); 0109 } 0110 } 0111 } 0112 0113 void KateLineLayout::invalidateLayout() 0114 { 0115 setLayout(nullptr); 0116 } 0117 0118 bool KateLineLayout::isDirty(int viewLine) const 0119 { 0120 Q_ASSERT(isValid() && viewLine >= 0 && viewLine < viewLineCount()); 0121 return m_dirtyList[viewLine]; 0122 } 0123 0124 bool KateLineLayout::setDirty(int viewLine, bool dirty) 0125 { 0126 Q_ASSERT(isValid() && viewLine >= 0 && viewLine < viewLineCount()); 0127 m_dirtyList[viewLine] = dirty; 0128 return dirty; 0129 } 0130 0131 KTextEditor::Cursor KateLineLayout::start() const 0132 { 0133 return KTextEditor::Cursor(line(), 0); 0134 } 0135 0136 int KateLineLayout::length() const 0137 { 0138 return textLine().length(); 0139 } 0140 0141 int KateLineLayout::viewLineCount() const 0142 { 0143 return m_layout->lineCount(); 0144 } 0145 0146 KateTextLayout KateLineLayout::viewLine(int viewLine) 0147 { 0148 if (viewLine < 0) { 0149 viewLine += viewLineCount(); 0150 } 0151 Q_ASSERT(isValid()); 0152 Q_ASSERT(viewLine >= 0 && viewLine < viewLineCount()); 0153 return KateTextLayout(this, viewLine); 0154 } 0155 0156 int KateLineLayout::width() const 0157 { 0158 int width = 0; 0159 0160 for (int i = 0; i < m_layout->lineCount(); ++i) { 0161 width = qMax((int)m_layout->lineAt(i).naturalTextWidth(), width); 0162 } 0163 0164 return width; 0165 } 0166 0167 int KateLineLayout::widthOfLastLine() 0168 { 0169 const KateTextLayout &lastLine = viewLine(viewLineCount() - 1); 0170 return lastLine.width() + lastLine.xOffset(); 0171 } 0172 0173 bool KateLineLayout::isOutsideDocument() const 0174 { 0175 return line() < 0 || line() >= m_renderer.doc()->lines(); 0176 } 0177 0178 void KateLineLayout::debugOutput() const 0179 { 0180 qCDebug(LOG_KTE) << "KateLineLayout: " << this << " valid " << isValid() << " line " << line() << " length " << length() << " width " << width() 0181 << " viewLineCount " << viewLineCount(); 0182 } 0183 0184 int KateLineLayout::viewLineForColumn(int column) const 0185 { 0186 int len = 0; 0187 int i = 0; 0188 for (; i < m_layout->lineCount() - 1; ++i) { 0189 len += m_layout->lineAt(i).textLength(); 0190 if (column < len) { 0191 return i; 0192 } 0193 } 0194 return i; 0195 } 0196 0197 bool KateLineLayout::isRightToLeft() const 0198 { 0199 if (!m_layout) { 0200 return false; 0201 } 0202 0203 return m_layout->textOption().textDirection() == Qt::RightToLeft; 0204 }