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