/* This file is part of the KDE libraries
   Copyright (C) 2003-2005 Hamish Rodda <rodda@kde.org>
   Copyright (C) 2008 David Nolden <david.nolden.kdevelop@art-master.de>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "smartrange.h"

#include <QtCore/QStack>

#include "document.h"
#include "view.h"
#include "attribute.h"
#include "rangefeedback.h"

#include <kaction.h>
#include <kdebug.h>

using namespace KTextEditor;

//Uncomment this to enable debugging of the child-order. If it is enabled, an assertion will
//be triggered when the order is violated.
//This is slow.
//    #define SHOULD_DEBUG_CHILD_ORDER

//Uncomment this to debug the m_overlapCount values. When it is enabled,
//extensive tests will be done to verify that the values are true,
//and an assertion is triggered when not.
//This is very slow, especially with many child-ranges.
//    #define SHOULD_DEBUG_OVERLAP

#ifdef SHOULD_DEBUG_CHILD_ORDER
#define DEBUG_CHILD_ORDER \
  {\
  KTextEditor::Cursor lastEnd = KTextEditor::Cursor(-1,-1);\
  for(int a = 0; a < m_childRanges.size(); ++a) {\
    Q_ASSERT(m_childRanges[a]->end() >= lastEnd);\
    Q_ASSERT(m_childRanges[a]->start() >= start());\
    Q_ASSERT(m_childRanges[a]->end() <= end());\
    lastEnd = m_childRanges[a]->end();\
  }\
  }\
  
#else
#define DEBUG_CHILD_ORDER
#endif

#ifdef SHOULD_DEBUG_OVERLAP
#define DEBUG_CHILD_OVERLAP  \
{\
  QVector<int> counter(m_childRanges.size(), 0);\
\
  for(int a = 0; a < m_childRanges.size(); ++a) {\
    const SmartRange& overlapper(*m_childRanges[a]);\
    for(int b = 0; b < a; ++b) {\
      const SmartRange& overlapped(*m_childRanges[b]);\
      Q_ASSERT(overlapped.end() <= overlapper.end());\
      if(overlapped.end() > overlapper.start()) {\
        ++counter[b];\
      }\
    }\
  }\
  for(int a = 0; a < m_childRanges.size(); ++a) {\
    Q_ASSERT(m_childRanges[a]->m_overlapCount == counter[a]);\
  }\
}\

#define DEBUG_PARENT_OVERLAP  \
if(m_parentRange) {\
  QVector<int> counter(m_parentRange->m_childRanges.size(), 0);\
\
  for(int a = 0; a < m_parentRange->m_childRanges.size(); ++a) {\
    const SmartRange& overlapper(*m_parentRange->m_childRanges[a]);\
    for(int b = 0; b < a; ++b) {\
      const SmartRange& overlapped(*m_parentRange->m_childRanges[b]);\
      Q_ASSERT(overlapped.end() <= overlapper.end());\
      if(overlapped.end() > overlapper.start()) {\
        ++counter[b];\
      }\
    }\
  }\
  for(int a = 0; a < m_parentRange->m_childRanges.size(); ++a) {\
    Q_ASSERT(m_parentRange->m_childRanges[a]->m_overlapCount == counter[a]);\
  }\
}\

#else
#define DEBUG_CHILD_OVERLAP
#define DEBUG_PARENT_OVERLAP
#endif

///Returns the index of the first range that ends behind @p pos
///The list must be sorted by the ranges end-positions.
static int lowerBound(const QList<SmartRange*>& ranges, const Cursor& pos)
{
    int begin = 0;
    int n = ranges.count();

    while (n > 0) {
        int half = n >> 1;
        int middle = begin + half;
        if(ranges[middle]->end() > pos) {
          n = half;
        }else{
          begin = middle + 1;
          n -= half + 1;
        }
    }
    return begin;
}

///Searches for the given range, or a lower bound for the given position. Does not work correctly in case of overlaps,
///but for that case we have a fallback. Only for use in findIndex.
static int lowerBoundRange(const QList<SmartRange*>& ranges, const Cursor& pos, const SmartRange* range)
{
    int begin = 0;
    int n = ranges.count();

    while (n > 0) {
        int half = n >> 1;
        int middle = begin + half;
        if(ranges[begin] == range)
          return begin;
        if(ranges[middle] == range)
          return middle;
        
        if(ranges[middle]->end() > pos) {
          n = half;
        }else{
          begin = middle + 1;
          n -= half + 1;
        }
    }
    return begin;
}

///Finds the index of the given SmartRange in the sorted list using binary search. Uses @param range For searching, and @param smartRange for equality comparison.
static int findIndex(const QList<SmartRange*>& ranges, const SmartRange* smartRange, const Range* range) {
  int index = lowerBoundRange(ranges, range->start(), smartRange);
  int childCount = ranges.count();
  
  //In case of degenerated ranges, we may have found the wrong index.
  while(index < childCount && ranges[index] != smartRange)
    ++index;

  if(index == childCount) {
    //During rangeChanged the order may temporarily be inconsistent, so we use indexOf as fallback
    return ranges.indexOf(const_cast<SmartRange*>(smartRange));
/*    if(smartRange != range) //Try again finding the range, using the smart-range only
      return findIndex(ranges, smartRange, smartRange);*/
    
//     Q_ASSERT(ranges.indexOf(const_cast<SmartRange*>(smartRange)) == -1);
    return -1;
  }
  
  return index;
}

SmartRange::SmartRange(SmartCursor* start, SmartCursor* end, SmartRange * parent, InsertBehaviors insertBehavior )
  : Range(start, end)
  , m_attribute(0L)
  , m_parentRange(parent)
  , m_ownsAttribute(false)
  , m_overlapCount(0)
{
  setInsertBehavior(insertBehavior);

  // Not calling setParentRange here...:
  // 1) subclasses are not yet constructed
  // 2) it would otherwise give the wrong impression
  if (m_parentRange)
    m_parentRange->insertChildRange(this);
}

SmartRange::~SmartRange( )
{
  deleteChildRanges();

  setParentRange(0L);

  /*if (!m_deleteCursors)
  {
    // Save from deletion in the parent
    m_start = 0L;
    m_end = 0L;
  }*/
}

bool SmartRange::confineToRange(const Range& range)
{
  if (!Range::confineToRange(range))
    // Don't need to check if children should be confined, they already are
    return false;

  foreach (SmartRange* child, m_childRanges)
    child->confineToRange(*this);

  return true;
}

bool SmartRange::expandToRange(const Range& range)
{
  if (!Range::expandToRange(range))
    // Don't need to check if parents should be expanded, they already are
    return false;

  if (parentRange())
    parentRange()->expandToRange(*this);
  
  return true;
}

void SmartRange::setRange(const Range& range)
{
  if (range == *this)
    return;

  Range old = *this;

  Range::setRange(range);
  
  DEBUG_CHILD_OVERLAP
}

const QList<SmartRange*>& SmartRange::childRanges() const
{
  return m_childRanges;
}

SmartRange * SmartRange::childBefore( const SmartRange * range ) const
{
  int index = findIndex(m_childRanges, range, range);
  
  if (--index >= 0)
    return m_childRanges[index];
  
  return 0L;
}

SmartRange * SmartRange::childAfter( const SmartRange * range ) const
{
  int index = findIndex(m_childRanges, range, range);
  if (index != -1 && ++index < m_childRanges.count())
    return m_childRanges[index];
  return 0L;
}

