• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

Kate

katerenderrange.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2003-2006 Hamish Rodda <rodda@kde.org>
00003    Copyright (C) 2007 Mirko Stocker <me@misto.ch>
00004    Copyright (C) 2008 David Nolden <david.nolden.kdevelop@art-master.de>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License version 2 as published by the Free Software Foundation.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "katerenderrange.h"
00022 
00023 #include <limits.h>
00024 
00025 #include "katesmartrange.h"
00026 #include "katedynamicanimation.h"
00027 
00030 static int lowerBound(const QList<KTextEditor::SmartRange*>& ranges, const KTextEditor::Cursor& pos)
00031 {
00032     int begin = 0;
00033     int n = ranges.count();
00034 
00035     int half;
00036     int middle;
00037 
00038     while (n > 0) {
00039         half = n >> 1;
00040         middle = begin + half;
00041         if(ranges[middle]->end() > pos) {
00042           n = half;
00043         }else{
00044           begin = middle + 1;
00045           n -= half + 1;
00046         }
00047     }
00048     return begin;
00049 }
00050 
00051 bool KateRenderRange::isReady() const {
00052     return false;
00053 }
00054 
00055 bool SmartRenderRange::isReady() const {
00056     return !m_currentRange;
00057 }
00058 
00059 SmartRenderRange::SmartRenderRange(KTextEditor::SmartRange* range, const SmartRenderRange& cloneFrom) : m_currentRange(cloneFrom.m_currentRange), m_endAtRange(range), m_view(cloneFrom.m_view), m_useDynamic(cloneFrom.m_useDynamic), m_list(cloneFrom.m_list) {
00060   Q_ASSERT(range);
00061   addTo(range);
00062   Q_ASSERT(m_currentRange == range);
00063   m_currentPos = range->start();
00064 }
00065 
00066 SmartRenderRange::SmartRenderRange(KateSmartRange* range, bool useDynamic, KateView* view, RenderRangeList* list)
00067   : m_currentRange(0L)
00068   , m_endAtRange(0)
00069   , m_view(view)
00070   , m_useDynamic(useDynamic)
00071   , m_list(list)
00072 {
00073   Q_ASSERT(range);
00074   addTo(range);
00075   m_currentPos = range->start();
00076 }
00077 
00078 KTextEditor::Cursor SmartRenderRange::nextBoundary() const
00079 {
00080   if (!m_currentRange || m_currentRange->end() <= m_currentPos)
00081     return KTextEditor::Cursor(INT_MAX,INT_MAX);
00082   if(m_currentPos < m_currentRange->start())
00083     return m_currentRange->start();
00084 
00085   KTextEditor::Cursor ret = m_currentRange->end();
00086   
00087   for(int child = lowerBound(m_currentRange->childRanges(), m_currentPos); child != m_currentRange->childRanges().size(); ++child) {
00088     KTextEditor::SmartRange* c = m_currentRange->childRanges()[child];
00089     
00090     if(!c->isEmpty() && !m_ignoreChildRanges.contains(c)) {
00091       if(c->start() > m_currentPos) {
00092         if(c->start() < ret)
00093             ret = c->start();
00094       
00095         if(c->overlapCount() == 0)
00096            //We don't need to search on, since there is no range overlapping the given one, thus we have already found 
00097            //the nearest range-start.
00098           break;
00099       }
00100     }
00101   }
00102   return ret;
00103 }
00104 
00105 bool SmartRenderRange::advanceTo(const KTextEditor::Cursor& pos)
00106 {
00107   m_currentPos = pos;
00108 
00109   if (!m_currentRange)
00110     return false;
00111 
00112   //Go up until the position is contained in m_currentRange
00113   while (m_currentRange && !m_currentRange->contains(pos) && m_currentRange->parentRange() && m_currentRange != m_endAtRange) {
00114     m_currentRange = m_currentRange->parentRange();
00115     m_attribs.pop();
00116   }
00117 
00118   if(m_currentPos >= m_currentRange->end()) {
00119     m_currentRange = 0; //We're ready with this range
00120     return false;
00121   }
00122   
00123   int currentChildCount = m_currentRange->childRanges().size();
00124   const QList<KTextEditor::SmartRange*>& currentChildRanges(m_currentRange->childRanges());
00125   
00126   int nextChild = lowerBound(currentChildRanges, pos);
00127   //If we skip a child, we must not recurse this range into another child,
00128   //else we will never see the skipped child again.
00129 //   int initialNextChild = nextChild;
00130   Q_ASSERT(nextChild <= currentChildCount);
00131   
00132   for(; nextChild < currentChildCount; ++nextChild)
00133   {
00134       if(m_ignoreChildRanges.contains(currentChildRanges[nextChild])) {
00135         if(!currentChildRanges[nextChild]->overlapCount())
00136             nextChild = currentChildCount; //No chance to find a child that contains this cursor
00137         continue;
00138       }
00139       break;
00140   }
00141   
00142   //Now nextChild may contain the position, or not. But it is definitely the range
00143   //we should next recurse into. Create copies for all ranges behind nextChild that overlap it.
00144   
00145   if(nextChild < currentChildCount) {
00146     int findOverlaps = currentChildRanges[nextChild]->overlapCount();
00147     
00148     int overlapCandidate = nextChild+1;
00149     while(findOverlaps && overlapCandidate < currentChildCount) {
00151         if(currentChildRanges[overlapCandidate]->start() < currentChildRanges[nextChild]->end()) {
00152             //found an overlap
00153             if(!m_ignoreChildRanges.contains(currentChildRanges[overlapCandidate]) && currentChildRanges[overlapCandidate]->contains(pos)) {
00154                 //Create additional SmartRenderRange's for all overlaps that are not ignored, and recurse into the first one
00155                 SmartRenderRange* additional = new SmartRenderRange(currentChildRanges[overlapCandidate], *this);
00156                 Q_ASSERT(additional->m_endAtRange == currentChildRanges[overlapCandidate]);
00157                 Q_ASSERT(additional->m_currentRange == currentChildRanges[overlapCandidate]);
00158                 additional->advanceTo(pos);
00159                 m_list->append(additional);
00160                 m_ignoreChildRanges.insert(currentChildRanges[overlapCandidate]);
00161             }
00162             --findOverlaps;
00163         }
00164         ++overlapCandidate;
00165     }
00166     
00167     
00168     if(nextChild < currentChildCount && currentChildRanges[nextChild]->contains(pos)) {
00169         addTo(currentChildRanges[nextChild]);
00170         //Recurse, to enter all needed ranges
00171         advanceTo(pos);
00172     }
00173   }
00174 
00175   return true;
00176 }
00177 
00178 KTextEditor::Attribute::Ptr SmartRenderRange::currentAttribute() const
00179 {
00180   if (m_attribs.count() && m_currentRange->contains(m_currentPos))
00181     return m_attribs.top();
00182   return KTextEditor::Attribute::Ptr();
00183 }
00184 
00185 void SmartRenderRange::addTo(KTextEditor::SmartRange* _range, bool intermediate) const
00186 {
00187   KateSmartRange* range = static_cast<KateSmartRange*>(_range);
00188   
00189   if(range->parentRange() != m_currentRange)
00190     addTo(range->parentRange(), true);
00191   
00192   KTextEditor::SmartRange* r = range;
00193   QStack<KTextEditor::SmartRange*> reverseStack;
00194   while (r != m_currentRange) {
00195     reverseStack.push(r);
00196     r = r->parentRange();
00197   }
00198   
00199   if(m_attribs.isEmpty() || (range->attribute() && (range->attribute()->isValid() || range->attribute()->hasAnyProperty() || (m_useDynamic && range->hasDynamic())))) {
00200     //Only merge attributes if it's required
00201     KTextEditor::Attribute::Ptr a(new KTextEditor::Attribute());
00202     if (!m_attribs.isEmpty())
00203       *a = *m_attribs.top();
00204 
00205     if (KTextEditor::Attribute::Ptr a2 = range->attribute())
00206       *a += *a2;
00207 
00208     if (m_useDynamic && range->hasDynamic())
00209       foreach (KateDynamicAnimation* anim, range->dynamicAnimations())
00210     anim->mergeToAttribute(a);
00211 
00212       m_attribs.push(a);
00213   }else{
00214     m_attribs.push(m_attribs.top());
00215   }
00216 
00217   if(!intermediate)
00218     m_currentRange = range;
00219 }
00220 
00221 NormalRenderRange::NormalRenderRange()
00222   : m_currentRange(0)
00223 {
00224 }
00225 
00226 NormalRenderRange::~NormalRenderRange()
00227 {
00228   QListIterator<pairRA> it = m_ranges;
00229   while (it.hasNext())
00230     delete it.next().first;
00231 }
00232 
00233 void NormalRenderRange::addRange(KTextEditor::Range* range, KTextEditor::Attribute::Ptr attribute)
00234 {
00235   m_ranges.append(pairRA(range, attribute));
00236 }
00237 
00238 KTextEditor::Cursor NormalRenderRange::nextBoundary() const
00239 {
00240   int index = m_currentRange;
00241   while (index < m_ranges.count()) {
00242     if (m_ranges.at(index).first->start() > m_currentPos)
00243       return m_ranges.at(index).first->start();
00244 
00245     else if (m_ranges.at(index).first->end() > m_currentPos)
00246       return m_ranges.at(index).first->end();
00247 
00248     ++index;
00249 
00250   }
00251 
00252   return KTextEditor::Cursor(INT_MAX, INT_MAX);
00253 }
00254 
00255 bool NormalRenderRange::advanceTo(const KTextEditor::Cursor& pos)
00256 {
00257   m_currentPos = pos;
00258 
00259   int index = m_currentRange;
00260   while (index < m_ranges.count()) {
00261     if (m_ranges.at(index).first->end() <= pos) {
00262       ++index;
00263 
00264     } else {
00265       bool ret = index != m_currentRange;
00266       m_currentRange = index;
00267       return ret;
00268     }
00269   }
00270 
00271   return false;
00272 }
00273 
00274 KTextEditor::Attribute::Ptr NormalRenderRange::currentAttribute() const
00275 {
00276   if (m_currentRange < m_ranges.count() && m_ranges[m_currentRange].first->contains(m_currentPos))
00277     return m_ranges[m_currentRange].second;
00278 
00279   return KTextEditor::Attribute::Ptr();
00280 }
00281 
00282 void RenderRangeList::appendRanges(const QList<KTextEditor::SmartRange*>& startingRanges, bool useDynamic, KateView* view)
00283 {
00284   foreach (KTextEditor::SmartRange* range, startingRanges)
00285     append(new SmartRenderRange(static_cast<KateSmartRange*>(range), useDynamic, view, this));
00286 }
00287 
00288 KTextEditor::Cursor RenderRangeList::nextBoundary() const
00289 {
00290   KTextEditor::Cursor ret = m_currentPos;
00291   bool first = true;
00292   foreach (KateRenderRange* r, *this) {
00293     if (first) {
00294       ret = r->nextBoundary();
00295       first = false;
00296 
00297     } else {
00298       KTextEditor::Cursor nb = r->nextBoundary();
00299       if (ret > nb)
00300         ret = nb;
00301     }
00302   }
00303   return ret;
00304 }
00305 
00306 RenderRangeList::~RenderRangeList()
00307 {
00308 }
00309 
00310 void RenderRangeList::advanceTo(const KTextEditor::Cursor& pos)
00311 {
00312   foreach (KateRenderRange* r, *this)
00313     r->advanceTo(pos);
00314   
00315   //Delete lists that are ready, else the list may get too large due to temporaries
00316   for(int a = size()-1; a >= 0; --a) {
00317       KateRenderRange* r = at(a);
00318       if(r->isReady()) {
00319           delete r;
00320           removeAt(a);
00321       }
00322   }
00323 }
00324 
00325 bool RenderRangeList::hasAttribute() const
00326 {
00327   foreach (KateRenderRange* r, *this)
00328     if (r->currentAttribute())
00329       return true;
00330 
00331   return false;
00332 }
00333 
00334 KTextEditor::Attribute::Ptr RenderRangeList::generateAttribute() const
00335 {
00336   KTextEditor::Attribute::Ptr a;
00337   bool ownsAttribute = false;
00338 
00339   foreach (KateRenderRange* r, *this) {
00340     if (KTextEditor::Attribute::Ptr a2 = r->currentAttribute()) {
00341       if(!a) {
00342     a = a2;
00343       }else {
00344     if(!ownsAttribute) {
00345       //Make an own copy of the attribute..
00346       ownsAttribute = true;
00347       a = new KTextEditor::Attribute(*a);
00348     }
00349        *a += *a2;
00350       }
00351     }
00352   }
00353 
00354   return a;
00355 }
00356 

Kate

Skip menu "Kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal