00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "katebuffer.h"
00022 #include "katebuffer.moc"
00023
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <unistd.h>
00027 #include <stdlib.h>
00028
00029 #include "katedocument.h"
00030 #include "katehighlight.h"
00031 #include "kateconfig.h"
00032 #include "kateglobal.h"
00033 #include "kateautoindent.h"
00034
00035 #include <kdebug.h>
00036 #include <kglobal.h>
00037 #include <kcharsets.h>
00038 #include <kencodingdetector.h>
00039
00040 #include <QtCore/QFile>
00041 #include <QtCore/QTextStream>
00042 #include <QtCore/QTimer>
00043 #include <QtCore/QTextCodec>
00044 #include <QtCore/QDate>
00045
00046 #include <limits.h>
00047
00053 static const qint64 KATE_FILE_LOADER_BS = 256 * 1024;
00054
00060 static const int KATE_HL_LOOKAHEAD = 64;
00061
00065 static const int KATE_MAX_DYNAMIC_CONTEXTS = 512;
00066
00067 class KateFileLoader: private KEncodingDetector
00068 {
00069 public:
00070 KateFileLoader (const QString &filename, QTextCodec *codec, bool removeTrailingSpaces, KEncodingDetector::AutoDetectScript script)
00071 : KEncodingDetector(codec,
00072 script==KEncodingDetector::None?KEncodingDetector::UserChosenEncoding:KEncodingDetector::DefaultEncoding,
00073 script)
00074 , m_eof (false)
00075 , m_lastWasEndOfLine (true)
00076 , m_lastWasR (false)
00077 , m_binary (false)
00078 , m_removeTrailingSpaces (removeTrailingSpaces)
00079 , m_utf8Borked (false)
00080 , m_position (0)
00081 , m_lastLineStart (0)
00082 , m_eol (-1)
00083 , m_file (filename)
00084 , m_buffer (qMin (m_file.size() == 0 ? KATE_FILE_LOADER_BS : m_file.size(), KATE_FILE_LOADER_BS), 0)
00085 {
00086 kDebug (13020) << "OPEN USES ENCODING: " << codec->name();
00087 }
00088
00089 ~KateFileLoader ()
00090 {
00091
00092 }
00093
00097 bool open ()
00098 {
00099 if (m_file.open (QIODevice::ReadOnly))
00100 {
00101 int c = m_file.read (m_buffer.data(), m_buffer.size());
00102
00103 if (c > 0)
00104 {
00105
00106
00107 analyze(m_buffer.data(), c);
00108 m_utf8Borked=errorsIfUtf8(m_buffer.data(), c);
00109 m_binary=processNull(m_buffer.data(), c);
00110 m_text = decoder()->toUnicode(m_buffer, c);
00111 }
00112
00113 m_eof = (c == -1) || (c == 0);
00114
00115 for (int i=0; i < m_text.length(); i++)
00116 {
00117 if (m_text[i] == '\n')
00118 {
00119 m_eol = KateDocumentConfig::eolUnix;
00120 break;
00121 }
00122 else if ((m_text[i] == '\r'))
00123 {
00124 if (((i+1) < m_text.length()) && (m_text[i+1] == '\n'))
00125 {
00126 m_eol = KateDocumentConfig::eolDos;
00127 break;
00128 }
00129 else
00130 {
00131 m_eol = KateDocumentConfig::eolMac;
00132 break;
00133 }
00134 }
00135 }
00136
00137 return true;
00138 }
00139
00140 return false;
00141 }
00142
00143 inline const char* actualEncoding () const { return encoding(); }
00144
00145
00146 inline bool eof () const { return m_eof && !m_lastWasEndOfLine && (m_lastLineStart == m_text.length()); }
00147
00148
00149 inline int eol () const { return m_eol; }
00150
00151
00152 inline bool binary () const { return m_binary; }
00153
00154
00155 inline bool brokenUTF8 () const { return m_utf8Borked; }
00156
00157
00158 inline bool removeTrailingSpaces () const { return m_removeTrailingSpaces; }
00159
00160
00161 inline const QChar *unicode () const { return m_text.unicode(); }
00162
00163
00164 void readLine (int &offset, int &length)
00165 {
00166 length = 0;
00167 offset = 0;
00168
00169 while (m_position <= m_text.length())
00170 {
00171 if (m_position == m_text.length())
00172 {
00173
00174 if (!m_eof)
00175 {
00176 int c = m_file.read (m_buffer.data(), m_buffer.size());
00177
00178 int readString = 0;
00179 if (c > 0)
00180 {
00181 m_binary=processNull(m_buffer.data(), c)||m_binary;
00182 m_utf8Borked=m_utf8Borked||errorsIfUtf8(m_buffer.data(), c);
00183
00184 QString str (decoder()->toUnicode (m_buffer.data(), c));
00185 readString = str.length();
00186
00187 m_text = m_text.mid (m_lastLineStart, m_position-m_lastLineStart)
00188 + str;
00189 }
00190 else
00191 m_text = m_text.mid (m_lastLineStart, m_position-m_lastLineStart);
00192
00193
00194 m_eof = (c == -1) || (c == 0);
00195
00196
00197 m_position -= m_lastLineStart;
00198 m_lastLineStart = 0;
00199 }
00200
00201
00202 if (m_eof && (m_position == m_text.length()))
00203 {
00204 m_lastWasEndOfLine = false;
00205
00206
00207 offset = m_lastLineStart;
00208 length = m_position-m_lastLineStart;
00209
00210 m_lastLineStart = m_position;
00211
00212 return;
00213 }
00214 }
00215
00216 if (m_text[m_position] == '\n')
00217 {
00218 m_lastWasEndOfLine = true;
00219
00220 if (m_lastWasR)
00221 {
00222 m_lastLineStart++;
00223 m_lastWasR = false;
00224 }
00225 else
00226 {
00227
00228 offset = m_lastLineStart;
00229 length = m_position-m_lastLineStart;
00230
00231 m_lastLineStart = m_position+1;
00232 m_position++;
00233
00234 return;
00235 }
00236 }
00237 else if (m_text[m_position] == '\r')
00238 {
00239 m_lastWasEndOfLine = true;
00240 m_lastWasR = true;
00241
00242
00243 offset = m_lastLineStart;
00244 length = m_position-m_lastLineStart;
00245
00246 m_lastLineStart = m_position+1;
00247 m_position++;
00248
00249 return;
00250 }
00251 else
00252 {
00253 m_lastWasEndOfLine = false;
00254 m_lastWasR = false;
00255 }
00256
00257 m_position++;
00258 }
00259 }
00260
00261
00262 private:
00263 bool m_eof;
00264 bool m_lastWasEndOfLine;
00265 bool m_lastWasR;
00266 bool m_binary;
00267 bool m_removeTrailingSpaces;
00268 bool m_utf8Borked;
00269 int m_position;
00270 int m_lastLineStart;
00271 int m_eol;
00272 QFile m_file;
00273 QByteArray m_buffer;
00274 QString m_text;
00275 };
00276
00280 KateBuffer::KateBuffer(KateDocument *doc)
00281 : QObject (doc),
00282 editSessionNumber (0),
00283 editIsRunning (false),
00284 editTagLineStart (0xffffffff),
00285 editTagLineEnd (0),
00286 editTagLineFrom (false),
00287 editChangesDone (false),
00288 m_doc (doc),
00289 m_binary (false),
00290 m_brokenUTF8 (false),
00291 m_highlight (0),
00292 m_regionTree (this),
00293 m_tabWidth (8),
00294 m_lineHighlightedMax (0),
00295 m_lineHighlighted (0),
00296 m_maxDynamicContexts (KATE_MAX_DYNAMIC_CONTEXTS)
00297 {
00298 clear();
00299 }
00300
00304 KateBuffer::~KateBuffer()
00305 {
00306
00307 if (m_highlight)
00308 m_highlight->release();
00309 }
00310
00311 void KateBuffer::editStart ()
00312 {
00313 editSessionNumber++;
00314
00315 if (editSessionNumber > 1)
00316 return;
00317
00318 editIsRunning = true;
00319
00320 editTagLineStart = INT_MAX;
00321 editTagLineEnd = 0;
00322 editTagLineFrom = false;
00323
00324 editChangesDone = false;
00325 }
00326
00327 void KateBuffer::editEnd ()
00328 {
00329 if (editSessionNumber == 0)
00330 return;
00331
00332 editSessionNumber--;
00333
00334 if (editSessionNumber > 0)
00335 return;
00336
00337 if (editChangesDone)
00338 {
00339
00340 if (m_highlight && editTagLineStart <= editTagLineEnd && editTagLineEnd <= m_lineHighlighted)
00341 {
00342
00343 ++editTagLineEnd;
00344
00345
00346 if (editTagLineStart > 0)
00347 --editTagLineStart;
00348
00349 bool needContinue = doHighlight (
00350 editTagLineStart,
00351 editTagLineEnd,
00352 true);
00353
00354 editTagLineStart = editTagLineEnd;
00355
00356 if (needContinue)
00357 m_lineHighlighted = editTagLineStart;
00358
00359 if (editTagLineStart > m_lineHighlightedMax)
00360 m_lineHighlightedMax = editTagLineStart;
00361 }
00362 else if (editTagLineStart < m_lineHighlightedMax)
00363 m_lineHighlightedMax = editTagLineStart;
00364 }
00365
00366 editIsRunning = false;
00367 }
00368
00369 void KateBuffer::clear()
00370 {
00371 m_regionTree.clear();
00372
00373
00374 m_lines.clear ();
00375 KateTextLine::Ptr textLine (new KateTextLine ());
00376 m_lines.push_back (textLine);
00377
00378
00379 m_binary = false;
00380 m_brokenUTF8 = false;
00381
00382 m_lineHighlightedMax = 0;
00383 m_lineHighlighted = 0;
00384 }
00385
00386 bool KateBuffer::openFile (const QString &m_file)
00387 {
00388 QTime t;
00389 t.start();
00390
00391 KateFileLoader file (m_file, m_doc->config()->codec(), m_doc->config()->configFlags() & KateDocumentConfig::cfRemoveSpaces, m_doc->scriptForEncodingAutoDetection());
00392
00393 bool ok = false;
00394 struct stat sbuf;
00395 if (stat(QFile::encodeName(m_file), &sbuf) == 0)
00396 {
00397 if (S_ISREG(sbuf.st_mode) && file.open())
00398 ok = true;
00399 }
00400
00401 if (!ok)
00402 {
00403 clear();
00404 return false;
00405 }
00406
00407 m_doc->config()->setEncoding(file.actualEncoding());
00408
00409
00410 if (m_doc->config()->allowEolDetection() && (file.eol() != -1))
00411 m_doc->config()->setEol (file.eol());
00412
00413
00414 clear ();
00415 m_lines.clear ();
00416
00417
00418 while ( !file.eof() )
00419 {
00420 int offset = 0, length = 0;
00421 file.readLine(offset, length);
00422 const QChar *unicodeData = file.unicode () + offset;
00423
00424
00425 if ( file.removeTrailingSpaces() )
00426 {
00427 while (length > 0)
00428 {
00429 if (unicodeData[length-1].isSpace())
00430 --length;
00431 else
00432 break;
00433 }
00434 }
00435
00436 KateTextLine::Ptr textLine (new KateTextLine (unicodeData, length));
00437 m_lines.push_back (textLine);
00438 }
00439
00440
00441 if (m_lines.isEmpty())
00442 {
00443 KateTextLine::Ptr textLine (new KateTextLine ());
00444 m_lines.push_back (textLine);
00445 }
00446
00447
00448 m_regionTree.fixRoot (m_lines.size());
00449
00450
00451 m_binary = file.binary ();
00452
00453
00454 m_brokenUTF8 = file.brokenUTF8();
00455
00456 kDebug (13020) << "Broken UTF-8: " << m_brokenUTF8;
00457
00458 kDebug (13020) << "LOADING DONE " << t.elapsed();
00459
00460 return true;
00461 }
00462
00463 bool KateBuffer::canEncode ()
00464 {
00465 QTextCodec *codec = m_doc->config()->codec();
00466
00467 kDebug(13020) << "ENC NAME: " << codec->name();
00468
00469
00470 if ((QString(codec->name()) == "UTF-8") || (QString(codec->name()) == "ISO-10646-UCS-2"))
00471 return true;
00472
00473 for (int i=0; i < m_lines.size(); i++)
00474 {
00475 if (!codec->canEncode (plainLine(i)->string()))
00476 {
00477 kDebug(13020) << "STRING LINE: " << plainLine(i)->string();
00478 kDebug(13020) << "ENC WORKING: FALSE";
00479
00480 return false;
00481 }
00482 }
00483
00484 return true;
00485 }
00486
00487 bool KateBuffer::saveFile (const QString &m_file)
00488 {
00489 QFile file (m_file);
00490 QTextStream stream (&file);
00491
00492 if ( !file.open( QIODevice::WriteOnly ) )
00493 {
00494 return false;
00495 }
00496
00497 QTextCodec *codec = m_doc->config()->codec();
00498
00499
00500 stream.setCodec(QTextCodec::codecForName("UTF-16"));
00501
00502
00503 stream.setCodec(codec);
00504
00505
00506 QString eol = m_doc->config()->eolString ();
00507
00508
00509 bool removeTrailingSpaces = m_doc->config()->configFlags() & KateDocumentConfig::cfRemoveSpaces;
00510
00511
00512 for (int i=0; i < m_lines.size(); i++)
00513 {
00514 KateTextLine::Ptr textline = plainLine(i);
00515
00516
00517 if (removeTrailingSpaces)
00518 {
00519 int lastChar = textline->lastChar();
00520
00521 if (lastChar > -1)
00522 {
00523 stream << textline->string().left(lastChar+1);
00524 }
00525 }
00526 else
00527 stream << textline->string();
00528
00529 if ((i+1) < m_lines.size())
00530 stream << eol;
00531 }
00532
00533 file.close ();
00534
00535 return (file.error() == QFile::NoError);
00536 }
00537
00538 KateTextLine::Ptr KateBuffer::line (int line)
00539 {
00540
00541 if (line < 0 || line >= m_lines.size())
00542 return KateTextLine::Ptr();
00543
00544
00545 if (line < m_lineHighlighted)
00546 return m_lines[line];
00547
00548
00549 int end = qMin(line + KATE_HL_LOOKAHEAD, m_lines.size()-1);
00550
00551 doHighlight ( m_lineHighlighted, end, false );
00552
00553 m_lineHighlighted = end;
00554
00555
00556 if (m_lineHighlighted > m_lineHighlightedMax)
00557 m_lineHighlightedMax = m_lineHighlighted;
00558
00559 return m_lines[line];
00560 }
00561
00562 void KateBuffer::changeLine(int i)
00563 {
00564 if (i < 0 || i >= m_lines.size())
00565 return;
00566
00567
00568 editChangesDone = true;
00569
00570
00571 if (i < editTagLineStart)
00572 editTagLineStart = i;
00573
00574 if (i > editTagLineEnd)
00575 editTagLineEnd = i;
00576 }
00577
00578 void KateBuffer::insertLine(int i, KateTextLine::Ptr line)
00579 {
00580 if (i < 0 || i > m_lines.size())
00581 return;
00582
00583 m_lines.insert (i, line);
00584
00585 if (m_lineHighlightedMax > i)
00586 m_lineHighlightedMax++;
00587
00588 if (m_lineHighlighted > i)
00589 m_lineHighlighted++;
00590
00591
00592 editChangesDone = true;
00593
00594
00595 if (i < editTagLineStart)
00596 editTagLineStart = i;
00597
00598 if (i <= editTagLineEnd)
00599 editTagLineEnd++;
00600
00601 if (i > editTagLineEnd)
00602 editTagLineEnd = i;
00603
00604
00605 editTagLineFrom = true;
00606
00607 m_regionTree.lineHasBeenInserted (i);
00608 }
00609
00610 void KateBuffer::removeLine(int i)
00611 {
00612 if (i < 0 || i >= m_lines.size())
00613 return;
00614
00615 m_lines.remove (i);
00616
00617 if (m_lineHighlightedMax > i)
00618 m_lineHighlightedMax--;
00619
00620 if (m_lineHighlighted > i)
00621 m_lineHighlighted--;
00622
00623
00624 editChangesDone = true;
00625
00626
00627 if (i < editTagLineStart)
00628 editTagLineStart = i;
00629
00630 if (i < editTagLineEnd)
00631 editTagLineEnd--;
00632
00633 if (i > editTagLineEnd)
00634 editTagLineEnd = i;
00635
00636
00637
00638 if (editTagLineEnd >= m_lines.size())
00639 editTagLineEnd = m_lines.size() - 1;
00640
00641 if (editTagLineStart > editTagLineEnd)
00642 editTagLineStart = editTagLineEnd;
00643
00644
00645 editTagLineFrom = true;
00646
00647 m_regionTree.lineHasBeenRemoved (i);
00648 }
00649
00650 void KateBuffer::setTabWidth (int w)
00651 {
00652 if ((m_tabWidth != w) && (m_tabWidth > 0))
00653 {
00654 m_tabWidth = w;
00655
00656 if (m_highlight && m_highlight->foldingIndentationSensitive())
00657 invalidateHighlighting();
00658 }
00659 }
00660
00661 void KateBuffer::setHighlight(int hlMode)
00662 {
00663 KateHighlighting *h = KateHlManager::self()->getHl(hlMode);
00664
00665
00666 if (h != m_highlight)
00667 {
00668 bool invalidate = !h->noHighlighting();
00669
00670 if (m_highlight)
00671 {
00672 m_highlight->release();
00673 invalidate = true;
00674 }
00675
00676 h->use();
00677
00678
00679 m_regionTree.clear();
00680 m_regionTree.fixRoot(m_lines.size());
00681
00682
00683 if (!h->indentation().isEmpty())
00684 m_doc->config()->setIndentationMode (h->indentation());
00685
00686 m_highlight = h;
00687
00688 if (invalidate)
00689 invalidateHighlighting();
00690
00691
00692
00693 m_doc->bufferHlChanged ();
00694 }
00695 }
00696
00697 void KateBuffer::invalidateHighlighting()
00698 {
00699 m_lineHighlightedMax = 0;
00700 m_lineHighlighted = 0;
00701 }
00702
00703
00704 void KateBuffer::updatePreviousNotEmptyLine(int current_line,bool addindent,int deindent)
00705 {
00706 KateTextLine::Ptr textLine;
00707 do {
00708 if (current_line == 0) return;
00709
00710 --current_line;
00711
00712 textLine = m_lines[current_line];
00713 } while (textLine->firstChar()==-1);
00714
00715 kDebug(13020)<<"updatePreviousNotEmptyLine: updating line:"<<current_line;
00716 QVector<int> foldingList=textLine->foldingListArray();
00717 while ( (foldingList.size()>0) && ( abs(foldingList[foldingList.size()-2])==1)) {
00718 foldingList.resize(foldingList.size()-2);
00719 }
00720 addIndentBasedFoldingInformation(foldingList,textLine->length(),addindent,deindent);
00721 textLine->setFoldingList(foldingList);
00722
00723 bool retVal_folding = false;
00724 m_regionTree.updateLine (current_line, &foldingList, &retVal_folding, true,false);
00725
00726
00727 }
00728
00729 void KateBuffer::addIndentBasedFoldingInformation(QVector<int> &foldingList,int linelength,bool addindent,int deindent)
00730 {
00731 if (addindent) {
00732
00733 kDebug(13020)<<"adding ident";
00734 foldingList.resize (foldingList.size() + 2);
00735 foldingList[foldingList.size()-2] = 1;
00736 foldingList[foldingList.size()-1] = 0;
00737 }
00738 kDebug(13020)<<"DEINDENT: "<<deindent;
00739 if (deindent > 0)
00740 {
00741
00742
00743
00744 for (int z=0;z<deindent;z++) {
00745
00746 foldingList.prepend(linelength+1);
00747 foldingList.prepend(-1);
00748 }
00749
00750
00751
00752
00753
00754
00755 }
00756 }
00757
00758
00759 bool KateBuffer::isEmptyLine(KateTextLine::Ptr textline)
00760 {
00761 QLinkedList<QRegExp> l;
00762 l=m_highlight->emptyLines(textline->attribute(0));
00763 kDebug(13020)<<"trying to find empty line data";
00764 if (l.isEmpty()) return false;
00765 QString txt=textline->string();
00766 kDebug(13020)<<"checking empty line regexp";
00767 foreach(const QRegExp &re,l) {
00768 if (re.exactMatch(txt)) return true;
00769 }
00770 kDebug(13020)<<"no matches";
00771 return false;
00772 }
00773
00774 bool KateBuffer::doHighlight (int startLine, int endLine, bool invalidate)
00775 {
00776
00777 if (!m_highlight)
00778 return false;
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 if (KateHlManager::self()->countDynamicCtxs() >= m_maxDynamicContexts)
00794 {
00795 {
00796 if (KateHlManager::self()->resetDynamicCtxs())
00797 {
00798 kDebug (13020) << "HL invalidated - too many dynamic contexts ( >= " << m_maxDynamicContexts << ")";
00799
00800
00801 KateHlManager::self()->setForceNoDCReset(true);
00802
00803 for (int i=0; i < KateGlobal::self()->kateDocuments().size(); ++i)
00804 (KateGlobal::self()->kateDocuments())[i]->makeAttribs();
00805
00806
00807
00808 doHighlight ( m_lineHighlighted, endLine, false );
00809 m_lineHighlighted = endLine;
00810
00811 KateHlManager::self()->setForceNoDCReset(false);
00812
00813 return false;
00814 }
00815 else
00816 {
00817 m_maxDynamicContexts *= 2;
00818 kDebug (13020) << "New dynamic contexts limit: " << m_maxDynamicContexts;
00819 }
00820 }
00821 }
00822
00823
00824 KateTextLine::Ptr prevLine;
00825
00826 if (startLine >= 1)
00827 prevLine = m_lines[startLine-1];
00828 else
00829 prevLine = new KateTextLine ();
00830
00831
00832 bool codeFoldingUpdate = false;
00833
00834
00835 int current_line = startLine;
00836
00837
00838 bool stillcontinue=false;
00839 bool indentContinueWhitespace=false;
00840 bool indentContinueNextWhitespace=false;
00841
00842
00843 while ( (current_line < m_lines.size()) && (stillcontinue || (current_line <= endLine)) )
00844 {
00845
00846 KateTextLine::Ptr textLine = m_lines[current_line];
00847
00848 QVector<int> foldingList;
00849 bool ctxChanged = false;
00850
00851 m_highlight->doHighlight (prevLine.data(), textLine.data(), foldingList, ctxChanged);
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 bool indentChanged = false;
00868 if (m_highlight->foldingIndentationSensitive())
00869 {
00870
00871 QVector<unsigned short> indentDepth (prevLine->indentationDepthArray());
00872
00873
00874 int iDepth = textLine->indentDepth(m_tabWidth);
00875 if (current_line==0)
00876 {
00877 indentDepth.resize (1);
00878 indentDepth[0] = iDepth;
00879 }
00880
00881 textLine->setNoIndentBasedFoldingAtStart(prevLine->noIndentBasedFolding());
00882
00883 kDebug(13020)<<"current_line:"<<current_line<<" textLine->noIndentBasedFoldingAtStart"<<textLine->noIndentBasedFoldingAtStart();
00884 if ( (textLine->firstChar() == -1) || textLine->noIndentBasedFoldingAtStart() || isEmptyLine(textLine) )
00885 {
00886
00887 if (!prevLine->indentationDepthArray().isEmpty())
00888 {
00889 iDepth = (prevLine->indentationDepthArray())[prevLine->indentationDepthArray().size()-1];
00890 kDebug(13020)<<"reusing old depth as current";
00891 }
00892 else
00893 {
00894 iDepth = prevLine->indentDepth(m_tabWidth);
00895 kDebug(13020)<<"creating indentdepth for previous line";
00896 }
00897 }
00898
00899 kDebug(13020)<<"iDepth:"<<iDepth;
00900
00901
00902
00903 int nextLineIndentation = 0;
00904 bool nextLineIndentationValid=true;
00905 indentContinueNextWhitespace=false;
00906 if ((current_line+1) < m_lines.size())
00907 {
00908 if ( (m_lines[current_line+1]->firstChar() == -1) || isEmptyLine(m_lines[current_line+1]) )
00909 {
00910 nextLineIndentation = iDepth;
00911 indentContinueNextWhitespace=true;
00912 }
00913 else
00914 nextLineIndentation = m_lines[current_line+1]->indentDepth(m_tabWidth);
00915 }
00916 else
00917 {
00918 nextLineIndentationValid=false;
00919 }
00920
00921 if (!textLine->noIndentBasedFoldingAtStart()) {
00922
00923 if ((iDepth > 0) && (indentDepth.isEmpty() || (indentDepth[indentDepth.size()-1] < iDepth)))
00924 {
00925 kDebug(13020)<<"adding depth to \"stack\":"<<iDepth;
00926 indentDepth.append (iDepth);
00927 } else {
00928 if (!indentDepth.isEmpty())
00929 {
00930 for (int z=indentDepth.size()-1; z > -1; z--)
00931 if (indentDepth[z]>iDepth)
00932 indentDepth.resize(z);
00933 if ((iDepth > 0) && (indentDepth.isEmpty() || (indentDepth[indentDepth.size()-1] < iDepth)))
00934 {
00935 kDebug(13020)<<"adding depth to \"stack\":"<<iDepth;
00936 indentDepth.append (iDepth);
00937 if (prevLine->firstChar()==-1) {
00938
00939 }
00940 }
00941 }
00942 }
00943 }
00944
00945 if (!textLine->noIndentBasedFolding())
00946 {
00947 if (nextLineIndentationValid)
00948 {
00949
00950 {
00951 kDebug(13020)<<"nextLineIndentation:"<<nextLineIndentation;
00952 bool addindent=false;
00953 int deindent=0;
00954 if (!indentDepth.isEmpty())
00955 kDebug(13020)<<"indentDepth[indentDepth.size()-1]:"<<indentDepth[indentDepth.size()-1];
00956 if ((nextLineIndentation>0) && ( indentDepth.isEmpty() || (indentDepth[indentDepth.size()-1]<nextLineIndentation)))
00957 {
00958 kDebug(13020)<<"addindent==true";
00959 addindent=true;
00960 } else {
00961 if ((!indentDepth.isEmpty()) && (indentDepth[indentDepth.size()-1]>nextLineIndentation))
00962 {
00963 kDebug(13020)<<"....";
00964 for (int z=indentDepth.size()-1; z > -1; z--)
00965 {
00966 kDebug(13020)<<indentDepth[z]<<" "<<nextLineIndentation;
00967 if (indentDepth[z]>nextLineIndentation)
00968 deindent++;
00969 }
00970 }
00971 }
00972
00973
00974
00975 if ((textLine->firstChar()==-1)) {
00976 updatePreviousNotEmptyLine(current_line,addindent,deindent);
00977 codeFoldingUpdate=true;
00978 }
00979 else
00980 {
00981 addIndentBasedFoldingInformation(foldingList,textLine->length(),addindent,deindent);
00982 }
00983 }
00984 }
00985 }
00986 indentChanged = !(indentDepth == textLine->indentationDepthArray());
00987
00988
00989 if (indentChanged)
00990 textLine->setIndentationDepth (indentDepth);
00991
00992 indentContinueWhitespace=textLine->firstChar()==-1;
00993 }
00994 bool foldingColChanged=false;
00995 bool foldingChanged = false;
00996 if (foldingList.size()!=textLine->foldingListArray().size()) {
00997 foldingChanged=true;
00998 } else {
00999 QVector<int>::ConstIterator it=foldingList.begin();
01000 QVector<int>::ConstIterator it1=textLine->foldingListArray().begin();
01001 bool markerType=true;
01002 for(;it!=foldingList.end();++it,++it1) {
01003 if (markerType) {
01004 if ( ((*it)!=(*it1))) {
01005 foldingChanged=true;
01006 foldingColChanged=false;
01007 break;
01008 }
01009 } else {
01010 if ((*it)!=(*it1)) {
01011 foldingColChanged=true;
01012 }
01013 }
01014 markerType=!markerType;
01015 }
01016 }
01017
01018 if (foldingChanged || foldingColChanged) {
01019 textLine->setFoldingList(foldingList);
01020 if (foldingChanged==false){
01021 textLine->setFoldingColumnsOutdated(textLine->foldingColumnsOutdated() | foldingColChanged);
01022 } else textLine->setFoldingColumnsOutdated(false);
01023 }
01024 bool retVal_folding = false;
01025
01026 m_regionTree.updateLine (current_line, &foldingList, &retVal_folding, foldingChanged,foldingColChanged);
01027
01028 codeFoldingUpdate = codeFoldingUpdate | retVal_folding;
01029
01030
01031 stillcontinue = ctxChanged || indentChanged || indentContinueWhitespace || indentContinueNextWhitespace;
01032
01033
01034 prevLine = textLine;
01035
01036
01037 current_line++;
01038 }
01039
01040
01041 if (invalidate)
01042 emit tagLines (startLine, current_line);
01043
01044
01045 if (codeFoldingUpdate)
01046 emit codeFoldingUpdated();
01047
01048
01049
01050
01051
01052
01053
01054
01055 return stillcontinue;
01056 }
01057
01058 void KateBuffer::codeFoldingColumnUpdate(int lineNr) {
01059 KateTextLine::Ptr line=plainLine(lineNr);
01060 if (!line) return;
01061 if (line->foldingColumnsOutdated()) {
01062 line->setFoldingColumnsOutdated(false);
01063 bool tmp;
01064 QVector<int> folding=line->foldingListArray();
01065 m_regionTree.updateLine(lineNr,&folding,&tmp,true,false);
01066 }
01067 }
01068
01069