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