void SmartRange::insertChildRange( SmartRange * newChild )
{
  DEBUG_CHILD_OVERLAP

  Q_ASSERT(newChild->parentRange() == this);

  // A new child has been added, so expand this range if required.
  expandToRange(*newChild);
  
  DEBUG_CHILD_ORDER

  int insertAt = lowerBound(m_childRanges, newChild->end());
  m_childRanges.insert(insertAt, newChild);
  
  //Increase the overlap of previous ranges
  for(int current = insertAt-1; current >= 0; --current) {
    SmartRange& range(*m_childRanges[current]);
    Q_ASSERT(range.end() <= newChild->end());
    
    if(range.end() > newChild->start()) {
      ++range.m_overlapCount;
    }else{
      //range.end() <= start(), The range does not overlap, and the same applies for all earlier ranges
      break;
    }
  }

  //Increase this ranges overlap from already existing ranges
  for(int current = insertAt+1; current < m_childRanges.size(); ++current) {
    SmartRange& range(*m_childRanges[current]);
    Q_ASSERT(range.end() >= newChild->end());
    
    if(range.start() < newChild->end())
      ++newChild->m_overlapCount; //The range overlaps newChild
    
    if(!range.m_overlapCount)
      break; //If this follower-range isn't overlapped by any other ranges, we can break here.
  }

  DEBUG_CHILD_OVERLAP

  DEBUG_CHILD_ORDER
  
  QMutableListIterator<SmartRange*> it = m_childRanges;
  it.toBack();

  foreach (SmartRangeNotifier* n, m_notifiers)
    emit n->childRangeInserted(this, newChild);

  foreach (SmartRangeWatcher* w, m_watchers)
    w->childRangeInserted(this, newChild);
  
  DEBUG_CHILD_OVERLAP
  DEBUG_CHILD_ORDER
}

void SmartRange::removeChildRange(SmartRange* child)
{
  DEBUG_CHILD_OVERLAP
  
  int index = findIndex(m_childRanges, child, child);
  if (index != -1) {
    m_childRanges.removeAt(index);

    //Reduce the overlap with all previously overlapping ranges(parentChildren is still sorted by the old end-position)
    for(int current = index-1; current >= 0; --current) {
      SmartRange& range(*m_childRanges[current]);
      Q_ASSERT(range.end() <= child->end());
      if(range.end() <= child->start()) {
        break; //This range did not overlap before, the same applies for all earlier ranges because of the order
      }else{
        if(range.m_overlapCount) {
          --range.m_overlapCount;
        } else {
          //May happen with more than 64 overlaps
#ifdef SHOULD_DEBUG_OVERLAP
          Q_ASSERT(0);
#endif
        }
      }
    }
    
    DEBUG_CHILD_OVERLAP
    
    child->m_overlapCount = 0; //It has no neighbors any more, so no overlap
    
    foreach (SmartRangeNotifier* n, m_notifiers)
      emit n->childRangeInserted(this, child);

    foreach (SmartRangeWatcher* w, m_watchers)
      w->childRangeInserted(this, child);
  }

  DEBUG_CHILD_OVERLAP
}

SmartRange * SmartRange::mostSpecificRange( const Range & input ) const
{
  if (!input.isValid())
    return 0L;

  if (contains(input)) {
    int child = lowerBound(m_childRanges, input.start());

    SmartRange* mostSpecific = 0;
    
    while(child != m_childRanges.size()) {
      SmartRange* r = m_childRanges[child];
      if(r->contains(input)) {
        SmartRange* candidate = r->mostSpecificRange(input);
        if(mostSpecific == 0 ||
          ((candidate->end() - candidate->start()) < (mostSpecific->end() - mostSpecific->start())) ||
          (candidate->end() < mostSpecific->end()))
          mostSpecific = candidate;
      }
      
      if(r->m_overlapCount == 0)
        break;
      
      ++child; //We have to iterate as long as there is overlapping ranges
    }

    if(mostSpecific)
      return mostSpecific;
    else
      return const_cast<SmartRange*>(this);

  } else if (parentRange()) {
    return parentRange()->mostSpecificRange(input);

  } else {
    return 0L;
  }
}

SmartRange * SmartRange::firstRangeContaining( const Cursor & pos ) const
{
  if (!pos.isValid())
    return 0L;

  if (contains(pos)) {
    if (parentRange() && parentRange()->contains(pos))
      return parentRange()->firstRangeContaining(pos);

    return const_cast<SmartRange*>(this);

  } else {
    if (!parentRange())
      return 0L;

    return parentRange()->firstRangeContaining(pos);
  }
}

