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