00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "katerenderer.h"
00023
00024 #include "katelinerange.h"
00025 #include "katedocument.h"
00026 #include "katearbitraryhighlight.h"
00027 #include "kateconfig.h"
00028 #include "katehighlight.h"
00029 #include "katefactory.h"
00030 #include "kateview.h"
00031
00032 #include <kdebug.h>
00033
00034 #include <qpainter.h>
00035 #include <qpopupmenu.h>
00036
00037 static const QChar tabChar('\t');
00038 static const QChar spaceChar(' ');
00039
00040 KateRenderer::KateRenderer(KateDocument* doc, KateView *view)
00041 : m_doc(doc), m_view (view), m_caretStyle(KateRenderer::Insert)
00042 , m_drawCaret(true)
00043 , m_showSelections(true)
00044 , m_showTabs(true)
00045 , m_printerFriendly(false)
00046 {
00047 KateFactory::self()->registerRenderer ( this );
00048 m_config = new KateRendererConfig (this);
00049
00050 m_tabWidth = m_doc->config()->tabWidth();
00051 m_indentWidth = m_tabWidth;
00052 if (m_doc->config()->configFlags() & KateDocumentConfig::cfSpaceIndent)
00053 {
00054 m_indentWidth = m_doc->config()->indentationWidth();
00055 }
00056
00057 updateAttributes ();
00058 }
00059
00060 KateRenderer::~KateRenderer()
00061 {
00062 delete m_config;
00063 KateFactory::self()->deregisterRenderer ( this );
00064 }
00065
00066 void KateRenderer::updateAttributes ()
00067 {
00068 m_schema = config()->schema ();
00069 m_attributes = m_doc->highlight()->attributes (m_schema);
00070 }
00071
00072 KateAttribute* KateRenderer::attribute(uint pos)
00073 {
00074 if (pos < m_attributes->size())
00075 return &m_attributes->at(pos);
00076
00077 return &m_attributes->at(0);
00078 }
00079
00080 void KateRenderer::setDrawCaret(bool drawCaret)
00081 {
00082 m_drawCaret = drawCaret;
00083 }
00084
00085 void KateRenderer::setCaretStyle(KateRenderer::caretStyles style)
00086 {
00087 m_caretStyle = style;
00088 }
00089
00090 void KateRenderer::setShowTabs(bool showTabs)
00091 {
00092 m_showTabs = showTabs;
00093 }
00094
00095 void KateRenderer::setTabWidth(int tabWidth)
00096 {
00097 m_tabWidth = tabWidth;
00098 }
00099
00100 bool KateRenderer::showIndentLines() const
00101 {
00102 return m_config->showIndentationLines();
00103 }
00104
00105 void KateRenderer::setShowIndentLines(bool showIndentLines)
00106 {
00107 m_config->setShowIndentationLines(showIndentLines);
00108 }
00109
00110 void KateRenderer::setIndentWidth(int indentWidth)
00111 {
00112 m_indentWidth = m_tabWidth;
00113 if (m_doc->config()->configFlags() & KateDocumentConfig::cfSpaceIndent)
00114 {
00115 m_indentWidth = indentWidth;
00116 }
00117 }
00118
00119 void KateRenderer::setShowSelections(bool showSelections)
00120 {
00121 m_showSelections = showSelections;
00122 }
00123
00124 void KateRenderer::increaseFontSizes()
00125 {
00126 QFont f ( *config()->font () );
00127 f.setPointSize (f.pointSize ()+1);
00128
00129 config()->setFont (f);
00130 }
00131
00132 void KateRenderer::decreaseFontSizes()
00133 {
00134 QFont f ( *config()->font () );
00135
00136 if ((f.pointSize ()-1) > 0)
00137 f.setPointSize (f.pointSize ()-1);
00138
00139 config()->setFont (f);
00140 }
00141
00142 bool KateRenderer::isPrinterFriendly() const
00143 {
00144 return m_printerFriendly;
00145 }
00146
00147 void KateRenderer::setPrinterFriendly(bool printerFriendly)
00148 {
00149 m_printerFriendly = printerFriendly;
00150 setShowTabs(false);
00151 setShowSelections(false);
00152 setDrawCaret(false);
00153 }
00154
00155 bool KateRenderer::paintTextLineBackground(QPainter& paint, int line, bool isCurrentLine, int xStart, int xEnd)
00156 {
00157 if (isPrinterFriendly())
00158 return false;
00159
00160
00161 KateFontStruct *fs = config()->fontStruct();
00162
00163
00164 QColor backgroundColor( config()->backgroundColor() );
00165
00166 bool selectionPainted = false;
00167 if (showSelections() && m_view->lineSelected(line))
00168 {
00169 backgroundColor = config()->selectionColor();
00170 selectionPainted = true;
00171 }
00172 else
00173 {
00174
00175 if (isCurrentLine)
00176 backgroundColor = config()->highlightedLineColor();
00177
00178
00179 int markRed = 0, markGreen = 0, markBlue = 0, markCount = 0;
00180
00181
00182 uint mrk = m_doc->mark( line );
00183 if (mrk)
00184 {
00185 for (uint bit = 0; bit < 32; bit++)
00186 {
00187 KTextEditor::MarkInterface::MarkTypes markType = (KTextEditor::MarkInterface::MarkTypes)(1<<bit);
00188 if (mrk & markType)
00189 {
00190 QColor markColor = config()->lineMarkerColor(markType);
00191
00192 if (markColor.isValid()) {
00193 markCount++;
00194 markRed += markColor.red();
00195 markGreen += markColor.green();
00196 markBlue += markColor.blue();
00197 }
00198 }
00199 }
00200 }
00201
00202 if (markCount) {
00203 markRed /= markCount;
00204 markGreen /= markCount;
00205 markBlue /= markCount;
00206 backgroundColor.setRgb(
00207 int((backgroundColor.red() * 0.9) + (markRed * 0.1)),
00208 int((backgroundColor.green() * 0.9) + (markGreen * 0.1)),
00209 int((backgroundColor.blue() * 0.9) + (markBlue * 0.1))
00210 );
00211 }
00212 }
00213
00214
00215 paint.fillRect(0, 0, xEnd - xStart, fs->fontHeight, backgroundColor);
00216
00217 return selectionPainted;
00218 }
00219
00220 void KateRenderer::paintWhitespaceMarker(QPainter &paint, uint x, uint y)
00221 {
00222 QPen penBackup( paint.pen() );
00223 paint.setPen( config()->tabMarkerColor() );
00224 paint.drawPoint(x, y);
00225 paint.drawPoint(x + 1, y);
00226 paint.drawPoint(x, y - 1);
00227 paint.setPen( penBackup );
00228 }
00229
00230
00231 void KateRenderer::paintIndentMarker(QPainter &paint, uint x, uint row)
00232 {
00233 QPen penBackup( paint.pen() );
00234 paint.setPen( config()->tabMarkerColor() );
00235
00236 const int top = paint.window().top();
00237 const int bottom = paint.window().bottom();
00238 const int h = bottom - top + 1;
00239
00240
00241 int pad = 0;
00242 if(row & 1 && h & 1) pad = 1;
00243
00244 for(int i = top; i <= bottom; i++)
00245 {
00246 if((i + pad) & 1)
00247 {
00248 paint.drawPoint(x + 2, i);
00249 }
00250 }
00251
00252 paint.setPen( penBackup );
00253 }
00254
00255
00256 void KateRenderer::paintTextLine(QPainter& paint, const KateLineRange* range, int xStart, int xEnd, const KateTextCursor* cursor, const KateBracketRange* bracketmark)
00257 {
00258 int line = range->line;
00259
00260
00261 KateTextLine::Ptr textLine = m_doc->kateTextLine(line);
00262 if (!textLine)
00263 return;
00264
00265 bool showCursor = drawCaret() && cursor && range->includesCursor(*cursor);
00266
00267 KateSuperRangeList& superRanges = m_doc->arbitraryHL()->rangesIncluding(range->line, 0);
00268
00269 int minIndent = 0;
00270
00271
00272
00273
00274 KateArbitraryHighlightRange* bracketStartRange (0L);
00275 KateArbitraryHighlightRange* bracketEndRange (0L);
00276 if (bracketmark && bracketmark->isValid()) {
00277 if (range->includesCursor(bracketmark->start())) {
00278 KateTextCursor startend = bracketmark->start();
00279 startend.setCol(startend.col()+1);
00280 bracketStartRange = new KateArbitraryHighlightRange(m_doc, bracketmark->start(), startend);
00281 bracketStartRange->setBGColor(config()->highlightedBracketColor());
00282 bracketStartRange->setBold(true);
00283 superRanges.append(bracketStartRange);
00284 }
00285
00286 if (range->includesCursor(bracketmark->end())) {
00287 KateTextCursor endend = bracketmark->end();
00288 endend.setCol(endend.col()+1);
00289 bracketEndRange = new KateArbitraryHighlightRange(m_doc, bracketmark->end(), endend);
00290 bracketEndRange->setBGColor(config()->highlightedBracketColor());
00291 bracketEndRange->setBold(true);
00292 superRanges.append(bracketEndRange);
00293 }
00294
00295 Q_ASSERT(bracketmark->start().line() <= bracketmark->end().line());
00296 if (bracketmark->start().line() < line && bracketmark->end().line() >= line)
00297 {
00298 minIndent = bracketmark->getMinIndent();
00299 }
00300 }
00301
00302
00303
00304 uint len = textLine->length();
00305 uint oldLen = len;
00306
00307
00308 bool cursorVisible = false;
00309 int cursorMaxWidth = 0;
00310
00311
00312 KateFontStruct * fs = config()->fontStruct();
00313
00314
00315
00316 bool hasSel = false;
00317 uint startSel = 0;
00318 uint endSel = 0;
00319
00320
00321 bool selectionPainted = false;
00322 bool isCurrentLine = (cursor && range->includesCursor(*cursor));
00323 selectionPainted = paintTextLineBackground(paint, line, isCurrentLine, xStart, xEnd);
00324 if (selectionPainted)
00325 {
00326 hasSel = true;
00327 startSel = 0;
00328 endSel = len + 1;
00329 }
00330
00331 int startcol = range->startCol;
00332 if (startcol > (int)len)
00333 startcol = len;
00334
00335 if (startcol < 0)
00336 startcol = 0;
00337
00338 int endcol = range->wrap ? range->endCol : -1;
00339 if (endcol < 0)
00340 len = len - startcol;
00341 else
00342 len = endcol - startcol;
00343
00344
00345 KateAttribute* attr = m_doc->highlight()->attributes(m_schema)->data();
00346
00347 const QColor *cursorColor = &attr[0].textColor();
00348
00349
00350 KateTextCursor currentPos(line, startcol);
00351 superRanges.firstBoundary(¤tPos);
00352
00353 if (showSelections() && !selectionPainted)
00354 hasSel = getSelectionBounds(line, oldLen, startSel, endSel);
00355
00356
00357 if (range->startsInvisibleBlock) {
00358 paint.setPen(QPen(config()->wordWrapMarkerColor(), 1, Qt::DashLine));
00359 paint.drawLine(0, fs->fontHeight - 1, xEnd - xStart, fs->fontHeight - 1);
00360 }
00361
00362
00363 if (range->xOffset() && range->xOffset() > xStart)
00364 {
00365 paint.fillRect(0, 0, range->xOffset() - xStart, fs->fontHeight,
00366 QBrush(config()->wordWrapMarkerColor(), QBrush::DiagCrossPattern));
00367 }
00368
00369
00370 uint xPos = range->xOffset();
00371 int cursorXPos = 0;
00372
00373
00374 if (len < 1)
00375 {
00376 if (showCursor && (cursor->col() >= int(startcol)))
00377 {
00378 cursorVisible = true;
00379 cursorXPos = xPos + cursor->col() * fs->myFontMetrics.width(spaceChar);
00380 }
00381 }
00382 else
00383 {
00384 bool isIMSel = false;
00385 bool isIMEdit = false;
00386
00387 bool isSel = false;
00388
00389 KateAttribute customHL;
00390
00391 const QColor *curColor = 0;
00392 const QColor *oldColor = 0;
00393
00394 KateAttribute* oldAt = &attr[0];
00395
00396 uint oldXPos = xPos;
00397 uint xPosAfter = xPos;
00398
00399 KateAttribute currentHL;
00400
00401 uint blockStartCol = startcol;
00402 uint curCol = startcol;
00403 uint nextCol = curCol + 1;
00404
00405
00406 const uchar *textAttributes = textLine->attributes ();
00407 bool noAttribs = !textAttributes;
00408
00409
00410 textAttributes = textAttributes + startcol;
00411
00412 uint atLen = m_doc->highlight()->attributes(m_schema)->size();
00413
00414
00415
00416 uint trailingWhitespaceColumn = textLine->lastChar() + 1;
00417 const uint lastIndentColumn = textLine->firstChar();
00418
00419
00420 const uint spaceWidth = fs->width (spaceChar, false, false, m_tabWidth);
00421
00422
00423 int curPos = textLine->cursorX(curCol, m_tabWidth);
00424
00425 while (curCol - startcol < len)
00426 {
00427
00428 Q_ASSERT(curPos == textLine->cursorX(curCol, m_tabWidth));
00429
00430 QChar curChar = textLine->string()[curCol];
00431
00432
00433 bool isTab = curChar == tabChar;
00434
00435
00436
00437 KateAttribute* curAt = (noAttribs || ((*textAttributes) >= atLen)) ? &attr[0] : &attr[*textAttributes];
00438
00439
00440
00441 xPosAfter += curAt->width(*fs, curChar, m_tabWidth);
00442
00443
00444 if (isTab)
00445 xPosAfter -= (xPosAfter % curAt->width(*fs, curChar, m_tabWidth));
00446
00447
00448
00449 if ((int)xPosAfter >= xStart)
00450 {
00451
00452 isSel = (showSelections() && hasSel && (curCol >= startSel) && (curCol < endSel));
00453
00454
00455 isIMEdit = m_view && m_view->isIMEdit( line, curCol );
00456
00457
00458 isIMSel = m_view && m_view->isIMSelection( line, curCol );
00459
00460
00461 curColor = isSel ? &(curAt->selectedTextColor()) : &(curAt->textColor());
00462
00463
00464 if (curAt != oldAt || curColor != oldColor || (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos)) {
00465 if (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos)
00466 customHL = KateArbitraryHighlightRange::merge(superRanges.rangesIncluding(currentPos));
00467
00468 KateAttribute hl = customHL;
00469
00470 hl += *curAt;
00471
00472
00473 if (!hl.itemSet(KateAttribute::TextColor))
00474 hl.setTextColor(*curColor);
00475
00476 if (!isSel)
00477 paint.setPen(hl.textColor());
00478 else
00479 paint.setPen(hl.selectedTextColor());
00480
00481 paint.setFont(hl.font(*currentFont()));
00482
00483 if (superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos)
00484 superRanges.nextBoundary();
00485
00486 currentHL = hl;
00487 }
00488
00489
00490
00491
00492
00493
00494 bool renderNow = false;
00495 if ((isTab)
00496
00497 || (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == KateTextCursor(line, nextCol))
00498
00499
00500 || (curCol >= len - 1)
00501
00502
00503 || (curCol + 1 >= trailingWhitespaceColumn)
00504
00505
00506 || (showIndentLines() && curCol < lastIndentColumn)
00507
00508
00509 || ((int)xPos > xEnd)
00510
00511
00512 || (!noAttribs && curAt != &attr[*(textAttributes+1)])
00513
00514
00515 || (isSel != (hasSel && (nextCol >= startSel) && (nextCol < endSel)))
00516
00517
00518
00519 || (textLine->string()[nextCol] == tabChar)
00520
00521
00522 || ( m_view && (isIMEdit != m_view->isIMEdit( line, nextCol )) )
00523
00524
00525 || ( m_view && (isIMSel != m_view->isIMSelection( line, nextCol )) )
00526 )
00527 {
00528 renderNow = true;
00529 }
00530
00531 if (renderNow)
00532 {
00533 if (!isPrinterFriendly())
00534 {
00535 bool paintBackground = true;
00536 uint width = xPosAfter - oldXPos;
00537 QColor fillColor;
00538
00539 if (isIMSel && !isTab)
00540 {
00541
00542 fillColor = m_view->colorGroup().color(QColorGroup::Foreground);
00543 }
00544 else if (isIMEdit && !isTab)
00545 {
00546
00547
00548 const QColorGroup& cg = m_view->colorGroup();
00549 int h1, s1, v1, h2, s2, v2;
00550 cg.color( QColorGroup::Base ).hsv( &h1, &s1, &v1 );
00551 cg.color( QColorGroup::Background ).hsv( &h2, &s2, &v2 );
00552 fillColor.setHsv( h1, s1, ( v1 + v2 ) / 2 );
00553 }
00554 else if (!selectionPainted && (isSel || currentHL.itemSet(KateAttribute::BGColor)))
00555 {
00556 if (isSel)
00557 {
00558 fillColor = config()->selectionColor();
00559
00560
00561
00562 if ((curCol >= len - 1) && m_view->lineEndSelected (line, endcol))
00563 width = xEnd - oldXPos;
00564 }
00565 else
00566 {
00567 fillColor = currentHL.bgColor();
00568 }
00569 }
00570 else
00571 {
00572 paintBackground = false;
00573 }
00574
00575 if (paintBackground)
00576 paint.fillRect(oldXPos - xStart, 0, width, fs->fontHeight, fillColor);
00577
00578 if (isIMSel && paintBackground && !isTab)
00579 {
00580 paint.save();
00581 paint.setPen( m_view->colorGroup().color( QColorGroup::BrightText ) );
00582 }
00583
00584
00585 if (showIndentLines() && curCol < lastIndentColumn)
00586 {
00587
00588 const int charWidth = isTab ? m_tabWidth - curPos % m_tabWidth : 1;
00589
00590
00591 int i = 0;
00592 if (curPos == 0 || curPos % m_indentWidth > 0)
00593 i = m_indentWidth - curPos % m_indentWidth;
00594
00595 for (; i < charWidth; i += m_indentWidth)
00596 {
00597
00598 paintIndentMarker(paint, xPos - xStart + i * spaceWidth, line);
00599
00600
00601 if (curPos+i == minIndent)
00602 {
00603 paintIndentMarker(paint, xPos - xStart + 1 + i * spaceWidth, line+1);
00604 }
00605 }
00606 }
00607 }
00608
00609
00610 int y = fs->fontAscent;
00611
00612
00613
00614 if (isTab || (curCol >= trailingWhitespaceColumn))
00615 {
00616
00617 static QString spaces;
00618 if (int(spaces.length()) != m_tabWidth)
00619 spaces.fill(' ', m_tabWidth);
00620
00621 paint.drawText(oldXPos-xStart, y, isTab ? spaces : QString(" "));
00622
00623 if (showTabs())
00624 {
00625
00626
00627 paintWhitespaceMarker(paint, xPos - xStart, y);
00628 }
00629
00630
00631 blockStartCol = nextCol;
00632 oldXPos = xPosAfter;
00633 }
00634 else
00635 {
00636
00637 paint.drawText(oldXPos-xStart, y, textLine->string(), blockStartCol, nextCol-blockStartCol);
00638
00639
00640 if (isIMEdit) {
00641 QRect r( oldXPos - xStart, 0, xPosAfter - oldXPos, fs->fontHeight );
00642 paint.drawLine( r.bottomLeft(), r.bottomRight() );
00643 }
00644
00645
00646 if (isIMSel) paint.restore();
00647
00648
00649 if ((int)xPos > xEnd)
00650 break;
00651
00652
00653 blockStartCol = nextCol;
00654 oldXPos = xPosAfter;
00655
00656 }
00657 }
00658
00659
00660 if (showCursor && (cursor->col() == int(curCol)))
00661 {
00662 cursorVisible = true;
00663 cursorXPos = xPos;
00664 cursorMaxWidth = xPosAfter - xPos;
00665 cursorColor = &curAt->textColor();
00666 }
00667 }
00668 else
00669 {
00670
00671 blockStartCol = nextCol;
00672 oldXPos = xPosAfter;
00673 }
00674
00675
00676 xPos = xPosAfter;
00677
00678
00679 textAttributes++;
00680
00681
00682 oldAt = curAt;
00683 oldColor = curColor;
00684
00685
00686 curCol++;
00687 nextCol++;
00688 currentPos.setCol(currentPos.col() + 1);
00689
00690
00691 if (isTab)
00692 {
00693 curPos += m_tabWidth - (curPos % m_tabWidth);
00694 }
00695 else
00696 {
00697 curPos++;
00698 }
00699 }
00700
00701
00702 if (showCursor && (cursor->col() >= int(curCol)))
00703 {
00704 cursorVisible = true;
00705 cursorXPos = xPos + (cursor->col() - int(curCol)) * fs->myFontMetrics.width(spaceChar);
00706 cursorMaxWidth = xPosAfter - xPos;
00707 cursorColor = &oldAt->textColor();
00708 }
00709 }
00710
00711
00712 if (cursorVisible)
00713 {
00714 uint cursorWidth = (caretStyle() == Replace && (cursorMaxWidth > 2)) ? cursorMaxWidth : 2;
00715 paint.fillRect(cursorXPos-xStart, 0, cursorWidth, fs->fontHeight, *cursorColor);
00716 }
00717
00718
00719 if (!isPrinterFriendly() && config()->wordWrapMarker() && fs->fixedPitch())
00720 {
00721 paint.setPen( config()->wordWrapMarkerColor() );
00722 int _x = m_doc->config()->wordWrapAt() * fs->myFontMetrics.width('x') - xStart;
00723 paint.drawLine( _x,0,_x,fs->fontHeight );
00724 }
00725
00726
00727 delete bracketStartRange;
00728 delete bracketEndRange;
00729 }
00730
00731 uint KateRenderer::textWidth(const KateTextLine::Ptr &textLine, int cursorCol)
00732 {
00733 if (!textLine)
00734 return 0;
00735
00736 int len = textLine->length();
00737
00738 if (cursorCol < 0)
00739 cursorCol = len;
00740
00741 KateFontStruct *fs = config()->fontStruct();
00742
00743 int x = 0;
00744 int width;
00745 for (int z = 0; z < cursorCol; z++) {
00746 KateAttribute* a = attribute(textLine->attribute(z));
00747
00748 if (z < len) {
00749 width = a->width(*fs, textLine->string(), z, m_tabWidth);
00750 } else {
00751
00752
00753 width = a->width(*fs, spaceChar, m_tabWidth);
00754 }
00755
00756 x += width;
00757
00758 if (textLine->getChar(z) == tabChar)
00759 x -= x % width;
00760 }
00761
00762 return x;
00763 }
00764
00765 uint KateRenderer::textWidth(const KateTextLine::Ptr &textLine, uint startcol, uint maxwidth, bool *needWrap, int *endX)
00766 {
00767 KateFontStruct *fs = config()->fontStruct();
00768 uint x = 0;
00769 uint endcol = startcol;
00770 int endX2 = 0;
00771 int lastWhiteSpace = -1;
00772 int lastWhiteSpaceX = -1;
00773
00774
00775
00776 bool foundNonWhitespace = startcol != 0;
00777 bool foundWhitespaceAfterNonWhitespace = startcol != 0;
00778
00779 *needWrap = false;
00780
00781 uint z = startcol;
00782 for (; z < textLine->length(); z++)
00783 {
00784 KateAttribute* a = attribute(textLine->attribute(z));
00785 int width = a->width(*fs, textLine->string(), z, m_tabWidth);
00786 Q_ASSERT(width);
00787 x += width;
00788
00789 if (textLine->getChar(z).isSpace())
00790 {
00791 lastWhiteSpace = z+1;
00792 lastWhiteSpaceX = x;
00793
00794 if (foundNonWhitespace)
00795 foundWhitespaceAfterNonWhitespace = true;
00796 }
00797 else
00798 {
00799 if (!foundWhitespaceAfterNonWhitespace) {
00800 foundNonWhitespace = true;
00801
00802 lastWhiteSpace = z+1;
00803 lastWhiteSpaceX = x;
00804 }
00805 }
00806
00807
00808
00809 if (textLine->getChar(z) == tabChar)
00810 x -= x % width;
00811
00812 if (x <= maxwidth)
00813 {
00814 if (lastWhiteSpace > -1)
00815 {
00816 endcol = lastWhiteSpace;
00817 endX2 = lastWhiteSpaceX;
00818 }
00819 else
00820 {
00821 endcol = z+1;
00822 endX2 = x;
00823 }
00824 }
00825 else if (z == startcol)
00826 {
00827
00828
00829 endcol = z+1;
00830 endX2 = x;
00831 }
00832
00833 if (x >= maxwidth)
00834 {
00835 *needWrap = true;
00836 break;
00837 }
00838 }
00839
00840 if (*needWrap)
00841 {
00842 if (endX)
00843 *endX = endX2;
00844
00845 return endcol;
00846 }
00847 else
00848 {
00849 if (endX)
00850 *endX = x;
00851
00852 return z+1;
00853 }
00854 }
00855
00856 uint KateRenderer::textWidth(const KateTextCursor &cursor)
00857 {
00858 int line = QMIN(QMAX(0, cursor.line()), (int)m_doc->numLines() - 1);
00859 int col = QMAX(0, cursor.col());
00860
00861 return textWidth(m_doc->kateTextLine(line), col);
00862 }
00863
00864 uint KateRenderer::textWidth( KateTextCursor &cursor, int xPos, uint startCol)
00865 {
00866 bool wrapCursor = m_view->wrapCursor();
00867 int len;
00868 int x, oldX;
00869
00870 KateFontStruct *fs = config()->fontStruct();
00871
00872 if (cursor.line() < 0) cursor.setLine(0);
00873 if (cursor.line() > (int)m_doc->lastLine()) cursor.setLine(m_doc->lastLine());
00874 KateTextLine::Ptr textLine = m_doc->kateTextLine(cursor.line());
00875
00876 if (!textLine) return 0;
00877
00878 len = textLine->length();
00879
00880 x = oldX = 0;
00881 int z = startCol;
00882 while (x < xPos && (!wrapCursor || z < len)) {
00883 oldX = x;
00884
00885 KateAttribute* a = attribute(textLine->attribute(z));
00886
00887 int width = 0;
00888
00889 if (z < len)
00890 width = a->width(*fs, textLine->string(), z, m_tabWidth);
00891 else
00892 width = a->width(*fs, spaceChar, m_tabWidth);
00893
00894 x += width;
00895
00896 if (textLine->getChar(z) == tabChar)
00897 x -= x % width;
00898
00899 z++;
00900 }
00901 if (xPos - oldX < x - xPos && z > 0) {
00902 z--;
00903 x = oldX;
00904 }
00905 cursor.setCol(z);
00906 return x;
00907 }
00908
00909 const QFont *KateRenderer::currentFont()
00910 {
00911 return config()->font();
00912 }
00913
00914 const QFontMetrics* KateRenderer::currentFontMetrics()
00915 {
00916 return config()->fontMetrics();
00917 }
00918
00919 uint KateRenderer::textPos(uint line, int xPos, uint startCol, bool nearest)
00920 {
00921 return textPos(m_doc->kateTextLine(line), xPos, startCol, nearest);
00922 }
00923
00924 uint KateRenderer::textPos(const KateTextLine::Ptr &textLine, int xPos, uint startCol, bool nearest)
00925 {
00926 Q_ASSERT(textLine);
00927 if (!textLine)
00928 return 0;
00929
00930 KateFontStruct *fs = config()->fontStruct();
00931
00932 int x, oldX;
00933 x = oldX = 0;
00934
00935 uint z = startCol;
00936 uint len= textLine->length();
00937 while ( (x < xPos) && (z < len)) {
00938 oldX = x;
00939
00940 KateAttribute* a = attribute(textLine->attribute(z));
00941 x += a->width(*fs, textLine->string(), z, m_tabWidth);
00942
00943 z++;
00944 }
00945 if ( ( (! nearest) || xPos - oldX < x - xPos ) && z > 0 ) {
00946 z--;
00947
00948 }
00949 return z;
00950 }
00951
00952 uint KateRenderer::fontHeight()
00953 {
00954 return config()->fontStruct ()->fontHeight;
00955 }
00956
00957 uint KateRenderer::documentHeight()
00958 {
00959 return m_doc->numLines() * fontHeight();
00960 }
00961
00962 bool KateRenderer::getSelectionBounds(uint line, uint lineLength, uint &start, uint &end)
00963 {
00964 bool hasSel = false;
00965
00966 if (m_view->hasSelection() && !m_view->blockSelectionMode())
00967 {
00968 if (m_view->lineIsSelection(line))
00969 {
00970 start = m_view->selStartCol();
00971 end = m_view->selEndCol();
00972 hasSel = true;
00973 }
00974 else if ((int)line == m_view->selStartLine())
00975 {
00976 start = m_view->selStartCol();
00977 end = lineLength;
00978 hasSel = true;
00979 }
00980 else if ((int)line == m_view->selEndLine())
00981 {
00982 start = 0;
00983 end = m_view->selEndCol();
00984 hasSel = true;
00985 }
00986 }
00987 else if (m_view->lineHasSelected(line))
00988 {
00989 start = m_view->selStartCol();
00990 end = m_view->selEndCol();
00991 hasSel = true;
00992 }
00993
00994 if (start > end) {
00995 int temp = end;
00996 end = start;
00997 start = temp;
00998 }
00999
01000 return hasSel;
01001 }
01002
01003 void KateRenderer::updateConfig ()
01004 {
01005
01006 updateAttributes ();
01007
01008 if (m_view)
01009 m_view->updateRendererConfig();
01010 }
01011
01012 uint KateRenderer::spaceWidth()
01013 {
01014 return attribute(0)->width(*config()->fontStruct(), spaceChar, m_tabWidth);
01015 }
01016
01017