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