diff options
Diffstat (limited to 'kate/part/katetextline.cpp')
-rw-r--r-- | kate/part/katetextline.cpp | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/kate/part/katetextline.cpp b/kate/part/katetextline.cpp new file mode 100644 index 000000000..250be5236 --- /dev/null +++ b/kate/part/katetextline.cpp @@ -0,0 +1,443 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001-2003 Christoph Cullmann <cullmann@kde.org> + Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org> + + Based on: + KateTextLine : Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "katetextline.h" +#include "katerenderer.h" + +#include <kglobal.h> + +#include <qregexp.h> + +KateTextLine::KateTextLine () + : m_flags(0) +{ +} + +KateTextLine::~KateTextLine() +{ +} + +void KateTextLine::insertText (uint pos, uint insLen, const QChar *insText, uchar *insAttribs) +{ + // nothing to do + if (insLen == 0) + return; + + // calc new textLen, store old + uint oldTextLen = m_text.length(); + m_text.insert (pos, insText, insLen); + uint textLen = m_text.length(); + + // resize the array + m_attributes.resize (textLen); + + // HA, insert behind text end, fill with spaces + if (pos >= oldTextLen) + { + for (uint z = oldTextLen; z < pos; z++) + m_attributes[z] = 0; + } + // HA, insert in text, move the old text behind pos + else if (oldTextLen > 0) + { + for (int z = oldTextLen -1; z >= (int) pos; z--) + m_attributes[z+insLen] = m_attributes[z]; + } + + // BUH, actually insert the new text + for (uint z = 0; z < insLen; z++) + { + if (insAttribs == 0) + m_attributes[z+pos] = 0; + else + m_attributes[z+pos] = insAttribs[z]; + } +} + +void KateTextLine::removeText (uint pos, uint delLen) +{ + // nothing to do + if (delLen == 0) + return; + + uint textLen = m_text.length(); + + if (textLen == 0) + return; // uh, again nothing real to do ;) + + if (pos >= textLen) + return; + + if ((pos + delLen) > textLen) + delLen = textLen - pos; + + // BU, MOVE THE OLD TEXT AROUND + for (uint z = pos; z < textLen - delLen; z++) + m_attributes[z] = m_attributes[z+delLen]; + + m_text.remove (pos, delLen); + m_attributes.resize (m_text.length ()); +} + +void KateTextLine::truncate(uint newLen) +{ + if (newLen < m_text.length()) + { + m_text.truncate (newLen); + m_attributes.truncate (newLen); + } +} + +int KateTextLine::nextNonSpaceChar(uint pos) const +{ + const uint len = m_text.length(); + const QChar *unicode = m_text.unicode(); + + for(uint i = pos; i < len; i++) + { + if(!unicode[i].isSpace()) + return i; + } + + return -1; +} + +int KateTextLine::previousNonSpaceChar(uint pos) const +{ + const int len = m_text.length(); + + if (pos >= (uint)len) + pos = len - 1; + + const QChar *unicode = m_text.unicode(); + + for(int i = pos; i >= 0; i--) + { + if(!unicode[i].isSpace()) + return i; + } + + return -1; +} + +int KateTextLine::firstChar() const +{ + return nextNonSpaceChar(0); +} + +int KateTextLine::lastChar() const +{ + return previousNonSpaceChar(m_text.length() - 1); +} + +const QChar *KateTextLine::firstNonSpace() const +{ + int first = firstChar(); + return (first > -1) ? ((QChar*)m_text.unicode())+first : m_text.unicode(); +} + +uint KateTextLine::indentDepth (uint tabwidth) const +{ + uint d = 0; + const uint len = m_text.length(); + const QChar *unicode = m_text.unicode(); + + for(uint i = 0; i < len; i++) + { + if(unicode[i].isSpace()) + { + if (unicode[i] == QChar('\t')) + d += tabwidth - (d % tabwidth); + else + d++; + } + else + return d; + } + + return d; +} + +bool KateTextLine::stringAtPos(uint pos, const QString& match) const +{ + const uint len = m_text.length(); + const uint matchlen = match.length(); + + if ((pos+matchlen) > len) + return false; + + // (pos > len) in case the uint pos was assigned a signed -1, pos+matchlen can + // overflow again which (pos+matchlen > len) does not catch; see bugs #129263 and #129580 + Q_ASSERT(pos < len); + + const QChar *unicode = m_text.unicode(); + const QChar *matchUnicode = match.unicode(); + + for (uint i=0; i < matchlen; i++) + if (unicode[i+pos] != matchUnicode[i]) + return false; + + return true; +} + +bool KateTextLine::startingWith(const QString& match) const +{ + const uint matchlen = match.length(); + + if (matchlen > m_text.length()) + return false; + + const QChar *unicode = m_text.unicode(); + const QChar *matchUnicode = match.unicode(); + + for (uint i=0; i < matchlen; i++) + if (unicode[i] != matchUnicode[i]) + return false; + + return true; +} + +bool KateTextLine::endingWith(const QString& match) const +{ + const uint matchlen = match.length(); + + if (matchlen > m_text.length()) + return false; + + const QChar *unicode = m_text.unicode(); + const QChar *matchUnicode = match.unicode(); + + uint start = m_text.length() - matchlen; + for (uint i=0; i < matchlen; i++) + if (unicode[start+i] != matchUnicode[i]) + return false; + + return true; +} + +int KateTextLine::cursorX(uint pos, uint tabChars) const +{ + uint x = 0; + + const uint n = kMin (pos, m_text.length()); + const QChar *unicode = m_text.unicode(); + + for ( uint z = 0; z < n; z++) + { + if (unicode[z] == QChar('\t')) + x += tabChars - (x % tabChars); + else + x++; + } + + return x; +} + + +uint KateTextLine::lengthWithTabs (uint tabChars) const +{ + uint x = 0; + const uint len = m_text.length(); + const QChar *unicode = m_text.unicode(); + + for ( uint z = 0; z < len; z++) + { + if (unicode[z] == QChar('\t')) + x += tabChars - (x % tabChars); + else + x++; + } + + return x; +} + +bool KateTextLine::searchText (uint startCol, const QString &text, uint *foundAtCol, uint *matchLen, bool casesensitive, bool backwards) +{ + int index; + + if (backwards) + { + int col = startCol; + uint l = text.length(); + // allow finding the string ending at eol + if ( col == (int) m_text.length() ) ++startCol; + + do { + index = m_text.findRev( text, col, casesensitive ); + col--; + } while ( col >= 0 && l + index >= startCol ); + } + else + index = m_text.find (text, startCol, casesensitive); + + if (index > -1) + { + if (foundAtCol) + (*foundAtCol) = index; + if (matchLen) + (*matchLen)=text.length(); + return true; + } + + return false; +} + +bool KateTextLine::searchText (uint startCol, const QRegExp ®exp, uint *foundAtCol, uint *matchLen, bool backwards) +{ + int index; + + if (backwards) + { + int col = startCol; + + // allow finding the string ending at eol + if ( col == (int) m_text.length() ) ++startCol; + do { + index = regexp.searchRev (m_text, col); + col--; + } while ( col >= 0 && regexp.matchedLength() + index >= (int)startCol ); + } + else + index = regexp.search (m_text, startCol); + + if (index > -1) + { + if (foundAtCol) + (*foundAtCol) = index; + + if (matchLen) + (*matchLen)=regexp.matchedLength(); + return true; + } + + return false; +} + +char *KateTextLine::dump (char *buf, bool withHighlighting) const +{ + uint l = m_text.length(); + char f = m_flags; + + if (!withHighlighting) + f = f | KateTextLine::flagNoOtherData; + + memcpy(buf, (char *) &f, 1); + buf += 1; + + memcpy(buf, &l, sizeof(uint)); + buf += sizeof(uint); + + memcpy(buf, (char *) m_text.unicode(), sizeof(QChar)*l); + buf += sizeof(QChar) * l; + + if (!withHighlighting) + return buf; + + memcpy(buf, (char *)m_attributes.data(), sizeof(uchar) * l); + buf += sizeof (uchar) * l; + + uint lctx = m_ctx.size(); + uint lfold = m_foldingList.size(); + uint lind = m_indentationDepth.size(); + + memcpy(buf, &lctx, sizeof(uint)); + buf += sizeof(uint); + + memcpy(buf, &lfold, sizeof(uint)); + buf += sizeof(uint); + + memcpy(buf, &lind, sizeof(uint)); + buf += sizeof(uint); + + memcpy(buf, (char *)m_ctx.data(), sizeof(short) * lctx); + buf += sizeof (short) * lctx; + + memcpy(buf, (char *)m_foldingList.data(), sizeof(uint)*lfold); + buf += sizeof (uint) * lfold; + + memcpy(buf, (char *)m_indentationDepth.data(), sizeof(unsigned short) * lind); + buf += sizeof (unsigned short) * lind; + + return buf; +} + +char *KateTextLine::restore (char *buf) +{ + uint l = 0; + char f = 0; + + memcpy((char *) &f, buf, 1); + buf += 1; + + // text + context length read + memcpy((char *) &l, buf, sizeof(uint)); + buf += sizeof(uint); + + // text + attributes + m_text.setUnicode ((QChar *) buf, l); + buf += sizeof(QChar) * l; + + // we just restore a KateTextLine from a buffer first time + if (f & KateTextLine::flagNoOtherData) + { + m_flags = 0; + + if (f & KateTextLine::flagAutoWrapped) + m_flags = m_flags | KateTextLine::flagAutoWrapped; + + // fill with clean empty attribs ! + m_attributes.fill (0, l); + + return buf; + } + else + m_flags = f; + + m_attributes.duplicate ((uchar *) buf, l); + buf += sizeof(uchar) * l; + + uint lctx = 0; + uint lfold = 0; + uint lind = 0; + + memcpy((char *) &lctx, buf, sizeof(uint)); + buf += sizeof(uint); + + memcpy((char *) &lfold, buf, sizeof(uint)); + buf += sizeof(uint); + + memcpy((char *) &lind, buf, sizeof(uint)); + buf += sizeof(uint); + + m_ctx.duplicate ((short *) buf, lctx); + buf += sizeof(short) * lctx; + + m_foldingList.duplicate ((uint *) buf, lfold); + buf += sizeof(uint)*lfold; + + m_indentationDepth.duplicate ((unsigned short *) buf, lind); + buf += sizeof(unsigned short) * lind; + + return buf; +} + +// kate: space-indent on; indent-width 2; replace-tabs on; |