int SmartRange::overlapCount() const
{
  return m_overlapCount;
}

QList<SmartRange*> SmartRange::deepestRangesContaining(const Cursor& pos) const
{
  QList<SmartRange*> ret;
  
  if(!contains(pos))
    return ret;
  
  int child = lowerBound(m_childRanges, pos);
  
  while(child != m_childRanges.size()) {
    SmartRange* r = m_childRanges[child];
    //The list will be unchanged if the range doesn't contain the position
    ret += r->deepestRangesContaining(pos);
    
    if(r->m_overlapCount == 0)
      break;
    
    ++child; //We have to iterate as long as there is overlapping ranges
  }
  
  if(!ret.isEmpty())
    return ret;
  else
    return ret << const_cast<SmartRange*>(this);
}

SmartRange * SmartRange::deepestRangeContaining( const Cursor & pos, QStack<SmartRange*>* rangesEntered, QStack<SmartRange*>* rangesExited ) const
{
  if (!pos.isValid()) {
    // Just leave all ranges
    if (rangesExited) {
      SmartRange* range = const_cast<SmartRange*>(this);
      while (range) {
        rangesExited->append(range);
        range = range->parentRange();
      }
    }
    return 0L;
  }

  return deepestRangeContainingInternal(pos, rangesEntered, rangesExited, true);
}

SmartRange * SmartRange::deepestRangeContainingInternal( const Cursor & pos, QStack<SmartRange*>* rangesEntered, QStack<SmartRange*>* rangesExited, bool first ) const
{
  if (contains(pos)) {
    if (!first && rangesEntered)
      rangesEntered->push(const_cast<SmartRange*>(this));

    int child = lowerBound(m_childRanges, pos);

    QStack<SmartRange*> mostSpecificStack;
    SmartRange* mostSpecific = 0;
    
    while(child != m_childRanges.size()) {
      SmartRange* r = m_childRanges[child];
      if(r->contains(pos)) {
        QStack<SmartRange*> candidateStack;
        SmartRange* candidateRange = r->deepestRangeContainingInternal(pos, rangesEntered ? &candidateStack : 0, 0);
        
        Q_ASSERT(!rangesEntered || !candidateStack.isEmpty());
        Q_ASSERT(candidateRange);
        
        if(!mostSpecific ||
          ((candidateRange->end() - candidateRange->start()) < (mostSpecific->end() - mostSpecific->start())) ||
          (candidateRange->end() < mostSpecific->end())) {
          mostSpecific = candidateRange;
          mostSpecificStack = candidateStack;
        }
      }
      
      if(r->m_overlapCount == 0)
        break;
      
      ++child; //We have to iterate as long as there is overlapping ranges
    }
    
    if(mostSpecific) {
      if(rangesEntered)
        *rangesEntered += mostSpecificStack;
      return mostSpecific;
    }
    
    return const_cast<SmartRange*>(this);

  } else {
    if (rangesExited)
      rangesExited->push(const_cast<SmartRange*>(this));

    if (!parentRange())
      return 0L;

    // first is true, because the parentRange won't be "entered" on first descent
    return parentRange()->deepestRangeContainingInternal(pos, rangesEntered, rangesExited, true);
  }
}

Document* SmartRange::document( ) const
{
  return smartStart().document();
}

void SmartRange::associateAction( KAction * action )
{
  m_associatedActions.append(action);

  bool enable = false;
  if (View* v = document()->activeView())
    if (contains(v->cursorPosition()))
      enable = true;

  action->setEnabled(enable);

  if (m_associatedActions.count() == 1)
    checkFeedback();
}

void SmartRange::dissociateAction( KAction * action )
{
  m_associatedActions.removeAll(action);
  if (!m_associatedActions.count())
    checkFeedback();
}

void SmartRange::clearAssociatedActions( )
{
  m_associatedActions.clear();
  checkFeedback();
}

