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::updateCursor( const KTextEditor::Cursor& newCursor, bool force, bool center, bool calledExternally )
01853 {
01854 if ( !force && (m_cursor == newCursor) )
01855 {
01856 if ( !m_madeVisible && m_view == m_doc->activeView() )
01857 {
01858
01859 m_doc->foldingTree()->ensureVisible( newCursor.line() );
01860
01861 makeVisible ( m_displayCursor, m_displayCursor.column(), false, center, calledExternally );
01862 }
01863
01864 return;
01865 }
01866
01867
01868 m_doc->foldingTree()->ensureVisible( newCursor.line() );
01869
01870 KTextEditor::Cursor oldDisplayCursor = m_displayCursor;
01871
01872 m_cursor = newCursor;
01873 m_displayCursor = toVirtualCursor(m_cursor);
01874
01875 if ( m_view == m_doc->activeView() )
01876 makeVisible ( m_displayCursor, m_displayCursor.column(), false, center, calledExternally );
01877
01878 updateBracketMarks();
01879
01880
01881
01882
01883 tagLine(oldDisplayCursor);
01884 tagLine(m_displayCursor);
01885
01886 updateMicroFocus();
01887
01888 if (m_cursorTimer.isActive ())
01889 {
01890 if ( KApplication::cursorFlashTime() > 0 )
01891 m_cursorTimer.start( KApplication::cursorFlashTime() / 2 );
01892 renderer()->setDrawCaret(true);
01893 }
01894
01895
01896 if (m_preserveX)
01897 m_preserveX = false;
01898 else {
01899 QMutexLocker lock(m_doc->smartMutex());
01900 m_preservedX = renderer()->cursorToX(cache()->textLayout(m_cursor), m_cursor, !m_view->wrapCursor());
01901 }
01902
01903
01904
01905
01906 cursorMoved();
01907
01908 if(!m_doc->isEditRunning())
01909 m_doc->setUndoDontMerge(true);
01910
01911 updateDirty();
01912
01914 emit m_view->cursorPositionChanged(m_view, m_cursor);
01915 }
01916
01917 void KateViewInternal::updateBracketMarkAttributes()
01918 {
01919 KTextEditor::Attribute::Ptr bracketFill = KTextEditor::Attribute::Ptr(new KTextEditor::Attribute());
01920 bracketFill->setBackground(m_view->m_renderer->config()->highlightedBracketColor());
01921 bracketFill->setBackgroundFillWhitespace(false);
01922 bracketFill->setFontBold();
01923
01924 m_bmStart->setAttribute(bracketFill);
01925 m_bmEnd->setAttribute(bracketFill);
01926
01927 if (m_view->m_renderer->config()->showWholeBracketExpression()) {
01928
01929 KTextEditor::Attribute::Ptr expressionFill = KTextEditor::Attribute::Ptr(new KTextEditor::Attribute());
01930 expressionFill->setBackground(m_view->m_renderer->config()->highlightedBracketColor());
01931 expressionFill->setBackgroundFillWhitespace(false);
01932
01933 m_bm->setAttribute(expressionFill);
01934 } else {
01935 m_bm->setAttribute(KTextEditor::Attribute::Ptr(new KTextEditor::Attribute()));
01936 }
01937 }
01938
01939 void KateViewInternal::updateBracketMarks()
01940 {
01941 bool showWholeBracketExpression = m_view->m_renderer->config()->showWholeBracketExpression();
01942
01943 QMutexLocker lock(m_doc->smartMutex());
01944 if (m_bmHighlighted) {
01945 view()->removeInternalHighlight(m_bmStart);
01946 view()->removeInternalHighlight(m_bmEnd);
01947 view()->removeInternalHighlight(m_bm);
01948 m_bmHighlighted = false;
01949 }
01950
01951 if ( m_bm->isValid() ) {
01952 tagRange(*m_bmStart, true);
01953 tagRange(*m_bmEnd, true);
01954 tagRange(*m_bm, true);
01955 }
01956
01957
01958 int maxLines = linesDisplayed () * 3;
01959 m_doc->newBracketMark( m_cursor, *m_bm, maxLines );
01960
01961 if ( m_bm->isValid() ) {
01962 m_bmStart->start() = m_bm->start();
01963 m_bmStart->end().setPosition(m_bm->start().line(), m_bm->start().column() + 1);
01964
01965 m_bmEnd->start() = m_bm->end();
01966 m_bmEnd->end().setPosition(m_bm->end().line(), m_bm->end().column() + 1);
01967
01968 tagRange(*m_bmStart, true);
01969 tagRange(*m_bmEnd, true);
01970 if (showWholeBracketExpression) {
01971 tagRange(*m_bm, true);
01972 }
01973
01974 view()->addInternalHighlight(m_bmStart);
01975 view()->addInternalHighlight(m_bmEnd);
01976 if (showWholeBracketExpression) {
01977 view()->addInternalHighlight(m_bm);
01978 }
01979 m_bmHighlighted = true;
01980 }
01981 }
01982
01983 bool KateViewInternal::tagLine(const KTextEditor::Cursor& virtualCursor)
01984 {
01985 QMutexLocker lock(m_doc->smartMutex());
01986
01987 if ((int)m_doc->getRealLine(virtualCursor.line()) > m_doc->lastLine())
01988 return false;
01989
01990
01991 int viewLine = cache()->displayViewLine(virtualCursor, true);
01992 if (viewLine >= 0 && viewLine < cache()->viewCacheLineCount()) {
01993 cache()->viewLine(viewLine).setDirty();
01994 m_leftBorder->update (0, lineToY(viewLine), m_leftBorder->width(), renderer()->fontHeight());
01995 return true;
01996 }
01997 return false;
01998 }
01999
02000 bool KateViewInternal::tagLines( int start, int end, bool realLines )
02001 {
02002 return tagLines(KTextEditor::Cursor(start, 0), KTextEditor::Cursor(end, -1), realLines);
02003 }
02004
02005 bool KateViewInternal::tagLines(KTextEditor::Cursor start, KTextEditor::Cursor end, bool realCursors)
02006 {
02007 QMutexLocker lock(m_doc->smartMutex());
02008 if (realCursors)
02009 {
02010 cache()->relayoutLines(start.line(), end.line());
02011
02012
02013 start = toVirtualCursor(start);
02014 end = toVirtualCursor(end);
02015
02016 } else {
02017 cache()->relayoutLines(toRealCursor(start).line(), toRealCursor(end).line());
02018 }
02019
02020 if (end.line() < startLine())
02021 {
02022
02023 return false;
02024 }
02025
02026
02027 if (start.line() > startLine() + cache()->viewCacheLineCount())
02028 {
02029
02030 return false;
02031 }
02032
02033 cache()->updateViewCache(startPos());
02034
02035
02036
02037 bool ret = false;
02038
02039 for (int z = 0; z < cache()->viewCacheLineCount(); z++)
02040 {
02041 KateTextLayout& line = cache()->viewLine(z);
02042 if ((line.virtualLine() > start.line() || (line.virtualLine() == start.line() && line.endCol() >= start.column() && start.column() != -1)) &&
02043 (line.virtualLine() < end.line() || (line.virtualLine() == end.line() && (line.startCol() <= end.column() || end.column() == -1)))) {
02044 ret = true;
02045 break;
02046
02047 }
02048 }
02049
02050 if (!m_view->dynWordWrap())
02051 {
02052 int y = lineToY( start.line() );
02053
02054 int h = (end.line() - start.line() + 2) * renderer()->fontHeight();
02055 if (end.line() >= m_doc->numVisLines() - 1)
02056 h = height();
02057
02058 m_leftBorder->update (0, y, m_leftBorder->width(), h);
02059 }
02060 else
02061 {
02062
02063
02064 for (int z = 0; z < cache()->viewCacheLineCount(); z++)
02065 {
02066 KateTextLayout& line = cache()->viewLine(z);
02067 if (!line.isValid() ||
02068 ((line.virtualLine() > start.line() || (line.virtualLine() == start.line() && line.endCol() >= start.column() && start.column() != -1)) &&
02069 (line.virtualLine() < end.line() || (line.virtualLine() == end.line() && (line.startCol() <= end.column() || end.column() == -1)))))
02070 {
02071
02072 m_leftBorder->update (0, z * renderer()->fontHeight(), m_leftBorder->width(), m_leftBorder->height());
02073 break;
02074 }
02075
02076
02077
02078
02079
02080
02081 }
02082 }
02083
02084 return ret;
02085 }
02086
02087 bool KateViewInternal::tagRange(const KTextEditor::Range& range, bool realCursors)
02088 {
02089 return tagLines(range.start(), range.end(), realCursors);
02090 }
02091
02092 void KateViewInternal::tagAll()
02093 {
02094 QMutexLocker lock(m_doc->smartMutex());
02095
02096
02097 cache()->clear ();
02098
02099 m_leftBorder->updateFont();
02100 m_leftBorder->update();
02101 }
02102
02103 void KateViewInternal::paintCursor()
02104 {
02105 if (tagLine(m_displayCursor))
02106 updateDirty();
02107 }
02108
02109
02110 void KateViewInternal::placeCursor( const QPoint& p, bool keepSelection, bool updateSelection )
02111 {
02112 KateTextLayout thisLine = yToKateTextLayout(p.y());
02113 KTextEditor::Cursor c;
02114
02115 QMutexLocker lock(m_doc->smartMutex());
02116
02117 if (!thisLine.isValid())
02118 thisLine = cache()->textLayout(m_doc->lines() - 1, -1);
02119
02120 c = renderer()->xToCursor(thisLine, startX() + p.x(), !view()->wrapCursor());
02121
02122 if (c.line () < 0 || c.line() >= m_doc->lines()) {
02123 return;
02124 }
02125
02126 lock.unlock();
02127
02128 if (updateSelection)
02129 KateViewInternal::updateSelection( c, keepSelection );
02130
02131 updateCursor( c );
02132 }
02133
02134
02135 bool KateViewInternal::isTargetSelected( const QPoint& p )
02136 {
02137 const KateTextLayout& thisLine = yToKateTextLayout(p.y());
02138 if (!thisLine.isValid())
02139 return false;
02140
02141 return m_view->cursorSelected(renderer()->xToCursor(thisLine, startX() + p.x(), !view()->wrapCursor()));
02142 }
02143
02144
02145
02146 bool KateViewInternal::eventFilter( QObject *obj, QEvent *e )
02147 {
02148 if (obj == m_lineScroll)
02149 {
02150
02151 if (e->type() == QEvent::Wheel && m_lineScroll->minimum() != m_lineScroll->maximum())
02152 {
02153 wheelEvent((QWheelEvent*)e);
02154 return true;
02155 }
02156
02157
02158 return QWidget::eventFilter( obj, e );
02159 }
02160
02161 switch( e->type() )
02162 {
02163 case QEvent::ChildAdded:
02164 case QEvent::ChildRemoved: {
02165 QChildEvent* c = static_cast<QChildEvent*>(e);
02166 if (c->added()) {
02167 c->child()->installEventFilter(this);
02168
02169
02170
02171 } else if (c->removed()) {
02172 c->child()->removeEventFilter(this);
02173
02174
02175
02176 }
02177 } break;
02178
02179 case QEvent::ShortcutOverride:
02180 {
02181 QKeyEvent *k = static_cast<QKeyEvent *>(e);
02182
02183 if (k->key() == Qt::Key_Escape) {
02184 if (m_view->isCompletionActive()) {
02185 m_view->abortCompletion();
02186 k->accept();
02187
02188 return true;
02189 } else if (m_view->viewBar()->isVisible()) {
02190 m_view->viewBar()->hideCurrentBarWidget();
02191 k->accept();
02192
02193 return true;
02194 } else if (!m_view->config()->persistentSelection() && m_view->selection()) {
02195 m_view->clearSelection();
02196 k->accept();
02197
02198 return true;
02199 }
02200 }
02201
02202
02203 if (m_view->viInputMode() && m_view->viInputModeStealKeys() && ( m_view->getCurrentViMode() != InsertMode ||
02204 ( m_view->getCurrentViMode() == InsertMode && k->modifiers() == Qt::ControlModifier ) ) ) {
02205 k->accept();
02206 return true;
02207 }
02208
02209 } break;
02210
02211 case QEvent::KeyPress:
02212 {
02213 QKeyEvent *k = static_cast<QKeyEvent *>(e);
02214
02215
02216 if (obj == this && (!k->modifiers() || k->modifiers() == Qt::ShiftModifier)) {
02217 keyPressEvent( k );
02218 if (k->isAccepted()) {
02219
02220 return true;
02221 }
02222 }
02223
02224
02225 } break;
02226
02227 case QEvent::DragMove:
02228 {
02229 QPoint currentPoint = ((QDragMoveEvent*) e)->pos();
02230
02231 QRect doNotScrollRegion( s_scrollMargin, s_scrollMargin,
02232 width() - s_scrollMargin * 2,
02233 height() - s_scrollMargin * 2 );
02234
02235 if ( !doNotScrollRegion.contains( currentPoint ) )
02236 {
02237 startDragScroll();
02238
02239 ( (QDragMoveEvent*)e )->accept( QRect(0,0,0,0) );
02240 }
02241
02242 dragMoveEvent((QDragMoveEvent*)e);
02243 } break;
02244
02245 case QEvent::DragLeave:
02246
02247 stopDragScroll();
02248 break;
02249
02250 case QEvent::WindowBlocked:
02251
02252
02253 m_doc->ignoreModifiedOnDiskOnce();
02254 break;
02255
02256 default:
02257 break;
02258 }
02259
02260 return QWidget::eventFilter( obj, e );
02261 }
02262
02263 void KateViewInternal::keyPressEvent( QKeyEvent* e )
02264 {
02265 if( e->key() == Qt::Key_Left && e->modifiers() == Qt::AltModifier ) {
02266 m_view->emitNavigateLeft();
02267 e->setAccepted(true);
02268 return;
02269 }
02270 if( e->key() == Qt::Key_Right && e->modifiers() == Qt::AltModifier ) {
02271 m_view->emitNavigateRight();
02272 e->setAccepted(true);
02273 return;
02274 }
02275 if( e->key() == Qt::Key_Up && e->modifiers() == Qt::AltModifier ) {
02276 m_view->emitNavigateUp();
02277 e->setAccepted(true);
02278 return;
02279 }
02280 if( e->key() == Qt::Key_Down && e->modifiers() == Qt::AltModifier ) {
02281 m_view->emitNavigateDown();
02282 e->setAccepted(true);
02283 return;
02284 }
02285 if( e->key() == Qt::Key_Return && e->modifiers() == Qt::AltModifier ) {
02286 m_view->emitNavigateAccept();
02287 e->setAccepted(true);
02288 return;
02289 }
02290 if( e->key() == Qt::Key_Backspace && e->modifiers() == Qt::AltModifier ) {
02291 m_view->emitNavigateBack();
02292 e->setAccepted(true);
02293 return;
02294 }
02295
02296 if( e->key() == Qt::Key_Alt && view()->completionWidget()->isCompletionActive() ) {
02297 m_completionItemExpanded = view()->completionWidget()->toggleExpanded(true);
02298 view()->completionWidget()->resetHadNavigation();
02299 m_altDownTime = QTime::currentTime();
02300 }
02301
02302
02303 const int key = e->key() | (e->modifiers() & Qt::ShiftModifier);
02304
02305 if (m_view->isCompletionActive())
02306 {
02307 if( key == Qt::Key_Enter || key == Qt::Key_Return ) {
02308 m_view->completionWidget()->execute();
02309 e->accept();
02310 return;
02311 }
02312 }
02313
02314 if ( m_view->viInputMode() ) {
02315 if ( !m_view->config()->viInputModeHideStatusBar() ) {
02316 m_view->viModeBar()->clearMessage();
02317 }
02318
02319 if ( getViInputModeManager()->getCurrentViMode() == InsertMode ) {
02320 if ( getViInputModeManager()->handleKeypress( e ) ) {
02321 return;
02322 } else if ( e->modifiers() != Qt::NoModifier && e->modifiers() != Qt::ShiftModifier ) {
02323
02324 QEvent *copy = new QKeyEvent ( e->type(), e->key(), e->modifiers(), e->text(),
02325 e->isAutoRepeat(), e->count() );
02326 QCoreApplication::postEvent( parent(), copy );
02327 }
02328 } else {
02329 if ( !getViInputModeManager()->handleKeypress( e ) ) {
02330
02331 QEvent *copy = new QKeyEvent ( e->type(), e->key(), e->modifiers(), e->text(),
02332 e->isAutoRepeat(), e->count() );
02333 QCoreApplication::postEvent( parent(), copy );
02334 }
02335 m_view->updateViModeBarCmd();
02336 return;
02337 }
02338 }
02339
02340 if( !m_doc->isReadWrite() )
02341 {
02342 e->ignore();
02343 return;
02344 }
02345
02346 if ((key == Qt::Key_Return) || (key == Qt::Key_Enter))
02347 {
02348 doReturn();
02349 e->accept();
02350 return;
02351 }
02352
02353 if (key == Qt::Key_Backspace || key == Qt::SHIFT + Qt::Key_Backspace)
02354 {
02355
02356 e->accept();
02357
02358 return;
02359 }
02360
02361 if (key == Qt::Key_Tab || key == Qt::SHIFT+Qt::Key_Backtab || key == Qt::Key_Backtab)
02362 {
02363 if (m_doc->invokeTemplateHandler(key)) {
02364 e->accept();
02365 return;
02366 }
02367
02368 if( key == Qt::Key_Tab )
02369 {
02370 uint tabHandling = m_doc->config()->tabHandling();
02371
02372 if (tabHandling == KateDocumentConfig::tabSmart)
02373 {
02374 if (m_view->selection())
02375 {
02376 tabHandling = KateDocumentConfig::tabIndents;
02377 }
02378 else
02379 {
02380
02381
02382
02383 KateTextLine::Ptr line = m_doc->kateTextLine( m_cursor.line() );
02384 int first = line->firstChar();
02385 if (first < 0 || m_cursor.column() <= first)
02386 tabHandling = KateDocumentConfig::tabIndents;
02387 else
02388 tabHandling = KateDocumentConfig::tabInsertsTab;
02389 }
02390 }
02391
02392 if (tabHandling == KateDocumentConfig::tabInsertsTab)
02393 m_doc->typeChars( m_view, QString("\t") );
02394 else
02395 m_doc->indent( m_view, m_cursor.line(), 1 );
02396
02397 e->accept();
02398
02399 return;
02400 }
02401 else if (m_doc->config()->tabHandling() != KateDocumentConfig::tabInsertsTab)
02402 {
02403
02404 m_doc->indent( m_view, m_cursor.line(), -1 );
02405 e->accept();
02406
02407 return;
02408 }
02409 }
02410
02411 if ( !(e->modifiers() & Qt::ControlModifier) && !e->text().isEmpty() && m_doc->typeChars ( m_view, e->text() ) )
02412 {
02413 e->accept();
02414
02415 return;
02416 }
02417
02418
02419 static const int altGR = Qt::ControlModifier | Qt::AltModifier;
02420 if( (e->modifiers() & altGR) == altGR && !e->text().isEmpty() && m_doc->typeChars ( m_view, e->text() ) )
02421 {
02422 e->accept();
02423
02424 return;
02425 }
02426
02427 e->ignore();
02428 }
02429
02430 void KateViewInternal::keyReleaseEvent( QKeyEvent* e )
02431 {
02432 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())) ) {
02433
02434 view()->completionWidget()->toggleExpanded(false, true);
02435 }
02436
02437 if (e->key() == Qt::SHIFT)
02438 {
02439 m_shiftKeyPressed = true;
02440 }
02441 else
02442 {
02443 if (m_shiftKeyPressed)
02444 {
02445 m_shiftKeyPressed = false;
02446
02447 if (m_selChangedByUser)
02448 {
02449 if (m_view->selection())
02450 QApplication::clipboard()->setText(m_view->selectionText (), QClipboard::Selection);
02451
02452 m_selChangedByUser = false;
02453 }
02454 }
02455 }
02456
02457 e->ignore();
02458 return;
02459 }
02460
02461 void KateViewInternal::contextMenuEvent ( QContextMenuEvent * e )
02462 {
02463
02464
02465 QPoint p = e->pos();
02466
02467 if ( m_view->m_doc->browserView() )
02468 {
02469 m_view->contextMenuEvent( e );
02470 return;
02471 }
02472
02473 if ( e->reason() == QContextMenuEvent::Keyboard )
02474 {
02475 makeVisible( m_cursor, 0 );
02476 p = cursorCoordinates(false);
02477 p.rx() -= startX();
02478 }
02479 else if ( ! m_view->selection() || m_view->config()->persistentSelection() )
02480 placeCursor( e->pos() );
02481
02482
02483 if (m_view->contextMenu()) {
02484 m_view->contextMenu()->popup( mapToGlobal( p ) );
02485 e->accept ();
02486 }
02487 }
02488
02489 void KateViewInternal::mousePressEvent( QMouseEvent* e )
02490 {
02491 switch (e->button())
02492 {
02493 case Qt::LeftButton:
02494 m_selChangedByUser = false;
02495
02496 if (m_possibleTripleClick)
02497 {
02498 m_possibleTripleClick = false;
02499
02500 m_selectionMode = Line;
02501
02502 if ( e->modifiers() & Qt::ShiftModifier )
02503 {
02504 updateSelection( m_cursor, true );
02505 }
02506 else
02507 {
02508 m_view->selectLine( m_cursor );
02509 }
02510
02511 if (m_view->selection())
02512 QApplication::clipboard()->setText(m_view->selectionText (), QClipboard::Selection);
02513
02514
02515
02516 if ( m_selectAnchor.line() > m_view->selectionRange().start().line() )
02517 {
02518
02519 if ( m_selectAnchor == m_view->selectionRange().end() && m_selectAnchor.column() == 0 )
02520 m_selectionCached.start().setPosition( m_selectAnchor.line()-1, 0 );
02521 else
02522 m_selectionCached.start().setPosition( m_selectAnchor.line(), 0 );
02523 m_selectionCached.end() = m_view->selectionRange().end();
02524 }
02525 else
02526 {
02527
02528 m_selectionCached.start() = m_view->selectionRange().start();
02529 if ( m_view->selectionRange().end().line() > m_view->selectionRange().start().line() )
02530 m_selectionCached.end().setPosition( m_view->selectionRange().start().line()+1, 0 );
02531 else
02532 m_selectionCached.end() = m_view->selectionRange().end();
02533 }
02534
02535
02536
02537 if ( m_view->selectionRange().start() < m_selectAnchor
02538 && m_selectAnchor.line() != m_view->selectionRange().start().line() )
02539 updateCursor( m_view->selectionRange().start() );
02540 else
02541 updateCursor( m_view->selectionRange().end() );
02542
02543 e->accept();
02544 return;
02545 }
02546 else if ( m_selectionMode == Default )
02547 {
02548 m_selectionMode = Mouse;
02549 }
02550
02551 if ( e->modifiers() & Qt::ShiftModifier )
02552 {
02553 if ( !m_selectAnchor.isValid() )
02554 m_selectAnchor = m_cursor;
02555 }
02556 else
02557 {
02558 m_selectionCached = KTextEditor::Range::invalid();
02559 }
02560
02561 if( !(e->modifiers() & Qt::ShiftModifier) && isTargetSelected( e->pos() ) )
02562 {
02563 m_dragInfo.state = diPending;
02564 m_dragInfo.start = e->pos();
02565 }
02566 else
02567 {
02568 m_dragInfo.state = diNone;
02569
02570 if ( e->modifiers() & Qt::ShiftModifier )
02571 {
02572 placeCursor( e->pos(), true, false );
02573 if ( m_selectionCached.start().isValid() )
02574 {
02575 if ( m_cursor < m_selectionCached.start() )
02576 m_selectAnchor = m_selectionCached.end();
02577 else
02578 m_selectAnchor = m_selectionCached.start();
02579 }
02580 m_view->setSelection( KTextEditor::Range( m_selectAnchor, m_cursor ) );
02581 }
02582 else
02583 {
02584 placeCursor( e->pos() );
02585 }
02586
02587 m_scrollX = 0;
02588 m_scrollY = 0;
02589
02590 m_scrollTimer.start (50);
02591 }
02592
02593 e->accept ();
02594 break;
02595
02596 default:
02597 e->ignore ();
02598 break;
02599 }
02600 }
02601
02602 void KateViewInternal::mouseDoubleClickEvent(QMouseEvent *e)
02603 {
02604 switch (e->button())
02605 {
02606 case Qt::LeftButton:
02607 m_selectionMode = Word;
02608
02609 if ( e->modifiers() & Qt::ShiftModifier )
02610 {
02611 KTextEditor::Range oldSelection = m_view->selectionRange();
02612
02613
02614 int cs, ce;
02615 KateTextLine::Ptr l = m_doc->kateTextLine( m_selectAnchor.line() );
02616
02617 ce = m_selectAnchor.column();
02618 if ( ce > 0 && m_doc->highlight()->isInWord( l->at(ce) ) ) {
02619 for (; ce < l->length(); ce++ )
02620 if ( !m_doc->highlight()->isInWord( l->at(ce) ) )
02621 break;
02622 }
02623
02624 cs = m_selectAnchor.column() - 1;
02625 if ( cs < m_doc->lineLength( m_selectAnchor.line() )
02626 && m_doc->highlight()->isInWord( l->at(cs) ) ) {
02627 for ( cs--; cs >= 0; cs-- )
02628 if ( !m_doc->highlight()->isInWord( l->at(cs) ) )
02629 break;
02630 }
02631
02632
02633 if (cs+1 < ce)
02634 {
02635 m_selectionCached.start().setPosition( m_selectAnchor.line(), cs+1 );
02636 m_selectionCached.end().setPosition( m_selectAnchor.line(), ce );
02637 }
02638 else
02639 {
02640 m_selectionCached.start() = m_selectAnchor;
02641 m_selectionCached.end() = m_selectAnchor;
02642 }
02643
02644 placeCursor( e->pos(), true );
02645 }
02646 else
02647 {
02648
02649
02650
02651
02652
02653 m_view->clearSelection( false, false );
02654 placeCursor( e->pos() );
02655 m_view->selectWord( m_cursor );
02656
02657 if (m_view->selection())
02658 {
02659 m_selectAnchor = m_view->selectionRange().start();
02660 m_selectionCached = m_view->selectionRange();
02661 }
02662 else
02663 {
02664
02665
02666 m_selectionMode = Default;
02667 }
02668 }
02669
02670
02671 if (m_view->selection())
02672 {
02673 QApplication::clipboard()->setText( m_view->selectionText(), QClipboard::Selection );
02674
02675
02676
02677 if (m_view->selectionRange().start() < m_selectionCached.start())
02678 updateCursor( m_view->selectionRange().start() );
02679 else
02680 updateCursor( m_view->selectionRange().end() );
02681 }
02682
02683 m_possibleTripleClick = true;
02684 QTimer::singleShot ( QApplication::doubleClickInterval(), this, SLOT(tripleClickTimeout()) );
02685
02686 m_scrollX = 0;
02687 m_scrollY = 0;
02688
02689 m_scrollTimer.start (50);
02690
02691 e->accept ();
02692 break;
02693
02694 default:
02695 e->ignore ();
02696 break;
02697 }
02698 }
02699
02700 void KateViewInternal::tripleClickTimeout()
02701 {
02702 m_possibleTripleClick = false;
02703 }
02704
02705 void KateViewInternal::mouseReleaseEvent( QMouseEvent* e )
02706 {
02707 switch (e->button())
02708 {
02709 case Qt::LeftButton:
02710 m_selectionMode = Default;
02711
02712
02713 if (m_selChangedByUser)
02714 {
02715 if (m_view->selection()) {
02716 QApplication::clipboard()->setText(m_view->selectionText (), QClipboard::Selection);
02717
02718
02719
02720 if ( m_view->selectionRange().start() < m_selectAnchor )
02721 updateCursor( m_view->selectionRange().start() );
02722 else
02723 updateCursor( m_view->selectionRange().end() );
02724 }
02725
02726 m_selChangedByUser = false;
02727 }
02728
02729 if (m_dragInfo.state == diPending)
02730 placeCursor( e->pos(), e->modifiers() & Qt::ShiftModifier );
02731 else if (m_dragInfo.state == diNone)
02732 m_scrollTimer.stop ();
02733
02734 m_dragInfo.state = diNone;
02735
02736 e->accept ();
02737 break;
02738
02739 case Qt::MidButton:
02740 placeCursor( e->pos() );
02741
02742 if( m_doc->isReadWrite() )
02743 {
02744 m_doc->paste( m_view, QClipboard::Selection );
02745 repaint();
02746 }
02747
02748 e->accept ();
02749 break;
02750
02751 default:
02752 e->ignore ();
02753 break;
02754 }
02755 }
02756
02757 void KateViewInternal::leaveEvent( QEvent* )
02758 {
02759 m_textHintTimer.stop();
02760 }
02761
02762 KTextEditor::Cursor KateViewInternal::coordinatesToCursor(const QPoint& _coord) const
02763 {
02764 QPoint coord(_coord);
02765
02766 KTextEditor::Cursor ret = KTextEditor::Cursor::invalid();
02767
02768 coord.setX( coord.x() - m_leftBorder->width() + startX() );
02769
02770 const KateTextLayout& thisLine = yToKateTextLayout(coord.y());
02771 if (thisLine.isValid())
02772 ret = renderer()->xToCursor(thisLine, coord.x(), !view()->wrapCursor());
02773
02774 return ret;
02775 }
02776
02777 void KateViewInternal::mouseMoveEvent( QMouseEvent* e )
02778 {
02779
02780 const KateTextLayout& thisLine = yToKateTextLayout(e->y());
02781 if (thisLine.isValid()) {
02782 KTextEditor::Cursor newPosition = renderer()->xToCursor(thisLine, e->x(), !view()->wrapCursor());
02783 if (newPosition != m_mouse) {
02784 m_mouse = newPosition;
02785 mouseMoved();
02786 }
02787 } else {
02788 if (m_mouse.isValid()) {
02789 m_mouse = KTextEditor::Cursor::invalid();
02790 mouseMoved();
02791 }
02792 }
02793
02794 if( e->buttons() & Qt::LeftButton )
02795 {
02796 if (m_dragInfo.state == diPending)
02797 {
02798
02799
02800 QPoint p( e->pos() - m_dragInfo.start );
02801
02802
02803 if( p.manhattanLength() > KGlobalSettings::dndEventDelay() )
02804 doDrag();
02805
02806 return;
02807 }
02808 else if (m_dragInfo.state == diDragging)
02809 {
02810
02811
02812 return;
02813 }
02814
02815 m_mouseX = e->x();
02816 m_mouseY = e->y();
02817
02818 m_scrollX = 0;
02819 m_scrollY = 0;
02820 int d = renderer()->fontHeight();
02821
02822 if (m_mouseX < 0)
02823 m_scrollX = -d;
02824
02825 if (m_mouseX > width())
02826 m_scrollX = d;
02827
02828 if (m_mouseY < 0)
02829 {
02830 m_mouseY = 0;
02831 m_scrollY = -d;
02832 }
02833
02834 if (m_mouseY > height())
02835 {
02836 m_mouseY = height();
02837 m_scrollY = d;
02838 }
02839
02840 placeCursor( QPoint( m_mouseX, m_mouseY ), true );
02841
02842 }
02843 else
02844 {
02845 if (isTargetSelected( e->pos() ) ) {
02846
02847
02848 if (m_mouseCursor != Qt::ArrowCursor) {
02849 m_mouseCursor = Qt::ArrowCursor;
02850 setCursor(m_mouseCursor);
02851 }
02852 } else {
02853
02854 if (m_mouseCursor != Qt::IBeamCursor) {
02855 m_mouseCursor = Qt::IBeamCursor;
02856 setCursor(m_mouseCursor);
02857 }
02858 }
02859
02860
02861
02862 if (m_textHintEnabled && geometry().contains(parentWidget()->mapFromGlobal(e->globalPos())))
02863 {
02864 m_textHintTimer.start(m_textHintTimeout);
02865 m_textHintMouseX=e->x();
02866 m_textHintMouseY=e->y();
02867 }
02868 }
02869 }
02870
02871 void KateViewInternal::updateDirty( )
02872 {
02873 uint h = renderer()->fontHeight();
02874
02875 int currentRectStart = -1;
02876 int currentRectEnd = -1;
02877
02878 QRegion updateRegion;
02879
02880 {
02881 QMutexLocker lock(m_doc->smartMutex());
02882
02883 for (int i = 0; i < cache()->viewCacheLineCount(); ++i) {
02884 if (cache()->viewLine(i).isDirty()) {
02885 if (currentRectStart == -1) {
02886 currentRectStart = h * i;
02887 currentRectEnd = h;
02888 } else {
02889 currentRectEnd += h;
02890 }
02891
02892 } else if (currentRectStart != -1) {
02893 updateRegion += QRect(0, currentRectStart, width(), currentRectEnd);
02894 currentRectStart = -1;
02895 currentRectEnd = -1;
02896 }
02897 }
02898 }
02899
02900
02901 if (currentRectStart != -1)
02902 updateRegion += QRect(0, currentRectStart, width(), currentRectEnd);
02903
02904 if (!updateRegion.isEmpty()) {
02905 if (debugPainting) kDebug( 13030 ) << k_funcinfo << "Update dirty region " << updateRegion;
02906 update(updateRegion);
02907 }
02908 }
02909
02910 void KateViewInternal::hideEvent(QHideEvent* e)
02911 {
02912 Q_UNUSED(e);
02913 if(m_view->isCompletionActive())
02914 m_view->completionWidget()->abortCompletion();
02915 }
02916
02917 void KateViewInternal::paintEvent(QPaintEvent *e)
02918 {
02919 QMutexLocker lock(m_doc->smartMutex());
02920
02921 if (m_smartDirty)
02922 doUpdateView();
02923
02924 if (debugPainting) kDebug (13030) << "GOT PAINT EVENT: Region" << e->region();
02925
02926 const QRect& unionRect = e->rect();
02927
02928 int xStart = startX() + unionRect.x();
02929 int xEnd = xStart + unionRect.width();
02930 uint h = renderer()->fontHeight();
02931 uint startz = (unionRect.y() / h);
02932 uint endz = startz + 1 + (unionRect.height() / h);
02933 uint lineRangesSize = cache()->viewCacheLineCount();
02934
02935 QPainter paint(this);
02936 paint.setRenderHints (QPainter::Antialiasing);
02937
02938
02939 renderer()->setCaretStyle(m_view->isOverwriteMode() ? KateRenderer::Block : KateRenderer::Line);
02940 renderer()->setShowTabs(m_doc->config()->configFlags() & KateDocumentConfig::cfShowTabs);
02941 renderer()->setShowTrailingSpaces(m_doc->config()->configFlags() & KateDocumentConfig::cfShowSpaces);
02942
02943 int sy = startz * h;
02944 paint.translate(unionRect.x(), startz * h);
02945
02946 for (uint z=startz; z <= endz; z++)
02947 {
02948 if ( (z >= lineRangesSize) || (cache()->viewLine(z).line() == -1) )
02949 {
02950 if (!(z >= lineRangesSize))
02951 cache()->viewLine(z).setDirty(false);
02952
02953 paint.fillRect( 0, 0, unionRect.width(), h, renderer()->config()->backgroundColor() );
02954 }
02955 else
02956 {
02957
02958 KateTextLayout& thisLine = cache()->viewLine(z);
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968 if (!thisLine.viewLine() || z == startz) {
02969
02970 if (!e->region().contains(QRect(unionRect.x(), startz * h, unionRect.width(), h)))
02971 continue;
02972
02973
02974
02975
02976 if (thisLine.viewLine())
02977 paint.translate(QPoint(0, h * - thisLine.viewLine()));
02978
02979
02980
02981
02982 renderer()->paintTextLine(paint, thisLine.kateLineLayout(), xStart, xEnd, &m_cursor);
02983
02984
02985
02986 if (thisLine.viewLine())
02987 paint.translate(0, h * thisLine.viewLine());
02988
02989 thisLine.setDirty(false);
02990 }
02991 }
02992
02993 paint.translate(0, h);
02994 sy += h;
02995 }
02996 }
02997
02998 void KateViewInternal::resizeEvent(QResizeEvent* e)
02999 {
03000 bool expandedHorizontally = width() > e->oldSize().width();
03001 bool expandedVertically = height() > e->oldSize().height();
03002 bool heightChanged = height() != e->oldSize().height();
03003
03004 m_madeVisible = false;
03005
03006 if (heightChanged) {
03007 setAutoCenterLines(m_autoCenterLines, false);
03008 m_cachedMaxStartPos.setPosition(-1, -1);
03009 }
03010
03011 if (m_view->dynWordWrap()) {
03012 bool dirtied = false;
03013
03014 QMutexLocker lock(m_doc->smartMutex());
03015
03016 for (int i = 0; i < cache()->viewCacheLineCount(); i++) {
03017
03018
03019 bool lineNeedsRedraw = false;
03020
03021 if (cache()->viewLine(i).wrap()) {
03022 lineNeedsRedraw = true;
03023
03024 } else if (const KateLineLayoutPtr& line = cache()->viewLine(i).kateLineLayout()) {
03025 if (QTextLayout* layout = line->layout())
03026 if (layout->textOption().textDirection() == Qt::RightToLeft)
03027 lineNeedsRedraw = true;
03028
03029 } else if (!expandedHorizontally && (cache()->viewLine(i).endX() - cache()->viewLine(i).startX()) > width()) {
03030 lineNeedsRedraw = true;
03031 }
03032
03033 if (lineNeedsRedraw) {
03034 dirtied = true;
03035 cache()->viewLine(i).setDirty();
03036 break;
03037 }
03038 }
03039
03040 if (dirtied || heightChanged) {
03041 updateView(true);
03042 m_leftBorder->update();
03043 }
03044
03045 if (width() < e->oldSize().width()) {
03046 if (!m_view->wrapCursor()) {
03047
03048 if (m_cursor.column() > m_doc->lineLength(m_cursor.line())) {
03049 KateTextLayout thisLine = currentLayout();
03050
03051 KTextEditor::Cursor newCursor(m_cursor.line(), thisLine.endCol() + ((width() - thisLine.xOffset() - thisLine.width()) / renderer()->spaceWidth()) - 1);
03052 lock.unlock();
03053 updateCursor(newCursor);
03054 lock.relock();
03055 }
03056 }
03057 }
03058
03059 } else {
03060 updateView();
03061
03062 if (expandedHorizontally && startX() > 0)
03063 scrollColumns(startX() - (width() - e->oldSize().width()));
03064 }
03065
03066 if (expandedVertically) {
03067 KTextEditor::Cursor max = maxStartPos();
03068 if (startPos() > max)
03069 scrollPos(max);
03070 }
03071 }
03072
03073 void KateViewInternal::scrollTimeout ()
03074 {
03075 if (m_scrollX || m_scrollY)
03076 {
03077 scrollLines (startPos().line() + (m_scrollY / (int) renderer()->fontHeight()));
03078 placeCursor( QPoint( m_mouseX, m_mouseY ), true );
03079 }
03080 }
03081
03082 void KateViewInternal::cursorTimeout ()
03083 {
03084 if (!debugPainting && !m_view->viInputMode()) {
03085 renderer()->setDrawCaret(!renderer()->drawCaret());
03086 paintCursor();
03087 }
03088 }
03089
03090 void KateViewInternal::textHintTimeout ()
03091 {
03092 m_textHintTimer.stop ();
03093
03094 KateTextLayout thisLine = yToKateTextLayout(m_textHintMouseY);
03095
03096 if (!thisLine.isValid()) return;
03097
03098 if (m_textHintMouseX> (lineMaxCursorX(thisLine) - thisLine.startX())) return;
03099
03100 KTextEditor::Cursor c = thisLine.start();
03101
03102 {
03103 QMutexLocker lock(m_doc->smartMutex());
03104 c = renderer()->xToCursor(cache()->textLayout(c), startX() + m_textHintMouseX, !view()->wrapCursor());
03105 }
03106
03107 QString tmp;
03108
03109 emit m_view->needTextHint(c, tmp);
03110
03111 if (!tmp.isEmpty()) kDebug(13030)<<"Hint text: "<<tmp;
03112 }
03113
03114 void KateViewInternal::focusInEvent (QFocusEvent *)
03115 {
03116 if (KApplication::cursorFlashTime() > 0)
03117 m_cursorTimer.start ( KApplication::cursorFlashTime() / 2 );
03118
03119 paintCursor();
03120
03121 m_doc->setActiveView( m_view );
03122
03123
03124 m_view->slotGotFocus ();
03125 }
03126
03127 void KateViewInternal::focusOutEvent (QFocusEvent *)
03128 {
03129
03130
03131
03132 m_cursorTimer.stop();
03133 m_view->renderer()->setDrawCaret(true);
03134 paintCursor();
03135
03136 m_textHintTimer.stop();
03137
03138 m_view->slotLostFocus ();
03139 }
03140
03141 void KateViewInternal::doDrag()
03142 {
03143 m_dragInfo.state = diDragging;
03144 m_dragInfo.dragObject = new QDrag(this);
03145 QMimeData *mimeData=new QMimeData();
03146 mimeData->setText(m_view->selectionText());
03147 m_dragInfo.dragObject->setMimeData(mimeData);
03148 m_dragInfo.dragObject->start(Qt::MoveAction);
03149 }
03150
03151 void KateViewInternal::dragEnterEvent( QDragEnterEvent* event )
03152 {
03153 if (event->source()==this) event->setDropAction(Qt::MoveAction);
03154 event->setAccepted( (event->mimeData()->hasText() && m_doc->isReadWrite()) ||
03155 KUrl::List::canDecode(event->mimeData()) );
03156 }
03157
03158 void KateViewInternal::fixDropEvent(QDropEvent* event) {
03159 if (event->source()!=this) event->setDropAction(Qt::CopyAction);
03160 else {
03161 Qt::DropAction action=Qt::MoveAction;
03162 #ifdef Q_WS_MAC
03163 if(event->keyboardModifiers() & Qt::AltModifier)
03164 action = Qt::CopyAction;
03165 #else
03166 if (event->keyboardModifiers() & Qt::ControlModifier)
03167 action = Qt::CopyAction;
03168 #endif
03169 event->setDropAction(action);
03170 }
03171 }
03172
03173 void KateViewInternal::dragMoveEvent( QDragMoveEvent* event )
03174 {
03175
03176 placeCursor( event->pos(), true, false );
03177
03178
03179
03180 fixDropEvent(event);
03181 }
03182
03183 void KateViewInternal::dropEvent( QDropEvent* event )
03184 {
03185 if ( KUrl::List::canDecode(event->mimeData()) ) {
03186
03187 emit dropEventPass(event);
03188
03189 } else if ( event->mimeData()->hasText() && m_doc->isReadWrite() ) {
03190
03191 QString text=event->mimeData()->text();
03192
03193
03194 bool priv = false;
03195 if (KateViewInternal* vi = qobject_cast<KateViewInternal*>(event->source()))
03196 priv = m_doc->ownedView( vi->m_view );
03197
03198
03199 bool selected = m_view->cursorSelected(m_cursor);
03200
03201 if( priv && selected ) {
03202
03203
03204 return;
03205 }
03206
03207 fixDropEvent(event);
03208
03209
03210
03211 KTextEditor::Cursor targetCursor(m_cursor);
03212 if ( event->dropAction() != Qt::CopyAction ) {
03213 editSetCursor(m_view->selectionRange().end());
03214 } else {
03215 m_view->clearSelection();
03216 }
03217
03218
03219 m_doc->editStart ();
03220
03221
03222 m_doc->insertText(targetCursor, text );
03223
03224 KateSmartCursor startCursor(targetCursor,m_doc);
03225
03226 if ( event->dropAction() != Qt::CopyAction )
03227 m_view->removeSelectedText();
03228
03229 KateSmartCursor endCursor1(startCursor,m_doc);
03230 endCursor1.advance(text.length(),KTextEditor::SmartCursor::ByCharacter);
03231 KTextEditor::Cursor endCursor(endCursor1);
03232 kDebug( 13030 )<<startCursor<<"---("<<text.length()<<")---"<<endCursor;
03233 m_view->setSelection(KTextEditor::Range(startCursor,endCursor));
03234 editSetCursor(endCursor);
03235
03236 m_doc->editEnd ();
03237
03238 event->acceptProposedAction();
03239 updateView();
03240 }
03241
03242
03243 m_dragInfo.state = diNone;
03244
03245 stopDragScroll();
03246 }
03247
03248
03249 void KateViewInternal::clear()
03250 {
03251 m_startPos = m_displayCursor = m_cursor = KTextEditor::Cursor(0, 0);
03252 updateView(true);
03253 }
03254
03255 void KateViewInternal::wheelEvent(QWheelEvent* e)
03256 {
03257 if (m_lineScroll->minimum() != m_lineScroll->maximum() && e->orientation() != Qt::Horizontal) {
03258
03259 if ( ( e->modifiers() & Qt::ControlModifier ) || ( e->modifiers() & Qt::ShiftModifier ) ) {
03260 if (e->delta() > 0)
03261 scrollPrevPage();
03262 else
03263 scrollNextPage();
03264 } else {
03265 scrollViewLines(-((e->delta() / 120) * QApplication::wheelScrollLines()));
03266 }
03267
03268 } else if (columnScrollingPossible()) {
03269 QWheelEvent copy = *e;
03270 QApplication::sendEvent(m_columnScroll, ©);
03271
03272 } else {
03273 e->ignore();
03274 }
03275 }
03276
03277 void KateViewInternal::startDragScroll()
03278 {
03279 if ( !m_dragScrollTimer.isActive() ) {
03280 m_dragScrollTimer.start( s_scrollTime );
03281 }
03282 }
03283
03284 void KateViewInternal::stopDragScroll()
03285 {
03286 m_dragScrollTimer.stop();
03287 updateView();
03288 }
03289
03290 void KateViewInternal::doDragScroll()
03291 {
03292 QPoint p = this->mapFromGlobal( QCursor::pos() );
03293
03294 int dx = 0, dy = 0;
03295 if ( p.y() < s_scrollMargin ) {
03296 dy = p.y() - s_scrollMargin;
03297 } else if ( p.y() > height() - s_scrollMargin ) {
03298 dy = s_scrollMargin - (height() - p.y());
03299 }
03300
03301 if ( p.x() < s_scrollMargin ) {
03302 dx = p.x() - s_scrollMargin;
03303 } else if ( p.x() > width() - s_scrollMargin ) {
03304 dx = s_scrollMargin - (width() - p.x());
03305 }
03306
03307 dy /= 4;
03308
03309 if (dy)
03310 scrollLines(startPos().line() + dy);
03311
03312 if (columnScrollingPossible () && dx)
03313 scrollColumns(qMin (m_startX + dx, m_columnScroll->maximum()));
03314
03315 if (!dy && !dx)
03316 stopDragScroll();
03317 }
03318
03319 void KateViewInternal::enableTextHints(int timeout)
03320 {
03321 m_textHintTimeout=timeout;
03322 m_textHintEnabled=true;
03323 m_textHintTimer.start(timeout);
03324 }
03325
03326 void KateViewInternal::disableTextHints()
03327 {
03328 m_textHintEnabled=false;
03329 m_textHintTimer.stop ();
03330 }
03331
03332
03333 void KateViewInternal::editStart()
03334 {
03335 editSessionNumber++;
03336
03337 if (editSessionNumber > 1)
03338 return;
03339
03340 editIsRunning = true;
03341 editOldCursor = m_cursor;
03342 }
03343
03344 void KateViewInternal::editEnd(int editTagLineStart, int editTagLineEnd, bool tagFrom)
03345 {
03346 if (editSessionNumber == 0)
03347 return;
03348
03349 editSessionNumber--;
03350
03351 if (editSessionNumber > 0)
03352 return;
03353
03354 if (tagFrom && (editTagLineStart <= int(m_doc->getRealLine(startLine()))))
03355 tagAll();
03356 else
03357 tagLines (editTagLineStart, tagFrom ? qMax(m_doc->lastLine() + 1, editTagLineEnd) : editTagLineEnd, true);
03358
03359 if (editOldCursor == m_cursor)
03360 updateBracketMarks();
03361
03362 updateView(true);
03363
03364 if (editOldCursor != m_cursor || m_view == m_doc->activeView())
03365 {
03366 m_madeVisible = false;
03367 updateCursor ( m_cursor, true );
03368 }
03369
03370 editIsRunning = false;
03371 }
03372
03373 void KateViewInternal::editSetCursor (const KTextEditor::Cursor &_cursor)
03374 {
03375 if (m_cursor != _cursor)
03376 {
03377 m_cursor = _cursor;
03378 }
03379 }
03380
03381
03382 void KateViewInternal::viewSelectionChanged ()
03383 {
03384 if (!m_view->selection())
03385 {
03386 m_selectAnchor = KTextEditor::Cursor::invalid();
03387
03388
03389
03390
03391
03392 m_selectionCached.start() = KTextEditor::Cursor::invalid();
03393
03394 }
03395 }
03396
03397 KateLayoutCache* KateViewInternal::cache( ) const
03398 {
03399 return m_layoutCache;
03400 }
03401
03402 KTextEditor::Cursor KateViewInternal::toRealCursor( const KTextEditor::Cursor & virtualCursor ) const
03403 {
03404 return KTextEditor::Cursor(m_doc->getRealLine(virtualCursor.line()), virtualCursor.column());
03405 }
03406
03407 KTextEditor::Cursor KateViewInternal::toVirtualCursor( const KTextEditor::Cursor & realCursor ) const
03408 {
03409 return KTextEditor::Cursor(m_doc->getVirtualLine(realCursor.line()), realCursor.column());
03410 }
03411
03412 KateRenderer * KateViewInternal::renderer( ) const
03413 {
03414 return m_view->renderer();
03415 }
03416
03417 void KateViewInternal::dynamicHighlightAdded( KateSmartRange * range )
03418 {
03419 QMutexLocker lock(m_doc->smartMutex());
03420
03421 DynamicRangeHL* hl = new DynamicRangeHL(range);
03422 hl->isView = view() == sender();
03423
03424 m_dynamicHighlights.insert(range, hl);
03425
03426 if (m_mouse.isValid())
03427
03428 dynamicMoved(true);
03429
03430 dynamicMoved(false);
03431 }
03432
03433 void KateViewInternal::dynamicHighlightRemoved( KateSmartRange * range )
03434 {
03435 QMutexLocker lock(m_doc->smartMutex());
03436
03437 removeWatcher(range, this);
03438
03439 delete m_dynamicHighlights.take(range);
03440 }
03441
03442 void KateViewInternal::rangeDeleted( KateSmartRange * range )
03443 {
03444 QMutexLocker lock(m_doc->smartMutex());
03445
03446 if (m_dynamicHighlights.contains(range)) {
03447 delete m_dynamicHighlights.take(range);
03448 return;
03449 }
03450
03451 foreach (DynamicRangeHL* hl, m_dynamicHighlights) {
03452
03453 if (hl->mouseAnimations.contains(range))
03454 delete hl->mouseAnimations.take(range);
03455
03456 if (hl->mouseOver && (hl->mouseOver == range || hl->mouseOver->hasParent(range))) {
03457 hl->mouseOver = static_cast<KateSmartRange*>(range->parentRange());
03458 }
03459
03460 if (hl->caretAnimations.contains(range))
03461 delete hl->caretAnimations.take(range);
03462
03463 if (hl->caretOver && (hl->caretOver == range || hl->caretOver->hasParent(range))) {
03464 hl->caretOver = static_cast<KateSmartRange*>(range->parentRange());
03465 }
03466 }
03467 }
03468
03469 void KateViewInternal::startDynamic( DynamicRangeHL* hl, KateSmartRange* range, KTextEditor::Attribute::ActivationType type )
03470 {
03471 QMutexLocker lock(m_doc->smartMutex());
03472
03473 if (type == KTextEditor::Attribute::ActivateMouseIn)
03474 range->setMouseOver(true);
03475 else
03476 range->setCaretOver(true);
03477
03478 if (!range->attribute() || !range->attribute()->dynamicAttribute(type))
03479 return;
03480
03481 KateDynamicAnimation* anim;
03482 if (hl->isView)
03483 anim = new KateDynamicAnimation(view(), range, type);
03484 else
03485 anim = new KateDynamicAnimation(m_doc, range, type);
03486
03487 connect(anim, SIGNAL(redraw(KateSmartRange*)), SLOT(updateRange(KateSmartRange*)));
03488
03489 if (type == KTextEditor::Attribute::ActivateMouseIn)
03490 hl->mouseAnimations.insert(range, anim);
03491 else
03492 hl->caretAnimations.insert(range, anim);
03493
03494 renderer()->dynamicRegion().addRange(range);
03495 }
03496
03497 void KateViewInternal::endDynamic( DynamicRangeHL* hl, KateSmartRange* range, KTextEditor::Attribute::ActivationType type )
03498 {
03499 QMutexLocker lock(m_doc->smartMutex());
03500
03501 if (type == KTextEditor::Attribute::ActivateMouseIn)
03502 range->setMouseOver(false);
03503 else
03504 range->setCaretOver(false);
03505
03506 if (!range->attribute() || !range->attribute()->dynamicAttribute(type))
03507 return;
03508
03509 KateDynamicAnimation* anim = 0L;
03510 if (type == KTextEditor::Attribute::ActivateMouseIn) {
03511 Q_ASSERT(hl->mouseAnimations.contains(range));
03512 anim = hl->mouseAnimations.take(range);
03513
03514 } else {
03515 Q_ASSERT(hl->caretAnimations.contains(range));
03516 anim = hl->caretAnimations.take(range);
03517 }
03518
03519 if (anim)
03520 anim->finish();
03521
03522
03523
03524
03525
03526
03527 }
03528
03529 void KateViewInternal::updateRange(KateSmartRange* range)
03530 {
03531
03532 tagRange(*range, true);
03533 updateDirty();
03534 }
03535
03536 void KateViewInternal::dynamicMoved( bool mouse )
03537 {
03538 QMutexLocker lock(m_doc->smartMutex());
03539
03540 foreach (DynamicRangeHL* hl, m_dynamicHighlights) {
03541 QStack<KTextEditor::SmartRange*> enterStack, exitStack;
03542 KTextEditor::SmartRange* oldRange = mouse ? hl->mouseOver : hl->caretOver;
03543 KTextEditor::SmartRange* newRange;
03544 if (mouse)
03545 newRange = (hl->mouseOver ? hl->mouseOver : hl->top)->deepestRangeContaining(m_mouse, &enterStack, &exitStack);
03546 else
03547 newRange = (hl->caretOver ? hl->caretOver : hl->top)->deepestRangeContaining(m_cursor, &enterStack, &exitStack);
03548
03549 if (newRange != oldRange) {
03550 if (newRange && !oldRange)
03551 enterStack.prepend(newRange);
03552
03553 foreach (KTextEditor::SmartRange* exitedRange, exitStack) {
03554 endDynamic(hl, static_cast<KateSmartRange*>(exitedRange), mouse ? KTextEditor::Attribute::ActivateMouseIn : KTextEditor::Attribute::ActivateCaretIn);
03555 static_cast<KateSmartRange*>(exitedRange)->feedbackMouseCaretChange(m_view, mouse, false);
03556 }
03557
03558 foreach (KTextEditor::SmartRange* enteredRange, enterStack) {
03559 static_cast<KateSmartRange*>(enteredRange)->feedbackMouseCaretChange(m_view, mouse, true);
03560 startDynamic(hl, static_cast<KateSmartRange*>(enteredRange), mouse ? KTextEditor::Attribute::ActivateMouseIn : KTextEditor::Attribute::ActivateCaretIn);
03561 }
03562
03563 if (mouse)
03564 hl->mouseOver = static_cast<KateSmartRange*>(newRange);
03565 else
03566 hl->caretOver = static_cast<KateSmartRange*>(newRange);
03567 }
03568 }
03569 }
03570
03571 void KateViewInternal::mouseMoved( )
03572 {
03573 view()->notifyMousePositionChanged(m_mouse);
03574
03575 dynamicMoved(true);
03576 }
03577
03578 KateViewInternal::DynamicRangeHL::DynamicRangeHL(KateSmartRange* _top)
03579 : top(_top)
03580 , isView(false)
03581 , caretOver(0L)
03582 , mouseOver(0L)
03583 {
03584 }
03585
03586 KateViewInternal::DynamicRangeHL::~ DynamicRangeHL( )
03587 {
03588 qDeleteAll(caretAnimations);
03589 qDeleteAll(mouseAnimations);
03590 }
03591
03592 void KateViewInternal::cursorMoved( )
03593 {
03594 dynamicMoved(false);
03595 }
03596
03597 bool KateViewInternal::rangeAffectsView(const KTextEditor::Range& range) const
03598 {
03599 if(range.end().line() < m_startPos.line())
03600 return false;
03601 if(range.start().line() > m_startPos.line() + m_visibleLineCount)
03602 return false;
03603
03604 return true;
03605 }
03606
03607 void KateViewInternal::relayoutRange( const KTextEditor::Range & range, bool realCursors )
03608 {
03609 int startLine = realCursors ? range.start().line() : toRealCursor(range.start()).line();
03610 int endLine = realCursors ? range.end().line() : toRealCursor(range.end()).line();
03611
03612
03613 cache()->relayoutLines(startLine, endLine);
03614
03615 const KateSmartRange* krange = dynamic_cast<const KateSmartRange*>(&range);
03616
03617 if (!m_smartDirty && (rangeAffectsView(range) ||
03618 (krange && rangeAffectsView(KTextEditor::Range(krange->kStart().lastPosition(), krange->kEnd().lastPosition()))))) {
03619 m_smartDirty = true;
03620 emit requestViewUpdateIfSmartDirty();
03621 }
03622 }
03623
03624 void KateViewInternal::rangePositionChanged( KTextEditor::SmartRange * range )
03625 {
03626
03627
03628
03629
03630
03631
03632
03633
03634 if(range->attribute())
03635 relayoutRange(*range);
03636 }
03637
03638 void KateViewInternal::rangeDeleted( KTextEditor::SmartRange * range )
03639 {
03640 QMutexLocker lock(m_doc->smartMutex());
03641
03642 if(range->attribute())
03643 relayoutRange(*range);
03644 }
03645
03646 void KateViewInternal::childRangeInserted( KTextEditor::SmartRange *, KTextEditor::SmartRange * child )
03647 {
03648 QMutexLocker lock(m_doc->smartMutex());
03649
03650 if(child->attribute() || child->childRanges().count())
03651 relayoutRange(*child);
03652
03653 addWatcher(child, this);
03654 }
03655
03656 void KateViewInternal::rangeAttributeChanged( KTextEditor::SmartRange * range, KTextEditor::Attribute::Ptr currentAttribute, KTextEditor::Attribute::Ptr previousAttribute )
03657 {
03658 QMutexLocker lock(m_doc->smartMutex());
03659
03660 if (currentAttribute != previousAttribute && !(currentAttribute && previousAttribute && *currentAttribute == *previousAttribute))
03661 relayoutRange(*range);
03662 }
03663
03664 void KateViewInternal::childRangeRemoved( KTextEditor::SmartRange *, KTextEditor::SmartRange * child )
03665 {
03666 QMutexLocker lock(m_doc->smartMutex());
03667
03668 if(child->attribute() || child->childRanges().count())
03669 relayoutRange(*child);
03670 removeWatcher(child, this);
03671 }
03672
03673 void KateViewInternal::addHighlightRange(KTextEditor::SmartRange* range)
03674 {
03675 QMutexLocker lock(m_doc->smartMutex());
03676
03677 relayoutRange(*range);
03678 ++m_watcherCount3;
03679 addWatcher(range, this);
03680 }
03681
03682 void KateViewInternal::removeHighlightRange(KTextEditor::SmartRange* range)
03683 {
03684 QMutexLocker lock(m_doc->smartMutex());
03685
03686 relayoutRange(*range);
03687 --m_watcherCount3;
03688 removeWatcher(range, this);
03689 }
03690
03691
03692 QVariant KateViewInternal::inputMethodQuery ( Qt::InputMethodQuery query ) const
03693 {
03694 switch (query) {
03695 case Qt::ImMicroFocus: {
03696
03697
03698
03699
03700
03701 KTextEditor::Cursor c = m_cursor;
03702 if (m_imPreedit)
03703 c = m_imPreedit->start();
03704 return QRect(cursorToCoordinate(c, true, false), QSize(0, renderer()->fontHeight()));
03705 }
03706
03707 case Qt::ImFont:
03708 return renderer()->currentFont();
03709
03710 case Qt::ImCursorPosition:
03711 if (m_imPreedit)
03712 return m_imPreedit->start().column();
03713 else
03714 return m_cursor.start().column();
03715
03716 case Qt::ImSurroundingText:
03717 if (KateTextLine::Ptr l = m_doc->kateTextLine(m_cursor.line()))
03718 return l->string();
03719 else
03720 return QString();
03721
03722 case Qt::ImCurrentSelection:
03723 if (view()->selection())
03724 return view()->selectionText();
03725 else
03726 return QString();
03727 }
03728
03729 return QWidget::inputMethodQuery(query);
03730 }
03731
03732 void KateViewInternal::inputMethodEvent(QInputMethodEvent* e)
03733 {
03734 if ( m_doc->readOnly() ) {
03735 e->ignore();
03736 return;
03737 }
03738
03739
03740
03741 if ( m_view->selection() )
03742 m_view->removeSelectedText();
03743
03744 bool createdPreedit = false;
03745 if (!m_imPreedit) {
03746 createdPreedit = true;
03747 m_imPreedit = m_view->doc()->smartManager()->newSmartRange(KTextEditor::Range(m_cursor, m_cursor), 0L, KTextEditor::SmartRange::ExpandLeft | KTextEditor::SmartRange::ExpandRight);
03748 }
03749
03750 if (!m_imPreedit->isEmpty()) {
03751 m_view->doc()->inputMethodStart();
03752 m_view->doc()->removeText(*m_imPreedit);
03753 m_view->doc()->inputMethodEnd();
03754 }
03755
03756 if (!e->commitString().isEmpty() || e->replacementLength()) {
03757 KTextEditor::Range preeditRange = *m_imPreedit;
03758
03759 KTextEditor::Cursor start(m_imPreedit->start().line(), m_imPreedit->start().column() + e->replacementStart());
03760 KTextEditor::Cursor removeEnd = start + KTextEditor::Cursor(0, e->replacementLength());
03761
03762 m_view->doc()->editStart(true);
03763 if (start != removeEnd)
03764 m_view->doc()->removeText(KTextEditor::Range(start, removeEnd));
03765 if (!e->commitString().isEmpty())
03766 m_view->doc()->insertText(start, e->commitString());
03767 m_view->doc()->editEnd();
03768
03769
03770 m_imPreedit->setRange(preeditRange);
03771 }
03772
03773 if (!e->preeditString().isEmpty()) {
03774 m_view->doc()->inputMethodStart();
03775 m_view->doc()->insertText(m_imPreedit->start(), e->preeditString());
03776 m_view->doc()->inputMethodEnd();
03777
03778 }
03779
03780
03781 if (m_imPreedit && e->preeditString().isEmpty()) {
03782 if (!createdPreedit)
03783 m_view->removeInternalHighlight(m_imPreedit);
03784
03785 delete m_imPreedit;
03786 m_imPreedit = 0L;
03787
03788 if ( KApplication::cursorFlashTime() > 0 )
03789 renderer()->setDrawCaret(false);
03790 renderer()->setCaretOverrideColor(QColor());
03791
03792 return;
03793 }
03794
03795 KTextEditor::Cursor newCursor = m_cursor;
03796 bool hideCursor = false;
03797 QColor caretColor;
03798
03799 if (m_imPreedit) {
03800 m_imPreedit->clearAndDeleteChildRanges();
03801
03802 int decorationColumn = 0;
03803 foreach (const QInputMethodEvent::Attribute &a, e->attributes()) {
03804 if (a.type == QInputMethodEvent::Cursor) {
03805 newCursor = m_imPreedit->start() + KTextEditor::Cursor(0, a.start);
03806 hideCursor = !a.length;
03807 QColor c = qvariant_cast<QColor>(a.value);
03808 if (c.isValid())
03809 caretColor = c;
03810
03811 } else if (a.type == QInputMethodEvent::TextFormat) {
03812 QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
03813 if (f.isValid() && decorationColumn <= a.start) {
03814 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);
03815 KTextEditor::SmartRange* formatRange = m_view->doc()->smartManager()->newSmartRange(fr, m_imPreedit);
03816 KTextEditor::Attribute::Ptr attribute(new KTextEditor::Attribute());
03817 attribute->merge(f);
03818 formatRange->setAttribute(attribute);
03819 decorationColumn = a.start + a.length;
03820 }
03821 }
03822 }
03823
03824 if (createdPreedit)
03825 m_view->addInternalHighlight(m_imPreedit);
03826 }
03827
03828 renderer()->setDrawCaret(hideCursor);
03829 renderer()->setCaretOverrideColor(caretColor);
03830
03831 if (newCursor != m_cursor)
03832 updateCursor(newCursor);
03833
03834 e->accept();
03835 }
03836
03837
03838
03839 ViMode KateViewInternal::getCurrentViMode()
03840 {
03841 return getViInputModeManager()->getCurrentViMode();
03842 }
03843
03844 KateViInputModeManager* KateViewInternal::getViInputModeManager()
03845 {
03846 if (!m_viInputModeManager) {
03847 m_viInputModeManager = new KateViInputModeManager(m_view, this);
03848 }
03849
03850 return m_viInputModeManager;
03851 }
03852
03853