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