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 #include "kateviewinternal.h"
00027 #include "kateviewinternal.moc"
00028
00029 #include "kateview.h"
00030 #include "katedocument.h"
00031 #include "katecodefoldinghelpers.h"
00032 #include "kateviewhelpers.h"
00033 #include "katehighlight.h"
00034 #include "katesupercursor.h"
00035 #include "katerenderer.h"
00036 #include "katecodecompletion.h"
00037 #include "kateconfig.h"
00038
00039 #include <kcursor.h>
00040 #include <kdebug.h>
00041 #include <kapplication.h>
00042 #include <kglobalsettings.h>
00043 #include <kurldrag.h>
00044
00045 #include <qstyle.h>
00046 #include <qdragobject.h>
00047 #include <qpopupmenu.h>
00048 #include <qdropsite.h>
00049 #include <qpainter.h>
00050 #include <qlayout.h>
00051 #include <qclipboard.h>
00052 #include <qpixmap.h>
00053
00054 static const int TimeMarkerEvent = 4321;
00055
00056 KateViewInternal::KateViewInternal(KateView *view, KateDocument *doc)
00057 : QWidget (view, "", Qt::WStaticContents | Qt::WRepaintNoErase | Qt::WResizeNoErase )
00058 , editSessionNumber (0)
00059 , editIsRunning (false)
00060 , m_view (view)
00061 , m_doc (doc)
00062 , m_scrollTranslateHack(0)
00063 , cursor (doc, true, 0, 0, this)
00064 , possibleTripleClick (false)
00065 , m_dummy (0)
00066 , m_startPos(0,0)
00067 , m_oldStartPos(0,0)
00068 , m_madeVisible(false)
00069 , m_shiftKeyPressed (false)
00070 , m_autoCenterLines (false)
00071 , m_columnScrollDisplayed(false)
00072 , m_selChangedByUser (false)
00073 , selectAnchor (-1, -1)
00074 , m_preserveMaxX(false)
00075 , m_currentMaxX(0)
00076 , m_usePlainLines(false)
00077 , m_updatingView(true)
00078 , m_cachedMaxStartPos(-1, -1)
00079 , m_dragScrollTimer(this)
00080 , m_scrollTimer (this)
00081 , m_cursorTimer (this)
00082 , m_textHintTimer (this)
00083 , m_suppressColumnScrollBar(false)
00084 , m_textHintEnabled(false)
00085 , m_textHintMouseX(-1)
00086 , m_textHintMouseY(-1)
00087 , m_imPreeditStartLine(0)
00088 , m_imPreeditStart(0)
00089 , m_imPreeditLength(0)
00090 {
00091 setMinimumSize (0,0);
00092
00093
00094 cursor.setMoveOnInsert (true);
00095
00096
00097
00098
00099 m_lineScroll = new KateScrollBar(QScrollBar::Vertical, m_view);
00100 m_lineScroll->show();
00101 m_lineScroll->setTracking (true);
00102
00103 m_lineLayout = new QVBoxLayout();
00104 m_colLayout = new QHBoxLayout();
00105
00106 m_colLayout->addWidget(m_lineScroll);
00107 m_lineLayout->addLayout(m_colLayout);
00108
00109 if (!m_view->dynWordWrap())
00110 {
00111
00112 m_dummy = new QWidget(m_view);
00113 m_dummy->setFixedHeight(style().scrollBarExtent().width());
00114 m_dummy->show();
00115 m_lineLayout->addWidget(m_dummy);
00116 }
00117
00118
00119 connect(m_lineScroll, SIGNAL(prevPage()), SLOT(scrollPrevPage()));
00120 connect(m_lineScroll, SIGNAL(nextPage()), SLOT(scrollNextPage()));
00121
00122 connect(m_lineScroll, SIGNAL(prevLine()), SLOT(scrollPrevLine()));
00123 connect(m_lineScroll, SIGNAL(nextLine()), SLOT(scrollNextLine()));
00124
00125 connect(m_lineScroll, SIGNAL(sliderMoved(int)), SLOT(scrollLines(int)));
00126 connect(m_lineScroll, SIGNAL(sliderMMBMoved(int)), SLOT(scrollLines(int)));
00127
00128
00129 m_lineScroll->installEventFilter(this);
00130
00131
00132
00133
00134 m_columnScroll = new QScrollBar(QScrollBar::Horizontal,m_view);
00135 m_columnScroll->hide();
00136 m_columnScroll->setTracking(true);
00137 m_startX = 0;
00138 m_oldStartX = 0;
00139
00140 connect( m_columnScroll, SIGNAL( valueChanged (int) ),
00141 this, SLOT( scrollColumns (int) ) );
00142
00143
00144
00145
00146 leftBorder = new KateIconBorder( this, m_view );
00147 leftBorder->show ();
00148
00149 connect( leftBorder, SIGNAL(toggleRegionVisibility(unsigned int)),
00150 m_doc->foldingTree(), SLOT(toggleRegionVisibility(unsigned int)));
00151
00152 connect( doc->foldingTree(), SIGNAL(regionVisibilityChangedAt(unsigned int)),
00153 this, SLOT(slotRegionVisibilityChangedAt(unsigned int)));
00154 connect( doc, SIGNAL(codeFoldingUpdated()),
00155 this, SLOT(slotCodeFoldingChanged()) );
00156
00157 displayCursor.setPos(0, 0);
00158 cursor.setPos(0, 0);
00159 cXPos = 0;
00160
00161 setAcceptDrops( true );
00162 setBackgroundMode( NoBackground );
00163
00164
00165 installEventFilter(this);
00166
00167
00168 setCursor( KCursor::ibeamCursor() );
00169
00170 dragInfo.state = diNone;
00171
00172
00173 connect( &m_dragScrollTimer, SIGNAL( timeout() ),
00174 this, SLOT( doDragScroll() ) );
00175
00176 connect( &m_scrollTimer, SIGNAL( timeout() ),
00177 this, SLOT( scrollTimeout() ) );
00178
00179 connect( &m_cursorTimer, SIGNAL( timeout() ),
00180 this, SLOT( cursorTimeout() ) );
00181
00182 connect( &m_textHintTimer, SIGNAL( timeout() ),
00183 this, SLOT( textHintTimeout() ) );
00184
00185
00186 connect( m_doc, SIGNAL( selectionChanged() ),
00187 this, SLOT( docSelectionChanged() ) );
00188
00189
00190
00191
00192
00193
00194 if (QApplication::reverseLayout()){
00195 m_view->m_grid->addMultiCellWidget(leftBorder, 0, 1, 2, 2);
00196 m_view->m_grid->addMultiCellWidget(m_columnScroll, 1, 1, 0, 1);
00197 m_view->m_grid->addMultiCellLayout(m_lineLayout, 0, 0, 0, 0);
00198 }
00199 else{
00200 m_view->m_grid->addMultiCellLayout(m_lineLayout, 0, 1, 2, 2);
00201 m_view->m_grid->addMultiCellWidget(m_columnScroll, 1, 1, 0, 1);
00202 m_view->m_grid->addWidget(leftBorder, 0, 0);
00203 }
00204
00205 updateView ();
00206 }
00207
00208 KateViewInternal::~KateViewInternal ()
00209 {
00210 }
00211
00212 void KateViewInternal::prepareForDynWrapChange()
00213 {
00214
00215 m_wrapChangeViewLine = displayViewLine(displayCursor, true);
00216 }
00217
00218 void KateViewInternal::dynWrapChanged()
00219 {
00220 if (m_view->dynWordWrap())
00221 {
00222 delete m_dummy;
00223 m_dummy = 0;
00224 m_columnScroll->hide();
00225 m_columnScrollDisplayed = false;
00226
00227 }
00228 else
00229 {
00230
00231 m_dummy = new QWidget(m_view);
00232 m_dummy->setFixedSize( style().scrollBarExtent().width(),
00233 style().scrollBarExtent().width() );
00234 m_dummy->show();
00235 m_lineLayout->addWidget(m_dummy);
00236 }
00237
00238 tagAll();
00239 updateView();
00240
00241 if (m_view->dynWordWrap())
00242 scrollColumns(0);
00243
00244
00245 if (m_wrapChangeViewLine != -1) {
00246 KateTextCursor newStart = viewLineOffset(displayCursor, -m_wrapChangeViewLine);
00247
00248
00249 if (!m_view->dynWordWrap() && scrollbarVisible(newStart.line())) {
00250 int lines = linesDisplayed() - 1;
00251
00252 if (m_view->height() != height())
00253 lines++;
00254
00255 if (newStart.line() + lines == displayCursor.line())
00256 newStart = viewLineOffset(displayCursor, 1 - m_wrapChangeViewLine);
00257 }
00258
00259 makeVisible(newStart, newStart.col(), true);
00260
00261 } else {
00262 update();
00263 }
00264 }
00265
00266 KateTextCursor KateViewInternal::endPos() const
00267 {
00268 int viewLines = linesDisplayed() - 1;
00269
00270 if (viewLines < 0) {
00271 kdDebug(13030) << "WARNING: viewLines wrong!" << endl;
00272 viewLines = 0;
00273 }
00274
00275
00276 if (!lineRanges.count() || lineRanges[0].line == -1 || viewLines >= (int)lineRanges.count()) {
00277
00278 return KateTextCursor(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
00279 }
00280
00281 for (int i = viewLines; i >= 0; i--) {
00282 LineRange& thisRange = lineRanges[i];
00283
00284 if (thisRange.line == -1) continue;
00285
00286 if (thisRange.virtualLine >= (int)m_doc->numVisLines()) {
00287
00288 return KateTextCursor(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
00289 }
00290
00291 return KateTextCursor(thisRange.virtualLine, thisRange.wrap ? thisRange.endCol - 1 : thisRange.endCol);
00292 }
00293
00294 Q_ASSERT(false);
00295 kdDebug(13030) << "WARNING: could not find a lineRange at all" << endl;
00296 return KateTextCursor(-1, -1);
00297 }
00298
00299 uint KateViewInternal::endLine() const
00300 {
00301 return endPos().line();
00302 }
00303
00304 LineRange KateViewInternal::yToLineRange(uint y) const
00305 {
00306 return lineRanges[y / m_view->renderer()->fontHeight()];
00307 }
00308
00309 int KateViewInternal::lineToY(uint viewLine) const
00310 {
00311 return (viewLine-startLine()) * m_view->renderer()->fontHeight();
00312 }
00313
00314 void KateViewInternal::slotIncFontSizes()
00315 {
00316 m_view->renderer()->increaseFontSizes();
00317 }
00318
00319 void KateViewInternal::slotDecFontSizes()
00320 {
00321 m_view->renderer()->decreaseFontSizes();
00322 }
00323
00327 void KateViewInternal::scrollLines ( int line )
00328 {
00329 KateTextCursor newPos(line, 0);
00330 scrollPos(newPos);
00331 }
00332
00333
00334 void KateViewInternal::scrollViewLines(int offset)
00335 {
00336 KateTextCursor c = viewLineOffset(startPos(), offset);
00337 scrollPos(c);
00338
00339 m_lineScroll->blockSignals(true);
00340 m_lineScroll->setValue(startLine());
00341 m_lineScroll->blockSignals(false);
00342 }
00343
00344 void KateViewInternal::scrollNextPage()
00345 {
00346 scrollViewLines(QMAX( linesDisplayed() - 1, 0 ));
00347 }
00348
00349 void KateViewInternal::scrollPrevPage()
00350 {
00351 scrollViewLines(-QMAX( linesDisplayed() - 1, 0 ));
00352 }
00353
00354 void KateViewInternal::scrollPrevLine()
00355 {
00356 scrollViewLines(-1);
00357 }
00358
00359 void KateViewInternal::scrollNextLine()
00360 {
00361 scrollViewLines(1);
00362 }
00363
00364 KateTextCursor KateViewInternal::maxStartPos(bool changed)
00365 {
00366 m_usePlainLines = true;
00367
00368 if (m_cachedMaxStartPos.line() == -1 || changed)
00369 {
00370 KateTextCursor end(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
00371
00372 m_cachedMaxStartPos = viewLineOffset(end, -(linesDisplayed() - 1));
00373 }
00374
00375
00376 if (!m_view->dynWordWrap() && m_columnScroll->isHidden() && scrollbarVisible(m_cachedMaxStartPos.line()))
00377 {
00378 KateTextCursor end(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
00379
00380 return viewLineOffset(end, -linesDisplayed());
00381 }
00382
00383 m_usePlainLines = false;
00384
00385 return m_cachedMaxStartPos;
00386 }
00387
00388
00389 void KateViewInternal::scrollPos(KateTextCursor& c, bool force)
00390 {
00391 if (!force && ((!m_view->dynWordWrap() && c.line() == (int)startLine()) || c == startPos()))
00392 return;
00393
00394 if (c.line() < 0)
00395 c.setLine(0);
00396
00397 KateTextCursor limit = maxStartPos();
00398 if (c > limit) {
00399 c = limit;
00400
00401
00402
00403 if (m_view->dynWordWrap())
00404 m_suppressColumnScrollBar = true;
00405
00406
00407 if (!force && ((!m_view->dynWordWrap() && c.line() == (int)startLine()) || c == startPos()))
00408 return;
00409 }
00410
00411 int viewLinesScrolled = displayViewLine(c);
00412
00413 m_oldStartPos = m_startPos;
00414 m_startPos = c;
00415
00416
00417 m_madeVisible = false;
00418
00419 if (!force) {
00420 int lines = linesDisplayed();
00421 if ((int)m_doc->numVisLines() < lines) {
00422 KateTextCursor end(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
00423 lines = QMIN((int)linesDisplayed(), displayViewLine(end) + 1);
00424 }
00425
00426 Q_ASSERT(lines >= 0);
00427
00428 if (QABS(viewLinesScrolled) < lines)
00429 {
00430 updateView(false, viewLinesScrolled);
00431
00432 int scrollHeight = -(viewLinesScrolled * m_view->renderer()->fontHeight());
00433 int scrollbarWidth = style().scrollBarExtent().width();
00434
00435
00436 qApp->postEvent(this, new QCustomEvent(QEvent::User + TimeMarkerEvent));
00437
00438
00439
00440
00441 scroll(0, scrollHeight);
00442 update(0, height()+scrollHeight-scrollbarWidth, width(), 2*scrollbarWidth);
00443
00444 leftBorder->scroll(0, scrollHeight);
00445 leftBorder->update(0, leftBorder->height()+scrollHeight-scrollbarWidth, leftBorder->width(), 2*scrollbarWidth);
00446
00447
00448 m_scrollTranslateHack = scrollHeight;
00449
00450 return;
00451 }
00452 }
00453
00454 updateView();
00455 update();
00456 leftBorder->update();
00457 }
00458
00459 void KateViewInternal::scrollColumns ( int x )
00460 {
00461 if (x == m_startX)
00462 return;
00463
00464 if (x < 0)
00465 x = 0;
00466
00467 int dx = m_startX - x;
00468 m_oldStartX = m_startX;
00469 m_startX = x;
00470
00471 if (QABS(dx) < width())
00472 scroll(dx, 0);
00473 else
00474 update();
00475
00476 m_columnScroll->blockSignals(true);
00477 m_columnScroll->setValue(m_startX);
00478 m_columnScroll->blockSignals(false);
00479 }
00480
00481
00482 void KateViewInternal::updateView(bool changed, int viewLinesScrolled)
00483 {
00484 m_updatingView = true;
00485
00486 uint contentLines = m_doc->visibleLines();
00487
00488 m_lineScroll->blockSignals(true);
00489
00490 KateTextCursor maxStart = maxStartPos(changed);
00491 int maxLineScrollRange = maxStart.line();
00492 if (m_view->dynWordWrap() && maxStart.col() != 0)
00493 maxLineScrollRange++;
00494 m_lineScroll->setRange(0, maxLineScrollRange);
00495
00496 if (m_view->dynWordWrap() && m_suppressColumnScrollBar) {
00497 m_suppressColumnScrollBar = false;
00498 m_lineScroll->setValue(maxStart.line());
00499 } else {
00500 m_lineScroll->setValue(startPos().line());
00501 }
00502 m_lineScroll->setSteps(1, height() / m_view->renderer()->fontHeight());
00503 m_lineScroll->blockSignals(false);
00504
00505 uint oldSize = lineRanges.size ();
00506 uint newSize = (height() / m_view->renderer()->fontHeight()) + 1;
00507 if (oldSize != newSize) {
00508 lineRanges.resize((height() / m_view->renderer()->fontHeight()) + 1);
00509 if (newSize > oldSize) {
00510 static LineRange blank;
00511 for (uint i = oldSize; i < newSize; i++) {
00512 lineRanges[i] = blank;
00513 }
00514 }
00515 }
00516
00517 if (oldSize < lineRanges.size ())
00518 {
00519 for (uint i=oldSize; i < lineRanges.size(); i++)
00520 lineRanges[i].dirty = true;
00521 }
00522
00523
00524 if (viewLinesScrolled != 0) {
00525
00526 bool forwards = viewLinesScrolled >= 0 ? true : false;
00527 for (uint z = forwards ? 0 : lineRanges.count() - 1; z < lineRanges.count(); forwards ? z++ : z--) {
00528 uint oldZ = z + viewLinesScrolled;
00529 if (oldZ < lineRanges.count()) {
00530 lineRanges[z] = lineRanges[oldZ];
00531 } else {
00532 lineRanges[z].dirty = true;
00533 }
00534 }
00535 }
00536
00537 if (m_view->dynWordWrap())
00538 {
00539 KateTextCursor realStart = startPos();
00540 realStart.setLine(m_doc->getRealLine(realStart.line()));
00541
00542 LineRange startRange = range(realStart);
00543 uint line = startRange.virtualLine;
00544 int realLine = startRange.line;
00545 uint oldLine = line;
00546 int startCol = startRange.startCol;
00547 int startX = startRange.startX;
00548 int endX = startRange.startX;
00549 int shiftX = startRange.startCol ? startRange.shiftX : 0;
00550 bool wrap = false;
00551 int newViewLine = startRange.viewLine;
00552
00553 TextLine::Ptr text = textLine(realLine);
00554
00555 bool alreadyDirty = false;
00556
00557 for (uint z = 0; z < lineRanges.size(); z++)
00558 {
00559 if (oldLine != line) {
00560 realLine = (int)m_doc->getRealLine(line);
00561
00562 if (z)
00563 lineRanges[z-1].startsInvisibleBlock = (realLine != lineRanges[z-1].line + 1);
00564
00565 text = textLine(realLine);
00566 startCol = 0;
00567 startX = 0;
00568 endX = 0;
00569 shiftX = 0;
00570 newViewLine = 0;
00571 oldLine = line;
00572 }
00573
00574 if (line >= contentLines || !text)
00575 {
00576 if (lineRanges[z].line != -1)
00577 lineRanges[z].dirty = true;
00578
00579 lineRanges[z].clear();
00580
00581 line++;
00582 }
00583 else
00584 {
00585 if (lineRanges[z].line != realLine || lineRanges[z].startCol != startCol)
00586 alreadyDirty = lineRanges[z].dirty = true;
00587
00588 if (lineRanges[z].dirty || changed || alreadyDirty) {
00589 alreadyDirty = true;
00590
00591 lineRanges[z].virtualLine = line;
00592 lineRanges[z].line = realLine;
00593 lineRanges[z].startsInvisibleBlock = false;
00594
00595 int tempEndX = 0;
00596
00597 int endCol = m_view->renderer()->textWidth(text, startCol, width() - shiftX, &wrap, &tempEndX);
00598
00599 endX += tempEndX;
00600
00601 if (wrap)
00602 {
00603 if (m_view->config()->dynWordWrapAlignIndent() > 0)
00604 {
00605 if (startX == 0)
00606 {
00607 int pos = text->nextNonSpaceChar(0);
00608
00609 if (pos > 0)
00610 shiftX = m_view->renderer()->textWidth(text, pos);
00611
00612 if (shiftX > ((double)width() / 100 * m_view->config()->dynWordWrapAlignIndent()))
00613 shiftX = 0;
00614 }
00615 }
00616
00617 if ((lineRanges[z].startX != startX) || (lineRanges[z].endX != endX) ||
00618 (lineRanges[z].startCol != startCol) || (lineRanges[z].endCol != endCol) ||
00619 (lineRanges[z].shiftX != shiftX))
00620 lineRanges[z].dirty = true;
00621
00622 lineRanges[z].startCol = startCol;
00623 lineRanges[z].endCol = endCol;
00624 lineRanges[z].startX = startX;
00625 lineRanges[z].endX = endX;
00626 lineRanges[z].viewLine = newViewLine;
00627 lineRanges[z].wrap = true;
00628
00629 startCol = endCol;
00630 startX = endX;
00631 }
00632 else
00633 {
00634 if ((lineRanges[z].startX != startX) || (lineRanges[z].endX != endX) ||
00635 (lineRanges[z].startCol != startCol) || (lineRanges[z].endCol != endCol))
00636 lineRanges[z].dirty = true;
00637
00638 lineRanges[z].startCol = startCol;
00639 lineRanges[z].endCol = endCol;
00640 lineRanges[z].startX = startX;
00641 lineRanges[z].endX = endX;
00642 lineRanges[z].viewLine = newViewLine;
00643 lineRanges[z].wrap = false;
00644
00645 line++;
00646 }
00647
00648 lineRanges[z].shiftX = shiftX;
00649
00650 } else {
00651
00652 if (lineRanges[z].wrap) {
00653 startCol = lineRanges[z].endCol;
00654 startX = lineRanges[z].endX;
00655 endX = lineRanges[z].endX;
00656 } else {
00657 line++;
00658 }
00659 shiftX = lineRanges[z].shiftX;
00660 }
00661 }
00662 newViewLine++;
00663 }
00664 }
00665 else
00666 {
00667 uint z = 0;
00668
00669 for(; (z + startLine() < contentLines) && (z < lineRanges.size()); z++)
00670 {
00671 if (lineRanges[z].dirty || lineRanges[z].line != (int)m_doc->getRealLine(z + startLine())) {
00672 lineRanges[z].dirty = true;
00673
00674 lineRanges[z].line = m_doc->getRealLine( z + startLine() );
00675 if (z)
00676 lineRanges[z-1].startsInvisibleBlock = (lineRanges[z].line != lineRanges[z-1].line + 1);
00677
00678 lineRanges[z].virtualLine = z + startLine();
00679 lineRanges[z].startCol = 0;
00680 lineRanges[z].endCol = m_doc->lineLength(lineRanges[z].line);
00681 lineRanges[z].startX = 0;
00682 lineRanges[z].endX = m_view->renderer()->textWidth( textLine( lineRanges[z].line ), -1 );
00683 lineRanges[z].shiftX = 0;
00684 lineRanges[z].viewLine = 0;
00685 lineRanges[z].wrap = false;
00686 }
00687 else if (z && lineRanges[z-1].dirty)
00688 {
00689 lineRanges[z-1].startsInvisibleBlock = (lineRanges[z].line != lineRanges[z-1].line + 1);
00690 }
00691 }
00692
00693 for (; z < lineRanges.size(); z++)
00694 {
00695 if (lineRanges[z].line != -1)
00696 lineRanges[z].dirty = true;
00697
00698 lineRanges[z].clear();
00699 }
00700
00701 if (scrollbarVisible(startLine()))
00702 {
00703 m_columnScroll->blockSignals(true);
00704
00705 int max = maxLen(startLine()) - width();
00706 if (max < 0)
00707 max = 0;
00708
00709 m_columnScroll->setRange(0, max);
00710
00711 m_columnScroll->setValue(m_startX);
00712
00713
00714 m_columnScroll->setSteps(m_view->renderer()->config()->fontMetrics()->width('a'), width());
00715
00716 m_columnScroll->blockSignals(false);
00717
00718 if (!m_columnScroll->isVisible () && !m_suppressColumnScrollBar)
00719 {
00720 m_columnScroll->show();
00721 m_columnScrollDisplayed = true;
00722 }
00723 }
00724 else if (m_columnScroll->isVisible () && !m_suppressColumnScrollBar && (startX() == 0))
00725 {
00726 m_columnScroll->hide();
00727 m_columnScrollDisplayed = false;
00728 }
00729 }
00730
00731 m_updatingView = false;
00732
00733 if (changed)
00734 paintText(0, 0, width(), height(), true);
00735 }
00736
00737 void KateViewInternal::paintText (int x, int y, int width, int height, bool paintOnlyDirty)
00738 {
00739
00740 int xStart = startX() + x;
00741 int xEnd = xStart + width;
00742 uint h = m_view->renderer()->fontHeight();
00743 uint startz = (y / h);
00744 uint endz = startz + 1 + (height / h);
00745 uint lineRangesSize = lineRanges.size();
00746
00747 static QPixmap drawBuffer;
00748
00749 if (drawBuffer.width() < KateViewInternal::width() || drawBuffer.height() < (int)h)
00750 drawBuffer.resize(KateViewInternal::width(), (int)h);
00751
00752 if (drawBuffer.isNull())
00753 return;
00754
00755 QPainter paint(this);
00756 QPainter paintDrawBuffer(&drawBuffer);
00757
00758
00759 m_view->renderer()->setCaretStyle(m_view->isOverwriteMode() ? KateRenderer::Replace : KateRenderer::Insert);
00760 m_view->renderer()->setShowTabs(m_doc->configFlags() & KateDocument::cfShowTabs);
00761
00762 for (uint z=startz; z <= endz; z++)
00763 {
00764 if ( (z >= lineRangesSize) || ((lineRanges[z].line == -1) && (!paintOnlyDirty || lineRanges[z].dirty)) )
00765 {
00766 if (!(z >= lineRangesSize))
00767 lineRanges[z].dirty = false;
00768
00769 paint.fillRect( x, z * h, width, h, *m_view->renderer()->config()->backgroundColor() );
00770 }
00771 else if (!paintOnlyDirty || lineRanges[z].dirty)
00772 {
00773 lineRanges[z].dirty = false;
00774
00775 m_view->renderer()->paintTextLine(paintDrawBuffer, &lineRanges[z], xStart, xEnd, &cursor, &bm);
00776
00777 paint.drawPixmap (x, z * h, drawBuffer, 0, 0, width, h);
00778 }
00779 }
00780 }
00781
00786 void KateViewInternal::makeVisible (const KateTextCursor& c, uint endCol, bool force, bool center)
00787 {
00788
00789
00790
00791
00792
00793 if ( force )
00794 {
00795 KateTextCursor scroll = c;
00796 scrollPos(scroll, force);
00797 }
00798 else if (center && (c < startPos() || c > endPos()))
00799 {
00800 KateTextCursor scroll = viewLineOffset(c, -int(linesDisplayed()) / 2);
00801 scrollPos(scroll);
00802 }
00803 else if ( c > viewLineOffset(endPos(), -m_minLinesVisible) )
00804 {
00805 KateTextCursor scroll = viewLineOffset(c, -(linesDisplayed() - m_minLinesVisible - 1));
00806
00807 if (!m_view->dynWordWrap() && m_columnScroll->isHidden())
00808 if (scrollbarVisible(scroll.line()))
00809 scroll.setLine(scroll.line() + 1);
00810
00811 scrollPos(scroll);
00812 }
00813 else if ( c < viewLineOffset(startPos(), m_minLinesVisible) )
00814 {
00815 KateTextCursor scroll = viewLineOffset(c, -m_minLinesVisible);
00816 scrollPos(scroll);
00817 }
00818 else
00819 {
00820
00821 KateTextCursor max = maxStartPos();
00822 if (startPos() > max) {
00823 scrollPos(max, max.col());
00824 }
00825 }
00826
00827 if (!m_view->dynWordWrap() && endCol != (uint)-1)
00828 {
00829 int sX = (int)m_view->renderer()->textWidth (textLine( m_doc->getRealLine( c.line() ) ), c.col() );
00830
00831 int sXborder = sX-8;
00832 if (sXborder < 0)
00833 sXborder = 0;
00834
00835 if (sX < m_startX)
00836 scrollColumns (sXborder);
00837 else if (sX > m_startX + width())
00838 scrollColumns (sX - width() + 8);
00839 }
00840
00841 m_madeVisible = !force;
00842 }
00843
00844 void KateViewInternal::slotRegionVisibilityChangedAt(unsigned int)
00845 {
00846 kdDebug(13030) << "slotRegionVisibilityChangedAt()" << endl;
00847 m_cachedMaxStartPos.setLine(-1);
00848 KateTextCursor max = maxStartPos();
00849 if (startPos() > max)
00850 scrollPos(max);
00851
00852 updateView();
00853 update();
00854 leftBorder->update();
00855 }
00856
00857 void KateViewInternal::slotCodeFoldingChanged()
00858 {
00859 leftBorder->update();
00860 }
00861
00862 void KateViewInternal::slotRegionBeginEndAddedRemoved(unsigned int)
00863 {
00864 kdDebug(13030) << "slotRegionBeginEndAddedRemoved()" << endl;
00865
00866 leftBorder->update();
00867 }
00868
00869 void KateViewInternal::showEvent ( QShowEvent *e )
00870 {
00871 updateView ();
00872
00873 QWidget::showEvent (e);
00874 }
00875
00876 uint KateViewInternal::linesDisplayed() const
00877 {
00878 int h = height();
00879 int fh = m_view->renderer()->fontHeight();
00880
00881 return (h - (h % fh)) / fh;
00882 }
00883
00884 QPoint KateViewInternal::cursorCoordinates()
00885 {
00886 int viewLine = displayViewLine(displayCursor, true);
00887
00888 if (viewLine == -1)
00889 return QPoint(-1, -1);
00890
00891 uint y = viewLine * m_view->renderer()->fontHeight();
00892 uint x = cXPos - m_startX - lineRanges[viewLine].startX + leftBorder->width() + lineRanges[viewLine].xOffset();
00893
00894 return QPoint(x, y);
00895 }
00896
00897 void KateViewInternal::doReturn()
00898 {
00899 KateTextCursor c = cursor;
00900 m_doc->newLine( c, this );
00901 updateCursor( c );
00902 updateView();
00903 }
00904
00905 void KateViewInternal::doDelete()
00906 {
00907 m_doc->del( cursor );
00908 }
00909
00910 void KateViewInternal::doBackspace()
00911 {
00912 m_doc->backspace( cursor );
00913 }
00914
00915 void KateViewInternal::doPaste()
00916 {
00917 m_doc->paste( m_view );
00918 }
00919
00920 void KateViewInternal::doTranspose()
00921 {
00922 m_doc->transpose( cursor );
00923 }
00924
00925 void KateViewInternal::doDeleteWordLeft()
00926 {
00927 wordLeft( true );
00928 m_doc->removeSelectedText();
00929 update();
00930 }
00931
00932 void KateViewInternal::doDeleteWordRight()
00933 {
00934 wordRight( true );
00935 m_doc->removeSelectedText();
00936 update();
00937 }
00938
00939 class CalculatingCursor : public KateTextCursor {
00940 public:
00941 CalculatingCursor(KateViewInternal* vi)
00942 : KateTextCursor()
00943 , m_vi(vi)
00944 {
00945 Q_ASSERT(valid());
00946 }
00947
00948 CalculatingCursor(KateViewInternal* vi, const KateTextCursor& c)
00949 : KateTextCursor(c)
00950 , m_vi(vi)
00951 {
00952 Q_ASSERT(valid());
00953 }
00954
00955
00956 CalculatingCursor(KateViewInternal* vi, uint line, uint col)
00957 : KateTextCursor(line, col)
00958 , m_vi(vi)
00959 {
00960 makeValid();
00961 }
00962
00963
00964 virtual CalculatingCursor& operator+=( int n ) = 0;
00965
00966 virtual CalculatingCursor& operator-=( int n ) = 0;
00967
00968 CalculatingCursor& operator++() { return operator+=( 1 ); }
00969
00970 CalculatingCursor& operator--() { return operator-=( 1 ); }
00971
00972 void makeValid() {
00973 m_line = QMAX( 0, QMIN( int( m_vi->m_doc->numLines() - 1 ), line() ) );
00974 if (m_vi->m_doc->wrapCursor())
00975 m_col = QMAX( 0, QMIN( m_vi->m_doc->lineLength( line() ), col() ) );
00976 else
00977 m_col = QMAX( 0, col() );
00978 Q_ASSERT( valid() );
00979 }
00980
00981 void toEdge( Bias bias ) {
00982 if( bias == left ) m_col = 0;
00983 else if( bias == right ) m_col = m_vi->m_doc->lineLength( line() );
00984 }
00985
00986 bool atEdge() const { return atEdge( left ) || atEdge( right ); }
00987
00988 bool atEdge( Bias bias ) const {
00989 switch( bias ) {
00990 case left: return col() == 0;
00991 case none: return atEdge();
00992 case right: return col() == m_vi->m_doc->lineLength( line() );
00993 default: Q_ASSERT(false); return false;
00994 }
00995 }
00996
00997 protected:
00998 bool valid() const {
00999 return line() >= 0 &&
01000 uint( line() ) < m_vi->m_doc->numLines() &&
01001 col() >= 0 &&
01002 (!m_vi->m_doc->wrapCursor() || col() <= m_vi->m_doc->lineLength( line() ));
01003 }
01004 KateViewInternal* m_vi;
01005 };
01006
01007 class BoundedCursor : public CalculatingCursor {
01008 public:
01009 BoundedCursor(KateViewInternal* vi)
01010 : CalculatingCursor( vi ) {};
01011 BoundedCursor(KateViewInternal* vi, const KateTextCursor& c )
01012 : CalculatingCursor( vi, c ) {};
01013 BoundedCursor(KateViewInternal* vi, uint line, uint col )
01014 : CalculatingCursor( vi, line, col ) {};
01015 virtual CalculatingCursor& operator+=( int n ) {
01016 m_col += n;
01017
01018 if (n > 0 && m_vi->m_view->dynWordWrap()) {
01019
01020 if (m_col > m_vi->m_doc->lineLength(m_line)) {
01021 LineRange currentRange = m_vi->range(*this);
01022
01023 int endX;
01024 bool crap;
01025 m_vi->m_view->renderer()->textWidth(m_vi->textLine(m_line), currentRange.startCol, m_vi->width() - currentRange.xOffset(), &crap, &endX);
01026 endX += (m_col - currentRange.endCol + 1) * m_vi->m_view->renderer()->spaceWidth();
01027
01028
01029 if (endX >= m_vi->width() - currentRange.xOffset()) {
01030 m_col -= n;
01031 if ( uint( line() ) < m_vi->m_doc->numLines() - 1 ) {
01032 m_line++;
01033 m_col = 0;
01034 }
01035 }
01036 }
01037
01038 } else if (n < 0 && col() < 0 && line() > 0 ) {
01039 m_line--;
01040 m_col = m_vi->m_doc->lineLength( line() );
01041 }
01042
01043 m_col = QMAX( 0, col() );
01044
01045 Q_ASSERT( valid() );
01046 return *this;
01047 }
01048 virtual CalculatingCursor& operator-=( int n ) {
01049 return operator+=( -n );
01050 }
01051 };
01052
01053 class WrappingCursor : public CalculatingCursor {
01054 public:
01055 WrappingCursor(KateViewInternal* vi)
01056 : CalculatingCursor( vi) {};
01057 WrappingCursor(KateViewInternal* vi, const KateTextCursor& c )
01058 : CalculatingCursor( vi, c ) {};
01059 WrappingCursor(KateViewInternal* vi, uint line, uint col )
01060 : CalculatingCursor( vi, line, col ) {};
01061
01062 virtual CalculatingCursor& operator+=( int n ) {
01063 if( n < 0 ) return operator-=( -n );
01064 int len = m_vi->m_doc->lineLength( line() );
01065 if( col() + n <= len ) {
01066 m_col += n;
01067 } else if( uint( line() ) < m_vi->m_doc->numLines() - 1 ) {
01068 n -= len - col() + 1;
01069 m_col = 0;
01070 m_line++;
01071 operator+=( n );
01072 } else {
01073 m_col = len;
01074 }
01075 Q_ASSERT( valid() );
01076 return *this;
01077 }
01078 virtual CalculatingCursor& operator-=( int n ) {
01079 if( n < 0 ) return operator+=( -n );
01080 if( col() - n >= 0 ) {
01081 m_col -= n;
01082 } else if( line() > 0 ) {
01083 n -= col() + 1;
01084 m_line--;
01085 m_col = m_vi->m_doc->lineLength( line() );
01086 operator-=( n );
01087 } else {
01088 m_col = 0;
01089 }
01090 Q_ASSERT( valid() );
01091 return *this;
01092 }
01093 };
01094
01095 void KateViewInternal::moveChar( Bias bias, bool sel )
01096 {
01097 KateTextCursor c;
01098 if ( m_doc->wrapCursor() ) {
01099 c = WrappingCursor( this, cursor ) += bias;
01100 } else {
01101 c = BoundedCursor( this, cursor ) += bias;
01102 }
01103 updateSelection( c, sel );
01104 updateCursor( c );
01105 }
01106
01107 void KateViewInternal::cursorLeft( bool sel ) { moveChar( left, sel ); }
01108 void KateViewInternal::cursorRight( bool sel ) { moveChar( right, sel ); }
01109
01110 void KateViewInternal::moveWord( Bias bias, bool sel )
01111 {
01112
01113
01114 WrappingCursor c( this, cursor );
01115 if( !c.atEdge( bias ) ) {
01116 Highlight* h = m_doc->highlight();
01117
01118 bool moved = false;
01119 while( !c.atEdge( bias ) && !h->isInWord( m_doc->textLine( c.line() )[ c.col() - (bias == left ? 1 : 0) ] ) )
01120 {
01121 c += bias;
01122 moved = true;
01123 }
01124
01125 if ( bias != right || !moved )
01126 {
01127 while( !c.atEdge( bias ) && h->isInWord( m_doc->textLine( c.line() )[ c.col() - (bias == left ? 1 : 0) ] ) )
01128 c += bias;
01129 if ( bias == right )
01130 {
01131 while ( !c.atEdge( bias ) && m_doc->textLine( c.line() )[ c.col() ].isSpace() )
01132 c+= bias;
01133 }
01134 }
01135
01136 } else {
01137 c += bias;
01138 }
01139 updateSelection( c, sel );
01140 updateCursor( c );
01141 }
01142
01143 void KateViewInternal::wordLeft ( bool sel ) { moveWord( left, sel ); }
01144 void KateViewInternal::wordRight( bool sel ) { moveWord( right, sel ); }
01145
01146 void KateViewInternal::moveEdge( Bias bias, bool sel )
01147 {
01148 BoundedCursor c( this, cursor );
01149 c.toEdge( bias );
01150 updateSelection( c, sel );
01151 updateCursor( c );
01152 }
01153
01154 void KateViewInternal::home( bool sel )
01155 {
01156 if (m_view->dynWordWrap() && currentRange().startCol) {
01157
01158 if (cursor.col() != currentRange().startCol) {
01159 KateTextCursor c(cursor.line(), currentRange().startCol);
01160 updateSelection( c, sel );
01161 updateCursor( c );
01162 return;
01163 }
01164 }
01165
01166 if( !(m_doc->configFlags() & KateDocument::cfSmartHome) ) {
01167 moveEdge( left, sel );
01168 return;
01169 }
01170
01171 KateTextCursor c = cursor;
01172 int lc = textLine( c.line() )->firstChar();
01173
01174 if( lc < 0 || c.col() == lc ) {
01175 c.setCol(0);
01176 } else {
01177 c.setCol(lc);
01178 }
01179
01180 updateSelection( c, sel );
01181 updateCursor( c );
01182 }
01183
01184 void KateViewInternal::end( bool sel )
01185 {
01186 if (m_view->dynWordWrap() && currentRange().wrap) {
01187
01188 if (cursor.col() < currentRange().endCol - 1) {
01189 KateTextCursor c(cursor.line(), currentRange().endCol - 1);
01190 updateSelection( c, sel );
01191 updateCursor( c );
01192 return;
01193 }
01194 }
01195
01196 moveEdge( right, sel );
01197 }
01198
01199 LineRange KateViewInternal::range(int realLine, const LineRange* previous)
01200 {
01201
01202 if (!m_updatingView && realLine >= lineRanges[0].line && realLine <= lineRanges[lineRanges.count() - 1].line)
01203 for (uint i = 0; i < lineRanges.count(); i++)
01204 if (realLine == lineRanges[i].line)
01205 if (!m_view->dynWordWrap() || (!previous && lineRanges[i].startCol == 0) || (previous && lineRanges[i].startCol == previous->endCol))
01206 return lineRanges[i];
01207
01208
01209 LineRange ret;
01210
01211 TextLine::Ptr text = textLine(realLine);
01212 if (!text) {
01213 return LineRange();
01214 }
01215
01216 if (!m_view->dynWordWrap()) {
01217 Q_ASSERT(!previous);
01218 ret.line = realLine;
01219 ret.virtualLine = m_doc->getVirtualLine(realLine);
01220 ret.startCol = 0;
01221 ret.endCol = m_doc->lineLength(realLine);
01222 ret.startX = 0;
01223 ret.endX = m_view->renderer()->textWidth(text, -1);
01224 ret.viewLine = 0;
01225 ret.wrap = false;
01226 return ret;
01227 }
01228
01229 ret.endCol = (int)m_view->renderer()->textWidth(text, previous ? previous->endCol : 0, width() - (previous ? previous->shiftX : 0), &ret.wrap, &ret.endX);
01230
01231 Q_ASSERT(ret.endCol > ret.startCol);
01232
01233 ret.line = realLine;
01234
01235 if (previous) {
01236 ret.virtualLine = previous->virtualLine;
01237 ret.startCol = previous->endCol;
01238 ret.startX = previous->endX;
01239 ret.endX += previous->endX;
01240 ret.shiftX = previous->shiftX;
01241 ret.viewLine = previous->viewLine + 1;
01242
01243 } else {
01244
01245 if (m_view->config()->dynWordWrapAlignIndent() > 0) {
01246 int pos = text->nextNonSpaceChar(0);
01247
01248 if (pos > 0)
01249 ret.shiftX = m_view->renderer()->textWidth(text, pos);
01250
01251 if (ret.shiftX > ((double)width() / 100 * m_view->config()->dynWordWrapAlignIndent()))
01252 ret.shiftX = 0;
01253 }
01254
01255 ret.virtualLine = m_doc->getVirtualLine(realLine);
01256 ret.startCol = 0;
01257 ret.startX = 0;
01258 ret.viewLine = 0;
01259 }
01260
01261 return ret;
01262 }
01263
01264 LineRange KateViewInternal::currentRange()
01265 {
01266 Q_ASSERT(m_view->dynWordWrap());
01267
01268 return range(cursor);
01269 }
01270
01271 LineRange KateViewInternal::previousRange()
01272 {
01273 uint currentViewLine = viewLine(cursor);
01274
01275 if (currentViewLine)
01276 return range(cursor.line(), currentViewLine - 1);
01277 else
01278 return range(m_doc->getRealLine(displayCursor.line() - 1), -1);
01279 }
01280
01281 LineRange KateViewInternal::nextRange()
01282 {
01283 uint currentViewLine = viewLine(cursor) + 1;
01284
01285 if (currentViewLine >= viewLineCount(cursor.line())) {
01286 currentViewLine = 0;
01287 return range(cursor.line() + 1, currentViewLine);
01288 } else {
01289 return range(cursor.line(), currentViewLine);
01290 }
01291 }
01292
01293 LineRange KateViewInternal::range(const KateTextCursor& realCursor)
01294 {
01295 Q_ASSERT(m_view->dynWordWrap());
01296
01297 LineRange thisRange;
01298 bool first = true;
01299
01300 do {
01301 thisRange = range(realCursor.line(), first ? 0L : &thisRange);
01302 first = false;
01303 } while (thisRange.wrap && !(realCursor.col() >= thisRange.startCol && realCursor.col() < thisRange.endCol) && thisRange.startCol != thisRange.endCol);
01304
01305 return thisRange;
01306 }
01307
01308 LineRange KateViewInternal::range(uint realLine, int viewLine)
01309 {
01310 Q_ASSERT(m_view->dynWordWrap());
01311
01312 LineRange thisRange;
01313 bool first = true;
01314
01315 do {
01316 thisRange = range(realLine, first ? 0L : &thisRange);
01317 first = false;
01318 } while (thisRange.wrap && viewLine != thisRange.viewLine && thisRange.startCol != thisRange.endCol);
01319
01320 if (viewLine != -1 && viewLine != thisRange.viewLine)
01321 kdDebug(13030) << "WARNING: viewLine " << viewLine << " of line " << realLine << " does not exist." << endl;
01322
01323 return thisRange;
01324 }
01325
01331 uint KateViewInternal::viewLine(const KateTextCursor& realCursor)
01332 {
01333 if (!m_view->dynWordWrap()) return 0;
01334
01335 if (realCursor.col() == 0) return 0;
01336
01337 LineRange thisRange;
01338 bool first = true;
01339
01340 do {
01341 thisRange = range(realCursor.line(), first ? 0L : &thisRange);
01342 first = false;
01343 } while (thisRange.wrap && !(realCursor.col() >= thisRange.startCol && realCursor.col() < thisRange.endCol) && thisRange.startCol != thisRange.endCol);
01344
01345 return thisRange.viewLine;
01346 }
01347
01348 int KateViewInternal::displayViewLine(const KateTextCursor& virtualCursor, bool limitToVisible)
01349 {
01350 KateTextCursor work = startPos();
01351
01352 int limit = linesDisplayed();
01353
01354
01355 if (!m_view->dynWordWrap()) {
01356 int ret = virtualCursor.line() - startLine();
01357 if (limitToVisible && (ret < 0 || ret > limit))
01358 return -1;
01359 else
01360 return ret;
01361 }
01362
01363 if (work == virtualCursor) {
01364 return 0;
01365 }
01366
01367 int ret = -viewLine(work);
01368 bool forwards = (work < virtualCursor) ? true : false;
01369
01370
01371 if (forwards) {
01372 while (work.line() != virtualCursor.line()) {
01373 ret += viewLineCount(m_doc->getRealLine(work.line()));
01374 work.setLine(work.line() + 1);
01375 if (limitToVisible && ret > limit)
01376 return -1;
01377 }
01378 } else {
01379 while (work.line() != virtualCursor.line()) {
01380 work.setLine(work.line() - 1);
01381 ret -= viewLineCount(m_doc->getRealLine(work.line()));
01382 if (limitToVisible && ret < 0)
01383 return -1;
01384 }
01385 }
01386
01387
01388 KateTextCursor realCursor = virtualCursor;
01389 realCursor.setLine(m_doc->getRealLine(realCursor.line()));
01390 if (realCursor.col() == -1) realCursor.setCol(m_doc->lineLength(realCursor.line()));
01391 ret += viewLine(realCursor);
01392
01393 if (limitToVisible && (ret < 0 || ret > limit))
01394 return -1;
01395
01396 return ret;
01397 }
01398
01399 uint KateViewInternal::lastViewLine(uint realLine)
01400 {
01401 if (!m_view->dynWordWrap()) return 0;
01402
01403 LineRange thisRange;
01404 bool first = true;
01405
01406 do {
01407 thisRange = range(realLine, first ? 0L : &thisRange);
01408 first = false;
01409 } while (thisRange.wrap && thisRange.startCol != thisRange.endCol);
01410
01411 return thisRange.viewLine;
01412 }
01413
01414 uint KateViewInternal::viewLineCount(uint realLine)
01415 {
01416 return lastViewLine(realLine) + 1;
01417 }
01418
01419
01420
01421
01422
01423
01424
01425
01426 KateTextCursor KateViewInternal::viewLineOffset(const KateTextCursor& virtualCursor, int offset, bool keepX)
01427 {
01428 if (!m_view->dynWordWrap()) {
01429 KateTextCursor ret(QMIN((int)m_doc->visibleLines() - 1, virtualCursor.line() + offset), 0);
01430
01431 if (ret.line() < 0)
01432 ret.setLine(0);
01433
01434 if (keepX) {
01435 int realLine = m_doc->getRealLine(ret.line());
01436 ret.setCol(m_doc->lineLength(realLine) - 1);
01437
01438 if (m_currentMaxX > cXPos)
01439 cXPos = m_currentMaxX;
01440
01441 if (m_doc->wrapCursor())
01442 cXPos = QMIN(cXPos, (int)m_view->renderer()->textWidth(textLine(realLine), m_doc->lineLength(realLine)));
01443
01444 m_view->renderer()->textWidth(ret, cXPos);
01445 }
01446
01447 return ret;
01448 }
01449
01450 KateTextCursor realCursor = virtualCursor;
01451 realCursor.setLine(m_doc->getRealLine(virtualCursor.line()));
01452
01453 uint cursorViewLine = viewLine(realCursor);
01454
01455 int currentOffset = 0;
01456 int virtualLine = 0;
01457
01458 bool forwards = (offset > 0) ? true : false;
01459
01460 if (forwards) {
01461 currentOffset = lastViewLine(realCursor.line()) - cursorViewLine;
01462 if (offset <= currentOffset) {
01463
01464 LineRange thisRange = range(realCursor.line(), cursorViewLine + offset);
01465 Q_ASSERT(thisRange.virtualLine == virtualCursor.line());
01466 return KateTextCursor(virtualCursor.line(), thisRange.startCol);
01467 }
01468
01469 virtualLine = virtualCursor.line() + 1;
01470
01471 } else {
01472 offset = -offset;
01473 currentOffset = cursorViewLine;
01474 if (offset <= currentOffset) {
01475
01476 LineRange thisRange = range(realCursor.line(), cursorViewLine - offset);
01477 Q_ASSERT(thisRange.virtualLine == virtualCursor.line());
01478 return KateTextCursor(virtualCursor.line(), thisRange.startCol);
01479 }
01480
01481 virtualLine = virtualCursor.line() - 1;
01482 }
01483
01484 currentOffset++;
01485
01486 while (virtualLine >= 0 && virtualLine < (int)m_doc->visibleLines())
01487 {
01488 LineRange thisRange;
01489 bool first = true;
01490 int realLine = m_doc->getRealLine(virtualLine);
01491
01492 do {
01493 thisRange = range(realLine, first ? 0L : &thisRange);
01494 first = false;
01495
01496 if (offset == currentOffset) {
01497 if (!forwards) {
01498
01499 int requiredViewLine = lastViewLine(realLine) - thisRange.viewLine;
01500 if (requiredViewLine != thisRange.viewLine) {
01501 thisRange = range(realLine, requiredViewLine);
01502 }
01503 }
01504
01505 KateTextCursor ret(virtualLine, thisRange.startCol);
01506
01507
01508 if (keepX) {
01509 ret.setCol(thisRange.endCol - 1);
01510 KateTextCursor realCursorTemp(m_doc->getRealLine(virtualCursor.line()), virtualCursor.col());
01511 int visibleX = m_view->renderer()->textWidth(realCursorTemp) - range(realCursorTemp).startX;
01512 int xOffset = thisRange.startX;
01513
01514 if (m_currentMaxX > visibleX)
01515 visibleX = m_currentMaxX;
01516
01517 cXPos = xOffset + visibleX;
01518
01519 cXPos = QMIN(cXPos, lineMaxCursorX(thisRange));
01520
01521 m_view->renderer()->textWidth(ret, cXPos);
01522 }
01523
01524 return ret;
01525 }
01526
01527 currentOffset++;
01528
01529 } while (thisRange.wrap);
01530
01531 if (forwards)
01532 virtualLine++;
01533 else
01534 virtualLine--;
01535 }
01536
01537
01538
01539 if (forwards)
01540 return KateTextCursor(m_doc->visibleLines() - 1, m_doc->lineLength(m_doc->visibleLines() - 1));
01541 else
01542 return KateTextCursor(0, 0);
01543 }
01544
01545 int KateViewInternal::lineMaxCursorX(const LineRange& range)
01546 {
01547 if (!m_doc->wrapCursor() && !range.wrap)
01548 return INT_MAX;
01549
01550 int maxX = range.endX;
01551
01552 if (maxX && range.wrap) {
01553 QChar lastCharInLine = textLine(range.line)->getChar(range.endCol - 1);
01554 maxX -= m_view->renderer()->config()->fontMetrics()->width(lastCharInLine);
01555 }
01556
01557 return maxX;
01558 }
01559
01560 int KateViewInternal::lineMaxCol(const LineRange& range)
01561 {
01562 int maxCol = range.endCol;
01563
01564 if (maxCol && range.wrap)
01565 maxCol--;
01566
01567 return maxCol;
01568 }
01569
01570 void KateViewInternal::cursorUp(bool sel)
01571 {
01572 if (displayCursor.line() == 0 && (!m_view->dynWordWrap() || viewLine(cursor) == 0))
01573 return;
01574
01575 int newLine = cursor.line(), newCol = 0, xOffset = 0, startCol = 0;
01576 m_preserveMaxX = true;
01577
01578 if (m_view->dynWordWrap()) {
01579
01580 LineRange thisRange = currentRange();
01581
01582 LineRange pRange = previousRange();
01583
01584
01585 Q_ASSERT((cursor.line() == thisRange.line) &&
01586 (cursor.col() >= thisRange.startCol) &&
01587 (!thisRange.wrap || cursor.col() < thisRange.endCol));
01588
01589
01590 int visibleX = m_view->renderer()->textWidth(cursor) - thisRange.startX;
01591 int currentLineVisibleX = visibleX;
01592
01593
01594 visibleX += thisRange.xOffset();
01595 visibleX -= pRange.xOffset();
01596
01597
01598 visibleX = QMAX(0, visibleX);
01599
01600 startCol = pRange.startCol;
01601 xOffset = pRange.startX;
01602 newLine = pRange.line;
01603
01604
01605
01606 if (thisRange.xOffset() && !pRange.xOffset() && currentLineVisibleX == 0)
01607 visibleX = m_currentMaxX;
01608 else if (visibleX < m_currentMaxX - pRange.xOffset())
01609 visibleX = m_currentMaxX - pRange.xOffset();
01610
01611 cXPos = xOffset + visibleX;
01612
01613 cXPos = QMIN(cXPos, lineMaxCursorX(pRange));
01614
01615 newCol = QMIN((int)m_view->renderer()->textPos(newLine, visibleX, startCol), lineMaxCol(pRange));
01616
01617 } else {
01618 newLine = m_doc->getRealLine(displayCursor.line() - 1);
01619
01620 if ((m_doc->wrapCursor()) && m_currentMaxX > cXPos)
01621 cXPos = m_currentMaxX;
01622 }
01623
01624 KateTextCursor c(newLine, newCol);
01625 m_view->renderer()->textWidth(c, cXPos);
01626
01627 updateSelection( c, sel );
01628 updateCursor( c );
01629 }
01630
01631 void KateViewInternal::cursorDown(bool sel)
01632 {
01633 if ((displayCursor.line() >= (int)m_doc->numVisLines() - 1) && (!m_view->dynWordWrap() || viewLine(cursor) == lastViewLine(cursor.line())))
01634 return;
01635
01636 int newLine = cursor.line(), newCol = 0, xOffset = 0, startCol = 0;
01637 m_preserveMaxX = true;
01638
01639 if (m_view->dynWordWrap()) {
01640
01641 LineRange thisRange = currentRange();
01642
01643 LineRange nRange = nextRange();
01644
01645
01646 Q_ASSERT((cursor.line() == thisRange.line) &&
01647 (cursor.col() >= thisRange.startCol) &&
01648 (!thisRange.wrap || cursor.col() < thisRange.endCol));
01649
01650
01651 int visibleX = m_view->renderer()->textWidth(cursor) - thisRange.startX;
01652 int currentLineVisibleX = visibleX;
01653
01654
01655 visibleX += thisRange.xOffset();
01656 visibleX -= nRange.xOffset();
01657
01658
01659 visibleX = QMAX(0, visibleX);
01660
01661 if (!thisRange.wrap) {
01662 newLine = m_doc->getRealLine(displayCursor.line() + 1);
01663 } else {
01664 startCol = thisRange.endCol;
01665 xOffset = thisRange.endX;
01666 }
01667
01668
01669
01670 if (thisRange.xOffset() && !nRange.xOffset() && currentLineVisibleX == 0)
01671 visibleX = m_currentMaxX;
01672 else if (visibleX < m_currentMaxX - nRange.xOffset())
01673 visibleX = m_currentMaxX - nRange.xOffset();
01674
01675 cXPos = xOffset + visibleX;
01676
01677 cXPos = QMIN(cXPos, lineMaxCursorX(nRange));
01678
01679 newCol = QMIN((int)m_view->renderer()->textPos(newLine, visibleX, startCol), lineMaxCol(nRange));
01680
01681 } else {
01682 newLine = m_doc->getRealLine(displayCursor.line() + 1);
01683
01684 if ((m_doc->wrapCursor()) && m_currentMaxX > cXPos)
01685 cXPos = m_currentMaxX;
01686 }
01687
01688 KateTextCursor c(newLine, newCol);
01689 m_view->renderer()->textWidth(c, cXPos);
01690
01691 updateSelection(c, sel);
01692 updateCursor(c);
01693 }
01694
01695 void KateViewInternal::cursorToMatchingBracket( bool sel )
01696 {
01697 KateTextCursor start( cursor ), end;
01698
01699 if( !m_doc->findMatchingBracket( start, end ) )
01700 return;
01701
01702
01703
01704
01705 if( end > start )
01706 end.setCol(end.col() + 1);
01707
01708 updateSelection( end, sel );
01709 updateCursor( end );
01710 }
01711
01712 void KateViewInternal::topOfView( bool sel )
01713 {
01714 KateTextCursor c = viewLineOffset(startPos(), m_minLinesVisible);
01715 updateSelection( c, sel );
01716 updateCursor( c );
01717 }
01718
01719 void KateViewInternal::bottomOfView( bool sel )
01720 {
01721
01722 KateTextCursor c = viewLineOffset(endPos(), -m_minLinesVisible);
01723 updateSelection( c, sel );
01724 updateCursor( c );
01725 }
01726
01727
01728 void KateViewInternal::scrollLines( int lines, bool sel )
01729 {
01730 KateTextCursor c = viewLineOffset(displayCursor, lines, true);
01731
01732
01733 c.setLine(m_doc->getRealLine(c.line()));
01734
01735 updateSelection( c, sel );
01736 updateCursor( c );
01737 }
01738
01739
01740 void KateViewInternal::scrollUp()
01741 {
01742 KateTextCursor newPos = viewLineOffset(m_startPos, -1);
01743 scrollPos(newPos);
01744 }
01745
01746 void KateViewInternal::scrollDown()
01747 {
01748 KateTextCursor newPos = viewLineOffset(m_startPos, 1);
01749 scrollPos(newPos);
01750 }
01751
01752 void KateViewInternal::setAutoCenterLines(int viewLines, bool updateView)
01753 {
01754 m_autoCenterLines = viewLines;
01755 m_minLinesVisible = QMIN(int((linesDisplayed() - 1)/2), m_autoCenterLines);
01756 if (updateView)
01757 KateViewInternal::updateView();
01758 }
01759
01760 void KateViewInternal::pageUp( bool sel )
01761 {
01762
01763 int viewLine = displayViewLine(displayCursor);
01764 bool atTop = (startPos().line() == 0 && startPos().col() == 0);
01765
01766
01767 int lineadj = 2 * m_minLinesVisible;
01768 int cursorStart = (linesDisplayed() - 1) - viewLine;
01769 if (cursorStart < m_minLinesVisible)
01770 lineadj -= m_minLinesVisible - cursorStart;
01771
01772 int linesToScroll = -QMAX( (linesDisplayed() - 1) - lineadj, 0 );
01773 m_preserveMaxX = true;
01774
01775
01776 if (!m_view->dynWordWrap()) {
01777 if (scrollbarVisible(startLine() + linesToScroll + viewLine)) {
01778 if (!m_columnScrollDisplayed) {
01779 linesToScroll++;
01780 }
01781 } else {
01782 if (m_columnScrollDisplayed) {
01783 linesToScroll--;
01784 }
01785 }
01786 }
01787
01788 if (!m_doc->pageUpDownMovesCursor () && !atTop) {
01789 int xPos = m_view->renderer()->textWidth(cursor) - currentRange().startX;
01790
01791 KateTextCursor newStartPos = viewLineOffset(startPos(), linesToScroll - 1);
01792 scrollPos(newStartPos);
01793
01794
01795 KateTextCursor newPos = viewLineOffset(newStartPos, viewLine, true);
01796 newPos.setLine(m_doc->getRealLine(newPos.line()));
01797
01798 LineRange newLine = range(newPos);
01799
01800 if (m_currentMaxX - newLine.xOffset() > xPos)
01801 xPos = m_currentMaxX - newLine.xOffset();
01802
01803 cXPos = QMIN(newLine.startX + xPos, lineMaxCursorX(newLine));
01804
01805 m_view->renderer()->textWidth( newPos, cXPos );
01806
01807 m_preserveMaxX = true;
01808 updateSelection( newPos, sel );
01809 updateCursor(newPos);
01810
01811 } else {
01812 scrollLines( linesToScroll, sel );
01813 }
01814 }
01815
01816 void KateViewInternal::pageDown( bool sel )
01817 {
01818
01819 int viewLine = displayViewLine(displayCursor);
01820 bool atEnd = startPos() >= m_cachedMaxStartPos;
01821
01822
01823 int lineadj = 2 * m_minLinesVisible;
01824 int cursorStart = m_minLinesVisible - viewLine;
01825 if (cursorStart > 0)
01826 lineadj -= cursorStart;
01827
01828 int linesToScroll = QMAX( (linesDisplayed() - 1) - lineadj, 0 );
01829 m_preserveMaxX = true;
01830
01831
01832 if (!m_view->dynWordWrap()) {
01833 if (scrollbarVisible(startLine() + linesToScroll + viewLine - (linesDisplayed() - 1))) {
01834 if (!m_columnScrollDisplayed) {
01835 linesToScroll--;
01836 }
01837 } else {
01838 if (m_columnScrollDisplayed) {
01839 linesToScroll--;
01840 }
01841 }
01842 }
01843
01844 if (!m_doc->pageUpDownMovesCursor () && !atEnd) {
01845 int xPos = m_view->renderer()->textWidth(cursor) - currentRange().startX;
01846
01847 KateTextCursor newStartPos = viewLineOffset(startPos(), linesToScroll + 1);
01848 scrollPos(newStartPos);
01849
01850
01851 KateTextCursor newPos = viewLineOffset(newStartPos, viewLine, true);
01852 newPos.setLine(m_doc->getRealLine(newPos.line()));
01853
01854 LineRange newLine = range(newPos);
01855
01856 if (m_currentMaxX - newLine.xOffset() > xPos)
01857 xPos = m_currentMaxX - newLine.xOffset();
01858
01859 cXPos = QMIN(newLine.startX + xPos, lineMaxCursorX(newLine));
01860
01861 m_view->renderer()->textWidth( newPos, cXPos );
01862
01863 m_preserveMaxX = true;
01864 updateSelection( newPos, sel );
01865 updateCursor(newPos);
01866
01867 } else {
01868 scrollLines( linesToScroll, sel );
01869 }
01870 }
01871
01872 bool KateViewInternal::scrollbarVisible(uint startLine)
01873 {
01874 return maxLen(startLine) > width() - 8;
01875 }
01876
01877 int KateViewInternal::maxLen(uint startLine)
01878 {
01879 Q_ASSERT(!m_view->dynWordWrap());
01880
01881 int displayLines = (m_view->height() / m_view->renderer()->fontHeight()) + 1;
01882
01883 int maxLen = 0;
01884
01885 for (int z = 0; z < displayLines; z++) {
01886 int virtualLine = startLine + z;
01887
01888 if (virtualLine < 0 || virtualLine >= (int)m_doc->visibleLines())
01889 break;
01890
01891 LineRange thisRange = range((int)m_doc->getRealLine(virtualLine));
01892
01893 maxLen = QMAX(maxLen, thisRange.endX);
01894 }
01895
01896 return maxLen;
01897 }
01898
01899 void KateViewInternal::top( bool sel )
01900 {
01901 KateTextCursor c( 0, cursor.col() );
01902 m_view->renderer()->textWidth( c, cXPos );
01903 updateSelection( c, sel );
01904 updateCursor( c );
01905 }
01906
01907 void KateViewInternal::bottom( bool sel )
01908 {
01909 KateTextCursor c( m_doc->lastLine(), cursor.col() );
01910 m_view->renderer()->textWidth( c, cXPos );
01911 updateSelection( c, sel );
01912 updateCursor( c );
01913 }
01914
01915 void KateViewInternal::top_home( bool sel )
01916 {
01917 KateTextCursor c( 0, 0 );
01918 updateSelection( c, sel );
01919 updateCursor( c );
01920 }
01921
01922 void KateViewInternal::bottom_end( bool sel )
01923 {
01924 KateTextCursor c( m_doc->lastLine(), m_doc->lineLength( m_doc->lastLine() ) );
01925 updateSelection( c, sel );
01926 updateCursor( c );
01927 }
01928
01929 void KateViewInternal::updateSelection( const KateTextCursor& newCursor, bool keepSel )
01930 {
01931 if( keepSel )
01932 {
01933 if ( !m_doc->hasSelection() || (selectAnchor.line() == -1)
01934 || ((m_doc->configFlags() & KateDocument::cfPersistent)
01935 && ((cursor < m_doc->selectStart) || (cursor > m_doc->selectEnd))) )
01936 {
01937 selectAnchor = cursor;
01938 m_doc->setSelection( cursor, newCursor );
01939 }
01940 else
01941 m_doc->setSelection( selectAnchor, newCursor);
01942
01943 m_selChangedByUser = true;
01944 }
01945 else if ( !(m_doc->configFlags() & KateDocument::cfPersistent) )
01946 m_doc->clearSelection();
01947 }
01948
01949 void KateViewInternal::updateCursor( const KateTextCursor& newCursor, bool force, bool center )
01950 {
01951 TextLine::Ptr l = textLine( newCursor.line() );
01952
01953 if ( !force && (cursor == newCursor) )
01954 {
01955 if ( !m_madeVisible )
01956 {
01957
01958 if ( l && ! l->isVisible() )
01959 m_doc->foldingTree()->ensureVisible( newCursor.line() );
01960
01961 makeVisible ( displayCursor, displayCursor.col(), false, center );
01962 }
01963
01964 return;
01965 }
01966
01967
01968 if ( l && ! l->isVisible() )
01969 m_doc->foldingTree()->ensureVisible( newCursor.line() );
01970
01971 KateTextCursor oldDisplayCursor = displayCursor;
01972
01973 cursor.setPos (newCursor);
01974 displayCursor.setPos (m_doc->getVirtualLine(cursor.line()), cursor.col());
01975
01976 cXPos = m_view->renderer()->textWidth( cursor );
01977 makeVisible ( displayCursor, displayCursor.col(), false, center );
01978
01979 updateBracketMarks();
01980
01981
01982 tagLine(oldDisplayCursor);
01983 tagLine(displayCursor);
01984
01985 QPoint cursorP = cursorCoordinates();
01986 setMicroFocusHint( cursorP.x(), cursorP.y(), 0, m_view->renderer()->fontHeight() );
01987
01988 if (m_cursorTimer.isActive ())
01989 {
01990 m_cursorTimer.start( KApplication::cursorFlashTime() / 2 );
01991 m_view->renderer()->setDrawCaret(true);
01992 }
01993
01994
01995 if (m_preserveMaxX)
01996 m_preserveMaxX = false;
01997 else
01998 if (m_view->dynWordWrap())
01999 m_currentMaxX = m_view->renderer()->textWidth(displayCursor) - currentRange().startX + currentRange().xOffset();
02000 else
02001 m_currentMaxX = cXPos;
02002
02003
02004
02005
02006 paintText(0, 0, width(), height(), true);
02007
02008 emit m_view->cursorPositionChanged();
02009 }
02010
02011 void KateViewInternal::updateBracketMarks()
02012 {
02013 if ( bm.isValid() ) {
02014 KateTextCursor bmStart(m_doc->getVirtualLine(bm.start().line()), bm.start().col());
02015 KateTextCursor bmEnd(m_doc->getVirtualLine(bm.end().line()), bm.end().col());
02016 tagLine(bmStart);
02017 tagLine(bmEnd);
02018 }
02019
02020 m_doc->newBracketMark( cursor, bm );
02021
02022 if ( bm.isValid() ) {
02023 KateTextCursor bmStart(m_doc->getVirtualLine(bm.start().line()), bm.start().col());
02024 KateTextCursor bmEnd(m_doc->getVirtualLine(bm.end().line()), bm.end().col());
02025 tagLine(bmStart);
02026 tagLine(bmEnd);
02027 }
02028 }
02029
02030 bool KateViewInternal::tagLine(const KateTextCursor& virtualCursor)
02031 {
02032 int viewLine = displayViewLine(virtualCursor, true);
02033 if (viewLine >= 0 && viewLine < (int)lineRanges.count()) {
02034 lineRanges[viewLine].dirty = true;
02035 leftBorder->update (0, lineToY(viewLine), leftBorder->width(), m_view->renderer()->fontHeight());
02036 return true;
02037 }
02038 return false;
02039 }
02040
02041 bool KateViewInternal::tagLines( int start, int end, bool realLines )
02042 {
02043 return tagLines(KateTextCursor(start, 0), KateTextCursor(end, -1), realLines);
02044 }
02045
02046 bool KateViewInternal::tagLines(KateTextCursor start, KateTextCursor end, bool realCursors)
02047 {
02048 if (realCursors)
02049 {
02050
02051 start.setLine(m_doc->getVirtualLine( start.line() ));
02052 end.setLine(m_doc->getVirtualLine( end.line() ));
02053 }
02054
02055 if (end.line() < (int)startLine())
02056 {
02057
02058 return false;
02059 }
02060 if (start.line() > (int)endLine())
02061 {
02062
02063 return false;
02064 }
02065
02066
02067
02068 bool ret = false;
02069
02070 for (uint z = 0; z < lineRanges.size(); z++)
02071 {
02072 if ((lineRanges[z].virtualLine > start.line() || (lineRanges[z].virtualLine == start.line() && lineRanges[z].endCol >= start.col() && start.col() != -1)) && (lineRanges[z].virtualLine < end.line() || (lineRanges[z].virtualLine == end.line() && (lineRanges[z].startCol <= end.col() || end.col() == -1)))) {
02073 ret = lineRanges[z].dirty = true;
02074
02075 }
02076 }
02077
02078 if (!m_view->dynWordWrap())
02079 {
02080 int y = lineToY( start.line() );
02081
02082 int h = (end.line() - start.line() + 2) * m_view->renderer()->fontHeight();
02083 if (end.line() == (int)m_doc->numVisLines() - 1)
02084 h = height();
02085
02086 leftBorder->update (0, y, leftBorder->width(), h);
02087 }
02088 else
02089 {
02090
02091
02092 for (uint z = 0; z < lineRanges.size(); z++)
02093 {
02094 if ((lineRanges[z].virtualLine > start.line() || (lineRanges[z].virtualLine == start.line() && lineRanges[z].endCol >= start.col() && start.col() != -1)) && (lineRanges[z].virtualLine < end.line() || (lineRanges[z].virtualLine == end.line() && (lineRanges[z].startCol <= end.col() || end.col() == -1))))
02095 {
02096
02097 leftBorder->update (0, z * m_view->renderer()->fontHeight(), leftBorder->width(), leftBorder->height());
02098 break;
02099 }
02100
02101
02102
02103
02104
02105
02106 }
02107 }
02108
02109 return ret;
02110 }
02111
02112 void KateViewInternal::tagAll()
02113 {
02114
02115 for (uint z = 0; z < lineRanges.size(); z++)
02116 {
02117 lineRanges[z].dirty = true;
02118 }
02119
02120 leftBorder->updateFont();
02121 leftBorder->update ();
02122 }
02123
02124 void KateViewInternal::paintCursor()
02125 {
02126 if (tagLine(displayCursor))
02127 paintText (0,0,width(), height(), true);
02128 }
02129
02130
02131 void KateViewInternal::placeCursor( const QPoint& p, bool keepSelection, bool updateSelection )
02132 {
02133 LineRange thisRange = yToLineRange(p.y());
02134
02135 if (thisRange.line == -1) {
02136 for (int i = (p.y() / m_view->renderer()->fontHeight()); i >= 0; i--) {
02137 thisRange = lineRanges[i];
02138 if (thisRange.line != -1)
02139 break;
02140 }
02141 Q_ASSERT(thisRange.line != -1);
02142 }
02143
02144 int realLine = thisRange.line;
02145 int visibleLine = thisRange.virtualLine;
02146 uint startCol = thisRange.startCol;
02147
02148 visibleLine = QMAX( 0, QMIN( visibleLine, int(m_doc->numVisLines()) - 1 ) );
02149
02150 KateTextCursor c(realLine, 0);
02151
02152 int x = QMIN(QMAX(0, p.x() - thisRange.xOffset()), lineMaxCursorX(thisRange) - thisRange.startX);
02153
02154 m_view->renderer()->textWidth( c, startX() + x, startCol);
02155
02156 if (updateSelection)
02157 KateViewInternal::updateSelection( c, keepSelection );
02158 updateCursor( c );
02159 }
02160
02161
02162 bool KateViewInternal::isTargetSelected( const QPoint& p )
02163 {
02164 LineRange thisRange = yToLineRange(p.y());
02165
02166 TextLine::Ptr l = textLine( thisRange.line );
02167 if( !l )
02168 return false;
02169
02170 int col = m_view->renderer()->textPos( l, p.x() - thisRange.xOffset(), thisRange.startCol );
02171
02172 return m_doc->lineColSelected( thisRange.line, col );
02173 }
02174
02175
02176
02177
02178
02179 bool KateViewInternal::eventFilter( QObject *obj, QEvent *e )
02180 {
02181 if (obj == m_lineScroll)
02182 {
02183
02184 if (e->type() == QEvent::Wheel && m_lineScroll->minValue() != m_lineScroll->maxValue())
02185 {
02186 wheelEvent((QWheelEvent*)e);
02187 return true;
02188 }
02189
02190
02191 return QWidget::eventFilter( obj, e );
02192 }
02193
02194 switch( e->type() )
02195 {
02196 case QEvent::KeyPress:
02197 {
02198 QKeyEvent *k = (QKeyEvent *)e;
02199
02200 if ((k->key() == Qt::Key_Escape) && !(m_doc->configFlags() & KateDocument::cfPersistent) )
02201 {
02202 m_doc->clearSelection();
02203 return true;
02204 }
02205 else if ( !((k->state() & ControlButton) || (k->state() & AltButton)) )
02206 {
02207 keyPressEvent( k );
02208 return k->isAccepted();
02209 }
02210
02211 } break;
02212
02213 case QEvent::DragMove:
02214 {
02215 QPoint currentPoint = ((QDragMoveEvent*) e)->pos();
02216
02217 QRect doNotScrollRegion( scrollMargin, scrollMargin,
02218 width() - scrollMargin * 2,
02219 height() - scrollMargin * 2 );
02220
02221 if ( !doNotScrollRegion.contains( currentPoint ) )
02222 {
02223 startDragScroll();
02224
02225 ( (QDragMoveEvent*)e )->accept( QRect(0,0,0,0) );
02226 }
02227
02228 dragMoveEvent((QDragMoveEvent*)e);
02229 } break;
02230
02231 case QEvent::DragLeave:
02232 stopDragScroll();
02233 break;
02234
02235 case QEvent::User + TimeMarkerEvent:
02236 m_scrollTranslateHack = 0;
02237 break;
02238
02239 default:
02240 break;
02241 }
02242
02243 return QWidget::eventFilter( obj, e );
02244 }
02245
02246 void KateViewInternal::keyPressEvent( QKeyEvent* e )
02247 {
02248 KKey key(e);
02249
02250 if (key == Qt::Key_Left)
02251 {
02252 m_view->cursorLeft();
02253 e->accept();
02254 return;
02255 }
02256
02257 if (key == Qt::Key_Right)
02258 {
02259 m_view->cursorRight();
02260 e->accept();
02261 return;
02262 }
02263
02264 if (key == Qt::Key_Down)
02265 {
02266 m_view->down();
02267 e->accept();
02268 return;
02269 }
02270
02271 if (key == Qt::Key_Up)
02272 {
02273 m_view->up();
02274 e->accept();
02275 return;
02276 }
02277
02278 if( !m_doc->isReadWrite() )
02279 {
02280 e->ignore();
02281 return;
02282 }
02283
02284 if ((key == Qt::Key_Return) || (key == Qt::Key_Enter) ||
02285 (key == SHIFT + Qt::Key_Return) || (key == SHIFT + Qt::Key_Enter))
02286 {
02287 m_view->keyReturn();
02288 e->accept();
02289 return;
02290 }
02291
02292 if (key == Qt::Key_Backspace || key == SHIFT + Qt::Key_Backspace)
02293 {
02294 m_view->backspace();
02295 e->accept();
02296 return;
02297 }
02298
02299 if (key == Qt::Key_Delete)
02300 {
02301 m_view->keyDelete();
02302 e->accept();
02303 return;
02304 }
02305
02306 if( (key == Qt::Key_Tab || key == SHIFT+Qt::Key_Backtab || key == Qt::Key_Backtab)
02307 && (m_doc->configFlags() & KateDocumentConfig::cfTabIndents) )
02308 {
02309 if( key == Qt::Key_Tab )
02310 {
02311 if (m_doc->hasSelection() || (m_doc->configFlags() & KateDocumentConfig::cfTabIndentsMode))
02312 m_doc->indent( m_view, cursor.line(), 1 );
02313 else if (m_doc->configFlags() & KateDocumentConfig::cfTabInsertsTab)
02314 m_doc->typeChars ( m_view, QString ("\t") );
02315 else
02316 m_doc->insertIndentChars ( m_view );
02317
02318 e->accept();
02319 return;
02320 }
02321
02322 if (key == SHIFT+Qt::Key_Backtab || key == Qt::Key_Backtab)
02323 {
02324 m_doc->indent( m_view, cursor.line(), -1 );
02325 e->accept();
02326 return;
02327 }
02328 }
02329
02330 if ( !(e->state() & ControlButton) && !(e->state() & AltButton)
02331 && m_doc->typeChars ( m_view, e->text() ) )
02332 {
02333 e->accept();
02334 return;
02335 }
02336
02337 e->ignore();
02338 }
02339
02340 void KateViewInternal::keyReleaseEvent( QKeyEvent* e )
02341 {
02342 KKey key(e);
02343
02344 if (key == SHIFT)
02345 m_shiftKeyPressed = true;
02346 else
02347 {
02348 if (m_shiftKeyPressed)
02349 {
02350 m_shiftKeyPressed = false;
02351
02352 if (m_selChangedByUser)
02353 {
02354 QApplication::clipboard()->setSelectionMode( true );
02355 m_doc->copy();
02356 QApplication::clipboard()->setSelectionMode( false );
02357
02358 m_selChangedByUser = false;
02359 }
02360 }
02361 }
02362
02363 e->ignore();
02364 return;
02365 }
02366
02367 void KateViewInternal::mousePressEvent( QMouseEvent* e )
02368 {
02369 switch (e->button())
02370 {
02371 case LeftButton:
02372 m_selChangedByUser = false;
02373
02374 if (possibleTripleClick)
02375 {
02376 possibleTripleClick = false;
02377
02378 m_doc->selectLine( cursor );
02379 QApplication::clipboard()->setSelectionMode( true );
02380 m_doc->copy();
02381 QApplication::clipboard()->setSelectionMode( false );
02382
02383 cursor.setCol(0);
02384 updateCursor( cursor );
02385 return;
02386 }
02387
02388 if( isTargetSelected( e->pos() ) )
02389 {
02390 dragInfo.state = diPending;
02391 dragInfo.start = e->pos();
02392 }
02393 else
02394 {
02395 dragInfo.state = diNone;
02396
02397 placeCursor( e->pos(), e->state() & ShiftButton );
02398 scrollX = 0;
02399 scrollY = 0;
02400
02401 m_scrollTimer.start (50);
02402 }
02403
02404 e->accept ();
02405 break;
02406
02407 case RightButton:
02408 if ( !isTargetSelected( e->pos() ) )
02409 placeCursor( e->pos() );
02410
02411 if (leftBorder->positionToArea( e->pos() ) != KateIconBorder::IconBorder)
02412 {
02413
02414 if (m_view->popup())
02415 m_view->popup()->popup( mapToGlobal( e->pos() ) );
02416 }
02417 e->accept ();
02418 break;
02419
02420 default:
02421 e->ignore ();
02422 break;
02423 }
02424 }
02425
02426 void KateViewInternal::mouseDoubleClickEvent(QMouseEvent *e)
02427 {
02428 switch (e->button())
02429 {
02430 case LeftButton:
02431 m_doc->selectWord( cursor );
02432
02433
02434 if (m_doc->hasSelection())
02435 {
02436 QApplication::clipboard()->setSelectionMode( true );
02437 m_doc->copy();
02438 QApplication::clipboard()->setSelectionMode( false );
02439
02440 cursor.setPos(m_doc->selectEnd);
02441 updateCursor( cursor );
02442 }
02443
02444 possibleTripleClick = true;
02445 QTimer::singleShot ( QApplication::doubleClickInterval(), this, SLOT(tripleClickTimeout()) );
02446
02447 e->accept ();
02448 break;
02449
02450 default:
02451 e->ignore ();
02452 break;
02453 }
02454 }
02455
02456 void KateViewInternal::tripleClickTimeout()
02457 {
02458 possibleTripleClick = false;
02459 }
02460
02461 void KateViewInternal::mouseReleaseEvent( QMouseEvent* e )
02462 {
02463 switch (e->button())
02464 {
02465 case LeftButton:
02466 if (m_selChangedByUser)
02467 {
02468 QApplication::clipboard()->setSelectionMode( true );
02469 m_doc->copy();
02470 QApplication::clipboard()->setSelectionMode( false );
02471
02472 m_selChangedByUser = false;
02473 }
02474
02475 if (dragInfo.state == diPending)
02476 placeCursor( e->pos() );
02477 else if (dragInfo.state == diNone)
02478 m_scrollTimer.stop ();
02479
02480 dragInfo.state = diNone;
02481
02482 e->accept ();
02483 break;
02484
02485 case MidButton:
02486 placeCursor( e->pos() );
02487
02488 if( m_doc->isReadWrite() )
02489 {
02490 QApplication::clipboard()->setSelectionMode( true );
02491 doPaste();
02492 QApplication::clipboard()->setSelectionMode( false );
02493 }
02494
02495 e->accept ();
02496 break;
02497
02498 default:
02499 e->ignore ();
02500 break;
02501 }
02502 }
02503
02504 void KateViewInternal::mouseMoveEvent( QMouseEvent* e )
02505 {
02506 if( e->state() & LeftButton )
02507 {
02508 if (dragInfo.state == diPending)
02509 {
02510
02511
02512 QPoint p( e->pos() - dragInfo.start );
02513
02514
02515 if( p.manhattanLength() > KGlobalSettings::dndEventDelay() )
02516 doDrag();
02517
02518 return;
02519 }
02520
02521 mouseX = e->x();
02522 mouseY = e->y();
02523
02524 scrollX = 0;
02525 scrollY = 0;
02526 int d = m_view->renderer()->fontHeight();
02527
02528 if (mouseX < 0)
02529 scrollX = -d;
02530
02531 if (mouseX > width())
02532 scrollX = d;
02533
02534 if (mouseY < 0)
02535 {
02536 mouseY = 0;
02537 scrollY = -d;
02538 }
02539
02540 if (mouseY > height())
02541 {
02542 mouseY = height();
02543 scrollY = d;
02544 }
02545
02546 placeCursor( QPoint( mouseX, mouseY ), true );
02547 }
02548 else
02549 {
02550 if (m_textHintEnabled)
02551 {
02552 m_textHintTimer.start(m_textHintTimeout);
02553 m_textHintMouseX=e->x();
02554 m_textHintMouseY=e->y();
02555 }
02556 }
02557 }
02558
02559 void KateViewInternal::paintEvent(QPaintEvent *e)
02560 {
02561 static bool forgetNext = false;
02562
02563 if (!forgetNext && m_scrollTranslateHack) {
02564
02565 QRect updateR = e->rect();
02566
02567
02568 updateR.moveBy(0, m_scrollTranslateHack);
02569
02570
02571 updateR = updateR.intersect(QRect(0, m_scrollTranslateHack < 0 ? 0 : m_scrollTranslateHack, width(), m_scrollTranslateHack < 0 ? height() + m_scrollTranslateHack : height()));
02572
02573
02574 if (updateR.intersects(e->rect()))
02575 updateR = QRegion(updateR).subtract(e->region()).boundingRect();
02576
02577
02578 forgetNext = true;
02579 repaint(updateR.x(), updateR.y(), updateR.width(), updateR.height(), false);
02580 }
02581
02582 forgetNext = false;
02583
02584 paintText(e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height());
02585 }
02586
02587 void KateViewInternal::resizeEvent(QResizeEvent* e)
02588 {
02589 bool expandedHorizontally = width() > e->oldSize().width();
02590 bool expandedVertically = height() > e->oldSize().height();
02591
02592 m_madeVisible = false;
02593
02594 if (height() != e->oldSize().height()) {
02595 setAutoCenterLines(m_autoCenterLines, false);
02596 }
02597
02598 if (height() != e->oldSize().height())
02599 m_cachedMaxStartPos.setPos(-1, -1);
02600
02601 if (m_view->dynWordWrap()) {
02602 bool dirtied = false;
02603
02604 int currentViewLine = displayViewLine(displayCursor, true);
02605
02606 for (uint i = 0; i < lineRanges.count(); i++) {
02607
02608
02609 if (lineRanges[i].wrap ||
02610 (!expandedHorizontally && (lineRanges[i].endX - lineRanges[i].startX) > width())) {
02611 dirtied = lineRanges[i].dirty = true;
02612 break;
02613 }
02614 }
02615
02616 if (dirtied || expandedVertically) {
02617 updateView(true);
02618 leftBorder->update();
02619
02620
02621 if (currentViewLine >= 0)
02622 makeVisible(displayCursor, displayCursor.col());
02623 }
02624
02625 if (width() < e->oldSize().width()) {
02626 if (!m_doc->wrapCursor()) {
02627
02628 if (cursor.col() > m_doc->lineLength(cursor.line())) {
02629 LineRange thisRange = currentRange();
02630
02631 KateTextCursor newCursor(cursor.line(), thisRange.endCol + ((width() - thisRange.xOffset() - (thisRange.endX - thisRange.startX)) / m_view->renderer()->spaceWidth()) - 1);
02632 updateCursor(newCursor);
02633 }
02634 }
02635 }
02636
02637 } else {
02638 updateView();
02639
02640 if (expandedHorizontally && startX() > 0)
02641 scrollColumns(startX() - (width() - e->oldSize().width()));
02642 }
02643
02644 if (expandedVertically) {
02645 KateTextCursor max = maxStartPos();
02646 if (startPos() > max)
02647 scrollPos(max);
02648 }
02649 }
02650
02651 void KateViewInternal::scrollTimeout ()
02652 {
02653 if (scrollX || scrollY)
02654 {
02655 scrollLines (startPos().line() + (scrollY / (int)m_view->renderer()->fontHeight()));
02656 placeCursor( QPoint( mouseX, mouseY ), true );
02657 }
02658 }
02659
02660 void KateViewInternal::cursorTimeout ()
02661 {
02662 m_view->renderer()->setDrawCaret(!m_view->renderer()->drawCaret());
02663 paintCursor();
02664 }
02665
02666 void KateViewInternal::textHintTimeout ()
02667 {
02668 m_textHintTimer.stop ();
02669
02670 LineRange thisRange = yToLineRange(m_textHintMouseY);
02671
02672 if (thisRange.line == -1) return;
02673
02674 if (m_textHintMouseX> (lineMaxCursorX(thisRange) - thisRange.startX)) return;
02675
02676 int realLine = thisRange.line;
02677 int startCol = thisRange.startCol;
02678
02679 KateTextCursor c(realLine, 0);
02680 m_view->renderer()->textWidth( c, startX() + m_textHintMouseX, startCol);
02681
02682 QString tmp;
02683
02684 emit m_view->needTextHint(c.line(), c.col(), tmp);
02685
02686 if (!tmp.isEmpty()) kdDebug(13030)<<"Hint text: "<<tmp<<endl;
02687 }
02688
02689 void KateViewInternal::focusInEvent (QFocusEvent *)
02690 {
02691 m_cursorTimer.start ( KApplication::cursorFlashTime() / 2 );
02692
02693 if (m_textHintEnabled)
02694 m_textHintTimer.start( m_textHintTimeout );
02695
02696 paintCursor();
02697
02698 m_doc->m_activeView = m_view;
02699
02700 emit m_view->gotFocus( m_view );
02701 }
02702
02703 void KateViewInternal::focusOutEvent (QFocusEvent *)
02704 {
02705 if( ! m_view->m_codeCompletion->codeCompletionVisible() )
02706 {
02707 m_cursorTimer.stop();
02708
02709 m_view->renderer()->setDrawCaret(true);
02710 paintCursor();
02711 emit m_view->lostFocus( m_view );
02712 }
02713
02714 m_textHintTimer.stop();
02715 }
02716
02717 void KateViewInternal::doDrag()
02718 {
02719 dragInfo.state = diDragging;
02720 dragInfo.dragObject = new QTextDrag(m_doc->selection(), this);
02721 dragInfo.dragObject->dragCopy();
02722 }
02723
02724 void KateViewInternal::dragEnterEvent( QDragEnterEvent* event )
02725 {
02726 event->accept( (QTextDrag::canDecode(event) && m_doc->isReadWrite()) ||
02727 KURLDrag::canDecode(event) );
02728 }
02729
02730 void KateViewInternal::dragMoveEvent( QDragMoveEvent* event )
02731 {
02732
02733 placeCursor( event->pos(), true, false );
02734 }
02735
02736 void KateViewInternal::dropEvent( QDropEvent* event )
02737 {
02738 if ( KURLDrag::canDecode(event) ) {
02739
02740 emit dropEventPass(event);
02741
02742 } else if ( QTextDrag::canDecode(event) && m_doc->isReadWrite() ) {
02743
02744 QString text;
02745
02746 if (!QTextDrag::decode(event, text))
02747 return;
02748
02749
02750 bool priv = false;
02751 if (event->source() && event->source()->inherits("KateViewInternal"))
02752 priv = m_doc->ownedView( ((KateViewInternal*)(event->source()))->m_view );
02753
02754
02755 bool selected = isTargetSelected( event->pos() );
02756
02757 if( priv && selected ) {
02758
02759
02760 return;
02761 }
02762
02763
02764 m_doc->insertText( cursor.line(), cursor.col(), text );
02765 placeCursor( event->pos() );
02766
02767 updateView();
02768 }
02769 }
02770
02771 void KateViewInternal::imStartEvent( QIMEvent *e )
02772 {
02773 if ( m_doc->m_bReadOnly ) {
02774 e->ignore();
02775 return;
02776 }
02777
02778 if ( m_doc->hasSelection() )
02779 m_doc->removeSelectedText();
02780
02781 m_imPreeditStartLine = cursor.line();
02782 m_imPreeditStart = cursor.col();
02783 m_imPreeditLength = 0;
02784
02785 m_doc->setIMSelectionValue( m_imPreeditStartLine, m_imPreeditStart, 0, 0, 0, true );
02786 }
02787
02788 void KateViewInternal::imComposeEvent( QIMEvent *e )
02789 {
02790 if ( m_doc->m_bReadOnly ) {
02791 e->ignore();
02792 return;
02793 }
02794
02795 if ( m_imPreeditLength > 0 ) {
02796 m_doc->removeText( cursor.line(), m_imPreeditStart,
02797 cursor.line(), m_imPreeditStart + m_imPreeditLength );
02798 }
02799
02800 m_doc->setIMSelectionValue( m_imPreeditStartLine, m_imPreeditStart, m_imPreeditStart + e->text().length(),
02801 m_imPreeditStart + e->cursorPos(), m_imPreeditStart + e->cursorPos() + e->selectionLength(),
02802 true );
02803
02804 m_doc->insertText( cursor.line(), cursor.col(), e->text() );
02805
02806 updateView( true );
02807 updateCursor( cursor, true );
02808 m_imPreeditLength = e->text().length();
02809 }
02810
02811 void KateViewInternal::imEndEvent( QIMEvent *e )
02812 {
02813 if ( m_doc->m_bReadOnly ) {
02814 e->ignore();
02815 return;
02816 }
02817
02818 if ( m_imPreeditLength > 0 ) {
02819 m_doc->removeText( cursor.line(), m_imPreeditStart,
02820 cursor.line(), m_imPreeditStart + m_imPreeditLength );
02821 }
02822
02823 m_doc->setIMSelectionValue( m_imPreeditStartLine, m_imPreeditStart, 0, 0, 0, false );
02824
02825 if ( e->text().length() > 0 ) {
02826 m_doc->insertText( cursor.line(), cursor.col(), e->text() );
02827
02828 if ( !m_cursorTimer.isActive() )
02829 m_cursorTimer.start ( KApplication::cursorFlashTime() / 2 );
02830
02831 updateView( true );
02832 updateCursor( cursor, true );
02833
02834 }
02835
02836 m_imPreeditStart = 0;
02837 m_imPreeditLength = 0;
02838 }
02839
02840
02841
02842
02843
02844 void KateViewInternal::clear()
02845 {
02846 cursor.setPos(0, 0);
02847 displayCursor.setPos(0, 0);
02848 }
02849
02850 void KateViewInternal::wheelEvent(QWheelEvent* e)
02851 {
02852 if (m_lineScroll->minValue() != m_lineScroll->maxValue() && e->orientation() != Qt::Horizontal) {
02853
02854 if ( ( e->state() & ControlButton ) || ( e->state() & ShiftButton ) ) {
02855 if (e->delta() > 0)
02856 scrollPrevPage();
02857 else
02858 scrollNextPage();
02859 } else {
02860 scrollViewLines(-((e->delta() / 120) * QApplication::wheelScrollLines()));
02861 }
02862
02863 } else if (!m_columnScroll->isHidden()) {
02864 QWheelEvent copy = *e;
02865 QApplication::sendEvent(m_columnScroll, ©);
02866
02867 } else {
02868 e->ignore();
02869 }
02870 }
02871
02872 void KateViewInternal::startDragScroll()
02873 {
02874 if ( !m_dragScrollTimer.isActive() ) {
02875 m_suppressColumnScrollBar = true;
02876 m_dragScrollTimer.start( scrollTime );
02877 }
02878 }
02879
02880 void KateViewInternal::stopDragScroll()
02881 {
02882 m_suppressColumnScrollBar = false;
02883 m_dragScrollTimer.stop();
02884 updateView();
02885 }
02886
02887 void KateViewInternal::doDragScroll()
02888 {
02889 QPoint p = this->mapFromGlobal( QCursor::pos() );
02890
02891 int dx = 0, dy = 0;
02892 if ( p.y() < scrollMargin ) {
02893 dy = p.y() - scrollMargin;
02894 } else if ( p.y() > height() - scrollMargin ) {
02895 dy = scrollMargin - (height() - p.y());
02896 }
02897 if ( p.x() < scrollMargin ) {
02898 dx = p.x() - scrollMargin;
02899 } else if ( p.x() > width() - scrollMargin ) {
02900 dx = scrollMargin - (width() - p.x());
02901 }
02902 dy /= 4;
02903
02904 if (dy)
02905 scrollLines(startPos().line() + dy);
02906 if (dx)
02907 scrollColumns(m_startX + dx);
02908 if (!dy && !dx)
02909 stopDragScroll();
02910 }
02911
02912 void KateViewInternal::enableTextHints(int timeout)
02913 {
02914 m_textHintTimeout=timeout;
02915 m_textHintEnabled=true;
02916 m_textHintTimer.start(timeout);
02917 }
02918
02919 void KateViewInternal::disableTextHints()
02920 {
02921 m_textHintEnabled=false;
02922 m_textHintTimer.stop ();
02923 }
02924
02925
02926 void KateViewInternal::editStart()
02927 {
02928 editSessionNumber++;
02929
02930 if (editSessionNumber > 1)
02931 return;
02932
02933 editIsRunning = true;
02934 editOldCursor = cursor;
02935 }
02936
02937 void KateViewInternal::editEnd(int editTagLineStart, int editTagLineEnd, bool tagFrom)
02938 {
02939 if (editSessionNumber == 0)
02940 return;
02941
02942 editSessionNumber--;
02943
02944 if (editSessionNumber > 0)
02945 return;
02946
02947 if (tagFrom && (editTagLineStart <= int(m_doc->getRealLine(startLine()))))
02948 tagAll();
02949 else
02950 tagLines (editTagLineStart, tagFrom ? m_doc->lastLine() : editTagLineEnd, true);
02951
02952 if (editOldCursor == cursor)
02953 updateBracketMarks();
02954
02955 if (m_imPreeditLength <= 0)
02956 updateView(true);
02957
02958 if ((editOldCursor != cursor) && (m_imPreeditLength <= 0))
02959 {
02960 m_madeVisible = false;
02961 updateCursor ( cursor, true );
02962 }
02963 else
02964 {
02965 makeVisible(displayCursor, displayCursor.col());
02966 }
02967
02968 editIsRunning = false;
02969 }
02970
02971 void KateViewInternal::editSetCursor (const KateTextCursor &cursor)
02972 {
02973 if (this->cursor != cursor)
02974 {
02975 this->cursor.setPos (cursor);
02976 }
02977 }
02978
02979
02980 void KateViewInternal::docSelectionChanged ()
02981 {
02982 if (!m_doc->hasSelection())
02983 selectAnchor.setPos (-1, -1);
02984 }
02985
02986
02987 KateScrollBar::KateScrollBar (Orientation orientation, QWidget* parent, const char* name)
02988 : QScrollBar (orientation, parent, name)
02989 , m_middleMouseDown (false)
02990 {
02991 connect(this, SIGNAL(valueChanged(int)), SLOT(sliderMaybeMoved(int)));
02992 }
02993
02994 void KateScrollBar::mousePressEvent(QMouseEvent* e)
02995 {
02996 if (e->button() == MidButton)
02997 m_middleMouseDown = true;
02998
02999 QScrollBar::mousePressEvent(e);
03000 }
03001
03002 void KateScrollBar::mouseReleaseEvent(QMouseEvent* e)
03003 {
03004 QScrollBar::mouseReleaseEvent(e);
03005
03006 m_middleMouseDown = false;
03007 }
03008
03009 void KateScrollBar::sliderMaybeMoved(int value)
03010 {
03011 if (m_middleMouseDown)
03012 emit sliderMMBMoved(value);
03013 }
03014
03015 TextLine::Ptr KateViewInternal::textLine( int realLine )
03016 {
03017 if (m_usePlainLines)
03018 return m_doc->plainKateTextLine(realLine);
03019 else
03020 return m_doc->kateTextLine(realLine);
03021 }
03022
03023
03024
03025