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