SmartRange::InsertBehaviors SmartRange::insertBehavior( ) const
{
  return ((smartStart().insertBehavior() == SmartCursor::MoveOnInsert) ? DoNotExpand : ExpandLeft) | ((smartEnd().insertBehavior() == SmartCursor::MoveOnInsert) ? ExpandRight : DoNotExpand);
}

void SmartRange::setInsertBehavior(SmartRange::InsertBehaviors behavior)
{
  static_cast<SmartCursor*>(m_start)->setInsertBehavior((behavior & ExpandLeft) ? SmartCursor::StayOnInsert : SmartCursor::MoveOnInsert);
  static_cast<SmartCursor*>(m_end)->setInsertBehavior((behavior & ExpandRight) ? SmartCursor::MoveOnInsert : SmartCursor::StayOnInsert);
}

void SmartRange::clearChildRanges()
{
  foreach (SmartRange* r, m_childRanges)
    r->removeText();
}

void SmartRange::deleteChildRanges()
{
  // FIXME: Probably more efficient to prevent them from unlinking themselves?
  qDeleteAll(m_childRanges);

  // i.e. this is probably already clear
  m_childRanges.clear();
}

void SmartRange::clearAndDeleteChildRanges( )
{
  // FIXME: Probably more efficient to prevent them from unlinking themselves?
  foreach (SmartRange* r, m_childRanges)
    r->removeText();

  qDeleteAll(m_childRanges);

  // i.e. this is probably already clear
  m_childRanges.clear();
}

void SmartRange::setParentRange( SmartRange * r )
{
  if (m_parentRange == r)
    return;
  
  DEBUG_PARENT_OVERLAP

  if (m_parentRange)
    m_parentRange->removeChildRange(this);

  SmartRange* oldParent = m_parentRange;

  m_parentRange = r;

  if (m_parentRange)
    m_parentRange->insertChildRange(this);

  foreach (SmartRangeNotifier* n, m_notifiers)
    emit n->parentRangeChanged(this, m_parentRange, oldParent);

  foreach (SmartRangeWatcher* w, m_watchers)
    w->parentRangeChanged(this, m_parentRange, oldParent);
  
  DEBUG_PARENT_OVERLAP
}

void SmartRange::setAttribute( Attribute::Ptr attribute )
{
  if (attribute == m_attribute)
    return;

  Attribute::Ptr prev = m_attribute;

  m_attribute = attribute;

  foreach (SmartRangeNotifier* n, m_notifiers)
    emit n->rangeAttributeChanged(this, attribute, prev);

  foreach (SmartRangeWatcher* w, m_watchers)
    w->rangeAttributeChanged(this, attribute, prev);
}

Attribute::Ptr SmartRange::attribute( ) const
{
  return m_attribute;
}

QStringList SmartRange::text( bool block ) const
{
  return document()->textLines(*this, block);
}

bool SmartRange::replaceText( const QStringList & text, bool block )
{
  return document()->replaceText(*this, text, block);
}

bool SmartRange::removeText( bool block )
{
  return document()->removeText(*this, block);
}

static bool rangeEndLessThan(const SmartRange* s1, const SmartRange* s2) {
  return s1->end() < s2->end();
}

void SmartRange::rebuildChildStructure() {
  
  ///Re-order
  qStableSort(m_childRanges.begin(), m_childRanges.end(), rangeEndLessThan);
  DEBUG_CHILD_ORDER
  ///Update overlap
  for(int a = 0; a < m_childRanges.size(); ++a) {
    SmartRange& overlapper(*m_childRanges[a]);
    overlapper.m_overlapCount = 0;
    
    //Increase the overlap of overlapped ranegs
    for(int current = a-1; current >= 0; --current) {
      SmartRange& range(*m_childRanges[current]);
      Q_ASSERT(range.end() <= overlapper.end());
      
      if(range.end() > overlapper.start()) {
        ++range.m_overlapCount;
      }else{
        //range.end() <= start(), The range does not overlap, and the same applies for all earlier ranges
        break;
      }
    }
  }
  
  DEBUG_CHILD_OVERLAP
}

