katetextline.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2001-2003 Christoph Cullmann <cullmann@kde.org>
00003    Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
00004 
00005    Based on:
00006      KateTextLine : Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
00007 
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Library General Public
00010    License version 2 as published by the Free Software Foundation.
00011 
00012    This library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Library General Public License for more details.
00016 
00017    You should have received a copy of the GNU Library General Public License
00018    along with this library; see the file COPYING.LIB.  If not, write to
00019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020    Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include "katetextline.h"
00024 #include "katerenderer.h"
00025 
00026 #include <kglobal.h>
00027 
00028 #include <qregexp.h>
00029 
00030 KateTextLine::KateTextLine ()
00031   : m_flags(0)
00032 {
00033 }
00034 
00035 KateTextLine::~KateTextLine()
00036 {
00037 }
00038 
00039 void KateTextLine::insertText (uint pos, uint insLen, const QChar *insText, uchar *insAttribs)
00040 {
00041   // nothing to do
00042   if (insLen == 0)
00043     return;
00044 
00045   // calc new textLen, store old
00046   uint oldTextLen = m_text.length();
00047   m_text.insert (pos, insText, insLen);
00048   uint textLen = m_text.length();
00049 
00050   // resize the array
00051   m_attributes.resize (textLen);
00052 
00053   // HA, insert behind text end, fill with spaces
00054   if (pos >= oldTextLen)
00055   {
00056     for (uint z = oldTextLen; z < pos; z++)
00057       m_attributes[z] = 0;
00058   }
00059   // HA, insert in text, move the old text behind pos
00060   else if (oldTextLen > 0)
00061   {
00062     for (int z = oldTextLen -1; z >= (int) pos; z--)
00063       m_attributes[z+insLen] = m_attributes[z];
00064   }
00065 
00066   // BUH, actually insert the new text
00067   for (uint z = 0; z < insLen; z++)
00068   {
00069     if (insAttribs == 0)
00070       m_attributes[z+pos] = 0;
00071     else
00072       m_attributes[z+pos] = insAttribs[z];
00073   }
00074 }
00075 
00076 void KateTextLine::removeText (uint pos, uint delLen)
00077 {
00078   // nothing to do
00079   if (delLen == 0)
00080     return;
00081 
00082   uint textLen = m_text.length();
00083 
00084   if (textLen == 0)
00085     return; // uh, again nothing real to do ;)
00086 
00087   if (pos >= textLen)
00088     return;
00089 
00090   if ((pos + delLen) > textLen)
00091     delLen = textLen - pos;
00092 
00093   // BU, MOVE THE OLD TEXT AROUND
00094   for (uint z = pos; z < textLen - delLen; z++)
00095     m_attributes[z] = m_attributes[z+delLen];
00096 
00097   m_text.remove (pos, delLen);
00098   m_attributes.resize (m_text.length ());
00099 }
00100 
00101 void KateTextLine::truncate(uint newLen)
00102 {
00103   if (newLen < m_text.length())
00104   {
00105     m_text.truncate (newLen);
00106     m_attributes.truncate (newLen);
00107   }
00108 }
00109 
00110 int KateTextLine::nextNonSpaceChar(uint pos) const
00111 {
00112   for(int i = pos; i < (int)m_text.length(); i++)
00113   {
00114     if(!m_text[i].isSpace())
00115       return i;
00116   }
00117 
00118   return -1;
00119 }
00120 
00121 int KateTextLine::previousNonSpaceChar(uint pos) const
00122 {
00123   if (pos >= m_text.length())
00124     pos = m_text.length() - 1;
00125 
00126   for(int i = pos; i >= 0; i--)
00127   {
00128     if(!m_text[i].isSpace())
00129       return i;
00130   }
00131 
00132   return -1;
00133 }
00134 
00135 int KateTextLine::firstChar() const
00136 {
00137   return nextNonSpaceChar(0);
00138 }
00139 
00140 int KateTextLine::lastChar() const
00141 {
00142   return previousNonSpaceChar(m_text.length() - 1);
00143 }
00144 
00145 const QChar *KateTextLine::firstNonSpace() const
00146 {
00147   int first = firstChar();
00148   return (first > -1) ? ((QChar*)m_text.unicode())+first : m_text.unicode();
00149 }
00150 
00151 uint KateTextLine::indentDepth (uint tabwidth) const
00152 {
00153   uint d = 0;
00154 
00155   for(uint i = 0; i < m_text.length(); i++)
00156   {
00157     if(m_text[i].isSpace())
00158     {
00159       if (m_text[i] == QChar('\t'))
00160         d += tabwidth - (d % tabwidth);
00161       else
00162         d++;
00163     }
00164     else
00165       return d;
00166   }
00167 
00168   return d;
00169 }
00170 
00171 bool KateTextLine::stringAtPos(uint pos, const QString& match) const
00172 {
00173   if ((pos+match.length()) > m_text.length())
00174     return false;
00175 
00176   for (uint i=0; i < match.length(); i++)
00177     if (m_text[i+pos] != match[i])
00178       return false;
00179 
00180   return true;
00181 }
00182 
00183 bool KateTextLine::startingWith(const QString& match) const
00184 {
00185   if (match.length() > m_text.length())
00186     return false;
00187 
00188   for (uint i=0; i < match.length(); i++)
00189     if (m_text[i] != match[i])
00190       return false;
00191 
00192   return true;
00193 }
00194 
00195 bool KateTextLine::endingWith(const QString& match) const
00196 {
00197   if (match.length() > m_text.length())
00198     return false;
00199 
00200   uint start = m_text.length() - match.length();
00201   for (uint i=0; i < match.length(); i++)
00202     if (m_text[start+i] != match[i])
00203       return false;
00204 
00205   return true;
00206 }
00207 
00208 int KateTextLine::cursorX(uint pos, uint tabChars) const
00209 {
00210   uint x = 0;
00211 
00212   for ( uint z = 0; z < kMin (pos, m_text.length()); z++)
00213   {
00214     if (m_text[z] == QChar('\t'))
00215       x += tabChars - (x % tabChars);
00216     else
00217       x++;
00218   }
00219 
00220   return x;
00221 }
00222 
00223 
00224 uint KateTextLine::lengthWithTabs (uint tabChars) const
00225 {
00226   uint x = 0;
00227 
00228   for ( uint z = 0; z < m_text.length(); z++)
00229   {
00230     if (m_text[z] == QChar('\t'))
00231       x += tabChars - (x % tabChars);
00232     else
00233       x++;
00234   }
00235 
00236   return x;
00237 }
00238 
00239 bool KateTextLine::searchText (uint startCol, const QString &text, uint *foundAtCol, uint *matchLen, bool casesensitive, bool backwards)
00240 {
00241   int index;
00242 
00243   if (backwards)
00244   {
00245     int col = startCol;
00246     uint l = text.length();
00247     // allow finding the string ending at eol
00248     if ( col == (int) m_text.length() ) ++startCol;
00249 
00250     do {
00251       index = m_text.findRev( text, col, casesensitive );
00252       col--;
00253     } while ( col >= 0 && l + index >= startCol );
00254   }
00255   else
00256     index = m_text.find (text, startCol, casesensitive);
00257 
00258   if (index > -1)
00259   {
00260     if (foundAtCol)
00261       (*foundAtCol) = index;
00262     if (matchLen)
00263       (*matchLen)=text.length();
00264     return true;
00265   }
00266 
00267   return false;
00268 }
00269 
00270 bool KateTextLine::searchText (uint startCol, const QRegExp &regexp, uint *foundAtCol, uint *matchLen, bool backwards)
00271 {
00272   int index;
00273 
00274   if (backwards)
00275   {
00276     int col = startCol;
00277 
00278     // allow finding the string ending at eol
00279     if ( col == (int) m_text.length() ) ++startCol;
00280     do {
00281       index = regexp.searchRev (m_text, col);
00282       col--;
00283     } while ( col >= 0 && regexp.matchedLength() + index >= (int)startCol );
00284   }
00285   else
00286     index = regexp.search (m_text, startCol);
00287 
00288   if (index > -1)
00289   {
00290     if (foundAtCol)
00291       (*foundAtCol) = index;
00292 
00293     if (matchLen)
00294       (*matchLen)=regexp.matchedLength();
00295     return true;
00296   }
00297 
00298   return false;
00299 }
00300 
00301 char *KateTextLine::dump (char *buf, bool withHighlighting) const
00302 {
00303   uint l = m_text.length();
00304   char f = m_flags;
00305 
00306   if (!withHighlighting)
00307     f = f | KateTextLine::flagNoOtherData;
00308 
00309   memcpy(buf, (char *) &f, 1);
00310   buf += 1;
00311 
00312   memcpy(buf, &l, sizeof(uint));
00313   buf += sizeof(uint);
00314 
00315   memcpy(buf, (char *) m_text.unicode(), sizeof(QChar)*l);
00316   buf += sizeof(QChar) * l;
00317 
00318   if (!withHighlighting)
00319     return buf;
00320 
00321   memcpy(buf, (char *)m_attributes.data(), sizeof(uchar) * l);
00322   buf += sizeof (uchar) * l;
00323 
00324   uint lctx = m_ctx.size();
00325   uint lfold = m_foldingList.size();
00326   uint lind = m_indentationDepth.size();
00327 
00328   memcpy(buf, &lctx, sizeof(uint));
00329   buf += sizeof(uint);
00330 
00331   memcpy(buf, &lfold, sizeof(uint));
00332   buf += sizeof(uint);
00333 
00334   memcpy(buf, &lind, sizeof(uint));
00335   buf += sizeof(uint);
00336 
00337   memcpy(buf, (char *)m_ctx.data(), sizeof(short) * lctx);
00338   buf += sizeof (short) * lctx;
00339 
00340   memcpy(buf, (char *)m_foldingList.data(), sizeof(uint)*lfold);
00341   buf += sizeof (uint) * lfold;
00342 
00343   memcpy(buf, (char *)m_indentationDepth.data(), sizeof(unsigned short) * lind);
00344   buf += sizeof (unsigned short) * lind;
00345 
00346   return buf;
00347 }
00348 
00349 char *KateTextLine::restore (char *buf)
00350 {
00351   uint l = 0;
00352   char f = 0;
00353 
00354   memcpy((char *) &f, buf, 1);
00355   buf += 1;
00356 
00357   // text + context length read
00358   memcpy((char *) &l, buf, sizeof(uint));
00359   buf += sizeof(uint);
00360 
00361   // text + attributes
00362   m_text.setUnicode ((QChar *) buf, l);
00363   buf += sizeof(QChar) * l;
00364 
00365   // we just restore a KateTextLine from a buffer first time
00366   if (f & KateTextLine::flagNoOtherData)
00367   {
00368     m_flags = 0;
00369 
00370     if (f & KateTextLine::flagAutoWrapped)
00371       m_flags = m_flags | KateTextLine::flagAutoWrapped;
00372 
00373     // fill with clean empty attribs !
00374     m_attributes.fill (0, l);
00375 
00376     return buf;
00377   }
00378   else
00379     m_flags = f;
00380 
00381   m_attributes.duplicate ((uchar *) buf, l);
00382   buf += sizeof(uchar) * l;
00383 
00384   uint lctx = 0;
00385   uint lfold = 0;
00386   uint lind = 0;
00387 
00388   memcpy((char *) &lctx, buf, sizeof(uint));
00389   buf += sizeof(uint);
00390 
00391   memcpy((char *) &lfold, buf, sizeof(uint));
00392   buf += sizeof(uint);
00393 
00394   memcpy((char *) &lind, buf, sizeof(uint));
00395   buf += sizeof(uint);
00396 
00397   m_ctx.duplicate ((short *) buf, lctx);
00398   buf += sizeof(short) * lctx;
00399 
00400   m_foldingList.duplicate ((uint *) buf, lfold);
00401   buf += sizeof(uint)*lfold;
00402 
00403   m_indentationDepth.duplicate ((unsigned short *) buf, lind);
00404   buf += sizeof(unsigned short) * lind;
00405 
00406   return buf;
00407 }
00408 
00409 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Home | KDE Accessibility Home | Description of Access Keys