/* This file is part of the KDE libraries Copyright (C) 2001-2003 Christoph Cullmann Copyright (C) 2002 Joseph Wenninger Based on: KateTextLine : Copyright (C) 1999 Jochen Wilhelmy 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 #include KateTextLine::KateTextLine () : m_flags(0) { } KateTextLine::~KateTextLine() { } void KateTextLine::insertText (uint pos, uint insLen, const TQChar *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 TQChar *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 TQChar *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 TQChar *KateTextLine::firstNonSpace() const { int first = firstChar(); return (first > -1) ? ((TQChar*)m_text.unicode())+first : m_text.unicode(); } uint KateTextLine::indentDepth (uint tabwidth) const { uint d = 0; const uint len = m_text.length(); const TQChar *unicode = m_text.unicode(); for(uint i = 0; i < len; i++) { if(unicode[i].isSpace()) { if (unicode[i] == TQChar('\t')) d += tabwidth - (d % tabwidth); else d++; } else return d; } return d; } bool KateTextLine::stringAtPos(uint pos, const TQString& 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 TQChar *unicode = m_text.unicode(); const TQChar *matchUnicode = match.unicode(); for (uint i=0; i < matchlen; i++) if (unicode[i+pos] != matchUnicode[i]) return false; return true; } bool KateTextLine::startingWith(const TQString& match) const { const uint matchlen = match.length(); if (matchlen > m_text.length()) return false; const TQChar *unicode = m_text.unicode(); const TQChar *matchUnicode = match.unicode(); for (uint i=0; i < matchlen; i++) if (unicode[i] != matchUnicode[i]) return false; return true; } bool KateTextLine::endingWith(const TQString& match) const { const uint matchlen = match.length(); if (matchlen > m_text.length()) return false; const TQChar *unicode = m_text.unicode(); const TQChar *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, (uint)m_text.length()); const TQChar *unicode = m_text.unicode(); for ( uint z = 0; z < n; z++) { if (unicode[z] == TQChar('\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 TQChar *unicode = m_text.unicode(); for ( uint z = 0; z < len; z++) { if (unicode[z] == TQChar('\t')) x += tabChars - (x % tabChars); else x++; } return x; } bool KateTextLine::searchText (uint startCol, const TQString &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 TQRegExp ®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(TQChar)*l); buf += sizeof(TQChar) * 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 ((TQChar *) buf, l); buf += sizeof(TQChar) * 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;