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