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