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