# kate Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# katebuffer.cpp

    00001 /* This file is part of the KDE libraries
    00002    Copyright (c) 2000 Waldo Bastian <bastian@kde.org>
    00003    Copyright (C) 2002-2004 Christoph Cullmann <cullmann@kde.org>
    00004
    00005    This library is free software; you can redistribute it and/or
    00006    modify it under the terms of the GNU Library General Public
    00007    License version 2 as published by the Free Software Foundation.
    00008
    00009    This library is distributed in the hope that it will be useful,
    00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00012    Library General Public License for more details.
    00013
    00014    You should have received a copy of the GNU Library General Public License
    00015    along with this library; see the file COPYING.LIB.  If not, write to
    00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00017    Boston, MA 02111-1307, USA.
    00018 */
    00019
    00020 #include <sys/types.h>
    00021 #include <sys/stat.h>
    00022 #include <unistd.h>
    00023
    00024 #include "katebuffer.h"
    00025 #include "katebuffer.moc"
    00026
    00027 #include "katedocument.h"
    00028 #include "katehighlight.h"
    00029 #include "kateconfig.h"
    00030 #include "katefactory.h"
    00031 #include "kateautoindent.h"
    00032
    00033 #include <kdebug.h>
    00034 #include <kglobal.h>
    00035 #include <kcharsets.h>
    00036
    00037 #include <qpopupmenu.h>
    00038 #include <qfile.h>
    00039 #include <qtextstream.h>
    00040 #include <qtimer.h>
    00041 #include <qtextcodec.h>
    00042 #include <qcstring.h>
    00043 #include <qdatetime.h>
    00044
    00049 static const Q_ULONG KATE_FILE_LOADER_BS  = 256 * 1024;
    00050
    00057 static const Q_ULONG KATE_AVG_BLOCK_SIZE  = 2048 * 80;
    00058 static const Q_ULONG KATE_MAX_BLOCK_LINES = 2048;
    00059
    00065 static const uint KATE_HL_LOOKAHEAD = 64;
    00066
    00072 uint KateBuffer::m_maxLoadedBlocks = 16;
    00073
    00077 static const uint KATE_MAX_DYNAMIC_CONTEXTS = 512;
    00078
    00079 void KateBuffer::setMaxLoadedBlocks (uint count)
    00080 {
    00081   m_maxLoadedBlocks = KMAX ((uint)4, count);
    00082 }
    00083
    00084 class KateFileLoader
    00085 {
    00086   public:
    00087     KateFileLoader (const QString &filename, QTextCodec *codec)
    00088       : m_file (filename)
    00089       , m_buffer (KMIN (m_file.size(), KATE_FILE_LOADER_BS))
    00090       , m_codec (codec)
    00091       , m_decoder (m_codec->makeDecoder())
    00092       , m_position (0)
    00093       , m_lastLineStart (0)
    00094       , m_eof (false) // default to not eof
    00095       , lastWasEndOfLine (true) // at start of file, we had a virtual newline
    00096       , lastWasR (false) // we have not found a \r as last char
    00097       , m_eol (-1) // no eol type detected atm
    00098       , m_twoByteEncoding (QString(codec->name()) == "ISO-10646-UCS-2")
    00099       , m_binary (false)
    00100     {
    00101     }
    00102
    00103     ~KateFileLoader ()
    00104     {
    00105       delete m_decoder;
    00106     }
    00107
    00111     bool open ()
    00112     {
    00113       if (m_file.open (IO_ReadOnly))
    00114       {
    00115         int c = m_file.readBlock (m_buffer.data(), m_buffer.size());
    00116
    00117         if (c > 0)
    00118         {
    00119           // fix utf16 LE, stolen from khtml ;)
    00120           if ((c >= 2) && (m_codec->mibEnum() == 1000) && (m_buffer[1] == 0x00))
    00121           {
    00122             // utf16LE, we need to put the decoder in LE mode
    00123             char reverseUtf16[3] = {0xFF, 0xFE, 0x00};
    00124             m_decoder->toUnicode(reverseUtf16, 2);
    00125           }
    00126
    00127           processNull (c);
    00128           m_text = m_decoder->toUnicode (m_buffer, c);
    00129         }
    00130
    00131         m_eof = (c == -1) || (c == 0) || (m_text.length() == 0) || m_file.atEnd();
    00132
    00133         for (uint i=0; i < m_text.length(); i++)
    00134         {
    00135           if (m_text[i] == '\n')
    00136           {
    00137             m_eol = KateDocumentConfig::eolUnix;
    00138             break;
    00139           }
    00140           else if ((m_text[i] == '\r'))
    00141           {
    00142             if (((i+1) < m_text.length()) && (m_text[i+1] == '\n'))
    00143             {
    00144               m_eol = KateDocumentConfig::eolDos;
    00145               break;
    00146             }
    00147             else
    00148             {
    00149               m_eol = KateDocumentConfig::eolMac;
    00150               break;
    00151             }
    00152           }
    00153         }
    00154
    00155         return true;
    00156       }
    00157
    00158       return false;
    00159     }
    00160
    00161     // no new lines around ?
    00162     inline bool eof () const { return m_eof && !lastWasEndOfLine && (m_lastLineStart == m_text.length()); }
    00163
    00164     // eol mode ? autodetected on open(), -1 for no eol found in the first block!
    00165     inline int eol () const { return m_eol; }
    00166
    00167     // binary ?
    00168     inline bool binary () const { return m_binary; }
    00169
    00170     // internal unicode data array
    00171     inline const QChar *unicode () const { return m_text.unicode(); }
    00172
    00173     // read a line, return length + offset in unicode data
    00174     void readLine (uint &offset, uint &length)
    00175     {
    00176       length = 0;
    00177       offset = 0;
    00178
    00179       while (m_position <= m_text.length())
    00180       {
    00181         if (m_position == m_text.length())
    00182         {
    00183           // try to load more text if something is around
    00184           if (!m_eof)
    00185           {
    00186             int c = m_file.readBlock (m_buffer.data(), m_buffer.size());
    00187
    00188             uint readString = 0;
    00189             if (c > 0)
    00190             {
    00191               processNull (c);
    00192
    00193               QString str (m_decoder->toUnicode (m_buffer, c));
    00194               readString = str.length();
    00195
    00196               m_text = m_text.mid (m_lastLineStart, m_position-m_lastLineStart)
    00197                        + str;
    00198             }
    00199             else
    00200               m_text = m_text.mid (m_lastLineStart, m_position-m_lastLineStart);
    00201
    00202             // is file completly read ?
    00203             m_eof = (c == -1) || (c == 0) || (readString == 0) || m_file.atEnd();
    00204
    00205             // recalc current pos and last pos
    00206             m_position -= m_lastLineStart;
    00207             m_lastLineStart = 0;
    00208           }
    00209
    00210           // oh oh, end of file, escape !
    00211           if (m_eof && (m_position == m_text.length()))
    00212           {
    00213             lastWasEndOfLine = false;
    00214
    00215             // line data
    00216             offset = m_lastLineStart;
    00217             length = m_position-m_lastLineStart;
    00218
    00219             m_lastLineStart = m_position;
    00220
    00221             return;
    00222           }
    00223         }
    00224
    00225         if (m_text[m_position] == '\n')
    00226         {
    00227           lastWasEndOfLine = true;
    00228
    00229           if (lastWasR)
    00230           {
    00231             m_lastLineStart++;
    00232             lastWasR = false;
    00233           }
    00234           else
    00235           {
    00236             // line data
    00237             offset = m_lastLineStart;
    00238             length = m_position-m_lastLineStart;
    00239
    00240             m_lastLineStart = m_position+1;
    00241             m_position++;
    00242
    00243             return;
    00244           }
    00245         }
    00246         else if (m_text[m_position] == '\r')
    00247         {
    00248           lastWasEndOfLine = true;
    00249           lastWasR = true;
    00250
    00251           // line data
    00252           offset = m_lastLineStart;
    00253           length = m_position-m_lastLineStart;
    00254
    00255           m_lastLineStart = m_position+1;
    00256           m_position++;
    00257
    00258           return;
    00259         }
    00260         else
    00261         {
    00262           lastWasEndOfLine = false;
    00263           lastWasR = false;
    00264         }
    00265
    00266         m_position++;
    00267       }
    00268     }
    00269
    00270     // this nice methode will kill all 0 bytes (or double bytes)
    00271     // and remember if this was a binary or not ;)
    00272     void processNull (uint length)
    00273     {
    00274       if (m_twoByteEncoding)
    00275       {
    00276         for (uint i=1; i < length; i+=2)
    00277         {
    00278           if ((m_buffer[i] == 0) && (m_buffer[i-1] == 0))
    00279           {
    00280             m_binary = true;
    00281             m_buffer[i] = ' ';
    00282           }
    00283         }
    00284       }
    00285       else
    00286       {
    00287         for (uint i=0; i < length; i++)
    00288         {
    00289           if (m_buffer[i] == 0)
    00290           {
    00291             m_binary = true;
    00292             m_buffer[i] = ' ';
    00293           }
    00294         }
    00295       }
    00296     }
    00297
    00298   private:
    00299     QFile m_file;
    00300     QByteArray m_buffer;
    00301     QTextCodec *m_codec;
    00302     QTextDecoder *m_decoder;
    00303     QString m_text;
    00304     uint m_position;
    00305     uint m_lastLineStart;
    00306     bool m_eof;
    00307     bool lastWasEndOfLine;
    00308     bool lastWasR;
    00309     int m_eol;
    00310     bool m_twoByteEncoding;
    00311     bool m_binary;
    00312 };
    00313
    00317 KateBuffer::KateBuffer(KateDocument *doc)
    00318  : QObject (doc),
    00319    editSessionNumber (0),
    00320    editIsRunning (false),
    00321    editTagLineStart (0xffffffff),
    00322    editTagLineEnd (0),
    00323    m_doc (doc),
    00324    m_lines (0),
    00325    m_lastInSyncBlock (0),
    00326    m_lastFoundBlock (0),
    00327    m_cacheReadError(false),
    00328    m_cacheWriteError(false),
    00329    m_loadingBorked (false),
    00330    m_binary (false),
    00331    m_highlight (0),
    00332    m_regionTree (this),
    00333    m_tabWidth (8),
    00334    m_lineHighlightedMax (0),
    00335    m_lineHighlighted (0),
    00336    m_maxDynamicContexts (KATE_MAX_DYNAMIC_CONTEXTS)
    00337 {
    00338   clear();
    00339 }
    00340
    00344 KateBuffer::~KateBuffer()
    00345 {
    00346   // DELETE ALL BLOCKS, will free mem
    00347   for (uint i=0; i < m_blocks.size(); i++)
    00348     delete m_blocks[i];
    00349
    00350   // release HL
    00351   if (m_highlight)
    00352     m_highlight->release();
    00353 }
    00354
    00355 void KateBuffer::editStart ()
    00356 {
    00357   editSessionNumber++;
    00358
    00359   if (editSessionNumber > 1)
    00360     return;
    00361
    00362   editIsRunning = true;
    00363
    00364   editTagLineStart = 0xffffffff;
    00365   editTagLineEnd = 0;
    00366 }
    00367
    00368 void KateBuffer::editEnd ()
    00369 {
    00370   if (editSessionNumber == 0)
    00371     return;
    00372
    00373   editSessionNumber--;
    00374
    00375   if (editSessionNumber > 0)
    00376     return;
    00377
    00378   // hl update !!!
    00379   if ( m_highlight && !m_highlight->noHighlighting()
    00380        && (editTagLineStart <= editTagLineEnd)
    00381        && (editTagLineEnd <= m_lineHighlighted))
    00382   {
    00383     // look one line too far, needed for linecontinue stuff
    00384     editTagLineEnd++;
    00385
    00386     // look one line before, needed nearly 100% only for indentation based folding !
    00387     if (editTagLineStart > 0)
    00388       editTagLineStart--;
    00389
    00390     KateBufBlock *buf2 = 0;
    00391     bool needContinue = false;
    00392     while ((buf2 = findBlock(editTagLineStart)))
    00393     {
    00394       needContinue = doHighlight (buf2,
    00395         (editTagLineStart > buf2->startLine()) ? editTagLineStart : buf2->startLine(),
    00396         (editTagLineEnd > buf2->endLine()) ? buf2->endLine() : editTagLineEnd,
    00397         true);
    00398
    00399       editTagLineStart = (editTagLineEnd > buf2->endLine()) ? buf2->endLine() : editTagLineEnd;
    00400
    00401       if ((editTagLineStart >= m_lines) || (editTagLineStart >= editTagLineEnd))
    00402         break;
    00403     }
    00404
    00405     if (needContinue)
    00406       m_lineHighlighted = editTagLineStart;
    00407
    00408     if (editTagLineStart > m_lineHighlightedMax)
    00409       m_lineHighlightedMax = editTagLineStart;
    00410   }
    00411   else if (editTagLineStart < m_lineHighlightedMax)
    00412     m_lineHighlightedMax = editTagLineStart;
    00413
    00414   editIsRunning = false;
    00415 }
    00416
    00417 void KateBuffer::editTagLine (uint line)
    00418 {
    00419   if (line < editTagLineStart)
    00420     editTagLineStart = line;
    00421
    00422   if (line > editTagLineEnd)
    00423     editTagLineEnd = line;
    00424 }
    00425
    00426 void KateBuffer::editInsertTagLine (uint line)
    00427 {
    00428   if (line < editTagLineStart)
    00429     editTagLineStart = line;
    00430
    00431   if (line <= editTagLineEnd)
    00432     editTagLineEnd++;
    00433
    00434   if (line > editTagLineEnd)
    00435     editTagLineEnd = line;
    00436 }
    00437
    00438 void KateBuffer::editRemoveTagLine (uint line)
    00439 {
    00440   if (line < editTagLineStart)
    00441     editTagLineStart = line;
    00442
    00443   if (line < editTagLineEnd)
    00444     editTagLineEnd--;
    00445
    00446   if (line > editTagLineEnd)
    00447     editTagLineEnd = line;
    00448 }
    00449
    00450 void KateBuffer::clear()
    00451 {
    00452   m_regionTree.clear();
    00453
    00454   // cleanup the blocks
    00455   for (uint i=0; i < m_blocks.size(); i++)
    00456     delete m_blocks[i];
    00457
    00458   m_blocks.clear ();
    00459
    00460   // create a bufblock with one line, we need that, only in openFile we won't have that
    00461   KateBufBlock *block = new KateBufBlock(this, 0, 0);
    00462   m_blocks.append (block);
    00463
    00464   // reset the state
    00465   m_lines = block->lines();
    00466   m_lastInSyncBlock = 0;
    00467   m_lastFoundBlock = 0;
    00468   m_cacheWriteError = false;
    00469   m_cacheReadError = false;
    00470   m_loadingBorked = false;
    00471   m_binary = false;
    00472
    00473   m_lineHighlightedMax = 0;
    00474   m_lineHighlighted = 0;
    00475 }
    00476
    00477 bool KateBuffer::openFile (const QString &m_file)
    00478 {
    00479   KateFileLoader file (m_file, m_doc->config()->codec());
    00480
    00481   bool ok = false;
    00482   struct stat sbuf;
    00483   if (stat(QFile::encodeName(m_file), &sbuf) == 0)
    00484   {
    00485     if (S_ISREG(sbuf.st_mode) && file.open())
    00486       ok = true;
    00487   }
    00488
    00489   if (!ok)
    00490   {
    00491     clear();
    00492     return false; // Error
    00493   }
    00494
    00495   // set eol mode, if a eol char was found in the first 256kb block!
    00496   if (file.eol() != -1)
    00497     m_doc->config()->setEol (file.eol());
    00498
    00499   // flush current content
    00500   clear ();
    00501
    00502   // cleanup the blocks
    00503   for (uint i=0; i < m_blocks.size(); i++)
    00504     delete m_blocks[i];
    00505
    00506   m_blocks.clear ();
    00507
    00508   // do the real work
    00509   KateBufBlock *block = 0;
    00510   m_lines = 0;
    00511   while (!file.eof() && !m_cacheWriteError)
    00512   {
    00513     block = new KateBufBlock (this, block, 0, &file);
    00514
    00515     m_lines = block->endLine ();
    00516
    00517     if (m_cacheWriteError || (block->lines() == 0))
    00518     {
    00519       delete block;
    00520       break;
    00521     }
    00522     else
    00523       m_blocks.append (block);
    00524   }
    00525
    00526   // we had a cache write error, this load is really borked !
    00527   if (m_cacheWriteError)
    00528     m_loadingBorked = true;
    00529
    00530   if (m_blocks.isEmpty() || (m_lines == 0))
    00531   {
    00532     // file was really empty, clean the buffers + emit the line changed
    00533     // loadingBorked will be false for such files, not matter what happened
    00534     // before
    00535     clear ();
    00536   }
    00537   else
    00538   {
    00539     // fix region tree
    00540     m_regionTree.fixRoot (m_lines);
    00541   }
    00542
    00543   // if we have no hl or the "None" hl activated, whole file is correct highlighted
    00544   // after loading, which wonder ;)
    00545   if (!m_highlight || m_highlight->noHighlighting())
    00546   {
    00547     m_lineHighlighted = m_lines;
    00548     m_lineHighlightedMax = m_lines;
    00549   }
    00550
    00551   // binary?
    00552   m_binary = file.binary ();
    00553
    00554   kdDebug (13020) << "LOADING DONE" << endl;
    00555
    00556   return !m_loadingBorked;
    00557 }
    00558
    00559 bool KateBuffer::canEncode ()
    00560 {
    00561   QTextCodec *codec = m_doc->config()->codec();
    00562
    00563   kdDebug(13020) << "ENC NAME: " << codec->name() << endl;
    00564
    00565   // hardcode some unicode encodings which can encode all chars
    00566   if ((QString(codec->name()) == "UTF-8") || (QString(codec->name()) == "ISO-10646-UCS-2"))
    00567     return true;
    00568
    00569   for (uint i=0; i < m_lines; i++)
    00570   {
    00571     if (!codec->canEncode (plainLine(i)->string()))
    00572     {
    00573       kdDebug(13020) << "STRING LINE: " << plainLine(i)->string() << endl;
    00574       kdDebug(13020) << "ENC WORKING: FALSE" << endl;
    00575
    00576       return false;
    00577     }
    00578   }
    00579
    00580   return true;
    00581 }
    00582
    00583 bool KateBuffer::saveFile (const QString &m_file)
    00584 {
    00585   QFile file (m_file);
    00586   QTextStream stream (&file);
    00587
    00588   if ( !file.open( IO_WriteOnly ) )
    00589   {
    00590     return false; // Error
    00591   }
    00592
    00593   QTextCodec *codec = m_doc->config()->codec();
    00594
    00595   // disable Unicode headers
    00596   stream.setEncoding(QTextStream::RawUnicode);
    00597
    00598   // this line sets the mapper to the correct codec
    00599   stream.setCodec(codec);
    00600
    00601   QString eol = m_doc->config()->eolString ();
    00602
    00603   // for tab replacement, initialize only once
    00604   uint pos, found, ml, l;
    00605   QChar onespace(' ');
    00606   QString onetab("\t");
    00607   uint tw = m_doc->config()->tabWidth();
    00608
    00609   // Use the document methods
    00610   if ( m_doc->configFlags() & KateDocument::cfReplaceTabs ||
    00611        m_doc->configFlags() & KateDocument::cfRemoveSpaces )
    00612     m_doc->editStart();
    00613
    00614   for (uint i=0; i < m_lines; i++)
    00615   {
    00616     KateTextLine::Ptr textLine = plainLine(i);
    00617
    00618     if (textLine)
    00619     {
    00620       // replace tabs if required
    00621       if ( m_doc->configFlags() & KateDocument::cfReplaceTabs )
    00622       {
    00623         pos = 0;
    00624         while ( textLine->searchText( pos, onetab, &found, &ml ) )
    00625         {
    00626           l = tw - ( found%tw );
    00627           if ( l )
    00628           {
    00629             QString t;
    00630             m_doc->editRemoveText( i, found, 1 );
    00631             m_doc->editInsertText( i, found, t.fill(onespace, l) ); // ### anything more efficient?
    00632             pos += l-1;
    00633           }
    00634         }
    00635       }
    00636
    00637       // remove trailing spaces if required
    00638       if ( (m_doc->configFlags() & KateDocument::cfRemoveSpaces) && textLine->length() )
    00639       {
    00640         pos = textLine->length() - 1;
    00641         uint lns = textLine->lastChar();
    00642         if ( lns != pos )
    00643           m_doc->editRemoveText( i, lns + 1, pos - lns );
    00644       }
    00645
    00646       stream << textLine->string();
    00647
    00648       if ((i+1) < m_lines)
    00649         stream << eol;
    00650     }
    00651   }
    00652
    00653   if ( m_doc->configFlags() & KateDocument::cfReplaceTabs ||
    00654        m_doc->configFlags() & KateDocument::cfRemoveSpaces )
    00655     m_doc->editEnd();
    00656
    00657   file.close ();
    00658
    00659   m_loadingBorked = false;
    00660
    00661   return (file.status() == IO_Ok);
    00662 }
    00663
    00664 KateTextLine::Ptr KateBuffer::line_internal (KateBufBlock *buf, uint i)
    00665 {
    00666   // update hl until this line + max KATE_HL_LOOKAHEAD
    00667   KateBufBlock *buf2 = 0;
    00668   while ((i >= m_lineHighlighted) && (buf2 = findBlock(m_lineHighlighted)))
    00669   {
    00670     uint end = kMin(i + KATE_HL_LOOKAHEAD, buf2->endLine());
    00671
    00672     doHighlight ( buf2,
    00673                   kMax(m_lineHighlighted, buf2->startLine()),
    00674                   end,
    00675                   false );
    00676
    00677     m_lineHighlighted = end;
    00678   }
    00679
    00680   // update hl max
    00681   if (m_lineHighlighted > m_lineHighlightedMax)
    00682     m_lineHighlightedMax = m_lineHighlighted;
    00683
    00684   return buf->line (i - buf->startLine());
    00685 }
    00686
    00687 KateBufBlock *KateBuffer::findBlock_internal (uint i, uint *index)
    00688 {
    00689   uint lastLine = m_blocks[m_lastInSyncBlock]->endLine ();
    00690
    00691   if (lastLine > i) // we are in a allready known area !
    00692   {
    00693     while (true)
    00694     {
    00695       KateBufBlock *buf = m_blocks[m_lastFoundBlock];
    00696
    00697       if ( (buf->startLine() <= i)
    00698            && (buf->endLine() > i) )
    00699       {
    00700         if (index)
    00701           (*index) = m_lastFoundBlock;
    00702
    00703         return m_blocks[m_lastFoundBlock];
    00704       }
    00705
    00706       if (i < buf->startLine())
    00707         m_lastFoundBlock--;
    00708       else
    00709         m_lastFoundBlock++;
    00710     }
    00711   }
    00712   else // we need first to resync the startLines !
    00713   {
    00714     if ((m_lastInSyncBlock+1) < m_blocks.size())
    00715       m_lastInSyncBlock++;
    00716     else
    00717       return 0;
    00718
    00719     for (; m_lastInSyncBlock < m_blocks.size(); m_lastInSyncBlock++)
    00720     {
    00721       // get next block
    00722       KateBufBlock *buf = m_blocks[m_lastInSyncBlock];
    00723
    00724       // sync startLine !
    00725       buf->setStartLine (lastLine);
    00726
    00727       // is it allready the searched block ?
    00728       if ((i >= lastLine) && (i < buf->endLine()))
    00729       {
    00730         // remember this block as last found !
    00731         m_lastFoundBlock = m_lastInSyncBlock;
    00732
    00733         if (index)
    00734           (*index) = m_lastFoundBlock;
    00735
    00736         return buf;
    00737       }
    00738
    00739       // increase lastLine with blocklinecount
    00740       lastLine += buf->lines ();
    00741     }
    00742   }
    00743
    00744   // no block found !
    00745   // index will not be set to any useful value in this case !
    00746   return 0;
    00747 }
    00748
    00749 void KateBuffer::changeLine(uint i)
    00750 {
    00751   KateBufBlock *buf = findBlock(i);
    00752
    00753   editTagLine (i);
    00754
    00755   if (buf)
    00756     buf->markDirty ();
    00757 }
    00758
    00759 void KateBuffer::insertLine(uint i, KateTextLine::Ptr line)
    00760 {
    00761   uint index = 0;
    00762   KateBufBlock *buf;
    00763   if (i == m_lines)
    00764     buf = findBlock(i-1, &index);
    00765   else
    00766     buf = findBlock(i, &index);
    00767
    00768   if (!buf)
    00769     return;
    00770
    00771   buf->insertLine(i -  buf->startLine(), line);
    00772
    00773   if (m_lineHighlightedMax > i)
    00774     m_lineHighlightedMax++;
    00775
    00776   if (m_lineHighlighted > i)
    00777     m_lineHighlighted++;
    00778
    00779   m_lines++;
    00780
    00781   // last sync block adjust
    00782   if (m_lastInSyncBlock > index)
    00783     m_lastInSyncBlock = index;
    00784
    00785   // last found
    00786   if (m_lastInSyncBlock < m_lastFoundBlock)
    00787     m_lastFoundBlock = m_lastInSyncBlock;
    00788
    00789   editInsertTagLine (i);
    00790
    00791   m_regionTree.lineHasBeenInserted (i);
    00792 }
    00793
    00794 void KateBuffer::removeLine(uint i)
    00795 {
    00796    uint index = 0;
    00797    KateBufBlock *buf = findBlock(i, &index);
    00798
    00799    if (!buf)
    00800      return;
    00801
    00802   buf->removeLine(i -  buf->startLine());
    00803
    00804   if (m_lineHighlightedMax > i)
    00805     m_lineHighlightedMax--;
    00806
    00807   if (m_lineHighlighted > i)
    00808     m_lineHighlighted--;
    00809
    00810   m_lines--;
    00811
    00812   // trash away a empty block
    00813   if (buf->lines() == 0)
    00814   {
    00815     // we need to change which block is last in sync
    00816     if (m_lastInSyncBlock >= index)
    00817     {
    00818       m_lastInSyncBlock = index;
    00819
    00820       if (buf->next())
    00821       {
    00822         if (buf->prev())
    00823           buf->next()->setStartLine (buf->prev()->endLine());
    00824         else
    00825           buf->next()->setStartLine (0);
    00826       }
    00827     }
    00828
    00829     // cu block !
    00830     delete buf;
    00831     m_blocks.erase (m_blocks.begin()+index);
    00832   }
    00833   else
    00834   {
    00835     // last sync block adjust
    00836     if (m_lastInSyncBlock > index)
    00837       m_lastInSyncBlock = index;
    00838   }
    00839
    00840   // last found
    00841   if (m_lastInSyncBlock < m_lastFoundBlock)
    00842     m_lastFoundBlock = m_lastInSyncBlock;
    00843
    00844   editRemoveTagLine (i);
    00845
    00846   m_regionTree.lineHasBeenRemoved (i);
    00847 }
    00848
    00849 void KateBuffer::setTabWidth (uint w)
    00850 {
    00851   if ((m_tabWidth != w) && (m_tabWidth > 0))
    00852   {
    00853     m_tabWidth = w;
    00854
    00855     if (m_highlight && m_highlight->foldingIndentationSensitive())
    00856       invalidateHighlighting();
    00857   }
    00858 }
    00859
    00860 void KateBuffer::setHighlight(uint hlMode)
    00861 {
    00862   KateHighlighting *h = KateHlManager::self()->getHl(hlMode);
    00863
    00864    // aha, hl will change
    00865   if (h != m_highlight)
    00866   {
    00867     bool invalidate = !h->noHighlighting();
    00868
    00869     if (m_highlight)
    00870     {
    00871       m_highlight->release();
    00872       invalidate = true;
    00873     }
    00874
    00875     h->use();
    00876
    00877     // try to set indentation
    00878     if (!h->indentation().isEmpty())
    00879       m_doc->config()->setIndentationMode (KateAutoIndent::modeNumber(h->indentation()));
    00880
    00881     m_highlight = h;
    00882
    00883     if (invalidate)
    00884       invalidateHighlighting();
    00885
    00886     // inform the document that the hl was really changed
    00887     // needed to update attributes and more ;)
    00888     m_doc->bufferHlChanged ();
    00889   }
    00890 }
    00891
    00892 void KateBuffer::invalidateHighlighting()
    00893 {
    00894   m_lineHighlightedMax = 0;
    00895   m_lineHighlighted = 0;
    00896 }
    00897
    00898 bool KateBuffer::doHighlight (KateBufBlock *buf, uint startLine, uint endLine, bool invalidate)
    00899 {
    00900   // no hl around, no stuff to do
    00901   if (!m_highlight)
    00902     return false;
    00903
    00904   // we tried to start in a line behind this buf block !
    00905   if (startLine >= (buf->startLine()+buf->lines()))
    00906     return false;
    00907
    00908   QTime t;
    00909   t.start();
    00910   kdDebug (13020) << "HIGHLIGHTED START --- NEED HL, LINESTART: " << startLine << " LINEEND: " << endLine << endl;
    00911   kdDebug (13020) << "HL UNTIL LINE: " << m_lineHighlighted << " MAX: " << m_lineHighlightedMax << endl;
    00912   kdDebug (13020) << "HL DYN COUNT: " << KateHlManager::self()->countDynamicCtxs() << " MAX: " << m_maxDynamicContexts << endl;
    00913
    00914   // see if there are too many dynamic contexts; if yes, invalidate HL of all documents
    00915   if (KateHlManager::self()->countDynamicCtxs() >= m_maxDynamicContexts)
    00916   {
    00917     {
    00918       if (KateHlManager::self()->resetDynamicCtxs())
    00919       {
    00920         kdDebug (13020) << "HL invalidated - too many dynamic contexts ( >= " << m_maxDynamicContexts << ")" << endl;
    00921
    00922         // avoid recursive invalidation
    00923         KateHlManager::self()->setForceNoDCReset(true);
    00924
    00925         for (KateDocument *doc = KateFactory::self()->documents()->first(); doc; doc = KateFactory::self()->documents()->next())
    00926           doc->makeAttribs();
    00927
    00928         // doHighlight *shall* do his work. After invalidation, some highlight has
    00929         // been recalculated, but *maybe not* until endLine ! So we shall force it manually...
    00930         KateBufBlock *buf = 0;
    00931         while ((endLine > m_lineHighlighted) && (buf = findBlock(m_lineHighlighted)))
    00932         {
    00933           uint end = kMin(endLine, buf->endLine());
    00934
    00935           doHighlight ( buf,
    00936                         kMax(m_lineHighlighted, buf->startLine()),
    00937                         end,
    00938                         false );
    00939
    00940           m_lineHighlighted = end;
    00941         }
    00942
    00943         KateHlManager::self()->setForceNoDCReset(false);
    00944
    00945         return false;
    00946       }
    00947       else
    00948       {
    00949         m_maxDynamicContexts *= 2;
    00950         kdDebug (13020) << "New dynamic contexts limit: " << m_maxDynamicContexts << endl;
    00951       }
    00952     }
    00953   }
    00954
    00955   // get the previous line, if we start at the beginning of this block
    00956   // take the last line of the previous block
    00957   KateTextLine::Ptr prevLine = 0;
    00958
    00959   if ((startLine == buf->startLine()) && buf->prev() && (buf->prev()->lines() > 0))
    00960     prevLine = buf->prev()->line (buf->prev()->lines() - 1);
    00961   else if ((startLine > buf->startLine()) && (startLine <= buf->endLine()))
    00962     prevLine = buf->line(startLine - buf->startLine() - 1);
    00963   else
    00964     prevLine = new KateTextLine ();
    00965
    00966   // does we need to emit a signal for the folding changes ?
    00967   bool codeFoldingUpdate = false;
    00968
    00969   // here we are atm, start at start line in the block
    00970   uint current_line = startLine - buf->startLine();
    00971
    00972   // does we need to continue
    00973   bool stillcontinue=false;
    00974
    00975   // loop over the lines of the block, from startline to endline or end of block
    00976   // if stillcontinue forces us to do so
    00977   while ( (current_line < buf->lines())
    00978           && (stillcontinue || ((current_line + buf->startLine()) <= endLine)) )
    00979   {
    00980     // current line
    00981     KateTextLine::Ptr textLine = buf->line(current_line);
    00982
    00983     QMemArray<uint> foldingList;
    00984     bool ctxChanged = false;
    00985
    00986     m_highlight->doHighlight (prevLine, textLine, &foldingList, &ctxChanged);
    00987
    00988     //
    00989     // indentation sensitive folding
    00990     //
    00991     bool indentChanged = false;
    00992     if (m_highlight->foldingIndentationSensitive())
    00993     {
    00994       // get the indentation array of the previous line to start with !
    00995       QMemArray<unsigned short> indentDepth;
    00996       indentDepth.duplicate (prevLine->indentationDepthArray());
    00997
    00998       // current indentation of this line
    00999       uint iDepth = textLine->indentDepth(m_tabWidth);
    01000
    01001       // this line is empty, beside spaces, use indentation depth of the previous line !
    01002       if (textLine->firstChar() == -1)
    01003       {
    01004         // do this to get skipped empty lines indent right, which was given in the indenation array
    01005         if (!prevLine->indentationDepthArray().isEmpty())
    01006           iDepth = (prevLine->indentationDepthArray())[prevLine->indentationDepthArray().size()-1];
    01007         else
    01008           iDepth = prevLine->indentDepth(m_tabWidth);
    01009       }
    01010
    01011       // query the next line indentation, if we are at the end of the block
    01012       // use the first line of the next buf block
    01013       uint nextLineIndentation = 0;
    01014
    01015       if ((current_line+1) < buf->lines())
    01016       {
    01017         if (buf->line(current_line+1)->firstChar() == -1)
    01018           nextLineIndentation = iDepth;
    01019         else
    01020           nextLineIndentation = buf->line(current_line+1)->indentDepth(m_tabWidth);
    01021       }
    01022       else
    01023       {
    01024         KateBufBlock *blk = buf->next();
    01025
    01026         if (blk && (blk->lines() > 0))
    01027         {
    01028           if (blk->line (0)->firstChar() == -1)
    01029             nextLineIndentation = iDepth;
    01030           else
    01031             nextLineIndentation = blk->line (0)->indentDepth(m_tabWidth);
    01032         }
    01033       }
    01034
    01035       // recalculate the indentation array for this line, query if we have to add
    01036       // a new folding start, this means newIn == true !
    01037       bool newIn = false;
    01038       if ((iDepth > 0) && (indentDepth.isEmpty() || (indentDepth[indentDepth.size()-1] < iDepth)))
    01039       {
    01040         indentDepth.resize (indentDepth.size()+1, QGArray::SpeedOptim);
    01041         indentDepth[indentDepth.size()-1] = iDepth;
    01042         newIn = true;
    01043       }
    01044       else
    01045       {
    01046         for (int z=indentDepth.size()-1; z > -1; z--)
    01047         {
    01048           if (indentDepth[z] > iDepth)
    01049             indentDepth.resize (z, QGArray::SpeedOptim);
    01050           else if (indentDepth[z] == iDepth)
    01051             break;
    01052           else if (indentDepth[z] < iDepth)
    01053           {
    01054             indentDepth.resize (indentDepth.size()+1, QGArray::SpeedOptim);
    01055             indentDepth[indentDepth.size()-1] = iDepth;
    01056             newIn = true;
    01057             break;
    01058           }
    01059         }
    01060       }
    01061
    01062       // just for debugging always true to start with !
    01063       indentChanged = !(indentDepth == textLine->indentationDepthArray());
    01064
    01065       // assign the new array to the textline !
    01066       if (indentChanged)
    01067         textLine->setIndentationDepth (indentDepth);
    01068
    01069       // add folding start to the list !
    01070       if (newIn)
    01071       {
    01072         foldingList.resize (foldingList.size() + 2, QGArray::SpeedOptim);
    01073         foldingList[foldingList.size()-2] = 1;
    01074         foldingList[foldingList.size()-1] = 0;
    01075       }
    01076
    01077       // calculate how much end folding symbols must be added to the list !
    01078       // remIn gives you the count of them
    01079       uint remIn = 0;
    01080
    01081       for (int z=indentDepth.size()-1; z > -1; z--)
    01082       {
    01083         if (indentDepth[z] > nextLineIndentation)
    01084           remIn++;
    01085         else
    01086           break;
    01087       }
    01088
    01089       if (remIn > 0)
    01090       {
    01091         foldingList.resize (foldingList.size() + (remIn*2), QGArray::SpeedOptim);
    01092
    01093         for (uint z= foldingList.size()-(remIn*2); z < foldingList.size(); z=z+2)
    01094         {
    01095           foldingList[z] = -1;
    01096           foldingList[z+1] = 0;
    01097         }
    01098       }
    01099     }
    01100     bool foldingColChanged=false;
    01101     bool foldingChanged = false;
    01102     if (foldingList.size()!=textLine->foldingListArray().size()) {
    01103       foldingChanged=true;
    01104     } else {
    01105       QMemArray<uint>::ConstIterator it=foldingList.begin();
    01106       QMemArray<uint>::ConstIterator it1=textLine->foldingListArray();
    01107       bool markerType=true;
    01108       for(;it!=foldingList.end();++it,++it1) {
    01109         if  (markerType) {
    01110           if ( ((*it)!=(*it1))) {
    01111             foldingChanged=true;
    01112             foldingColChanged=false;
    01113             break;
    01114           }
    01115         } else {
    01116             if ((*it)!=(*it1)) {
    01117               foldingColChanged=true;
    01118             }
    01119         }
    01120         markerType=!markerType;
    01121       }
    01122     }
    01123
    01124     if (foldingChanged || foldingColChanged) {
    01125       textLine->setFoldingList(foldingList);
    01126       if (foldingChanged==false){
    01127         textLine->setFoldingColumnsOutdated(textLine->foldingColumnsOutdated() | foldingColChanged);
    01128       } else textLine->setFoldingColumnsOutdated(false);
    01129     }
    01130     bool retVal_folding = false;
    01131     //perhaps make en enums out of the change flags
    01132     m_regionTree.updateLine (current_line + buf->startLine(), &foldingList, &retVal_folding, foldingChanged,foldingColChanged);
    01133
    01134     codeFoldingUpdate = codeFoldingUpdate | retVal_folding;
    01135
    01136     // need we to continue ?
    01137     stillcontinue = ctxChanged || indentChanged;
    01138
    01139     // move around the lines
    01140     prevLine = textLine;
    01141
    01142     // increment line
    01143     current_line++;
    01144   }
    01145
    01146   buf->markDirty ();
    01147
    01148   // tag the changed lines !
    01149   if (invalidate)
    01150     emit tagLines (startLine, current_line + buf->startLine());
    01151
    01152   // emit that we have changed the folding
    01153   if (codeFoldingUpdate)
    01154     emit codeFoldingUpdated();
    01155
    01156   kdDebug (13020) << "HIGHLIGHTED END --- NEED HL, LINESTART: " << startLine << " LINEEND: " << endLine << endl;
    01157   kdDebug (13020) << "HL UNTIL LINE: " << m_lineHighlighted << " MAX: " << m_lineHighlightedMax << endl;
    01158   kdDebug (13020) << "HL DYN COUNT: " << KateHlManager::self()->countDynamicCtxs() << " MAX: " << m_maxDynamicContexts << endl;
    01159   kdDebug (13020) << "TIME TAKEN: " << t.elapsed() << endl;
    01160
    01161   // if we are at the last line of the block + we still need to continue
    01162   // return the need of that !
    01163   return stillcontinue && ((current_line+1) == buf->lines());
    01164 }
    01165
    01166 void KateBuffer::codeFoldingColumnUpdate(unsigned int lineNr) {
    01167   KateTextLine::Ptr line=plainLine(lineNr);
    01168   if (!line) return;
    01169   if (line->foldingColumnsOutdated()) {
    01170     line->setFoldingColumnsOutdated(false);
    01171     bool tmp;
    01172     QMemArray<uint> folding=line->foldingListArray();
    01173     m_regionTree.updateLine(lineNr,&folding,&tmp,true,false);
    01174   }
    01175 }
    01176
    01177 //BEGIN KateBufBlock
    01178
    01179 KateBufBlock::KateBufBlock ( KateBuffer *parent, KateBufBlock *prev, KateBufBlock *next,
    01180                              KateFileLoader *stream )
    01181 : m_state (KateBufBlock::stateDirty),
    01182   m_startLine (0),
    01183   m_lines (0),
    01184   m_vmblock (0),
    01185   m_vmblockSize (0),
    01186   m_parent (parent),
    01187   m_prev (prev),
    01188   m_next (next),
    01189   list (0),
    01190   listPrev (0),
    01191   listNext (0)
    01192 {
    01193   // init startline + the next pointers of the neighbour blocks
    01194   if (m_prev)
    01195   {
    01196     m_startLine = m_prev->endLine ();
    01197     m_prev->m_next = this;
    01198   }
    01199
    01200   if (m_next)
    01201     m_next->m_prev = this;
    01202
    01203   // we have a stream, use it to fill the block !
    01204   // this can lead to 0 line blocks which are invalid !
    01205   if (stream)
    01206   {
    01207     // this we lead to either dirty or swapped state
    01208     fillBlock (stream);
    01209   }
    01210   else // init the block if no stream given !
    01211   {
    01212     // fill in one empty line !
    01213     KateTextLine::Ptr textLine = new KateTextLine ();
    01214     m_stringList.push_back (textLine);
    01215     m_lines++;
    01216
    01217     // if we have allready enough blocks around, swap one
    01218     if (m_parent->m_loadedBlocks.count() >= KateBuffer::maxLoadedBlocks())
    01219       m_parent->m_loadedBlocks.first()->swapOut();
    01220
    01221     // we are a new nearly empty dirty block
    01222     m_state = KateBufBlock::stateDirty;
    01223     m_parent->m_loadedBlocks.append (this);
    01224   }
    01225 }
    01226
    01227 KateBufBlock::~KateBufBlock ()
    01228 {
    01229   // sync prev/next pointers
    01230   if (m_prev)
    01231     m_prev->m_next = m_next;
    01232
    01233   if (m_next)
    01234     m_next->m_prev = m_prev;
    01235
    01236   // if we have some swapped data allocated, free it now or never
    01237   if (m_vmblock)
    01238     KateFactory::self()->vm()->free(m_vmblock);
    01239
    01240   // remove me from the list I belong
    01241   KateBufBlockList::remove (this);
    01242 }
    01243
    01244 void KateBufBlock::fillBlock (KateFileLoader *stream)
    01245 {
    01246   // is allready too much stuff around in mem ?
    01247   bool swap = m_parent->m_loadedBlocks.count() >= KateBuffer::maxLoadedBlocks();
    01248
    01249   QByteArray rawData;
    01250
    01251   // calcs the approx size for KATE_AVG_BLOCK_SIZE chars !
    01252   if (swap)
    01253     rawData.resize ((KATE_AVG_BLOCK_SIZE * sizeof(QChar)) + ((KATE_AVG_BLOCK_SIZE/80) * 8));
    01254
    01255   char *buf = rawData.data ();
    01256   uint size = 0;
    01257   uint blockSize = 0;
    01258   while (!stream->eof() && (blockSize < KATE_AVG_BLOCK_SIZE) && (m_lines < KATE_MAX_BLOCK_LINES))
    01259   {
    01260     uint offset = 0, length = 0;
    01261     stream->readLine(offset, length);
    01262     const QChar *unicodeData = stream->unicode () + offset;
    01263
    01264     blockSize += length;
    01265
    01266     if (swap)
    01267     {
    01268       // create the swapped data on the fly, no need to waste time
    01269       // via going over the textline classes and dump them !
    01270       char attr = KateTextLine::flagNoOtherData;
    01271       uint pos = size;
    01272
    01273       // calc new size
    01274       size = size + 1 + sizeof(uint) + (sizeof(QChar)*length);
    01275
    01276       if (size > rawData.size ())
    01277       {
    01278         rawData.resize (size);
    01279         buf = rawData.data ();
    01280       }
    01281
    01282       memcpy(buf+pos, (char *) &attr, 1);
    01283       pos += 1;
    01284
    01285       memcpy(buf+pos, (char *) &length, sizeof(uint));
    01286       pos += sizeof(uint);
    01287
    01288       memcpy(buf+pos, (char *) unicodeData, sizeof(QChar)*length);
    01289       pos += sizeof(QChar)*length;
    01290     }
    01291     else
    01292     {
    01293       KateTextLine::Ptr textLine = new KateTextLine ();
    01294       textLine->insertText (0, length, unicodeData);
    01295       m_stringList.push_back (textLine);
    01296     }
    01297
    01298     m_lines++;
    01299   }
    01300
    01301   if (swap)
    01302   {
    01303     m_vmblock = KateFactory::self()->vm()->allocate(size);
    01304     m_vmblockSize = size;
    01305
    01306     if (!rawData.isEmpty())
    01307     {
    01308       if (!KateFactory::self()->vm()->copyBlock(m_vmblock, rawData.data(), 0, size))
    01309       {
    01310         if (m_vmblock)
    01311           KateFactory::self()->vm()->free(m_vmblock);
    01312
    01313         m_vmblock = 0;
    01314         m_vmblockSize = 0;
    01315
    01316         m_parent->m_cacheWriteError = true;
    01317       }
    01318     }
    01319
    01320     // fine, we are swapped !
    01321     m_state = KateBufBlock::stateSwapped;
    01322   }
    01323   else
    01324   {
    01325     // we are a new dirty block without any swap data
    01326     m_state = KateBufBlock::stateDirty;
    01327     m_parent->m_loadedBlocks.append (this);
    01328   }
    01329
    01330   kdDebug (13020) << "A BLOCK LOADED WITH LINES: " << m_lines << endl;
    01331 }
    01332
    01333 KateTextLine::Ptr KateBufBlock::line(uint i)
    01334 {
    01335   // take care that the string list is around !!!
    01336   if (m_state == KateBufBlock::stateSwapped)
    01337     swapIn ();
    01338
    01339   // LRU
    01340   if (!m_parent->m_loadedBlocks.isLast(this))
    01341     m_parent->m_loadedBlocks.append (this);
    01342
    01343   return m_stringList[i];
    01344 }
    01345
    01346 void KateBufBlock::insertLine(uint i, KateTextLine::Ptr line)
    01347 {
    01348   // take care that the string list is around !!!
    01349   if (m_state == KateBufBlock::stateSwapped)
    01350     swapIn ();
    01351
    01352   m_stringList.insert (m_stringList.begin()+i, line);
    01353   m_lines++;
    01354
    01355   markDirty ();
    01356 }
    01357
    01358 void KateBufBlock::removeLine(uint i)
    01359 {
    01360   // take care that the string list is around !!!
    01361   if (m_state == KateBufBlock::stateSwapped)
    01362     swapIn ();
    01363
    01364   m_stringList.erase (m_stringList.begin()+i);
    01365   m_lines--;
    01366
    01367   markDirty ();
    01368 }
    01369
    01370 void KateBufBlock::markDirty ()
    01371 {
    01372   if (m_state != KateBufBlock::stateSwapped)
    01373   {
    01374     // LRU
    01375     if (!m_parent->m_loadedBlocks.isLast(this))
    01376       m_parent->m_loadedBlocks.append (this);
    01377
    01378     if (m_state == KateBufBlock::stateClean)
    01379     {
    01380       // if we have some swapped data allocated which is dirty, free it now
    01381       if (m_vmblock)
    01382         KateFactory::self()->vm()->free(m_vmblock);
    01383
    01384       m_vmblock = 0;
    01385       m_vmblockSize = 0;
    01386
    01387       // we are dirty
    01388       m_state = KateBufBlock::stateDirty;
    01389     }
    01390   }
    01391 }
    01392
    01393 void KateBufBlock::swapIn ()
    01394 {
    01395   if (m_state != KateBufBlock::stateSwapped)
    01396     return;
    01397
    01398   QByteArray rawData (m_vmblockSize);
    01399
    01400   // what to do if that fails ?
    01401   if (!KateFactory::self()->vm()->copyBlock(rawData.data(), m_vmblock, 0, rawData.size()))
    01402     m_parent->m_cacheReadError = true;
    01403
    01404   // reserve mem, keep realloc away on push_back
    01405   m_stringList.reserve (m_lines);
    01406
    01407   char *buf = rawData.data();
    01408   for (uint i=0; i < m_lines; i++)
    01409   {
    01410     KateTextLine::Ptr textLine = new KateTextLine ();
    01411     buf = textLine->restore (buf);
    01412     m_stringList.push_back (textLine);
    01413   }
    01414
    01415   // if we have allready enough blocks around, swap one
    01416   if (m_parent->m_loadedBlocks.count() >= KateBuffer::maxLoadedBlocks())
    01417     m_parent->m_loadedBlocks.first()->swapOut();
    01418
    01419   // fine, we are now clean again, save state + append to clean list
    01420   m_state = KateBufBlock::stateClean;
    01421   m_parent->m_loadedBlocks.append (this);
    01422 }
    01423
    01424 void KateBufBlock::swapOut ()
    01425 {
    01426   if (m_state == KateBufBlock::stateSwapped)
    01427     return;
    01428
    01429   if (m_state == KateBufBlock::stateDirty)
    01430   {
    01431     bool haveHl = m_parent->m_highlight && !m_parent->m_highlight->noHighlighting();
    01432
    01433     // Calculate size.
    01434     uint size = 0;
    01435     for (uint i=0; i < m_lines; i++)
    01436       size += m_stringList[i]->dumpSize (haveHl);
    01437
    01438     QByteArray rawData (size);
    01439     char *buf = rawData.data();
    01440
    01441     // Dump textlines
    01442     for (uint i=0; i < m_lines; i++)
    01443       buf = m_stringList[i]->dump (buf, haveHl);
    01444
    01445     m_vmblock = KateFactory::self()->vm()->allocate(rawData.size());
    01446     m_vmblockSize = rawData.size();
    01447
    01448     if (!rawData.isEmpty())
    01449     {
    01450       if (!KateFactory::self()->vm()->copyBlock(m_vmblock, rawData.data(), 0, rawData.size()))
    01451       {
    01452         if (m_vmblock)
    01453           KateFactory::self()->vm()->free(m_vmblock);
    01454
    01455         m_vmblock = 0;
    01456         m_vmblockSize = 0;
    01457
    01458         m_parent->m_cacheWriteError = true;
    01459
    01460         return;
    01461       }
    01462     }
    01463   }
    01464
    01465   m_stringList.clear();
    01466
    01467   // we are now swapped out, set state + remove us out of the lists !
    01468   m_state = KateBufBlock::stateSwapped;
    01469   KateBufBlockList::remove (this);
    01470 }
    01471
    01472 //END KateBufBlock
    01473
    01474 //BEGIN KateBufBlockList
    01475
    01476 KateBufBlockList::KateBufBlockList ()
    01477  : m_count (0),
    01478    m_first (0),
    01479    m_last (0)
    01480 {
    01481 }
    01482
    01483 void KateBufBlockList::append (KateBufBlock *buf)
    01484 {
    01485   if (buf->list)
    01486     buf->list->removeInternal (buf);
    01487
    01488   m_count++;
    01489
    01490   // append a element
    01491   if (m_last)
    01492   {
    01493     m_last->listNext = buf;
    01494
    01495     buf->listPrev = m_last;
    01496     buf->listNext = 0;
    01497
    01498     m_last = buf;
    01499
    01500     buf->list = this;
    01501
    01502     return;
    01503   }
    01504
    01505   // insert the first element
    01506   m_last = buf;
    01507   m_first = buf;
    01508
    01509   buf->listPrev = 0;
    01510   buf->listNext = 0;
    01511
    01512   buf->list = this;
    01513 }
    01514
    01515 void KateBufBlockList::removeInternal (KateBufBlock *buf)
    01516 {
    01517   if (buf->list != this)
    01518     return;
    01519
    01520   m_count--;
    01521
    01522   if ((buf == m_first) && (buf == m_last))
    01523   {
    01524     // last element removed !
    01525     m_first = 0;
    01526     m_last = 0;
    01527   }
    01528   else if (buf == m_first)
    01529   {
    01530     // first element removed
    01531     m_first = buf->listNext;
    01532     m_first->listPrev = 0;
    01533   }
    01534   else if (buf == m_last)
    01535   {
    01536     // last element removed
    01537     m_last = buf->listPrev;
    01538     m_last->listNext = 0;
    01539   }
    01540   else
    01541   {
    01542     buf->listPrev->listNext = buf->listNext;
    01543     buf->listNext->listPrev = buf->listPrev;
    01544   }
    01545
    01546   buf->listPrev = 0;
    01547   buf->listNext = 0;
    01548
    01549   buf->list = 0;
    01550 }
    01551
    01552 //END KateBufBlockList
    01553
    01554 // kate: space-indent on; indent-width 2; replace-tabs on;

This file is part of the documentation for kate Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:36:29 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003