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