• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • applications API Reference
  • KDE Home
  • Contact Us
 

Kate

  • sources
  • kde-4.12
  • applications
  • kate
  • part
  • view
kateviewinternal.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2  Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org>
3  Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
4  Copyright (C) 2002,2003 Christoph Cullmann <cullmann@kde.org>
5  Copyright (C) 2002-2007 Hamish Rodda <rodda@kde.org>
6  Copyright (C) 2003 Anakim Border <aborder@sources.sourceforge.net>
7  Copyright (C) 2007 Mirko Stocker <me@misto.ch>
8  Copyright (C) 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
9  Copyright (C) 2008 Erlend Hamberg <ehamberg@gmail.com>
10 
11  Based on:
12  KWriteView : Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
13 
14  This library is free software; you can redistribute it and/or
15  modify it under the terms of the GNU Library General Public
16  License version 2 as published by the Free Software Foundation.
17 
18  This library is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  Library General Public License for more details.
22 
23  You should have received a copy of the GNU Library General Public License
24  along with this library; see the file COPYING.LIB. If not, write to
25  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26  Boston, MA 02110-1301, USA.
27 */
28 
29 #include "kateviewinternal.h"
30 #include "kateviewinternal.moc"
31 
32 #include "kateview.h"
33 #include "kateviewhelpers.h"
34 #include "katehighlight.h"
35 #include "katebuffer.h"
36 #include "katerenderer.h"
37 #include "kateconfig.h"
38 #include "katelayoutcache.h"
39 #include "katecompletionwidget.h"
40 #include "kateviinputmodemanager.h"
41 #include "katesearchbar.h"
42 #include "spellcheck/spellingmenu.h"
43 #include "kateviewaccessible.h"
44 
45 #include <ktexteditor/movingrange.h>
46 #include <kcursor.h>
47 #include <kdebug.h>
48 #include <kapplication.h>
49 #include <kglobalsettings.h>
50 
51 #include <QtCore/QMimeData>
52 #include <QtGui/QPainter>
53 #include <QtGui/QClipboard>
54 #include <QtGui/QPixmap>
55 #include <QtGui/QKeyEvent>
56 #include <QtGui/QLayout>
57 #include <QToolTip>
58 
59 static const bool debugPainting = false;
60 
61 KateViewInternal::KateViewInternal(KateView *view)
62  : QWidget (view)
63  , editSessionNumber (0)
64  , editIsRunning (false)
65  , m_view (view)
66  , m_cursor(doc()->buffer(), KTextEditor::Cursor(0, 0), Kate::TextCursor::MoveOnInsert)
67  , m_mouse()
68  , m_possibleTripleClick (false)
69  , m_completionItemExpanded (false)
70  , m_bm(doc()->newMovingRange(KTextEditor::Range::invalid(), KTextEditor::MovingRange::DoNotExpand))
71  , m_bmStart(doc()->newMovingRange(KTextEditor::Range::invalid(), KTextEditor::MovingRange::DoNotExpand))
72  , m_bmEnd(doc()->newMovingRange(KTextEditor::Range::invalid(), KTextEditor::MovingRange::DoNotExpand))
73  , m_dummy (0)
74 
75  // stay on cursor will avoid that the view scroll around on press return at beginning
76  , m_startPos (doc()->buffer(), KTextEditor::Cursor (0, 0), Kate::TextCursor::StayOnInsert)
77 
78  , m_visibleLineCount(0)
79  , m_madeVisible(false)
80  , m_shiftKeyPressed (false)
81  , m_autoCenterLines(0)
82  , m_minLinesVisible(0)
83  , m_selChangedByUser (false)
84  , m_selectAnchor (-1, -1)
85  , m_selectionMode( Default )
86  , m_layoutCache(new KateLayoutCache(renderer(), this))
87  , m_preserveX(false)
88  , m_preservedX(0)
89  , m_updatingView(true)
90  , m_cachedMaxStartPos(-1, -1)
91  , m_dragScrollTimer(this)
92  , m_scrollTimer (this)
93  , m_cursorTimer (this)
94  , m_textHintTimer (this)
95  , m_textHintEnabled(false)
96  , m_textHintPos(-1, -1)
97  , m_imPreeditRange(0)
98  , m_smartDirty(false)
99  , m_viInputMode(false)
100  , m_viInputModeManager (0)
101 {
102  setMinimumSize (0,0);
103  setAttribute(Qt::WA_OpaquePaintEvent);
104  setAttribute(Qt::WA_InputMethodEnabled);
105 
106  // invalidate m_selectionCached.start(), or keyb selection is screwed initially
107  m_selectionCached = KTextEditor::Range::invalid();
108 
109  // bracket markers are only for this view and should not be printed
110  m_bm->setView (m_view);
111  m_bmStart->setView (m_view);
112  m_bmEnd->setView (m_view);
113  m_bm->setAttributeOnlyForViews (true);
114  m_bmStart->setAttributeOnlyForViews (true);
115  m_bmEnd->setAttributeOnlyForViews (true);
116 
117  // use z depth defined in moving ranges interface
118  m_bm->setZDepth (-1000.0);
119  m_bmStart->setZDepth (-1000.0);
120  m_bmEnd->setZDepth (-1000.0);
121 
122  // update mark attributes
123  updateBracketMarkAttributes();
124 
125  //
126  // scrollbar for lines
127  //
128  m_lineScroll = new KateScrollBar(Qt::Vertical, this);
129  m_lineScroll->show();
130  m_lineScroll->setTracking (true);
131  m_lineScroll->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding );
132 
133  // Hijack the line scroller's controls, so we can scroll nicely for word-wrap
134  connect(m_lineScroll, SIGNAL(actionTriggered(int)), SLOT(scrollAction(int)));
135  connect(m_lineScroll, SIGNAL(sliderMoved(int)), SLOT(scrollLines(int)));
136  connect(m_lineScroll, SIGNAL(sliderMMBMoved(int)), SLOT(scrollLines(int)));
137  connect(m_lineScroll, SIGNAL(valueChanged(int)), SLOT(scrollLines(int)));
138 
139  // catch wheel events, completing the hijack
140  m_lineScroll->installEventFilter(this);
141 
142  //
143  // scrollbar for columns
144  //
145  m_columnScroll = new QScrollBar(Qt::Horizontal,m_view);
146 
147  if (m_view->dynWordWrap())
148  m_columnScroll->hide();
149  else
150  m_columnScroll->show();
151 
152  m_columnScroll->setTracking(true);
153  m_startX = 0;
154 
155  connect(m_columnScroll, SIGNAL(valueChanged(int)), SLOT(scrollColumns(int)));
156 
157  // bottom corner box
158  m_dummy = new QWidget(m_view);
159  m_dummy->setFixedSize(m_lineScroll->width(), m_columnScroll->sizeHint().height());
160  m_dummy->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
161 
162  if (m_view->dynWordWrap())
163  m_dummy->hide();
164  else
165  m_dummy->show();
166 
167  cache()->setWrap(m_view->dynWordWrap());
168 
169  //
170  // iconborder ;)
171  //
172  m_leftBorder = new KateIconBorder( this, m_view );
173  m_leftBorder->show ();
174 
175  // update view if folding ranges change
176  connect( &m_view->textFolding(), SIGNAL(foldingRangesChanged()), SLOT(slotRegionVisibilityChanged()));
177 
178  m_displayCursor.setPosition(0, 0);
179 
180  setAcceptDrops( true );
181 
182  // event filter
183  installEventFilter(this);
184 
185  // set initial cursor
186  m_mouseCursor = Qt::IBeamCursor;
187  setCursor(m_mouseCursor);
188 
189  // call mouseMoveEvent also if no mouse button is pressed
190  setMouseTracking(true);
191 
192  m_dragInfo.state = diNone;
193 
194  // timers
195  connect( &m_dragScrollTimer, SIGNAL(timeout()),
196  this, SLOT(doDragScroll()) );
197 
198  connect( &m_scrollTimer, SIGNAL(timeout()),
199  this, SLOT(scrollTimeout()) );
200 
201  connect( &m_cursorTimer, SIGNAL(timeout()),
202  this, SLOT(cursorTimeout()) );
203 
204  connect( &m_textHintTimer, SIGNAL(timeout()),
205  this, SLOT(textHintTimeout()) );
206 
207  // selection changed to set anchor
208  connect( m_view, SIGNAL(selectionChanged(KTextEditor::View*)),
209  this, SLOT(viewSelectionChanged()) );
210 
211 #ifndef QT_NO_ACCESSIBILITY
212 #if QT_VERSION >= 0x040800
213  QAccessible::installFactory(accessibleInterfaceFactory);
214 #endif
215 #endif
216 
217  // update is called in KateView, after construction and layout is over
218  // but before any other kateviewinternal call
219 }
220 
221 KateViewInternal::~KateViewInternal ()
222 {
223 #ifndef QT_NO_ACCESSIBILITY
224 #if QT_VERSION >= 0x040800
225  QAccessible::removeFactory(accessibleInterfaceFactory);
226 #endif
227 #endif
228 
229  // kill preedit ranges
230  delete m_imPreeditRange;
231  qDeleteAll (m_imPreeditRangeChildren);
232 
233  delete m_viInputModeManager;
234 
235  // delete bracket markers
236  delete m_bm;
237  delete m_bmStart;
238  delete m_bmEnd;
239 }
240 
241 void KateViewInternal::prepareForDynWrapChange()
242 {
243  // Which is the current view line?
244  m_wrapChangeViewLine = cache()->displayViewLine(m_displayCursor, true);
245 }
246 
247 void KateViewInternal::dynWrapChanged()
248 {
249  m_dummy->setFixedSize(m_lineScroll->width(), m_columnScroll->sizeHint().height());
250  if (m_view->dynWordWrap())
251  {
252  m_columnScroll->hide();
253  m_dummy->hide();
254 
255  }
256  else
257  {
258  // column scrollbar + bottom corner box
259  m_columnScroll->show();
260  m_dummy->show();
261  }
262 
263  cache()->setWrap(m_view->dynWordWrap());
264  updateView();
265 
266  if (m_view->dynWordWrap())
267  scrollColumns(0);
268 
269  // Determine where the cursor should be to get the cursor on the same view line
270  if (m_wrapChangeViewLine != -1) {
271  KTextEditor::Cursor newStart = viewLineOffset(m_displayCursor, -m_wrapChangeViewLine);
272  makeVisible(newStart, newStart.column(), true);
273 
274  } else {
275  update();
276  }
277 }
278 
279 KTextEditor::Cursor KateViewInternal::endPos() const
280 {
281  // Hrm, no lines laid out at all??
282  if (!cache()->viewCacheLineCount())
283  return KTextEditor::Cursor();
284 
285  for (int i = qMin(linesDisplayed() - 1, cache()->viewCacheLineCount() - 1); i >= 0; i--) {
286  const KateTextLayout& thisLine = cache()->viewLine(i);
287 
288  if (thisLine.line() == -1) continue;
289 
290  if (thisLine.virtualLine() >= m_view->textFolding().visibleLines()) {
291  // Cache is too out of date
292  return KTextEditor::Cursor(m_view->textFolding().visibleLines() - 1, doc()->lineLength(m_view->textFolding().visibleLineToLine(m_view->textFolding().visibleLines() - 1)));
293  }
294 
295  return KTextEditor::Cursor(thisLine.virtualLine(), thisLine.wrap() ? thisLine.endCol() - 1 : thisLine.endCol());
296  }
297 
298  return KTextEditor::Cursor();
299 }
300 
301 int KateViewInternal::endLine() const
302 {
303  return endPos().line();
304 }
305 
306 KateTextLayout KateViewInternal::yToKateTextLayout(int y) const
307 {
308  if (y < 0 || y > size().height())
309  return KateTextLayout::invalid();
310 
311  int range = y / renderer()->lineHeight();
312 
313  // lineRanges is always bigger than 0, after the initial updateView call
314  if (range >= 0 && range < cache()->viewCacheLineCount())
315  return cache()->viewLine(range);
316 
317  return KateTextLayout::invalid();
318 }
319 
320 int KateViewInternal::lineToY(int viewLine) const
321 {
322  return (viewLine-startLine()) * renderer()->lineHeight();
323 }
324 
325 void KateViewInternal::slotIncFontSizes()
326 {
327  renderer()->increaseFontSizes();
328  update();
329 }
330 
331 void KateViewInternal::slotDecFontSizes()
332 {
333  renderer()->decreaseFontSizes();
334  update();
335 }
336 
340 void KateViewInternal::scrollLines ( int line )
341 {
342  KTextEditor::Cursor newPos(line, 0);
343  scrollPos(newPos);
344 }
345 
346 // This can scroll less than one true line
347 void KateViewInternal::scrollViewLines(int offset)
348 {
349  KTextEditor::Cursor c = viewLineOffset(startPos(), offset);
350  scrollPos(c);
351 
352  bool blocked = m_lineScroll->blockSignals(true);
353  m_lineScroll->setValue(startLine());
354  m_lineScroll->blockSignals(blocked);
355 }
356 
357 void KateViewInternal::scrollAction( int action )
358 {
359  switch (action) {
360  case QAbstractSlider::SliderSingleStepAdd:
361  scrollNextLine();
362  break;
363 
364  case QAbstractSlider::SliderSingleStepSub:
365  scrollPrevLine();
366  break;
367 
368  case QAbstractSlider::SliderPageStepAdd:
369  scrollNextPage();
370  break;
371 
372  case QAbstractSlider::SliderPageStepSub:
373  scrollPrevPage();
374  break;
375 
376  case QAbstractSlider::SliderToMinimum:
377  top_home();
378  break;
379 
380  case QAbstractSlider::SliderToMaximum:
381  bottom_end();
382  break;
383  }
384 }
385 
386 void KateViewInternal::scrollNextPage()
387 {
388  scrollViewLines(qMax( linesDisplayed() - 1, 0 ));
389 }
390 
391 void KateViewInternal::scrollPrevPage()
392 {
393  scrollViewLines(-qMax( linesDisplayed() - 1, 0 ));
394 }
395 
396 void KateViewInternal::scrollPrevLine()
397 {
398  scrollViewLines(-1);
399 }
400 
401 void KateViewInternal::scrollNextLine()
402 {
403  scrollViewLines(1);
404 }
405 
406 KTextEditor::Cursor KateViewInternal::maxStartPos(bool changed)
407 {
408  cache()->setAcceptDirtyLayouts(true);
409 
410  if (m_cachedMaxStartPos.line() == -1 || changed)
411  {
412  KTextEditor::Cursor end(m_view->textFolding().visibleLines() - 1, doc()->lineLength(m_view->textFolding().visibleLineToLine(m_view->textFolding().visibleLines() - 1)));
413 
414  if (m_view->config()->scrollPastEnd())
415  m_cachedMaxStartPos = viewLineOffset(end, -m_minLinesVisible);
416  else
417  m_cachedMaxStartPos = viewLineOffset(end, -(linesDisplayed() - 1));
418  }
419 
420  cache()->setAcceptDirtyLayouts(false);
421 
422  return m_cachedMaxStartPos;
423 }
424 
425 // c is a virtual cursor
426 void KateViewInternal::scrollPos(KTextEditor::Cursor& c, bool force, bool calledExternally)
427 {
428  if (!force && ((!m_view->dynWordWrap() && c.line() == startLine()) || c == startPos()))
429  return;
430 
431  if (c.line() < 0)
432  c.setLine(0);
433 
434  KTextEditor::Cursor limit = maxStartPos();
435  if (c > limit) {
436  c = limit;
437 
438  // Re-check we're not just scrolling to the same place
439  if (!force && ((!m_view->dynWordWrap() && c.line() == startLine()) || c == startPos()))
440  return;
441  }
442 
443  int viewLinesScrolled = 0;
444 
445  // only calculate if this is really used and useful, could be wrong here, please recheck
446  // for larger scrolls this makes 2-4 seconds difference on my xeon with dyn. word wrap on
447  // try to get it really working ;)
448  bool viewLinesScrolledUsable = !force
449  && (c.line() >= startLine() - linesDisplayed() - 1)
450  && (c.line() <= endLine() + linesDisplayed() + 1);
451 
452  if (viewLinesScrolledUsable) {
453  viewLinesScrolled = cache()->displayViewLine(c);
454  }
455 
456  m_startPos.setPosition(c);
457 
458  // set false here but reversed if we return to makeVisible
459  m_madeVisible = false;
460 
461  if (viewLinesScrolledUsable)
462  {
463  int lines = linesDisplayed();
464  if (m_view->textFolding().visibleLines() < lines) {
465  KTextEditor::Cursor end(m_view->textFolding().visibleLines() - 1, doc()->lineLength(m_view->textFolding().visibleLineToLine(m_view->textFolding().visibleLines() - 1)));
466  lines = qMin(linesDisplayed(), cache()->displayViewLine(end) + 1);
467  }
468 
469  Q_ASSERT(lines >= 0);
470 
471  if (!calledExternally && qAbs(viewLinesScrolled) < lines)
472  {
473  updateView(false, viewLinesScrolled);
474 
475  int scrollHeight = -(viewLinesScrolled * (int)renderer()->lineHeight());
476 
477  // scroll excluding child widgets (floating notifications)
478  scroll(0, scrollHeight, rect());
479  m_leftBorder->scroll(0, scrollHeight);
480 
481  emit m_view->verticalScrollPositionChanged( m_view, c );
482  emit m_view->displayRangeChanged(m_view);
483  return;
484  }
485  }
486 
487  updateView();
488  update();
489  m_leftBorder->update();
490  emit m_view->verticalScrollPositionChanged( m_view, c );
491  emit m_view->displayRangeChanged(m_view);
492 }
493 
494 void KateViewInternal::scrollColumns ( int x )
495 {
496  if (x == m_startX)
497  return;
498 
499  if (x < 0)
500  x = 0;
501 
502  int dx = m_startX - x;
503  m_startX = x;
504 
505  if (qAbs(dx) < width()) {
506  // scroll excluding child widgets (floating notifications)
507  scroll(dx, 0, rect());
508  } else
509  update();
510 
511  emit m_view->horizontalScrollPositionChanged( m_view );
512  emit m_view->displayRangeChanged(m_view);
513 
514  bool blocked = m_columnScroll->blockSignals(true);
515  m_columnScroll->setValue(m_startX);
516  m_columnScroll->blockSignals(blocked);
517 }
518 
519 // If changed is true, the lines that have been set dirty have been updated.
520 void KateViewInternal::updateView(bool changed, int viewLinesScrolled)
521 {
522  doUpdateView(changed, viewLinesScrolled);
523 
524  if (changed)
525  updateDirty();
526 }
527 
528 void KateViewInternal::doUpdateView(bool changed, int viewLinesScrolled)
529 {
530  if(!isVisible() && !viewLinesScrolled && !changed )
531  return; //When this view is not visible, don't do anything
532 
533  m_updatingView = true;
534 
535  bool blocked = m_lineScroll->blockSignals(true);
536 
537  if (width() != cache()->viewWidth()) {
538  cache()->setViewWidth(width());
539  changed = true;
540  }
541 
542  /* It was observed that height() could be negative here --
543  when the main Kate view has 0 as size (during creation),
544  and there frame arount KateViewInternal. In which
545  case we'd set the view cache to 0 (or less!) lines, and
546  start allocating huge chunks of data, later. */
547  int newSize = (qMax (0, height()) / renderer()->lineHeight()) + 1;
548  cache()->updateViewCache(startPos(), newSize, viewLinesScrolled);
549  m_visibleLineCount = newSize;
550 
551  KTextEditor::Cursor maxStart = maxStartPos(changed);
552  int maxLineScrollRange = maxStart.line();
553  if (m_view->dynWordWrap() && maxStart.column() != 0)
554  maxLineScrollRange++;
555  m_lineScroll->setRange(0, maxLineScrollRange);
556 
557  m_lineScroll->setValue(startPos().line());
558  m_lineScroll->setSingleStep(1);
559  m_lineScroll->setPageStep(qMax (0, height()) / renderer()->lineHeight());
560  m_lineScroll->blockSignals(blocked);
561 
562  if (!m_view->dynWordWrap())
563  {
564  int max = maxLen(startLine()) - width();
565  if (max < 0)
566  max = 0;
567 
568  // if we lose the ability to scroll horizontally, move view to the far-left
569  if (max == 0)
570  {
571  scrollColumns(0);
572  }
573 
574  blocked = m_columnScroll->blockSignals(true);
575 
576  // disable scrollbar
577  m_columnScroll->setDisabled (max == 0);
578 
579  m_columnScroll->setRange(0, max);
580 
581  m_columnScroll->setValue(m_startX);
582 
583  // Approximate linescroll
584  m_columnScroll->setSingleStep(renderer()->config()->fontMetrics().width('a'));
585  m_columnScroll->setPageStep(width());
586 
587  m_columnScroll->blockSignals(blocked);
588  }
589 
590  if (m_smartDirty)
591  m_smartDirty = false;
592 
593  m_updatingView = false;
594 }
595 
600 void KateViewInternal::makeVisible (const KTextEditor::Cursor& c, int endCol, bool force, bool center, bool calledExternally)
601 {
602  //kDebug(13030) << "MakeVisible start " << startPos() << " end " << endPos() << " -> request: " << c;// , new start [" << scroll.line << "," << scroll.col << "] lines " << (linesDisplayed() - 1) << " height " << height();
603  // if the line is in a folded region, unfold all the way up
604  //if ( doc()->foldingTree()->findNodeForLine( c.line )->visible )
605  // kDebug(13030)<<"line ("<<c.line<<") should be visible";
606 
607  if ( force )
608  {
609  KTextEditor::Cursor scroll = c;
610  scrollPos(scroll, force, calledExternally);
611  }
612  else if (center && (c < startPos() || c > endPos()))
613  {
614  KTextEditor::Cursor scroll = viewLineOffset(c, -int(linesDisplayed()) / 2);
615  scrollPos(scroll, false, calledExternally);
616  }
617  else if ( c > viewLineOffset(startPos(), linesDisplayed() - m_minLinesVisible - 1) )
618  {
619  KTextEditor::Cursor scroll = viewLineOffset(c, -(linesDisplayed() - m_minLinesVisible - 1));
620  scrollPos(scroll, false, calledExternally);
621  }
622  else if ( c < viewLineOffset(startPos(), m_minLinesVisible) )
623  {
624  KTextEditor::Cursor scroll = viewLineOffset(c, -m_minLinesVisible);
625  scrollPos(scroll, false, calledExternally);
626  }
627  else
628  {
629  // Check to see that we're not showing blank lines
630  KTextEditor::Cursor max = maxStartPos();
631  if (startPos() > max) {
632  scrollPos(max, max.column(), calledExternally);
633  }
634  }
635 
636  if (!m_view->dynWordWrap() && (endCol != -1 || m_view->wrapCursor()))
637  {
638  KTextEditor::Cursor rc = toRealCursor(c);
639  int sX = renderer()->cursorToX(cache()->textLayout(rc), rc, !m_view->wrapCursor());
640 
641  int sXborder = sX-8;
642  if (sXborder < 0)
643  sXborder = 0;
644 
645  if (sX < m_startX)
646  scrollColumns (sXborder);
647  else if (sX > m_startX + width())
648  scrollColumns (sX - width() + 8);
649  }
650 
651  m_madeVisible = !force;
652 
653 #ifndef QT_NO_ACCESSIBILITY
654 #if QT_VERSION >= 0x040800
655  QAccessible::updateAccessibility( this, KateCursorAccessible::ChildId, QAccessible::Focus );
656 #endif
657 #endif
658 }
659 
660 void KateViewInternal::slotRegionVisibilityChanged()
661 {
662  kDebug(13030);
663  cache()->clear();
664 
665  m_cachedMaxStartPos.setLine(-1);
666  KTextEditor::Cursor max = maxStartPos();
667  if (startPos() > max)
668  scrollPos(max);
669 
670  // if text was folded: make sure the cursor is on a visible line
671  qint64 foldedRangeId = -1;
672  if (!m_view->textFolding().isLineVisible (m_cursor.line(), &foldedRangeId)) {
673  KTextEditor::Range foldingRange = m_view->textFolding().foldingRange(foldedRangeId);
674  Q_ASSERT(foldingRange.start().isValid());
675 
676  // set cursor to start of folding region
677  updateCursor(foldingRange.start(), true);
678  }
679 
680  updateView();
681  update();
682  m_leftBorder->update();
683  emit m_view->displayRangeChanged(m_view);
684 }
685 
686 void KateViewInternal::slotRegionBeginEndAddedRemoved(unsigned int)
687 {
688  kDebug(13030);
689  // FIXME: performance problem
690  m_leftBorder->update();
691 }
692 
693 void KateViewInternal::showEvent ( QShowEvent *e )
694 {
695  updateView ();
696 
697  QWidget::showEvent (e);
698 }
699 
700 int KateViewInternal::linesDisplayed() const
701 {
702  int h = height();
703 
704  // catch zero heights, even if should not happen
705  int fh = qMax (1, renderer()->lineHeight());
706 
707  // default to 1, there is always one line around....
708  // too many places calc with linesDisplayed() - 1
709  return qMax (1, (h - (h % fh)) / fh);
710 }
711 
712 QPoint KateViewInternal::cursorToCoordinate( const KTextEditor::Cursor & cursor, bool realCursor, bool includeBorder ) const
713 {
714  int viewLine = cache()->displayViewLine(realCursor ? toVirtualCursor(cursor) : cursor, true);
715 
716  if (viewLine < 0 || viewLine >= cache()->viewCacheLineCount())
717  return QPoint(-1, -1);
718 
719  int y = (int)viewLine * renderer()->lineHeight();
720 
721  KateTextLayout layout = cache()->viewLine(viewLine);
722  int x = 0;
723 
724  // only set x value if we have a valid layout (bug #171027)
725  if (layout.isValid())
726  x = (int)layout.lineLayout().cursorToX(cursor.column());
727 // else
728 // kDebug() << "Invalid Layout";
729 
730  if (includeBorder) x += m_leftBorder->width();
731 
732  x -= startX();
733 
734  return QPoint(x, y);
735 }
736 
737 QPoint KateViewInternal::cursorCoordinates(bool includeBorder) const
738 {
739  return cursorToCoordinate(m_displayCursor, false, includeBorder);
740 }
741 
742 KTextEditor::Cursor KateViewInternal::findMatchingBracket()
743 {
744  KTextEditor::Cursor c;
745 
746  if (!m_bm->toRange().isValid())
747  return KTextEditor::Cursor::invalid();
748 
749  Q_ASSERT(m_bmEnd->toRange().isValid());
750  Q_ASSERT(m_bmStart->toRange().isValid());
751 
752  if (m_bmStart->toRange().contains(m_cursor) || m_bmStart->end() == m_cursor.toCursor()) {
753  c = m_bmEnd->end();
754  } else if (m_bmEnd->toRange().contains(m_cursor) || m_bmEnd->end() == m_cursor.toCursor()) {
755  c = m_bmStart->start();
756  } else {
757  // should never happen: a range exists, but the cursor position is
758  // neither at the start nor at the end...
759  return KTextEditor::Cursor::invalid();
760  }
761 
762  return c;
763 }
764 
765 void KateViewInternal::doReturn()
766 {
767  doc()->newLine( m_view );
768  updateView();
769 }
770 
771 void KateViewInternal::doSmartNewline()
772 {
773  int ln = m_cursor.line();
774  Kate::TextLine line = doc()->kateTextLine(ln);
775  int col = qMin(m_cursor.column(), line->firstChar());
776  if (col != -1) {
777  while (line->length() > col &&
778  !(line->at(col).isLetterOrNumber() || line->at(col) == QLatin1Char('_')) &&
779  col < m_cursor.column()) ++col;
780  } else {
781  col = line->length(); // stay indented
782  }
783  doc()->editStart();
784  doc()->editWrapLine(ln, m_cursor.column());
785  doc()->insertText(KTextEditor::Cursor(ln + 1, 0), line->string(0, col));
786  doc()->editEnd();
787 
788  updateView();
789 }
790 
791 void KateViewInternal::doDelete()
792 {
793  doc()->del( m_view, m_cursor );
794 }
795 
796 void KateViewInternal::doBackspace()
797 {
798  doc()->backspace( m_view, m_cursor );
799 }
800 
801 void KateViewInternal::doTabulator()
802 {
803  doc()->insertTab( m_view, m_cursor );
804 }
805 
806 void KateViewInternal::doTranspose()
807 {
808  doc()->transpose( m_cursor );
809 }
810 
811 void KateViewInternal::doDeletePrevWord()
812 {
813  doc()->editStart();
814  wordPrev( true );
815  KTextEditor::Range selection = m_view->selectionRange();
816  m_view->removeSelectedText();
817  doc()->editEnd();
818  tagRange(selection, true);
819  updateDirty();
820 }
821 
822 void KateViewInternal::doDeleteNextWord()
823 {
824  doc()->editStart();
825  wordNext( true );
826  KTextEditor::Range selection = m_view->selectionRange();
827  m_view->removeSelectedText();
828  doc()->editEnd();
829  tagRange(selection, true);
830  updateDirty();
831 }
832 
833 class CalculatingCursor : public KTextEditor::Cursor {
834 public:
835  // These constructors constrain their arguments to valid positions
836  // before only the third one did, but that leads to crashs
837  // see bug 227449
838  CalculatingCursor(KateViewInternal* vi)
839  : KTextEditor::Cursor()
840  , m_vi(vi)
841  {
842  makeValid();
843  }
844 
845  CalculatingCursor(KateViewInternal* vi, const KTextEditor::Cursor& c)
846  : KTextEditor::Cursor(c)
847  , m_vi(vi)
848  {
849  makeValid();
850  }
851 
852  CalculatingCursor(KateViewInternal* vi, int line, int col)
853  : KTextEditor::Cursor(line, col)
854  , m_vi(vi)
855  {
856  makeValid();
857  }
858 
859 
860  virtual CalculatingCursor& operator+=( int n ) = 0;
861 
862  virtual CalculatingCursor& operator-=( int n ) = 0;
863 
864  CalculatingCursor& operator++() { return operator+=( 1 ); }
865 
866  CalculatingCursor& operator--() { return operator-=( 1 ); }
867 
868  void makeValid() {
869  setLine(qBound( 0, line(), int( doc()->lines() - 1 ) ) );
870  if (view()->wrapCursor())
871  m_column = qBound( 0, column(), doc()->lineLength( line() ) );
872  else
873  m_column = qMax( 0, column() );
874  Q_ASSERT( valid() );
875  }
876 
877  void toEdge( KateViewInternal::Bias bias ) {
878  if( bias == KateViewInternal::left ) m_column = 0;
879  else if( bias == KateViewInternal::right ) m_column = doc()->lineLength( line() );
880  }
881 
882  bool atEdge() const { return atEdge( KateViewInternal::left ) || atEdge( KateViewInternal::right ); }
883 
884  bool atEdge( KateViewInternal::Bias bias ) const {
885  switch( bias ) {
886  case KateViewInternal::left: return column() == 0;
887  case KateViewInternal::none: return atEdge();
888  case KateViewInternal::right: return column() >= doc()->lineLength( line() );
889  default: Q_ASSERT(false); return false;
890  }
891  }
892 
893 protected:
894  bool valid() const {
895  return line() >= 0 &&
896  line() < doc()->lines() &&
897  column() >= 0 &&
898  (!view()->wrapCursor() || column() <= doc()->lineLength( line() ));
899  }
900  KateView* view() { return m_vi->m_view; }
901  const KateView* view() const { return m_vi->m_view; }
902  KateDocument* doc() { return view()->doc(); }
903  const KateDocument* doc() const { return view()->doc(); }
904  KateViewInternal* m_vi;
905 };
906 
907 class BoundedCursor : public CalculatingCursor {
908 public:
909  BoundedCursor(KateViewInternal* vi)
910  : CalculatingCursor( vi ) {}
911  BoundedCursor(KateViewInternal* vi, const KTextEditor::Cursor& c )
912  : CalculatingCursor( vi, c ) {}
913  BoundedCursor(KateViewInternal* vi, int line, int col )
914  : CalculatingCursor( vi, line, col ) {}
915  virtual CalculatingCursor& operator+=( int n ) {
916  KateLineLayoutPtr thisLine = m_vi->cache()->line(line());
917  if (!thisLine->isValid()) {
918  kWarning() << "Did not retrieve valid layout for line " << line();
919  return *this;
920  }
921 
922  const bool wrapCursor = view()->wrapCursor();
923  int maxColumn = -1;
924  if (n >= 0) {
925  for (int i = 0; i < n; i++) {
926  if (m_column >= thisLine->length()) {
927  if (wrapCursor) {
928  break;
929 
930  } else if (view()->dynWordWrap()) {
931  // Don't go past the edge of the screen in dynamic wrapping mode
932  if (maxColumn == -1)
933  maxColumn = thisLine->length() + ((m_vi->width() - thisLine->widthOfLastLine()) / m_vi->renderer()->spaceWidth()) - 1;
934 
935  if (m_column >= maxColumn) {
936  m_column = maxColumn;
937  break;
938  }
939 
940  ++m_column;
941 
942  } else {
943  ++m_column;
944  }
945 
946  } else {
947  m_column = thisLine->layout()->nextCursorPosition(m_column);
948  }
949  }
950  } else {
951  for (int i = 0; i > n; i--) {
952  if (m_column >= thisLine->length())
953  --m_column;
954  else if (m_column == 0)
955  break;
956  else
957  m_column = thisLine->layout()->previousCursorPosition(m_column);
958  }
959  }
960 
961  Q_ASSERT( valid() );
962  return *this;
963  }
964  virtual CalculatingCursor& operator-=( int n ) {
965  return operator+=( -n );
966  }
967 };
968 
969 class WrappingCursor : public CalculatingCursor {
970 public:
971  WrappingCursor(KateViewInternal* vi)
972  : CalculatingCursor( vi) {}
973  WrappingCursor(KateViewInternal* vi, const KTextEditor::Cursor& c )
974  : CalculatingCursor( vi, c ) {}
975  WrappingCursor(KateViewInternal* vi, int line, int col )
976  : CalculatingCursor( vi, line, col ) {}
977 
978  virtual CalculatingCursor& operator+=( int n ) {
979  KateLineLayoutPtr thisLine = m_vi->cache()->line(line());
980  if (!thisLine->isValid()) {
981  kWarning() << "Did not retrieve a valid layout for line " << line();
982  return *this;
983  }
984 
985  if (n >= 0) {
986  for (int i = 0; i < n; i++) {
987  if (m_column >= thisLine->length()) {
988  // Have come to the end of a line
989  if (line() >= doc()->lines() - 1)
990  // Have come to the end of the document
991  break;
992 
993  // Advance to the beginning of the next line
994  m_column = 0;
995  setLine(line() + 1);
996 
997  // Retrieve the next text range
998  thisLine = m_vi->cache()->line(line());
999  if (!thisLine->isValid()) {
1000  kWarning() << "Did not retrieve a valid layout for line " << line();
1001  return *this;
1002  }
1003 
1004  continue;
1005  }
1006 
1007  m_column = thisLine->layout()->nextCursorPosition(m_column);
1008  }
1009 
1010  } else {
1011  for (int i = 0; i > n; i--) {
1012  if (m_column == 0) {
1013  // Have come to the start of the document
1014  if (line() == 0)
1015  break;
1016 
1017  // Start going back to the end of the last line
1018  setLine(line() - 1);
1019 
1020  // Retrieve the next text range
1021  thisLine = m_vi->cache()->line(line());
1022  if (!thisLine->isValid()) {
1023  kWarning() << "Did not retrieve a valid layout for line " << line();
1024  return *this;
1025  }
1026 
1027  // Finish going back to the end of the last line
1028  m_column = thisLine->length();
1029 
1030  continue;
1031  }
1032 
1033  if (m_column > thisLine->length())
1034  --m_column;
1035  else
1036  m_column = thisLine->layout()->previousCursorPosition(m_column);
1037  }
1038  }
1039 
1040  Q_ASSERT(valid());
1041  return *this;
1042  }
1043  virtual CalculatingCursor& operator-=( int n ) {
1044  return operator+=( -n );
1045  }
1046 };
1047 
1048 void KateViewInternal::moveChar( KateViewInternal::Bias bias, bool sel )
1049 {
1050  KTextEditor::Cursor c;
1051  if ( m_view->wrapCursor() ) {
1052  c = WrappingCursor( this, m_cursor ) += bias;
1053  } else {
1054  c = BoundedCursor( this, m_cursor ) += bias;
1055  }
1056 
1057  updateSelection( c, sel );
1058  updateCursor( c );
1059 }
1060 
1061 void KateViewInternal::cursorPrevChar( bool sel )
1062 {
1063  if ( ! m_view->wrapCursor() && m_cursor.column() == 0 )
1064  return;
1065 
1066  moveChar( KateViewInternal::left, sel );
1067 }
1068 
1069 void KateViewInternal::cursorNextChar( bool sel )
1070 {
1071  moveChar( KateViewInternal::right, sel );
1072 }
1073 
1074 void KateViewInternal::wordPrev( bool sel )
1075 {
1076  WrappingCursor c( this, m_cursor );
1077 
1078  // First we skip backwards all space.
1079  // Then we look up into which category the current position falls:
1080  // 1. a "word" character
1081  // 2. a "non-word" character (except space)
1082  // 3. the beginning of the line
1083  // and skip all preceding characters that fall into this class.
1084  // The code assumes that space is never part of the word character class.
1085 
1086  KateHighlighting* h = doc()->highlight();
1087  if( !c.atEdge( left ) ) {
1088 
1089  while( !c.atEdge( left ) && doc()->line( c.line() )[ c.column() - 1 ].isSpace() )
1090  --c;
1091  }
1092  if( c.atEdge( left ) )
1093  {
1094  --c;
1095  }
1096  else if( h->isInWord( doc()->line( c.line() )[ c.column() - 1 ] ) )
1097  {
1098  while( !c.atEdge( left ) && h->isInWord( doc()->line( c.line() )[ c.column() - 1 ] ) )
1099  --c;
1100  }
1101  else
1102  {
1103  while( !c.atEdge( left )
1104  && !h->isInWord( doc()->line( c.line() )[ c.column() - 1 ] )
1105  // in order to stay symmetric to wordLeft()
1106  // we must not skip space preceding a non-word sequence
1107  && !doc()->line( c.line() )[ c.column() - 1 ].isSpace() )
1108  {
1109  --c;
1110  }
1111  }
1112 
1113  updateSelection( c, sel );
1114  updateCursor( c );
1115 }
1116 
1117 void KateViewInternal::wordNext( bool sel )
1118 {
1119  WrappingCursor c( this, m_cursor );
1120 
1121  // We look up into which category the current position falls:
1122  // 1. a "word" character
1123  // 2. a "non-word" character (except space)
1124  // 3. the end of the line
1125  // and skip all following characters that fall into this class.
1126  // If the skipped characters are followed by space, we skip that too.
1127  // The code assumes that space is never part of the word character class.
1128 
1129  KateHighlighting* h = doc()->highlight();
1130  if( c.atEdge( right ) )
1131  {
1132  ++c;
1133  }
1134  else if( h->isInWord( doc()->line( c.line() )[ c.column() ] ) )
1135  {
1136  while( !c.atEdge( right ) && h->isInWord( doc()->line( c.line() )[ c.column() ] ) )
1137  ++c;
1138  }
1139  else
1140  {
1141  while( !c.atEdge( right )
1142  && !h->isInWord( doc()->line( c.line() )[ c.column() ] )
1143  // we must not skip space, because if that space is followed
1144  // by more non-word characters, we would skip them, too
1145  && !doc()->line( c.line() )[ c.column() ].isSpace() )
1146  {
1147  ++c;
1148  }
1149  }
1150 
1151  while( !c.atEdge( right ) && doc()->line( c.line() )[ c.column() ].isSpace() )
1152  ++c;
1153 
1154  updateSelection( c, sel );
1155  updateCursor( c );
1156 }
1157 
1158 void KateViewInternal::moveEdge( KateViewInternal::Bias bias, bool sel )
1159 {
1160  BoundedCursor c( this, m_cursor );
1161  c.toEdge( bias );
1162  updateSelection( c, sel );
1163  updateCursor( c );
1164 }
1165 
1166 void KateViewInternal::home( bool sel )
1167 {
1168  if (m_view->dynWordWrap() && currentLayout().startCol()) {
1169  // Allow us to go to the real start if we're already at the start of the view line
1170  if (m_cursor.column() != currentLayout().startCol()) {
1171  KTextEditor::Cursor c = currentLayout().start();
1172  updateSelection( c, sel );
1173  updateCursor( c );
1174  return;
1175  }
1176  }
1177 
1178  if( !doc()->config()->smartHome() ) {
1179  moveEdge( left, sel );
1180  return;
1181  }
1182 
1183  Kate::TextLine l = doc()->kateTextLine( m_cursor.line() );
1184 
1185  if (!l)
1186  return;
1187 
1188  KTextEditor::Cursor c = m_cursor;
1189  int lc = l->firstChar();
1190 
1191  if( lc < 0 || c.column() == lc ) {
1192  c.setColumn(0);
1193  } else {
1194  c.setColumn(lc);
1195  }
1196 
1197  updateSelection( c, sel );
1198  updateCursor( c, true );
1199 }
1200 
1201 void KateViewInternal::end( bool sel )
1202 {
1203  KateTextLayout layout = currentLayout();
1204 
1205  if (m_view->dynWordWrap() && layout.wrap()) {
1206  // Allow us to go to the real end if we're already at the end of the view line
1207  if (m_cursor.column() < layout.endCol() - 1) {
1208  KTextEditor::Cursor c(m_cursor.line(), layout.endCol() - 1);
1209  updateSelection( c, sel );
1210  updateCursor( c );
1211  return;
1212  }
1213  }
1214 
1215  if( !doc()->config()->smartHome() ) {
1216  moveEdge( right, sel );
1217  return;
1218  }
1219 
1220  Kate::TextLine l = doc()->kateTextLine( m_cursor.line() );
1221 
1222  if (!l)
1223  return;
1224 
1225  // "Smart End", as requested in bugs #78258 and #106970
1226  if (m_cursor.column() == doc()->lineLength(m_cursor.line())) {
1227  KTextEditor::Cursor c = m_cursor;
1228  c.setColumn(l->lastChar() + 1);
1229  updateSelection(c, sel);
1230  updateCursor(c, true);
1231  } else {
1232  moveEdge(right, sel);
1233  }
1234 }
1235 
1236 KateTextLayout KateViewInternal::currentLayout() const
1237 {
1238  return cache()->textLayout(m_cursor);
1239 }
1240 
1241 KateTextLayout KateViewInternal::previousLayout() const
1242 {
1243  int currentViewLine = cache()->viewLine(m_cursor);
1244 
1245  if (currentViewLine)
1246  return cache()->textLayout(m_cursor.line(), currentViewLine - 1);
1247  else
1248  return cache()->textLayout(m_view->textFolding().visibleLineToLine(m_displayCursor.line() - 1), -1);
1249 }
1250 
1251 KateTextLayout KateViewInternal::nextLayout() const
1252 {
1253  int currentViewLine = cache()->viewLine(m_cursor) + 1;
1254 
1255  if (currentViewLine >= cache()->line(m_cursor.line())->viewLineCount()) {
1256  currentViewLine = 0;
1257  return cache()->textLayout(m_view->textFolding().visibleLineToLine(m_displayCursor.line() + 1), currentViewLine);
1258  } else {
1259  return cache()->textLayout(m_cursor.line(), currentViewLine);
1260  }
1261 }
1262 
1263 /*
1264  * This returns the cursor which is offset by (offset) view lines.
1265  * This is the main function which is called by code not specifically dealing with word-wrap.
1266  * The opposite conversion (cursor to offset) can be done with cache()->displayViewLine().
1267  *
1268  * The cursors involved are virtual cursors (ie. equivalent to m_displayCursor)
1269  */
1270 
1271 KTextEditor::Cursor KateViewInternal::viewLineOffset(const KTextEditor::Cursor& virtualCursor, int offset, bool keepX)
1272 {
1273  if (!m_view->dynWordWrap()) {
1274  KTextEditor::Cursor ret(qMin((int)m_view->textFolding().visibleLines() - 1, virtualCursor.line() + offset), 0);
1275 
1276  if (ret.line() < 0)
1277  ret.setLine(0);
1278 
1279  if (keepX) {
1280  int realLine = m_view->textFolding().visibleLineToLine(ret.line());
1281  KateTextLayout t = cache()->textLayout(realLine, 0);
1282  Q_ASSERT(t.isValid());
1283 
1284  ret.setColumn(renderer()->xToCursor(t, m_preservedX, !m_view->wrapCursor()).column());
1285  }
1286 
1287  return ret;
1288  }
1289 
1290  KTextEditor::Cursor realCursor = virtualCursor;
1291  realCursor.setLine(m_view->textFolding().visibleLineToLine(m_view->textFolding().lineToVisibleLine(virtualCursor.line())));
1292 
1293  int cursorViewLine = cache()->viewLine(realCursor);
1294 
1295  int currentOffset = 0;
1296  int virtualLine = 0;
1297 
1298  bool forwards = (offset > 0) ? true : false;
1299 
1300  if (forwards) {
1301  currentOffset = cache()->lastViewLine(realCursor.line()) - cursorViewLine;
1302  if (offset <= currentOffset) {
1303  // the answer is on the same line
1304  KateTextLayout thisLine = cache()->textLayout(realCursor.line(), cursorViewLine + offset);
1305  Q_ASSERT(thisLine.virtualLine() == virtualCursor.line());
1306  return KTextEditor::Cursor(virtualCursor.line(), thisLine.startCol());
1307  }
1308 
1309  virtualLine = virtualCursor.line() + 1;
1310 
1311  } else {
1312  offset = -offset;
1313  currentOffset = cursorViewLine;
1314  if (offset <= currentOffset) {
1315  // the answer is on the same line
1316  KateTextLayout thisLine = cache()->textLayout(realCursor.line(), cursorViewLine - offset);
1317  Q_ASSERT(thisLine.virtualLine() == (int) m_view->textFolding().lineToVisibleLine(virtualCursor.line()));
1318  return KTextEditor::Cursor(virtualCursor.line(), thisLine.startCol());
1319  }
1320 
1321  virtualLine = virtualCursor.line() - 1;
1322  }
1323 
1324  currentOffset++;
1325 
1326  while (virtualLine >= 0 && virtualLine < (int)m_view->textFolding().visibleLines())
1327  {
1328  int realLine = m_view->textFolding().visibleLineToLine(virtualLine);
1329  KateLineLayoutPtr thisLine = cache()->line(realLine, virtualLine);
1330  if (!thisLine)
1331  break;
1332 
1333  for (int i = 0; i < thisLine->viewLineCount(); ++i) {
1334  if (offset == currentOffset) {
1335  KateTextLayout thisViewLine = thisLine->viewLine(i);
1336 
1337  if (!forwards) {
1338  // We actually want it the other way around
1339  int requiredViewLine = cache()->lastViewLine(realLine) - thisViewLine.viewLine();
1340  if (requiredViewLine != thisViewLine.viewLine()) {
1341  thisViewLine = thisLine->viewLine(requiredViewLine);
1342  }
1343  }
1344 
1345  KTextEditor::Cursor ret(virtualLine, thisViewLine.startCol());
1346 
1347  // keep column position
1348  if (keepX) {
1349  KTextEditor::Cursor realCursor = toRealCursor(virtualCursor);
1350  KateTextLayout t = cache()->textLayout(realCursor);
1351  // renderer()->cursorToX(t, realCursor, !m_view->wrapCursor());
1352 
1353  realCursor = renderer()->xToCursor(thisViewLine, m_preservedX, !m_view->wrapCursor());
1354  ret.setColumn(realCursor.column());
1355  }
1356 
1357  return ret;
1358  }
1359 
1360  currentOffset++;
1361  }
1362 
1363  if (forwards)
1364  virtualLine++;
1365  else
1366  virtualLine--;
1367  }
1368 
1369  // Looks like we were asked for something a bit exotic.
1370  // Return the max/min valid position.
1371  if (forwards)
1372  return KTextEditor::Cursor(m_view->textFolding().visibleLines() - 1, doc()->lineLength(m_view->textFolding().visibleLineToLine (m_view->textFolding().visibleLines() - 1)));
1373  else
1374  return KTextEditor::Cursor(0, 0);
1375 }
1376 
1377 int KateViewInternal::lineMaxCursorX(const KateTextLayout& range)
1378 {
1379  if (!m_view->wrapCursor() && !range.wrap())
1380  return INT_MAX;
1381 
1382  int maxX = range.endX();
1383 
1384  if (maxX && range.wrap()) {
1385  QChar lastCharInLine = doc()->kateTextLine(range.line())->at(range.endCol() - 1);
1386  maxX -= renderer()->config()->fontMetrics().width(lastCharInLine);
1387  }
1388 
1389  return maxX;
1390 }
1391 
1392 int KateViewInternal::lineMaxCol(const KateTextLayout& range)
1393 {
1394  int maxCol = range.endCol();
1395 
1396  if (maxCol && range.wrap())
1397  maxCol--;
1398 
1399  return maxCol;
1400 }
1401 
1402 void KateViewInternal::cursorUp(bool sel)
1403 {
1404  if(!sel && m_view->completionWidget()->isCompletionActive()) {
1405  m_view->completionWidget()->cursorUp();
1406  return;
1407  }
1408 
1409  if (m_displayCursor.line() == 0 && (!m_view->dynWordWrap() || cache()->viewLine(m_cursor) == 0))
1410  return;
1411 
1412  m_preserveX = true;
1413 
1414  KateTextLayout thisLine = currentLayout();
1415  // This is not the first line because that is already simplified out above
1416  KateTextLayout pRange = previousLayout();
1417 
1418  // Ensure we're in the right spot
1419  Q_ASSERT(m_cursor.line() == thisLine.line());
1420  Q_ASSERT(m_cursor.column() >= thisLine.startCol());
1421  Q_ASSERT(!thisLine.wrap() || m_cursor.column() < thisLine.endCol());
1422 
1423  KTextEditor::Cursor c = renderer()->xToCursor(pRange, m_preservedX, !m_view->wrapCursor());
1424 
1425  updateSelection( c, sel );
1426  updateCursor( c );
1427 }
1428 
1429 void KateViewInternal::cursorDown(bool sel)
1430 {
1431  if(!sel && m_view->completionWidget()->isCompletionActive()) {
1432  m_view->completionWidget()->cursorDown();
1433  return;
1434  }
1435 
1436  if ((m_displayCursor.line() >= m_view->textFolding().visibleLines() - 1) && (!m_view->dynWordWrap() || cache()->viewLine(m_cursor) == cache()->lastViewLine(m_cursor.line())))
1437  return;
1438 
1439  m_preserveX = true;
1440 
1441  KateTextLayout thisLine = currentLayout();
1442  // This is not the last line because that is already simplified out above
1443  KateTextLayout nRange = nextLayout();
1444 
1445  // Ensure we're in the right spot
1446  Q_ASSERT((m_cursor.line() == thisLine.line()) &&
1447  (m_cursor.column() >= thisLine.startCol()) &&
1448  (!thisLine.wrap() || m_cursor.column() < thisLine.endCol()));
1449 
1450  KTextEditor::Cursor c = renderer()->xToCursor(nRange, m_preservedX, !m_view->wrapCursor());
1451 
1452  updateSelection(c, sel);
1453  updateCursor(c);
1454 }
1455 
1456 void KateViewInternal::cursorToMatchingBracket( bool sel )
1457 {
1458  KTextEditor::Cursor c = findMatchingBracket();
1459 
1460  if (c.isValid()) {
1461  updateSelection( c, sel );
1462  updateCursor( c );
1463  }
1464 }
1465 
1466 void KateViewInternal::topOfView( bool sel )
1467 {
1468  KTextEditor::Cursor c = viewLineOffset(startPos(), m_minLinesVisible);
1469  updateSelection( toRealCursor(c), sel );
1470  updateCursor( toRealCursor(c) );
1471 }
1472 
1473 void KateViewInternal::bottomOfView( bool sel )
1474 {
1475  KTextEditor::Cursor c = viewLineOffset(endPos(), -m_minLinesVisible);
1476  updateSelection( toRealCursor(c), sel );
1477  updateCursor( toRealCursor(c) );
1478 }
1479 
1480 // lines is the offset to scroll by
1481 void KateViewInternal::scrollLines( int lines, bool sel )
1482 {
1483  KTextEditor::Cursor c = viewLineOffset(m_displayCursor, lines, true);
1484 
1485  // Fix the virtual cursor -> real cursor
1486  c.setLine(m_view->textFolding().visibleLineToLine(c.line()));
1487 
1488  updateSelection( c, sel );
1489  updateCursor( c );
1490 }
1491 
1492 // This is a bit misleading... it's asking for the view to be scrolled, not the cursor
1493 void KateViewInternal::scrollUp()
1494 {
1495  KTextEditor::Cursor newPos = viewLineOffset(startPos(), -1);
1496  scrollPos(newPos);
1497 }
1498 
1499 void KateViewInternal::scrollDown()
1500 {
1501  KTextEditor::Cursor newPos = viewLineOffset(startPos(), 1);
1502  scrollPos(newPos);
1503 }
1504 
1505 void KateViewInternal::setAutoCenterLines(int viewLines, bool updateView)
1506 {
1507  m_autoCenterLines = viewLines;
1508  m_minLinesVisible = qMin(int((linesDisplayed() - 1)/2), m_autoCenterLines);
1509  if (updateView)
1510  KateViewInternal::updateView();
1511 }
1512 
1513 void KateViewInternal::pageUp( bool sel, bool half )
1514 {
1515  if (m_view->isCompletionActive()) {
1516  m_view->completionWidget()->pageUp();
1517  return;
1518  }
1519 
1520  // remember the view line and x pos
1521  int viewLine = cache()->displayViewLine(m_displayCursor);
1522  bool atTop = startPos().atStartOfDocument();
1523 
1524  // Adjust for an auto-centering cursor
1525  int lineadj = m_minLinesVisible;
1526 
1527  int linesToScroll;
1528  if ( ! half )
1529  linesToScroll = -qMax( (linesDisplayed() - 1) - lineadj, 0 );
1530  else
1531  linesToScroll = -qMax( (linesDisplayed()/2 - 1) - lineadj, 0 );
1532 
1533  m_preserveX = true;
1534 
1535  if (!doc()->pageUpDownMovesCursor () && !atTop) {
1536  KTextEditor::Cursor newStartPos = viewLineOffset(startPos(), linesToScroll - 1);
1537  scrollPos(newStartPos);
1538 
1539  // put the cursor back approximately where it was
1540  KTextEditor::Cursor newPos = toRealCursor(viewLineOffset(newStartPos, viewLine, true));
1541 
1542  KateTextLayout newLine = cache()->textLayout(newPos);
1543 
1544  newPos = renderer()->xToCursor(newLine, m_preservedX, !m_view->wrapCursor());
1545 
1546  m_preserveX = true;
1547  updateSelection( newPos, sel );
1548  updateCursor(newPos);
1549 
1550  } else {
1551  scrollLines( linesToScroll, sel );
1552  }
1553 }
1554 
1555 void KateViewInternal::pageDown( bool sel ,bool half)
1556 {
1557  if (m_view->isCompletionActive()) {
1558  m_view->completionWidget()->pageDown();
1559  return;
1560  }
1561 
1562  // remember the view line
1563  int viewLine = cache()->displayViewLine(m_displayCursor);
1564  bool atEnd = startPos() >= m_cachedMaxStartPos;
1565 
1566  // Adjust for an auto-centering cursor
1567  int lineadj = m_minLinesVisible;
1568 
1569  int linesToScroll;
1570  if ( ! half )
1571  linesToScroll = qMax( (linesDisplayed() - 1) - lineadj, 0 );
1572  else
1573  linesToScroll = qMax( (linesDisplayed()/2 - 1) - lineadj, 0 );
1574 
1575  m_preserveX = true;
1576 
1577  if (!doc()->pageUpDownMovesCursor () && !atEnd) {
1578  KTextEditor::Cursor newStartPos = viewLineOffset(startPos(), linesToScroll + 1);
1579  scrollPos(newStartPos);
1580 
1581  // put the cursor back approximately where it was
1582  KTextEditor::Cursor newPos = toRealCursor(viewLineOffset(newStartPos, viewLine, true));
1583 
1584  KateTextLayout newLine = cache()->textLayout(newPos);
1585 
1586  newPos = renderer()->xToCursor(newLine, m_preservedX, !m_view->wrapCursor());
1587 
1588  m_preserveX = true;
1589  updateSelection( newPos, sel );
1590  updateCursor(newPos);
1591 
1592  } else {
1593  scrollLines( linesToScroll, sel );
1594  }
1595 }
1596 
1597 int KateViewInternal::maxLen(int startLine)
1598 {
1599  Q_ASSERT(!m_view->dynWordWrap());
1600 
1601  int displayLines = (m_view->height() / renderer()->lineHeight()) + 1;
1602 
1603  int maxLen = 0;
1604 
1605  for (int z = 0; z < displayLines; z++) {
1606  int virtualLine = startLine + z;
1607 
1608  if (virtualLine < 0 || virtualLine >= (int)m_view->textFolding().visibleLines())
1609  break;
1610 
1611  maxLen = qMax(maxLen, cache()->line(m_view->textFolding().visibleLineToLine(virtualLine))->width());
1612  }
1613 
1614  return maxLen;
1615 }
1616 
1617 bool KateViewInternal::columnScrollingPossible ()
1618 {
1619  return !m_view->dynWordWrap() && m_columnScroll->isEnabled() && (m_columnScroll->maximum() > 0);
1620 }
1621 
1622 void KateViewInternal::top( bool sel )
1623 {
1624  KTextEditor::Cursor newCursor(0, 0);
1625 
1626  newCursor = renderer()->xToCursor(cache()->textLayout(newCursor), m_preservedX, !m_view->wrapCursor());
1627 
1628  updateSelection( newCursor, sel );
1629  updateCursor( newCursor );
1630 }
1631 
1632 void KateViewInternal::bottom( bool sel )
1633 {
1634  KTextEditor::Cursor newCursor(doc()->lastLine(), 0);
1635 
1636  newCursor = renderer()->xToCursor(cache()->textLayout(newCursor), m_preservedX, !m_view->wrapCursor());
1637 
1638  updateSelection( newCursor, sel );
1639  updateCursor( newCursor );
1640 }
1641 
1642 void KateViewInternal::top_home( bool sel )
1643 {
1644  if (m_view->isCompletionActive()) {
1645  m_view->completionWidget()->top();
1646  return;
1647  }
1648 
1649  KTextEditor::Cursor c( 0, 0 );
1650  updateSelection( c, sel );
1651  updateCursor( c );
1652 }
1653 
1654 void KateViewInternal::bottom_end( bool sel )
1655 {
1656  if (m_view->isCompletionActive()) {
1657  m_view->completionWidget()->bottom();
1658  return;
1659  }
1660 
1661  KTextEditor::Cursor c( doc()->lastLine(), doc()->lineLength( doc()->lastLine() ) );
1662  updateSelection( c, sel );
1663  updateCursor( c );
1664 }
1665 
1666 void KateViewInternal::updateSelection( const KTextEditor::Cursor& _newCursor, bool keepSel )
1667 {
1668  KTextEditor::Cursor newCursor = _newCursor;
1669  if( keepSel )
1670  {
1671  if ( !m_view->selection() || (m_selectAnchor.line() == -1)
1672  //don't kill the selection if we have a persistent selection and
1673  //the cursor is inside or at the boundaries of the selected area
1674  || (m_view->config()->persistentSelection()
1675  && !(m_view->selectionRange().contains(m_cursor)
1676  || m_view->selectionRange().boundaryAtCursor(m_cursor))) )
1677  {
1678  m_selectAnchor = m_cursor;
1679  setSelection( KTextEditor::Range(m_cursor, newCursor) );
1680  }
1681  else
1682  {
1683  bool doSelect = true;
1684  switch (m_selectionMode)
1685  {
1686  case Word:
1687  {
1688  // Restore selStartCached if needed. It gets nuked by
1689  // viewSelectionChanged if we drag the selection into non-existence,
1690  // which can legitimately happen if a shift+DC selection is unable to
1691  // set a "proper" (i.e. non-empty) cached selection, e.g. because the
1692  // start was on something that isn't a word. Word select mode relies
1693  // on the cached selection being set properly, even if it is empty
1694  // (i.e. selStartCached == selEndCached).
1695  if ( !m_selectionCached.isValid() )
1696  m_selectionCached.start() = m_selectionCached.end();
1697 
1698  int c;
1699  if ( newCursor > m_selectionCached.start() )
1700  {
1701  m_selectAnchor = m_selectionCached.start();
1702 
1703  Kate::TextLine l = doc()->kateTextLine( newCursor.line() );
1704 
1705  c = newCursor.column();
1706  if ( c > 0 && doc()->highlight()->isInWord( l->at( c-1 ) ) ) {
1707  for ( ; c < l->length(); c++ )
1708  if ( !doc()->highlight()->isInWord( l->at( c ) ) )
1709  break;
1710  }
1711 
1712  newCursor.setColumn( c );
1713  }
1714  else if ( newCursor < m_selectionCached.start() )
1715  {
1716  m_selectAnchor = m_selectionCached.end();
1717 
1718  Kate::TextLine l = doc()->kateTextLine( newCursor.line() );
1719 
1720  c = newCursor.column();
1721  if ( c > 0 && c < doc()->lineLength( newCursor.line() )
1722  && doc()->highlight()->isInWord( l->at( c ) )
1723  && doc()->highlight()->isInWord( l->at( c-1 ) ) ) {
1724  for ( c -= 2; c >= 0; c-- )
1725  if ( !doc()->highlight()->isInWord( l->at( c ) ) )
1726  break;
1727  newCursor.setColumn( c+1 );
1728  }
1729  }
1730  else
1731  doSelect = false;
1732 
1733  }
1734  break;
1735  case Line:
1736  if ( !m_selectionCached.isValid() ) {
1737  m_selectionCached = KTextEditor::Range(endLine(), 0, endLine(), 0);
1738  }
1739  if ( newCursor.line() > m_selectionCached.start().line() )
1740  {
1741  if (newCursor.line() + 1 >= doc()->lines() )
1742  newCursor.setColumn( doc()->line( newCursor.line() ).length() );
1743  else
1744  newCursor.setPosition( newCursor.line() + 1, 0 );
1745  // Grow to include the entire line
1746  m_selectAnchor = m_selectionCached.start();
1747  m_selectAnchor.setColumn( 0 );
1748  }
1749  else if ( newCursor.line() < m_selectionCached.start().line() )
1750  {
1751  newCursor.setColumn( 0 );
1752  // Grow to include entire line
1753  m_selectAnchor = m_selectionCached.end();
1754  if ( m_selectAnchor.column() > 0 )
1755  {
1756  if ( m_selectAnchor.line()+1 >= doc()->lines() )
1757  m_selectAnchor.setColumn( doc()->line( newCursor.line() ).length() );
1758  else
1759  m_selectAnchor.setPosition( m_selectAnchor.line() + 1, 0 );
1760  }
1761  }
1762  else // same line, ignore
1763  doSelect = false;
1764  break;
1765  case Mouse:
1766  {
1767  if ( !m_selectionCached.isValid() )
1768  break;
1769 
1770  if ( newCursor > m_selectionCached.end() )
1771  m_selectAnchor = m_selectionCached.start();
1772  else if ( newCursor < m_selectionCached.start() )
1773  m_selectAnchor = m_selectionCached.end();
1774  else
1775  doSelect = false;
1776  }
1777  break;
1778  default: /* nothing special to do */;
1779  }
1780 
1781  if ( doSelect )
1782  setSelection( KTextEditor::Range(m_selectAnchor, newCursor) );
1783  else if ( m_selectionCached.isValid() ) // we have a cached selection, so we restore that
1784  setSelection( m_selectionCached );
1785  }
1786 
1787  m_selChangedByUser = true;
1788  }
1789  else if ( !m_view->config()->persistentSelection() )
1790  {
1791  m_view->clearSelection();
1792 
1793  m_selectionCached = KTextEditor::Range::invalid();
1794  m_selectAnchor = KTextEditor::Cursor::invalid();
1795  }
1796 
1797 #ifndef QT_NO_ACCESSIBILITY
1798 #if QT_VERSION >= 0x040800
1799  QAccessible::updateAccessibility(this, 0, QAccessible::TextSelectionChanged);
1800 #endif
1801 #endif
1802 }
1803 
1804 void KateViewInternal::setCaretStyle( KateRenderer::caretStyles style, bool repaint )
1805 {
1806  renderer()->setCaretStyle( style );
1807 
1808  if ( repaint ) {
1809  if ( m_cursorTimer.isActive() &&
1810  KApplication::cursorFlashTime() > 0 ) {
1811  m_cursorTimer.start( KApplication::cursorFlashTime() / 2 );
1812  }
1813  renderer()->setDrawCaret(true);
1814  paintCursor();
1815  }
1816 }
1817 
1818 void KateViewInternal::setSelection( const KTextEditor::Range &range )
1819 {
1820  disconnect(m_view, SIGNAL(selectionChanged(KTextEditor::View*)), this, SLOT(viewSelectionChanged()));
1821  m_view->setSelection(range);
1822  connect(m_view, SIGNAL(selectionChanged(KTextEditor::View*)), this, SLOT(viewSelectionChanged()));
1823 }
1824 
1825 void KateViewInternal::moveCursorToSelectionEdge()
1826 {
1827  if (!m_view->selection())
1828  return;
1829 
1830  int tmp = m_minLinesVisible;
1831  m_minLinesVisible = 0;
1832 
1833  if ( m_view->selectionRange().start() < m_selectAnchor )
1834  updateCursor( m_view->selectionRange().start() );
1835  else
1836  updateCursor( m_view->selectionRange().end() );
1837 
1838  m_minLinesVisible = tmp;
1839 }
1840 
1841 void KateViewInternal::updateCursor( const KTextEditor::Cursor& newCursor, bool force, bool center, bool calledExternally )
1842 {
1843  if ( !force && (m_cursor.toCursor() == newCursor) )
1844  {
1845  m_displayCursor = toVirtualCursor(newCursor);
1846  if ( !m_madeVisible && m_view == doc()->activeView() )
1847  {
1848  // unfold if required
1849  m_view->textFolding().ensureLineIsVisible ( newCursor.line() );
1850 
1851  makeVisible ( m_displayCursor, m_displayCursor.column(), false, center, calledExternally );
1852  }
1853 
1854  return;
1855  }
1856 
1857  // unfold if required
1858  m_view->textFolding().ensureLineIsVisible ( newCursor.line() );
1859 
1860  KTextEditor::Cursor oldDisplayCursor = m_displayCursor;
1861 
1862  m_displayCursor = toVirtualCursor(newCursor);
1863  m_cursor.setPosition( newCursor );
1864 
1865  if ( m_view == doc()->activeView() )
1866  makeVisible ( m_displayCursor, m_displayCursor.column(), false, center, calledExternally );
1867 
1868  updateBracketMarks();
1869 
1870  // It's efficient enough to just tag them both without checking to see if they're on the same view line
1871 /* kdDebug()<<"oldDisplayCursor:"<<oldDisplayCursor<<endl;
1872  kdDebug()<<"m_displayCursor:"<<m_displayCursor<<endl;*/
1873  tagLine(oldDisplayCursor);
1874  tagLine(m_displayCursor);
1875 
1876  updateMicroFocus();
1877 
1878  if (m_cursorTimer.isActive ())
1879  {
1880  if ( KApplication::cursorFlashTime() > 0 )
1881  m_cursorTimer.start( KApplication::cursorFlashTime() / 2 );
1882  renderer()->setDrawCaret(true);
1883  }
1884 
1885  // Remember the maximum X position if requested
1886  if (m_preserveX)
1887  m_preserveX = false;
1888  else
1889  m_preservedX = renderer()->cursorToX(cache()->textLayout(m_cursor), m_cursor, !m_view->wrapCursor());
1890 
1891  //kDebug(13030) << "m_preservedX: " << m_preservedX << " (was "<< oldmaxx << "), m_cursorX: " << m_cursorX;
1892  //kDebug(13030) << "Cursor now located at real " << cursor.line << "," << cursor.col << ", virtual " << m_displayCursor.line << ", " << m_displayCursor.col << "; Top is " << startLine() << ", " << startPos().col;
1893 
1894  cursorMoved();
1895 
1896  updateDirty(); //paintText(0, 0, width(), height(), true);
1897 
1898  emit m_view->cursorPositionChanged(m_view, m_cursor);
1899 }
1900 
1901 void KateViewInternal::updateBracketMarkAttributes()
1902 {
1903  KTextEditor::Attribute::Ptr bracketFill = KTextEditor::Attribute::Ptr(new KTextEditor::Attribute());
1904  bracketFill->setBackground(m_view->m_renderer->config()->highlightedBracketColor());
1905  bracketFill->setBackgroundFillWhitespace(false);
1906  if (QFontInfo(renderer()->currentFont()).fixedPitch()) {
1907  // make font bold only for fixed fonts, otherwise text jumps around
1908  bracketFill->setFontBold();
1909  }
1910 
1911  m_bmStart->setAttribute(bracketFill);
1912  m_bmEnd->setAttribute(bracketFill);
1913 
1914  if (m_view->m_renderer->config()->showWholeBracketExpression()) {
1915  KTextEditor::Attribute::Ptr expressionFill = KTextEditor::Attribute::Ptr(new KTextEditor::Attribute());
1916  expressionFill->setBackground(m_view->m_renderer->config()->highlightedBracketColor());
1917  expressionFill->setBackgroundFillWhitespace(false);
1918 
1919  m_bm->setAttribute(expressionFill);
1920  } else {
1921  m_bm->setAttribute(KTextEditor::Attribute::Ptr(new KTextEditor::Attribute()));
1922  }
1923 }
1924 
1925 void KateViewInternal::updateBracketMarks()
1926 {
1927  // add some limit to this, this is really endless on big files without limit
1928  int maxLines = 5000;
1929  KTextEditor::Range newRange;
1930  doc()->newBracketMark( m_cursor, newRange, maxLines );
1931 
1932  // new range valid, then set ranges to it
1933  if (newRange.isValid ()) {
1934  // modify full range
1935  m_bm->setRange (newRange);
1936 
1937  // modify start and end ranges
1938  m_bmStart->setRange (KTextEditor::Range (m_bm->start(), KTextEditor::Cursor (m_bm->start().line(), m_bm->start().column() + 1)));
1939  m_bmEnd->setRange (KTextEditor::Range (m_bm->end(), KTextEditor::Cursor (m_bm->end().line(), m_bm->end().column() + 1)));
1940  return;
1941  }
1942 
1943  // new range was invalid
1944  m_bm->setRange (KTextEditor::Range::invalid());
1945  m_bmStart->setRange (KTextEditor::Range::invalid());
1946  m_bmEnd->setRange (KTextEditor::Range::invalid());
1947 }
1948 
1949 bool KateViewInternal::tagLine(const KTextEditor::Cursor& virtualCursor)
1950 {
1951  // FIXME may be a more efficient way for this
1952  if ((int)m_view->textFolding().visibleLineToLine(virtualCursor.line()) > doc()->lastLine())
1953  return false;
1954  // End FIXME
1955 
1956  int viewLine = cache()->displayViewLine(virtualCursor, true);
1957  if (viewLine >= 0 && viewLine < cache()->viewCacheLineCount()) {
1958  cache()->viewLine(viewLine).setDirty();
1959  m_leftBorder->update (0, lineToY(viewLine), m_leftBorder->width(), renderer()->lineHeight());
1960  return true;
1961  }
1962  return false;
1963 }
1964 
1965 bool KateViewInternal::tagLines( int start, int end, bool realLines )
1966 {
1967  return tagLines(KTextEditor::Cursor(start, 0), KTextEditor::Cursor(end, -1), realLines);
1968 }
1969 
1970 bool KateViewInternal::tagLines(KTextEditor::Cursor start, KTextEditor::Cursor end, bool realCursors)
1971 {
1972  if (realCursors)
1973  {
1974  cache()->relayoutLines(start.line(), end.line());
1975 
1976  //kDebug(13030)<<"realLines is true";
1977  start = toVirtualCursor(start);
1978  end = toVirtualCursor(end);
1979 
1980  } else {
1981  cache()->relayoutLines(toRealCursor(start).line(), toRealCursor(end).line());
1982  }
1983 
1984  if (end.line() < startLine())
1985  {
1986  //kDebug(13030)<<"end<startLine";
1987  return false;
1988  }
1989  // Used to be > endLine(), but cache may not be valid when checking, so use a
1990  // less optimal but still adequate approximation (potential overestimation but minimal performance difference)
1991  if (start.line() > startLine() + cache()->viewCacheLineCount())
1992  {
1993  //kDebug(13030)<<"start> endLine"<<start<<" "<<(endLine());
1994  return false;
1995  }
1996 
1997  cache()->updateViewCache(startPos());
1998 
1999  //kDebug(13030) << "tagLines( [" << start << "], [" << end << "] )";
2000 
2001  bool ret = false;
2002 
2003  for (int z = 0; z < cache()->viewCacheLineCount(); z++)
2004  {
2005  KateTextLayout& line = cache()->viewLine(z);
2006  if ((line.virtualLine() > start.line() || (line.virtualLine() == start.line() && line.endCol() >= start.column() && start.column() != -1)) &&
2007  (line.virtualLine() < end.line() || (line.virtualLine() == end.line() && (line.startCol() <= end.column() || end.column() == -1)))) {
2008  ret = true;
2009  break;
2010  //kDebug(13030) << "Tagged line " << line.line();
2011  }
2012  }
2013 
2014  if (!m_view->dynWordWrap())
2015  {
2016  int y = lineToY( start.line() );
2017  // FIXME is this enough for when multiple lines are deleted
2018  int h = (end.line() - start.line() + 2) * renderer()->lineHeight();
2019  if (end.line() >= m_view->textFolding().visibleLines() - 1)
2020  h = height();
2021 
2022  m_leftBorder->update (0, y, m_leftBorder->width(), h);
2023  }
2024  else
2025  {
2026  // FIXME Do we get enough good info in editRemoveText to optimize this more?
2027  //bool justTagged = false;
2028  for (int z = 0; z < cache()->viewCacheLineCount(); z++)
2029  {
2030  KateTextLayout& line = cache()->viewLine(z);
2031  if (!line.isValid() ||
2032  ((line.virtualLine() > start.line() || (line.virtualLine() == start.line() && line.endCol() >= start.column() && start.column() != -1)) &&
2033  (line.virtualLine() < end.line() || (line.virtualLine() == end.line() && (line.startCol() <= end.column() || end.column() == -1)))))
2034  {
2035  //justTagged = true;
2036  m_leftBorder->update (0, z * renderer()->lineHeight(), m_leftBorder->width(), m_leftBorder->height());
2037  break;
2038  }
2039  /*else if (justTagged)
2040  {
2041  justTagged = false;
2042  leftBorder->update (0, z * doc()->viewFont.fontHeight, leftBorder->width(), doc()->viewFont.fontHeight);
2043  break;
2044  }*/
2045  }
2046  }
2047 
2048  return ret;
2049 }
2050 
2051 bool KateViewInternal::tagRange(const KTextEditor::Range& range, bool realCursors)
2052 {
2053  return tagLines(range.start(), range.end(), realCursors);
2054 }
2055 
2056 void KateViewInternal::tagAll()
2057 {
2058  // clear the cache...
2059  cache()->clear ();
2060 
2061  m_leftBorder->updateFont();
2062  m_leftBorder->update();
2063 }
2064 
2065 void KateViewInternal::paintCursor()
2066 {
2067  if (tagLine(m_displayCursor))
2068  updateDirty(); //paintText (0,0,width(), height(), true);
2069 }
2070 
2071 // Point in content coordinates
2072 void KateViewInternal::placeCursor( const QPoint& p, bool keepSelection, bool updateSelection )
2073 {
2074  KateTextLayout thisLine = yToKateTextLayout(p.y());
2075  KTextEditor::Cursor c;
2076 
2077  if (!thisLine.isValid()) // probably user clicked below the last line -> use the last line
2078  thisLine = cache()->textLayout(doc()->lines() - 1, -1);
2079 
2080  c = renderer()->xToCursor(thisLine, startX() + p.x(), !m_view->wrapCursor());
2081 
2082  if (c.line () < 0 || c.line() >= doc()->lines()) {
2083  return;
2084  }
2085 
2086  if (updateSelection)
2087  KateViewInternal::updateSelection( c, keepSelection );
2088 
2089  int tmp = m_minLinesVisible;
2090  m_minLinesVisible = 0;
2091  updateCursor( c );
2092  m_minLinesVisible = tmp;
2093 
2094  if (updateSelection && keepSelection)
2095  moveCursorToSelectionEdge();
2096 }
2097 
2098 // Point in content coordinates
2099 bool KateViewInternal::isTargetSelected( const QPoint& p )
2100 {
2101  const KateTextLayout& thisLine = yToKateTextLayout(p.y());
2102  if (!thisLine.isValid())
2103  return false;
2104 
2105  return m_view->cursorSelected(renderer()->xToCursor(thisLine, startX() + p.x(), !m_view->wrapCursor()));
2106 }
2107 
2108 //BEGIN EVENT HANDLING STUFF
2109 
2110 bool KateViewInternal::eventFilter( QObject *obj, QEvent *e )
2111 {
2112  if (obj == m_lineScroll)
2113  {
2114  // the second condition is to make sure a scroll on the vertical bar doesn't cause a horizontal scroll ;)
2115  if (e->type() == QEvent::Wheel && m_lineScroll->minimum() != m_lineScroll->maximum())
2116  {
2117  wheelEvent((QWheelEvent*)e);
2118  return true;
2119  }
2120 
2121  // continue processing
2122  return QWidget::eventFilter( obj, e );
2123  }
2124 
2125  switch( e->type() )
2126  {
2127  case QEvent::ChildAdded:
2128  case QEvent::ChildRemoved: {
2129  QChildEvent* c = static_cast<QChildEvent*>(e);
2130  if (c->added()) {
2131  c->child()->installEventFilter(this);
2132  /*foreach (QWidget* child, c->child()->findChildren<QWidget*>())
2133  child->installEventFilter(this);*/
2134 
2135  } else if (c->removed()) {
2136  c->child()->removeEventFilter(this);
2137 
2138  /*foreach (QWidget* child, c->child()->findChildren<QWidget*>())
2139  child->removeEventFilter(this);*/
2140  }
2141  } break;
2142 
2143  case QEvent::ShortcutOverride:
2144  {
2145  QKeyEvent *k = static_cast<QKeyEvent *>(e);
2146 
2147  if (k->key() == Qt::Key_Escape && k->modifiers() == Qt::NoModifier) {
2148  if (m_view->isCompletionActive()) {
2149  m_view->abortCompletion();
2150  k->accept();
2151  //kDebug() << obj << "shortcut override" << k->key() << "aborting completion";
2152  return true;
2153  } else if (m_view->bottomViewBar()->isVisible()) {
2154  m_view->bottomViewBar()->hideCurrentBarWidget();
2155  k->accept();
2156  //kDebug() << obj << "shortcut override" << k->key() << "closing view bar";
2157  return true;
2158  } else if (!m_view->config()->persistentSelection() && m_view->selection()) {
2159  if (!m_view->viInputMode()) // Vim mode handles clearing selections itself.
2160  {
2161  m_view->clearSelection();
2162  }
2163  k->accept();
2164  //kDebug() << obj << "shortcut override" << k->key() << "clearing selection";
2165  return true;
2166  }
2167  }
2168 
2169  // if vi input mode key stealing is on, override kate shortcuts
2170  if (m_view->viInputMode() && m_view->viInputModeStealKeys() && ( m_view->getCurrentViMode() != InsertMode ||
2171  ( m_view->getCurrentViMode() == InsertMode && k->modifiers() == Qt::ControlModifier ) ) ) {
2172  k->accept();
2173  return true;
2174  }
2175 
2176  } break;
2177 
2178  case QEvent::KeyPress:
2179  {
2180  QKeyEvent *k = static_cast<QKeyEvent *>(e);
2181 
2182  // Override all other single key shortcuts which do not use a modifier other than Shift
2183  if (obj == this && (!k->modifiers() || k->modifiers() == Qt::ShiftModifier)) {
2184  keyPressEvent( k );
2185  if (k->isAccepted()) {
2186  //kDebug() << obj << "shortcut override" << k->key() << "using keystroke";
2187  return true;
2188  }
2189  }
2190 
2191  //kDebug() << obj << "shortcut override" << k->key() << "ignoring";
2192  } break;
2193 
2194  case QEvent::DragMove:
2195  {
2196  QPoint currentPoint = ((QDragMoveEvent*) e)->pos();
2197 
2198  QRect doNotScrollRegion( s_scrollMargin, s_scrollMargin,
2199  width() - s_scrollMargin * 2,
2200  height() - s_scrollMargin * 2 );
2201 
2202  if ( !doNotScrollRegion.contains( currentPoint ) )
2203  {
2204  startDragScroll();
2205  // Keep sending move events
2206  ( (QDragMoveEvent*)e )->accept( QRect(0,0,0,0) );
2207  }
2208 
2209  dragMoveEvent((QDragMoveEvent*)e);
2210  } break;
2211 
2212  case QEvent::DragLeave:
2213  // happens only when pressing ESC while dragging
2214  stopDragScroll();
2215  break;
2216 
2217  case QEvent::WindowBlocked:
2218  // next focus originates from an internal dialog:
2219  // don't show the modonhd prompt
2220  if (isVisible()) {
2221  doc()->ignoreModifiedOnDiskOnce();
2222  }
2223  break;
2224 
2225  default:
2226  break;
2227  }
2228 
2229  return QWidget::eventFilter( obj, e );
2230 }
2231 
2232 void KateViewInternal::keyPressEvent( QKeyEvent* e )
2233 {
2234  if( e->key() == Qt::Key_Left && e->modifiers() == Qt::AltModifier ) {
2235  m_view->emitNavigateLeft();
2236  e->setAccepted(true);
2237  return;
2238  }
2239  if( e->key() == Qt::Key_Right && e->modifiers() == Qt::AltModifier ) {
2240  m_view->emitNavigateRight();
2241  e->setAccepted(true);
2242  return;
2243  }
2244  if( e->key() == Qt::Key_Up && e->modifiers() == Qt::AltModifier ) {
2245  m_view->emitNavigateUp();
2246  e->setAccepted(true);
2247  return;
2248  }
2249  if( e->key() == Qt::Key_Down && e->modifiers() == Qt::AltModifier ) {
2250  m_view->emitNavigateDown();
2251  e->setAccepted(true);
2252  return;
2253  }
2254  if( e->key() == Qt::Key_Return && e->modifiers() == Qt::AltModifier ) {
2255  m_view->emitNavigateAccept();
2256  e->setAccepted(true);
2257  return;
2258  }
2259  if( e->key() == Qt::Key_Backspace && e->modifiers() == Qt::AltModifier ) {
2260  m_view->emitNavigateBack();
2261  e->setAccepted(true);
2262  return;
2263  }
2264 
2265  if( e->key() == Qt::Key_Alt && m_view->completionWidget()->isCompletionActive() ) {
2266  m_completionItemExpanded = m_view->completionWidget()->toggleExpanded(true);
2267  m_view->completionWidget()->resetHadNavigation();
2268  m_altDownTime = QTime::currentTime();
2269  }
2270 
2271  // Note: AND'ing with <Shift> is a quick hack to fix Key_Enter
2272  const int key = e->key() | (e->modifiers() & Qt::ShiftModifier);
2273 
2274  if (m_view->isCompletionActive()
2275  && !m_view->viInputMode() /* Vi input mode needs to handle completion keypresses itself for e.g. mappings */)
2276  {
2277  if( key == Qt::Key_Enter || key == Qt::Key_Return ) {
2278  m_view->completionWidget()->execute();
2279  e->accept();
2280  return;
2281  }
2282  }
2283 
2284  if ( m_view->viInputMode() ) {
2285  if ( getViInputModeManager()->getCurrentViMode() == InsertMode
2286  || getViInputModeManager()->getCurrentViMode() == ReplaceMode ) {
2287  if ( getViInputModeManager()->handleKeypress( e ) ) {
2288  return;
2289  } else if ( e->modifiers() != Qt::NoModifier && e->modifiers() != Qt::ShiftModifier ) {
2290  // re-post key events not handled if they have a modifier other than shift
2291  QEvent *copy = new QKeyEvent ( e->type(), e->key(), e->modifiers(), e->text(),
2292  e->isAutoRepeat(), e->count() );
2293  QCoreApplication::postEvent( parent(), copy );
2294  }
2295  } else { // !InsertMode
2296  if ( !getViInputModeManager()->handleKeypress( e ) ) {
2297  // we didn't need that keypress, un-steal it :-)
2298  QEvent *copy = new QKeyEvent ( e->type(), e->key(), e->modifiers(), e->text(),
2299  e->isAutoRepeat(), e->count() );
2300  QCoreApplication::postEvent( parent(), copy );
2301  }
2302  m_view->updateViModeBarCmd();
2303  return;
2304  }
2305  }
2306 
2307  if( !doc()->isReadWrite() )
2308  {
2309  e->ignore();
2310  return;
2311  }
2312 
2313  if ((key == Qt::Key_Return) || (key == Qt::Key_Enter) || (key == Qt::SHIFT + Qt::Key_Return) || (key == Qt::SHIFT + Qt::Key_Enter))
2314  {
2315  doReturn();
2316  e->accept();
2317  return;
2318  }
2319 
2320  if (key == Qt::Key_Backspace || key == Qt::SHIFT + Qt::Key_Backspace)
2321  {
2322  //m_view->backspace();
2323  e->accept();
2324 
2325  return;
2326  }
2327 
2328  if (key == Qt::Key_Tab || key == Qt::SHIFT+Qt::Key_Backtab || key == Qt::Key_Backtab)
2329  {
2330  if(m_view->completionWidget()->isCompletionActive())
2331  {
2332  e->accept();
2333  m_view->completionWidget()->tab(key != Qt::Key_Tab);
2334  return;
2335  }
2336 
2337  if( key == Qt::Key_Tab )
2338  {
2339  uint tabHandling = doc()->config()->tabHandling();
2340  // convert tabSmart into tabInsertsTab or tabIndents:
2341  if (tabHandling == KateDocumentConfig::tabSmart)
2342  {
2343  // multiple lines selected
2344  if (m_view->selection() && !m_view->selectionRange().onSingleLine())
2345  {
2346  tabHandling = KateDocumentConfig::tabIndents;
2347  }
2348 
2349  // otherwise: take look at cursor position
2350  else
2351  {
2352  // if the cursor is at or before the first non-space character
2353  // or on an empty line,
2354  // Tab indents, otherwise it inserts a tab character.
2355  Kate::TextLine line = doc()->kateTextLine( m_cursor.line() );
2356  int first = line->firstChar();
2357  if (first < 0 || m_cursor.column() <= first)
2358  tabHandling = KateDocumentConfig::tabIndents;
2359  else
2360  tabHandling = KateDocumentConfig::tabInsertsTab;
2361  }
2362  }
2363 
2364  if (tabHandling == KateDocumentConfig::tabInsertsTab)
2365  doc()->typeChars( m_view, QString("\t") );
2366  else
2367  doc()->indent( m_view->selection() ? m_view->selectionRange() : KTextEditor::Range(m_cursor.line(), 0, m_cursor.line(), 0), 1 );
2368 
2369  e->accept();
2370 
2371  return;
2372  }
2373  else if (doc()->config()->tabHandling() != KateDocumentConfig::tabInsertsTab)
2374  {
2375  // key == Qt::SHIFT+Qt::Key_Backtab || key == Qt::Key_Backtab
2376  doc()->indent( m_view->selection() ? m_view->selectionRange() : KTextEditor::Range(m_cursor.line(), 0, m_cursor.line(), 0), -1 );
2377  e->accept();
2378 
2379  return;
2380  }
2381  }
2382 
2383  if ( !(e->modifiers() & Qt::ControlModifier) && !e->text().isEmpty() && doc()->typeChars ( m_view, e->text() ) )
2384  {
2385  e->accept();
2386 
2387  return;
2388  }
2389 
2390  // allow composition of AltGr + (q|2|3) on windows
2391  static const int altGR = Qt::ControlModifier | Qt::AltModifier;
2392  if( (e->modifiers() & altGR) == altGR && !e->text().isEmpty() && doc()->typeChars ( m_view, e->text() ) )
2393  {
2394  e->accept();
2395 
2396  return;
2397  }
2398 
2399  e->ignore();
2400 }
2401 
2402 void KateViewInternal::keyReleaseEvent( QKeyEvent* e )
2403 {
2404  if( e->key() == Qt::Key_Alt && m_view->completionWidget()->isCompletionActive() && ((m_completionItemExpanded && (m_view->completionWidget()->hadNavigation() || m_altDownTime.msecsTo(QTime::currentTime()) > 300)) || (!m_completionItemExpanded && !m_view->completionWidget()->hadNavigation())) ) {
2405 
2406  m_view->completionWidget()->toggleExpanded(false, true);
2407  }
2408 
2409  if ((e->modifiers() & Qt::SHIFT) == Qt::SHIFT)
2410  {
2411  m_shiftKeyPressed = true;
2412  }
2413  else
2414  {
2415  if (m_shiftKeyPressed)
2416  {
2417  m_shiftKeyPressed = false;
2418 
2419  if (m_selChangedByUser)
2420  {
2421  if (m_view->selection())
2422  QApplication::clipboard()->setText(m_view->selectionText (), QClipboard::Selection);
2423 
2424  m_selChangedByUser = false;
2425  }
2426  }
2427  }
2428 
2429  e->ignore();
2430  return;
2431 }
2432 
2433 void KateViewInternal::contextMenuEvent ( QContextMenuEvent * e )
2434 {
2435  // try to show popup menu
2436 
2437  QPoint p = e->pos();
2438 
2439  if ( doc()->browserView() )
2440  {
2441  m_view->contextMenuEvent( e );
2442  return;
2443  }
2444 
2445  if ( e->reason() == QContextMenuEvent::Keyboard )
2446  {
2447  makeVisible( m_displayCursor, 0 );
2448  p = cursorCoordinates(false);
2449  p.rx() -= startX();
2450  }
2451  else if ( ! m_view->selection() || m_view->config()->persistentSelection() )
2452  placeCursor( e->pos() );
2453 
2454  // popup is a qguardedptr now
2455  if (m_view->contextMenu()) {
2456  m_view->spellingMenu()->setUseMouseForMisspelledRange((e->reason() == QContextMenuEvent::Mouse));
2457  m_view->contextMenu()->popup( mapToGlobal( p ) );
2458  e->accept ();
2459  }
2460 }
2461 
2462 void KateViewInternal::mousePressEvent( QMouseEvent* e )
2463 {
2464  switch (e->button())
2465  {
2466  case Qt::LeftButton:
2467  m_selChangedByUser = false;
2468 
2469  if (m_possibleTripleClick)
2470  {
2471  m_possibleTripleClick = false;
2472 
2473  m_selectionMode = Line;
2474 
2475  if ( e->modifiers() & Qt::ShiftModifier )
2476  {
2477  updateSelection( m_cursor, true );
2478  }
2479  else
2480  {
2481  m_view->selectLine( m_cursor );
2482  if (m_view->selection())
2483  m_selectAnchor = m_view->selectionRange().start();
2484  }
2485 
2486  if (m_view->selection())
2487  QApplication::clipboard()->setText(m_view->selectionText (), QClipboard::Selection);
2488 
2489  // Keep the line at the select anchor selected during further
2490  // mouse selection
2491  if ( m_selectAnchor.line() > m_view->selectionRange().start().line() )
2492  {
2493  // Preserve the last selected line
2494  if ( m_selectAnchor == m_view->selectionRange().end() && m_selectAnchor.column() == 0 )
2495  m_selectionCached.start().setPosition( m_selectAnchor.line()-1, 0 );
2496  else
2497  m_selectionCached.start().setPosition( m_selectAnchor.line(), 0 );
2498  m_selectionCached.end() = m_view->selectionRange().end();
2499  }
2500  else
2501  {
2502  // Preserve the first selected line
2503  m_selectionCached.start() = m_view->selectionRange().start();
2504  if ( m_view->selectionRange().end().line() > m_view->selectionRange().start().line() )
2505  m_selectionCached.end().setPosition( m_view->selectionRange().start().line()+1, 0 );
2506  else
2507  m_selectionCached.end() = m_view->selectionRange().end();
2508  }
2509 
2510  moveCursorToSelectionEdge();
2511 
2512  m_scrollX = 0;
2513  m_scrollY = 0;
2514  m_scrollTimer.start (50);
2515 
2516  e->accept();
2517  return;
2518  }
2519  else if ( m_selectionMode == Default )
2520  {
2521  m_selectionMode = Mouse;
2522  }
2523 
2524  // request the software keyboard, if any
2525  if ( e->button() == Qt::LeftButton && qApp->autoSipEnabled() )
2526  {
2527  QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel( style()->styleHint( QStyle::SH_RequestSoftwareInputPanel ) );
2528  if ( hasFocus() || behavior == QStyle::RSIP_OnMouseClick )
2529  {
2530  QEvent event( QEvent::RequestSoftwareInputPanel );
2531  QApplication::sendEvent( this, &event );
2532  }
2533  }
2534 
2535  if ( e->modifiers() & Qt::ShiftModifier )
2536  {
2537  if ( !m_selectAnchor.isValid() )
2538  m_selectAnchor = m_cursor;
2539  }
2540  else
2541  {
2542  m_selectionCached = KTextEditor::Range::invalid();
2543  }
2544 
2545  if( !(e->modifiers() & Qt::ShiftModifier) && isTargetSelected( e->pos() ) )
2546  {
2547  m_dragInfo.state = diPending;
2548  m_dragInfo.start = e->pos();
2549  }
2550  else
2551  {
2552  m_dragInfo.state = diNone;
2553 
2554  if ( e->modifiers() & Qt::ShiftModifier )
2555  {
2556  placeCursor( e->pos(), true, false );
2557  if ( m_selectionCached.start().isValid() )
2558  {
2559  if ( m_cursor.toCursor() < m_selectionCached.start() )
2560  m_selectAnchor = m_selectionCached.end();
2561  else
2562  m_selectAnchor = m_selectionCached.start();
2563  }
2564  setSelection( KTextEditor::Range( m_selectAnchor, m_cursor ) );
2565  }
2566  else
2567  {
2568  placeCursor( e->pos() );
2569  }
2570 
2571  m_scrollX = 0;
2572  m_scrollY = 0;
2573 
2574  m_scrollTimer.start (50);
2575  }
2576 
2577  e->accept ();
2578  break;
2579 
2580  default:
2581  e->ignore ();
2582  break;
2583  }
2584 }
2585 
2586 void KateViewInternal::mouseDoubleClickEvent(QMouseEvent *e)
2587 {
2588  switch (e->button())
2589  {
2590  case Qt::LeftButton:
2591  m_selectionMode = Word;
2592 
2593  if ( e->modifiers() & Qt::ShiftModifier )
2594  {
2595  KTextEditor::Range oldSelection = m_view->selectionRange();
2596 
2597  // Now select the word under the select anchor
2598  int cs, ce;
2599  Kate::TextLine l = doc()->kateTextLine( m_selectAnchor.line() );
2600 
2601  ce = m_selectAnchor.column();
2602  if ( ce > 0 && doc()->highlight()->isInWord( l->at(ce) ) ) {
2603  for (; ce < l->length(); ce++ )
2604  if ( !doc()->highlight()->isInWord( l->at(ce) ) )
2605  break;
2606  }
2607 
2608  cs = m_selectAnchor.column() - 1;
2609  if ( cs < doc()->lineLength( m_selectAnchor.line() )
2610  && doc()->highlight()->isInWord( l->at(cs) ) ) {
2611  for ( cs--; cs >= 0; cs-- )
2612  if ( !doc()->highlight()->isInWord( l->at(cs) ) )
2613  break;
2614  }
2615 
2616  // ...and keep it selected
2617  if (cs+1 < ce)
2618  {
2619  m_selectionCached.start().setPosition( m_selectAnchor.line(), cs+1 );
2620  m_selectionCached.end().setPosition( m_selectAnchor.line(), ce );
2621  }
2622  else
2623  {
2624  m_selectionCached.start() = m_selectAnchor;
2625  m_selectionCached.end() = m_selectAnchor;
2626  }
2627  // Now word select to the mouse cursor
2628  placeCursor( e->pos(), true );
2629  }
2630  else
2631  {
2632  // first clear the selection, otherwise we run into bug #106402
2633  // ...and set the cursor position, for the same reason (otherwise there
2634  // are *other* idiosyncrasies we can't fix without reintroducing said
2635  // bug)
2636  // Parameters: don't redraw, and don't emit selectionChanged signal yet
2637  m_view->clearSelection( false, false );
2638  placeCursor( e->pos() );
2639  m_view->selectWord( m_cursor );
2640  cursorToMatchingBracket(true);
2641 
2642  if (m_view->selection())
2643  {
2644  m_selectAnchor = m_view->selectionRange().start();
2645  m_selectionCached = m_view->selectionRange();
2646  }
2647  else
2648  {
2649  m_selectAnchor = m_cursor;
2650  m_selectionCached = KTextEditor::Range(m_cursor, m_cursor);
2651  }
2652  }
2653 
2654  // Move cursor to end (or beginning) of selected word
2655  if (m_view->selection())
2656  QApplication::clipboard()->setText( m_view->selectionText(), QClipboard::Selection );
2657 
2658  moveCursorToSelectionEdge();
2659  m_possibleTripleClick = true;
2660  QTimer::singleShot ( QApplication::doubleClickInterval(), this, SLOT(tripleClickTimeout()) );
2661 
2662  m_scrollX = 0;
2663  m_scrollY = 0;
2664 
2665  m_scrollTimer.start (50);
2666 
2667  e->accept ();
2668  break;
2669 
2670  default:
2671  e->ignore ();
2672  break;
2673  }
2674 }
2675 
2676 void KateViewInternal::tripleClickTimeout()
2677 {
2678  m_possibleTripleClick = false;
2679 }
2680 
2681 void KateViewInternal::mouseReleaseEvent( QMouseEvent* e )
2682 {
2683  switch (e->button())
2684  {
2685  case Qt::LeftButton:
2686  m_selectionMode = Default;
2687 // m_selectionCached.start().setLine( -1 );
2688 
2689  if (m_selChangedByUser)
2690  {
2691  if (m_view->selection()) {
2692  QApplication::clipboard()->setText(m_view->selectionText (), QClipboard::Selection);
2693  }
2694  moveCursorToSelectionEdge();
2695 
2696  m_selChangedByUser = false;
2697  }
2698 
2699  if (m_dragInfo.state == diPending)
2700  placeCursor( e->pos(), e->modifiers() & Qt::ShiftModifier );
2701  else if (m_dragInfo.state == diNone)
2702  m_scrollTimer.stop ();
2703 
2704  m_dragInfo.state = diNone;
2705 
2706  e->accept ();
2707  break;
2708 
2709  case Qt::MidButton:
2710  placeCursor( e->pos() );
2711 
2712  if( doc()->isReadWrite() ) {
2713  QString clipboard = QApplication::clipboard()->text(QClipboard::Selection);
2714  m_view->paste( &clipboard );
2715  }
2716 
2717  e->accept ();
2718  break;
2719 
2720  default:
2721  e->ignore ();
2722  break;
2723  }
2724 }
2725 
2726 void KateViewInternal::leaveEvent( QEvent* )
2727 {
2728  m_textHintTimer.stop();
2729 
2730  // fix bug 194452, scrolling keeps going if you scroll via mouse drag and press and other mouse
2731  // button outside the view area
2732  if (m_dragInfo.state == diNone)
2733  m_scrollTimer.stop ();
2734 }
2735 
2736 KTextEditor::Cursor KateViewInternal::coordinatesToCursor(const QPoint& _coord, bool includeBorder) const
2737 {
2738  QPoint coord(_coord);
2739 
2740  KTextEditor::Cursor ret = KTextEditor::Cursor::invalid();
2741 
2742  if (includeBorder) coord.rx() -= m_leftBorder->width();
2743  coord.rx() += startX();
2744 
2745  const KateTextLayout& thisLine = yToKateTextLayout(coord.y());
2746  if (thisLine.isValid())
2747  ret = renderer()->xToCursor(thisLine, coord.x(), !m_view->wrapCursor());
2748 
2749  return ret;
2750 }
2751 
2752 void KateViewInternal::mouseMoveEvent( QMouseEvent* e )
2753 {
2754  KTextEditor::Cursor newPosition = coordinatesToCursor (e->pos(), false);
2755  if (newPosition != m_mouse) {
2756  m_mouse = newPosition;
2757  mouseMoved();
2758  }
2759 
2760  if( e->buttons() & Qt::LeftButton )
2761  {
2762  if (m_dragInfo.state == diPending)
2763  {
2764  // we had a mouse down, but haven't confirmed a drag yet
2765  // if the mouse has moved sufficiently, we will confirm
2766  QPoint p( e->pos() - m_dragInfo.start );
2767 
2768  // we've left the drag square, we can start a real drag operation now
2769  if( p.manhattanLength() > KGlobalSettings::dndEventDelay() )
2770  doDrag();
2771 
2772  return;
2773  }
2774  else if (m_dragInfo.state == diDragging)
2775  {
2776  // Don't do anything after a canceled drag until the user lets go of
2777  // the mouse button!
2778  return;
2779  }
2780 
2781  m_mouseX = e->x();
2782  m_mouseY = e->y();
2783 
2784  m_scrollX = 0;
2785  m_scrollY = 0;
2786  int d = renderer()->lineHeight();
2787 
2788  if (m_mouseX < 0)
2789  m_scrollX = -d;
2790 
2791  if (m_mouseX > width())
2792  m_scrollX = d;
2793 
2794  if (m_mouseY < 0)
2795  {
2796  m_mouseY = 0;
2797  m_scrollY = -d;
2798  }
2799 
2800  if (m_mouseY > height())
2801  {
2802  m_mouseY = height();
2803  m_scrollY = d;
2804  }
2805 
2806  placeCursor( QPoint( m_mouseX, m_mouseY ), true );
2807 
2808  }
2809  else
2810  {
2811  if (isTargetSelected( e->pos() ) ) {
2812  // mouse is over selected text. indicate that the text is draggable by setting
2813  // the arrow cursor as other Qt text editing widgets do
2814  if (m_mouseCursor != Qt::ArrowCursor) {
2815  m_mouseCursor = Qt::ArrowCursor;
2816  setCursor(m_mouseCursor);
2817  }
2818  } else {
2819  // normal text cursor
2820  if (m_mouseCursor != Qt::IBeamCursor) {
2821  m_mouseCursor = Qt::IBeamCursor;
2822  setCursor(m_mouseCursor);
2823  }
2824  }
2825  //We need to check whether the mouse position is actually within the widget,
2826  //because other widgets like the icon border forward their events to this,
2827  //and we will create invalid text hint requests if we don't check
2828  if (m_textHintEnabled && geometry().contains(parentWidget()->mapFromGlobal(e->globalPos())))
2829  {
2830  if ( QToolTip::isVisible() ) {
2831  QToolTip::hideText();
2832  }
2833  m_textHintTimer.start(m_textHintTimeout);
2834  m_textHintPos = e->pos();
2835  }
2836  }
2837 }
2838 
2839 void KateViewInternal::updateDirty( )
2840 {
2841  uint h = renderer()->lineHeight();
2842 
2843  int currentRectStart = -1;
2844  int currentRectEnd = -1;
2845 
2846  QRegion updateRegion;
2847 
2848  {
2849  for (int i = 0; i < cache()->viewCacheLineCount(); ++i) {
2850  if (cache()->viewLine(i).isDirty()) {
2851  if (currentRectStart == -1) {
2852  currentRectStart = h * i;
2853  currentRectEnd = h;
2854  } else {
2855  currentRectEnd += h;
2856  }
2857 
2858  } else if (currentRectStart != -1) {
2859  updateRegion += QRect(0, currentRectStart, width(), currentRectEnd);
2860  currentRectStart = -1;
2861  currentRectEnd = -1;
2862  }
2863  }
2864  }
2865 
2866 
2867  if (currentRectStart != -1)
2868  updateRegion += QRect(0, currentRectStart, width(), currentRectEnd);
2869 
2870  if (!updateRegion.isEmpty()) {
2871  if (debugPainting) kDebug( 13030 ) << k_funcinfo << "Update dirty region " << updateRegion;
2872  update(updateRegion);
2873  }
2874 }
2875 
2876 void KateViewInternal::hideEvent(QHideEvent* e)
2877 {
2878  Q_UNUSED(e);
2879  if(m_view->isCompletionActive())
2880  m_view->completionWidget()->abortCompletion();
2881 }
2882 
2883 void KateViewInternal::paintEvent(QPaintEvent *e)
2884 {
2885  if (m_smartDirty)
2886  doUpdateView();
2887 
2888  if (debugPainting) kDebug (13030) << "GOT PAINT EVENT: Region" << e->region();
2889 
2890  const QRect& unionRect = e->rect();
2891 
2892  int xStart = startX() + unionRect.x();
2893  int xEnd = xStart + unionRect.width();
2894  uint h = renderer()->lineHeight();
2895  uint startz = (unionRect.y() / h);
2896  uint endz = startz + 1 + (unionRect.height() / h);
2897  uint lineRangesSize = cache()->viewCacheLineCount();
2898 
2899  QPainter paint(this);
2900  paint.setRenderHints (QPainter::Antialiasing);
2901 
2902  // TODO put in the proper places
2903  if ( !m_view->viInputMode() ) {
2904  setCaretStyle( m_view->isOverwriteMode() ? KateRenderer::Block : KateRenderer::Line );
2905  }
2906  renderer()->setShowTabs(doc()->config()->showTabs());
2907  renderer()->setShowTrailingSpaces(doc()->config()->showSpaces());
2908 
2909  int sy = startz * h;
2910  paint.translate(unionRect.x(), startz * h);
2911 
2912  for (uint z=startz; z <= endz; z++)
2913  {
2914  if ( (z >= lineRangesSize) || (cache()->viewLine(z).line() == -1) )
2915  {
2916  if (!(z >= lineRangesSize))
2917  cache()->viewLine(z).setDirty(false);
2918 
2919  paint.fillRect( 0, 0, unionRect.width(), h, renderer()->config()->backgroundColor() );
2920  }
2921  else
2922  {
2923  //kDebug( 13030 )<<"KateViewInternal::paintEvent(QPaintEvent *e):cache()->viewLine"<<z;
2924  KateTextLayout& thisLine = cache()->viewLine(z);
2925 
2926  /* If viewLine() returns non-zero, then a document line was split
2927  in several visual lines, and we're trying to paint visual line
2928  that is not the first. In that case, this line was already
2929  painted previously, since KateRenderer::paintTextLine paints
2930  all visual lines.
2931  Except if we're at the start of the region that needs to
2932  be painted -- when no previous calls to paintTextLine were made.
2933  */
2934  if (!thisLine.viewLine() || z == startz) {
2935  // Don't bother if we're not in the requested update region
2936  if (!e->region().contains(QRect(unionRect.x(), startz * h, unionRect.width(), h)))
2937  continue;
2938 
2939  //kDebug (13030) << "paint text: line: " << thisLine.line() << " viewLine " << thisLine.viewLine() << " x: " << unionRect.x() << " y: " << sy
2940  // << " width: " << xEnd-xStart << " height: " << h << endl;
2941 
2942  if (thisLine.viewLine())
2943  paint.translate(QPoint(0, h * - thisLine.viewLine()));
2944 
2945  // The paintTextLine function should be well behaved, but if not, this clipping may be needed
2946  //paint.setClipRect(QRect(xStart, 0, xEnd - xStart, h * (thisLine.kateLineLayout()->viewLineCount())));
2947 
2948  KTextEditor::Cursor pos = m_cursor;
2949  renderer()->paintTextLine(paint, thisLine.kateLineLayout(), xStart, xEnd, &pos);
2950 
2951  //paint.setClipping(false);
2952 
2953  if (thisLine.viewLine())
2954  paint.translate(0, h * thisLine.viewLine());
2955 
2956  thisLine.setDirty(false);
2957  }
2958  }
2959 
2960  paint.translate(0, h);
2961  sy += h;
2962  }
2963 }
2964 
2965 void KateViewInternal::resizeEvent(QResizeEvent* e)
2966 {
2967  bool expandedHorizontally = width() > e->oldSize().width();
2968  bool expandedVertically = height() > e->oldSize().height();
2969  bool heightChanged = height() != e->oldSize().height();
2970 
2971  m_dummy->setFixedSize(m_lineScroll->width(), m_columnScroll->sizeHint().height());
2972  m_madeVisible = false;
2973 
2974  if (heightChanged) {
2975  setAutoCenterLines(m_autoCenterLines, false);
2976  m_cachedMaxStartPos.setPosition(-1, -1);
2977  }
2978 
2979  if (m_view->dynWordWrap()) {
2980  bool dirtied = false;
2981 
2982  for (int i = 0; i < cache()->viewCacheLineCount(); i++) {
2983  // find the first dirty line
2984  // the word wrap updateView algorithm is forced to check all lines after a dirty one
2985  KateTextLayout viewLine = cache()->viewLine(i);
2986 
2987  if (viewLine.wrap() || viewLine.isRightToLeft() || viewLine.width() > width()) {
2988  dirtied = true;
2989  viewLine.setDirty();
2990  break;
2991  }
2992  }
2993 
2994  if (dirtied || heightChanged) {
2995  updateView(true);
2996  m_leftBorder->update();
2997  }
2998  } else {
2999  updateView();
3000 
3001  if (expandedHorizontally && startX() > 0)
3002  scrollColumns(startX() - (width() - e->oldSize().width()));
3003  }
3004 
3005  if (width() < e->oldSize().width() && !m_view->wrapCursor()) {
3006  // May have to restrain cursor to new smaller width...
3007  if (m_cursor.column() > doc()->lineLength(m_cursor.line())) {
3008  KateTextLayout thisLine = currentLayout();
3009 
3010  KTextEditor::Cursor newCursor(m_cursor.line(), thisLine.endCol() + ((width() - thisLine.xOffset() - (thisLine.width()- m_startX)) / renderer()->spaceWidth()) - 1);
3011  if (newCursor.column() < m_cursor.column())
3012  updateCursor(newCursor);
3013  }
3014  }
3015 
3016 
3017  if (expandedVertically) {
3018  KTextEditor::Cursor max = maxStartPos();
3019  if (startPos() > max)
3020  scrollPos(max);
3021  }
3022  emit m_view->displayRangeChanged(m_view);
3023 }
3024 
3025 void KateViewInternal::scrollTimeout ()
3026 {
3027  if (m_scrollX || m_scrollY)
3028  {
3029  scrollLines (startPos().line() + (m_scrollY / (int) renderer()->lineHeight()));
3030  placeCursor( QPoint( m_mouseX, m_mouseY ), true );
3031  }
3032 }
3033 
3034 void KateViewInternal::cursorTimeout ()
3035 {
3036  if (!debugPainting && !m_view->viInputMode()) {
3037  renderer()->setDrawCaret(!renderer()->drawCaret());
3038  paintCursor();
3039  }
3040 }
3041 
3042 void KateViewInternal::textHintTimeout ()
3043 {
3044  m_textHintTimer.stop ();
3045 
3046  KTextEditor::Cursor c = coordinatesToCursor(m_textHintPos, false);
3047  if (!c.isValid()) return;
3048 
3049  QString tmp;
3050 
3051  emit m_view->needTextHint(c, tmp);
3052 
3053  if (!tmp.isEmpty()) {
3054  kDebug(13030) << "Hint text: " << tmp;
3055  QPoint pos(startX() + m_textHintPos.x(), m_textHintPos.y());
3056  QToolTip::showText(mapToGlobal(pos), tmp);
3057  }
3058 }
3059 
3060 void KateViewInternal::focusInEvent (QFocusEvent *)
3061 {
3062  if (KApplication::cursorFlashTime() > 0)
3063  m_cursorTimer.start ( KApplication::cursorFlashTime() / 2 );
3064 
3065  paintCursor();
3066 
3067  doc()->setActiveView( m_view );
3068 
3069  // this will handle focus stuff in kateview
3070  m_view->slotGotFocus ();
3071 }
3072 
3073 void KateViewInternal::focusOutEvent (QFocusEvent *)
3074 {
3075  //if (m_view->isCompletionActive())
3076  //m_view->abortCompletion();
3077 
3078  m_cursorTimer.stop();
3079  m_view->renderer()->setDrawCaret(true);
3080  paintCursor();
3081 
3082  m_textHintTimer.stop();
3083 
3084  m_view->slotLostFocus ();
3085 }
3086 
3087 void KateViewInternal::doDrag()
3088 {
3089  m_dragInfo.state = diDragging;
3090  m_dragInfo.dragObject = new QDrag(this);
3091  QMimeData *mimeData=new QMimeData();
3092  mimeData->setText(m_view->selectionText());
3093  m_dragInfo.dragObject->setMimeData(mimeData);
3094  m_dragInfo.dragObject->start(Qt::MoveAction);
3095 }
3096 
3097 void KateViewInternal::dragEnterEvent( QDragEnterEvent* event )
3098 {
3099  if (event->source()==this) event->setDropAction(Qt::MoveAction);
3100  event->setAccepted( (event->mimeData()->hasText() && doc()->isReadWrite()) ||
3101  KUrl::List::canDecode(event->mimeData()) );
3102 }
3103 
3104 void KateViewInternal::fixDropEvent(QDropEvent* event) {
3105  if (event->source()!=this) event->setDropAction(Qt::CopyAction);
3106  else {
3107  Qt::DropAction action=Qt::MoveAction;
3108 #ifdef Q_WS_MAC
3109  if(event->keyboardModifiers() & Qt::AltModifier)
3110  action = Qt::CopyAction;
3111 #else
3112  if (event->keyboardModifiers() & Qt::ControlModifier)
3113  action = Qt::CopyAction;
3114 #endif
3115  event->setDropAction(action);
3116  }
3117 }
3118 
3119 void KateViewInternal::dragMoveEvent( QDragMoveEvent* event )
3120 {
3121  // track the cursor to the current drop location
3122  placeCursor( event->pos(), true, false );
3123 
3124  // important: accept action to switch between copy and move mode
3125  // without this, the text will always be copied.
3126  fixDropEvent(event);
3127 }
3128 
3129 void KateViewInternal::dropEvent( QDropEvent* event )
3130 {
3131  if ( KUrl::List::canDecode(event->mimeData()) ) {
3132 
3133  emit dropEventPass(event);
3134 
3135  } else if ( event->mimeData()->hasText() && doc()->isReadWrite() ) {
3136 
3137  QString text=event->mimeData()->text();
3138 
3139  // is the source our own document?
3140  bool priv = false;
3141  if (KateViewInternal* vi = qobject_cast<KateViewInternal*>(event->source()))
3142  priv = doc()->ownedView( vi->m_view );
3143 
3144  // dropped on a text selection area?
3145  bool selected = m_view->cursorSelected(m_cursor);
3146 
3147  fixDropEvent(event);
3148 
3149  if( priv && selected && event->dropAction() != Qt::CopyAction ) {
3150  // this is a drag that we started and dropped on our selection
3151  // ignore this case
3152  return;
3153  }
3154 
3155  // fix the cursor position before editStart(), so that it is correctly
3156  // stored for the undo action
3157  KTextEditor::Cursor targetCursor(m_cursor); // backup current cursor
3158  int selectionWidth = m_view->selectionRange().columnWidth(); // for block selection
3159  int selectionHeight = m_view->selectionRange().numberOfLines(); // for block selection
3160 
3161  if ( event->dropAction() != Qt::CopyAction ) {
3162  editSetCursor(m_view->selectionRange().end());
3163  } else {
3164  m_view->clearSelection();
3165  }
3166 
3167  // use one transaction
3168  doc()->editStart ();
3169 
3170  // on move: remove selected text; on copy: duplicate text
3171  doc()->insertText(targetCursor, text, m_view->blockSelection());
3172 
3173  Kate::TextCursor startCursor(doc()->buffer(), targetCursor, KTextEditor::MovingCursor::MoveOnInsert);
3174 
3175  if ( event->dropAction() != Qt::CopyAction )
3176  m_view->removeSelectedText();
3177 
3178  Kate::TextCursor endCursor1(doc()->buffer(), startCursor, KTextEditor::MovingCursor::MoveOnInsert);
3179 
3180  if ( !m_view->blockSelection() ) {
3181  endCursor1.move(text.length());
3182  } else {
3183  endCursor1.setColumn(startCursor.column()+selectionWidth);
3184  endCursor1.setLine(startCursor.line()+selectionHeight);
3185  }
3186 
3187  KTextEditor::Cursor endCursor(endCursor1);
3188  kDebug( 13030 )<<startCursor<<"---("<<text.length()<<")---"<<endCursor;
3189  setSelection(KTextEditor::Range(startCursor,endCursor));
3190  editSetCursor(endCursor);
3191 
3192  doc()->editEnd ();
3193 
3194  event->acceptProposedAction();
3195  updateView();
3196  }
3197 
3198  // finally finish drag and drop mode
3199  m_dragInfo.state = diNone;
3200  // important, because the eventFilter`s DragLeave does not occur
3201  stopDragScroll();
3202 }
3203 //END EVENT HANDLING STUFF
3204 
3205 void KateViewInternal::clear()
3206 {
3207  m_startPos.setPosition (0, 0);
3208  m_displayCursor = KTextEditor::Cursor(0, 0);
3209  m_cursor.setPosition(0, 0);
3210  cache()->clear();
3211  updateView(true);
3212 }
3213 
3214 void KateViewInternal::wheelEvent(QWheelEvent* e)
3215 {
3216  // zoom text, if ctrl is pressed
3217  if (e->modifiers() == Qt::ControlModifier) {
3218  if (e->delta() > 0) {
3219  slotIncFontSizes();
3220  } else {
3221  slotDecFontSizes();
3222  }
3223  e->accept();
3224  return;
3225  }
3226 
3227  // scroll up/down or left/right, if possible
3228  if (m_lineScroll->minimum() != m_lineScroll->maximum() && e->orientation() != Qt::Horizontal) {
3229  // React to this as a vertical event
3230  if ( e->modifiers() & Qt::ShiftModifier ) {
3231  if (e->delta() > 0)
3232  scrollPrevPage();
3233  else
3234  scrollNextPage();
3235  } else {
3236  const int scrollLines = QApplication::wheelScrollLines();
3237  scrollViewLines(e->delta() > 0 ? -scrollLines : scrollLines);
3238  e->accept();
3239  return;
3240  }
3241 
3242  } else if (columnScrollingPossible()) {
3243  QWheelEvent copy = *e;
3244  QApplication::sendEvent(m_columnScroll, &copy);
3245 
3246  } else {
3247  e->ignore();
3248  }
3249 }
3250 
3251 void KateViewInternal::startDragScroll()
3252 {
3253  if ( !m_dragScrollTimer.isActive() ) {
3254  m_dragScrollTimer.start( s_scrollTime );
3255  }
3256 }
3257 
3258 void KateViewInternal::stopDragScroll()
3259 {
3260  m_dragScrollTimer.stop();
3261  updateView();
3262 }
3263 
3264 void KateViewInternal::doDragScroll()
3265 {
3266  QPoint p = this->mapFromGlobal( QCursor::pos() );
3267 
3268  int dx = 0, dy = 0;
3269  if ( p.y() < s_scrollMargin ) {
3270  dy = p.y() - s_scrollMargin;
3271  } else if ( p.y() > height() - s_scrollMargin ) {
3272  dy = s_scrollMargin - (height() - p.y());
3273  }
3274 
3275  if ( p.x() < s_scrollMargin ) {
3276  dx = p.x() - s_scrollMargin;
3277  } else if ( p.x() > width() - s_scrollMargin ) {
3278  dx = s_scrollMargin - (width() - p.x());
3279  }
3280 
3281  dy /= 4;
3282 
3283  if (dy)
3284  scrollLines(startPos().line() + dy);
3285 
3286  if (columnScrollingPossible () && dx)
3287  scrollColumns(qMin (m_startX + dx, m_columnScroll->maximum()));
3288 
3289  if (!dy && !dx)
3290  stopDragScroll();
3291 }
3292 
3293 void KateViewInternal::enableTextHints(int timeout)
3294 {
3295  if (timeout >= 0) {
3296  m_textHintTimeout = timeout;
3297  m_textHintEnabled = true;
3298  m_textHintTimer.start(timeout);
3299  } else {
3300  kWarning() << "Attempt to enable text hints with negative timeout:" << timeout;
3301  }
3302 }
3303 
3304 void KateViewInternal::disableTextHints()
3305 {
3306  if (m_textHintEnabled) {
3307  m_textHintEnabled = false;
3308  m_textHintTimer.stop ();
3309  }
3310 }
3311 
3312 //BEGIN EDIT STUFF
3313 void KateViewInternal::editStart()
3314 {
3315  editSessionNumber++;
3316 
3317  if (editSessionNumber > 1)
3318  return;
3319 
3320  editIsRunning = true;
3321  editOldCursor = m_cursor;
3322  editOldSelection = m_view->selectionRange();
3323 }
3324 
3325 void KateViewInternal::editEnd(int editTagLineStart, int editTagLineEnd, bool tagFrom)
3326 {
3327  if (editSessionNumber == 0)
3328  return;
3329 
3330  editSessionNumber--;
3331 
3332  if (editSessionNumber > 0)
3333  return;
3334 
3335  // fix start position, might have moved from column 0
3336  // try to clever calculate the right start column for the tricky dyn word wrap case
3337  int col = 0;
3338  if (m_view->dynWordWrap()) {
3339  if (KateLineLayoutPtr layout = cache()->line(m_startPos.line())) {
3340  int index = layout->viewLineForColumn (m_startPos.column());
3341  if (index >= 0 && index < layout->viewLineCount())
3342  col = layout->viewLine (index).startCol();
3343  }
3344  }
3345  m_startPos.setPosition (m_startPos.line(), col);
3346 
3347  if (tagFrom && (editTagLineStart <= int(m_view->textFolding().visibleLineToLine(startLine()))))
3348  tagAll();
3349  else
3350  tagLines (editTagLineStart, tagFrom ? qMax(doc()->lastLine() + 1, editTagLineEnd) : editTagLineEnd, true);
3351 
3352  if (editOldCursor == m_cursor.toCursor())
3353  updateBracketMarks();
3354 
3355  updateView(true);
3356 
3357  if (editOldCursor != m_cursor.toCursor() || m_view == doc()->activeView())
3358  {
3359  // Only scroll the view to the cursor if the insertion happens at the cursor.
3360  // This might not be the case for e.g. collaborative editing, when a remote user
3361  // inserts text at a position not at the caret.
3362  if ( m_cursor.line() >= editTagLineStart && m_cursor.line() <= editTagLineEnd ) {
3363  m_madeVisible = false;
3364  updateCursor ( m_cursor, true );
3365  }
3366  }
3367 
3372  if (editOldSelection != m_view->selectionRange()
3373  || (editOldSelection.isValid() && !editOldSelection.isEmpty() && !(editTagLineStart > editOldSelection.end().line() && editTagLineEnd < editOldSelection.start().line())))
3374  emit m_view->selectionChanged (m_view);
3375 
3376  editIsRunning = false;
3377 }
3378 
3379 void KateViewInternal::editSetCursor (const KTextEditor::Cursor &_cursor)
3380 {
3381  if (m_cursor.toCursor() != _cursor)
3382  {
3383  m_cursor.setPosition(_cursor);
3384  }
3385 }
3386 //END
3387 
3388 void KateViewInternal::viewSelectionChanged ()
3389 {
3390  if (!m_view->selection()) {
3391  m_selectAnchor = KTextEditor::Cursor::invalid();
3392  } else {
3393  m_selectAnchor = m_view->selectionRange().start();
3394  }
3395  // Do NOT nuke the entire range! The reason is that a shift+DC selection
3396  // might (correctly) set the range to be empty (i.e. start() == end()), and
3397  // subsequent dragging might shrink the selection into non-existence. When
3398  // this happens, we use the cached end to restore the cached start so that
3399  // updateSelection is not confused. See also comments in updateSelection.
3400  m_selectionCached.start() = KTextEditor::Cursor::invalid();
3401 }
3402 
3403 KateLayoutCache* KateViewInternal::cache( ) const
3404 {
3405  return m_layoutCache;
3406 }
3407 
3408 KTextEditor::Cursor KateViewInternal::toRealCursor( const KTextEditor::Cursor & virtualCursor ) const
3409 {
3410  return KTextEditor::Cursor(m_view->textFolding().visibleLineToLine(virtualCursor.line()), virtualCursor.column());
3411 }
3412 
3413 KTextEditor::Cursor KateViewInternal::toVirtualCursor( const KTextEditor::Cursor & realCursor ) const
3414 {
3419  if (realCursor.line() < 0)
3420  return KTextEditor::Cursor::invalid ();
3421 
3422  return KTextEditor::Cursor(m_view->textFolding().lineToVisibleLine(realCursor.line()), realCursor.column());
3423 }
3424 
3425 KateRenderer * KateViewInternal::renderer( ) const
3426 {
3427  return m_view->renderer();
3428 }
3429 
3430 void KateViewInternal::mouseMoved( )
3431 {
3432  m_view->notifyMousePositionChanged(m_mouse);
3433  m_view->updateRangesIn (KTextEditor::Attribute::ActivateMouseIn);
3434 }
3435 
3436 void KateViewInternal::cursorMoved( )
3437 {
3438  m_view->updateRangesIn (KTextEditor::Attribute::ActivateCaretIn);
3439 #ifndef QT_NO_ACCESSIBILITY
3440 #if QT_VERSION >= 0x040800
3441  QAccessible::updateAccessibility(this, 0, QAccessible::TextCaretMoved);
3442 #endif
3443 #endif
3444 }
3445 
3446 bool KateViewInternal::rangeAffectsView(const KTextEditor::Range& range, bool realCursors) const
3447 {
3448  int startLine = m_startPos.line();
3449  int endLine = startLine + (int)m_visibleLineCount;
3450 
3451  if ( realCursors ) {
3452  startLine = (int)m_view->textFolding().visibleLineToLine(startLine);
3453  endLine = (int)m_view->textFolding().visibleLineToLine(endLine);
3454  }
3455 
3456  return (range.end().line() >= startLine) || (range.start().line() <= endLine);
3457 }
3458 
3459 //BEGIN IM INPUT STUFF
3460 QVariant KateViewInternal::inputMethodQuery ( Qt::InputMethodQuery query ) const
3461 {
3462  switch (query) {
3463  case Qt::ImMicroFocus: {
3464  // Cursor placement code is changed for Asian input method that
3465  // shows candidate window. This behavior is same as Qt/E 2.3.7
3466  // which supports Asian input methods. Asian input methods need
3467  // start point of IM selection text to place candidate window as
3468  // adjacent to the selection text.
3469  return QRect (cursorToCoordinate(m_cursor, true, false), QSize(0, renderer()->lineHeight()));
3470  }
3471 
3472  case Qt::ImFont:
3473  return renderer()->currentFont();
3474 
3475  case Qt::ImCursorPosition:
3476  return m_cursor.column();
3477 
3478  case Qt::ImAnchorPosition:
3479  // If selectAnchor is at the same line, return the real anchor position
3480  // Otherwise return the same position of cursor
3481  if (m_view->selection() && m_selectAnchor.line() == m_cursor.line())
3482  return m_selectAnchor.column();
3483  else
3484  return m_cursor.column();
3485 
3486  case Qt::ImSurroundingText:
3487  if (Kate::TextLine l = doc()->kateTextLine(m_cursor.line()))
3488  return l->string();
3489  else
3490  return QString();
3491 
3492  case Qt::ImCurrentSelection:
3493  if (m_view->selection())
3494  return m_view->selectionText();
3495  else
3496  return QString();
3497  default:
3498  /* values: ImMaximumTextLength */
3499  break;
3500  }
3501 
3502  return QWidget::inputMethodQuery(query);
3503 }
3504 
3505 void KateViewInternal::inputMethodEvent(QInputMethodEvent* e)
3506 {
3507  if ( doc()->readOnly() ) {
3508  e->ignore();
3509  return;
3510  }
3511 
3512  //kDebug( 13030 ) << "Event: cursor" << m_cursor << "commit" << e->commitString() << "preedit" << e->preeditString() << "replacement start" << e->replacementStart() << "length" << e->replacementLength();
3513 
3514  if (!m_imPreeditRange) {
3515  m_imPreeditRange = doc()->newMovingRange (KTextEditor::Range(m_cursor, m_cursor), KTextEditor::MovingRange::ExpandLeft | KTextEditor::MovingRange::ExpandRight);
3516  }
3517 
3518  if (!m_imPreeditRange->toRange().isEmpty()) {
3519  doc()->inputMethodStart();
3520  doc()->removeText(*m_imPreeditRange);
3521  doc()->inputMethodEnd();
3522  }
3523 
3524  if (!e->commitString().isEmpty() || e->replacementLength()) {
3525  m_view->removeSelectedText();
3526 
3527  KTextEditor::Range preeditRange = *m_imPreeditRange;
3528 
3529  KTextEditor::Cursor start(m_imPreeditRange->start().line(), m_imPreeditRange->start().column() + e->replacementStart());
3530  KTextEditor::Cursor removeEnd = start + KTextEditor::Cursor(0, e->replacementLength());
3531 
3532  doc()->editStart();
3533  if (start != removeEnd)
3534  doc()->removeText(KTextEditor::Range(start, removeEnd));
3535  if (!e->commitString().isEmpty()) {
3536  // if the input method event is text that should be inserted, call KateDocument::typeChars()
3537  // with the text. that method will handle the input and take care of overwrite mode, etc.
3538  doc()->typeChars(m_view, e->commitString());
3539  }
3540  doc()->editEnd();
3541 
3542  // Revert to the same range as above
3543  m_imPreeditRange->setRange(preeditRange);
3544  }
3545 
3546  if (!e->preeditString().isEmpty()) {
3547  doc()->inputMethodStart();
3548  doc()->insertText(m_imPreeditRange->start(), e->preeditString());
3549  doc()->inputMethodEnd();
3550  // The preedit range gets automatically repositioned
3551  }
3552 
3553  // Finished this input method context?
3554  if (m_imPreeditRange && e->preeditString().isEmpty()) {
3555  // delete the range and reset the pointer
3556  delete m_imPreeditRange;
3557  m_imPreeditRange = 0L;
3558  qDeleteAll (m_imPreeditRangeChildren);
3559  m_imPreeditRangeChildren.clear ();
3560 
3561  if ( KApplication::cursorFlashTime() > 0 )
3562  renderer()->setDrawCaret(false);
3563  renderer()->setCaretOverrideColor(QColor());
3564 
3565  e->accept();
3566  return;
3567  }
3568 
3569  KTextEditor::Cursor newCursor = m_cursor;
3570  bool hideCursor = false;
3571  QColor caretColor;
3572 
3573  if (m_imPreeditRange) {
3574  qDeleteAll (m_imPreeditRangeChildren);
3575  m_imPreeditRangeChildren.clear ();
3576 
3577  int decorationColumn = 0;
3578  foreach (const QInputMethodEvent::Attribute &a, e->attributes()) {
3579  if (a.type == QInputMethodEvent::Cursor) {
3580  newCursor = m_imPreeditRange->start() + KTextEditor::Cursor(0, a.start);
3581  hideCursor = !a.length;
3582  QColor c = qvariant_cast<QColor>(a.value);
3583  if (c.isValid())
3584  caretColor = c;
3585 
3586  } else if (a.type == QInputMethodEvent::TextFormat) {
3587  QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
3588  if (f.isValid() && decorationColumn <= a.start) {
3589  KTextEditor::Range fr(m_imPreeditRange->start().line(), m_imPreeditRange->start().column() + a.start, m_imPreeditRange->start().line(), m_imPreeditRange->start().column() + a.start + a.length);
3590  KTextEditor::MovingRange* formatRange = doc()->newMovingRange (fr);
3591  KTextEditor::Attribute::Ptr attribute(new KTextEditor::Attribute());
3592  attribute->merge(f);
3593  formatRange->setAttribute(attribute);
3594  decorationColumn = a.start + a.length;
3595  m_imPreeditRangeChildren.push_back (formatRange);
3596  }
3597  }
3598  }
3599  }
3600 
3601  renderer()->setDrawCaret(hideCursor);
3602  renderer()->setCaretOverrideColor(caretColor);
3603 
3604  if (newCursor != m_cursor.toCursor())
3605  updateCursor(newCursor);
3606 
3607  e->accept();
3608 }
3609 
3610 //END IM INPUT STUFF
3611 
3612 ViMode KateViewInternal::getCurrentViMode()
3613 {
3614  return getViInputModeManager()->getCurrentViMode();
3615 }
3616 
3617 KateViInputModeManager* KateViewInternal::getViInputModeManager()
3618 {
3619  if (!m_viInputModeManager) {
3620  m_viInputModeManager = new KateViInputModeManager(m_view, this);
3621  }
3622 
3623  return m_viInputModeManager;
3624 }
3625 
3626 KateViInputModeManager* KateViewInternal::resetViInputModeManager()
3627 {
3628  if (m_viInputModeManager) {
3629  delete m_viInputModeManager;
3630  }
3631  m_viInputModeManager = new KateViInputModeManager(m_view, this);
3632 
3633  return m_viInputModeManager;
3634 }
3635 
3636 // kate: space-indent on; indent-width 2; replace-tabs on;
KateViewInternal::editEnd
void editEnd(int editTagLineStart, int editTagLineEnd, bool tagFrom)
Definition: kateviewinternal.cpp:3325
QVariant
KTextEditor::View::horizontalScrollPositionChanged
void horizontalScrollPositionChanged(KTextEditor::View *view)
KateDocument::line
virtual QString line(int line) const
Definition: katedocument.cpp:447
KateViewInternal::cursorPrevChar
void cursorPrevChar(bool sel=false)
Definition: kateviewinternal.cpp:1061
KTextEditor::Cursor::operator-=
friend friend Cursor & operator-=(Cursor &c1, const Cursor &c2)
QColor
KateLineLayout::line
int line() const
Definition: katelinelayout.cpp:75
InsertMode
Definition: kateviinputmodemanager.h:50
KTextEditor::Range::start
Cursor & start()
KateDocument::config
KateDocumentConfig * config()
Configuration.
Definition: katedocument.h:1009
KateRenderer::cursorToX
int cursorToX(const KateTextLayout &range, int col, bool returnPastLine=false) const
Returns the x position of cursor col on the line range.
Definition: katerenderer.cpp:1048
KateViewInternal::resizeEvent
virtual void resizeEvent(QResizeEvent *)
Definition: kateviewinternal.cpp:2965
KateRendererConfig::showWholeBracketExpression
bool showWholeBracketExpression() const
Definition: kateconfig.cpp:2602
KSharedPtr< KateLineLayout >
KTextEditor::Cursor::atStartOfDocument
bool atStartOfDocument() const
KateViewInternal::doReturn
void doReturn()
Definition: kateviewinternal.cpp:765
qint64
KateViewInternal::doBackspace
void doBackspace()
Definition: kateviewinternal.cpp:796
katehighlight.h
KateViewInternal::dragEnterEvent
virtual void dragEnterEvent(QDragEnterEvent *)
Definition: kateviewinternal.cpp:3097
KateDocument::ignoreModifiedOnDiskOnce
void ignoreModifiedOnDiskOnce()
Definition: katedocument.cpp:4697
kateview.h
KTextEditor::Cursor::invalid
static Cursor invalid()
KateTextLayout::startCol
int startCol() const
Definition: katetextlayout.cpp:127
KateRenderer::Block
Definition: katerenderer.h:71
QTextCharFormat
KateIconBorder::updateFont
void updateFont()
Definition: kateviewhelpers.cpp:1396
KateLineLayout::viewLine
KateTextLayout viewLine(int viewLine) const
Definition: katelinelayout.cpp:177
KateRendererConfig::highlightedBracketColor
const QColor & highlightedBracketColor() const
Definition: kateconfig.cpp:2275
KateRenderer::currentFont
const QFont & currentFont() const
Definition: katerenderer.cpp:805
KateView::clearSelection
bool clearSelection()
Definition: kateview.cpp:1966
KateViewInternal::KateViewInternal
KateViewInternal(KateView *view)
Definition: kateviewinternal.cpp:61
KateDocument::newMovingRange
virtual KTextEditor::MovingRange * newMovingRange(const KTextEditor::Range &range, KTextEditor::MovingRange::InsertBehaviors insertBehaviors=KTextEditor::MovingRange::DoNotExpand, KTextEditor::MovingRange::EmptyBehavior emptyBehavior=KTextEditor::MovingRange::AllowEmpty)
Create a new moving range for this document.
Definition: katedocument.cpp:4742
KateViewInternal::startPos
KTextEditor::Cursor startPos() const
Definition: kateviewinternal.h:124
KTextEditor::View::verticalScrollPositionChanged
void verticalScrollPositionChanged(KTextEditor::View *view, const KTextEditor::Cursor &newPos)
KateView::selectWord
void selectWord(const KTextEditor::Cursor &cursor)
Definition: kateview.cpp:2129
KTextEditor::MovingCursor::column
virtual int column() const =0
KateViewInternal::focusInEvent
virtual void focusInEvent(QFocusEvent *)
Definition: kateviewinternal.cpp:3060
kdebug.h
KateLineLayout::layout
QTextLayout * layout() const
Definition: katelinelayout.cpp:125
KateViewInternal::topOfView
void topOfView(bool sel=false)
Definition: kateviewinternal.cpp:1466
KateView::renderer
KateRenderer * renderer()
Definition: kateview.cpp:1653
KateViewInternal::tagRange
bool tagRange(const KTextEditor::Range &range, bool realCursors)
Definition: kateviewinternal.cpp:2051
KateRenderer::spaceWidth
qreal spaceWidth() const
Definition: katerenderer.cpp:907
KateView::isCompletionActive
virtual bool isCompletionActive() const
Definition: kateview.cpp:2316
katerenderer.h
KTextEditor::Attribute::ActivateMouseIn
KateTextLayout::line
int line() const
Definition: katetextlayout.cpp:93
KTextEditor::Attribute
kapplication.h
KateView::bottomViewBar
KateViewBar * bottomViewBar() const
Definition: kateview.cpp:2936
KateViewInternal::mouseDoubleClickEvent
virtual void mouseDoubleClickEvent(QMouseEvent *)
Definition: kateviewinternal.cpp:2586
KateViewInternal::slotDecFontSizes
void slotDecFontSizes()
Definition: kateviewinternal.cpp:331
KateCompletionWidget::pageDown
void pageDown()
Definition: katecompletionwidget.cpp:1093
KateDocument::highlight
KateHighlighting * highlight() const
Definition: katedocument.cpp:4702
kateviewaccessible.h
KTextEditor::Range::isValid
virtual bool isValid() const
Kate::TextCursor::column
int column() const
Retrieve the column on which this cursor is situated.
Definition: katetextcursor.h:141
KateView::dynWordWrap
bool dynWordWrap() const
Definition: kateview.h:245
kglobalsettings.h
KateRenderer::setCaretOverrideColor
void setCaretOverrideColor(const QColor &color)
Set a brush with which to override drawing of the caret.
Definition: katerenderer.cpp:1083
KateDocument::activeView
virtual KTextEditor::View * activeView() const
Definition: katedocument.h:156
KateDocument::transpose
void transpose(const KTextEditor::Cursor &)
Definition: katedocument.cpp:2694
KateDocumentConfig::tabIndents
Definition: kateconfig.h:196
timeout
int timeout
KateViewInternal::keyPressEvent
virtual void keyPressEvent(QKeyEvent *)
Definition: kateviewinternal.cpp:2232
KateViewInternal::bottomOfView
void bottomOfView(bool sel=false)
Definition: kateviewinternal.cpp:1473
KateDocument::lineLength
virtual int lineLength(int line) const
Definition: katedocument.cpp:758
KateViewInternal::dropEvent
virtual void dropEvent(QDropEvent *)
Definition: kateviewinternal.cpp:3129
KateViewInternal::clear
void clear()
Definition: kateviewinternal.cpp:3205
KateViewInternal::top_home
void top_home(bool sel=false)
Definition: kateviewinternal.cpp:1642
KateViewInternal::editSetCursor
void editSetCursor(const KTextEditor::Cursor &cursor)
Definition: kateviewinternal.cpp:3379
KateCompletionWidget::cursorDown
void cursorDown()
Definition: katecompletionwidget.cpp:1063
Kate::TextFolding::visibleLineToLine
int visibleLineToLine(int visibleLine) const
Convert a visible line number to a line number in the text buffer.
Definition: katetextfolding.cpp:422
QWidget
KateTextLayout::isValid
bool isValid() const
Definition: katetextlayout.cpp:88
KateViewInternal::inputMethodQuery
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const
IM input stuff.
Definition: kateviewinternal.cpp:3460
KateViewInternal::pageUp
void pageUp(bool sel=false, bool half=false)
Definition: kateviewinternal.cpp:1513
KateViewInternal::cursorToCoordinate
QPoint cursorToCoordinate(const KTextEditor::Cursor &cursor, bool realCursor=true, bool includeBorder=true) const
Definition: kateviewinternal.cpp:712
ReplaceMode
Definition: kateviinputmodemanager.h:54
KateViewInternal::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *)
Definition: kateviewinternal.cpp:2681
KateLayoutCache::textLayout
KateTextLayout textLayout(const KTextEditor::Cursor &realCursor)
Returns the layout describing the text line which is occupied by realCursor.
Definition: katelayoutcache.cpp:337
KateViInputModeManager
Definition: kateviinputmodemanager.h:68
movingrange.h
KateTextLayout::start
KTextEditor::Cursor start() const
Definition: katetextlayout.cpp:135
KateViewInternal::KateIconBorder
friend class KateIconBorder
Definition: kateviewinternal.h:62
KateView::emitNavigateUp
void emitNavigateUp()
Definition: kateview.h:372
KateRenderer::increaseFontSizes
void increaseFontSizes()
Change to a different font (soon to be font set?)
Definition: katerenderer.cpp:140
KateView::contextMenu
QMenu * contextMenu() const
Definition: kateview.cpp:2789
KateDocument::inputMethodEnd
void inputMethodEnd()
Definition: katedocument.cpp:850
KTextEditor::MovingRange::toRange
const Range toRange() const
KateViewInternal::hideEvent
virtual void hideEvent(QHideEvent *e)
Definition: kateviewinternal.cpp:2876
KTextEditor::MovingRange
KateViewInternal::wordNext
void wordNext(bool sel=false)
Definition: kateviewinternal.cpp:1117
QString
KateViewInternal::focusOutEvent
virtual void focusOutEvent(QFocusEvent *)
Definition: kateviewinternal.cpp:3073
KateLayoutCache::clear
void clear()
Definition: katelayoutcache.cpp:513
KateCompletionWidget::resetHadNavigation
void resetHadNavigation()
Definition: katecompletionwidget.cpp:969
KateViewInternal::scrollDown
void scrollDown()
Definition: kateviewinternal.cpp:1499
KUrl::List::canDecode
static bool canDecode(const QMimeData *mimeData)
KateViewInternal::none
Definition: kateviewinternal.h:73
KateView::textFolding
Kate::TextFolding & textFolding()
Folding handler for this view.
Definition: kateview.h:574
KateViewInternal::doSmartNewline
void doSmartNewline()
Definition: kateviewinternal.cpp:771
QObject
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KTextEditor::Cursor
k_funcinfo
#define k_funcinfo
KateTextLayout::setDirty
bool setDirty(bool dirty=true)
Definition: katetextlayout.cpp:42
KateDocument::indent
void indent(KTextEditor::Range range, int change)
Definition: katedocument.cpp:2898
KateView::needTextHint
void needTextHint(const KTextEditor::Cursor &position, QString &text)
KateDocument::backspace
void backspace(KateView *view, const KTextEditor::Cursor &)
Definition: katedocument.cpp:2725
KateTextLayout::endCol
int endCol(bool indicateEOL=false) const
Return the end column of this text line.
Definition: katetextlayout.cpp:140
KateRenderer::xToCursor
KTextEditor::Cursor xToCursor(const KateTextLayout &range, int x, bool returnPastLine=false) const
Returns the real cursor which is occupied by the specified x value, or that closest to it...
Definition: katerenderer.cpp:1071
KateViewInternal::doDeletePrevWord
void doDeletePrevWord()
Definition: kateviewinternal.cpp:811
KateViewInternal::Bias
Bias
Definition: kateviewinternal.h:70
KateView::cursorSelected
bool cursorSelected(const KTextEditor::Cursor &cursor)
Definition: kateview.cpp:2058
config
KSharedConfigPtr config()
KateViewInternal::top
void top(bool sel=false)
Definition: kateviewinternal.cpp:1622
kateviewhelpers.h
Kate::TextCursor::setPosition
void setPosition(const TextCursor &position)
Fast way to set the current cursor position to position.
Definition: katetextcursor.cpp:64
KTextEditor::MovingRange::setAttributeOnlyForViews
virtual void setAttributeOnlyForViews(bool onlyForViews)=0
katebuffer.h
KateViewInternal::startX
int startX() const
Definition: kateviewinternal.h:126
KateDocument::lastLine
int lastLine() const
gets the last line number (lines() - 1)
Definition: katedocument.h:691
debugPainting
static const bool debugPainting
Definition: kateviewinternal.cpp:59
KateViewInternal::tagLines
bool tagLines(int start, int end, bool realLines=false)
Definition: kateviewinternal.cpp:1965
KateRenderer::setShowTrailingSpaces
void setShowTrailingSpaces(bool showSpaces)
Set whether a mark should be painted for trailing spaces.
Definition: katerenderer.cpp:110
KateViewInternal::doDeleteNextWord
void doDeleteNextWord()
Definition: kateviewinternal.cpp:822
KateViewInternal::slotIncFontSizes
void slotIncFontSizes()
Definition: kateviewinternal.cpp:325
KTextEditor::Range::columnWidth
int columnWidth() const
KTextEditor::MovingCursor::setColumn
void setColumn(int column)
KateViewInternal::yToKateTextLayout
KateTextLayout yToKateTextLayout(int y) const
Definition: kateviewinternal.cpp:306
KateLayoutCache::setAcceptDirtyLayouts
void setAcceptDirtyLayouts(bool accept)
Definition: katelayoutcache.cpp:561
KateView::selectionRange
virtual const KTextEditor::Range & selectionRange() const
Definition: kateview.cpp:2760
operator++
KIconLoader::Group & operator++(KIconLoader::Group &group)
kateviinputmodemanager.h
kcursor.h
KateViewInternal::cursorToMatchingBracket
void cursorToMatchingBracket(bool sel=false)
Definition: kateviewinternal.cpp:1456
KateDocument::setActiveView
void setActiveView(KTextEditor::View *)
Definition: katedocument.cpp:2551
KateViewInternal::bottom
void bottom(bool sel=false)
Definition: kateviewinternal.cpp:1632
KateRenderer
Handles all of the work of rendering the text (used for the views and printing)
Definition: katerenderer.h:50
KateView::displayRangeChanged
void displayRangeChanged(KateView *view)
KateView::completionWidget
KateCompletionWidget * completionWidget() const
Definition: kateview.cpp:2321
KateDocument::insertText
virtual bool insertText(const KTextEditor::Cursor &position, const QString &s, bool block=false)
Definition: katedocument.cpp:530
KateTextLayout::xOffset
int xOffset() const
Definition: katetextlayout.cpp:55
KateLineLayout::isValid
bool isValid() const
Definition: katelinelayout.cpp:120
KateViewInternal::BoundedCursor
friend class BoundedCursor
Definition: kateviewinternal.h:65
KateRenderer::setShowTabs
void setShowTabs(bool showTabs)
Set whether a mark should be painted to help identifying tabs.
Definition: katerenderer.cpp:105
QScrollBar
KateCompletionWidget::toggleExpanded
bool toggleExpanded(bool forceExpand=false, bool forceUnExpand=false)
Returns whether the current item was expanded/unexpanded.
Definition: katecompletionwidget.cpp:981
KTextEditor::MovingRange::ExpandLeft
KateTextLayout::isRightToLeft
bool isRightToLeft() const
Definition: katetextlayout.cpp:215
KateView::contextMenuEvent
void contextMenuEvent(QContextMenuEvent *)
Definition: kateview.cpp:1268
KateViewInternal::cursorNextChar
void cursorNextChar(bool sel=false)
Definition: kateviewinternal.cpp:1069
KateViewInternal::mousePressEvent
virtual void mousePressEvent(QMouseEvent *)
Definition: kateviewinternal.cpp:2462
KateDocument::newBracketMark
void newBracketMark(const KTextEditor::Cursor &start, KTextEditor::Range &bm, int maxLines=-1)
Definition: katedocument.cpp:3572
KTextEditor::Cursor::isValid
virtual bool isValid() const
KateTextLayout::viewLine
int viewLine() const
Return the index of this visual line inside the document line (KateLineLayout).
Definition: katetextlayout.cpp:109
KateRenderer::config
KateRendererConfig * config() const
Configuration.
Definition: katerenderer.h:362
KateView::setSelection
virtual bool setSelection(const KTextEditor::Range &selection)
Definition: kateview.cpp:1931
KateViewInternal::cursorUp
void cursorUp(bool sel=false)
Definition: kateviewinternal.cpp:1402
KateRenderer::decreaseFontSizes
void decreaseFontSizes()
Definition: katerenderer.cpp:148
KateLayoutCache::lastViewLine
int lastViewLine(int realLine)
Definition: katelayoutcache.cpp:462
katelayoutcache.h
KTextEditor::Attribute::Ptr
KSharedPtr< Attribute > Ptr
KateViewInternal::left
Definition: kateviewinternal.h:72
KateCompletionWidget::bottom
void bottom()
Definition: katecompletionwidget.cpp:1136
KateViewInternal::tagAll
void tagAll()
Definition: kateviewinternal.cpp:2056
KateViewInternal::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *)
Definition: kateviewinternal.cpp:2752
KateDocumentConfig::tabInsertsTab
Definition: kateconfig.h:195
KateLayoutCache::line
KateLineLayoutPtr line(int realLine, int virtualLine=-1)
Returns the KateLineLayout for the specified line.
Definition: katelayoutcache.cpp:280
KateViewInternal
Definition: kateviewinternal.h:57
KateViewInternal::keyReleaseEvent
virtual void keyReleaseEvent(QKeyEvent *)
Definition: kateviewinternal.cpp:2402
KTextEditor::Range::invalid
static Range invalid()
Kate::TextFolding::foldingRange
KTextEditor::Range foldingRange(qint64 id) const
Returns the folding range associated with id.
Definition: katetextfolding.cpp:159
KateDocument::lines
virtual int lines() const
Definition: katedocument.cpp:753
KParts::ReadWritePart::isReadWrite
bool isReadWrite() const
Kate::TextCursor::line
int line() const
Retrieve the line on which this cursor is situated.
Definition: katetextcursor.cpp:132
KateCompletionWidget::top
void top()
Definition: katecompletionwidget.cpp:1123
KateCompletionWidget::cursorUp
void cursorUp()
Definition: katecompletionwidget.cpp:1078
KateViewConfig::persistentSelection
bool persistentSelection() const
Definition: kateconfig.cpp:1669
KTextEditor::MovingRange::isEmpty
bool isEmpty() const
katecompletionwidget.h
KateViewInternal::setCaretStyle
void setCaretStyle(KateRenderer::caretStyles style, bool repaint=false)
Set the caret's style.
Definition: kateviewinternal.cpp:1804
kateviewinternal.h
KateView::emitNavigateDown
void emitNavigateDown()
Definition: kateview.h:375
katesearchbar.h
KateTextLayout::kateLineLayout
KateLineLayoutPtr kateLineLayout() const
Definition: katetextlayout.cpp:122
KTextEditor::MovingRange::setAttribute
virtual void setAttribute(Attribute::Ptr attribute)=0
KateViewInternal::end
void end(bool sel=false)
Definition: kateviewinternal.cpp:1201
KateView::blockSelection
virtual bool blockSelection() const
Definition: kateview.cpp:2196
KTextEditor::Cursor::operator+=
friend friend Cursor & operator+=(Cursor &c1, const Cursor &c2)
ViMode
ViMode
The four vi modes supported by Kate's vi input mode.
Definition: kateviinputmodemanager.h:48
KTextEditor::Range::boundaryAtCursor
bool boundaryAtCursor(const Cursor &cursor) const
KateDocument::newLine
void newLine(KateView *view)
Definition: katedocument.cpp:2659
KateViewInternal::editStart
void editStart()
Definition: kateviewinternal.cpp:3313
KateRenderer::Line
Definition: katerenderer.h:70
KateViewInternal::paintEvent
virtual void paintEvent(QPaintEvent *e)
Definition: kateviewinternal.cpp:2883
KateView::emitNavigateAccept
void emitNavigateAccept()
Definition: kateview.h:378
KateView::updateRangesIn
void updateRangesIn(KTextEditor::Attribute::ActivationType activationType)
check if ranges changed for mouse in and caret in
Definition: kateview.cpp:3107
KTextEditor::MovingRange::setRange
virtual void setRange(const KTextEditor::Range &range)=0
KateViewInternal::doTabulator
void doTabulator()
Definition: kateviewinternal.cpp:801
KateViewInternal::doDelete
void doDelete()
Definition: kateviewinternal.cpp:791
KateLayoutCache
This class handles Kate's caching of layouting information (in KateLineLayout and KateTextLayout)...
Definition: katelayoutcache.h:77
KTextEditor::Attribute::ActivateCaretIn
KateView::selection
virtual bool selection() const
Definition: kateview.cpp:2008
KateLineLayout::viewLineCount
int viewLineCount() const
Definition: katelinelayout.cpp:172
KTextEditor::View::cursorPositionChanged
void cursorPositionChanged(KTextEditor::View *view, const KTextEditor::Cursor &newPosition)
KateLayoutCache::viewLine
KateTextLayout & viewLine(int viewLine)
Returns the layout of the corresponding line in the view.
Definition: katelayoutcache.cpp:358
KateDocument::typeChars
bool typeChars(KateView *type, const QString &realChars)
Type chars in a view.
Definition: katedocument.cpp:2594
KateView
Definition: kateview.h:78
KTextEditor::MovingCursor::toCursor
const Cursor toCursor() const
KTextEditor::Range
KateView::spellingMenu
KateSpellingMenu * spellingMenu()
Definition: kateview.cpp:3040
Kate::TextFolding::lineToVisibleLine
int lineToVisibleLine(int line) const
Convert a text buffer line to a visible line number.
Definition: katetextfolding.cpp:366
KateViewInternal::updateDirty
void updateDirty()
Definition: kateviewinternal.cpp:2839
KTextEditor::Range::onSingleLine
bool onSingleLine() const
KateDocument
Definition: katedocument.h:74
KTextEditor::MovingRange::setView
virtual void setView(View *view)=0
KateView::selectLine
void selectLine(const KTextEditor::Cursor &cursor)
Definition: kateview.cpp:2149
KateViewInternal::dropEventPass
void dropEventPass(QDropEvent *)
KateLayoutCache::setViewWidth
void setViewWidth(int width)
Definition: katelayoutcache.cpp:520
KateViewInternal::doTranspose
void doTranspose()
Definition: kateviewinternal.cpp:806
KateViewInternal::right
Definition: kateviewinternal.h:74
KTextEditor::MovingCursor::MoveOnInsert
KateDocument::del
void del(KateView *view, const KTextEditor::Cursor &)
Definition: katedocument.cpp:2805
KateViewInternal::wordPrev
void wordPrev(bool sel=false)
Definition: kateviewinternal.cpp:1074
KateViewInternal::pageDown
void pageDown(bool sel=false, bool half=false)
Definition: kateviewinternal.cpp:1555
KateViewInternal::endLine
int endLine() const
Definition: kateviewinternal.cpp:301
KateDocument::kateTextLine
Kate::TextLine kateTextLine(uint i)
Definition: katedocument.cpp:4707
KateRenderer::caretStyles
caretStyles
Style of Caret.
Definition: katerenderer.h:69
KateLayoutCache::setWrap
void setWrap(bool wrap)
Definition: katelayoutcache.cpp:542
KateDocument::editWrapLine
bool editWrapLine(int line, int col, bool newLine=true, bool *newLineAdded=0)
Wrap line.
Definition: katedocument.cpp:1083
Kate::TextFolding::isLineVisible
bool isLineVisible(int line, qint64 *foldedRangeId=0) const
Query if a given line is visible.
Definition: katetextfolding.cpp:281
KTextEditor::MovingRange::ExpandRight
KateViewInternal::KateScrollBar
friend class KateScrollBar
Definition: kateviewinternal.h:63
KateViewInternal::wheelEvent
virtual void wheelEvent(QWheelEvent *e)
Definition: kateviewinternal.cpp:3214
KateViewInternal::contextMenuEvent
void contextMenuEvent(QContextMenuEvent *e)
Definition: kateviewinternal.cpp:2433
KTextEditor::Cursor::line
virtual int line() const
KateCompletionWidget::isCompletionActive
bool isCompletionActive() const
Definition: katecompletionwidget.cpp:746
KateView::removeSelectedText
bool removeSelectedText()
Definition: kateview.cpp:2021
KateViewInternal::dragMoveEvent
virtual void dragMoveEvent(QDragMoveEvent *)
Definition: kateviewinternal.cpp:3119
KateViewBar::hideCurrentBarWidget
void hideCurrentBarWidget()
Hides currently shown bar widget.
Definition: kateviewhelpers.cpp:2527
KTextEditor::MovingRange::start
virtual const MovingCursor & start() const =0
KateTextLayout
This class represents one visible line of text; with dynamic wrapping, many KateTextLayouts can be ne...
Definition: katetextlayout.h:38
KTextEditor::MovingCursor::line
virtual int line() const =0
KateViInputModeManager::handleKeypress
bool handleKeypress(const QKeyEvent *e)
feed key the given key press to the command parser
Definition: kateviinputmodemanager.cpp:112
KTextEditor::Cursor::setLine
virtual void setLine(int line)
KateView::viInputMode
bool viInputMode() const
Definition: kateview.cpp:1515
KateTextLayout::width
int width() const
Definition: katetextlayout.cpp:202
spellingmenu.h
KateViewInternal::prepareForDynWrapChange
void prepareForDynWrapChange()
Definition: kateviewinternal.cpp:241
KateView::updateViModeBarCmd
void updateViModeBarCmd()
Update vi mode statusbar with the (partial) vi command being typed.
Definition: kateview.cpp:1555
KateLayoutCache::relayoutLines
void relayoutLines(int startRealLine, int endRealLine)
Definition: katelayoutcache.cpp:548
QPoint
KTextEditor::Cursor::setPosition
virtual void setPosition(const Cursor &position)
KateView::getCurrentViMode
ViMode getCurrentViMode() const
Definition: kateview.cpp:1562
KTextEditor::View::selectionChanged
void selectionChanged(KTextEditor::View *view)
KateTextLayout::virtualLine
int virtualLine() const
Definition: katetextlayout.cpp:101
KateViewInternal::endPos
KTextEditor::Cursor endPos() const
Definition: kateviewinternal.cpp:279
Kate::TextCursor
Class representing a 'clever' text cursor.
Definition: katetextcursor.h:43
KateRenderer::setCaretStyle
void setCaretStyle(KateRenderer::caretStyles style)
Set the style of caret to be painted.
Definition: katerenderer.cpp:100
KateDocument::editEnd
void editEnd()
End a editor operation.
Definition: katedocument.cpp:796
QRect
KTextEditor::Range::end
Cursor & end()
KateSpellingMenu::setUseMouseForMisspelledRange
void setUseMouseForMisspelledRange(bool b)
This method has to be called before the menu is shown in response to a context menu event...
Definition: spellingmenu.cpp:161
KateHighlighting
Definition: katehighlight.h:119
KateCompletionWidget::tab
void tab(bool shift)
Definition: katecompletionwidget.cpp:1325
KateViewInternal::disableTextHints
void disableTextHints()
Definition: kateviewinternal.cpp:3304
KateCompletionWidget::hadNavigation
bool hadNavigation() const
Definition: katecompletionwidget.cpp:965
Kate::TextLine
QSharedPointer< TextLineData > TextLine
The normal world only accesses the text lines with shared pointers.
Definition: katetextline.h:443
KateTextLayout::isDirty
bool isDirty() const
Definition: katetextlayout.cpp:34
KateRenderer::paintTextLine
void paintTextLine(QPainter &paint, KateLineLayoutPtr range, int xStart, int xEnd, const KTextEditor::Cursor *cursor=0L)
This is the ultimate function to perform painting of a text line.
Definition: katerenderer.cpp:506
Kate::TextFolding::ensureLineIsVisible
void ensureLineIsVisible(int line)
Ensure that a given line will be visible.
Definition: katetextfolding.cpp:313
KateViewConfig::scrollPastEnd
bool scrollPastEnd() const
Definition: kateconfig.cpp:1854
KTextEditor::MovingRange::setZDepth
virtual void setZDepth(qreal zDepth)=0
KateCompletionWidget::pageUp
void pageUp()
Definition: katecompletionwidget.cpp:1108
copy
CopyJob * copy(const KUrl &src, const KUrl &dest, JobFlags flags=DefaultFlags)
KateViewInternal::startLine
int startLine() const
Definition: kateviewinternal.h:125
KateViewInternal::home
void home(bool sel=false)
Definition: kateviewinternal.cpp:1166
KateView::selectionText
virtual QString selectionText() const
Definition: kateview.cpp:2016
installEventFilter
void installEventFilter(QWidget *filter)
KateRenderer::lineHeight
int lineHeight() const
Definition: katerenderer.cpp:825
KTextEditor::Range::numberOfLines
int numberOfLines() const
KateRendererConfig::backgroundColor
const QColor & backgroundColor() const
Definition: kateconfig.cpp:2178
KateDocument::ownedView
bool ownedView(KateView *)
Definition: katedocument.cpp:2559
KateView::wrapCursor
bool wrapCursor() const
Definition: kateview.cpp:2237
KateTextLayout::endX
int endX() const
Definition: katetextlayout.cpp:194
kWarning
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KateLayoutCache::displayViewLine
int displayViewLine(const KTextEditor::Cursor &virtualCursor, bool limitToVisible=false)
Definition: katelayoutcache.cpp:404
KateViewInternal::showEvent
virtual void showEvent(QShowEvent *)
Definition: kateviewinternal.cpp:693
KateViewInternal::leaveEvent
virtual void leaveEvent(QEvent *)
Definition: kateviewinternal.cpp:2726
KateDocument::inputMethodStart
void inputMethodStart()
Definition: katedocument.cpp:845
KTextEditor::MovingCursor::move
bool move(int chars, WrapBehavior wrapBehavior=Wrap)
QSize
KateDocument::insertTab
void insertTab(KateView *view, const KTextEditor::Cursor &)
Definition: katedocument.cpp:2913
KateTextLayout::lineLayout
const QTextLine & lineLayout() const
Definition: katetextlayout.cpp:117
KateViewInternal::~KateViewInternal
~KateViewInternal()
Definition: kateviewinternal.cpp:221
KateView::abortCompletion
virtual void abortCompletion()
Definition: kateview.cpp:2334
KateViewInternal::enableTextHints
void enableTextHints(int timeout)
Definition: kateviewinternal.cpp:3293
KateView::viInputModeStealKeys
bool viInputModeStealKeys() const
Definition: kateview.cpp:1520
KateView::emitNavigateLeft
void emitNavigateLeft()
Definition: kateview.h:366
KTextEditor::Range::contains
bool contains(const Range &range) const
KTextEditor::MovingRange::end
virtual const MovingCursor & end() const =0
KateViewInternal::tagLine
bool tagLine(const KTextEditor::Cursor &virtualCursor)
Definition: kateviewinternal.cpp:1949
KateRendererConfig::fontMetrics
const QFontMetricsF & fontMetrics() const
Definition: kateconfig.cpp:2135
KateView::isOverwriteMode
bool isOverwriteMode() const
Return values for "save" related commands.
Definition: kateview.cpp:1199
KateView::emitNavigateBack
void emitNavigateBack()
Definition: kateview.h:381
KateViewInternal::WrappingCursor
friend class WrappingCursor
Definition: kateviewinternal.h:66
KateViewInternal::cursorDown
void cursorDown(bool sel=false)
Definition: kateviewinternal.cpp:1429
KateViewInternal::eventFilter
virtual bool eventFilter(QObject *obj, QEvent *e)
Definition: kateviewinternal.cpp:2110
KateDocument::editStart
void editStart()
Enclose editor actions with editStart() and editEnd() to group them.
Definition: katedocument.cpp:776
KTextEditor::View
KateViInputModeManager::getCurrentViMode
ViMode getCurrentViMode() const
Definition: kateviinputmodemanager.cpp:449
KateView::emitNavigateRight
void emitNavigateRight()
Definition: kateview.h:369
KateLayoutCache::viewCacheLineCount
int viewCacheLineCount() const
Definition: katelayoutcache.cpp:364
KTextEditor::Range::isEmpty
bool isEmpty() const
KateLineLayout::length
int length() const
Definition: katelinelayout.cpp:167
KateCompletionWidget::abortCompletion
void abortCompletion()
Definition: katecompletionwidget.cpp:751
KateView::config
KateViewConfig * config()
Configuration.
Definition: kateview.h:654
QEvent
KTextEditor::Cursor::Cursor
Cursor()
KTextEditor::MovingCursor::setLine
void setLine(int line)
KateHighlighting::isInWord
bool isInWord(QChar c, int attrib=0) const
Definition: katehighlight.cpp:1084
KateRenderer::setDrawCaret
void setDrawCaret(bool drawCaret)
Set whether the caret (text cursor) will be drawn.
Definition: katerenderer.cpp:95
KateLayoutCache::updateViewCache
void updateViewCache(const KTextEditor::Cursor &startPos, int newViewLineCount=-1, int viewLinesScrolled=0)
Definition: katelayoutcache.cpp:159
Kate::TextFolding::visibleLines
int visibleLines() const
Query number of visible lines.
Definition: katetextfolding.cpp:340
KGlobalSettings::dndEventDelay
static int dndEventDelay()
kateconfig.h
KTextEditor::Cursor::setColumn
virtual void setColumn(int column)
KTextEditor::Cursor::column
int column() const
KateLineLayout::widthOfLastLine
int widthOfLastLine() const
Definition: katelinelayout.cpp:196
KateTextLayout::invalid
static KateTextLayout invalid()
Definition: katetextlayout.cpp:210
KateViewInternal::cursorCoordinates
QPoint cursorCoordinates(bool includeBorder=true) const
Definition: kateviewinternal.cpp:737
KateViewInternal::scrollUp
void scrollUp()
Definition: kateviewinternal.cpp:1493
KTextEditor::Cursor::m_column
int m_column
KateDocument::removeText
virtual bool removeText(const KTextEditor::Range &range, bool block=false)
Definition: katedocument.cpp:633
Default
KateViewInternal::bottom_end
void bottom_end(bool sel=false)
Definition: kateviewinternal.cpp:1654
KateCompletionWidget::execute
void execute()
Definition: katecompletionwidget.cpp:795
KateViewInternal::dynWrapChanged
void dynWrapChanged()
Definition: kateviewinternal.cpp:247
KateDocumentConfig::tabHandling
uint tabHandling() const
Definition: kateconfig.cpp:472
KateTextLayout::wrap
bool wrap() const
Definition: katetextlayout.cpp:173
KateViewInternal::coordinatesToCursor
KTextEditor::Cursor coordinatesToCursor(const QPoint &coord, bool includeBorder=true) const
Definition: kateviewinternal.cpp:2736
KateView::paste
void paste(const QString *textToPaste=0)
Definition: kateview.cpp:2374
KateViewInternal::findMatchingBracket
KTextEditor::Cursor findMatchingBracket()
Definition: kateviewinternal.cpp:742
KateDocumentConfig::tabSmart
indents in leading space, otherwise inserts tab
Definition: kateconfig.h:197
KateViewInternal::inputMethodEvent
virtual void inputMethodEvent(QInputMethodEvent *e)
Definition: kateviewinternal.cpp:3505
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:31:53 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Kate

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

applications API Reference

Skip menu "applications API Reference"
  •   kate
  •       kate
  •   KTextEditor
  •   Kate
  • Applications
  •   Libraries
  •     libkonq
  • Konsole

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal