File indexing completed on 2023-09-24 04:11:28
0001 /* 0002 SPDX-FileCopyrightText: 2010 Christoph Cullmann <cullmann@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "katetextline.h" 0008 0009 namespace Kate 0010 { 0011 0012 int TextLineData::firstChar() const 0013 { 0014 return nextNonSpaceChar(0); 0015 } 0016 0017 int TextLineData::lastChar() const 0018 { 0019 return previousNonSpaceChar(m_text.length() - 1); 0020 } 0021 0022 int TextLineData::nextNonSpaceChar(int pos) const 0023 { 0024 Q_ASSERT(pos >= 0); 0025 0026 for (int i = pos; i < m_text.length(); i++) { 0027 if (!m_text[i].isSpace()) { 0028 return i; 0029 } 0030 } 0031 0032 return -1; 0033 } 0034 0035 int TextLineData::previousNonSpaceChar(int pos) const 0036 { 0037 if (pos >= m_text.length()) { 0038 pos = m_text.length() - 1; 0039 } 0040 0041 for (int i = pos; i >= 0; i--) { 0042 if (!m_text[i].isSpace()) { 0043 return i; 0044 } 0045 } 0046 0047 return -1; 0048 } 0049 0050 QString TextLineData::leadingWhitespace() const 0051 { 0052 if (firstChar() < 0) { 0053 return string(0, length()); 0054 } 0055 0056 return string(0, firstChar()); 0057 } 0058 0059 int TextLineData::indentDepth(int tabWidth) const 0060 { 0061 int d = 0; 0062 const int len = m_text.length(); 0063 const QChar *unicode = m_text.unicode(); 0064 0065 for (int i = 0; i < len; ++i) { 0066 if (unicode[i].isSpace()) { 0067 if (unicode[i] == QLatin1Char('\t')) { 0068 d += tabWidth - (d % tabWidth); 0069 } else { 0070 d++; 0071 } 0072 } else { 0073 return d; 0074 } 0075 } 0076 0077 return d; 0078 } 0079 0080 bool TextLineData::matchesAt(int column, const QString &match) const 0081 { 0082 if (column < 0) { 0083 return false; 0084 } 0085 0086 const int len = m_text.length(); 0087 const int matchlen = match.length(); 0088 0089 if ((column + matchlen) > len) { 0090 return false; 0091 } 0092 0093 const QChar *unicode = m_text.unicode(); 0094 const QChar *matchUnicode = match.unicode(); 0095 0096 for (int i = 0; i < matchlen; ++i) { 0097 if (unicode[i + column] != matchUnicode[i]) { 0098 return false; 0099 } 0100 } 0101 0102 return true; 0103 } 0104 0105 int TextLineData::toVirtualColumn(int column, int tabWidth) const 0106 { 0107 if (column < 0) { 0108 return 0; 0109 } 0110 0111 int x = 0; 0112 const int zmax = qMin(column, m_text.length()); 0113 const QChar *unicode = m_text.unicode(); 0114 0115 for (int z = 0; z < zmax; ++z) { 0116 if (unicode[z] == QLatin1Char('\t')) { 0117 x += tabWidth - (x % tabWidth); 0118 } else { 0119 x++; 0120 } 0121 } 0122 0123 return x + column - zmax; 0124 } 0125 0126 int TextLineData::fromVirtualColumn(int column, int tabWidth) const 0127 { 0128 if (column < 0) { 0129 return 0; 0130 } 0131 0132 const int zmax = qMin(m_text.length(), column); 0133 const QChar *unicode = m_text.unicode(); 0134 0135 int x = 0; 0136 int z = 0; 0137 for (; z < zmax; ++z) { 0138 int diff = 1; 0139 if (unicode[z] == QLatin1Char('\t')) { 0140 diff = tabWidth - (x % tabWidth); 0141 } 0142 0143 if (x + diff > column) { 0144 break; 0145 } 0146 x += diff; 0147 } 0148 0149 return z + qMax(column - x, 0); 0150 } 0151 0152 int TextLineData::virtualLength(int tabWidth) const 0153 { 0154 int x = 0; 0155 const int len = m_text.length(); 0156 const QChar *unicode = m_text.unicode(); 0157 0158 for (int z = 0; z < len; ++z) { 0159 if (unicode[z] == QLatin1Char('\t')) { 0160 x += tabWidth - (x % tabWidth); 0161 } else { 0162 x++; 0163 } 0164 } 0165 0166 return x; 0167 } 0168 0169 void TextLineData::addAttribute(const Attribute &attribute) 0170 { 0171 // try to append to previous range, if same attribute value 0172 if (!m_attributesList.isEmpty() && (m_attributesList.back().attributeValue == attribute.attributeValue) 0173 && ((m_attributesList.back().offset + m_attributesList.back().length) == attribute.offset)) { 0174 m_attributesList.back().length += attribute.length; 0175 return; 0176 } 0177 0178 m_attributesList.append(attribute); 0179 } 0180 0181 short TextLineData::attribute(int pos) const 0182 { 0183 auto found = std::upper_bound(m_attributesList.cbegin(), m_attributesList.cend(), pos, [](const int &p, const Attribute &x) { 0184 return p < x.offset + x.length; 0185 }); 0186 if (found != m_attributesList.cend() && found->offset <= pos && pos < (found->offset + found->length)) { 0187 return found->attributeValue; 0188 } 0189 return 0; 0190 } 0191 0192 }