void SmartRange::rangeChanged( Cursor* c, const Range& from )
{
#ifdef SHOULD_DEBUG_CHILD_ORDER
  if (parentRange() ) {
    //Make sure the child-order is correct, in respect to "from"
    QList<SmartRange*>& parentChildren(parentRange()->m_childRanges);
    
    int index = findIndex(parentChildren, this, &from);
    Q_ASSERT(index != -1);
    Q_ASSERT(parentChildren[index] == this);
    const Range* lastRange = 0;
    for(int a = 0; a < index; ++a) {
      if(lastRange) {
        Q_ASSERT(lastRange->end() <= parentChildren[a]->end());
      }
      lastRange = parentChildren[a];
    }
    
    if(lastRange) {
      Q_ASSERT(lastRange->end() <= from.end());
    }
    
    if(index+1 < parentChildren.size()) {
      Q_ASSERT(from.end() <= parentChildren[index+1]->end());
    }
    lastRange = &from;
    
    for(int a = index+1; a < parentChildren.size(); ++a) {
      if(lastRange) {
        Q_ASSERT(lastRange->end() <= parentChildren[a]->end());
      }
      lastRange = parentChildren[a];
    }
  }
#endif
  Range::rangeChanged(c, from);

  // Decide whether the parent range has expanded or contracted, if there is one
  if (parentRange() ) {
    QList<SmartRange*>& parentChildren(parentRange()->m_childRanges);
    
    int index = findIndex(parentChildren, this, &from);
    Q_ASSERT(index != -1);
    Q_ASSERT(parentChildren[index] == this);
    
    //Reduce the overlap with all previously overlapping ranges(parentChildren is still sorted by the old end-position)
    for(int current = index-1; current >= 0; --current) {
      SmartRange& range(*parentChildren[current]);
      Q_ASSERT(range.end() <= from.end());
      if(range.end() <= from.start()) {
//         break; //This range did not overlap before, the same applies for all earlier ranges because of the order
      }else{
        if(range.m_overlapCount) {
          --range.m_overlapCount;
        }else{
#ifdef SHOULD_DEBUG_OVERLAP
          Q_ASSERT(0);
#endif
        }
      }
    }
    
  //Decrease this ranges overlap from existing ranges behind, since it may be moved so it isn't overlapped any more
  for(int current = index+1; current < parentChildren.size(); ++current) {
    SmartRange& range(*parentChildren[current]);
    Q_ASSERT(range.end() >= from.end());
    
    if(range.start() < from.end())
      --m_overlapCount; //The range overlaps newChild
    
    if(!range.m_overlapCount)
      break; //If this follower-range isn't overlapped by any other ranges, we can break here.
  }
    
    if(from.end() != end()) {
      //Update the order in the parent, the ranges must be strictly sorted
      if(from.end() > end()) {
        //Bubble backwards, the position has been reduced
        while(index > 0 && parentChildren[index-1]->end() > end()) {
          parentChildren[index] = parentChildren[index-1];
          parentChildren[index-1] = this;
          --index;
        }
      }else{
        //Bubble forwards, the position has moved forwards
        while( index+1 < parentChildren.size() && (parentChildren[index+1]->end() < end()) ) {
          parentChildren[index] = parentChildren[index+1];
          parentChildren[index+1] = this;
          ++index;
        }
      }
    }
    Q_ASSERT(parentChildren[index] == this);
    
    //Increase the overlap
    for(int current = index-1; current >= 0; --current) {
      SmartRange& range(*parentChildren[current]);
      Q_ASSERT(range.end() <= end());
      
      if(range.end() > start()) {
        ++range.m_overlapCount;
      }else{
        //range.end() <= start(), The range does not overlap, and the same applies for all earlier ranges
        break;
      }
    }
    
  //Increase this ranges overlap from existing ranges behind, since it may have been moved
  for(int current = index+1; current < parentChildren.size(); ++current) {
    SmartRange& range(*parentChildren[current]);
    Q_ASSERT(range.end() >= end());
    
    if(range.start() < end())
      ++m_overlapCount; //The range overlaps newChild
    
    if(!range.m_overlapCount)
      break; //If this follower-range isn't overlapped by any other ranges, we can break here.
  }
    
  DEBUG_CHILD_ORDER
  DEBUG_PARENT_OVERLAP
  
  //Expand the parent in the end, so the overlap is consistent when the parent gets control
  if ((start() < from.start() || end() > from.end()))
    parentRange()->expandToRange(*this);
  }
  
  DEBUG_CHILD_OVERLAP

  
  // Contract child ranges if required
  if(!m_childRanges.isEmpty()) {
    if (start() > from.start()) {
      foreach(SmartRange* child, m_childRanges) {
        if(child->start() < start())
          child->start() = start();
        else if(!child->m_overlapCount)
          break; //We can safely break here, because the child is not overlapped
      }
    }

    if (end() < from.end()) {
      
      //We have to create a copy of the child-ranges, because their order may change
      QList<SmartRange*> oldChildRanges = m_childRanges;
      
      for(int a = oldChildRanges.size()-1; a >= 0; --a) {
        if(oldChildRanges[a]->end() <= end())
          break; //Child-ranges are sorted by the end-cursor, so we can just break here.
        oldChildRanges[a]->end() = end();
      }
    }
  }

  DEBUG_CHILD_ORDER
  DEBUG_CHILD_OVERLAP
  
  // SmartCursor and its subclasses take care of adjusting ranges if the tree
  // structure is being used.
  foreach (SmartRangeNotifier* n, m_notifiers)
    if (n->wantsDirectChanges()) {
      emit n->rangePositionChanged(this);
      emit n->rangeContentsChanged(this);

      if (start() == end())
        emit n->rangeEliminated(this);
    }

  foreach (SmartRangeWatcher* w, m_watchers)
    if (w->wantsDirectChanges()) {
      w->rangePositionChanged(this);
      w->rangeContentsChanged(this);

      if (start() == end())
        w->rangeEliminated(this);
    }
}

