00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00042 if (insLen == 0)
00043 return;
00044
00045
00046 uint oldTextLen = m_text.length();
00047 m_text.insert (pos, insText, insLen);
00048 uint textLen = m_text.length();
00049
00050
00051 m_attributes.resize (textLen);
00052
00053
00054 if (pos >= oldTextLen)
00055 {
00056 for (uint z = oldTextLen; z < pos; z++)
00057 m_attributes[z] = 0;
00058 }
00059
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
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
00079 if (delLen == 0)
00080 return;
00081
00082 uint textLen = m_text.length();
00083
00084 if (textLen == 0)
00085 return;
00086
00087 if (pos >= textLen)
00088 return;
00089
00090 if ((pos + delLen) > textLen)
00091 delLen = textLen - pos;
00092
00093
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 const uint len = m_text.length();
00113 const QChar *unicode = m_text.unicode();
00114
00115 for(uint i = pos; i < len; i++)
00116 {
00117 if(!unicode[i].isSpace())
00118 return i;
00119 }
00120
00121 return -1;
00122 }
00123
00124 int KateTextLine::previousNonSpaceChar(uint pos) const
00125 {
00126 const int len = m_text.length();
00127
00128 if (pos >= (uint)len)
00129 pos = len - 1;
00130
00131 const QChar *unicode = m_text.unicode();
00132
00133 for(int i = pos; i >= 0; i--)
00134 {
00135 if(!unicode[i].isSpace())
00136 return i;
00137 }
00138
00139 return -1;
00140 }
00141
00142 int KateTextLine::firstChar() const
00143 {
00144 return nextNonSpaceChar(0);
00145 }
00146
00147 int KateTextLine::lastChar() const
00148 {
00149 return previousNonSpaceChar(m_text.length() - 1);
00150 }
00151
00152 const QChar *KateTextLine::firstNonSpace() const
00153 {
00154 int first = firstChar();
00155 return (first > -1) ? ((QChar*)m_text.unicode())+first : m_text.unicode();
00156 }
00157
00158 uint KateTextLine::indentDepth (uint tabwidth) const
00159 {
00160 uint d = 0;
00161 const uint len = m_text.length();
00162 const QChar *unicode = m_text.unicode();
00163
00164 for(uint i = 0; i < len; i++)
00165 {
00166 if(unicode[i].isSpace())
00167 {
00168 if (unicode[i] == QChar('\t'))
00169 d += tabwidth - (d % tabwidth);
00170 else
00171 d++;
00172 }
00173 else
00174 return d;
00175 }
00176
00177 return d;
00178 }
00179
00180 bool KateTextLine::stringAtPos(uint pos, const QString& match) const
00181 {
00182 const uint len = m_text.length();
00183 const uint matchlen = match.length();
00184
00185 if ((pos+matchlen) > len)
00186 return false;
00187
00188
00189
00190 Q_ASSERT(pos < len);
00191
00192 const QChar *unicode = m_text.unicode();
00193 const QChar *matchUnicode = match.unicode();
00194
00195 for (uint i=0; i < matchlen; i++)
00196 if (unicode[i+pos] != matchUnicode[i])
00197 return false;
00198
00199 return true;
00200 }
00201
00202 bool KateTextLine::startingWith(const QString& match) const
00203 {
00204 const uint matchlen = match.length();
00205
00206 if (matchlen > m_text.length())
00207 return false;
00208
00209 const QChar *unicode = m_text.unicode();
00210 const QChar *matchUnicode = match.unicode();
00211
00212 for (uint i=0; i < matchlen; i++)
00213 if (unicode[i] != matchUnicode[i])
00214 return false;
00215
00216 return true;
00217 }
00218
00219 bool KateTextLine::endingWith(const QString& match) const
00220 {
00221 const uint matchlen = match.length();
00222
00223 if (matchlen > m_text.length())
00224 return false;
00225
00226 const QChar *unicode = m_text.unicode();
00227 const QChar *matchUnicode = match.unicode();
00228
00229 uint start = m_text.length() - matchlen;
00230 for (uint i=0; i < matchlen; i++)
00231 if (unicode[start+i] != matchUnicode[i])
00232 return false;
00233
00234 return true;
00235 }
00236
00237 int KateTextLine::cursorX(uint pos, uint tabChars) const
00238 {
00239 uint x = 0;
00240
00241 const uint n = kMin (pos, m_text.length());
00242 const QChar *unicode = m_text.unicode();
00243
00244 for ( uint z = 0; z < n; z++)
00245 {
00246 if (unicode[z] == QChar('\t'))
00247 x += tabChars - (x % tabChars);
00248 else
00249 x++;
00250 }
00251
00252 return x;
00253 }
00254
00255
00256 uint KateTextLine::lengthWithTabs (uint tabChars) const
00257 {
00258 uint x = 0;
00259 const uint len = m_text.length();
00260 const QChar *unicode = m_text.unicode();
00261
00262 for ( uint z = 0; z < len; z++)
00263 {
00264 if (unicode[z] == QChar('\t'))
00265 x += tabChars - (x % tabChars);
00266 else
00267 x++;
00268 }
00269
00270 return x;
00271 }
00272
00273 bool KateTextLine::searchText (uint startCol, const QString &text, uint *foundAtCol, uint *matchLen, bool casesensitive, bool backwards)
00274 {
00275 int index;
00276
00277 if (backwards)
00278 {
00279 int col = startCol;
00280 uint l = text.length();
00281
00282 if ( col == (int) m_text.length() ) ++startCol;
00283
00284 do {
00285 index = m_text.findRev( text, col, casesensitive );
00286 col--;
00287 } while ( col >= 0 && l + index >= startCol );
00288 }
00289 else
00290 index = m_text.find (text, startCol, casesensitive);
00291
00292 if (index > -1)
00293 {
00294 if (foundAtCol)
00295 (*foundAtCol) = index;
00296 if (matchLen)
00297 (*matchLen)=text.length();
00298 return true;
00299 }
00300
00301 return false;
00302 }
00303
00304 bool KateTextLine::searchText (uint startCol, const QRegExp ®exp, uint *foundAtCol, uint *matchLen, bool backwards)
00305 {
00306 int index;
00307
00308 if (backwards)
00309 {
00310 int col = startCol;
00311
00312
00313 if ( col == (int) m_text.length() ) ++startCol;
00314 do {
00315 index = regexp.searchRev (m_text, col);
00316 col--;
00317 } while ( col >= 0 && regexp.matchedLength() + index >= (int)startCol );
00318 }
00319 else
00320 index = regexp.search (m_text, startCol);
00321
00322 if (index > -1)
00323 {
00324 if (foundAtCol)
00325 (*foundAtCol) = index;
00326
00327 if (matchLen)
00328 (*matchLen)=regexp.matchedLength();
00329 return true;
00330 }
00331
00332 return false;
00333 }
00334
00335 char *KateTextLine::dump (char *buf, bool withHighlighting) const
00336 {
00337 uint l = m_text.length();
00338 char f = m_flags;
00339
00340 if (!withHighlighting)
00341 f = f | KateTextLine::flagNoOtherData;
00342
00343 memcpy(buf, (char *) &f, 1);
00344 buf += 1;
00345
00346 memcpy(buf, &l, sizeof(uint));
00347 buf += sizeof(uint);
00348
00349 memcpy(buf, (char *) m_text.unicode(), sizeof(QChar)*l);
00350 buf += sizeof(QChar) * l;
00351
00352 if (!withHighlighting)
00353 return buf;
00354
00355 memcpy(buf, (char *)m_attributes.data(), sizeof(uchar) * l);
00356 buf += sizeof (uchar) * l;
00357
00358 uint lctx = m_ctx.size();
00359 uint lfold = m_foldingList.size();
00360 uint lind = m_indentationDepth.size();
00361
00362 memcpy(buf, &lctx, sizeof(uint));
00363 buf += sizeof(uint);
00364
00365 memcpy(buf, &lfold, sizeof(uint));
00366 buf += sizeof(uint);
00367
00368 memcpy(buf, &lind, sizeof(uint));
00369 buf += sizeof(uint);
00370
00371 memcpy(buf, (char *)m_ctx.data(), sizeof(short) * lctx);
00372 buf += sizeof (short) * lctx;
00373
00374 memcpy(buf, (char *)m_foldingList.data(), sizeof(uint)*lfold);
00375 buf += sizeof (uint) * lfold;
00376
00377 memcpy(buf, (char *)m_indentationDepth.data(), sizeof(unsigned short) * lind);
00378 buf += sizeof (unsigned short) * lind;
00379
00380 return buf;
00381 }
00382
00383 char *KateTextLine::restore (char *buf)
00384 {
00385 uint l = 0;
00386 char f = 0;
00387
00388 memcpy((char *) &f, buf, 1);
00389 buf += 1;
00390
00391
00392 memcpy((char *) &l, buf, sizeof(uint));
00393 buf += sizeof(uint);
00394
00395
00396 m_text.setUnicode ((QChar *) buf, l);
00397 buf += sizeof(QChar) * l;
00398
00399
00400 if (f & KateTextLine::flagNoOtherData)
00401 {
00402 m_flags = 0;
00403
00404 if (f & KateTextLine::flagAutoWrapped)
00405 m_flags = m_flags | KateTextLine::flagAutoWrapped;
00406
00407
00408 m_attributes.fill (0, l);
00409
00410 return buf;
00411 }
00412 else
00413 m_flags = f;
00414
00415 m_attributes.duplicate ((uchar *) buf, l);
00416 buf += sizeof(uchar) * l;
00417
00418 uint lctx = 0;
00419 uint lfold = 0;
00420 uint lind = 0;
00421
00422 memcpy((char *) &lctx, buf, sizeof(uint));
00423 buf += sizeof(uint);
00424
00425 memcpy((char *) &lfold, buf, sizeof(uint));
00426 buf += sizeof(uint);
00427
00428 memcpy((char *) &lind, buf, sizeof(uint));
00429 buf += sizeof(uint);
00430
00431 m_ctx.duplicate ((short *) buf, lctx);
00432 buf += sizeof(short) * lctx;
00433
00434 m_foldingList.duplicate ((uint *) buf, lfold);
00435 buf += sizeof(uint)*lfold;
00436
00437 m_indentationDepth.duplicate ((unsigned short *) buf, lind);
00438 buf += sizeof(unsigned short) * lind;
00439
00440 return buf;
00441 }
00442
00443