22 #include "katerenderer.h"
24 #include "katelinerange.h"
25 #include "katedocument.h"
26 #include "katearbitraryhighlight.h"
27 #include "kateconfig.h"
28 #include "katehighlight.h"
29 #include "katefactory.h"
34 #include <tqpainter.h>
35 #include <tqpopupmenu.h>
38 : m_doc(doc), m_view (view), m_caretStyle(
KateRenderer::Insert)
40 , m_showSelections(true)
42 , m_printerFriendly(false)
44 KateFactory::self()->registerRenderer (
this );
45 m_config =
new KateRendererConfig (
this);
47 m_tabWidth = m_doc->config()->tabWidth();
48 m_indentWidth = m_tabWidth;
49 if (m_doc->config()->configFlags() & KateDocumentConfig::cfSpaceIndent)
51 m_indentWidth = m_doc->config()->indentationWidth();
60 KateFactory::self()->deregisterRenderer (
this );
65 m_schema =
config()->schema ();
66 m_attributes = m_doc->highlight()->attributes (m_schema);
71 if (pos < m_attributes->size())
72 return &m_attributes->at(pos);
74 return &m_attributes->at(0);
94 m_tabWidth = tabWidth;
99 return m_config->showIndentationLines();
109 m_indentWidth = m_tabWidth;
110 if (m_doc->config()->configFlags() & KateDocumentConfig::cfSpaceIndent)
112 m_indentWidth = indentWidth;
123 TQFont f ( *
config()->font () );
124 f.setPointSize (f.pointSize ()+1);
129 void KateRenderer::decreaseFontSizes()
131 TQFont f ( *
config()->font () );
133 if ((f.pointSize ()-1) > 0)
134 f.setPointSize (f.pointSize ()-1);
141 return m_printerFriendly;
146 m_printerFriendly = printerFriendly;
158 KateFontStruct *fs =
config()->fontStruct();
161 TQColor backgroundColor(
config()->backgroundColor() );
163 bool selectionPainted =
false;
166 backgroundColor =
config()->selectionColor();
167 selectionPainted =
true;
173 backgroundColor =
config()->highlightedLineColor();
176 int markRed = 0, markGreen = 0, markBlue = 0, markCount = 0;
179 uint mrk = m_doc->mark( line );
182 for (uint bit = 0; bit < 32; bit++)
184 KTextEditor::MarkInterface::MarkTypes markType = (KTextEditor::MarkInterface::MarkTypes)(1<<bit);
187 TQColor markColor =
config()->lineMarkerColor(markType);
189 if (markColor.isValid()) {
191 markRed += markColor.red();
192 markGreen += markColor.green();
193 markBlue += markColor.blue();
200 markRed /= markCount;
201 markGreen /= markCount;
202 markBlue /= markCount;
203 backgroundColor.setRgb(
204 int((backgroundColor.red() * 0.9) + (markRed * 0.1)),
205 int((backgroundColor.green() * 0.9) + (markGreen * 0.1)),
206 int((backgroundColor.blue() * 0.9) + (markBlue * 0.1))
212 paint.fillRect(0, 0, xEnd - xStart, fs->fontHeight, backgroundColor);
214 return selectionPainted;
217 void KateRenderer::paintWhitespaceMarker(TQPainter &paint, uint x, uint y)
219 TQPen penBackup( paint.pen() );
220 paint.setPen(
config()->tabMarkerColor() );
221 paint.drawPoint(x, y);
222 paint.drawPoint(x + 1, y);
223 paint.drawPoint(x, y - 1);
224 paint.setPen( penBackup );
228 void KateRenderer::paintIndentMarker(TQPainter &paint, uint x, uint row)
230 TQPen penBackup( paint.pen() );
231 paint.setPen(
config()->tabMarkerColor() );
233 const int top = paint.window().top();
234 const int bottom = paint.window().bottom();
235 const int h = bottom - top + 1;
239 if(row & 1 && h & 1) pad = 1;
241 for(
int i = top; i <= bottom; i++)
245 paint.drawPoint(x + 2, i);
249 paint.setPen( penBackup );
255 int line = range->line;
262 bool showCursor =
drawCaret() && cursor && range->includesCursor(*cursor);
264 KateSuperRangeList& superRanges = m_doc->arbitraryHL()->rangesIncluding(range->line, 0);
271 KateArbitraryHighlightRange* bracketStartRange (0L);
272 KateArbitraryHighlightRange* bracketEndRange (0L);
273 if (bracketmark && bracketmark->isValid()) {
274 if (range->includesCursor(bracketmark->start())) {
276 startend.setCol(startend.col()+1);
277 bracketStartRange =
new KateArbitraryHighlightRange(m_doc, bracketmark->start(), startend);
278 bracketStartRange->setBGColor(
config()->highlightedBracketColor());
279 bracketStartRange->setBold(
true);
280 superRanges.append(bracketStartRange);
283 if (range->includesCursor(bracketmark->end())) {
285 endend.setCol(endend.col()+1);
286 bracketEndRange =
new KateArbitraryHighlightRange(m_doc, bracketmark->end(), endend);
287 bracketEndRange->setBGColor(
config()->highlightedBracketColor());
288 bracketEndRange->setBold(
true);
289 superRanges.append(bracketEndRange);
292 Q_ASSERT(bracketmark->start().line() <= bracketmark->end().line());
293 if (bracketmark->start().line() < line && bracketmark->end().line() >= line)
295 minIndent = bracketmark->getMinIndent();
301 uint len = textLine->length();
305 bool cursorVisible =
false;
306 int cursorMaxWidth = 0;
309 KateFontStruct * fs =
config()->fontStruct();
318 bool selectionPainted =
false;
319 bool isCurrentLine = (cursor && range->includesCursor(*cursor));
321 if (selectionPainted)
328 int startcol = range->startCol;
329 if (startcol > (
int)len)
335 int endcol = range->wrap ? range->endCol : -1;
337 len = len - startcol;
339 len = endcol - startcol;
342 KateAttribute* attr = m_doc->highlight()->attributes(m_schema)->data();
344 const TQColor *cursorColor = &attr[0].textColor();
348 superRanges.firstBoundary(¤tPos);
351 hasSel = getSelectionBounds(line, oldLen, startSel, endSel);
354 if (range->startsInvisibleBlock) {
355 paint.setPen(TQPen(
config()->wordWrapMarkerColor(), 1, TQt::DashLine));
356 paint.drawLine(0, fs->fontHeight - 1, xEnd - xStart, fs->fontHeight - 1);
360 if (range->xOffset() && range->xOffset() > xStart)
362 paint.fillRect(0, 0, range->xOffset() - xStart, fs->fontHeight,
363 TQBrush(
config()->wordWrapMarkerColor(), TQBrush::DiagCrossPattern));
367 uint xPos = range->xOffset();
373 if (showCursor && (cursor->col() >=
int(startcol)))
375 cursorVisible =
true;
376 cursorXPos = xPos + cursor->col() * fs->myFontMetrics.width(TQChar(
' '));
381 bool isIMSel =
false;
382 bool isIMEdit =
false;
388 const TQColor *curColor = 0;
389 const TQColor *oldColor = 0;
394 uint xPosAfter = xPos;
398 uint blockStartCol = startcol;
399 uint curCol = startcol;
400 uint nextCol = curCol + 1;
403 const uchar *textAttributes = textLine->attributes ();
404 bool noAttribs = !textAttributes;
407 textAttributes = textAttributes + startcol;
409 uint atLen = m_doc->highlight()->attributes(m_schema)->size();
413 uint trailingWhitespaceColumn = textLine->lastChar() + 1;
414 const uint lastIndentColumn = textLine->firstChar();
417 const uint
spaceWidth = fs->width (TQChar(
' '),
false,
false, m_tabWidth);
420 int curPos = textLine->cursorX(curCol, m_tabWidth);
422 while (curCol - startcol < len)
428 TQChar curChar = textLine->string()[curCol];
431 bool isTab = curChar == TQChar(
'\t');
435 KateAttribute* curAt = (noAttribs || ((*textAttributes) >= atLen)) ? &attr[0] : &attr[*textAttributes];
439 xPosAfter += curAt->width(*fs, curChar, m_tabWidth);
443 xPosAfter -= (xPosAfter % curAt->width(*fs, curChar, m_tabWidth));
447 if ((
int)xPosAfter >= xStart)
450 isSel = (
showSelections() && hasSel && (curCol >= startSel) && (curCol < endSel));
453 isIMEdit = m_view && m_view->isIMEdit( line, curCol );
456 isIMSel = m_view && m_view->isIMSelection( line, curCol );
459 curColor = isSel ? &(curAt->selectedTextColor()) : &(curAt->textColor());
462 if (curAt != oldAt || curColor != oldColor || (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos)) {
463 if (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos)
464 customHL = KateArbitraryHighlightRange::merge(superRanges.rangesIncluding(currentPos));
471 if (!hl.itemSet(KateAttribute::TextColor))
472 hl.setTextColor(*curColor);
475 paint.setPen(hl.textColor());
477 paint.setPen(hl.selectedTextColor());
479 paint.setFont(hl.font(*currentFont()));
481 if (superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos)
482 superRanges.nextBoundary();
492 bool renderNow =
false;
495 || (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) ==
KateTextCursor(line, nextCol))
498 || (curCol - startcol >= len - 1)
501 || (curCol + 1 >= trailingWhitespaceColumn)
507 || ((
int)xPos > xEnd)
510 || (!noAttribs && curAt != &attr[*(textAttributes+1)])
513 || (isSel != (hasSel && (nextCol >= startSel) && (nextCol < endSel)))
517 || (textLine->string()[nextCol] == TQChar(
'\t'))
520 || ( m_view && (isIMEdit != m_view->isIMEdit( line, nextCol )) )
523 || ( m_view && (isIMSel != m_view->isIMSelection( line, nextCol )) )
533 bool paintBackground =
true;
534 uint width = xPosAfter - oldXPos;
537 if (isIMSel && !isTab)
540 fillColor = m_view->colorGroup().color(TQColorGroup::Foreground);
542 else if (isIMEdit && !isTab)
546 const TQColorGroup& cg = m_view->colorGroup();
547 int h1, s1, v1, h2, s2, v2;
548 TQColor(cg.color( TQColorGroup::Base )).hsv( &h1, &s1, &v1 );
549 TQColor(cg.color( TQColorGroup::Background )).hsv( &h2, &s2, &v2 );
550 fillColor.setHsv( h1, s1, ( v1 + v2 ) / 2 );
552 else if (!selectionPainted && (isSel || currentHL.itemSet(KateAttribute::BGColor)))
556 fillColor =
config()->selectionColor();
560 if ((curCol >= len - 1) && m_view->lineEndSelected (line, endcol))
561 width = xEnd - oldXPos;
565 fillColor = currentHL.bgColor();
570 paintBackground =
false;
574 paint.fillRect(oldXPos - xStart, 0, width, fs->fontHeight, fillColor);
576 if (isIMSel && paintBackground && !isTab)
579 paint.setPen( m_view->colorGroup().color( TQColorGroup::BrightText ) );
586 const int charWidth = isTab ? m_tabWidth - curPos % m_tabWidth : 1;
590 if (curPos == 0 || curPos % m_indentWidth > 0)
591 i = m_indentWidth - curPos % m_indentWidth;
593 for (; i < charWidth; i += m_indentWidth)
596 paintIndentMarker(paint, xPos - xStart + i *
spaceWidth, line);
599 if (curPos+i == minIndent)
601 paintIndentMarker(paint, xPos - xStart + 1 + i *
spaceWidth, line+1);
608 int y = fs->fontAscent;
612 if (isTab || (curCol >= trailingWhitespaceColumn))
615 static TQString spaces;
616 if (
int(spaces.length()) != m_tabWidth)
617 spaces.fill(
' ', m_tabWidth);
619 paint.drawText(oldXPos-xStart, y, isTab ? spaces : TQString(
" "));
625 paintWhitespaceMarker(paint, xPos - xStart, y);
629 blockStartCol = nextCol;
635 paint.drawText(oldXPos-xStart, y, textLine->string(), blockStartCol, nextCol-blockStartCol);
639 TQRect r( oldXPos - xStart, 0, xPosAfter - oldXPos, fs->fontHeight );
640 paint.drawLine( r.bottomLeft(), r.bottomRight() );
644 if (isIMSel) paint.restore();
647 if ((
int)xPos > xEnd)
651 blockStartCol = nextCol;
658 if (showCursor && (cursor->col() ==
int(curCol)))
660 cursorVisible =
true;
662 cursorMaxWidth = xPosAfter - xPos;
663 cursorColor = &curAt->textColor();
669 blockStartCol = nextCol;
686 currentPos.setCol(currentPos.col() + 1);
691 curPos += m_tabWidth - (curPos % m_tabWidth);
701 if (
showSelections() && hasSel && !selectionPainted && xStart >= (int)xPos && m_view->lineEndSelected(line, -1))
703 paint.fillRect(0, 0, xEnd-xStart, fs->fontHeight,
config()->selectionColor());
707 if (showCursor && (cursor->col() >= int(curCol)))
709 cursorVisible =
true;
710 cursorXPos = xPos + (cursor->col() - int(curCol)) * fs->myFontMetrics.width(TQChar(
' '));
711 cursorMaxWidth = xPosAfter - xPos;
712 cursorColor = &oldAt->textColor();
719 uint cursorWidth = (
caretStyle() == Replace && (cursorMaxWidth > 2)) ? cursorMaxWidth : 2;
720 paint.fillRect(cursorXPos-xStart, 0, cursorWidth, fs->fontHeight, *cursorColor);
726 paint.setPen(
config()->wordWrapMarkerColor() );
727 int _x = m_doc->config()->wordWrapAt() * fs->myFontMetrics.width(
'x') - xStart;
728 paint.drawLine( _x,0,_x,fs->fontHeight );
732 delete bracketStartRange;
733 delete bracketEndRange;
741 const int len = textLine->length();
746 KateFontStruct *fs =
config()->fontStruct();
748 const TQChar *unicode = textLine->text();
749 const TQString &textString = textLine->string();
753 for (
int z = 0; z < cursorCol; z++) {
757 width = a->width(*fs, textString, z, m_tabWidth);
761 width = a->width(*fs, TQChar(
' '), m_tabWidth);
766 if (z < len && unicode[z] == TQChar(
'\t'))
773 uint KateRenderer::textWidth(
const KateTextLine::Ptr &textLine, uint startcol, uint maxwidth,
bool *needWrap,
int *endX)
775 KateFontStruct *fs =
config()->fontStruct();
777 uint endcol = startcol;
779 int lastWhiteSpace = -1;
780 int lastWhiteSpaceX = -1;
784 bool foundNonWhitespace = startcol != 0;
785 bool foundWhitespaceAfterNonWhitespace = startcol != 0;
789 const uint len = textLine->length();
790 const TQChar *unicode = textLine->text();
791 const TQString &textString = textLine->string();
797 int width = a->width(*fs, textString, z, m_tabWidth);
803 if (unicode[z] == TQChar(
'\t'))
806 if (unicode[z].isSpace())
808 lastWhiteSpace = z+1;
811 if (foundNonWhitespace)
812 foundWhitespaceAfterNonWhitespace =
true;
816 if (!foundWhitespaceAfterNonWhitespace) {
817 foundNonWhitespace =
true;
819 lastWhiteSpace = z+1;
826 if (lastWhiteSpace > -1)
828 endcol = lastWhiteSpace;
829 endX2 = lastWhiteSpaceX;
837 else if (z == startcol)
870 int line = kMin(kMax(0, cursor.line()), (
int)m_doc->numLines() - 1);
871 int col = kMax(0, cursor.col());
873 return textWidth(m_doc->kateTextLine(line), col);
876 uint KateRenderer::textWidth(
KateTextCursor &cursor,
int xPos, uint startCol)
878 bool wrapCursor = m_view->wrapCursor();
881 KateFontStruct *fs =
config()->fontStruct();
883 if (cursor.line() < 0) cursor.setLine(0);
884 if (cursor.line() > (
int)m_doc->lastLine()) cursor.setLine(m_doc->lastLine());
887 if (!textLine)
return 0;
889 const uint len = textLine->length();
890 const TQChar *unicode = textLine->text();
891 const TQString &textString = textLine->string();
895 while (x < xPos && (!wrapCursor || z < len)) {
903 width = a->width(*fs, textString, z, m_tabWidth);
905 width = a->width(*fs, TQChar(
' '), m_tabWidth);
909 if (z < len && unicode[z] == TQChar(
'\t'))
914 if (xPos - oldX < x - xPos && z > 0) {
922 const TQFont *KateRenderer::currentFont()
927 const TQFontMetrics* KateRenderer::currentFontMetrics()
929 return config()->fontMetrics();
934 return textPos(m_doc->kateTextLine(line), xPos, startCol, nearest);
943 KateFontStruct *fs =
config()->fontStruct();
949 const uint len = textLine->length();
950 const TQString &textString = textLine->string();
952 while ( (x < xPos) && (z < len)) {
956 x += a->width(*fs, textString, z, m_tabWidth);
960 if ( ( (! nearest) || xPos - oldX < x - xPos ) && z > 0 ) {
967 uint KateRenderer::fontHeight()
969 return config()->fontStruct ()->fontHeight;
972 uint KateRenderer::documentHeight()
974 return m_doc->numLines() * fontHeight();
977 bool KateRenderer::getSelectionBounds(uint line, uint lineLength, uint &start, uint &end)
981 if (m_view->hasSelection() && !m_view->blockSelectionMode())
983 if (m_view->lineIsSelection(line))
985 start = m_view->selStartCol();
986 end = m_view->selEndCol();
989 else if ((
int)line == m_view->selStartLine())
991 start = m_view->selStartCol();
995 else if ((
int)line == m_view->selEndLine())
998 end = m_view->selEndCol();
1002 else if (m_view->lineHasSelected(line))
1004 start = m_view->selStartCol();
1005 end = m_view->selEndCol();
1018 void KateRenderer::updateConfig ()
1024 m_view->updateRendererConfig();
1029 return attribute(0)->width(*
config()->fontStruct(), TQChar(
' '), m_tabWidth);
The Attribute class incorporates all text decorations supported by Kate.
Handles all of the work of rendering the text (used for the views and printing)
void setShowTabs(bool showTabs)
Set whether a mark should be painted to help identifying tabs.
void setIndentWidth(int indentWidth)
Sets the width of the tab.
void setShowSelections(bool showSelections)
Set whether the view's selections should be shown.
KateRenderer::caretStyles caretStyle() const
The style of the caret (text cursor) to be painted.
void setDrawCaret(bool drawCaret)
Set whether the caret (text cursor) will be drawn.
bool isPrinterFriendly() const
uint textPos(uint line, int xPos, uint startCol=0, bool nearest=true)
void setPrinterFriendly(bool printerFriendly)
Configure this renderer to paint in a printer-friendly fashion.
bool showIndentLines() const
bool paintTextLineBackground(TQPainter &paint, int line, bool isCurrentLine, int xStart, int xEnd)
Paint the background of a line.
KateAttribute * attribute(uint pos)
This takes an in index, and returns all the attributes for it.
bool drawCaret() const
Determine whether the caret (text cursor) will be drawn.
bool showSelections() const
Show the view's selection?
void paintTextLine(TQPainter &paint, const KateLineRange *range, int xStart, int xEnd, const KateTextCursor *cursor=0L, const KateBracketRange *bracketmark=0L)
This is the ultimate function to perform painting of a text line.
void setTabWidth(int tabWidth)
Sets the width of the tab.
caretStyles
Style of Caret (Insert or Replace mode)
KateRenderer(KateDocument *doc, KateView *view=0)
Constructor.
void increaseFontSizes()
Change to a different font (soon to be font set?)
void setCaretStyle(KateRenderer::caretStyles style)
Set the style of caret to be painted.
void setShowIndentLines(bool showLines)
Set whether a guide should be painted to help identifying indent lines.
void updateAttributes()
update the highlighting attributes (for example after an hl change or after hl config changed)
~KateRenderer()
Destructor.
KateRendererConfig * config()
Configuration.
uint spaceWidth()
Text width & height calculation functions...
Simple cursor class with no document pointer.
const TDEShortcut & end()