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