File indexing completed on 2024-04-28 15:30:17

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 }