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
00025 #include <qregexp.h>
00026 #include <kglobal.h>
00027
00028 TextLine::TextLine ()
00029 : m_flags(TextLine::flagVisible)
00030 {
00031 }
00032
00033 TextLine::~TextLine()
00034 {
00035 }
00036
00037 void TextLine::insertText (uint pos, uint insLen, const QChar *insText, uchar *insAttribs)
00038 {
00039
00040 if (insLen == 0)
00041 return;
00042
00043
00044 uint oldTextLen = m_text.length();
00045 m_text.insert (pos, insText, insLen);
00046 uint textLen = m_text.length();
00047
00048
00049 m_attributes.resize (textLen);
00050
00051
00052 if (pos >= oldTextLen)
00053 {
00054 for (uint z = oldTextLen; z < pos; z++)
00055 m_attributes[z] = 0;
00056 }
00057
00058 else if (oldTextLen > 0)
00059 {
00060 for (int z = oldTextLen -1; z >= (int) pos; z--)
00061 m_attributes[z+insLen] = m_attributes[z];
00062 }
00063
00064
00065 for (uint z = 0; z < insLen; z++)
00066 {
00067 if (insAttribs == 0)
00068 m_attributes[z+pos] = 0;
00069 else
00070 m_attributes[z+pos] = insAttribs[z];
00071 }
00072 }
00073
00074 void TextLine::removeText (uint pos, uint delLen)
00075 {
00076
00077 if (delLen == 0)
00078 return;
00079
00080 uint textLen = m_text.length();
00081
00082 if (textLen == 0)
00083 return;
00084
00085 if (pos >= textLen)
00086 return;
00087
00088 if ((pos + delLen) > textLen)
00089 delLen = textLen - pos;
00090
00091
00092 for (uint z = pos; z < textLen - delLen; z++)
00093 m_attributes[z] = m_attributes[z+delLen];
00094
00095 m_text.remove (pos, delLen);
00096 textLen = m_text.length ();
00097 m_attributes.resize (textLen);
00098 }
00099
00100 void TextLine::append(const QChar *s, uint l)
00101 {
00102 insertText (m_text.length(), l, s, 0);
00103 }
00104
00105 void TextLine::truncate(uint newLen)
00106 {
00107 if (newLen < m_text.length())
00108 {
00109 m_text.truncate (newLen);
00110 m_attributes.truncate (newLen);
00111 }
00112 }
00113
00114 int TextLine::nextNonSpaceChar(uint pos) const
00115 {
00116 for(int i = pos; i < (int)m_text.length(); i++)
00117 {
00118 if(!m_text[i].isSpace())
00119 return i;
00120 }
00121
00122 return -1;
00123 }
00124
00125 int TextLine::previousNonSpaceChar(uint pos) const
00126 {
00127 if (pos >= m_text.length())
00128 pos = m_text.length() - 1;
00129
00130 for(int i = pos; i >= 0; i--)
00131 {
00132 if(!m_text[i].isSpace())
00133 return i;
00134 }
00135
00136 return -1;
00137 }
00138
00139 int TextLine::firstChar() const
00140 {
00141 return nextNonSpaceChar(0);
00142 }
00143
00144 int TextLine::lastChar() const
00145 {
00146 return previousNonSpaceChar(m_text.length() - 1);
00147 }
00148
00149 QString TextLine::withoutTrailingSpaces()
00150 {
00151 return m_text.left (lastChar() + 1);
00152 }
00153
00154 const QChar *TextLine::firstNonSpace() const
00155 {
00156 int first = firstChar();
00157 return (first > -1) ? ((QChar*)m_text.unicode())+first : m_text.unicode();
00158 }
00159
00160 uint TextLine::indentDepth (uint tabwidth) const
00161 {
00162 uint d = 0;
00163
00164 for(uint i = 0; i < m_text.length(); i++)
00165 {
00166 if(m_text[i].isSpace())
00167 {
00168 if (m_text[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 TextLine::stringAtPos(uint pos, const QString& match) const
00181 {
00182 return (m_text.mid(pos, match.length()) == match);
00183 }
00184
00185 bool TextLine::startingWith(const QString& match) const
00186 {
00187 return (m_text.left(match.length()) == match);
00188 }
00189
00190 bool TextLine::endingWith(const QString& match) const
00191 {
00192 return (m_text.right(match.length()) == match);
00193 }
00194
00195 int TextLine::cursorX(uint pos, uint tabChars) const
00196 {
00197 uint x = 0;
00198
00199 for (uint z = 0; z < kMin (pos, m_text.length()); z++)
00200 {
00201 if (m_text[z] == QChar('\t'))
00202 x += tabChars - (x % tabChars);
00203 else
00204 x++;
00205 }
00206
00207 return x;
00208 }
00209
00210 void TextLine::setAttribs(uchar attribute, uint start, uint end)
00211 {
00212 if (end > m_text.length())
00213 end = m_text.length();
00214
00215 for (uint z = start; z < end; z++)
00216 m_attributes[z] = attribute;
00217 }
00218
00219 bool TextLine::searchText (uint startCol, const QString &text, uint *foundAtCol, uint *matchLen, bool casesensitive, bool backwards)
00220 {
00221 int index;
00222
00223 if (backwards)
00224 index = m_text.findRev (text, startCol, casesensitive);
00225 else
00226 index = m_text.find (text, startCol, casesensitive);
00227
00228 if (index > -1)
00229 {
00230 (*foundAtCol) = index;
00231 (*matchLen)=text.length();
00232 return true;
00233 }
00234
00235 return false;
00236 }
00237
00238 bool TextLine::searchText (uint startCol, const QRegExp ®exp, uint *foundAtCol, uint *matchLen, bool backwards)
00239 {
00240 int index;
00241
00242 if (backwards)
00243 index = regexp.searchRev (m_text, startCol);
00244 else
00245 index = regexp.search (m_text, startCol);
00246
00247 if (index > -1)
00248 {
00249 (*foundAtCol) = index;
00250 (*matchLen)=regexp.matchedLength();
00251 return true;
00252 }
00253
00254 return false;
00255 }
00256
00257 uint TextLine::dumpSize () const
00258 {
00259 uint attributesLen = 0;
00260
00261 if ( ! m_attributes.isEmpty())
00262 {
00263 attributesLen = 1;
00264
00265 uint lastAttrib = m_attributes[0];
00266
00267 for (uint z=0; z < m_attributes.size(); z++)
00268 {
00269 if (m_attributes[z] != lastAttrib)
00270 {
00271 attributesLen++;
00272 lastAttrib = m_attributes[z];
00273 }
00274 }
00275 }
00276
00277 return (1 + 5*sizeof(uint)) + (m_text.length()*sizeof(QChar)) + (attributesLen * (sizeof(uchar) + sizeof(uint))) + (m_ctx.size() * sizeof(short)) + (m_foldingList.size() * sizeof(signed char) + (m_indentationDepth.size() * sizeof(unsigned short)));
00278 }
00279
00280 char *TextLine::dump (char *buf) const
00281 {
00282 uint l = m_text.length();
00283 uint lctx = m_ctx.size();
00284 uint lfold = m_foldingList.size();
00285 uint lind = m_indentationDepth.size();
00286
00287 memcpy(buf, &l, sizeof(uint));
00288 buf += sizeof(uint);
00289
00290 memcpy(buf, (char *) m_text.unicode(), sizeof(QChar)*l);
00291 buf += sizeof(QChar)*l;
00292
00293 memcpy(buf, (char *) &m_flags, 1);
00294 buf += 1;
00295
00296 char *attribLenPos = buf;
00297 buf += sizeof(uint);
00298
00299 memcpy(buf, &lctx, sizeof(uint));
00300 buf += sizeof(uint);
00301
00302 memcpy(buf, &lfold, sizeof(uint));
00303 buf += sizeof(uint);
00304
00305 memcpy(buf, &lind, sizeof(uint));
00306 buf += sizeof(uint);
00307
00308
00309
00310 uint attributesLen = 0;
00311
00312 if ( ! m_attributes.isEmpty() )
00313 {
00314 attributesLen = 1;
00315
00316 uchar lastAttrib = m_attributes[0];
00317 uint lastStart = 0;
00318 uint length = 0;
00319
00320 for (uint z=0; z < m_attributes.size(); z++)
00321 {
00322 if (m_attributes[z] != lastAttrib)
00323 {
00324 length = z - lastStart;
00325
00326 memcpy(buf, &lastAttrib, sizeof(uchar));
00327 buf += sizeof(uchar);
00328
00329 memcpy(buf, &length, sizeof(uint));
00330 buf += sizeof(uint);
00331
00332 lastStart = z;
00333 lastAttrib = m_attributes[z];
00334
00335 attributesLen ++;
00336 }
00337 }
00338
00339 length = m_attributes.size() - lastStart;
00340
00341 memcpy(buf, &lastAttrib, sizeof(uchar));
00342 buf += sizeof(uchar);
00343
00344 memcpy(buf, &length, sizeof(uint));
00345 buf += sizeof(uint);
00346 }
00347
00348 memcpy(attribLenPos, &attributesLen, sizeof(uint));
00349
00350
00351
00352 memcpy(buf, (char *)m_ctx.data(), sizeof(short) * lctx);
00353 buf += sizeof (short) * lctx;
00354
00355 memcpy(buf, (char *)m_foldingList.data(), lfold);
00356 buf += sizeof (signed char) * lfold;
00357
00358 memcpy(buf, (char *)m_indentationDepth.data(), sizeof(unsigned short) * lind);
00359 buf += sizeof (unsigned short) * lind;
00360
00361 return buf;
00362 }
00363
00364 char *TextLine::restore (char *buf)
00365 {
00366 uint l = 0;
00367 uint lattrib = 0;
00368 uint lctx = 0;
00369 uint lfold = 0;
00370 uint lind = 0;
00371
00372
00373 memcpy((char *) &l, buf, sizeof(uint));
00374 buf += sizeof(uint);
00375
00376
00377 m_text.setUnicode ((QChar *) buf, l);
00378 buf += sizeof(QChar)*l;
00379
00380 m_attributes.resize (l);
00381
00382 memcpy((char *) &m_flags, buf, 1);
00383 buf += 1;
00384
00385
00386 if (m_flags == TextLine::flagNoOtherData)
00387 {
00388 m_flags = TextLine::flagVisible;
00389 m_attributes.fill (0);
00390
00391 return buf;
00392 }
00393
00394 memcpy((char *) &lattrib, buf, sizeof(uint));
00395 buf += sizeof(uint);
00396
00397 memcpy((char *) &lctx, buf, sizeof(uint));
00398 buf += sizeof(uint);
00399
00400 memcpy((char *) &lfold, buf, sizeof(uint));
00401 buf += sizeof(uint);
00402
00403 memcpy((char *) &lind, buf, sizeof(uint));
00404 buf += sizeof(uint);
00405
00406
00407
00408 uchar *attr = m_attributes.data();
00409
00410 uchar attrib = 0;
00411 uint length = 0;
00412 uint pos = 0;
00413
00414 for (uint z=0; z < lattrib; z++)
00415 {
00416 if (pos >= m_attributes.size())
00417 break;
00418
00419 memcpy((char *) &attrib, buf, sizeof(uchar));
00420 buf += sizeof(uchar);
00421
00422 memcpy((char *) &length, buf, sizeof(uint));
00423 buf += sizeof(uint);
00424
00425 if ((pos+length) > m_attributes.size())
00426 length = m_attributes.size() - pos;
00427
00428 memset (attr, attrib, length);
00429
00430 pos += length;
00431 attr += length;
00432 }
00433
00434
00435
00436 m_ctx.duplicate ((short *) buf, lctx);
00437 buf += sizeof(short) * lctx;
00438
00439 m_foldingList.duplicate ((signed char *) buf, lfold);
00440 buf += lfold;
00441
00442 m_indentationDepth.duplicate ((unsigned short *) buf, lind);
00443 buf += sizeof(unsigned short) * lind;
00444
00445 return buf;
00446 }
00447
00448