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