00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "kateviewinternal.h"
00029 #include "kateviewinternal.moc"
00030
00031 #include "kateview.h"
00032 #include "katecodefolding.h"
00033 #include "kateviewhelpers.h"
00034 #include "katehighlight.h"
00035 #include "katesmartrange.h"
00036 #include "katerenderer.h"
00037 #include "kateconfig.h"
00038 #include "katelayoutcache.h"
00039 #include "katedynamicanimation.h"
00040 #include "katesmartmanager.h"
00041 #include "katecompletionwidget.h"
00042 #include "katenamespace.h"
00043 #include "kateviinputmodemanager.h"
00044 #include "katevimodebar.h"
00045
00046 #include <kcursor.h>
00047 #include <kdebug.h>
00048 #include <kapplication.h>
00049 #include <kglobalsettings.h>
00050
00051 #include <QtCore/QMimeData>
00052 #include <QtGui/QPainter>
00053 #include <QtGui/QLayout>
00054 #include <QtGui/QClipboard>
00055 #include <QtGui/QPixmap>
00056 #include <QtGui/QKeyEvent>
00057 #include <QtCore/QStack>
00058 #include <QtCore/QMutex>
00059 #include <QtCore/QThread>
00060
00061 static const bool debugPainting = false;
00062
00063 KateViewInternal::KateViewInternal(KateView *view, KateDocument *doc)
00064 : QWidget (view)
00065 , editSessionNumber (0)
00066 , editIsRunning (false)
00067 , m_view (view)
00068 , m_doc (doc)
00069 , m_cursor(doc)
00070 , m_mouse()
00071 , m_possibleTripleClick (false)
00072 , m_completionItemExpanded (false)
00073 , m_bm(doc->smartManager()->newSmartRange())
00074 , m_bmStart(doc->smartManager()->newSmartRange(KTextEditor::Range(), m_bm))
00075 , m_bmEnd(doc->smartManager()->newSmartRange(KTextEditor::Range(), m_bm))
00076 , m_bmHighlighted(false)
00077 , m_dummy (0)
00078
00079
00080 , m_startPos(doc, KTextEditor::SmartCursor::StayOnInsert)
00081
00082 , m_madeVisible(false)
00083 , m_shiftKeyPressed (false)
00084 , m_autoCenterLines (false)
00085 , m_selChangedByUser (false)
00086 , m_selectAnchor (-1, -1)
00087 , m_selectionMode( Default )
00088 , m_layoutCache(new KateLayoutCache(renderer(), this))
00089 , m_preserveMaxX(false)
00090 , m_currentMaxX(0)
00091 , m_updatingView(true)
00092 , m_cachedMaxStartPos(-1, -1)
00093 , m_dragScrollTimer(this)
00094 , m_scrollTimer (this)
00095 , m_cursorTimer (this)
00096 , m_textHintTimer (this)
00097 , m_textHintEnabled(false)
00098 , m_textHintMouseX(-1)
00099 , m_textHintMouseY(-1)
00100 , m_imPreedit(0L)
00101 , m_smartDirty(false)
00102 , m_viInputMode(false)
00103 , m_viInputModeManager (0)
00104 {
00105 m_watcherCount1 = 0;
00106 m_watcherCount3 = 0;
00107
00108 updateBracketMarkAttributes();
00109
00110 setMinimumSize (0,0);
00111 setAttribute(Qt::WA_OpaquePaintEvent);
00112 setAttribute(Qt::WA_InputMethodEnabled);
00113
00114
00115 m_cursor.setInsertBehavior (KTextEditor::SmartCursor::MoveOnInsert);
00116 m_cursor.setInternal();
00117
00118 m_startPos.setInternal();
00119
00120
00121 m_selectionCached = KTextEditor::Range::invalid();
00122
00123
00124
00125 m_lineScroll = new KateScrollBar(Qt::Vertical, this);
00126 m_lineScroll->show();
00127 m_lineScroll->setTracking (true);
00128 m_lineScroll->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding );
00129
00130
00131 m_dummy = new QWidget(m_view);
00132 m_dummy->setFixedSize(m_lineScroll->width(), m_lineScroll->width());
00133 m_dummy->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
00134
00135 if (m_view->dynWordWrap())
00136 m_dummy->hide();
00137 else
00138 m_dummy->show();
00139
00140 cache()->setWrap(m_view->dynWordWrap());
00141
00142
00143 connect(m_lineScroll, SIGNAL(actionTriggered(int)), SLOT(scrollAction(int)));
00144 connect(m_lineScroll, SIGNAL(sliderMoved(int)), SLOT(scrollLines(int)));
00145 connect(m_lineScroll, SIGNAL(sliderMMBMoved(int)), SLOT(scrollLines(int)));
00146
00147
00148
00149
00150
00151
00152
00153 m_columnScroll = new QScrollBar(Qt::Horizontal,m_view);
00154
00155 if (m_view->dynWordWrap())
00156 m_columnScroll->hide();
00157 else
00158 m_columnScroll->show();
00159
00160 m_columnScroll->setTracking(true);
00161 m_startX = 0;
00162
00163 connect(m_columnScroll, SIGNAL(valueChanged(int)), SLOT(scrollColumns(int)));
00164
00165
00166
00167
00168 m_leftBorder = new KateIconBorder( this, m_view );
00169 m_leftBorder->show ();
00170
00171 connect( m_leftBorder, SIGNAL(toggleRegionVisibility(unsigned int)),
00172 m_doc->foldingTree(), SLOT(toggleRegionVisibility(unsigned int)));
00173
00174 connect( doc->foldingTree(), SIGNAL(regionVisibilityChangedAt(unsigned int,bool)),
00175 this, SLOT(slotRegionVisibilityChangedAt(unsigned int,bool)));
00176 connect( doc, SIGNAL(codeFoldingUpdated()),
00177 this, SLOT(slotCodeFoldingChanged()) );
00178
00179 m_displayCursor.setPosition(0, 0);
00180 m_cursor.setInsertBehavior(KTextEditor::SmartCursor::MoveOnInsert);
00181 m_cursorX = 0;
00182
00183 setAcceptDrops( true );
00184
00185
00186 installEventFilter(this);
00187 m_view->viewBar()->installEventFilter(this);
00188
00189
00190 setAttribute(Qt::WA_InputMethodEnabled, true);
00191
00192
00193 m_mouseCursor = Qt::IBeamCursor;
00194 setCursor(m_mouseCursor);
00195
00196
00197 setMouseTracking(true);
00198
00199 m_dragInfo.state = diNone;
00200
00201
00202 connect( &m_dragScrollTimer, SIGNAL( timeout() ),
00203 this, SLOT( doDragScroll() ) );
00204
00205 connect( &m_scrollTimer, SIGNAL( timeout() ),
00206 this, SLOT( scrollTimeout() ) );
00207
00208 connect( &m_cursorTimer, SIGNAL( timeout() ),
00209 this, SLOT( cursorTimeout() ) );
00210
00211 connect( &m_textHintTimer, SIGNAL( timeout() ),
00212 this, SLOT( textHintTimeout() ) );
00213
00214
00215 connect( m_view, SIGNAL( selectionChanged(KTextEditor::View*) ),
00216 this, SLOT( viewSelectionChanged() ) );
00217
00218 connect(m_doc, SIGNAL(dynamicHighlightAdded(KateSmartRange*)), SLOT(dynamicHighlightAdded(KateSmartRange*)));
00219 connect(m_doc, SIGNAL(dynamicHighlightRemoved(KateSmartRange*)), SLOT(dynamicHighlightRemoved(KateSmartRange*)));
00220 connect(m_view, SIGNAL(dynamicHighlightAdded(KateSmartRange*)), SLOT(dynamicHighlightAdded(KateSmartRange*)));
00221 connect(m_view, SIGNAL(dynamicHighlightRemoved(KateSmartRange*)), SLOT(dynamicHighlightRemoved(KateSmartRange*)));
00222 connect(m_doc->smartManager(), SIGNAL(signalRangeDeleted(KateSmartRange*)), SLOT(rangeDeleted(KateSmartRange*)));
00223
00224
00225
00226
00227
00228 connect(this, SIGNAL(requestViewUpdate(bool)), this, SLOT(updateView(bool)), Qt::QueuedConnection);
00229 }
00230
00231 void KateViewInternal::removeWatcher(KTextEditor::SmartRange* range, KTextEditor::SmartRangeWatcher* watcher)
00232 {
00233 if (range->watchers().contains(this)) {
00234 --m_watcherCount1;
00235 range->removeWatcher(watcher);
00236
00237 }
00238
00239 foreach (KTextEditor::SmartRange* child, range->childRanges())
00240 removeWatcher(child, watcher);
00241 }
00242
00243 void KateViewInternal::addWatcher(KTextEditor::SmartRange* range, KTextEditor::SmartRangeWatcher* watcher)
00244 {
00245
00246
00247
00248
00249 if (!range->watchers().contains(watcher)) {
00250 range->addWatcher(watcher);
00251 ++m_watcherCount1;
00252 Q_ASSERT(range->watchers().contains(watcher));
00253
00254 }
00255
00256 foreach (KTextEditor::SmartRange* child, range->childRanges())
00257 addWatcher(child, watcher);
00258 }
00259
00260 KateViewInternal::~KateViewInternal ()
00261 {
00262
00263 disconnect(m_doc->smartManager(), SIGNAL(signalRangeDeleted(KateSmartRange*)), this, SLOT(rangeDeleted(KateSmartRange*)));
00264
00265 qDeleteAll(m_dynamicHighlights);
00266
00267 delete m_imPreedit;
00268
00269 if (m_viInputModeManager) {
00270 delete m_viInputModeManager;
00271 }
00272 }
00273
00274 void KateViewInternal::prepareForDynWrapChange()
00275 {
00276
00277 m_wrapChangeViewLine = cache()->displayViewLine(m_displayCursor, true);
00278 }
00279
00280 void KateViewInternal::dynWrapChanged()
00281 {
00282 if (m_view->dynWordWrap())
00283 {
00284 m_columnScroll->hide();
00285 m_dummy->hide();
00286
00287 }
00288 else
00289 {
00290
00291 m_columnScroll->show();
00292 m_dummy->show();
00293 }
00294
00295 cache()->setWrap(m_view->dynWordWrap());
00296 updateView();
00297
00298 if (m_view->dynWordWrap())
00299 scrollColumns(0);
00300
00301
00302 if (m_wrapChangeViewLine != -1) {
00303 KTextEditor::Cursor newStart = viewLineOffset(m_displayCursor, -m_wrapChangeViewLine);
00304 makeVisible(newStart, newStart.column(), true);
00305
00306 } else {
00307 update();
00308 }
00309 }
00310
00311 KTextEditor::Cursor KateViewInternal::endPos() const
00312 {
00313
00314 if (!cache()->viewCacheLineCount())
00315 return KTextEditor::Cursor();
00316
00317 for (int i = qMin(linesDisplayed() - 1, cache()->viewCacheLineCount() - 1); i >= 0; i--) {
00318 const KateTextLayout& thisLine = cache()->viewLine(i);
00319
00320 if (thisLine.line() == -1) continue;
00321
00322 if (thisLine.virtualLine() >= m_doc->numVisLines()) {
00323
00324 return KTextEditor::Cursor(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
00325 }
00326
00327 return KTextEditor::Cursor(thisLine.virtualLine(), thisLine.wrap() ? thisLine.endCol() - 1 : thisLine.endCol());
00328 }
00329
00330 Q_ASSERT(false);
00331 kDebug(13030) << "WARNING: could not find a lineRange at all";
00332 return KTextEditor::Cursor(-1, -1);
00333 }
00334
00335 int KateViewInternal::endLine() const
00336 {
00337 return endPos().line();
00338 }
00339
00340 KateTextLayout KateViewInternal::yToKateTextLayout(int y) const
00341 {
00342 if (y < 0 || y > size().height())
00343 return KateTextLayout::invalid();
00344
00345 int range = y / renderer()->fontHeight();
00346
00347
00348 if (range >= 0 && range <= cache()->viewCacheLineCount())
00349 return cache()->viewLine(range);
00350
00351 return KateTextLayout::invalid();
00352 }
00353
00354 int KateViewInternal::lineToY(int viewLine) const
00355 {
00356 return (viewLine-startLine()) * renderer()->fontHeight();
00357 }
00358
00359 void KateViewInternal::slotIncFontSizes()
00360 {
00361 renderer()->increaseFontSizes();
00362 }
00363
00364 void KateViewInternal::slotDecFontSizes()
00365 {
00366 renderer()->decreaseFontSizes();
00367 }
00368
00372 void KateViewInternal::scrollLines ( int line )
00373 {
00374 KTextEditor::Cursor newPos(line, 0);
00375 scrollPos(newPos);
00376 }
00377
00378
00379 void KateViewInternal::scrollViewLines(int offset)
00380 {
00381 KTextEditor::Cursor c = viewLineOffset(startPos(), offset);
00382 scrollPos(c);
00383
00384 bool blocked = m_lineScroll->blockSignals(true);
00385 m_lineScroll->setValue(startLine());
00386 m_lineScroll->blockSignals(blocked);
00387 }
00388
00389 void KateViewInternal::scrollAction( int action )
00390 {
00391 switch (action) {
00392 case QAbstractSlider::SliderSingleStepAdd:
00393 scrollNextLine();
00394 break;
00395
00396 case QAbstractSlider::SliderSingleStepSub:
00397 scrollPrevLine();
00398 break;
00399
00400 case QAbstractSlider::SliderPageStepAdd:
00401 scrollNextPage();
00402 break;
00403
00404 case QAbstractSlider::SliderPageStepSub:
00405 scrollPrevPage();
00406 break;
00407
00408 case QAbstractSlider::SliderToMinimum:
00409 top_home();
00410 break;
00411
00412 case QAbstractSlider::SliderToMaximum:
00413 bottom_end();
00414 break;
00415 }
00416 }
00417
00418 void KateViewInternal::scrollNextPage()
00419 {
00420 scrollViewLines(qMax( linesDisplayed() - 1, 0 ));
00421 }
00422
00423 void KateViewInternal::scrollPrevPage()
00424 {
00425 scrollViewLines(-qMax( linesDisplayed() - 1, 0 ));
00426 }
00427
00428 void KateViewInternal::scrollPrevLine()
00429 {
00430 scrollViewLines(-1);
00431 }
00432
00433 void KateViewInternal::scrollNextLine()
00434 {
00435 scrollViewLines(1);
00436 }
00437
00438 KTextEditor::Cursor KateViewInternal::maxStartPos(bool changed)
00439 {
00440 cache()->setAcceptDirtyLayouts(true);
00441
00442 if (m_cachedMaxStartPos.line() == -1 || changed)
00443 {
00444 KTextEditor::Cursor end(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
00445
00446 m_cachedMaxStartPos = viewLineOffset(end, -(linesDisplayed() - 1));
00447 }
00448
00449 cache()->setAcceptDirtyLayouts(false);
00450
00451 return m_cachedMaxStartPos;
00452 }
00453
00454
00455 void KateViewInternal::scrollPos(KTextEditor::Cursor& c, bool force, bool calledExternally)
00456 {
00457 if (!force && ((!m_view->dynWordWrap() && c.line() == startLine()) || c == startPos()))
00458 return;
00459
00460 if (c.line() < 0)
00461 c.setLine(0);
00462
00463 KTextEditor::Cursor limit = maxStartPos();
00464 if (c > limit) {
00465 c = limit;
00466
00467
00468 if (!force && ((!m_view->dynWordWrap() && c.line() == startLine()) || c == startPos()))
00469 return;
00470 }
00471
00472 int viewLinesScrolled = 0;
00473
00474
00475
00476
00477 bool viewLinesScrolledUsable = !force
00478 && (c.line() >= startLine() - linesDisplayed() - 1)
00479 && (c.line() <= endLine() + linesDisplayed() + 1);
00480
00481 if (viewLinesScrolledUsable)
00482 viewLinesScrolled = cache()->displayViewLine(c);
00483
00484 m_startPos.setPosition(c);
00485
00486
00487 m_madeVisible = false;
00488
00489 if (viewLinesScrolledUsable)
00490 {
00491 int lines = linesDisplayed();
00492 if (m_doc->numVisLines() < lines) {
00493 KTextEditor::Cursor end(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
00494 lines = qMin(linesDisplayed(), cache()->displayViewLine(end) + 1);
00495 }
00496
00497 Q_ASSERT(lines >= 0);
00498
00499 if (!calledExternally && qAbs(viewLinesScrolled) < lines)
00500 {
00501 updateView(false, viewLinesScrolled);
00502
00503 int scrollHeight = -(viewLinesScrolled * (int)renderer()->fontHeight());
00504
00505 scroll(0, scrollHeight);
00506 m_leftBorder->scroll(0, scrollHeight);
00507
00508 emit m_view->verticalScrollPositionChanged( m_view, c );
00509 return;
00510 }
00511 }
00512
00513 updateView();
00514 update();
00515 m_leftBorder->update();
00516 emit m_view->verticalScrollPositionChanged( m_view, c );
00517 }
00518
00519 void KateViewInternal::scrollColumns ( int x )
00520 {
00521 if (x == m_startX)
00522 return;
00523
00524 if (x < 0)
00525 x = 0;
00526
00527 int dx = m_startX - x;
00528 m_startX = x;
00529
00530 if (qAbs(dx) < width())
00531 scroll(dx, 0);
00532 else
00533 update();
00534
00535 emit m_view->horizontalScrollPositionChanged( m_view );
00536
00537 bool blocked = m_columnScroll->blockSignals(true);
00538 m_columnScroll->setValue(m_startX);
00539 m_columnScroll->blockSignals(blocked);
00540 }
00541
00542
00543 void KateViewInternal::updateView(bool changed, int viewLinesScrolled)
00544 {
00545 QMutexLocker lock(m_doc->smartMutex());
00546
00547 doUpdateView(changed, viewLinesScrolled);
00548
00549 if (changed)
00550 updateDirty();
00551 }
00552
00553 void KateViewInternal::doUpdateView(bool changed, int viewLinesScrolled)
00554 {
00555 m_updatingView = true;
00556
00557 bool blocked = m_lineScroll->blockSignals(true);
00558
00559 if (width() != cache()->viewWidth())
00560 cache()->setViewWidth(width());
00561
00562
00563
00564
00565
00566
00567 int newSize = (qMax (0, height()) / renderer()->fontHeight()) + 1;
00568 cache()->updateViewCache(startPos(), newSize, viewLinesScrolled);
00569
00570 KTextEditor::Cursor maxStart = maxStartPos(changed);
00571 int maxLineScrollRange = maxStart.line();
00572 if (m_view->dynWordWrap() && maxStart.column() != 0)
00573 maxLineScrollRange++;
00574 m_lineScroll->setRange(0, maxLineScrollRange);
00575
00576 m_lineScroll->setValue(startPos().line());
00577 m_lineScroll->setSingleStep(1);
00578 m_lineScroll->setPageStep(qMax (0, height()) / renderer()->fontHeight());
00579 m_lineScroll->blockSignals(blocked);
00580
00581 if (!m_view->dynWordWrap())
00582 {
00583 int max = maxLen(startLine()) - width();
00584 if (max < 0)
00585 max = 0;
00586
00587
00588 if (max == 0)
00589 {
00590 scrollColumns(0);
00591 }
00592
00593 blocked = m_columnScroll->blockSignals(true);
00594
00595
00596 m_columnScroll->setDisabled (max == 0);
00597
00598 m_columnScroll->setRange(0, max);
00599
00600 m_columnScroll->setValue(m_startX);
00601
00602
00603 m_columnScroll->setSingleStep(renderer()->config()->fontMetrics().width('a'));
00604 m_columnScroll->setPageStep(width());
00605
00606 m_columnScroll->blockSignals(blocked);
00607 }
00608
00609 if (m_smartDirty)
00610 m_smartDirty = false;
00611
00612 m_updatingView = false;
00613 }
00614
00619 void KateViewInternal::makeVisible (const KTextEditor::Cursor& c, int endCol, bool force, bool center, bool calledExternally)
00620 {
00621
00622
00623
00624
00625
00626 if ( force )
00627 {
00628 KTextEditor::Cursor scroll = c;
00629 scrollPos(scroll, force, calledExternally);
00630 }
00631 else if (center && (c < startPos() || c > endPos()))
00632 {
00633 KTextEditor::Cursor scroll = viewLineOffset(c, -int(linesDisplayed()) / 2);
00634 scrollPos(scroll, false, calledExternally);
00635 }
00636 else if ( c > viewLineOffset(endPos(), -m_minLinesVisible) )
00637 {
00638 KTextEditor::Cursor scroll = viewLineOffset(c, -(linesDisplayed() - m_minLinesVisible - 1));
00639 scrollPos(scroll, false, calledExternally);
00640 }
00641 else if ( c < viewLineOffset(startPos(), m_minLinesVisible) )
00642 {
00643 KTextEditor::Cursor scroll = viewLineOffset(c, -m_minLinesVisible);
00644 scrollPos(scroll, false, calledExternally);
00645 }
00646 else
00647 {
00648
00649 KTextEditor::Cursor max = maxStartPos();
00650 if (startPos() > max) {
00651 scrollPos(max, max.column(), calledExternally);
00652 }
00653 }
00654
00655 if (!m_view->dynWordWrap() && endCol != -1)
00656 {
00657 int sX = renderer()->cursorToX(cache()->textLayout(c), c);
00658
00659 int sXborder = sX-8;
00660 if (sXborder < 0)
00661 sXborder = 0;
00662
00663 if (sX < m_startX)
00664 scrollColumns (sXborder);
00665 else if (sX > m_startX + width())
00666 scrollColumns (sX - width() + 8);
00667 }
00668
00669 m_madeVisible = !force;
00670 }
00671
00672 void KateViewInternal::slotRegionVisibilityChangedAt(unsigned int,bool clear_cache)
00673 {
00674 kDebug(13030) << "slotRegionVisibilityChangedAt()";
00675 m_cachedMaxStartPos.setLine(-1);
00676 KTextEditor::Cursor max = maxStartPos();
00677 if (startPos() > max)
00678 scrollPos(max);
00679
00680 if (clear_cache)
00681 cache()->clear ();
00682 updateView();
00683 update();
00684 m_leftBorder->update();
00685 }
00686
00687 void KateViewInternal::slotCodeFoldingChanged()
00688 {
00689 m_leftBorder->update();
00690 }
00691
00692 void KateViewInternal::slotRegionBeginEndAddedRemoved(unsigned int)
00693 {
00694 kDebug(13030) << "slotRegionBeginEndAddedRemoved()";
00695
00696 m_leftBorder->update();
00697 }
00698
00699 void KateViewInternal::showEvent ( QShowEvent *e )
00700 {
00701 updateView ();
00702
00703 QWidget::showEvent (e);
00704 }
00705
00706 int KateViewInternal::linesDisplayed() const
00707 {
00708 int h = height();
00709 int fh = renderer()->fontHeight();
00710
00711
00712
00713 return qMax (1, (h - (h % fh)) / fh);
00714 }
00715
00716 KTextEditor::Cursor KateViewInternal::getCursor() const
00717 {
00718 QMutexLocker l(m_doc->smartMutex());
00719
00720 return m_cursor;
00721 }
00722
00723 QPoint KateViewInternal::cursorToCoordinate( const KTextEditor::Cursor & cursor, bool realCursor, bool includeBorder ) const
00724 {
00725 QMutexLocker l(m_doc->smartMutex());
00726
00727 int viewLine = cache()->displayViewLine(realCursor ? toVirtualCursor(cursor) : cursor, true);
00728
00729 if (viewLine < 0 || viewLine >= cache()->viewCacheLineCount())
00730 return QPoint(-1, -1);
00731
00732 int y = (int)viewLine * renderer()->fontHeight();
00733
00734 KateTextLayout layout = cache()->viewLine(viewLine);
00735 int x = 0;
00736
00737
00738 if (layout.isValid())
00739 x = (int)layout.lineLayout().cursorToX(cursor.column());
00740
00741
00742
00743 if (includeBorder) x += m_leftBorder->width();
00744
00745 return QPoint(x, y);
00746 }
00747
00748 QPoint KateViewInternal::cursorCoordinates(bool includeBorder) const
00749 {
00750 return cursorToCoordinate(m_displayCursor, false, includeBorder);
00751 }
00752
00753 KTextEditor::Cursor KateViewInternal::findMatchingBracket()
00754 {
00755 KTextEditor::Cursor c;
00756
00757 if (!m_bm->isValid())
00758 return KTextEditor::Cursor(-1, -1);
00759
00760 Q_ASSERT(m_bmEnd->isValid());
00761 Q_ASSERT(m_bmStart->isValid());
00762
00763 if (m_bmStart->contains(m_cursor) || m_bmStart->end() == m_cursor) {
00764 c = m_bmEnd->end();
00765 } else if (m_bmEnd->contains(m_cursor) || m_bmEnd->end() == m_cursor) {
00766 c = m_bmStart->start();
00767 } else {
00768
00769
00770 return KTextEditor::Cursor(-1, -1);
00771 }
00772
00773 return c;
00774 }
00775
00776 void KateViewInternal::doReturn()
00777 {
00778 m_doc->newLine( view() );
00779 updateView();
00780 }
00781
00782 void KateViewInternal::doSmartNewline()
00783 {
00784 int ln = m_cursor.line();
00785 KateTextLine::Ptr line = m_doc->kateTextLine(ln);
00786 int col = qMin(m_cursor.column(), line->firstChar());
00787 if (col != -1) {
00788 while (line->length() > col &&
00789 !line->at(col).isLetterOrNumber() &&
00790 col < m_cursor.column()) ++col;
00791 } else {
00792 col = line->length();
00793 }
00794 m_doc->editStart();
00795 m_doc->editWrapLine(ln, m_cursor.column());
00796 m_doc->insertText(KTextEditor::Cursor(ln + 1, 0), line->string(0, col));
00797 m_doc->editEnd();
00798
00799 updateView();
00800 }
00801
00802 void KateViewInternal::doDelete()
00803 {
00804 m_doc->del( m_view, m_cursor );
00805 }
00806
00807 void KateViewInternal::doBackspace()
00808 {
00809 m_doc->backspace( m_view, m_cursor );
00810 }
00811
00812 void KateViewInternal::doTranspose()
00813 {
00814 m_doc->transpose( m_cursor );
00815 }
00816
00817 void KateViewInternal::doDeleteWordLeft()
00818 {
00819 m_doc->editStart();
00820 wordLeft( true );
00821 KTextEditor::Range selection = m_view->selectionRange();
00822 m_view->removeSelectedText();
00823 m_doc->editEnd();
00824 tagRange(selection, true);
00825 updateDirty();
00826 }
00827
00828 void KateViewInternal::doDeleteWordRight()
00829 {
00830 m_doc->editStart();
00831 wordRight( true );
00832 KTextEditor::Range selection = m_view->selectionRange();
00833 m_view->removeSelectedText();
00834 m_doc->editEnd();
00835 tagRange(selection, true);
00836 updateDirty();
00837 }
00838
00839 class CalculatingCursor : public KTextEditor::Cursor {
00840 public:
00841 CalculatingCursor(KateViewInternal* vi)
00842 : KTextEditor::Cursor()
00843 , m_vi(vi)
00844 {
00845 Q_ASSERT(valid());
00846 }
00847
00848 CalculatingCursor(KateViewInternal* vi, const KTextEditor::Cursor& c)
00849 : KTextEditor::Cursor(c)
00850 , m_vi(vi)
00851 {
00852 Q_ASSERT(valid());
00853 }
00854
00855
00856 CalculatingCursor(KateViewInternal* vi, int line, int col)
00857 : KTextEditor::Cursor(line, col)
00858 , m_vi(vi)
00859 {
00860 makeValid();
00861 }
00862
00863
00864 virtual CalculatingCursor& operator+=( int n ) = 0;
00865
00866 virtual CalculatingCursor& operator-=( int n ) = 0;
00867
00868 CalculatingCursor& operator++() { return operator+=( 1 ); }
00869
00870 CalculatingCursor& operator--() { return operator-=( 1 ); }
00871
00872 void makeValid() {
00873 setLine(qBound( 0, line(), int( m_vi->m_doc->lines() - 1 ) ) );
00874 if (m_vi->m_view->wrapCursor())
00875 m_column = qBound( 0, column(), m_vi->m_doc->lineLength( line() ) );
00876 else
00877 m_column = qMax( 0, column() );
00878 Q_ASSERT( valid() );
00879 }
00880
00881 void toEdge( KateViewInternal::Bias bias ) {
00882 if( bias == KateViewInternal::left ) m_column = 0;
00883 else if( bias == KateViewInternal::right ) m_column = m_vi->m_doc->lineLength( line() );
00884 }
00885
00886 bool atEdge() const { return atEdge( KateViewInternal::left ) || atEdge( KateViewInternal::right ); }
00887
00888 bool atEdge( KateViewInternal::Bias bias ) const {
00889 switch( bias ) {
00890 case KateViewInternal::left: return column() == 0;
00891 case KateViewInternal::none: return atEdge();
00892 case KateViewInternal::right: return column() == m_vi->m_doc->lineLength( line() );
00893 default: Q_ASSERT(false); return false;
00894 }
00895 }
00896
00897 protected:
00898 bool valid() const {
00899 return line() >= 0 &&
00900 line() < m_vi->m_doc->lines() &&
00901 column() >= 0 &&
00902 (!m_vi->m_view->wrapCursor() || column() <= m_vi->m_doc->lineLength( line() ));
00903 }
00904 KateViewInternal* m_vi;
00905 };
00906
00907 class BoundedCursor : public CalculatingCursor {
00908 public:
00909 BoundedCursor(KateViewInternal* vi)
00910 : CalculatingCursor( vi ) {}
00911 BoundedCursor(KateViewInternal* vi, const KTextEditor::Cursor& c )
00912 : CalculatingCursor( vi, c ) {}
00913 BoundedCursor(KateViewInternal* vi, int line, int col )
00914 : CalculatingCursor( vi, line, col ) {}
00915 virtual CalculatingCursor& operator+=( int n ) {
00916 KateLineLayoutPtr thisLine = m_vi->cache()->line(line());
00917 if (!thisLine->isValid()) {
00918 kWarning() << "Did not retrieve valid layout for line " << line();
00919 return *this;
00920 }
00921
00922 const bool noWrapCursor = m_vi->view()->blockSelection() || !m_vi->m_view->wrapCursor();
00923 int maxColumn = -1;
00924 if (n >= 0) {
00925 for (int i = 0; i < n; i++) {
00926 if (m_column >= thisLine->length()) {
00927 if (!noWrapCursor) {
00928 break;
00929
00930 } else if (m_vi->view()->dynWordWrap()) {
00931
00932 if (maxColumn == -1)
00933 maxColumn = thisLine->length() + ((m_vi->width() - thisLine->widthOfLastLine()) / m_vi->renderer()->spaceWidth()) - 1;
00934
00935 if (m_column >= maxColumn) {
00936 m_column = maxColumn;
00937 break;
00938 }
00939
00940 ++m_column;
00941
00942 } else {
00943 ++m_column;
00944 }
00945
00946 } else {
00947 m_column = thisLine->layout()->nextCursorPosition(m_column);
00948 }
00949 }
00950 } else {
00951 for (int i = 0; i > n; i--) {
00952 if (m_column >= thisLine->length())
00953 --m_column;
00954 else if (m_column == 0)
00955 break;
00956 else
00957 m_column = thisLine->layout()->previousCursorPosition(m_column);
00958 }
00959 }
00960
00961 Q_ASSERT( valid() );
00962 return *this;
00963 }
00964 virtual CalculatingCursor& operator-=( int n ) {
00965 return operator+=( -n );
00966 }
00967 };
00968
00969 class WrappingCursor : public CalculatingCursor {
00970 public:
00971 WrappingCursor(KateViewInternal* vi)
00972 : CalculatingCursor( vi) {}
00973 WrappingCursor(KateViewInternal* vi, const KTextEditor::Cursor& c )
00974 : CalculatingCursor( vi, c ) {}
00975 WrappingCursor(KateViewInternal* vi, int line, int col )
00976 : CalculatingCursor( vi, line, col ) {}
00977
00978 virtual CalculatingCursor& operator+=( int n ) {
00979 KateLineLayoutPtr thisLine = m_vi->cache()->line(line());
00980 if (!thisLine->isValid()) {
00981 kWarning() << "Did not retrieve a valid layout for line " << line();
00982 return *this;
00983 }
00984
00985 if (n >= 0) {
00986 for (int i = 0; i < n; i++) {
00987 if (m_column == thisLine->length()) {
00988
00989 if (line() >= m_vi->m_doc->lines() - 1)
00990
00991 break;
00992
00993
00994 m_column = 0;
00995 setLine(line() + 1);
00996
00997
00998 thisLine = m_vi->cache()->line(line());
00999 if (!thisLine->isValid()) {
01000 kWarning() << "Did not retrieve a valid layout for line " << line();
01001 return *this;
01002 }
01003
01004 continue;
01005 }
01006
01007 m_column = thisLine->layout()->nextCursorPosition(m_column);
01008 }
01009
01010 } else {
01011 for (int i = 0; i > n; i--) {
01012 if (m_column == 0) {
01013
01014 if (line() == 0)
01015 break;
01016
01017
01018 setLine(line() - 1);
01019
01020
01021 thisLine = m_vi->cache()->line(line());
01022 if (!thisLine->isValid()) {
01023 kWarning() << "Did not retrieve a valid layout for line " << line();
01024 return *this;
01025 }
01026
01027
01028 m_column = thisLine->length();
01029
01030 continue;
01031 }
01032
01033 m_column = thisLine->layout()->previousCursorPosition(m_column);
01034 }
01035 }
01036
01037 Q_ASSERT(valid());
01038 return *this;
01039 }
01040 virtual CalculatingCursor& operator-=( int n ) {
01041 return operator+=( -n );
01042 }
01043 };
01044
01045 void KateViewInternal::moveChar( KateViewInternal::Bias bias, bool sel )
01046 {
01047 KTextEditor::Cursor c;
01048 if ( m_view->wrapCursor() ) {
01049 c = WrappingCursor( this, m_cursor ) += bias;
01050 } else {
01051 c = BoundedCursor( this, m_cursor ) += bias;
01052 }
01053
01054 updateSelection( c, sel );
01055 updateCursor( c );
01056 }
01057
01058 void KateViewInternal::cursorLeft( bool sel )
01059 {
01060 QMutexLocker l(m_doc->smartMutex());
01061
01062 if ( ! m_view->wrapCursor() && m_cursor.column() == 0 )
01063 return;
01064
01065 moveChar( KateViewInternal::left, sel );
01066 }
01067
01068 void KateViewInternal::cursorRight( bool sel )
01069 {
01070 QMutexLocker l(m_doc->smartMutex());
01071
01072 moveChar( KateViewInternal::right, sel );
01073 }
01074
01075 void KateViewInternal::wordLeft ( bool sel )
01076 {
01077 WrappingCursor c( this, m_cursor );
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087 KateHighlighting* h = m_doc->highlight();
01088 if( !c.atEdge( left ) ) {
01089
01090 while( !c.atEdge( left ) && m_doc->line( c.line() )[ c.column() - 1 ].isSpace() )
01091 --c;
01092 }
01093 if( c.atEdge( left ) )
01094 {
01095 --c;
01096 }
01097 else if( h->isInWord( m_doc->line( c.line() )[ c.column() - 1 ] ) )
01098 {
01099 while( !c.atEdge( left ) && h->isInWord( m_doc->line( c.line() )[ c.column() - 1 ] ) )
01100 --c;
01101 }
01102 else
01103 {
01104 while( !c.atEdge( left )
01105 && !h->isInWord( m_doc->line( c.line() )[ c.column() - 1 ] )
01106
01107
01108 && !m_doc->line( c.line() )[ c.column() - 1 ].isSpace() )
01109 {
01110 --c;
01111 }
01112 }
01113
01114 updateSelection( c, sel );
01115 updateCursor( c );
01116 }
01117
01118 void KateViewInternal::wordRight( bool sel )
01119 {
01120 WrappingCursor c( this, m_cursor );
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130 KateHighlighting* h = m_doc->highlight();
01131 if( c.atEdge( right ) )
01132 {
01133 ++c;
01134 }
01135 else if( h->isInWord( m_doc->line( c.line() )[ c.column() ] ) )
01136 {
01137 while( !c.atEdge( right ) && h->isInWord( m_doc->line( c.line() )[ c.column() ] ) )
01138 ++c;
01139 }
01140 else
01141 {
01142 while( !c.atEdge( right )
01143 && !h->isInWord( m_doc->line( c.line() )[ c.column() ] )
01144
01145
01146 && !m_doc->line( c.line() )[ c.column() ].isSpace() )
01147 {
01148 ++c;
01149 }
01150 }
01151
01152 while( !c.atEdge( right ) && m_doc->line( c.line() )[ c.column() ].isSpace() )
01153 ++c;
01154
01155 updateSelection( c, sel );
01156 updateCursor( c );
01157 }
01158
01159 void KateViewInternal::moveEdge( KateViewInternal::Bias bias, bool sel )
01160 {
01161 BoundedCursor c( this, m_cursor );
01162 c.toEdge( bias );
01163 updateSelection( c, sel );
01164 updateCursor( c );
01165 }
01166
01167 void KateViewInternal::home( bool sel )
01168 {
01169 if (m_view->dynWordWrap() && currentLayout().startCol()) {
01170
01171 if (m_cursor.column() != currentLayout().startCol()) {
01172 KTextEditor::Cursor c = currentLayout().start();
01173 updateSelection( c, sel );
01174 updateCursor( c );
01175 return;
01176 }
01177 }
01178
01179 if( !(m_doc->config()->configFlags() & KateDocumentConfig::cfSmartHome) ) {
01180 moveEdge( left, sel );
01181 return;
01182 }
01183
01184 KateTextLine::Ptr l = m_doc->kateTextLine( m_cursor.line() );
01185
01186 if (!l)
01187 return;
01188
01189 KTextEditor::Cursor c = m_cursor;
01190 int lc = l->firstChar();
01191
01192 if( lc < 0 || c.column() == lc ) {
01193 c.setColumn(0);
01194 } else {
01195 c.setColumn(lc);
01196 }
01197
01198 updateSelection( c, sel );
01199 updateCursor( c, true );
01200 }
01201
01202 void KateViewInternal::end( bool sel )
01203 {
01204 if (m_view->isCompletionActive()) {
01205 view()->completionWidget()->bottom();
01206 return;
01207 }
01208
01209 QMutexLocker lock(m_doc->smartMutex());
01210
01211 KateTextLayout layout = currentLayout();
01212
01213 if (m_view->dynWordWrap() && layout.wrap()) {
01214
01215 if (m_cursor.column() < layout.endCol() - 1) {
01216 KTextEditor::Cursor c(m_cursor.line(), layout.endCol() - 1);
01217 updateSelection( c, sel );
01218 updateCursor( c );
01219 return;
01220 }
01221 }
01222
01223 if( !(m_doc->config()->configFlags() & KateDocumentConfig::cfSmartHome) ) {
01224 moveEdge( right, sel );
01225 return;
01226 }
01227
01228 KateTextLine::Ptr l = m_doc->kateTextLine( m_cursor.line() );
01229
01230 if (!l)
01231 return;
01232
01233
01234 if (m_cursor.column() == m_doc->lineLength(m_cursor.line())) {
01235 KTextEditor::Cursor c = m_cursor;
01236 c.setColumn(l->lastChar() + 1);
01237 updateSelection(c, sel);
01238 updateCursor(c, true);
01239 } else {
01240 moveEdge(right, sel);
01241 }
01242 }
01243
01244 KateTextLayout KateViewInternal::currentLayout() const
01245 {
01246 return cache()->textLayout(m_cursor);
01247 }
01248
01249 KateTextLayout KateViewInternal::previousLayout() const
01250 {
01251 int currentViewLine = cache()->viewLine(m_cursor);
01252
01253 if (currentViewLine)
01254 return cache()->textLayout(m_cursor.line(), currentViewLine - 1);
01255 else
01256 return cache()->textLayout(m_doc->getRealLine(m_displayCursor.line() - 1), -1);
01257 }
01258
01259 KateTextLayout KateViewInternal::nextLayout() const
01260 {
01261 int currentViewLine = cache()->viewLine(m_cursor) + 1;
01262
01263 if (currentViewLine >= cache()->line(m_cursor.line())->viewLineCount()) {
01264 currentViewLine = 0;
01265 return cache()->textLayout(m_doc->getRealLine(m_displayCursor.line() + 1), currentViewLine);
01266 } else {
01267 return cache()->textLayout(m_cursor.line(), currentViewLine);
01268 }
01269 }
01270
01271
01272
01273
01274
01275
01276
01277
01278 KTextEditor::Cursor KateViewInternal::viewLineOffset(const KTextEditor::Cursor& virtualCursor, int offset, bool keepX)
01279 {
01280 if (!m_view->dynWordWrap()) {
01281 KTextEditor::Cursor ret(qMin((int)m_doc->visibleLines() - 1, virtualCursor.line() + offset), 0);
01282
01283 if (ret.line() < 0)
01284 ret.setLine(0);
01285
01286 if (keepX) {
01287 int realLine = m_doc->getRealLine(ret.line());
01288 KateTextLayout t = cache()->textLayout(realLine, 0);
01289 Q_ASSERT(t.isValid());
01290
01291 if (m_currentMaxX > m_cursorX)
01292 m_cursorX = m_currentMaxX;
01293
01294 ret.setColumn(renderer()->xToCursor(t, m_cursorX, !m_view->wrapCursor()).column());
01295 }
01296
01297 return ret;
01298 }
01299
01300 KTextEditor::Cursor realCursor = virtualCursor;
01301 realCursor.setLine(m_doc->getRealLine(virtualCursor.line()));
01302
01303 int cursorViewLine = cache()->viewLine(realCursor);
01304
01305 int currentOffset = 0;
01306 int virtualLine = 0;
01307
01308 bool forwards = (offset > 0) ? true : false;
01309
01310 if (forwards) {
01311 currentOffset = cache()->lastViewLine(realCursor.line()) - cursorViewLine;
01312 if (offset <= currentOffset) {
01313
01314 KateTextLayout thisLine = cache()->textLayout(realCursor.line(), cursorViewLine + offset);
01315 Q_ASSERT(thisLine.virtualLine() == virtualCursor.line());
01316 return KTextEditor::Cursor(virtualCursor.line(), thisLine.startCol());
01317 }
01318
01319 virtualLine = virtualCursor.line() + 1;
01320
01321 } else {
01322 offset = -offset;
01323 currentOffset = cursorViewLine;
01324 if (offset <= currentOffset) {
01325
01326 KateTextLayout thisLine = cache()->textLayout(realCursor.line(), cursorViewLine - offset);
01327 Q_ASSERT(thisLine.virtualLine() == virtualCursor.line());
01328 return KTextEditor::Cursor(virtualCursor.line(), thisLine.startCol());
01329 }
01330
01331 virtualLine = virtualCursor.line() - 1;
01332 }
01333
01334 currentOffset++;
01335
01336 while (virtualLine >= 0 && virtualLine < (int)m_doc->visibleLines())
01337 {
01338 int realLine = m_doc->getRealLine(virtualLine);
01339 KateLineLayoutPtr thisLine = cache()->line(realLine, virtualLine);
01340 if (!thisLine)
01341 break;
01342
01343 for (int i = 0; i < thisLine->viewLineCount(); ++i) {
01344 if (offset == currentOffset) {
01345 KateTextLayout thisViewLine = thisLine->viewLine(i);
01346
01347 if (!forwards) {
01348
01349 int requiredViewLine = cache()->lastViewLine(realLine) - thisViewLine.viewLine();
01350 if (requiredViewLine != thisViewLine.viewLine()) {
01351 thisViewLine = thisLine->viewLine(requiredViewLine);
01352 }
01353 }
01354
01355 KTextEditor::Cursor ret(virtualLine, thisViewLine.startCol());
01356
01357
01358 if (keepX) {
01359 KTextEditor::Cursor realCursor = toRealCursor(virtualCursor);
01360 KateTextLayout t = cache()->textLayout(realCursor);
01361 m_cursorX = renderer()->cursorToX(t, realCursor);
01362
01363 if (m_currentMaxX > m_cursorX) {
01364 m_cursorX = m_currentMaxX;
01365 }
01366
01367 realCursor = renderer()->xToCursor(thisViewLine, m_cursorX, !m_view->wrapCursor());
01368 ret.setColumn(realCursor.column());
01369 }
01370
01371 return ret;
01372 }
01373
01374 currentOffset++;
01375 }
01376
01377 if (forwards)
01378 virtualLine++;
01379 else
01380 virtualLine--;
01381 }
01382
01383
01384
01385 if (forwards)
01386 return KTextEditor::Cursor(m_doc->visibleLines() - 1, m_doc->lineLength(m_doc->getRealLine (m_doc->visibleLines() - 1)));
01387 else
01388 return KTextEditor::Cursor(0, 0);
01389 }
01390
01391 int KateViewInternal::lineMaxCursorX(const KateTextLayout& range)
01392 {
01393 if (!m_view->wrapCursor() && !range.wrap())
01394 return INT_MAX;
01395
01396 int maxX = range.endX();
01397
01398 if (maxX && range.wrap()) {
01399 QChar lastCharInLine = m_doc->kateTextLine(range.line())->at(range.endCol() - 1);
01400 maxX -= renderer()->config()->fontMetrics().width(lastCharInLine);
01401 }
01402
01403 return maxX;
01404 }
01405
01406 int KateViewInternal::lineMaxCol(const KateTextLayout& range)
01407 {
01408 int maxCol = range.endCol();
01409
01410 if (maxCol && range.wrap())
01411 maxCol--;
01412
01413 return maxCol;
01414 }
01415
01416 void KateViewInternal::cursorUp(bool sel)
01417 {
01418 if(!sel && m_view->completionWidget()->isCompletionActive()) {
01419 m_view->completionWidget()->cursorUp();
01420 return;
01421 }
01422
01423 QMutexLocker l(m_doc->smartMutex());
01424
01425 if (m_displayCursor.line() == 0 && (!m_view->dynWordWrap() || cache()->viewLine(m_cursor) == 0))
01426 return;
01427
01428 m_preserveMaxX = true;
01429
01430 KateTextLayout thisLine = currentLayout();
01431
01432 KateTextLayout pRange = previousLayout();
01433
01434
01435 Q_ASSERT(m_cursor.line() == thisLine.line());
01436 Q_ASSERT(m_cursor.column() >= thisLine.startCol());
01437 Q_ASSERT(!thisLine.wrap() || m_cursor.column() < thisLine.endCol());
01438
01439
01440 m_cursorX = renderer()->cursorToX(thisLine, m_cursor);
01441
01442 if (m_currentMaxX > m_cursorX)
01443 m_cursorX = m_currentMaxX;
01444
01445 KTextEditor::Cursor c = renderer()->xToCursor(pRange, m_cursorX, !m_view->wrapCursor());
01446
01447 updateSelection( c, sel );
01448 updateCursor( c );
01449 }
01450
01451 void KateViewInternal::cursorDown(bool sel)
01452 {
01453 if(!sel && m_view->completionWidget()->isCompletionActive()) {
01454 m_view->completionWidget()->cursorDown();
01455 return;
01456 }
01457
01458 QMutexLocker l(m_doc->smartMutex());
01459
01460 if ((m_displayCursor.line() >= m_doc->numVisLines() - 1) && (!m_view->dynWordWrap() || cache()->viewLine(m_cursor) == cache()->lastViewLine(m_cursor.line())))
01461 return;
01462
01463 m_preserveMaxX = true;
01464
01465 KateTextLayout thisLine = currentLayout();
01466
01467 KateTextLayout nRange = nextLayout();
01468
01469
01470 Q_ASSERT((m_cursor.line() == thisLine.line()) &&
01471 (m_cursor.column() >= thisLine.startCol()) &&
01472 (!thisLine.wrap() || m_cursor.column() < thisLine.endCol()));
01473
01474
01475 m_cursorX = renderer()->cursorToX(thisLine, m_cursor);
01476
01477 if (m_currentMaxX > m_cursorX)
01478 m_cursorX = m_currentMaxX;
01479
01480 KTextEditor::Cursor c = renderer()->xToCursor(nRange, m_cursorX, !m_view->wrapCursor());
01481
01482 updateSelection(c, sel);
01483 updateCursor(c);
01484 }
01485
01486 void KateViewInternal::cursorToMatchingBracket( bool sel )
01487 {
01488 KTextEditor::Cursor c = findMatchingBracket();
01489
01490 if (c.isValid()) {
01491 updateSelection( c, sel );
01492 updateCursor( c );
01493 }
01494 }
01495
01496 void KateViewInternal::topOfView( bool sel )
01497 {
01498 KTextEditor::Cursor c = viewLineOffset(startPos(), m_minLinesVisible);
01499 updateSelection( c, sel );
01500 updateCursor( c );
01501 }
01502
01503 void KateViewInternal::bottomOfView( bool sel )
01504 {
01505
01506 KTextEditor::Cursor c = viewLineOffset(endPos(), -m_minLinesVisible);
01507 updateSelection( c, sel );
01508 updateCursor( c );
01509 }
01510
01511
01512 void KateViewInternal::scrollLines( int lines, bool sel )
01513 {
01514 KTextEditor::Cursor c = viewLineOffset(m_displayCursor, lines, true);
01515
01516
01517 c.setLine(m_doc->getRealLine(c.line()));
01518
01519 updateSelection( c, sel );
01520 updateCursor( c );
01521 }
01522
01523
01524 void KateViewInternal::scrollUp()
01525 {
01526 KTextEditor::Cursor newPos = viewLineOffset(startPos(), -1);
01527 scrollPos(newPos);
01528 }
01529
01530 void KateViewInternal::scrollDown()
01531 {
01532 KTextEditor::Cursor newPos = viewLineOffset(startPos(), 1);
01533 scrollPos(newPos);
01534 }
01535
01536 void KateViewInternal::setAutoCenterLines(int viewLines, bool updateView)
01537 {
01538 m_autoCenterLines = viewLines;
01539 m_minLinesVisible = qMin(int((linesDisplayed() - 1)/2), m_autoCenterLines);
01540 if (updateView)
01541 KateViewInternal::updateView();
01542 }
01543
01544 void KateViewInternal::pageUp( bool sel )
01545 {
01546 if (m_view->isCompletionActive()) {
01547 view()->completionWidget()->pageUp();
01548 return;
01549 }
01550
01551 QMutexLocker l(m_doc->smartMutex());
01552
01553
01554 int viewLine = cache()->displayViewLine(m_displayCursor);
01555 bool atTop = startPos().atStartOfDocument();
01556
01557
01558 int lineadj = 2 * m_minLinesVisible;
01559 int cursorStart = (linesDisplayed() - 1) - viewLine;
01560 if (cursorStart < m_minLinesVisible)
01561 lineadj -= m_minLinesVisible - cursorStart;
01562
01563 int linesToScroll = -qMax( (linesDisplayed() - 1) - lineadj, 0 );
01564 m_preserveMaxX = true;
01565
01566 if (!m_doc->pageUpDownMovesCursor () && !atTop) {
01567 m_cursorX = renderer()->cursorToX(currentLayout(), m_cursor);
01568
01569 KTextEditor::Cursor newStartPos = viewLineOffset(startPos(), linesToScroll - 1);
01570 scrollPos(newStartPos);
01571
01572
01573 KTextEditor::Cursor newPos = toRealCursor(viewLineOffset(newStartPos, viewLine, true));
01574
01575 KateTextLayout newLine = cache()->textLayout(newPos);
01576
01577 if (m_currentMaxX> m_cursorX)
01578 m_cursorX = m_currentMaxX;
01579
01580 newPos = renderer()->xToCursor(newLine, m_cursorX, !view()->wrapCursor());
01581
01582 m_preserveMaxX = true;
01583 updateSelection( newPos, sel );
01584 updateCursor(newPos);
01585
01586 } else {
01587 scrollLines( linesToScroll, sel );
01588 }
01589 }
01590
01591 void KateViewInternal::pageDown( bool sel )
01592 {
01593 if (m_view->isCompletionActive()) {
01594 view()->completionWidget()->pageDown();
01595 return;
01596 }
01597
01598 QMutexLocker l(m_doc->smartMutex());
01599
01600
01601 int viewLine = cache()->displayViewLine(m_displayCursor);
01602 bool atEnd = startPos() >= m_cachedMaxStartPos;
01603
01604
01605 int lineadj = 2 * m_minLinesVisible;
01606 int cursorStart = m_minLinesVisible - viewLine;
01607 if (cursorStart > 0)
01608 lineadj -= cursorStart;
01609
01610 int linesToScroll = qMax( (linesDisplayed() - 1) - lineadj, 0 );
01611 m_preserveMaxX = true;
01612
01613 if (!m_doc->pageUpDownMovesCursor () && !atEnd) {
01614 m_cursorX = renderer()->cursorToX(currentLayout(), m_cursor);
01615
01616 KTextEditor::Cursor newStartPos = viewLineOffset(startPos(), linesToScroll + 1);
01617 scrollPos(newStartPos);
01618
01619
01620 KTextEditor::Cursor newPos = toRealCursor(viewLineOffset(newStartPos, viewLine, true));
01621
01622 KateTextLayout newLine = cache()->textLayout(newPos);
01623
01624 if (m_currentMaxX> m_cursorX)
01625 m_cursorX = m_currentMaxX;
01626
01627 newPos = renderer()->xToCursor(newLine, m_cursorX, !view()->wrapCursor());
01628
01629 m_preserveMaxX = true;
01630 updateSelection( newPos, sel );
01631 updateCursor(newPos);
01632
01633 } else {
01634 scrollLines( linesToScroll, sel );
01635 }
01636 }
01637
01638 int KateViewInternal::maxLen(int startLine)
01639 {
01640 Q_ASSERT(!m_view->dynWordWrap());
01641
01642 int displayLines = (m_view->height() / renderer()->fontHeight()) + 1;
01643
01644 int maxLen = 0;
01645
01646 for (int z = 0; z < displayLines; z++) {
01647 int virtualLine = startLine + z;
01648
01649 if (virtualLine < 0 || virtualLine >= (int)m_doc->visibleLines())
01650 break;
01651
01652 maxLen = qMax(maxLen, cache()->line(m_doc->getRealLine(virtualLine))->width());
01653 }
01654
01655 return maxLen;
01656 }
01657
01658 bool KateViewInternal::columnScrollingPossible ()
01659 {
01660 return !m_view->dynWordWrap() && m_columnScroll->isEnabled() && (m_columnScroll->maximum() > 0);
01661 }
01662
01663 void KateViewInternal::top( bool sel )
01664 {
01665 m_cursorX = renderer()->cursorToX(currentLayout(), m_cursor);
01666
01667 KTextEditor::Cursor newCursor(0, 0);
01668
01669 if (m_currentMaxX > m_cursorX)
01670 m_cursorX = m_currentMaxX;
01671
01672 newCursor = renderer()->xToCursor(cache()->textLayout(newCursor), m_cursorX, !view()->wrapCursor());
01673
01674 updateSelection( newCursor, sel );
01675 updateCursor( newCursor );
01676 }
01677
01678 void KateViewInternal::bottom( bool sel )
01679 {
01680 KTextEditor::Cursor newCursor(m_doc->lastLine(), 0);
01681
01682 if (m_currentMaxX > m_cursorX)
01683 m_cursorX = m_currentMaxX;
01684
01685 newCursor = renderer()->xToCursor(cache()->textLayout(newCursor), m_cursorX, !view()->wrapCursor());
01686
01687 updateSelection( newCursor, sel );
01688 updateCursor( newCursor );
01689 }
01690
01691 void KateViewInternal::top_home( bool sel )
01692 {
01693 if (m_view->isCompletionActive()) {
01694 view()->completionWidget()->top();
01695 return;
01696 }
01697
01698 QMutexLocker l(m_doc->smartMutex());
01699
01700 KTextEditor::Cursor c( 0, 0 );
01701 updateSelection( c, sel );
01702 updateCursor( c );
01703 }
01704
01705 void KateViewInternal::bottom_end( bool sel )
01706 {
01707 if (m_view->isCompletionActive()) {
01708 view()->completionWidget()->bottom();
01709 return;
01710 }
01711
01712 QMutexLocker l(m_doc->smartMutex());
01713
01714 KTextEditor::Cursor c( m_doc->lastLine(), m_doc->lineLength( m_doc->lastLine() ) );
01715 updateSelection( c, sel );
01716 updateCursor( c );
01717 }
01718
01719 void KateViewInternal::updateSelection( const KTextEditor::Cursor& _newCursor, bool keepSel )
01720 {
01721 KTextEditor::Cursor newCursor = _newCursor;
01722 if( keepSel )
01723 {
01724 if ( !m_view->selection() || (m_selectAnchor.line() == -1)
01725
01726
01727 || (m_view->config()->persistentSelection()
01728 && !(m_view->selectionRange().contains(m_cursor)
01729 || m_view->selectionRange().boundaryAtCursor(m_cursor))) )
01730 {
01731 m_selectAnchor = m_cursor;
01732 m_view->setSelection( KTextEditor::Range(m_cursor, newCursor) );
01733 }
01734 else
01735 {
01736 bool doSelect = true;
01737 switch (m_selectionMode)
01738 {
01739 case Word:
01740 {
01741
01742
01743
01744
01745
01746
01747
01748 if ( !m_selectionCached.isValid() )
01749 m_selectionCached.start() = m_selectionCached.end();
01750
01751 int c;
01752 if ( newCursor > m_selectionCached.start() )
01753 {
01754 m_selectAnchor = m_selectionCached.start();
01755
01756 KateTextLine::Ptr l = m_doc->kateTextLine( newCursor.line() );
01757
01758 c = newCursor.column();
01759 if ( c > 0 && m_doc->highlight()->isInWord( l->at( c-1 ) ) ) {
01760 for ( ; c < l->length(); c++ )
01761 if ( !m_doc->highlight()->isInWord( l->at( c ) ) )
01762 break;
01763 }
01764
01765 newCursor.setColumn( c );
01766 }
01767 else if ( newCursor < m_selectionCached.start() )
01768 {
01769 m_selectAnchor = m_selectionCached.end();
01770
01771 KateTextLine::Ptr l = m_doc->kateTextLine( newCursor.line() );
01772
01773 c = newCursor.column();
01774 if ( c > 0 && c < m_doc->lineLength( newCursor.line() )
01775 && m_doc->highlight()->isInWord( l->at( c ) )
01776 && m_doc->highlight()->isInWord( l->at( c-1 ) ) ) {
01777 for ( c -= 2; c >= 0; c-- )
01778 if ( !m_doc->highlight()->isInWord( l->at( c ) ) )
01779 break;
01780 newCursor.setColumn( c+1 );
01781 }
01782 }
01783 else
01784 doSelect = false;
01785
01786 }
01787 break;
01788 case Line:
01789 if ( newCursor.line() > m_selectionCached.start().line() )
01790 {
01791 if (newCursor.line() + 1 >= m_doc->lines() )
01792 newCursor.setColumn( m_doc->line( newCursor.line() ).length() );
01793 else
01794 newCursor.setPosition( newCursor.line() + 1, 0 );
01795
01796 m_selectAnchor = m_selectionCached.start();
01797 m_selectAnchor.setColumn( 0 );
01798 }
01799 else if ( newCursor.line() < m_selectionCached.start().line() )
01800 {
01801 newCursor.setColumn( 0 );
01802
01803 m_selectAnchor = m_selectionCached.end();
01804 if ( m_selectAnchor.column() > 0 )
01805 {
01806 if ( m_selectAnchor.line()+1 >= m_doc->lines() )
01807 m_selectAnchor.setColumn( m_doc->line( newCursor.line() ).length() );
01808 else
01809 m_selectAnchor.setPosition( m_selectAnchor.line() + 1, 0 );
01810 }
01811 }
01812 else
01813 doSelect = false;
01814 break;
01815 case Mouse:
01816 {
01817 if ( !m_selectionCached.isValid() )
01818 break;
01819
01820 if ( newCursor > m_selectionCached.end() )
01821 m_selectAnchor = m_selectionCached.start();
01822 else if ( newCursor < m_selectionCached.start() )
01823 m_selectAnchor = m_selectionCached.end();
01824 else
01825 doSelect = false;
01826 }
01827 break;
01828 default: ;
01829 }
01830
01831 if ( doSelect )
01832 m_view->setSelection( KTextEditor::Range(m_selectAnchor, newCursor) );
01833 else if ( m_selectionCached.isValid() )
01834 m_view->setSelection( m_selectionCached );
01835 }
01836
01837 m_selChangedByUser = true;
01838 }
01839 else if ( !m_view->config()->persistentSelection() )
01840 {
01841 m_view->clearSelection();
01842
01843 m_selectionCached = KTextEditor::Range::invalid();
01844 }
01845 }
01846
01847 void KateViewInternal::updateCursor( const KTextEditor::Cursor& newCursor, bool force, bool center, bool calledExternally )
01848 {
01849 if ( !force && (m_cursor == newCursor) )
01850 {
01851 if ( !m_madeVisible && m_view == m_doc->activeView() )
01852 {
01853
01854 m_doc->foldingTree()->ensureVisible( newCursor.line() );
01855
01856 makeVisible ( m_displayCursor, m_displayCursor.column(), false, center, calledExternally );
01857 }
01858
01859 return;
01860 }
01861
01862
01863 m_doc->foldingTree()->ensureVisible( newCursor.line() );
01864
01865 KTextEditor::Cursor oldDisplayCursor = m_displayCursor;
01866
01867 m_cursor = newCursor;
01868 m_displayCursor = toVirtualCursor(m_cursor);
01869
01870 m_cursorX = renderer()->cursorToX(cache()->textLayout(m_cursor), m_cursor);
01871 if ( m_view == m_doc->activeView() )
01872 makeVisible ( m_displayCursor, m_displayCursor.column(), false, center, calledExternally );
01873
01874 updateBracketMarks();
01875
01876
01877
01878
01879 tagLine(oldDisplayCursor);
01880 tagLine(m_displayCursor);
01881
01882 updateMicroFocus();
01883
01884 if (m_cursorTimer.isActive ())
01885 {
01886 if ( KApplication::cursorFlashTime() > 0 )
01887 m_cursorTimer.start( KApplication::cursorFlashTime() / 2 );
01888 renderer()->setDrawCaret(true);
01889 }
01890
01891
01892 if (m_preserveMaxX)
01893 m_preserveMaxX = false;
01894 else
01895 m_currentMaxX = m_cursorX;
01896
01897
01898
01899
01900 cursorMoved();
01901
01902 if(!m_doc->isEditRunning())
01903 m_doc->setUndoDontMerge(true);
01904
01905 updateDirty();
01906
01908 emit m_view->cursorPositionChanged(m_view, m_cursor);
01909 }
01910
01911 void KateViewInternal::updateBracketMarkAttributes()
01912 {
01913 KTextEditor::Attribute::Ptr bracketFill = KTextEditor::Attribute::Ptr(new KTextEditor::Attribute());
01914 bracketFill->setBackground(m_view->m_renderer->config()->highlightedBracketColor());
01915 bracketFill->setBackgroundFillWhitespace(false);
01916 bracketFill->setFontBold();
01917
01918 m_bmStart->setAttribute(bracketFill);
01919 m_bmEnd->setAttribute(bracketFill);
01920
01921 if (m_view->m_renderer->config()->showWholeBracketExpression()) {
01922
01923 KTextEditor::Attribute::Ptr expressionFill = KTextEditor::Attribute::Ptr(new KTextEditor::Attribute());
01924 expressionFill->setBackground(m_view->m_renderer->config()->highlightedBracketColor());
01925 expressionFill->setBackgroundFillWhitespace(false);
01926
01927 m_bm->setAttribute(expressionFill);
01928 } else {
01929 m_bm->setAttribute(KTextEditor::Attribute::Ptr(new KTextEditor::Attribute()));
01930 }
01931 }
01932
01933 void KateViewInternal::updateBracketMarks()
01934 {
01935 bool showWholeBracketExpression = m_view->m_renderer->config()->showWholeBracketExpression();
01936
01937 QMutexLocker lock(m_doc->smartMutex());
01938 if (m_bmHighlighted) {
01939 view()->removeInternalHighlight(m_bmStart);
01940 view()->removeInternalHighlight(m_bmEnd);
01941 view()->removeInternalHighlight(m_bm);
01942 m_bmHighlighted = false;
01943 }
01944
01945 if ( m_bm->isValid() ) {
01946 tagRange(*m_bmStart, true);
01947 tagRange(*m_bmEnd, true);
01948 tagRange(*m_bm, true);
01949 }
01950
01951
01952 int maxLines = linesDisplayed () * 3;
01953 m_doc->newBracketMark( m_cursor, *m_bm, maxLines );
01954
01955 if ( m_bm->isValid() ) {
01956 m_bmStart->start() = m_bm->start();
01957 m_bmStart->end().setPosition(m_bm->start().line(), m_bm->start().column() + 1);
01958
01959 m_bmEnd->start() = m_bm->end();
01960 m_bmEnd->end().setPosition(m_bm->end().line(), m_bm->end().column() + 1);
01961
01962 tagRange(*m_bmStart, true);
01963 tagRange(*m_bmEnd, true);
01964 if (showWholeBracketExpression) {
01965 tagRange(*m_bm, true);
01966 }
01967
01968 view()->addInternalHighlight(m_bmStart);
01969 view()->addInternalHighlight(m_bmEnd);
01970 if (showWholeBracketExpression) {
01971 view()->addInternalHighlight(m_bm);
01972 }
01973 m_bmHighlighted = true;
01974 }
01975 }
01976
01977 bool KateViewInternal::tagLine(const KTextEditor::Cursor& virtualCursor)
01978 {
01979 QMutexLocker lock(m_doc->smartMutex());
01980
01981 if ((int)m_doc->getRealLine(virtualCursor.line()) > m_doc->lastLine())
01982 return false;
01983
01984
01985 int viewLine = cache()->displayViewLine(virtualCursor, true);
01986 if (viewLine >= 0 && viewLine < cache()->viewCacheLineCount()) {
01987 cache()->viewLine(viewLine).setDirty();
01988 m_leftBorder->update (0, lineToY(viewLine), m_leftBorder->width(), renderer()->fontHeight());
01989 return true;
01990 }
01991 return false;
01992 }
01993
01994 bool KateViewInternal::tagLines( int start, int end, bool realLines )
01995 {
01996 return tagLines(KTextEditor::Cursor(start, 0), KTextEditor::Cursor(end, -1), realLines);
01997 }
01998
01999 bool KateViewInternal::tagLines(KTextEditor::Cursor start, KTextEditor::Cursor end, bool realCursors)
02000 {
02001 QMutexLocker lock(m_doc->smartMutex());
02002 if (realCursors)
02003 {
02004 cache()->relayoutLines(start.line(), end.line());
02005
02006
02007 start = toVirtualCursor(start);
02008 end = toVirtualCursor(end);
02009
02010 } else {
02011 cache()->relayoutLines(toRealCursor(start).line(), toRealCursor(end).line());
02012 }
02013
02014 if (end.line() < startLine())
02015 {
02016
02017 return false;
02018 }
02019
02020
02021 if (start.line() > startLine() + cache()->viewCacheLineCount())
02022 {
02023
02024 return false;
02025 }
02026
02027 cache()->updateViewCache(startPos());
02028
02029
02030
02031 bool ret = false;
02032
02033 for (int z = 0; z < cache()->viewCacheLineCount(); z++)
02034 {
02035 KateTextLayout& line = cache()->viewLine(z);
02036 if ((line.virtualLine() > start.line() || (line.virtualLine() == start.line() && line.endCol() >= start.column() && start.column() != -1)) &&
02037 (line.virtualLine() < end.line() || (line.virtualLine() == end.line() && (line.startCol() <= end.column() || end.column() == -1)))) {
02038 ret = true;
02039 break;
02040
02041 }
02042 }
02043
02044 if (!m_view->dynWordWrap())
02045 {
02046 int y = lineToY( start.line() );
02047
02048 int h = (end.line() - start.line() + 2) * renderer()->fontHeight();
02049 if (end.line() == m_doc->numVisLines() - 1)
02050 h = height();
02051
02052 m_leftBorder->update (0, y, m_leftBorder->width(), h);
02053 }
02054 else
02055 {
02056
02057
02058 for (int z = 0; z < cache()->viewCacheLineCount(); z++)
02059 {
02060 KateTextLayout& line = cache()->viewLine(z);
02061 if (!line.isValid() ||
02062 ((line.virtualLine() > start.line() || (line.virtualLine() == start.line() && line.endCol() >= start.column() && start.column() != -1)) &&
02063 (line.virtualLine() < end.line() || (line.virtualLine() == end.line() && (line.startCol() <= end.column() || end.column() == -1)))))
02064 {
02065
02066 m_leftBorder->update (0, z * renderer()->fontHeight(), m_leftBorder->width(), m_leftBorder->height());
02067 break;
02068 }
02069
02070
02071
02072
02073
02074
02075 }
02076 }
02077
02078 return ret;
02079 }
02080
02081 bool KateViewInternal::tagRange(const KTextEditor::Range& range, bool realCursors)
02082 {
02083 return tagLines(range.start(), range.end(), realCursors);
02084 }
02085
02086 void KateViewInternal::tagAll()
02087 {
02088 QMutexLocker lock(m_doc->smartMutex());
02089
02090
02091 cache()->clear ();
02092
02093 m_leftBorder->updateFont();
02094 m_leftBorder->update();
02095 }
02096
02097 void KateViewInternal::paintCursor()
02098 {
02099 if (tagLine(m_displayCursor))
02100 updateDirty();
02101 }
02102
02103
02104 void KateViewInternal::placeCursor( const QPoint& p, bool keepSelection, bool updateSelection )
02105 {
02106 KateTextLayout thisLine = yToKateTextLayout(p.y());
02107 KTextEditor::Cursor c;
02108
02109 if (!thisLine.isValid())
02110 thisLine = cache()->textLayout(m_doc->lines() - 1, -1);
02111
02112 c = renderer()->xToCursor(thisLine, startX() + p.x(), !view()->wrapCursor());
02113
02114 if (c.line () < 0 || c.line() >= m_doc->lines()) {
02115 return;
02116 }
02117 if (updateSelection)
02118 KateViewInternal::updateSelection( c, keepSelection );
02119
02120 updateCursor( c );
02121 }
02122
02123
02124 bool KateViewInternal::isTargetSelected( const QPoint& p )
02125 {
02126 const KateTextLayout& thisLine = yToKateTextLayout(p.y());
02127 if (!thisLine.isValid())
02128 return false;
02129
02130 return m_view->cursorSelected(renderer()->xToCursor(thisLine, startX() + p.x(), !view()->wrapCursor()));
02131 }
02132
02133
02134
02135 bool KateViewInternal::eventFilter( QObject *obj, QEvent *e )
02136 {
02137 if (obj == m_lineScroll)
02138 {
02139
02140 if (e->type() == QEvent::Wheel && m_lineScroll->minimum() != m_lineScroll->maximum())
02141 {
02142 wheelEvent((QWheelEvent*)e);
02143 return true;
02144 }
02145
02146
02147 return QWidget::eventFilter( obj, e );
02148 }
02149
02150 switch( e->type() )
02151 {
02152 case QEvent::ChildAdded:
02153 case QEvent::ChildRemoved: {
02154 QChildEvent* c = static_cast<QChildEvent*>(e);
02155 if (c->added()) {
02156 c->child()->installEventFilter(this);
02157
02158
02159
02160 } else if (c->removed()) {
02161 c->child()->removeEventFilter(this);
02162
02163
02164
02165 }
02166 } break;
02167
02168 case QEvent::ShortcutOverride:
02169 {
02170 QKeyEvent *k = static_cast<QKeyEvent *>(e);
02171
02172 if (k->key() == Qt::Key_Escape) {
02173 if (m_view->isCompletionActive()) {
02174 m_view->abortCompletion();
02175 k->accept();
02176
02177 return true;
02178 } else if (m_view->viewBar()->isVisible()) {
02179 m_view->viewBar()->hideCurrentBarWidget();
02180 k->accept();
02181
02182 return true;
02183 } else if (!m_view->config()->persistentSelection() && m_view->selection()) {
02184 m_view->clearSelection();
02185 k->accept();
02186
02187 return true;
02188 }
02189 }
02190
02191
02192 if (m_view->viInputMode() && m_view->viInputModeStealKeys() && ( m_view->getCurrentViMode() != InsertMode ||
02193 ( m_view->getCurrentViMode() == InsertMode && k->modifiers() == Qt::ControlModifier ) ) ) {
02194 k->accept();
02195 return true;
02196 }
02197
02198 } break;
02199
02200 case QEvent::KeyPress:
02201 {
02202 QKeyEvent *k = static_cast<QKeyEvent *>(e);
02203
02204
02205 if (obj == this && (!k->modifiers() || k->modifiers() == Qt::ShiftModifier)) {
02206 keyPressEvent( k );
02207 if (k->isAccepted()) {
02208
02209 return true;
02210 }
02211 }
02212
02213
02214 } break;
02215
02216 case QEvent::DragMove:
02217 {
02218 QPoint currentPoint = ((QDragMoveEvent*) e)->pos();
02219
02220 QRect doNotScrollRegion( s_scrollMargin, s_scrollMargin,
02221 width() - s_scrollMargin * 2,
02222 height() - s_scrollMargin * 2 );
02223
02224 if ( !doNotScrollRegion.contains( currentPoint ) )
02225 {
02226 startDragScroll();
02227
02228 ( (QDragMoveEvent*)e )->accept( QRect(0,0,0,0) );
02229 }
02230
02231 dragMoveEvent((QDragMoveEvent*)e);
02232 } break;
02233
02234 case QEvent::DragLeave:
02235
02236 stopDragScroll();
02237 break;
02238
02239 case QEvent::WindowBlocked:
02240
02241
02242 m_doc->ignoreModifiedOnDiskOnce();
02243 break;
02244
02245 default:
02246 break;
02247 }
02248
02249 return QWidget::eventFilter( obj, e );
02250 }
02251
02252 void KateViewInternal::keyPressEvent( QKeyEvent* e )
02253 {
02254 if( e->key() == Qt::Key_Left && e->modifiers() == Qt::AltModifier ) {
02255 m_view->emitNavigateLeft();
02256 e->setAccepted(true);
02257 return;
02258 }
02259 if( e->key() == Qt::Key_Right && e->modifiers() == Qt::AltModifier ) {
02260 m_view->emitNavigateRight();
02261 e->setAccepted(true);
02262 return;
02263 }
02264 if( e->key() == Qt::Key_Up && e->modifiers() == Qt::AltModifier ) {
02265 m_view->emitNavigateUp();
02266 e->setAccepted(true);
02267 return;
02268 }
02269 if( e->key() == Qt::Key_Down && e->modifiers() == Qt::AltModifier ) {
02270 m_view->emitNavigateDown();
02271 e->setAccepted(true);
02272 return;
02273 }
02274 if( e->key() == Qt::Key_Return && e->modifiers() == Qt::AltModifier ) {
02275 m_view->emitNavigateAccept();
02276 e->setAccepted(true);
02277 return;
02278 }
02279 if( e->key() == Qt::Key_Backspace && e->modifiers() == Qt::AltModifier ) {
02280 m_view->emitNavigateBack();
02281 e->setAccepted(true);
02282 return;
02283 }
02284
02285 if( e->key() == Qt::Key_Alt && view()->completionWidget()->isCompletionActive() ) {
02286 m_completionItemExpanded = view()->completionWidget()->toggleExpanded(true);
02287 view()->completionWidget()->resetHadNavigation();
02288 m_altDownTime = QTime::currentTime();
02289 }
02290
02291
02292 const int key = e->key() | (e->modifiers() & Qt::ShiftModifier);
02293
02294 if (m_view->isCompletionActive())
02295 {
02296 if( key == Qt::Key_Enter || key == Qt::Key_Return ) {
02297 m_view->completionWidget()->execute();
02298 e->accept();
02299 return;
02300 }
02301 }
02302
02303 if ( m_view->viInputMode() ) {
02304 if ( !m_view->config()->viInputModeHideStatusBar() ) {
02305 m_view->viModeBar()->clearMessage();
02306 }
02307
02308 if ( getViInputModeManager()->getCurrentViMode() == InsertMode ) {
02309 if ( getViInputModeManager()->handleKeypress( e ) ) {
02310 return;
02311 } else if ( e->modifiers() != Qt::NoModifier && e->modifiers() != Qt::ShiftModifier ) {
02312
02313 QEvent *copy = new QKeyEvent ( e->type(), e->key(), e->modifiers(), e->text(),
02314 e->isAutoRepeat(), e->count() );
02315 QCoreApplication::postEvent( parent(), copy );
02316 }
02317 } else {
02318 if ( !getViInputModeManager()->handleKeypress( e ) ) {
02319
02320 QEvent *copy = new QKeyEvent ( e->type(), e->key(), e->modifiers(), e->text(),
02321 e->isAutoRepeat(), e->count() );
02322 QCoreApplication::postEvent( parent(), copy );
02323 }
02324 m_view->updateViModeBarCmd();
02325 return;
02326 }
02327 }
02328
02329 if( !m_doc->isReadWrite() )
02330 {
02331 e->ignore();
02332 return;
02333 }
02334
02335 if ((key == Qt::Key_Return) || (key == Qt::Key_Enter))
02336 {
02337 doReturn();
02338 e->accept();
02339 return;
02340 }
02341
02342 if (key == Qt::Key_Backspace || key == Qt::SHIFT + Qt::Key_Backspace)
02343 {
02344
02345 e->accept();
02346
02347 return;
02348 }
02349
02350 if (key == Qt::Key_Tab || key == Qt::SHIFT+Qt::Key_Backtab || key == Qt::Key_Backtab)
02351 {
02352 if (m_doc->invokeTabInterceptor(key)) {
02353 e->accept();
02354 return;
02355 }
02356
02357 if( key == Qt::Key_Tab )
02358 {
02359 uint tabHandling = m_doc->config()->tabHandling();
02360
02361 if (tabHandling == KateDocumentConfig::tabSmart)
02362 {
02363 if (m_view->selection())
02364 {
02365 tabHandling = KateDocumentConfig::tabIndents;
02366 }
02367 else
02368 {
02369
02370
02371
02372 KateTextLine::Ptr line = m_doc->kateTextLine( m_cursor.line() );
02373 int first = line->firstChar();
02374 if (first < 0 || m_cursor.column() <= first)
02375 tabHandling = KateDocumentConfig::tabIndents;
02376 else
02377 tabHandling = KateDocumentConfig::tabInsertsTab;
02378 }
02379 }
02380
02381 if (tabHandling == KateDocumentConfig::tabInsertsTab)
02382 m_doc->typeChars( m_view, QString("\t") );
02383 else
02384 m_doc->indent( m_view, m_cursor.line(), 1 );
02385
02386 e->accept();
02387
02388 return;
02389 }
02390 else if (m_doc->config()->tabHandling() != KateDocumentConfig::tabInsertsTab)
02391 {
02392
02393 m_doc->indent( m_view, m_cursor.line(), -1 );
02394 e->accept();
02395
02396 return;
02397 }
02398 }
02399
02400 if ( !(e->modifiers() & Qt::ControlModifier) && !e->text().isEmpty() && m_doc->typeChars ( m_view, e->text() ) )
02401 {
02402 e->accept();
02403
02404 return;
02405 }
02406
02407
02408 static const int altGR = Qt::ControlModifier | Qt::AltModifier;
02409 if( (e->modifiers() & altGR) == altGR && !e->text().isEmpty() && m_doc->typeChars ( m_view, e->text() ) )
02410 {
02411 e->accept();
02412
02413 return;
02414 }
02415
02416 e->ignore();
02417 }
02418
02419 void KateViewInternal::keyReleaseEvent( QKeyEvent* e )
02420 {
02421 if( e->key() == Qt::Key_Alt && view()->completionWidget()->isCompletionActive() && ((m_completionItemExpanded && (view()->completionWidget()->hadNavigation() || m_altDownTime.msecsTo(QTime::currentTime()) > 300)) || (!m_completionItemExpanded && !view()->completionWidget()->hadNavigation())) ) {
02422
02423 view()->completionWidget()->toggleExpanded(false, true);
02424 }
02425
02426 if (e->key() == Qt::SHIFT)
02427 {
02428 m_shiftKeyPressed = true;
02429 }
02430 else
02431 {
02432 if (m_shiftKeyPressed)
02433 {
02434 m_shiftKeyPressed = false;
02435
02436 if (m_selChangedByUser)
02437 {
02438 if (m_view->selection())
02439 QApplication::clipboard()->setText(m_view->selectionText (), QClipboard::Selection);
02440
02441 m_selChangedByUser = false;
02442 }
02443 }
02444 }
02445
02446 e->ignore();
02447 return;
02448 }
02449
02450 void KateViewInternal::contextMenuEvent ( QContextMenuEvent * e )
02451 {
02452
02453
02454 QPoint p = e->pos();
02455
02456 if ( m_view->m_doc->browserView() )
02457 {
02458 m_view->contextMenuEvent( e );
02459 return;
02460 }
02461
02462 if ( e->reason() == QContextMenuEvent::Keyboard )
02463 {
02464 makeVisible( m_cursor, 0 );
02465 p = cursorCoordinates();
02466 }
02467 else if ( ! m_view->selection() || m_view->config()->persistentSelection() )
02468 placeCursor( e->pos() );
02469
02470
02471 if (m_view->contextMenu()) {
02472 m_view->contextMenu()->popup( mapToGlobal( p ) );
02473 e->accept ();
02474 }
02475 }
02476
02477 void KateViewInternal::mousePressEvent( QMouseEvent* e )
02478 {
02479 switch (e->button())
02480 {
02481 case Qt::LeftButton:
02482 m_selChangedByUser = false;
02483
02484 if (m_possibleTripleClick)
02485 {
02486 m_possibleTripleClick = false;
02487
02488 m_selectionMode = Line;
02489
02490 if ( e->modifiers() & Qt::ShiftModifier )
02491 {
02492 updateSelection( m_cursor, true );
02493 }
02494 else
02495 {
02496 m_view->selectLine( m_cursor );
02497 }
02498
02499 if (m_view->selection())
02500 QApplication::clipboard()->setText(m_view->selectionText (), QClipboard::Selection);
02501
02502
02503
02504 if ( m_selectAnchor.line() > m_view->selectionRange().start().line() )
02505 {
02506
02507 if ( m_selectAnchor == m_view->selectionRange().end() && m_selectAnchor.column() == 0 )
02508 m_selectionCached.start().setPosition( m_selectAnchor.line()-1, 0 );
02509 else
02510 m_selectionCached.start().setPosition( m_selectAnchor.line(), 0 );
02511 m_selectionCached.end() = m_view->selectionRange().end();
02512 }
02513 else
02514 {
02515
02516 m_selectionCached.start() = m_view->selectionRange().start();
02517 if ( m_view->selectionRange().end().line() > m_view->selectionRange().start().line() )
02518 m_selectionCached.end().setPosition( m_view->selectionRange().start().line()+1, 0 );
02519 else
02520 m_selectionCached.end() = m_view->selectionRange().end();
02521 }
02522
02523
02524
02525 if ( m_view->selectionRange().start() < m_selectAnchor
02526 && m_selectAnchor.line() != m_view->selectionRange().start().line() )
02527 updateCursor( m_view->selectionRange().start() );
02528 else
02529 updateCursor( m_view->selectionRange().end() );
02530
02531 e->accept();
02532 return;
02533 }
02534 else if ( m_selectionMode == Default )
02535 {
02536 m_selectionMode = Mouse;
02537 }
02538
02539 if ( e->modifiers() & Qt::ShiftModifier )
02540 {
02541 if ( !m_selectAnchor.isValid() )
02542 m_selectAnchor = m_cursor;
02543 }
02544 else
02545 {
02546 m_selectionCached = KTextEditor::Range::invalid();
02547 }
02548
02549 if( !(e->modifiers() & Qt::ShiftModifier) && isTargetSelected( e->pos() ) )
02550 {
02551 m_dragInfo.state = diPending;
02552 m_dragInfo.start = e->pos();
02553 }
02554 else
02555 {
02556 m_dragInfo.state = diNone;
02557
02558 if ( e->modifiers() & Qt::ShiftModifier )
02559 {
02560 placeCursor( e->pos(), true, false );
02561 if ( m_selectionCached.start().isValid() )
02562 {
02563 if ( m_cursor < m_selectionCached.start() )
02564 m_selectAnchor = m_selectionCached.end();
02565 else
02566 m_selectAnchor = m_selectionCached.start();
02567 }
02568 m_view->setSelection( KTextEditor::Range( m_selectAnchor, m_cursor ) );
02569 }
02570 else
02571 {
02572 placeCursor( e->pos() );
02573 }
02574
02575 m_scrollX = 0;
02576 m_scrollY = 0;
02577
02578 m_scrollTimer.start (50);
02579 }
02580
02581 e->accept ();
02582 break;
02583
02584 default:
02585 e->ignore ();
02586 break;
02587 }
02588 }
02589
02590 void KateViewInternal::mouseDoubleClickEvent(QMouseEvent *e)
02591 {
02592 switch (e->button())
02593 {
02594 case Qt::LeftButton:
02595 m_selectionMode = Word;
02596
02597 if ( e->modifiers() & Qt::ShiftModifier )
02598 {
02599 KTextEditor::Range oldSelection = m_view->selectionRange();
02600
02601
02602 int cs, ce;
02603 KateTextLine::Ptr l = m_doc->kateTextLine( m_selectAnchor.line() );
02604
02605 ce = m_selectAnchor.column();
02606 if ( ce > 0 && m_doc->highlight()->isInWord( l->at(ce) ) ) {
02607 for (; ce < l->length(); ce++ )
02608 if ( !m_doc->highlight()->isInWord( l->at(ce) ) )
02609 break;
02610 }
02611
02612 cs = m_selectAnchor.column() - 1;
02613 if ( cs < m_doc->lineLength( m_selectAnchor.line() )
02614 && m_doc->highlight()->isInWord( l->at(cs) ) ) {
02615 for ( cs--; cs >= 0; cs-- )
02616 if ( !m_doc->highlight()->isInWord( l->at(cs) ) )
02617 break;
02618 }
02619
02620
02621 if (cs+1 < ce)
02622 {
02623 m_selectionCached.start().setPosition( m_selectAnchor.line(), cs+1 );
02624 m_selectionCached.end().setPosition( m_selectAnchor.line(), ce );
02625 }
02626 else
02627 {
02628 m_selectionCached.start() = m_selectAnchor;
02629 m_selectionCached.end() = m_selectAnchor;
02630 }
02631
02632 placeCursor( e->pos(), true );
02633 }
02634 else
02635 {
02636
02637
02638
02639
02640
02641 m_view->clearSelection( false, false );
02642 placeCursor( e->pos() );
02643 m_view->selectWord( m_cursor );
02644
02645 if (m_view->selection())
02646 {
02647 m_selectAnchor = m_view->selectionRange().start();
02648 m_selectionCached = m_view->selectionRange();
02649 }
02650 else
02651 {
02652
02653
02654 m_selectionMode = Default;
02655 }
02656 }
02657
02658
02659 if (m_view->selection())
02660 {
02661 QApplication::clipboard()->setText( m_view->selectionText(), QClipboard::Selection );
02662
02663
02664
02665 if (m_view->selectionRange().start() < m_selectionCached.start())
02666 updateCursor( m_view->selectionRange().start() );
02667 else
02668 updateCursor( m_view->selectionRange().end() );
02669 }
02670
02671 m_possibleTripleClick = true;
02672 QTimer::singleShot ( QApplication::doubleClickInterval(), this, SLOT(tripleClickTimeout()) );
02673
02674 m_scrollX = 0;
02675 m_scrollY = 0;
02676
02677 m_scrollTimer.start (50);
02678
02679 e->accept ();
02680 break;
02681
02682 default:
02683 e->ignore ();
02684 break;
02685 }
02686 }
02687
02688 void KateViewInternal::tripleClickTimeout()
02689 {
02690 m_possibleTripleClick = false;
02691 }
02692
02693 void KateViewInternal::mouseReleaseEvent( QMouseEvent* e )
02694 {
02695 switch (e->button())
02696 {
02697 case Qt::LeftButton:
02698 m_selectionMode = Default;
02699
02700
02701 if (m_selChangedByUser)
02702 {
02703 if (m_view->selection()) {
02704 QApplication::clipboard()->setText(m_view->selectionText (), QClipboard::Selection);
02705
02706
02707
02708 if ( m_view->selectionRange().start() < m_selectAnchor )
02709 updateCursor( m_view->selectionRange().start() );
02710 else
02711 updateCursor( m_view->selectionRange().end() );
02712 }
02713
02714 m_selChangedByUser = false;
02715 }
02716
02717 if (m_dragInfo.state == diPending)
02718 placeCursor( e->pos(), e->modifiers() & Qt::ShiftModifier );
02719 else if (m_dragInfo.state == diNone)
02720 m_scrollTimer.stop ();
02721
02722 m_dragInfo.state = diNone;
02723
02724 e->accept ();
02725 break;
02726
02727 case Qt::MidButton:
02728 placeCursor( e->pos() );
02729
02730 if( m_doc->isReadWrite() )
02731 {
02732 m_doc->paste( m_view, QClipboard::Selection );
02733 repaint();
02734 }
02735
02736 e->accept ();
02737 break;
02738
02739 default:
02740 e->ignore ();
02741 break;
02742 }
02743 }
02744
02745 void KateViewInternal::leaveEvent( QEvent* )
02746 {
02747 m_textHintTimer.stop();
02748 }
02749
02750 KTextEditor::Cursor KateViewInternal::coordinatesToCursor(const QPoint& _coord) const
02751 {
02752 QPoint coord(_coord);
02753
02754 KTextEditor::Cursor ret = KTextEditor::Cursor::invalid();
02755
02756 coord.setX( coord.x() - m_leftBorder->width() );
02757
02758 const KateTextLayout& thisLine = yToKateTextLayout(coord.y());
02759 if (thisLine.isValid())
02760 ret = renderer()->xToCursor(thisLine, coord.x(), !view()->wrapCursor());
02761
02762 return ret;
02763 }
02764
02765 void KateViewInternal::mouseMoveEvent( QMouseEvent* e )
02766 {
02767
02768 const KateTextLayout& thisLine = yToKateTextLayout(e->y());
02769 if (thisLine.isValid()) {
02770 KTextEditor::Cursor newPosition = renderer()->xToCursor(thisLine, e->x(), !view()->wrapCursor());
02771 if (newPosition != m_mouse) {
02772 m_mouse = newPosition;
02773 mouseMoved();
02774 }
02775 } else {
02776 if (m_mouse.isValid()) {
02777 m_mouse = KTextEditor::Cursor::invalid();
02778 mouseMoved();
02779 }
02780 }
02781
02782 if( e->buttons() & Qt::LeftButton )
02783 {
02784 if (m_dragInfo.state == diPending)
02785 {
02786
02787
02788 QPoint p( e->pos() - m_dragInfo.start );
02789
02790
02791 if( p.manhattanLength() > KGlobalSettings::dndEventDelay() )
02792 doDrag();
02793
02794 return;
02795 }
02796 else if (m_dragInfo.state == diDragging)
02797 {
02798
02799
02800 return;
02801 }
02802
02803 m_mouseX = e->x();
02804 m_mouseY = e->y();
02805
02806 m_scrollX = 0;
02807 m_scrollY = 0;
02808 int d = renderer()->fontHeight();
02809
02810 if (m_mouseX < 0)
02811 m_scrollX = -d;
02812
02813 if (m_mouseX > width())
02814 m_scrollX = d;
02815
02816 if (m_mouseY < 0)
02817 {
02818 m_mouseY = 0;
02819 m_scrollY = -d;
02820 }
02821
02822 if (m_mouseY > height())
02823 {
02824 m_mouseY = height();
02825 m_scrollY = d;
02826 }
02827
02828 placeCursor( QPoint( m_mouseX, m_mouseY ), true );
02829
02830 }
02831 else
02832 {
02833 if (isTargetSelected( e->pos() ) ) {
02834
02835
02836 if (m_mouseCursor != Qt::ArrowCursor) {
02837 m_mouseCursor = Qt::ArrowCursor;
02838 setCursor(m_mouseCursor);
02839 }
02840 } else {
02841
02842 if (m_mouseCursor != Qt::IBeamCursor) {
02843 m_mouseCursor = Qt::IBeamCursor;
02844 setCursor(m_mouseCursor);
02845 }
02846 }
02847
02848
02849
02850 if (m_textHintEnabled && geometry().contains(mapFromGlobal(e->globalPos())))
02851 {
02852 m_textHintTimer.start(m_textHintTimeout);
02853 m_textHintMouseX=e->x();
02854 m_textHintMouseY=e->y();
02855 }
02856 }
02857 }
02858
02859 void KateViewInternal::updateDirty( )
02860 {
02861 uint h = renderer()->fontHeight();
02862
02863 int currentRectStart = -1;
02864 int currentRectEnd = -1;
02865
02866 QRegion updateRegion;
02867
02868 for (int i = 0; i < cache()->viewCacheLineCount(); ++i) {
02869 if (cache()->viewLine(i).isDirty()) {
02870 if (currentRectStart == -1) {
02871 currentRectStart = h * i;
02872 currentRectEnd = h;
02873 } else {
02874 currentRectEnd += h;
02875 }
02876
02877 } else if (currentRectStart != -1) {
02878 updateRegion += QRect(0, currentRectStart, width(), currentRectEnd);
02879 currentRectStart = -1;
02880 currentRectEnd = -1;
02881 }
02882 }
02883
02884 if (currentRectStart != -1)
02885 updateRegion += QRect(0, currentRectStart, width(), currentRectEnd);
02886
02887 if (!updateRegion.isEmpty()) {
02888 if (debugPainting) kDebug( 13030 ) << k_funcinfo << "Update dirty region " << updateRegion;
02889 update(updateRegion);
02890 }
02891 }
02892
02893 void KateViewInternal::hideEvent(QHideEvent* e)
02894 {
02895 Q_UNUSED(e);
02896 if(m_view->isCompletionActive())
02897 m_view->completionWidget()->abortCompletion();
02898 }
02899
02900 void KateViewInternal::paintEvent(QPaintEvent *e)
02901 {
02902 QMutexLocker lock(m_doc->smartMutex());
02903
02904 if (m_smartDirty)
02905 doUpdateView();
02906
02907 if (debugPainting) kDebug (13030) << "GOT PAINT EVENT: Region" << e->region();
02908
02909 const QRect& unionRect = e->rect();
02910
02911 int xStart = startX() + unionRect.x();
02912 int xEnd = xStart + unionRect.width();
02913 uint h = renderer()->fontHeight();
02914 uint startz = (unionRect.y() / h);
02915 uint endz = startz + 1 + (unionRect.height() / h);
02916 uint lineRangesSize = cache()->viewCacheLineCount();
02917
02918 QPainter paint(this);
02919 paint.setRenderHints (QPainter::Antialiasing);
02920
02921
02922 renderer()->setCaretStyle(m_view->isOverwriteMode() ? KateRenderer::Block : KateRenderer::Line);
02923 renderer()->setShowTabs(m_doc->config()->configFlags() & KateDocumentConfig::cfShowTabs);
02924 renderer()->setShowTrailingSpaces(m_doc->config()->configFlags() & KateDocumentConfig::cfShowSpaces);
02925
02926 int sy = startz * h;
02927 paint.translate(unionRect.x(), startz * h);
02928
02929 for (uint z=startz; z <= endz; z++)
02930 {
02931 if ( (z >= lineRangesSize) || (cache()->viewLine(z).line() == -1) )
02932 {
02933 if (!(z >= lineRangesSize))
02934 cache()->viewLine(z).setDirty(false);
02935
02936 paint.fillRect( 0, 0, unionRect.width(), h, renderer()->config()->backgroundColor() );
02937 }
02938 else
02939 {
02940
02941 KateTextLayout& thisLine = cache()->viewLine(z);
02942
02943 if (!thisLine.viewLine() || z == startz) {
02944
02945 if (!e->region().contains(QRect(unionRect.x(), startz * h, unionRect.width(), h)))
02946 continue;
02947
02948
02949
02950
02951 if (thisLine.viewLine())
02952 paint.translate(QPoint(0, h * - thisLine.viewLine()));
02953
02954
02955
02956
02957 renderer()->paintTextLine(paint, thisLine.kateLineLayout(), xStart, xEnd, &m_cursor);
02958
02959
02960
02961 if (thisLine.viewLine())
02962 paint.translate(0, h * thisLine.viewLine());
02963
02964 thisLine.setDirty(false);
02965 }
02966 }
02967
02968 paint.translate(0, h);
02969 sy += h;
02970 }
02971 }
02972
02973 void KateViewInternal::resizeEvent(QResizeEvent* e)
02974 {
02975 bool expandedHorizontally = width() > e->oldSize().width();
02976 bool expandedVertically = height() > e->oldSize().height();
02977 bool heightChanged = height() != e->oldSize().height();
02978
02979 m_madeVisible = false;
02980
02981 if (heightChanged) {
02982 setAutoCenterLines(m_autoCenterLines, false);
02983 m_cachedMaxStartPos.setPosition(-1, -1);
02984 }
02985
02986 if (m_view->dynWordWrap()) {
02987 bool dirtied = false;
02988
02989 for (int i = 0; i < cache()->viewCacheLineCount(); i++) {
02990
02991
02992 bool lineNeedsRedraw = false;
02993
02994 if (cache()->viewLine(i).wrap()) {
02995 lineNeedsRedraw = true;
02996
02997 } else if (const KateLineLayoutPtr& line = cache()->viewLine(i).kateLineLayout()) {
02998 if (QTextLayout* layout = line->layout())
02999 if (layout->textOption().textDirection() == Qt::RightToLeft)
03000 lineNeedsRedraw = true;
03001
03002 } else if (!expandedHorizontally && (cache()->viewLine(i).endX() - cache()->viewLine(i).startX()) > width()) {
03003 lineNeedsRedraw = true;
03004 }
03005
03006 if (lineNeedsRedraw) {
03007 dirtied = true;
03008 cache()->viewLine(i).setDirty();
03009 break;
03010 }
03011 }
03012
03013 if (dirtied || heightChanged) {
03014 updateView(true);
03015 m_leftBorder->update();
03016 }
03017
03018 if (width() < e->oldSize().width()) {
03019 if (!m_view->wrapCursor()) {
03020
03021 if (m_cursor.column() > m_doc->lineLength(m_cursor.line())) {
03022 KateTextLayout thisLine = currentLayout();
03023
03024 KTextEditor::Cursor newCursor(m_cursor.line(), thisLine.endCol() + ((width() - thisLine.xOffset() - thisLine.width()) / renderer()->spaceWidth()) - 1);
03025 updateCursor(newCursor);
03026 }
03027 }
03028 }
03029
03030 } else {
03031 updateView();
03032
03033 if (expandedHorizontally && startX() > 0)
03034 scrollColumns(startX() - (width() - e->oldSize().width()));
03035 }
03036
03037 if (expandedVertically) {
03038 KTextEditor::Cursor max = maxStartPos();
03039 if (startPos() > max)
03040 scrollPos(max);
03041 }
03042 }
03043
03044 void KateViewInternal::scrollTimeout ()
03045 {
03046 if (m_scrollX || m_scrollY)
03047 {
03048 scrollLines (startPos().line() + (m_scrollY / (int) renderer()->fontHeight()));
03049 placeCursor( QPoint( m_mouseX, m_mouseY ), true );
03050 }
03051 }
03052
03053 void KateViewInternal::cursorTimeout ()
03054 {
03055 if (!debugPainting && !m_view->viInputMode()) {
03056 renderer()->setDrawCaret(!renderer()->drawCaret());
03057 paintCursor();
03058 }
03059 }
03060
03061 void KateViewInternal::textHintTimeout ()
03062 {
03063 m_textHintTimer.stop ();
03064
03065 KateTextLayout thisLine = yToKateTextLayout(m_textHintMouseY);
03066
03067 if (!thisLine.isValid()) return;
03068
03069 if (m_textHintMouseX> (lineMaxCursorX(thisLine) - thisLine.startX())) return;
03070
03071 KTextEditor::Cursor c = thisLine.start();
03072 c = renderer()->xToCursor(cache()->textLayout(c), m_textHintMouseX, !view()->wrapCursor());
03073
03074 QString tmp;
03075
03076 emit m_view->needTextHint(c, tmp);
03077
03078 if (!tmp.isEmpty()) kDebug(13030)<<"Hint text: "<<tmp;
03079 }
03080
03081 void KateViewInternal::focusInEvent (QFocusEvent *)
03082 {
03083 if (KApplication::cursorFlashTime() > 0)
03084 m_cursorTimer.start ( KApplication::cursorFlashTime() / 2 );
03085
03086 paintCursor();
03087
03088 m_doc->setActiveView( m_view );
03089
03090
03091 m_view->slotGotFocus ();
03092 }
03093
03094 void KateViewInternal::focusOutEvent (QFocusEvent *)
03095 {
03096
03097
03098
03099 m_cursorTimer.stop();
03100 m_view->renderer()->setDrawCaret(true);
03101 paintCursor();
03102
03103 m_textHintTimer.stop();
03104
03105 m_view->slotLostFocus ();
03106 }
03107
03108 void KateViewInternal::doDrag()
03109 {
03110 m_dragInfo.state = diDragging;
03111 m_dragInfo.dragObject = new QDrag(this);
03112 QMimeData *mimeData=new QMimeData();
03113 mimeData->setText(m_view->selectionText());
03114 m_dragInfo.dragObject->setMimeData(mimeData);
03115 m_dragInfo.dragObject->start(Qt::MoveAction);
03116 }
03117
03118 void KateViewInternal::dragEnterEvent( QDragEnterEvent* event )
03119 {
03120 if (event->source()==this) event->setDropAction(Qt::MoveAction);
03121 event->setAccepted( (event->mimeData()->hasText() && m_doc->isReadWrite()) ||
03122 KUrl::List::canDecode(event->mimeData()) );
03123 }
03124
03125 void KateViewInternal::fixDropEvent(QDropEvent* event) {
03126 if (event->source()!=this) event->setDropAction(Qt::CopyAction);
03127 else {
03128 Qt::DropAction action=Qt::MoveAction;
03129 #ifdef Q_WS_MAC
03130 if(event->keyboardModifiers() & Qt::AltModifier)
03131 action = Qt::CopyAction;
03132 #else
03133 if (event->keyboardModifiers() & Qt::ControlModifier)
03134 action = Qt::CopyAction;
03135 #endif
03136 event->setDropAction(action);
03137 }
03138 }
03139
03140 void KateViewInternal::dragMoveEvent( QDragMoveEvent* event )
03141 {
03142
03143 placeCursor( event->pos(), true, false );
03144
03145
03146
03147 fixDropEvent(event);
03148 }
03149
03150 void KateViewInternal::dropEvent( QDropEvent* event )
03151 {
03152 if ( KUrl::List::canDecode(event->mimeData()) ) {
03153
03154 emit dropEventPass(event);
03155
03156 } else if ( event->mimeData()->hasText() && m_doc->isReadWrite() ) {
03157
03158 QString text=event->mimeData()->text();
03159
03160
03161 bool priv = false;
03162 if (KateViewInternal* vi = qobject_cast<KateViewInternal*>(event->source()))
03163 priv = m_doc->ownedView( vi->m_view );
03164
03165
03166 bool selected = m_view->cursorSelected(m_cursor);
03167
03168 if( priv && selected ) {
03169
03170
03171 return;
03172 }
03173
03174 fixDropEvent(event);
03175
03176
03177
03178 KTextEditor::Cursor targetCursor(m_cursor);
03179 if ( event->dropAction() != Qt::CopyAction ) {
03180 editSetCursor(m_view->selectionRange().end());
03181 } else {
03182 m_view->clearSelection();
03183 }
03184
03185
03186 m_doc->editStart ();
03187
03188
03189 m_doc->insertText(targetCursor, text );
03190
03191 KateSmartCursor startCursor(targetCursor,m_doc);
03192
03193 if ( event->dropAction() != Qt::CopyAction )
03194 m_view->removeSelectedText();
03195
03196 KateSmartCursor endCursor1(startCursor,m_doc);
03197 endCursor1.advance(text.length(),KTextEditor::SmartCursor::ByCharacter);
03198 KTextEditor::Cursor endCursor(endCursor1);
03199 kDebug( 13030 )<<startCursor<<"---("<<text.length()<<")---"<<endCursor;
03200 m_view->setSelection(KTextEditor::Range(startCursor,endCursor));
03201 editSetCursor(endCursor);
03202
03203 m_doc->editEnd ();
03204
03205 event->acceptProposedAction();
03206 updateView();
03207 }
03208
03209
03210 m_dragInfo.state = diNone;
03211
03212 stopDragScroll();
03213 }
03214
03215
03216 void KateViewInternal::clear()
03217 {
03218 m_startPos = m_displayCursor = m_cursor = KTextEditor::Cursor(0, 0);
03219 updateView(true);
03220 }
03221
03222 void KateViewInternal::wheelEvent(QWheelEvent* e)
03223 {
03224 if (m_lineScroll->minimum() != m_lineScroll->maximum() && e->orientation() != Qt::Horizontal) {
03225
03226 if ( ( e->modifiers() & Qt::ControlModifier ) || ( e->modifiers() & Qt::ShiftModifier ) ) {
03227 if (e->delta() > 0)
03228 scrollPrevPage();
03229 else
03230 scrollNextPage();
03231 } else {
03232 scrollViewLines(-((e->delta() / 120) * QApplication::wheelScrollLines()));
03233 }
03234
03235 } else if (columnScrollingPossible()) {
03236 QWheelEvent copy = *e;
03237 QApplication::sendEvent(m_columnScroll, ©);
03238
03239 } else {
03240 e->ignore();
03241 }
03242 }
03243
03244 void KateViewInternal::startDragScroll()
03245 {
03246 if ( !m_dragScrollTimer.isActive() ) {
03247 m_dragScrollTimer.start( s_scrollTime );
03248 }
03249 }
03250
03251 void KateViewInternal::stopDragScroll()
03252 {
03253 m_dragScrollTimer.stop();
03254 updateView();
03255 }
03256
03257 void KateViewInternal::doDragScroll()
03258 {
03259 QPoint p = this->mapFromGlobal( QCursor::pos() );
03260
03261 int dx = 0, dy = 0;
03262 if ( p.y() < s_scrollMargin ) {
03263 dy = p.y() - s_scrollMargin;
03264 } else if ( p.y() > height() - s_scrollMargin ) {
03265 dy = s_scrollMargin - (height() - p.y());
03266 }
03267
03268 if ( p.x() < s_scrollMargin ) {
03269 dx = p.x() - s_scrollMargin;
03270 } else if ( p.x() > width() - s_scrollMargin ) {
03271 dx = s_scrollMargin - (width() - p.x());
03272 }
03273
03274 dy /= 4;
03275
03276 if (dy)
03277 scrollLines(startPos().line() + dy);
03278
03279 if (columnScrollingPossible () && dx)
03280 scrollColumns(qMin (m_startX + dx, m_columnScroll->maximum()));
03281
03282 if (!dy && !dx)
03283 stopDragScroll();
03284 }
03285
03286 void KateViewInternal::enableTextHints(int timeout)
03287 {
03288 m_textHintTimeout=timeout;
03289 m_textHintEnabled=true;
03290 m_textHintTimer.start(timeout);
03291 }
03292
03293 void KateViewInternal::disableTextHints()
03294 {
03295 m_textHintEnabled=false;
03296 m_textHintTimer.stop ();
03297 }
03298
03299
03300 void KateViewInternal::editStart()
03301 {
03302 editSessionNumber++;
03303
03304 if (editSessionNumber > 1)
03305 return;
03306
03307 editIsRunning = true;
03308 editOldCursor = m_cursor;
03309 }
03310
03311 void KateViewInternal::editEnd(int editTagLineStart, int editTagLineEnd, bool tagFrom)
03312 {
03313 if (editSessionNumber == 0)
03314 return;
03315
03316 editSessionNumber--;
03317
03318 if (editSessionNumber > 0)
03319 return;
03320
03321 if (tagFrom && (editTagLineStart <= int(m_doc->getRealLine(startLine()))))
03322 tagAll();
03323 else
03324 tagLines (editTagLineStart, tagFrom ? qMax(m_doc->lastLine() + 1, editTagLineEnd) : editTagLineEnd, true);
03325
03326 if (editOldCursor == m_cursor)
03327 updateBracketMarks();
03328
03329 updateView(true);
03330
03331 if (editOldCursor != m_cursor)
03332 {
03333 m_madeVisible = false;
03334 updateCursor ( m_cursor, true );
03335 }
03336 else if ( m_view == m_doc->activeView() )
03337 {
03338 makeVisible(m_displayCursor, m_displayCursor.column());
03339 }
03340
03341 editIsRunning = false;
03342 }
03343
03344 void KateViewInternal::editSetCursor (const KTextEditor::Cursor &_cursor)
03345 {
03346 if (m_cursor != _cursor)
03347 {
03348 m_cursor = _cursor;
03349 }
03350 }
03351
03352
03353 void KateViewInternal::viewSelectionChanged ()
03354 {
03355 if (!m_view->selection())
03356 {
03357 m_selectAnchor = KTextEditor::Cursor::invalid();
03358
03359
03360
03361
03362
03363 m_selectionCached.start() = KTextEditor::Cursor::invalid();
03364
03365 }
03366 }
03367
03368 KateLayoutCache* KateViewInternal::cache( ) const
03369 {
03370 return m_layoutCache;
03371 }
03372
03373 KTextEditor::Cursor KateViewInternal::toRealCursor( const KTextEditor::Cursor & virtualCursor ) const
03374 {
03375 return KTextEditor::Cursor(m_doc->getRealLine(virtualCursor.line()), virtualCursor.column());
03376 }
03377
03378 KTextEditor::Cursor KateViewInternal::toVirtualCursor( const KTextEditor::Cursor & realCursor ) const
03379 {
03380 return KTextEditor::Cursor(m_doc->getVirtualLine(realCursor.line()), realCursor.column());
03381 }
03382
03383 KateRenderer * KateViewInternal::renderer( ) const
03384 {
03385 return m_view->renderer();
03386 }
03387
03388 void KateViewInternal::dynamicHighlightAdded( KateSmartRange * range )
03389 {
03390 QMutexLocker lock(m_doc->smartMutex());
03391
03392 DynamicRangeHL* hl = new DynamicRangeHL(range);
03393 hl->isView = view() == sender();
03394
03395 m_dynamicHighlights.insert(range, hl);
03396
03397 if (m_mouse.isValid())
03398
03399 dynamicMoved(true);
03400
03401 dynamicMoved(false);
03402 }
03403
03404 void KateViewInternal::dynamicHighlightRemoved( KateSmartRange * range )
03405 {
03406 QMutexLocker lock(m_doc->smartMutex());
03407
03408 removeWatcher(range, this);
03409
03410 delete m_dynamicHighlights.take(range);
03411 }
03412
03413 void KateViewInternal::rangeDeleted( KateSmartRange * range )
03414 {
03415 QMutexLocker lock(m_doc->smartMutex());
03416
03417 if (m_dynamicHighlights.contains(range)) {
03418 delete m_dynamicHighlights.take(range);
03419 return;
03420 }
03421
03422 foreach (DynamicRangeHL* hl, m_dynamicHighlights) {
03423
03424 if (hl->mouseAnimations.contains(range))
03425 delete hl->mouseAnimations.take(range);
03426
03427 if (hl->mouseOver && (hl->mouseOver == range || hl->mouseOver->hasParent(range))) {
03428 hl->mouseOver = static_cast<KateSmartRange*>(range->parentRange());
03429 }
03430
03431 if (hl->caretAnimations.contains(range))
03432 delete hl->caretAnimations.take(range);
03433
03434 if (hl->caretOver && (hl->caretOver == range || hl->caretOver->hasParent(range))) {
03435 hl->caretOver = static_cast<KateSmartRange*>(range->parentRange());
03436 }
03437 }
03438 }
03439
03440 void KateViewInternal::startDynamic( DynamicRangeHL* hl, KateSmartRange* range, KTextEditor::Attribute::ActivationType type )
03441 {
03442 QMutexLocker lock(m_doc->smartMutex());
03443
03444 if (type == KTextEditor::Attribute::ActivateMouseIn)
03445 range->setMouseOver(true);
03446 else
03447 range->setCaretOver(true);
03448
03449 if (!range->attribute() || !range->attribute()->dynamicAttribute(type))
03450 return;
03451
03452 KateDynamicAnimation* anim;
03453 if (hl->isView)
03454 anim = new KateDynamicAnimation(view(), range, type);
03455 else
03456 anim = new KateDynamicAnimation(m_doc, range, type);
03457
03458 connect(anim, SIGNAL(redraw(KateSmartRange*)), SLOT(updateRange(KateSmartRange*)));
03459
03460 if (type == KTextEditor::Attribute::ActivateMouseIn)
03461 hl->mouseAnimations.insert(range, anim);
03462 else
03463 hl->caretAnimations.insert(range, anim);
03464
03465 renderer()->dynamicRegion().addRange(range);
03466 }
03467
03468 void KateViewInternal::endDynamic( DynamicRangeHL* hl, KateSmartRange* range, KTextEditor::Attribute::ActivationType type )
03469 {
03470 QMutexLocker lock(m_doc->smartMutex());
03471
03472 if (type == KTextEditor::Attribute::ActivateMouseIn)
03473 range->setMouseOver(false);
03474 else
03475 range->setCaretOver(false);
03476
03477 if (!range->attribute() || !range->attribute()->dynamicAttribute(type))
03478 return;
03479
03480 KateDynamicAnimation* anim = 0L;
03481 if (type == KTextEditor::Attribute::ActivateMouseIn) {
03482 Q_ASSERT(hl->mouseAnimations.contains(range));
03483 anim = hl->mouseAnimations.take(range);
03484
03485 } else {
03486 Q_ASSERT(hl->caretAnimations.contains(range));
03487 anim = hl->caretAnimations.take(range);
03488 }
03489
03490 if (anim)
03491 anim->finish();
03492
03493
03494
03495
03496
03497
03498 }
03499
03500 void KateViewInternal::updateRange(KateSmartRange* range)
03501 {
03502
03503 tagRange(*range, true);
03504 updateDirty();
03505 }
03506
03507 void KateViewInternal::dynamicMoved( bool mouse )
03508 {
03509 QMutexLocker lock(m_doc->smartMutex());
03510
03511 foreach (DynamicRangeHL* hl, m_dynamicHighlights) {
03512 QStack<KTextEditor::SmartRange*> enterStack, exitStack;
03513 KTextEditor::SmartRange* oldRange = mouse ? hl->mouseOver : hl->caretOver;
03514 KTextEditor::SmartRange* newRange;
03515 if (mouse)
03516 newRange = (hl->mouseOver ? hl->mouseOver : hl->top)->deepestRangeContaining(m_mouse, &enterStack, &exitStack);
03517 else
03518 newRange = (hl->caretOver ? hl->caretOver : hl->top)->deepestRangeContaining(m_cursor, &enterStack, &exitStack);
03519
03520 if (newRange != oldRange) {
03521 if (newRange && !oldRange)
03522 enterStack.prepend(newRange);
03523
03524 foreach (KTextEditor::SmartRange* exitedRange, exitStack) {
03525 endDynamic(hl, static_cast<KateSmartRange*>(exitedRange), mouse ? KTextEditor::Attribute::ActivateMouseIn : KTextEditor::Attribute::ActivateCaretIn);
03526 static_cast<KateSmartRange*>(exitedRange)->feedbackMouseCaretChange(m_view, mouse, false);
03527 }
03528
03529 foreach (KTextEditor::SmartRange* enteredRange, enterStack) {
03530 static_cast<KateSmartRange*>(enteredRange)->feedbackMouseCaretChange(m_view, mouse, true);
03531 startDynamic(hl, static_cast<KateSmartRange*>(enteredRange), mouse ? KTextEditor::Attribute::ActivateMouseIn : KTextEditor::Attribute::ActivateCaretIn);
03532 }
03533
03534 if (mouse)
03535 hl->mouseOver = static_cast<KateSmartRange*>(newRange);
03536 else
03537 hl->caretOver = static_cast<KateSmartRange*>(newRange);
03538 }
03539 }
03540 }
03541
03542 void KateViewInternal::mouseMoved( )
03543 {
03544 view()->notifyMousePositionChanged(m_mouse);
03545
03546 dynamicMoved(true);
03547 }
03548
03549 KateViewInternal::DynamicRangeHL::DynamicRangeHL(KateSmartRange* _top)
03550 : top(_top)
03551 , isView(false)
03552 , caretOver(0L)
03553 , mouseOver(0L)
03554 {
03555 }
03556
03557 KateViewInternal::DynamicRangeHL::~ DynamicRangeHL( )
03558 {
03559 qDeleteAll(caretAnimations);
03560 qDeleteAll(mouseAnimations);
03561 }
03562
03563 void KateViewInternal::cursorMoved( )
03564 {
03565 dynamicMoved(false);
03566 }
03567
03568 void KateViewInternal::relayoutRange( const KTextEditor::Range & range, bool realCursors )
03569 {
03570 int startLine = realCursors ? range.start().line() : toRealCursor(range.start()).line();
03571 int endLine = realCursors ? range.end().line() : toRealCursor(range.end()).line();
03572
03573
03574 cache()->relayoutLines(startLine, endLine);
03575
03576 if (!m_smartDirty) {
03577 m_smartDirty = true;
03578 emit requestViewUpdate(true);
03579 }
03580 }
03581
03582 void KateViewInternal::rangePositionChanged( KTextEditor::SmartRange * range )
03583 {
03584
03585
03586
03587
03588
03589
03590
03591 relayoutRange(*range);
03592 }
03593
03594 void KateViewInternal::rangeDeleted( KTextEditor::SmartRange * range )
03595 {
03596 relayoutRange(*range);
03597 }
03598
03599 void KateViewInternal::childRangeInserted( KTextEditor::SmartRange *, KTextEditor::SmartRange * child )
03600 {
03601 QMutexLocker lock(m_doc->smartMutex());
03602
03603 relayoutRange(*child);
03604 addWatcher(child, this);
03605 }
03606
03607 void KateViewInternal::rangeAttributeChanged( KTextEditor::SmartRange * range, KTextEditor::Attribute::Ptr currentAttribute, KTextEditor::Attribute::Ptr previousAttribute )
03608 {
03609 if (currentAttribute != previousAttribute)
03610 relayoutRange(*range);
03611 }
03612
03613 void KateViewInternal::childRangeRemoved( KTextEditor::SmartRange *, KTextEditor::SmartRange * child )
03614 {
03615 QMutexLocker lock(m_doc->smartMutex());
03616
03617 relayoutRange(*child);
03618 removeWatcher(child, this);
03619 }
03620
03621 void KateViewInternal::addHighlightRange(KTextEditor::SmartRange* range)
03622 {
03623 QMutexLocker lock(m_doc->smartMutex());
03624
03625 relayoutRange(*range);
03626 ++m_watcherCount3;
03627 addWatcher(range, this);
03628 }
03629
03630 void KateViewInternal::removeHighlightRange(KTextEditor::SmartRange* range)
03631 {
03632 QMutexLocker lock(m_doc->smartMutex());
03633
03634 relayoutRange(*range);
03635 --m_watcherCount3;
03636 removeWatcher(range, this);
03637 }
03638
03639
03640 QVariant KateViewInternal::inputMethodQuery ( Qt::InputMethodQuery query ) const
03641 {
03642 switch (query) {
03643 case Qt::ImMicroFocus: {
03644
03645
03646
03647
03648
03649 KTextEditor::Cursor c = m_cursor;
03650 if (m_imPreedit)
03651 c = m_imPreedit->start();
03652 return QRect(cursorToCoordinate(c, true, false), QSize(0, renderer()->fontHeight()));
03653 }
03654
03655 case Qt::ImFont:
03656 return renderer()->currentFont();
03657
03658 case Qt::ImCursorPosition:
03659 if (m_imPreedit)
03660 return m_imPreedit->start().column();
03661 else
03662 return m_cursor.start().column();
03663
03664 case Qt::ImSurroundingText:
03665 if (KateTextLine::Ptr l = m_doc->kateTextLine(m_cursor.line()))
03666 return l->string();
03667 else
03668 return QString();
03669
03670 case Qt::ImCurrentSelection:
03671 if (view()->selection())
03672 return view()->selectionText();
03673 else
03674 return QString();
03675 }
03676
03677 return QWidget::inputMethodQuery(query);
03678 }
03679
03680 void KateViewInternal::inputMethodEvent(QInputMethodEvent* e)
03681 {
03682 if ( m_doc->readOnly() ) {
03683 e->ignore();
03684 return;
03685 }
03686
03687
03688
03689 if ( m_view->selection() )
03690 m_view->removeSelectedText();
03691
03692 bool createdPreedit = false;
03693 if (!m_imPreedit) {
03694 createdPreedit = true;
03695 m_imPreedit = m_view->doc()->smartManager()->newSmartRange(KTextEditor::Range(m_cursor, m_cursor), 0L, KTextEditor::SmartRange::ExpandLeft | KTextEditor::SmartRange::ExpandRight);
03696 }
03697
03698 if (!m_imPreedit->isEmpty()) {
03699 m_view->doc()->editStart(false);
03700 m_view->doc()->removeText(*m_imPreedit);
03701 m_view->doc()->editEnd();
03702 }
03703
03704 if (!e->commitString().isEmpty() || e->replacementLength()) {
03705 KTextEditor::Range preeditRange = *m_imPreedit;
03706
03707 KTextEditor::Cursor start(m_imPreedit->start().line(), m_imPreedit->start().column() + e->replacementStart());
03708 KTextEditor::Cursor removeEnd = start + KTextEditor::Cursor(0, e->replacementLength());
03709
03710 m_view->doc()->editStart(true);
03711 if (start != removeEnd)
03712 m_view->doc()->removeText(KTextEditor::Range(start, removeEnd));
03713 if (!e->commitString().isEmpty())
03714 m_view->doc()->insertText(start, e->commitString());
03715 m_view->doc()->editEnd();
03716
03717
03718 m_imPreedit->setRange(preeditRange);
03719 }
03720
03721 if (!e->preeditString().isEmpty()) {
03722 m_view->doc()->editStart(false);
03723 m_view->doc()->insertText(m_imPreedit->start(), e->preeditString());
03724 m_view->doc()->editEnd();
03725
03726 }
03727
03728
03729 if (m_imPreedit && e->preeditString().isEmpty()) {
03730 if (!createdPreedit)
03731 m_view->removeInternalHighlight(m_imPreedit);
03732
03733 delete m_imPreedit;
03734 m_imPreedit = 0L;
03735
03736 renderer()->setDrawCaret(false);
03737 renderer()->setCaretOverrideColor(QColor());
03738
03739 return;
03740 }
03741
03742 KTextEditor::Cursor newCursor = m_cursor;
03743 bool hideCursor = false;
03744 QColor caretColor;
03745
03746 if (m_imPreedit) {
03747 m_imPreedit->clearAndDeleteChildRanges();
03748
03749 int decorationColumn = 0;
03750 foreach (const QInputMethodEvent::Attribute &a, e->attributes()) {
03751 if (a.type == QInputMethodEvent::Cursor) {
03752 newCursor = m_imPreedit->start() + KTextEditor::Cursor(0, a.start);
03753 hideCursor = !a.length;
03754 QColor c = qvariant_cast<QColor>(a.value);
03755 if (c.isValid())
03756 caretColor = c;
03757
03758 } else if (a.type == QInputMethodEvent::TextFormat) {
03759 QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
03760 if (f.isValid() && decorationColumn <= a.start) {
03761 KTextEditor::Range fr(m_imPreedit->start().line(), m_imPreedit->start().column() + a.start, m_imPreedit->start().line(), m_imPreedit->start().column() + a.start + a.length);
03762 KTextEditor::SmartRange* formatRange = m_view->doc()->smartManager()->newSmartRange(fr, m_imPreedit);
03763 KTextEditor::Attribute::Ptr attribute(new KTextEditor::Attribute());
03764 attribute->merge(f);
03765 formatRange->setAttribute(attribute);
03766 decorationColumn = a.start + a.length;
03767 }
03768 }
03769 }
03770
03771 if (createdPreedit)
03772 m_view->addInternalHighlight(m_imPreedit);
03773 }
03774
03775 renderer()->setDrawCaret(hideCursor);
03776 renderer()->setCaretOverrideColor(caretColor);
03777
03778 if (newCursor != m_cursor)
03779 updateCursor(newCursor);
03780
03781 e->accept();
03782 }
03783
03784
03785
03786 ViMode KateViewInternal::getCurrentViMode()
03787 {
03788 return getViInputModeManager()->getCurrentViMode();
03789 }
03790
03791 KateViInputModeManager* KateViewInternal::getViInputModeManager()
03792 {
03793 if (!m_viInputModeManager) {
03794 m_viInputModeManager = new KateViInputModeManager(m_view, this);
03795 }
03796
03797 return m_viInputModeManager;
03798 }
03799
03800