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