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