bool SmartRange::isSmartRange( ) const
{
  return true;
}

SmartRange* SmartRange::toSmartRange( ) const
{
  return const_cast<SmartRange*>(this);
}

bool SmartRange::hasParent( SmartRange * parent ) const
{
  if (parentRange() == parent)
    return true;

  if (parentRange())
    return parentRange()->hasParent(parent);

  return false;
}

const QList< SmartRangeWatcher * > & SmartRange::watchers( ) const
{
  return m_watchers;
}

void SmartRange::addWatcher( SmartRangeWatcher * watcher )
{
  if (!m_watchers.contains(watcher))
    m_watchers.append(watcher);

  checkFeedback();
}

void SmartRange::removeWatcher( SmartRangeWatcher * watcher )
{
  m_watchers.removeAll(watcher);
  checkFeedback();
}

SmartRangeNotifier * SmartRange::primaryNotifier( )
{
  if (m_notifiers.isEmpty())
    m_notifiers.append(createNotifier());

  return m_notifiers.first();
}

const QList< SmartRangeNotifier * > SmartRange::notifiers( ) const
{
  return m_notifiers;
}

void SmartRange::addNotifier( SmartRangeNotifier * notifier )
{
  if (!m_notifiers.contains(notifier))
    m_notifiers.append(notifier);

  checkFeedback();
}

void SmartRange::removeNotifier( SmartRangeNotifier * notifier )
{
  m_notifiers.removeAll(notifier);
  checkFeedback();
}

void SmartRange::deletePrimaryNotifier( )
{
  if (m_notifiers.isEmpty())
    return;

  SmartRangeNotifier* n = m_notifiers.first();
  removeNotifier(n);
  delete n;
}

void SmartRange::checkFeedback( )
{
}

// kate: space-indent on; indent-width 2; replace-tabs on;
