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 if (line == -1)
00874 return;
00875
00876 KateRenderer *renderer = m_view->renderer();
00877
00878
00879
00880
00881
00882
00883 uint preeditStrLen = renderer->textWidth(textLine(m_imPreeditStartLine), cursor.col()) - renderer->textWidth(textLine(m_imPreeditStartLine), m_imPreeditSelStart);
00884 uint x = cXPos - m_startX - lineRanges[line].startX + lineRanges[line].xOffset() - preeditStrLen;
00885 uint y = line * renderer->fontHeight();
00886
00887 setMicroFocusHint(x, y, 0, renderer->fontHeight());
00888 }
00889
00890 void KateViewInternal::doReturn()
00891 {
00892 KateTextCursor c = cursor;
00893 m_doc->newLine( c, this );
00894 updateCursor( c );
00895 updateView();
00896 }
00897
00898 void KateViewInternal::doDelete()
00899 {
00900 m_doc->del( m_view, cursor );
00901 if (m_view->m_codeCompletion->codeCompletionVisible()) {
00902 m_view->m_codeCompletion->updateBox();
00903 }
00904 }
00905
00906 void KateViewInternal::doBackspace()
00907 {
00908 m_doc->backspace( m_view, cursor );
00909 if (m_view->m_codeCompletion->codeCompletionVisible()) {
00910 m_view->m_codeCompletion->updateBox();
00911 }
00912 }
00913
00914 void KateViewInternal::doTranspose()
00915 {
00916 m_doc->transpose( cursor );
00917 }
00918
00919 void KateViewInternal::doDeleteWordLeft()
00920 {
00921 wordLeft( true );
00922 m_view->removeSelectedText();
00923 update();
00924 }
00925
00926 void KateViewInternal::doDeleteWordRight()
00927 {
00928 wordRight( true );
00929 m_view->removeSelectedText();
00930 update();
00931 }
00932
00933 class CalculatingCursor : public KateTextCursor {
00934 public:
00935 CalculatingCursor(KateViewInternal* vi)
00936 : KateTextCursor()
00937 , m_vi(vi)
00938 {
00939 Q_ASSERT(valid());
00940 }
00941
00942 CalculatingCursor(KateViewInternal* vi, const KateTextCursor& c)
00943 : KateTextCursor(c)
00944 , m_vi(vi)
00945 {
00946 Q_ASSERT(valid());
00947 }
00948
00949
00950 CalculatingCursor(KateViewInternal* vi, uint line, uint col)
00951 : KateTextCursor(line, col)
00952 , m_vi(vi)
00953 {
00954 makeValid();
00955 }
00956
00957
00958 virtual CalculatingCursor& operator+=( int n ) = 0;
00959
00960 virtual CalculatingCursor& operator-=( int n ) = 0;
00961
00962 CalculatingCursor& operator++() { return operator+=( 1 ); }
00963
00964 CalculatingCursor& operator--() { return operator-=( 1 ); }
00965
00966 void makeValid() {
00967 m_line = kMax( 0, kMin( int( m_vi->m_doc->numLines() - 1 ), line() ) );
00968 if (m_vi->m_view->wrapCursor())
00969 m_col = kMax( 0, kMin( m_vi->m_doc->lineLength( line() ), col() ) );
00970 else
00971 m_col = kMax( 0, col() );
00972 Q_ASSERT( valid() );
00973 }
00974
00975 void toEdge( Bias bias ) {
00976 if( bias == left ) m_col = 0;
00977 else if( bias == right ) m_col = m_vi->m_doc->lineLength( line() );
00978 }
00979
00980 bool atEdge() const { return atEdge( left ) || atEdge( right ); }
00981
00982 bool atEdge( Bias bias ) const {
00983 switch( bias ) {
00984 case left: return col() == 0;
00985 case none: return atEdge();
00986 case right: return col() == m_vi->m_doc->lineLength( line() );
00987 default: Q_ASSERT(false); return false;
00988 }
00989 }
00990
00991 protected:
00992 bool valid() const {
00993 return line() >= 0 &&
00994 uint( line() ) < m_vi->m_doc->numLines() &&
00995 col() >= 0 &&
00996 (!m_vi->m_view->wrapCursor() || col() <= m_vi->m_doc->lineLength( line() ));
00997 }
00998 KateViewInternal* m_vi;
00999 };
01000
01001 class BoundedCursor : public CalculatingCursor {
01002 public:
01003 BoundedCursor(KateViewInternal* vi)
01004 : CalculatingCursor( vi ) {};
01005 BoundedCursor(KateViewInternal* vi, const KateTextCursor& c )
01006 : CalculatingCursor( vi, c ) {};
01007 BoundedCursor(KateViewInternal* vi, uint line, uint col )
01008 : CalculatingCursor( vi, line, col ) {};
01009 virtual CalculatingCursor& operator+=( int n ) {
01010 m_col += n;
01011
01012 if (n > 0 && m_vi->m_view->dynWordWrap()) {
01013
01014 if (m_col > m_vi->m_doc->lineLength(m_line)) {
01015 KateLineRange currentRange = m_vi->range(*this);
01016
01017 int endX;
01018 bool crap;
01019 m_vi->m_view->renderer()->textWidth(m_vi->textLine(m_line), currentRange.startCol, m_vi->width() - currentRange.xOffset(), &crap, &endX);
01020 endX += (m_col - currentRange.endCol + 1) * m_vi->m_view->renderer()->spaceWidth();
01021
01022
01023 if (endX >= m_vi->width() - currentRange.xOffset()) {
01024 m_col -= n;
01025 if ( uint( line() ) < m_vi->m_doc->numLines() - 1 ) {
01026 m_line++;
01027 m_col = 0;
01028 }
01029 }
01030 }
01031
01032 } else if (n < 0 && col() < 0 && line() > 0 ) {
01033 m_line--;
01034 m_col = m_vi->m_doc->lineLength( line() );
01035 }
01036
01037 m_col = kMax( 0, col() );
01038
01039 Q_ASSERT( valid() );
01040 return *this;
01041 }
01042 virtual CalculatingCursor& operator-=( int n ) {
01043 return operator+=( -n );
01044 }
01045 };
01046
01047 class WrappingCursor : public CalculatingCursor {
01048 public:
01049 WrappingCursor(KateViewInternal* vi)
01050 : CalculatingCursor( vi) {};
01051 WrappingCursor(KateViewInternal* vi, const KateTextCursor& c )
01052 : CalculatingCursor( vi, c ) {};
01053 WrappingCursor(KateViewInternal* vi, uint line, uint col )
01054 : CalculatingCursor( vi, line, col ) {};
01055
01056 virtual CalculatingCursor& operator+=( int n ) {
01057 if( n < 0 ) return operator-=( -n );
01058 int len = m_vi->m_doc->lineLength( line() );
01059 if( col() + n <= len ) {
01060 m_col += n;
01061 } else if( uint( line() ) < m_vi->m_doc->numLines() - 1 ) {
01062 n -= len - col() + 1;
01063 m_col = 0;
01064 m_line++;
01065 operator+=( n );
01066 } else {
01067 m_col = len;
01068 }
01069 Q_ASSERT( valid() );
01070 return *this;
01071 }
01072 virtual CalculatingCursor& operator-=( int n ) {
01073 if( n < 0 ) return operator+=( -n );
01074 if( col() - n >= 0 ) {
01075 m_col -= n;
01076 } else if( line() > 0 ) {
01077 n -= col() + 1;
01078 m_line--;
01079 m_col = m_vi->m_doc->lineLength( line() );
01080 operator-=( n );
01081 } else {
01082 m_col = 0;
01083 }
01084 Q_ASSERT( valid() );
01085 return *this;
01086 }
01087 };
01088
01089 void KateViewInternal::moveChar( Bias bias, bool sel )
01090 {
01091 KateTextCursor c;
01092 if ( m_view->wrapCursor() ) {
01093 c = WrappingCursor( this, cursor ) += bias;
01094 } else {
01095 c = BoundedCursor( this, cursor ) += bias;
01096 }
01097
01098 updateSelection( c, sel );
01099 updateCursor( c );
01100 }
01101
01102 void KateViewInternal::cursorLeft( bool sel )
01103 {
01104 if ( ! m_view->wrapCursor() && cursor.col() == 0 )
01105 return;
01106
01107 moveChar( left, sel );
01108 if (m_view->m_codeCompletion->codeCompletionVisible()) {
01109 m_view->m_codeCompletion->updateBox();
01110 }
01111 }
01112
01113 void KateViewInternal::cursorRight( bool sel )
01114 {
01115 moveChar( right, sel );
01116 if (m_view->m_codeCompletion->codeCompletionVisible()) {
01117 m_view->m_codeCompletion->updateBox();
01118 }
01119 }
01120
01121 void KateViewInternal::wordLeft ( bool sel )
01122 {
01123 WrappingCursor c( this, cursor );
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133 KateHighlighting* h = m_doc->highlight();
01134 if( !c.atEdge( left ) ) {
01135
01136 while( !c.atEdge( left ) && m_doc->textLine( c.line() )[ c.col() - 1 ].isSpace() )
01137 --c;
01138 }
01139 if( c.atEdge( left ) )
01140 {
01141 --c;
01142 }
01143 else if( h->isInWord( m_doc->textLine( c.line() )[ c.col() - 1 ] ) )
01144 {
01145 while( !c.atEdge( left ) && h->isInWord( m_doc->textLine( c.line() )[ c.col() - 1 ] ) )
01146 --c;
01147 }
01148 else
01149 {
01150 while( !c.atEdge( left )
01151 && !h->isInWord( m_doc->textLine( c.line() )[ c.col() - 1 ] )
01152
01153
01154 && !m_doc->textLine( c.line() )[ c.col() - 1 ].isSpace() )
01155 {
01156 --c;
01157 }
01158 }
01159
01160 updateSelection( c, sel );
01161 updateCursor( c );
01162 }
01163
01164 void KateViewInternal::wordRight( bool sel )
01165 {
01166 WrappingCursor c( this, cursor );
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 KateHighlighting* h = m_doc->highlight();
01177 if( c.atEdge( right ) )
01178 {
01179 ++c;
01180 }
01181 else if( h->isInWord( m_doc->textLine( c.line() )[ c.col() ] ) )
01182 {
01183 while( !c.atEdge( right ) && h->isInWord( m_doc->textLine( c.line() )[ c.col() ] ) )
01184 ++c;
01185 }
01186 else
01187 {
01188 while( !c.atEdge( right )
01189 && !h->isInWord( m_doc->textLine( c.line() )[ c.col() ] )
01190
01191
01192 && !m_doc->textLine( c.line() )[ c.col() ].isSpace() )
01193 {
01194 ++c;
01195 }
01196 }
01197
01198 while( !c.atEdge( right ) && m_doc->textLine( c.line() )[ c.col() ].isSpace() )
01199 ++c;
01200
01201 updateSelection( c, sel );
01202 updateCursor( c );
01203 }
01204
01205 void KateViewInternal::moveEdge( Bias bias, bool sel )
01206 {
01207 BoundedCursor c( this, cursor );
01208 c.toEdge( bias );
01209 updateSelection( c, sel );
01210 updateCursor( c );
01211 }
01212
01213 void KateViewInternal::home( bool sel )
01214 {
01215 if (m_view->m_codeCompletion->codeCompletionVisible()) {
01216 QKeyEvent e(QEvent::KeyPress, Qt::Key_Home, 0, 0);
01217 m_view->m_codeCompletion->handleKey(&e);
01218 return;
01219 }
01220
01221 if (m_view->dynWordWrap() && currentRange().startCol) {
01222
01223 if (cursor.col() != currentRange().startCol) {
01224 KateTextCursor c(cursor.line(), currentRange().startCol);
01225 updateSelection( c, sel );
01226 updateCursor( c );
01227 return;
01228 }
01229 }
01230
01231 if( !(m_doc->configFlags() & KateDocument::cfSmartHome) ) {
01232 moveEdge( left, sel );
01233 return;
01234 }
01235
01236 KateTextLine::Ptr l = textLine( cursor.line() );
01237
01238 if (!l)
01239 return;
01240
01241 KateTextCursor c = cursor;
01242 int lc = l->firstChar();
01243
01244 if( lc < 0 || c.col() == lc ) {
01245 c.setCol(0);
01246 } else {
01247 c.setCol(lc);
01248 }
01249
01250 updateSelection( c, sel );
01251 updateCursor( c, true );
01252 }
01253
01254 void KateViewInternal::end( bool sel )
01255 {
01256 if (m_view->m_codeCompletion->codeCompletionVisible()) {
01257 QKeyEvent e(QEvent::KeyPress, Qt::Key_End, 0, 0);
01258 m_view->m_codeCompletion->handleKey(&e);
01259 return;
01260 }
01261
01262
01263
01264 bool alreadyAtEndOfLine = false;
01265
01266 if (m_view->dynWordWrap() && currentRange().wrap) {
01267
01268 if (cursor.col() < currentRange().endCol - 1) {
01269 KateTextCursor c(cursor.line(), currentRange().endCol - 1);
01270 updateSelection( c, sel );
01271 updateCursor( c );
01272 return;
01273 }
01274 alreadyAtEndOfLine = true;
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 int lc = l->lastChar();
01290
01291
01292 int endOfLine = currentRange().endCol - (m_view->dynWordWrap() ? 1 : 0);
01293
01294 if (lc < 0 || c.col() == (lc + 1)) {
01295 if (alreadyAtEndOfLine) {
01296 moveEdge(right, sel);
01297 return;
01298 }
01299 c.setCol(endOfLine);
01300 } else {
01301 c.setCol(lc + 1);
01302 }
01303
01304 updateSelection( c, sel );
01305 updateCursor( c, true );
01306 }
01307
01308 KateLineRange KateViewInternal::range(int realLine, const KateLineRange* previous)
01309 {
01310
01311 if (!m_updatingView && realLine >= lineRanges[0].line && realLine <= lineRanges[lineRanges.count() - 1].line)
01312 for (uint i = 0; i < lineRanges.count(); i++)
01313 if (realLine == lineRanges[i].line)
01314 if (!m_view->dynWordWrap() || (!previous && lineRanges[i].startCol == 0) || (previous && lineRanges[i].startCol == previous->endCol))
01315 return lineRanges[i];
01316
01317
01318 KateLineRange ret;
01319
01320 KateTextLine::Ptr text = textLine(realLine);
01321 if (!text) {
01322 return KateLineRange();
01323 }
01324
01325 if (!m_view->dynWordWrap()) {
01326 Q_ASSERT(!previous);
01327 ret.line = realLine;
01328 ret.virtualLine = m_doc->getVirtualLine(realLine);
01329 ret.startCol = 0;
01330 ret.endCol = m_doc->lineLength(realLine);
01331 ret.startX = 0;
01332 ret.endX = m_view->renderer()->textWidth(text, -1);
01333 ret.viewLine = 0;
01334 ret.wrap = false;
01335 return ret;
01336 }
01337
01338 ret.endCol = (int)m_view->renderer()->textWidth(text, previous ? previous->endCol : 0, width() - (previous ? previous->shiftX : 0), &ret.wrap, &ret.endX);
01339
01340 Q_ASSERT(ret.endCol > ret.startCol);
01341
01342 ret.line = realLine;
01343
01344 if (previous) {
01345 ret.virtualLine = previous->virtualLine;
01346 ret.startCol = previous->endCol;
01347 ret.startX = previous->endX;
01348 ret.endX += previous->endX;
01349 ret.shiftX = previous->shiftX;
01350 ret.viewLine = previous->viewLine + 1;
01351
01352 } else {
01353
01354 if (m_view->config()->dynWordWrapAlignIndent() > 0) {
01355 int pos = text->nextNonSpaceChar(0);
01356
01357 if (pos > 0)
01358 ret.shiftX = m_view->renderer()->textWidth(text, pos);
01359
01360 if (ret.shiftX > ((double)width() / 100 * m_view->config()->dynWordWrapAlignIndent()))
01361 ret.shiftX = 0;
01362 }
01363
01364 ret.virtualLine = m_doc->getVirtualLine(realLine);
01365 ret.startCol = 0;
01366 ret.startX = 0;
01367 ret.viewLine = 0;
01368 }
01369
01370 return ret;
01371 }
01372
01373 KateLineRange KateViewInternal::currentRange()
01374 {
01375
01376
01377 return range(cursor);
01378 }
01379
01380 KateLineRange KateViewInternal::previousRange()
01381 {
01382 uint currentViewLine = viewLine(cursor);
01383
01384 if (currentViewLine)
01385 return range(cursor.line(), currentViewLine - 1);
01386 else
01387 return range(m_doc->getRealLine(displayCursor.line() - 1), -1);
01388 }
01389
01390 KateLineRange KateViewInternal::nextRange()
01391 {
01392 uint currentViewLine = viewLine(cursor) + 1;
01393
01394 if (currentViewLine >= viewLineCount(cursor.line())) {
01395 currentViewLine = 0;
01396 return range(cursor.line() + 1, currentViewLine);
01397 } else {
01398 return range(cursor.line(), currentViewLine);
01399 }
01400 }
01401
01402 KateLineRange KateViewInternal::range(const KateTextCursor& realCursor)
01403 {
01404
01405
01406 KateLineRange thisRange;
01407 bool first = true;
01408
01409 do {
01410 thisRange = range(realCursor.line(), first ? 0L : &thisRange);
01411 first = false;
01412 } while (thisRange.wrap && !(realCursor.col() >= thisRange.startCol && realCursor.col() < thisRange.endCol) && thisRange.startCol != thisRange.endCol);
01413
01414 return thisRange;
01415 }
01416
01417 KateLineRange KateViewInternal::range(uint realLine, int viewLine)
01418 {
01419
01420
01421 KateLineRange thisRange;
01422 bool first = true;
01423
01424 do {
01425 thisRange = range(realLine, first ? 0L : &thisRange);
01426 first = false;
01427 } while (thisRange.wrap && viewLine != thisRange.viewLine && thisRange.startCol != thisRange.endCol);
01428
01429 if (viewLine != -1 && viewLine != thisRange.viewLine)
01430 kdDebug(13030) << "WARNING: viewLine " << viewLine << " of line " << realLine << " does not exist." << endl;
01431
01432 return thisRange;
01433 }
01434
01440 uint KateViewInternal::viewLine(const KateTextCursor& realCursor)
01441 {
01442 if (!m_view->dynWordWrap()) return 0;
01443
01444 if (realCursor.col() == 0) return 0;
01445
01446 KateLineRange thisRange;
01447 bool first = true;
01448
01449 do {
01450 thisRange = range(realCursor.line(), first ? 0L : &thisRange);
01451 first = false;
01452 } while (thisRange.wrap && !(realCursor.col() >= thisRange.startCol && realCursor.col() < thisRange.endCol) && thisRange.startCol != thisRange.endCol);
01453
01454 return thisRange.viewLine;
01455 }
01456
01457 int KateViewInternal::displayViewLine(const KateTextCursor& virtualCursor, bool limitToVisible)
01458 {
01459 KateTextCursor work = startPos();
01460
01461 int limit = linesDisplayed();
01462
01463
01464 if (!m_view->dynWordWrap()) {
01465 int ret = virtualCursor.line() - startLine();
01466 if (limitToVisible && (ret < 0 || ret > limit))
01467 return -1;
01468 else
01469 return ret;
01470 }
01471
01472 if (work == virtualCursor) {
01473 return 0;
01474 }
01475
01476 int ret = -(int)viewLine(work);
01477 bool forwards = (work < virtualCursor) ? true : false;
01478
01479
01480 if (forwards) {
01481 while (work.line() != virtualCursor.line()) {
01482 ret += viewLineCount(m_doc->getRealLine(work.line()));
01483 work.setLine(work.line() + 1);
01484 if (limitToVisible && ret > limit)
01485 return -1;
01486 }
01487 } else {
01488 while (work.line() != virtualCursor.line()) {
01489 work.setLine(work.line() - 1);
01490 ret -= viewLineCount(m_doc->getRealLine(work.line()));
01491 if (limitToVisible && ret < 0)
01492 return -1;
01493 }
01494 }
01495
01496
01497 KateTextCursor realCursor = virtualCursor;
01498 realCursor.setLine(m_doc->getRealLine(realCursor.line()));
01499 if (realCursor.col() == -1) realCursor.setCol(m_doc->lineLength(realCursor.line()));
01500 ret += viewLine(realCursor);
01501
01502 if (limitToVisible && (ret < 0 || ret > limit))
01503 return -1;
01504
01505 return ret;
01506 }
01507
01508 uint KateViewInternal::lastViewLine(uint realLine)
01509 {
01510 if (!m_view->dynWordWrap()) return 0;
01511
01512 KateLineRange thisRange;
01513 bool first = true;
01514
01515 do {
01516 thisRange = range(realLine, first ? 0L : &thisRange);
01517 first = false;
01518 } while (thisRange.wrap && thisRange.startCol != thisRange.endCol);
01519
01520 return thisRange.viewLine;
01521 }
01522
01523 uint KateViewInternal::viewLineCount(uint realLine)
01524 {
01525 return lastViewLine(realLine) + 1;
01526 }
01527
01528
01529
01530
01531
01532
01533
01534
01535 KateTextCursor KateViewInternal::viewLineOffset(const KateTextCursor& virtualCursor, int offset, bool keepX)
01536 {
01537 if (!m_view->dynWordWrap()) {
01538 KateTextCursor ret(kMin((int)m_doc->visibleLines() - 1, virtualCursor.line() + offset), 0);
01539
01540 if (ret.line() < 0)
01541 ret.setLine(0);
01542
01543 if (keepX) {
01544 int realLine = m_doc->getRealLine(ret.line());
01545 ret.setCol(m_doc->lineLength(realLine) - 1);
01546
01547 if (m_currentMaxX > cXPos)
01548 cXPos = m_currentMaxX;
01549
01550 if (m_view->wrapCursor())
01551 cXPos = kMin(cXPos, (int)m_view->renderer()->textWidth(textLine(realLine), m_doc->lineLength(realLine)));
01552
01553 m_view->renderer()->textWidth(ret, cXPos);
01554 }
01555
01556 return ret;
01557 }
01558
01559 KateTextCursor realCursor = virtualCursor;
01560 realCursor.setLine(m_doc->getRealLine(virtualCursor.line()));
01561
01562 uint cursorViewLine = viewLine(realCursor);
01563
01564 int currentOffset = 0;
01565 int virtualLine = 0;
01566
01567 bool forwards = (offset > 0) ? true : false;
01568
01569 if (forwards) {
01570 currentOffset = lastViewLine(realCursor.line()) - cursorViewLine;
01571 if (offset <= currentOffset) {
01572
01573 KateLineRange thisRange = range(realCursor.line(), cursorViewLine + offset);
01574 Q_ASSERT(thisRange.virtualLine == virtualCursor.line());
01575 return KateTextCursor(virtualCursor.line(), thisRange.startCol);
01576 }
01577
01578 virtualLine = virtualCursor.line() + 1;
01579
01580 } else {
01581 offset = -offset;
01582 currentOffset = cursorViewLine;
01583 if (offset <= currentOffset) {
01584
01585 KateLineRange thisRange = range(realCursor.line(), cursorViewLine - offset);
01586 Q_ASSERT(thisRange.virtualLine == virtualCursor.line());
01587 return KateTextCursor(virtualCursor.line(), thisRange.startCol);
01588 }
01589
01590 virtualLine = virtualCursor.line() - 1;
01591 }
01592
01593 currentOffset++;
01594
01595 while (virtualLine >= 0 && virtualLine < (int)m_doc->visibleLines())
01596 {
01597 KateLineRange thisRange;
01598 bool first = true;
01599 int realLine = m_doc->getRealLine(virtualLine);
01600
01601 do {
01602 thisRange = range(realLine, first ? 0L : &thisRange);
01603 first = false;
01604
01605 if (offset == currentOffset) {
01606 if (!forwards) {
01607
01608 int requiredViewLine = lastViewLine(realLine) - thisRange.viewLine;
01609 if (requiredViewLine != thisRange.viewLine) {
01610 thisRange = range(realLine, requiredViewLine);
01611 }
01612 }
01613
01614 KateTextCursor ret(virtualLine, thisRange.startCol);
01615
01616
01617 if (keepX) {
01618 ret.setCol(thisRange.endCol - 1);
01619 KateTextCursor realCursorTemp(m_doc->getRealLine(virtualCursor.line()), virtualCursor.col());
01620 int visibleX = m_view->renderer()->textWidth(realCursorTemp) - range(realCursorTemp).startX;
01621 int xOffset = thisRange.startX;
01622
01623 if (m_currentMaxX > visibleX)
01624 visibleX = m_currentMaxX;
01625
01626 cXPos = xOffset + visibleX;
01627
01628 cXPos = kMin(cXPos, lineMaxCursorX(thisRange));
01629
01630 m_view->renderer()->textWidth(ret, cXPos);
01631 }
01632
01633 return ret;
01634 }
01635
01636 currentOffset++;
01637
01638 } while (thisRange.wrap);
01639
01640 if (forwards)
01641 virtualLine++;
01642 else
01643 virtualLine--;
01644 }
01645
01646
01647
01648 if (forwards)
01649 return KateTextCursor(m_doc->visibleLines() - 1, m_doc->lineLength(m_doc->visibleLines() - 1));
01650 else
01651 return KateTextCursor(0, 0);
01652 }
01653
01654 int KateViewInternal::lineMaxCursorX(const KateLineRange& range)
01655 {
01656 if (!m_view->wrapCursor() && !range.wrap)
01657 return INT_MAX;
01658
01659 int maxX = range.endX;
01660
01661 if (maxX && range.wrap) {
01662 QChar lastCharInLine = textLine(range.line)->getChar(range.endCol - 1);
01663 maxX -= m_view->renderer()->config()->fontMetrics()->width(lastCharInLine);
01664 }
01665
01666 return maxX;
01667 }
01668
01669 int KateViewInternal::lineMaxCol(const KateLineRange& range)
01670 {
01671 int maxCol = range.endCol;
01672
01673 if (maxCol && range.wrap)
01674 maxCol--;
01675
01676 return maxCol;
01677 }
01678
01679 void KateViewInternal::cursorUp(bool sel)
01680 {
01681 if (m_view->m_codeCompletion->codeCompletionVisible()) {
01682 QKeyEvent e(QEvent::KeyPress, Qt::Key_Up, 0, 0);
01683 m_view->m_codeCompletion->handleKey(&e);
01684 return;
01685 }
01686
01687 if (displayCursor.line() == 0 && (!m_view->dynWordWrap() || viewLine(cursor) == 0))
01688 return;
01689
01690 int newLine = cursor.line(), newCol = 0, xOffset = 0, startCol = 0;
01691 m_preserveMaxX = true;
01692
01693 if (m_view->dynWordWrap()) {
01694
01695 KateLineRange thisRange = currentRange();
01696
01697 KateLineRange pRange = previousRange();
01698
01699
01700 Q_ASSERT((cursor.line() == thisRange.line) &&
01701 (cursor.col() >= thisRange.startCol) &&
01702 (!thisRange.wrap || cursor.col() < thisRange.endCol));
01703
01704
01705 int visibleX = m_view->renderer()->textWidth(cursor) - thisRange.startX;
01706 int currentLineVisibleX = visibleX;
01707
01708
01709 visibleX += thisRange.xOffset();
01710 visibleX -= pRange.xOffset();
01711
01712
01713 visibleX = kMax(0, visibleX);
01714
01715 startCol = pRange.startCol;
01716 xOffset = pRange.startX;
01717 newLine = pRange.line;
01718
01719
01720
01721 if (thisRange.xOffset() && !pRange.xOffset() && currentLineVisibleX == 0)
01722 visibleX = m_currentMaxX;
01723 else if (visibleX < m_currentMaxX - pRange.xOffset())
01724 visibleX = m_currentMaxX - pRange.xOffset();
01725
01726 cXPos = xOffset + visibleX;
01727
01728 cXPos = kMin(cXPos, lineMaxCursorX(pRange));
01729
01730 newCol = kMin((int)m_view->renderer()->textPos(newLine, visibleX, startCol), lineMaxCol(pRange));
01731
01732 } else {
01733 newLine = m_doc->getRealLine(displayCursor.line() - 1);
01734
01735 if ((m_view->wrapCursor()) && m_currentMaxX > cXPos)
01736 cXPos = m_currentMaxX;
01737 }
01738
01739 KateTextCursor c(newLine, newCol);
01740 m_view->renderer()->textWidth(c, cXPos);
01741
01742 updateSelection( c, sel );
01743 updateCursor( c );
01744 }
01745
01746 void KateViewInternal::cursorDown(bool sel)
01747 {
01748 if (m_view->m_codeCompletion->codeCompletionVisible()) {
01749 QKeyEvent e(QEvent::KeyPress, Qt::Key_Down, 0, 0);
01750 m_view->m_codeCompletion->handleKey(&e);
01751 return;
01752 }
01753
01754 if ((displayCursor.line() >= (int)m_doc->numVisLines() - 1) && (!m_view->dynWordWrap() || viewLine(cursor) == lastViewLine(cursor.line())))
01755 return;
01756
01757 int newLine = cursor.line(), newCol = 0, xOffset = 0, startCol = 0;
01758 m_preserveMaxX = true;
01759
01760 if (m_view->dynWordWrap()) {
01761
01762 KateLineRange thisRange = currentRange();
01763
01764 KateLineRange nRange = nextRange();
01765
01766
01767 Q_ASSERT((cursor.line() == thisRange.line) &&
01768 (cursor.col() >= thisRange.startCol) &&
01769 (!thisRange.wrap || cursor.col() < thisRange.endCol));
01770
01771
01772 int visibleX = m_view->renderer()->textWidth(cursor) - thisRange.startX;
01773 int currentLineVisibleX = visibleX;
01774
01775
01776 visibleX += thisRange.xOffset();
01777 visibleX -= nRange.xOffset();
01778
01779
01780 visibleX = kMax(0, visibleX);
01781
01782 if (!thisRange.wrap) {
01783 newLine = m_doc->getRealLine(displayCursor.line() + 1);
01784 } else {
01785 startCol = thisRange.endCol;
01786 xOffset = thisRange.endX;
01787 }
01788
01789
01790
01791 if (thisRange.xOffset() && !nRange.xOffset() && currentLineVisibleX == 0)
01792 visibleX = m_currentMaxX;
01793 else if (visibleX < m_currentMaxX - nRange.xOffset())
01794 visibleX = m_currentMaxX - nRange.xOffset();
01795
01796 cXPos = xOffset + visibleX;
01797
01798 cXPos = kMin(cXPos, lineMaxCursorX(nRange));
01799
01800 newCol = kMin((int)m_view->renderer()->textPos(newLine, visibleX, startCol), lineMaxCol(nRange));
01801
01802 } else {
01803 newLine = m_doc->getRealLine(displayCursor.line() + 1);
01804
01805 if ((m_view->wrapCursor()) && m_currentMaxX > cXPos)
01806 cXPos = m_currentMaxX;
01807 }
01808
01809 KateTextCursor c(newLine, newCol);
01810 m_view->renderer()->textWidth(c, cXPos);
01811
01812 updateSelection(c, sel);
01813 updateCursor(c);
01814 }
01815
01816 void KateViewInternal::cursorToMatchingBracket( bool sel )
01817 {
01818 KateTextCursor start( cursor ), end;
01819
01820 if( !m_doc->findMatchingBracket( start, end ) )
01821 return;
01822
01823
01824
01825
01826 if( end > start )
01827 end.setCol(end.col() + 1);
01828
01829 updateSelection( end, sel );
01830 updateCursor( end );
01831 }
01832
01833 void KateViewInternal::topOfView( bool sel )
01834 {
01835 KateTextCursor c = viewLineOffset(startPos(), m_minLinesVisible);
01836 updateSelection( c, sel );
01837 updateCursor( c );
01838 }
01839
01840 void KateViewInternal::bottomOfView( bool sel )
01841 {
01842
01843 KateTextCursor c = viewLineOffset(endPos(), -m_minLinesVisible);
01844 updateSelection( c, sel );
01845 updateCursor( c );
01846 }
01847
01848
01849 void KateViewInternal::scrollLines( int lines, bool sel )
01850 {
01851 KateTextCursor c = viewLineOffset(displayCursor, lines, true);
01852
01853
01854 c.setLine(m_doc->getRealLine(c.line()));
01855
01856 updateSelection( c, sel );
01857 updateCursor( c );
01858 }
01859
01860
01861 void KateViewInternal::scrollUp()
01862 {
01863 KateTextCursor newPos = viewLineOffset(m_startPos, -1);
01864 scrollPos(newPos);
01865 }
01866
01867 void KateViewInternal::scrollDown()
01868 {
01869 KateTextCursor newPos = viewLineOffset(m_startPos, 1);
01870 scrollPos(newPos);
01871 }
01872
01873 void KateViewInternal::setAutoCenterLines(int viewLines, bool updateView)
01874 {
01875 m_autoCenterLines = viewLines;
01876 m_minLinesVisible = kMin(int((linesDisplayed() - 1)/2), m_autoCenterLines);
01877 if (updateView)
01878 KateViewInternal::updateView();
01879 }
01880
01881 void KateViewInternal::pageUp( bool sel )
01882 {
01883 if (m_view->m_codeCompletion->codeCompletionVisible()) {
01884 QKeyEvent e(QEvent::KeyPress, Qt::Key_PageUp, 0, 0);
01885 m_view->m_codeCompletion->handleKey(&e);
01886 return;
01887 }
01888
01889
01890 int viewLine = displayViewLine(displayCursor);
01891 bool atTop = (startPos().line() == 0 && startPos().col() == 0);
01892
01893
01894 int lineadj = 2 * m_minLinesVisible;
01895 int cursorStart = (linesDisplayed() - 1) - viewLine;
01896 if (cursorStart < m_minLinesVisible)
01897 lineadj -= m_minLinesVisible - cursorStart;
01898
01899 int linesToScroll = -kMax( ((int)linesDisplayed() - 1) - lineadj, 0 );
01900 m_preserveMaxX = true;
01901
01902 if (!m_doc->pageUpDownMovesCursor () && !atTop) {
01903 int xPos = m_view->renderer()->textWidth(cursor) - currentRange().startX;
01904
01905 KateTextCursor newStartPos = viewLineOffset(startPos(), linesToScroll - 1);
01906 scrollPos(newStartPos);
01907
01908
01909 KateTextCursor newPos = viewLineOffset(newStartPos, viewLine, true);
01910 newPos.setLine(m_doc->getRealLine(newPos.line()));
01911
01912 KateLineRange newLine = range(newPos);
01913
01914 if (m_currentMaxX - newLine.xOffset() > xPos)
01915 xPos = m_currentMaxX - newLine.xOffset();
01916
01917 cXPos = kMin(newLine.startX + xPos, lineMaxCursorX(newLine));
01918
01919 m_view->renderer()->textWidth( newPos, cXPos );
01920
01921 m_preserveMaxX = true;
01922 updateSelection( newPos, sel );
01923 updateCursor(newPos);
01924
01925 } else {
01926 scrollLines( linesToScroll, sel );
01927 }
01928 }
01929
01930 void KateViewInternal::pageDown( bool sel )
01931 {
01932 if (m_view->m_codeCompletion->codeCompletionVisible()) {
01933 QKeyEvent e(QEvent::KeyPress, Qt::Key_PageDown, 0, 0);
01934 m_view->m_codeCompletion->handleKey(&e);
01935 return;
01936 }
01937
01938
01939 int viewLine = displayViewLine(displayCursor);
01940 bool atEnd = startPos() >= m_cachedMaxStartPos;
01941
01942
01943 int lineadj = 2 * m_minLinesVisible;
01944 int cursorStart = m_minLinesVisible - viewLine;
01945 if (cursorStart > 0)
01946 lineadj -= cursorStart;
01947
01948 int linesToScroll = kMax( ((int)linesDisplayed() - 1) - lineadj, 0 );
01949 m_preserveMaxX = true;
01950
01951 if (!m_doc->pageUpDownMovesCursor () && !atEnd) {
01952 int xPos = m_view->renderer()->textWidth(cursor) - currentRange().startX;
01953
01954 KateTextCursor newStartPos = viewLineOffset(startPos(), linesToScroll + 1);
01955 scrollPos(newStartPos);
01956
01957
01958 KateTextCursor newPos = viewLineOffset(newStartPos, viewLine, true);
01959 newPos.setLine(m_doc->getRealLine(newPos.line()));
01960
01961 KateLineRange newLine = range(newPos);
01962
01963 if (m_currentMaxX - newLine.xOffset() > xPos)
01964 xPos = m_currentMaxX - newLine.xOffset();
01965
01966 cXPos = kMin(newLine.startX + xPos, lineMaxCursorX(newLine));
01967
01968 m_view->renderer()->textWidth( newPos, cXPos );
01969
01970 m_preserveMaxX = true;
01971 updateSelection( newPos, sel );
01972 updateCursor(newPos);
01973
01974 } else {
01975 scrollLines( linesToScroll, sel );
01976 }
01977 }
01978
01979 int KateViewInternal::maxLen(uint startLine)
01980 {
01981
01982
01983 int displayLines = (m_view->height() / m_view->renderer()->fontHeight()) + 1;
01984
01985 int maxLen = 0;
01986
01987 for (int z = 0; z < displayLines; z++) {
01988 int virtualLine = startLine + z;
01989
01990 if (virtualLine < 0 || virtualLine >= (int)m_doc->visibleLines())
01991 break;
01992
01993 KateLineRange thisRange = range((int)m_doc->getRealLine(virtualLine));
01994
01995 maxLen = kMax(maxLen, thisRange.endX);
01996 }
01997
01998 return maxLen;
01999 }
02000
02001 void KateViewInternal::top( bool sel )
02002 {
02003 KateTextCursor c( 0, cursor.col() );
02004 m_view->renderer()->textWidth( c, cXPos );
02005 updateSelection( c, sel );
02006 updateCursor( c );
02007 }
02008
02009 void KateViewInternal::bottom( bool sel )
02010 {
02011 KateTextCursor c( m_doc->lastLine(), cursor.col() );
02012 m_view->renderer()->textWidth( c, cXPos );
02013 updateSelection( c, sel );
02014 updateCursor( c );
02015 }
02016
02017 void KateViewInternal::top_home( bool sel )
02018 {
02019 if (m_view->m_codeCompletion->codeCompletionVisible()) {
02020 QKeyEvent e(QEvent::KeyPress, Qt::Key_Home, 0, 0);
02021 m_view->m_codeCompletion->handleKey(&e);
02022 return;
02023 }
02024 KateTextCursor c( 0, 0 );
02025 updateSelection( c, sel );
02026 updateCursor( c );
02027 }
02028
02029 void KateViewInternal::bottom_end( bool sel )
02030 {
02031 if (m_view->m_codeCompletion->codeCompletionVisible()) {
02032 QKeyEvent e(QEvent::KeyPress, Qt::Key_End, 0, 0);
02033 m_view->m_codeCompletion->handleKey(&e);
02034 return;
02035 }
02036 KateTextCursor c( m_doc->lastLine(), m_doc->lineLength( m_doc->lastLine() ) );
02037 updateSelection( c, sel );
02038 updateCursor( c );
02039 }
02040
02041 void KateViewInternal::updateSelection( const KateTextCursor& _newCursor, bool keepSel )
02042 {
02043 KateTextCursor newCursor = _newCursor;
02044 if( keepSel )
02045 {
02046 if ( !m_view->hasSelection() || (selectAnchor.line() == -1)
02047 || (m_view->config()->persistentSelection()
02048 && ((cursor < m_view->selectStart) || (cursor > m_view->selectEnd))) )
02049 {
02050 selectAnchor = cursor;
02051 m_view->setSelection( cursor, newCursor );
02052 }
02053 else
02054 {
02055 bool doSelect = true;
02056 switch (m_selectionMode)
02057 {
02058 case Word:
02059 {
02060 bool same = ( newCursor.line() == selStartCached.line() );
02061 uint c;
02062 if ( newCursor.line() > selStartCached.line() ||
02063 ( same && newCursor.col() > selEndCached.col() ) )
02064 {
02065 selectAnchor = selStartCached;
02066
02067 KateTextLine::Ptr l = m_doc->kateTextLine( newCursor.line() );
02068
02069 for ( c = newCursor.col(); c < l->length(); c++ )
02070 if ( !m_doc->highlight()->isInWord( l->getChar( c ) ) )
02071 break;
02072
02073 newCursor.setCol( c );
02074 }
02075 else if ( newCursor.line() < selStartCached.line() ||
02076 ( same && newCursor.col() < selStartCached.col() ) )
02077 {
02078 selectAnchor = selEndCached;
02079
02080 KateTextLine::Ptr l = m_doc->kateTextLine( newCursor.line() );
02081
02082 for ( c = newCursor.col(); c > 0; c-- )
02083 if ( !m_doc->highlight()->isInWord( l->getChar( c ) ) )
02084 break;
02085
02086 newCursor.setCol( c+1 );
02087 }
02088 else
02089 doSelect = false;
02090
02091 }
02092 break;
02093 case Line:
02094 if ( newCursor.line() > selStartCached.line() )
02095 {
02096 selectAnchor = selStartCached;
02097 newCursor.setCol( m_doc->textLine( newCursor.line() ).length() );
02098 }
02099 else if ( newCursor.line() < selStartCached.line() )
02100 {
02101 selectAnchor = selEndCached;
02102 newCursor.setCol( 0 );
02103 }
02104 else
02105 doSelect = false;
02106 break;
02107 default:
02108 {
02109 if ( selStartCached.line() < 0 )
02110 break;
02111
02112 if ( newCursor.line() > selEndCached.line() ||
02113 ( newCursor.line() == selEndCached.line() &&
02114 newCursor.col() > selEndCached.col() ) )
02115 selectAnchor = selStartCached;
02116
02117 else if ( newCursor.line() < selStartCached.line() ||
02118 ( newCursor.line() == selStartCached.line() &&
02119 newCursor.col() < selStartCached.col() ) )
02120 selectAnchor = selEndCached;
02121
02122 else
02123 doSelect = false;
02124 }
02125
02126 }
02127
02128 if ( doSelect )
02129 m_view->setSelection( selectAnchor, newCursor);
02130 else if ( selStartCached.line() > 0 )
02131 m_view->setSelection( selStartCached, selEndCached );
02132 }
02133
02134 m_selChangedByUser = true;
02135 }
02136 else if ( !m_view->config()->persistentSelection() )
02137 {
02138 m_view->clearSelection();
02139 selStartCached.setLine( -1 );
02140 selectAnchor.setLine( -1 );
02141 }
02142 }
02143
02144 void KateViewInternal::updateCursor( const KateTextCursor& newCursor, bool force, bool center, bool calledExternally )
02145 {
02146 if ( !force && (cursor == newCursor) )
02147 {
02148 if ( !m_madeVisible )
02149 {
02150
02151 m_doc->foldingTree()->ensureVisible( newCursor.line() );
02152
02153 makeVisible ( displayCursor, displayCursor.col(), false, center, calledExternally );
02154 }
02155
02156 return;
02157 }
02158
02159
02160 m_doc->foldingTree()->ensureVisible( newCursor.line() );
02161
02162 KateTextCursor oldDisplayCursor = displayCursor;
02163
02164 cursor.setPos (newCursor);
02165 displayCursor.setPos (m_doc->getVirtualLine(cursor.line()), cursor.col());
02166
02167 cXPos = m_view->renderer()->textWidth( cursor );
02168 makeVisible ( displayCursor, displayCursor.col(), false, center, calledExternally );
02169
02170 updateBracketMarks();
02171
02172
02173 tagLine(oldDisplayCursor);
02174 tagLine(displayCursor);
02175
02176 updateMicroFocusHint();
02177
02178 if (m_cursorTimer.isActive ())
02179 {
02180 if ( KApplication::cursorFlashTime() > 0 )
02181 m_cursorTimer.start( KApplication::cursorFlashTime() / 2 );
02182 m_view->renderer()->setDrawCaret(true);
02183 }
02184
02185
02186 if (m_preserveMaxX)
02187 m_preserveMaxX = false;
02188 else
02189 if (m_view->dynWordWrap())
02190 m_currentMaxX = m_view->renderer()->textWidth(displayCursor) - currentRange().startX + currentRange().xOffset();
02191 else
02192 m_currentMaxX = cXPos;
02193
02194
02195
02196
02197 paintText(0, 0, width(), height(), true);
02198
02199 emit m_view->cursorPositionChanged();
02200 }
02201
02202 void KateViewInternal::updateBracketMarks()
02203 {
02204 if ( bm.isValid() ) {
02205 KateTextCursor bmStart(m_doc->getVirtualLine(bm.start().line()), bm.start().col());
02206 KateTextCursor bmEnd(m_doc->getVirtualLine(bm.end().line()), bm.end().col());
02207
02208 if( bm.getMinIndent() != 0 )
02209 {
02210
02211 if( bmStart > bmEnd )
02212 {
02213 tagLines(bmEnd, bmStart, true);
02214 }
02215 else
02216 {
02217 tagLines(bmStart, bmEnd, true);
02218 }
02219 }
02220 else
02221 {
02222 tagLine(bmStart);
02223 tagLine(bmEnd);
02224 }
02225 }
02226
02227
02228 int maxLines = linesDisplayed () * 3;
02229 m_doc->newBracketMark( cursor, bm, maxLines );
02230
02231 if ( bm.isValid() ) {
02232 KateTextCursor bmStart(m_doc->getVirtualLine(bm.start().line()), bm.start().col());
02233 KateTextCursor bmEnd(m_doc->getVirtualLine(bm.end().line()), bm.end().col());
02234
02235 if( bm.getMinIndent() != 0 )
02236 {
02237
02238 if( bmStart > bmEnd )
02239 {
02240 tagLines(bmEnd, bmStart, true);
02241 }
02242 else
02243 {
02244 tagLines(bmStart, bmEnd, true);
02245 }
02246 }
02247 else
02248 {
02249 tagLine(bmStart);
02250 tagLine(bmEnd);
02251 }
02252 }
02253 }
02254
02255 bool KateViewInternal::tagLine(const KateTextCursor& virtualCursor)
02256 {
02257 int viewLine = displayViewLine(virtualCursor, true);
02258 if (viewLine >= 0 && viewLine < (int)lineRanges.count()) {
02259 lineRanges[viewLine].dirty = true;
02260 leftBorder->update (0, lineToY(viewLine), leftBorder->width(), m_view->renderer()->fontHeight());
02261 return true;
02262 }
02263 return false;
02264 }
02265
02266 bool KateViewInternal::tagLines( int start, int end, bool realLines )
02267 {
02268 return tagLines(KateTextCursor(start, 0), KateTextCursor(end, -1), realLines);
02269 }
02270
02271 bool KateViewInternal::tagLines(KateTextCursor start, KateTextCursor end, bool realCursors)
02272 {
02273 if (realCursors)
02274 {
02275
02276 start.setLine(m_doc->getVirtualLine( start.line() ));
02277 end.setLine(m_doc->getVirtualLine( end.line() ));
02278 }
02279
02280 if (end.line() < (int)startLine())
02281 {
02282
02283 return false;
02284 }
02285 if (start.line() > (int)endLine())
02286 {
02287
02288 return false;
02289 }
02290
02291
02292
02293 bool ret = false;
02294
02295 for (uint z = 0; z < lineRanges.size(); z++)
02296 {
02297 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)))) {
02298 ret = lineRanges[z].dirty = true;
02299
02300 }
02301 }
02302
02303 if (!m_view->dynWordWrap())
02304 {
02305 int y = lineToY( start.line() );
02306
02307 int h = (end.line() - start.line() + 2) * m_view->renderer()->fontHeight();
02308 if (end.line() == (int)m_doc->numVisLines() - 1)
02309 h = height();
02310
02311 leftBorder->update (0, y, leftBorder->width(), h);
02312 }
02313 else
02314 {
02315
02316
02317 for (uint z = 0; z < lineRanges.size(); z++)
02318 {
02319 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))))
02320 {
02321
02322 leftBorder->update (0, z * m_view->renderer()->fontHeight(), leftBorder->width(), leftBorder->height());
02323 break;
02324 }
02325
02326
02327
02328
02329
02330
02331 }
02332 }
02333
02334 return ret;
02335 }
02336
02337 void KateViewInternal::tagAll()
02338 {
02339
02340 for (uint z = 0; z < lineRanges.size(); z++)
02341 {
02342 lineRanges[z].dirty = true;
02343 }
02344
02345 leftBorder->updateFont();
02346 leftBorder->update ();
02347 }
02348
02349 void KateViewInternal::paintCursor()
02350 {
02351 if (tagLine(displayCursor))
02352 paintText (0,0,width(), height(), true);
02353 }
02354
02355
02356 void KateViewInternal::placeCursor( const QPoint& p, bool keepSelection, bool updateSelection )
02357 {
02358 KateLineRange thisRange = yToKateLineRange(p.y());
02359
02360 if (thisRange.line == -1) {
02361 for (int i = (p.y() / m_view->renderer()->fontHeight()); i >= 0; i--) {
02362 thisRange = lineRanges[i];
02363 if (thisRange.line != -1)
02364 break;
02365 }
02366 Q_ASSERT(thisRange.line != -1);
02367 }
02368
02369 int realLine = thisRange.line;
02370 int visibleLine = thisRange.virtualLine;
02371 uint startCol = thisRange.startCol;
02372
02373 visibleLine = kMax( 0, kMin( visibleLine, int(m_doc->numVisLines()) - 1 ) );
02374
02375 KateTextCursor c(realLine, 0);
02376
02377 int x = kMin(kMax(-m_startX, p.x() - thisRange.xOffset()), lineMaxCursorX(thisRange) - thisRange.startX);
02378
02379 m_view->renderer()->textWidth( c, startX() + x, startCol);
02380
02381 if (updateSelection)
02382 KateViewInternal::updateSelection( c, keepSelection );
02383
02384 updateCursor( c );
02385 }
02386
02387
02388 bool KateViewInternal::isTargetSelected( const QPoint& p )
02389 {
02390 KateLineRange thisRange = yToKateLineRange(p.y());
02391
02392 KateTextLine::Ptr l = textLine( thisRange.line );
02393 if( !l )
02394 return false;
02395
02396 int col = m_view->renderer()->textPos( l, p.x() - thisRange.xOffset(), thisRange.startCol, false );
02397
02398 return m_view->lineColSelected( thisRange.line, col );
02399 }
02400
02401
02402
02403 bool KateViewInternal::eventFilter( QObject *obj, QEvent *e )
02404 {
02405 if (obj == m_lineScroll)
02406 {
02407
02408 if (e->type() == QEvent::Wheel && m_lineScroll->minValue() != m_lineScroll->maxValue())
02409 {
02410 wheelEvent((QWheelEvent*)e);
02411 return true;
02412 }
02413
02414
02415 return QWidget::eventFilter( obj, e );
02416 }
02417
02418 switch( e->type() )
02419 {
02420 case QEvent::KeyPress:
02421 {
02422 QKeyEvent *k = (QKeyEvent *)e;
02423
02424 if (m_view->m_codeCompletion->codeCompletionVisible ())
02425 {
02426 kdDebug (13030) << "hint around" << endl;
02427
02428 if( k->key() == Key_Escape )
02429 m_view->m_codeCompletion->abortCompletion();
02430 }
02431
02432 if ((k->key() == Qt::Key_Escape) && !m_view->config()->persistentSelection() )
02433 {
02434 m_view->clearSelection();
02435 return true;
02436 }
02437 else if ( !((k->state() & ControlButton) || (k->state() & AltButton)) )
02438 {
02439 keyPressEvent( k );
02440 return k->isAccepted();
02441 }
02442
02443 } break;
02444
02445 case QEvent::DragMove:
02446 {
02447 QPoint currentPoint = ((QDragMoveEvent*) e)->pos();
02448
02449 QRect doNotScrollRegion( scrollMargin, scrollMargin,
02450 width() - scrollMargin * 2,
02451 height() - scrollMargin * 2 );
02452
02453 if ( !doNotScrollRegion.contains( currentPoint ) )
02454 {
02455 startDragScroll();
02456
02457 ( (QDragMoveEvent*)e )->accept( QRect(0,0,0,0) );
02458 }
02459
02460 dragMoveEvent((QDragMoveEvent*)e);
02461 } break;
02462
02463 case QEvent::DragLeave:
02464
02465 stopDragScroll();
02466 break;
02467
02468 case QEvent::WindowBlocked:
02469
02470
02471 m_doc->m_isasking = -1;
02472 break;
02473
02474 default:
02475 break;
02476 }
02477
02478 return QWidget::eventFilter( obj, e );
02479 }
02480
02481 void KateViewInternal::keyPressEvent( QKeyEvent* e )
02482 {
02483 KKey key(e);
02484
02485 bool codeComp = m_view->m_codeCompletion->codeCompletionVisible ();
02486
02487 if (codeComp)
02488 {
02489 kdDebug (13030) << "hint around" << endl;
02490
02491 if( e->key() == Key_Enter || e->key() == Key_Return ||
02492 (key == SHIFT + Qt::Key_Return) || (key == SHIFT + Qt::Key_Enter)) {
02493 m_view->m_codeCompletion->doComplete();
02494 e->accept();
02495 return;
02496 }
02497 }
02498
02499 if( !m_doc->isReadWrite() )
02500 {
02501 e->ignore();
02502 return;
02503 }
02504
02505 if ((key == Qt::Key_Return) || (key == Qt::Key_Enter))
02506 {
02507 m_view->keyReturn();
02508 e->accept();
02509 return;
02510 }
02511
02512 if ((key == SHIFT + Qt::Key_Return) || (key == SHIFT + Qt::Key_Enter))
02513 {
02514 uint ln = cursor.line();
02515 int col = cursor.col();
02516 KateTextLine::Ptr line = m_doc->kateTextLine( ln );
02517 int pos = line->firstChar();
02518 if (pos > cursor.col()) pos = cursor.col();
02519 if (pos != -1) {
02520 while ((int)line->length() > pos &&
02521 !line->getChar(pos).isLetterOrNumber() &&
02522 pos < cursor.col()) ++pos;
02523 } else {
02524 pos = line->length();
02525 }
02526 m_doc->editStart();
02527 m_doc->insertText( cursor.line(), line->length(), "\n" + line->string(0, pos)
02528 + line->string().right( line->length() - cursor.col() ) );
02529 cursor.setPos(ln + 1, pos);
02530 if (col < int(line->length()))
02531 m_doc->editRemoveText(ln, col, line->length() - col);
02532 m_doc->editEnd();
02533 updateCursor(cursor, true);
02534 updateView();
02535 e->accept();
02536
02537 return;
02538 }
02539
02540 if (key == Qt::Key_Backspace || key == SHIFT + Qt::Key_Backspace)
02541 {
02542 m_view->backspace();
02543 e->accept();
02544
02545 if (codeComp)
02546 m_view->m_codeCompletion->updateBox ();
02547
02548 return;
02549 }
02550
02551 if (key == Qt::Key_Tab || key == SHIFT+Qt::Key_Backtab || key == Qt::Key_Backtab)
02552 {
02553 if (m_doc->invokeTabInterceptor(key)) {
02554 e->accept();
02555 return;
02556 } else
02557 if (m_doc->configFlags() & KateDocumentConfig::cfTabIndents)
02558 {
02559 if( key == Qt::Key_Tab )
02560 {
02561 if (m_view->hasSelection() || (m_doc->configFlags() & KateDocumentConfig::cfTabIndentsMode))
02562 m_doc->indent( m_view, cursor.line(), 1 );
02563 else if (m_doc->configFlags() & KateDocumentConfig::cfTabInsertsTab)
02564 m_doc->typeChars ( m_view, QString ("\t") );
02565 else
02566 m_doc->insertIndentChars ( m_view );
02567
02568 e->accept();
02569
02570 if (codeComp)
02571 m_view->m_codeCompletion->updateBox ();
02572
02573 return;
02574 }
02575
02576 if (key == SHIFT+Qt::Key_Backtab || key == Qt::Key_Backtab)
02577 {
02578 m_doc->indent( m_view, cursor.line(), -1 );
02579 e->accept();
02580
02581 if (codeComp)
02582 m_view->m_codeCompletion->updateBox ();
02583
02584 return;
02585 }
02586 }
02587 }
02588 if ( !(e->state() & ControlButton) && !(e->state() & AltButton)
02589 && m_doc->typeChars ( m_view, e->text() ) )
02590 {
02591 e->accept();
02592
02593 if (codeComp)
02594 m_view->m_codeCompletion->updateBox ();
02595
02596 return;
02597 }
02598
02599 e->ignore();
02600 }
02601
02602 void KateViewInternal::keyReleaseEvent( QKeyEvent* e )
02603 {
02604 KKey key(e);
02605
02606 if (key == SHIFT)
02607 m_shiftKeyPressed = true;
02608 else
02609 {
02610 if (m_shiftKeyPressed)
02611 {
02612 m_shiftKeyPressed = false;
02613
02614 if (m_selChangedByUser)
02615 {
02616 QApplication::clipboard()->setSelectionMode( true );
02617 m_view->copy();
02618 QApplication::clipboard()->setSelectionMode( false );
02619
02620 m_selChangedByUser = false;
02621 }
02622 }
02623 }
02624
02625 e->ignore();
02626 return;
02627 }
02628
02629 void KateViewInternal::contextMenuEvent ( QContextMenuEvent * e )
02630 {
02631
02632
02633 QPoint p = e->pos();
02634
02635 if ( m_view->m_doc->browserView() )
02636 {
02637 m_view->contextMenuEvent( e );
02638 return;
02639 }
02640
02641 if ( e->reason() == QContextMenuEvent::Keyboard )
02642 {
02643 makeVisible( cursor, 0 );
02644 p = cursorCoordinates();
02645 }
02646 else if ( ! m_view->hasSelection() || m_view->config()->persistentSelection() )
02647 placeCursor( e->pos() );
02648
02649
02650 if (m_view->popup()) {
02651 m_view->popup()->popup( mapToGlobal( p ) );
02652 e->accept ();
02653 }
02654 }
02655
02656 void KateViewInternal::mousePressEvent( QMouseEvent* e )
02657 {
02658 switch (e->button())
02659 {
02660 case LeftButton:
02661 m_selChangedByUser = false;
02662
02663 if (possibleTripleClick)
02664 {
02665 possibleTripleClick = false;
02666
02667 m_selectionMode = Line;
02668
02669 if ( e->state() & Qt::ShiftButton )
02670 {
02671 updateSelection( cursor, true );
02672 }
02673 else
02674 {
02675 m_view->selectLine( cursor );
02676 }
02677
02678 QApplication::clipboard()->setSelectionMode( true );
02679 m_view->copy();
02680 QApplication::clipboard()->setSelectionMode( false );
02681
02682 selStartCached = m_view->selectStart;
02683 selEndCached = m_view->selectEnd;
02684
02685 cursor.setCol(0);
02686 updateCursor( cursor, true );
02687 e->accept ();
02688 return;
02689 }
02690
02691 if ( e->state() & Qt::ShiftButton )
02692 {
02693 selStartCached = m_view->selectStart;
02694 selEndCached = m_view->selectEnd;
02695 }
02696 else
02697 selStartCached.setLine( -1 );
02698
02699 if( isTargetSelected( e->pos() ) )
02700 {
02701 dragInfo.state = diPending;
02702 dragInfo.start = e->pos();
02703 }
02704 else
02705 {
02706 dragInfo.state = diNone;
02707
02708 placeCursor( e->pos(), e->state() & ShiftButton );
02709
02710 scrollX = 0;
02711 scrollY = 0;
02712
02713 m_scrollTimer.start (50);
02714 }
02715
02716 e->accept ();
02717 break;
02718
02719 default:
02720 e->ignore ();
02721 break;
02722 }
02723 }
02724
02725 void KateViewInternal::mouseDoubleClickEvent(QMouseEvent *e)
02726 {
02727 switch (e->button())
02728 {
02729 case LeftButton:
02730 m_selectionMode = Word;
02731
02732 if ( e->state() & Qt::ShiftButton )
02733 {
02734 selStartCached = m_view->selectStart;
02735 selEndCached = m_view->selectEnd;
02736 updateSelection( cursor, true );
02737 }
02738 else
02739 {
02740
02741
02742
02743
02744 m_view->clearSelection( false, false );
02745 m_view->selectWord( cursor );
02746 selectAnchor = KateTextCursor (m_view->selEndLine(), m_view->selEndCol());
02747 selStartCached = m_view->selectStart;
02748 selEndCached = m_view->selectEnd;
02749 }
02750
02751
02752 if (m_view->hasSelection())
02753 {
02754 QApplication::clipboard()->setSelectionMode( true );
02755 m_view->copy();
02756 QApplication::clipboard()->setSelectionMode( false );
02757
02758 cursor.setPos(m_view->selectEnd);
02759 updateCursor( cursor, true );
02760
02761 selStartCached = m_view->selectStart;
02762 selEndCached = m_view->selectEnd;
02763 }
02764
02765 possibleTripleClick = true;
02766 QTimer::singleShot ( QApplication::doubleClickInterval(), this, SLOT(tripleClickTimeout()) );
02767
02768 e->accept ();
02769 break;
02770
02771 default:
02772 e->ignore ();
02773 break;
02774 }
02775 }
02776
02777 void KateViewInternal::tripleClickTimeout()
02778 {
02779 possibleTripleClick = false;
02780 }
02781
02782 void KateViewInternal::mouseReleaseEvent( QMouseEvent* e )
02783 {
02784 switch (e->button())
02785 {
02786 case LeftButton:
02787 m_selectionMode = Default;
02788
02789
02790 if (m_selChangedByUser)
02791 {
02792 QApplication::clipboard()->setSelectionMode( true );
02793 m_view->copy();
02794 QApplication::clipboard()->setSelectionMode( false );
02795
02796 m_selChangedByUser = false;
02797 }
02798
02799 if (dragInfo.state == diPending)
02800 placeCursor( e->pos(), e->state() & ShiftButton );
02801 else if (dragInfo.state == diNone)
02802 m_scrollTimer.stop ();
02803
02804 dragInfo.state = diNone;
02805
02806 e->accept ();
02807 break;
02808
02809 case MidButton:
02810 placeCursor( e->pos() );
02811
02812 if( m_doc->isReadWrite() )
02813 {
02814 QApplication::clipboard()->setSelectionMode( true );
02815 m_view->paste ();
02816 QApplication::clipboard()->setSelectionMode( false );
02817 }
02818
02819 e->accept ();
02820 break;
02821
02822 default:
02823 e->ignore ();
02824 break;
02825 }
02826 }
02827
02828 void KateViewInternal::mouseMoveEvent( QMouseEvent* e )
02829 {
02830 if( e->state() & LeftButton )
02831 {
02832 if (dragInfo.state == diPending)
02833 {
02834
02835
02836 QPoint p( e->pos() - dragInfo.start );
02837
02838
02839 if( p.manhattanLength() > KGlobalSettings::dndEventDelay() )
02840 doDrag();
02841
02842 return;
02843 }
02844
02845 mouseX = e->x();
02846 mouseY = e->y();
02847
02848 scrollX = 0;
02849 scrollY = 0;
02850 int d = m_view->renderer()->fontHeight();
02851
02852 if (mouseX < 0)
02853 scrollX = -d;
02854
02855 if (mouseX > width())
02856 scrollX = d;
02857
02858 if (mouseY < 0)
02859 {
02860 mouseY = 0;
02861 scrollY = -d;
02862 }
02863
02864 if (mouseY > height())
02865 {
02866 mouseY = height();
02867 scrollY = d;
02868 }
02869
02870 placeCursor( QPoint( mouseX, mouseY ), true );
02871
02872 }
02873 else
02874 {
02875 if (isTargetSelected( e->pos() ) ) {
02876
02877
02878 if (m_mouseCursor != ArrowCursor) {
02879 setCursor( KCursor::arrowCursor() );
02880 m_mouseCursor = ArrowCursor;
02881 }
02882 } else {
02883
02884 if (m_mouseCursor != IbeamCursor) {
02885 setCursor( KCursor::ibeamCursor() );
02886 m_mouseCursor = IbeamCursor;
02887 }
02888 }
02889
02890 if (m_textHintEnabled)
02891 {
02892 m_textHintTimer.start(m_textHintTimeout);
02893 m_textHintMouseX=e->x();
02894 m_textHintMouseY=e->y();
02895 }
02896 }
02897 }
02898
02899 void KateViewInternal::paintEvent(QPaintEvent *e)
02900 {
02901 paintText(e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height());
02902 }
02903
02904 void KateViewInternal::resizeEvent(QResizeEvent* e)
02905 {
02906 bool expandedHorizontally = width() > e->oldSize().width();
02907 bool expandedVertically = height() > e->oldSize().height();
02908 bool heightChanged = height() != e->oldSize().height();
02909
02910 m_madeVisible = false;
02911
02912 if (heightChanged) {
02913 setAutoCenterLines(m_autoCenterLines, false);
02914 m_cachedMaxStartPos.setPos(-1, -1);
02915 }
02916
02917 if (m_view->dynWordWrap()) {
02918 bool dirtied = false;
02919
02920 for (uint i = 0; i < lineRanges.count(); i++) {
02921
02922
02923 if (lineRanges[i].wrap ||
02924 (!expandedHorizontally && (lineRanges[i].endX - lineRanges[i].startX) > width())) {
02925 dirtied = lineRanges[i].dirty = true;
02926 break;
02927 }
02928 }
02929
02930 if (dirtied || heightChanged) {
02931 updateView(true);
02932 leftBorder->update();
02933 }
02934
02935 if (width() < e->oldSize().width()) {
02936 if (!m_view->wrapCursor()) {
02937
02938 if (cursor.col() > m_doc->lineLength(cursor.line())) {
02939 KateLineRange thisRange = currentRange();
02940
02941 KateTextCursor newCursor(cursor.line(), thisRange.endCol + ((width() - thisRange.xOffset() - (thisRange.endX - thisRange.startX)) / m_view->renderer()->spaceWidth()) - 1);
02942 updateCursor(newCursor);
02943 }
02944 }
02945 }
02946
02947 } else {
02948 updateView();
02949
02950 if (expandedHorizontally && startX() > 0)
02951 scrollColumns(startX() - (width() - e->oldSize().width()));
02952 }
02953
02954 if (expandedVertically) {
02955 KateTextCursor max = maxStartPos();
02956 if (startPos() > max)
02957 scrollPos(max);
02958 }
02959 }
02960
02961 void KateViewInternal::scrollTimeout ()
02962 {
02963 if (scrollX || scrollY)
02964 {
02965 scrollLines (startPos().line() + (scrollY / (int)m_view->renderer()->fontHeight()));
02966 placeCursor( QPoint( mouseX, mouseY ), true );
02967 }
02968 }
02969
02970 void KateViewInternal::cursorTimeout ()
02971 {
02972 m_view->renderer()->setDrawCaret(!m_view->renderer()->drawCaret());
02973 paintCursor();
02974 }
02975
02976 void KateViewInternal::textHintTimeout ()
02977 {
02978 m_textHintTimer.stop ();
02979
02980 KateLineRange thisRange = yToKateLineRange(m_textHintMouseY);
02981
02982 if (thisRange.line == -1) return;
02983
02984 if (m_textHintMouseX> (lineMaxCursorX(thisRange) - thisRange.startX)) return;
02985
02986 int realLine = thisRange.line;
02987 int startCol = thisRange.startCol;
02988
02989 KateTextCursor c(realLine, 0);
02990 m_view->renderer()->textWidth( c, startX() + m_textHintMouseX, startCol);
02991
02992 QString tmp;
02993
02994 emit m_view->needTextHint(c.line(), c.col(), tmp);
02995
02996 if (!tmp.isEmpty()) kdDebug(13030)<<"Hint text: "<<tmp<<endl;
02997 }
02998
02999 void KateViewInternal::focusInEvent (QFocusEvent *)
03000 {
03001 if (KApplication::cursorFlashTime() > 0)
03002 m_cursorTimer.start ( KApplication::cursorFlashTime() / 2 );
03003
03004 if (m_textHintEnabled)
03005 m_textHintTimer.start( m_textHintTimeout );
03006
03007 paintCursor();
03008
03009 m_doc->setActiveView( m_view );
03010
03011 emit m_view->gotFocus( m_view );
03012 }
03013
03014 void KateViewInternal::focusOutEvent (QFocusEvent *)
03015 {
03016 if( ! m_view->m_codeCompletion->codeCompletionVisible() )
03017 {
03018 m_cursorTimer.stop();
03019
03020 m_view->renderer()->setDrawCaret(true);
03021 paintCursor();
03022 emit m_view->lostFocus( m_view );
03023 }
03024
03025 m_textHintTimer.stop();
03026 }
03027
03028 void KateViewInternal::doDrag()
03029 {
03030 dragInfo.state = diDragging;
03031 dragInfo.dragObject = new QTextDrag(m_view->selection(), this);
03032 dragInfo.dragObject->drag();
03033 }
03034
03035 void KateViewInternal::dragEnterEvent( QDragEnterEvent* event )
03036 {
03037 event->accept( (QTextDrag::canDecode(event) && m_doc->isReadWrite()) ||
03038 KURLDrag::canDecode(event) );
03039 }
03040
03041 void KateViewInternal::dragMoveEvent( QDragMoveEvent* event )
03042 {
03043
03044 placeCursor( event->pos(), true, false );
03045
03046
03047
03048 event->acceptAction();
03049 }
03050
03051 void KateViewInternal::dropEvent( QDropEvent* event )
03052 {
03053 if ( KURLDrag::canDecode(event) ) {
03054
03055 emit dropEventPass(event);
03056
03057 } else if ( QTextDrag::canDecode(event) && m_doc->isReadWrite() ) {
03058
03059 QString text;
03060
03061 if (!QTextDrag::decode(event, text))
03062 return;
03063
03064
03065 bool priv = false;
03066 if (event->source() && event->source()->inherits("KateViewInternal"))
03067 priv = m_doc->ownedView( ((KateViewInternal*)(event->source()))->m_view );
03068
03069
03070 bool selected = isTargetSelected( event->pos() );
03071
03072 if( priv && selected ) {
03073
03074
03075 return;
03076 }
03077
03078
03079 m_doc->editStart ();
03080
03081
03082 if ( event->action() != QDropEvent::Copy )
03083 m_view->removeSelectedText();
03084
03085 m_doc->insertText( cursor.line(), cursor.col(), text );
03086
03087 m_doc->editEnd ();
03088
03089 placeCursor( event->pos() );
03090
03091 event->acceptAction();
03092 updateView();
03093 }
03094
03095
03096 dragInfo.state = diNone;
03097
03098 stopDragScroll();
03099 }
03100
03101
03102 void KateViewInternal::clear()
03103 {
03104 cursor.setPos(0, 0);
03105 displayCursor.setPos(0, 0);
03106 }
03107
03108 void KateViewInternal::wheelEvent(QWheelEvent* e)
03109 {
03110 if (m_lineScroll->minValue() != m_lineScroll->maxValue() && e->orientation() != Qt::Horizontal) {
03111
03112 if ( ( e->state() & ControlButton ) || ( e->state() & ShiftButton ) ) {
03113 if (e->delta() > 0)
03114 scrollPrevPage();
03115 else
03116 scrollNextPage();
03117 } else {
03118 scrollViewLines(-((e->delta() / 120) * QApplication::wheelScrollLines()));
03119
03120 update();
03121 leftBorder->update();
03122 }
03123
03124 } else if (columnScrollingPossible()) {
03125 QWheelEvent copy = *e;
03126 QApplication::sendEvent(m_columnScroll, ©);
03127
03128 } else {
03129 e->ignore();
03130 }
03131 }
03132
03133 void KateViewInternal::startDragScroll()
03134 {
03135 if ( !m_dragScrollTimer.isActive() ) {
03136 m_dragScrollTimer.start( scrollTime );
03137 }
03138 }
03139
03140 void KateViewInternal::stopDragScroll()
03141 {
03142 m_dragScrollTimer.stop();
03143 updateView();
03144 }
03145
03146 void KateViewInternal::doDragScroll()
03147 {
03148 QPoint p = this->mapFromGlobal( QCursor::pos() );
03149
03150 int dx = 0, dy = 0;
03151 if ( p.y() < scrollMargin ) {
03152 dy = p.y() - scrollMargin;
03153 } else if ( p.y() > height() - scrollMargin ) {
03154 dy = scrollMargin - (height() - p.y());
03155 }
03156
03157 if ( p.x() < scrollMargin ) {
03158 dx = p.x() - scrollMargin;
03159 } else if ( p.x() > width() - scrollMargin ) {
03160 dx = scrollMargin - (width() - p.x());
03161 }
03162
03163 dy /= 4;
03164
03165 if (dy)
03166 scrollLines(startPos().line() + dy);
03167
03168 if (columnScrollingPossible () && dx)
03169 scrollColumns(kMin (m_startX + dx, m_columnScroll->maxValue()));
03170
03171 if (!dy && !dx)
03172 stopDragScroll();
03173 }
03174
03175 void KateViewInternal::enableTextHints(int timeout)
03176 {
03177 m_textHintTimeout=timeout;
03178 m_textHintEnabled=true;
03179 m_textHintTimer.start(timeout);
03180 }
03181
03182 void KateViewInternal::disableTextHints()
03183 {
03184 m_textHintEnabled=false;
03185 m_textHintTimer.stop ();
03186 }
03187
03188 bool KateViewInternal::columnScrollingPossible ()
03189 {
03190 return !m_view->dynWordWrap() && m_columnScroll->isEnabled() && (m_columnScroll->maxValue() > 0);
03191 }
03192
03193
03194 void KateViewInternal::editStart()
03195 {
03196 editSessionNumber++;
03197
03198 if (editSessionNumber > 1)
03199 return;
03200
03201 editIsRunning = true;
03202 editOldCursor = cursor;
03203 }
03204
03205 void KateViewInternal::editEnd(int editTagLineStart, int editTagLineEnd, bool tagFrom)
03206 {
03207 if (editSessionNumber == 0)
03208 return;
03209
03210 editSessionNumber--;
03211
03212 if (editSessionNumber > 0)
03213 return;
03214
03215 if (tagFrom && (editTagLineStart <= int(m_doc->getRealLine(startLine()))))
03216 tagAll();
03217 else
03218 tagLines (editTagLineStart, tagFrom ? m_doc->lastLine() : editTagLineEnd, true);
03219
03220 if (editOldCursor == cursor)
03221 updateBracketMarks();
03222
03223 if (m_imPreeditLength <= 0)
03224 updateView(true);
03225
03226 if ((editOldCursor != cursor) && (m_imPreeditLength <= 0))
03227 {
03228 m_madeVisible = false;
03229 updateCursor ( cursor, true );
03230 }
03231 else if ( m_view->isActive() )
03232 {
03233 makeVisible(displayCursor, displayCursor.col());
03234 }
03235
03236 editIsRunning = false;
03237 }
03238
03239 void KateViewInternal::editSetCursor (const KateTextCursor &cursor)
03240 {
03241 if (this->cursor != cursor)
03242 {
03243 this->cursor.setPos (cursor);
03244 }
03245 }
03246
03247
03248 void KateViewInternal::viewSelectionChanged ()
03249 {
03250 if (!m_view->hasSelection())
03251 selectAnchor.setPos (-1, -1);
03252 }
03253
03254
03255 void KateViewInternal::imStartEvent( QIMEvent *e )
03256 {
03257 if ( m_doc->m_bReadOnly ) {
03258 e->ignore();
03259 return;
03260 }
03261
03262 if ( m_view->hasSelection() )
03263 m_view->removeSelectedText();
03264
03265 m_imPreeditStartLine = cursor.line();
03266 m_imPreeditStart = cursor.col();
03267 m_imPreeditLength = 0;
03268 m_imPreeditSelStart = m_imPreeditStart;
03269
03270 m_view->setIMSelectionValue( m_imPreeditStartLine, m_imPreeditStart, 0, 0, 0, true );
03271 }
03272
03273 void KateViewInternal::imComposeEvent( QIMEvent *e )
03274 {
03275 if ( m_doc->m_bReadOnly ) {
03276 e->ignore();
03277 return;
03278 }
03279
03280
03281 if ( m_imPreeditLength > 0 ) {
03282 cursor.setPos( m_imPreeditStartLine, m_imPreeditStart );
03283 m_doc->removeText( m_imPreeditStartLine, m_imPreeditStart,
03284 m_imPreeditStartLine, m_imPreeditStart + m_imPreeditLength );
03285 }
03286
03287 m_imPreeditLength = e->text().length();
03288 m_imPreeditSelStart = m_imPreeditStart + e->cursorPos();
03289
03290
03291 m_view->setIMSelectionValue( m_imPreeditStartLine, m_imPreeditStart, m_imPreeditStart + m_imPreeditLength,
03292 m_imPreeditSelStart, m_imPreeditSelStart + e->selectionLength(),
03293 true );
03294
03295
03296 m_doc->insertText( m_imPreeditStartLine, m_imPreeditStart, e->text() );
03297
03298
03299
03300 cursor.setPos( m_imPreeditStartLine, m_imPreeditSelStart );
03301 updateCursor( cursor, true );
03302
03303 updateView( true );
03304 }
03305
03306 void KateViewInternal::imEndEvent( QIMEvent *e )
03307 {
03308 if ( m_doc->m_bReadOnly ) {
03309 e->ignore();
03310 return;
03311 }
03312
03313 if ( m_imPreeditLength > 0 ) {
03314 cursor.setPos( m_imPreeditStartLine, m_imPreeditStart );
03315 m_doc->removeText( m_imPreeditStartLine, m_imPreeditStart,
03316 m_imPreeditStartLine, m_imPreeditStart + m_imPreeditLength );
03317 }
03318
03319 m_view->setIMSelectionValue( m_imPreeditStartLine, m_imPreeditStart, 0, 0, 0, false );
03320
03321 if ( e->text().length() > 0 ) {
03322 m_doc->insertText( cursor.line(), cursor.col(), e->text() );
03323
03324 if ( !m_cursorTimer.isActive() && KApplication::cursorFlashTime() > 0 )
03325 m_cursorTimer.start ( KApplication::cursorFlashTime() / 2 );
03326
03327 updateView( true );
03328 updateCursor( cursor, true );
03329 }
03330
03331 m_imPreeditStart = 0;
03332 m_imPreeditLength = 0;
03333 m_imPreeditSelStart = 0;
03334 }
03335
03336
03337