Kate
katerenderrange.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00097
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
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;
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
00128
00129
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;
00137 continue;
00138 }
00139 break;
00140 }
00141
00142
00143
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
00153 if(!m_ignoreChildRanges.contains(currentChildRanges[overlapCandidate]) && currentChildRanges[overlapCandidate]->contains(pos)) {
00154
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
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
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
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
00346 ownsAttribute = true;
00347 a = new KTextEditor::Attribute(*a);
00348 }
00349 *a += *a2;
00350 }
00351 }
00352 }
00353
00354 return a;
00355 }
00356