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