• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kate
 

kate

  • kate
  • part
katerenderer.cpp
1/* This file is part of the KDE libraries
2 Copyright (C) 2003 Hamish Rodda <rodda@kde.org>
3 Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
4 Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
5 Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License version 2 as published by the Free Software Foundation.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22#include "katerenderer.h"
23
24#include "katelinerange.h"
25#include "katedocument.h"
26#include "katearbitraryhighlight.h"
27#include "kateconfig.h"
28#include "katehighlight.h"
29#include "katefactory.h"
30#include "kateview.h"
31
32#include <kdebug.h>
33
34#include <tqpainter.h>
35#include <tqpopupmenu.h>
36
37KateRenderer::KateRenderer(KateDocument* doc, KateView *view)
38 : m_doc(doc), m_view (view), m_caretStyle(KateRenderer::Insert)
39 , m_drawCaret(true)
40 , m_showSelections(true)
41 , m_showTabs(true)
42 , m_printerFriendly(false)
43{
44 KateFactory::self()->registerRenderer ( this );
45 m_config = new KateRendererConfig (this);
46
47 m_tabWidth = m_doc->config()->tabWidth();
48 m_indentWidth = m_tabWidth;
49 if (m_doc->config()->configFlags() & KateDocumentConfig::cfSpaceIndent)
50 {
51 m_indentWidth = m_doc->config()->indentationWidth();
52 }
53
54 updateAttributes ();
55}
56
57KateRenderer::~KateRenderer()
58{
59 delete m_config;
60 KateFactory::self()->deregisterRenderer ( this );
61}
62
63void KateRenderer::updateAttributes ()
64{
65 m_schema = config()->schema ();
66 m_attributes = m_doc->highlight()->attributes (m_schema);
67}
68
69KateAttribute* KateRenderer::attribute(uint pos)
70{
71 if (pos < m_attributes->size())
72 return &m_attributes->at(pos);
73
74 return &m_attributes->at(0);
75}
76
77void KateRenderer::setDrawCaret(bool drawCaret)
78{
79 m_drawCaret = drawCaret;
80}
81
82void KateRenderer::setCaretStyle(KateRenderer::caretStyles style)
83{
84 m_caretStyle = style;
85}
86
87void KateRenderer::setShowTabs(bool showTabs)
88{
89 m_showTabs = showTabs;
90}
91
92void KateRenderer::setTabWidth(int tabWidth)
93{
94 m_tabWidth = tabWidth;
95}
96
97bool KateRenderer::showIndentLines() const
98{
99 return m_config->showIndentationLines();
100}
101
102void KateRenderer::setShowIndentLines(bool showIndentLines)
103{
104 m_config->setShowIndentationLines(showIndentLines);
105}
106
107void KateRenderer::setIndentWidth(int indentWidth)
108{
109 m_indentWidth = m_tabWidth;
110 if (m_doc->config()->configFlags() & KateDocumentConfig::cfSpaceIndent)
111 {
112 m_indentWidth = indentWidth;
113 }
114}
115
116void KateRenderer::setShowSelections(bool showSelections)
117{
118 m_showSelections = showSelections;
119}
120
121void KateRenderer::increaseFontSizes()
122{
123 TQFont f ( *config()->font () );
124 f.setPointSize (f.pointSize ()+1);
125
126 config()->setFont (f);
127}
128
129void KateRenderer::decreaseFontSizes()
130{
131 TQFont f ( *config()->font () );
132
133 if ((f.pointSize ()-1) > 0)
134 f.setPointSize (f.pointSize ()-1);
135
136 config()->setFont (f);
137}
138
139bool KateRenderer::isPrinterFriendly() const
140{
141 return m_printerFriendly;
142}
143
144void KateRenderer::setPrinterFriendly(bool printerFriendly)
145{
146 m_printerFriendly = printerFriendly;
147 setShowTabs(false);
148 setShowSelections(false);
149 setDrawCaret(false);
150}
151
152bool KateRenderer::paintTextLineBackground(TQPainter& paint, int line, bool isCurrentLine, int xStart, int xEnd)
153{
154 if (isPrinterFriendly())
155 return false;
156
157 // font data
158 KateFontStruct *fs = config()->fontStruct();
159
160 // Normal background color
161 TQColor backgroundColor( config()->backgroundColor() );
162
163 bool selectionPainted = false;
164 if (showSelections() && m_view->lineSelected(line))
165 {
166 backgroundColor = config()->selectionColor();
167 selectionPainted = true;
168 }
169 else
170 {
171 // paint the current line background if we're on the current line
172 if (isCurrentLine)
173 backgroundColor = config()->highlightedLineColor();
174
175 // Check for mark background
176 int markRed = 0, markGreen = 0, markBlue = 0, markCount = 0;
177
178 // Retrieve marks for this line
179 uint mrk = m_doc->mark( line );
180 if (mrk)
181 {
182 for (uint bit = 0; bit < 32; bit++)
183 {
184 KTextEditor::MarkInterface::MarkTypes markType = (KTextEditor::MarkInterface::MarkTypes)(1<<bit);
185 if (mrk & markType)
186 {
187 TQColor markColor = config()->lineMarkerColor(markType);
188
189 if (markColor.isValid()) {
190 markCount++;
191 markRed += markColor.red();
192 markGreen += markColor.green();
193 markBlue += markColor.blue();
194 }
195 }
196 } // for
197 } // Marks
198
199 if (markCount) {
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))
207 );
208 }
209 } // background preprocessing
210
211 // Draw line background
212 paint.fillRect(0, 0, xEnd - xStart, fs->fontHeight, backgroundColor);
213
214 return selectionPainted;
215}
216
217void KateRenderer::paintWhitespaceMarker(TQPainter &paint, uint x, uint y)
218{
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 );
225}
226
227
228void KateRenderer::paintIndentMarker(TQPainter &paint, uint x, uint row)
229{
230 TQPen penBackup( paint.pen() );
231 paint.setPen( config()->tabMarkerColor() );
232
233 const int top = paint.window().top();
234 const int bottom = paint.window().bottom();
235 const int h = bottom - top + 1;
236
237 // Dot padding.
238 int pad = 0;
239 if(row & 1 && h & 1) pad = 1;
240
241 for(int i = top; i <= bottom; i++)
242 {
243 if((i + pad) & 1)
244 {
245 paint.drawPoint(x + 2, i);
246 }
247 }
248
249 paint.setPen( penBackup );
250}
251
252
253void KateRenderer::paintTextLine(TQPainter& paint, const KateLineRange* range, int xStart, int xEnd, const KateTextCursor* cursor, const KateBracketRange* bracketmark)
254{
255 int line = range->line;
256
257 // textline
258 KateTextLine::Ptr textLine = m_doc->kateTextLine(line);
259 if (!textLine)
260 return;
261
262 bool showCursor = drawCaret() && cursor && range->includesCursor(*cursor);
263
264 KateSuperRangeList& superRanges = m_doc->arbitraryHL()->rangesIncluding(range->line, 0);
265
266 int minIndent = 0;
267
268 // A bit too verbose for my tastes
269 // Re-write a bracketmark class? put into its own function? add more helper constructors to the range stuff?
270 // Also, need a light-weight arbitraryhighlightrange class for static stuff
271 KateArbitraryHighlightRange* bracketStartRange (0L);
272 KateArbitraryHighlightRange* bracketEndRange (0L);
273 if (bracketmark && bracketmark->isValid()) {
274 if (range->includesCursor(bracketmark->start())) {
275 KateTextCursor startend = 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);
281 }
282
283 if (range->includesCursor(bracketmark->end())) {
284 KateTextCursor endend = 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);
290 }
291
292 Q_ASSERT(bracketmark->start().line() <= bracketmark->end().line());
293 if (bracketmark->start().line() < line && bracketmark->end().line() >= line)
294 {
295 minIndent = bracketmark->getMinIndent();
296 }
297 }
298
299
300 // length, chars + raw attribs
301 uint len = textLine->length();
302 uint oldLen = len;
303
304 // should the cursor be painted (if it is in the current xstart - xend range)
305 bool cursorVisible = false;
306 int cursorMaxWidth = 0;
307
308 // font data
309 KateFontStruct * fs = config()->fontStruct();
310
311 // Paint selection background as the whole line is selected
312 // selection startcol/endcol calc
313 bool hasSel = false;
314 uint startSel = 0;
315 uint endSel = 0;
316
317 // was the selection background already completely painted ?
318 bool selectionPainted = false;
319 bool isCurrentLine = (cursor && range->includesCursor(*cursor));
320 selectionPainted = paintTextLineBackground(paint, line, isCurrentLine, xStart, xEnd);
321 if (selectionPainted)
322 {
323 hasSel = true;
324 startSel = 0;
325 endSel = len + 1;
326 }
327
328 int startcol = range->startCol;
329 if (startcol > (int)len)
330 startcol = len;
331
332 if (startcol < 0)
333 startcol = 0;
334
335 int endcol = range->wrap ? range->endCol : -1;
336 if (endcol < 0)
337 len = len - startcol;
338 else
339 len = endcol - startcol;
340
341 // text attribs font/style data
342 KateAttribute* attr = m_doc->highlight()->attributes(m_schema)->data();
343
344 const TQColor *cursorColor = &attr[0].textColor();
345
346 // Start arbitrary highlighting
347 KateTextCursor currentPos(line, startcol);
348 superRanges.firstBoundary(&currentPos);
349
350 if (showSelections() && !selectionPainted)
351 hasSel = getSelectionBounds(line, oldLen, startSel, endSel);
352
353 // Draws the dashed underline at the start of a folded block of text.
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);
357 }
358
359 // draw word-wrap-honor-indent filling
360 if (range->xOffset() && range->xOffset() > xStart)
361 {
362 paint.fillRect(0, 0, range->xOffset() - xStart, fs->fontHeight,
363 TQBrush(config()->wordWrapMarkerColor(), TQBrush::DiagCrossPattern));
364 }
365
366 // painting loop
367 uint xPos = range->xOffset();
368 int cursorXPos = 0;
369
370 // Optimisation to quickly draw an empty line of text
371 if (len < 1)
372 {
373 if (showCursor && (cursor->col() >= int(startcol)))
374 {
375 cursorVisible = true;
376 cursorXPos = xPos + cursor->col() * fs->myFontMetrics.width(TQChar(' '));
377 }
378 }
379 else
380 {
381 bool isIMSel = false;
382 bool isIMEdit = false;
383
384 bool isSel = false;
385
386 KateAttribute customHL;
387
388 const TQColor *curColor = 0;
389 const TQColor *oldColor = 0;
390
391 KateAttribute* oldAt = &attr[0];
392
393 uint oldXPos = xPos;
394 uint xPosAfter = xPos;
395
396 KateAttribute currentHL;
397
398 uint blockStartCol = startcol;
399 uint curCol = startcol;
400 uint nextCol = curCol + 1;
401
402 // text + attrib data from line
403 const uchar *textAttributes = textLine->attributes();
404 bool noAttribs = !textAttributes;
405
406 // adjust to startcol ;)
407 textAttributes = textAttributes + startcol;
408
409 uint atLen = m_doc->highlight()->attributes(m_schema)->size();
410
411 // Determine if we have trailing whitespace and store the column
412 // if lastChar == -1, set to 0, if lastChar exists, increase by one
413 uint trailingWhitespaceColumn = textLine->lastChar() + 1;
414 const uint lastIndentColumn = textLine->firstChar();
415
416 // Could be precomputed.
417 const uint spaceWidth = fs->width (TQChar(' '), false, false, m_tabWidth);
418
419 // Get current x position.
420 int curPos = textLine->cursorX(curCol, m_tabWidth);
421
422 while (curCol - startcol < len)
423 {
424 const TQString &textString = textLine->string();
425 int currCharNumCols = textString[curCol].isHighSurrogate() ? 2 : 1;
426 nextCol = curCol + currCharNumCols;
427
428 // make sure curPos is updated correctly.
429 // ### if uncommented, causes an O(n^2) behaviour
430 //Q_ASSERT(curPos == textLine->cursorX(curCol, m_tabWidth));
431
432 // Decide if this character is a tab - we treat the spacing differently
433 // TODO: move tab width calculation elsewhere?
434 bool isTab = textString[curCol] == TQChar('\t');
435
436 // Determine current syntax highlighting attribute
437 // A bit legacy but doesn't need to change
438 KateAttribute* curAt = (noAttribs || ((*textAttributes) >= atLen)) ? &attr[0] : &attr[*textAttributes];
439
440 // X position calculation. Incorrect for fonts with non-zero leftBearing() and rightBearing() results.
441 // TODO: make internal charWidth() function.
442 xPosAfter += curAt->width(*fs, textString, curCol, m_tabWidth);
443
444 // Tab special treatment, move to charWidth().
445 if (isTab)
446 xPosAfter -= (xPosAfter % curAt->width(*fs, textString[curCol], m_tabWidth));
447
448 // Only draw after the starting X value
449 // Haha, this was always wrong, due to the use of individual char width calculations...?? :(
450 if ((int)xPosAfter >= xStart)
451 {
452 // Determine if we're in a selection and should be drawing it
453 isSel = (showSelections() && hasSel && (curCol >= startSel) && (curCol < endSel));
454
455 // input method edit area
456 isIMEdit = m_view && m_view->isIMEdit( line, curCol );
457
458 // input method selection
459 isIMSel = m_view && m_view->isIMSelection( line, curCol );
460
461 // Determine current color, taking into account selection
462 curColor = isSel ? &(curAt->selectedTextColor()) : &(curAt->textColor());
463
464 // Incorporate in arbitrary highlighting
465 if (curAt != oldAt || curColor != oldColor || (superRanges.count() &&
466 superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos))
467 {
468 if (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos)
469 customHL = KateArbitraryHighlightRange::merge(superRanges.rangesIncluding(currentPos));
470
471 KateAttribute hl = customHL;
472
473 hl += *curAt;
474
475 // use default highlighting color if we haven't defined one above.
476 if (!hl.itemSet(KateAttribute::TextColor))
477 hl.setTextColor(*curColor);
478
479 if (!isSel)
480 paint.setPen(hl.textColor());
481 else
482 paint.setPen(hl.selectedTextColor());
483
484 paint.setFont(hl.font(*currentFont()));
485
486 if (superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos)
487 superRanges.nextBoundary();
488
489 currentHL = hl;
490 }
491
492 // Determine whether we can delay painting to draw a block of similarly formatted
493 // characters or not
494 // Reasons for NOT delaying the drawing until the next character
495 // You have to detect the change one character in advance.
496 // TODO: KateAttribute::canBatchRender()
497 bool renderNow = false;
498 if ((isTab)
499 // formatting has changed OR
500 || (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == KateTextCursor(line, nextCol))
501
502 // it is the end of the line OR
503 || ((curCol - startcol) >= (len - currCharNumCols))
504
505 // the rest of the line is trailing whitespace OR
506 || (nextCol >= trailingWhitespaceColumn)
507
508 // indentation lines OR
509 || (showIndentLines() && curCol < lastIndentColumn)
510
511 // the x position is past the end OR
512 || ((int)xPos > xEnd)
513
514 // it is a different attribute OR
515 || (!noAttribs && curAt != &attr[*(textAttributes+1)])
516
517 // the selection boundary was crossed OR
518 || (isSel != (hasSel && (nextCol >= startSel) && (nextCol < endSel)))
519
520 // the next char is a tab (removed the "and this isn't" because that's dealt with above)
521 // i.e. we have to draw the current text so the tab can be rendered as above.
522 || (textString[nextCol] == TQChar('\t'))
523
524 // input method edit area
525 || ( m_view && (isIMEdit != m_view->isIMEdit( line, nextCol )) )
526
527 // input method selection
528 || ( m_view && (isIMSel != m_view->isIMSelection( line, nextCol )) )
529 )
530 {
531 renderNow = true;
532 }
533
534 if (renderNow)
535 {
536 if (!isPrinterFriendly())
537 {
538 bool paintBackground = true;
539 uint width = xPosAfter - oldXPos;
540 TQColor fillColor;
541
542 if (isIMSel && !isTab)
543 {
544 // input method selection
545 fillColor = m_view->colorGroup().color(TQColorGroup::Foreground);
546 }
547 else if (isIMEdit && !isTab)
548 {
549 // XIM support
550 // input method edit area
551 const TQColorGroup& cg = m_view->colorGroup();
552 int h1, s1, v1, h2, s2, v2;
553 TQColor(cg.color( TQColorGroup::Base )).hsv( &h1, &s1, &v1 );
554 TQColor(cg.color( TQColorGroup::Background )).hsv( &h2, &s2, &v2 );
555 fillColor.setHsv( h1, s1, ( v1 + v2 ) / 2 );
556 }
557 else if (!selectionPainted && (isSel || currentHL.itemSet(KateAttribute::BGColor)))
558 {
559 if (isSel)
560 {
561 fillColor = config()->selectionColor();
562
563 // If this is the last block of text, fill up to the end of the line if the
564 // selection stretches that far
565 if (curCol >= (len - currCharNumCols) && m_view->lineEndSelected(line, endcol))
566 width = xEnd - oldXPos;
567 }
568 else
569 {
570 fillColor = currentHL.bgColor();
571 }
572 }
573 else
574 {
575 paintBackground = false;
576 }
577
578 if (paintBackground)
579 paint.fillRect(oldXPos - xStart, 0, width, fs->fontHeight, fillColor);
580
581 if (isIMSel && paintBackground && !isTab)
582 {
583 paint.save();
584 paint.setPen( m_view->colorGroup().color( TQColorGroup::BrightText ) );
585 }
586
587 // Draw indentation markers.
588 if (showIndentLines() && curCol < lastIndentColumn)
589 {
590 // Draw multiple guides when tab width greater than indent width.
591 const int charWidth = isTab ? m_tabWidth - curPos % m_tabWidth : 1;
592
593 // Do not draw indent guides on the first line.
594 int i = 0;
595 if (curPos == 0 || curPos % m_indentWidth > 0)
596 i = m_indentWidth - curPos % m_indentWidth;
597
598 for (; i < charWidth; i += m_indentWidth)
599 {
600 // In most cases this is done one or zero times.
601 paintIndentMarker(paint, xPos - xStart + i * spaceWidth, line);
602
603 // Draw highlighted line.
604 if (curPos+i == minIndent)
605 {
606 paintIndentMarker(paint, xPos - xStart + 1 + i * spaceWidth, line+1);
607 }
608 }
609 }
610 }
611
612 // or we will see no text ;)
613 int y = fs->fontAscent;
614
615 // make sure we redraw the right character groups on attrib/selection changes
616 // Special case... de-special case some of it
617 if (isTab || (curCol >= trailingWhitespaceColumn))
618 {
619 // Draw spaces too, because it might be eg. underlined
620 static TQString spaces;
621 if (int(spaces.length()) != m_tabWidth)
622 spaces.fill(' ', m_tabWidth);
623
624 paint.drawText(oldXPos-xStart, y, isTab ? spaces : TQString(" "));
625
626 if (showTabs())
627 {
628 // trailing spaces and tabs may also have to be different options.
629 // if( curCol >= lastIndentColumn )
630 paintWhitespaceMarker(paint, xPos - xStart, y);
631 }
632
633 // variable advancement
634 blockStartCol = nextCol;
635 oldXPos = xPosAfter;
636 }
637 else
638 {
639 // Here's where the money is...
640 paint.drawText(oldXPos-xStart, y, textString, blockStartCol, nextCol-blockStartCol);
641
642 // Draw preedit's underline
643 if (isIMEdit) {
644 TQRect r( oldXPos - xStart, 0, xPosAfter - oldXPos, fs->fontHeight );
645 paint.drawLine( r.bottomLeft(), r.bottomRight() );
646 }
647
648 // Put pen color back
649 if (isIMSel) paint.restore();
650
651 // We're done drawing?
652 if ((int)xPos > xEnd)
653 break;
654
655 // variable advancement
656 blockStartCol = nextCol;
657 oldXPos = xPosAfter;
658 }
659 } // renderNow
660
661 // determine cursor X position
662 if (showCursor && (cursor->col() == int(curCol)))
663 {
664 cursorVisible = true;
665 cursorXPos = xPos;
666 cursorMaxWidth = xPosAfter - xPos;
667 cursorColor = &curAt->textColor();
668 }
669 } // xPosAfter >= xStart
670 else
671 {
672 // variable advancement
673 blockStartCol = nextCol;
674 oldXPos = xPosAfter;
675 }
676
677 // increase xPos
678 xPos = xPosAfter;
679
680 // increase attribs pos
681 textAttributes++;
682
683 // to only switch font/color if needed
684 oldAt = curAt;
685 oldColor = curColor;
686
687 // col move
688 curCol += currCharNumCols;
689 currentPos.setCol(currentPos.col() + currCharNumCols);
690
691 // Update the current indentation pos.
692 if (isTab)
693 {
694 curPos += m_tabWidth - (curPos % m_tabWidth);
695 }
696 else
697 {
698 curPos++;
699 }
700 }
701
702 // If this line has a partial selection that's the start of a multi-line selection,
703 // we have to fill areas on the right side of the text with the selection color.
704 if (showSelections() && hasSel && !selectionPainted && xStart >= (int)xPos && m_view->lineEndSelected(line, -1))
705 {
706 paint.fillRect(0, 0, xEnd-xStart, fs->fontHeight, config()->selectionColor());
707 }
708
709 // Determine cursor position (if it is not within the range being drawn)
710 if (showCursor && (cursor->col() >= int(curCol)))
711 {
712 cursorVisible = true;
713 cursorXPos = xPos + (cursor->col() - int(curCol)) * fs->myFontMetrics.width(TQChar(' '));
714 cursorMaxWidth = xPosAfter - xPos;
715 cursorColor = &oldAt->textColor();
716 }
717 }
718
719 // Paint cursor
720 if (cursorVisible)
721 {
722 uint cursorWidth = (caretStyle() == Replace && (cursorMaxWidth > 2)) ? cursorMaxWidth : 2;
723 paint.fillRect(cursorXPos-xStart, 0, cursorWidth, fs->fontHeight, *cursorColor);
724 }
725
726 // show word wrap marker if desirable
727 if (!isPrinterFriendly() && config()->wordWrapMarker() && fs->fixedPitch())
728 {
729 paint.setPen( config()->wordWrapMarkerColor() );
730 int _x = m_doc->config()->wordWrapAt() * fs->myFontMetrics.width('x') - xStart;
731 paint.drawLine( _x,0,_x,fs->fontHeight );
732 }
733
734 // cleanup ;)
735 delete bracketStartRange;
736 delete bracketEndRange;
737}
738
739uint KateRenderer::textWidth(const KateTextLine::Ptr &textLine, int cursorCol)
740{
741 if (!textLine)
742 return 0;
743
744 const int len = textLine->length();
745
746 if (cursorCol < 0)
747 cursorCol = len;
748
749 KateFontStruct *fs = config()->fontStruct();
750
751 const TQChar *unicode = textLine->text();
752 const TQString &textString = textLine->string();
753
754 int x = 0;
755 int width;
756 for (int z = 0; z < cursorCol; z++) {
757 KateAttribute* a = attribute(textLine->attribute(z));
758
759 if (z < len) {
760 width = a->width(*fs, textString, z, m_tabWidth);
761 } else {
762 width = a->width(*fs, TQChar(' '), m_tabWidth);
763 }
764
765 x += width;
766
767 if (z < len && unicode[z] == TQChar('\t'))
768 x -= x % width;
769
770 if (textString[z].isHighSurrogate())
771 {
772 ++z;
773 }
774 }
775
776 return x;
777}
778
779uint KateRenderer::textWidth(const KateTextLine::Ptr &textLine, uint startcol, uint maxwidth, bool *needWrap, int *endX)
780{
781 KateFontStruct *fs = config()->fontStruct();
782 uint x = 0;
783 uint endcol = startcol;
784 int endX2 = 0;
785 int lastWhiteSpace = -1;
786 int lastWhiteSpaceX = -1;
787
788 // used to not wrap a solitary word off the first line, ie. the
789 // first line should not wrap until some characters have been displayed if possible
790 bool foundNonWhitespace = startcol != 0;
791 bool foundWhitespaceAfterNonWhitespace = startcol != 0;
792
793 *needWrap = false;
794
795 const uint len = textLine->length();
796 const TQChar *unicode = textLine->text();
797 const TQString &textString = textLine->string();
798
799 uint z = startcol;
800 for (; z < len; z++)
801 {
802 KateAttribute* a = attribute(textLine->attribute(z));
803 int width = a->width(*fs, textString, z, m_tabWidth);
804 Q_ASSERT(width);
805 x += width;
806
807 // How should tabs be treated when they word-wrap on a print-out?
808 // if startcol != 0, this messes up (then again, word wrapping messes up anyway)
809 if (unicode[z] == TQChar('\t'))
810 x -= x % width;
811
812 if (textString[z].isHighSurrogate())
813 {
814 ++z;
815 }
816 else if (unicode[z].isSpace())
817 {
818 lastWhiteSpace = z+1;
819 lastWhiteSpaceX = x;
820
821 if (foundNonWhitespace)
822 foundWhitespaceAfterNonWhitespace = true;
823 }
824 else
825 {
826 if (!foundWhitespaceAfterNonWhitespace) {
827 foundNonWhitespace = true;
828
829 lastWhiteSpace = z+1;
830 lastWhiteSpaceX = x;
831 }
832 }
833
834 if (x <= maxwidth)
835 {
836 if (lastWhiteSpace > -1)
837 {
838 endcol = lastWhiteSpace;
839 endX2 = lastWhiteSpaceX;
840 }
841 else
842 {
843 endcol = z+1;
844 endX2 = x;
845 }
846 }
847 else if (z == startcol)
848 {
849 // require a minimum of 1 character advancement per call, even if it means drawing gets cut off
850 // (geez gideon causes troubles with starting the views very small)
851 endcol = z+1;
852 endX2 = x;
853 }
854
855 if (x >= maxwidth)
856 {
857 *needWrap = true;
858 break;
859 }
860 }
861
862 if (*needWrap)
863 {
864 if (endX)
865 *endX = endX2;
866
867 return endcol;
868 }
869 else
870 {
871 if (endX)
872 *endX = x;
873
874 return z+1;
875 }
876}
877
878uint KateRenderer::textWidth(const KateTextCursor &cursor)
879{
880 int line = kMin(kMax(0, cursor.line()), (int)m_doc->numLines() - 1);
881 int col = kMax(0, cursor.col());
882
883 return textWidth(m_doc->kateTextLine(line), col);
884}
885
886uint KateRenderer::textWidth( KateTextCursor &cursor, int xPos, uint startCol)
887{
888 bool wrapCursor = m_view->wrapCursor();
889
890 KateFontStruct *fs = config()->fontStruct();
891
892 if (cursor.line() < 0) cursor.setLine(0);
893 if (cursor.line() > (int)m_doc->lastLine()) cursor.setLine(m_doc->lastLine());
894 KateTextLine::Ptr textLine = m_doc->kateTextLine(cursor.line());
895
896 if (!textLine) return 0;
897
898 const uint len = textLine->length();
899 const TQChar *unicode = textLine->text();
900 const TQString &textString = textLine->string();
901
902 int x = 0;
903 int oldX = 0;
904 int oldZ = 0;
905 int width = 0;
906 uint z = startCol;
907 while (x < xPos && (!wrapCursor || z < len)) {
908 oldX = x;
909 oldZ = z;
910
911 KateAttribute* a = attribute(textLine->attribute(z));
912
913 if (z < len)
914 width = a->width(*fs, textString, z, m_tabWidth);
915 else
916 width = a->width(*fs, TQChar(' '), m_tabWidth);
917
918 x += width;
919
920 if (z < len && unicode[z] == TQChar('\t'))
921 x -= x % width;
922
923 z += textString[z].isHighSurrogate() ? 2 : 1;
924 }
925 if (xPos - oldX < x - xPos && z > 0) {
926 x = oldX;
927 z = oldZ;
928 }
929 cursor.setCol(z);
930 return x;
931}
932
933const TQFont *KateRenderer::currentFont()
934{
935 return config()->font();
936}
937
938const TQFontMetrics* KateRenderer::currentFontMetrics()
939{
940 return config()->fontMetrics();
941}
942
943uint KateRenderer::textPos(uint line, int xPos, uint startCol, bool nearest)
944{
945 return textPos(m_doc->kateTextLine(line), xPos, startCol, nearest);
946}
947
948uint KateRenderer::textPos(const KateTextLine::Ptr &textLine, int xPos, uint startCol, bool nearest)
949{
950 Q_ASSERT(textLine);
951 if (!textLine)
952 return 0;
953
954 KateFontStruct *fs = config()->fontStruct();
955
956 int x = 0;
957 int oldX = 0;
958 int oldZ = 0;
959 uint z = startCol;
960 const uint len = textLine->length();
961 const TQString &textString = textLine->string();
962
963 while ( (x < xPos) && (z < len)) {
964 oldX = x;
965 oldZ = z;
966
967 KateAttribute* a = attribute(textLine->attribute(z));
968 x += a->width(*fs, textString, z, m_tabWidth);
969
970 z += textString[z].isHighSurrogate() ? 2 : 1;
971 }
972 if ( ( (! nearest) || xPos - oldX < x - xPos ) && z > 0 ) {
973 z = oldZ;
974 // newXPos = oldX;
975 }// else newXPos = x;
976 return z;
977}
978
979uint KateRenderer::fontHeight()
980{
981 return config()->fontStruct ()->fontHeight;
982}
983
984uint KateRenderer::documentHeight()
985{
986 return m_doc->numLines() * fontHeight();
987}
988
989bool KateRenderer::getSelectionBounds(uint line, uint lineLength, uint &start, uint &end)
990{
991 bool hasSel = false;
992
993 if (m_view->hasSelection() && !m_view->blockSelectionMode())
994 {
995 if (m_view->lineIsSelection(line))
996 {
997 start = m_view->selStartCol();
998 end = m_view->selEndCol();
999 hasSel = true;
1000 }
1001 else if ((int)line == m_view->selStartLine())
1002 {
1003 start = m_view->selStartCol();
1004 end = lineLength;
1005 hasSel = true;
1006 }
1007 else if ((int)line == m_view->selEndLine())
1008 {
1009 start = 0;
1010 end = m_view->selEndCol();
1011 hasSel = true;
1012 }
1013 }
1014 else if (m_view->lineHasSelected(line))
1015 {
1016 start = m_view->selStartCol();
1017 end = m_view->selEndCol();
1018 hasSel = true;
1019 }
1020
1021 if (start > end) {
1022 int temp = end;
1023 end = start;
1024 start = temp;
1025 }
1026
1027 return hasSel;
1028}
1029
1030void KateRenderer::updateConfig ()
1031{
1032 // update the attibute list pointer
1033 updateAttributes ();
1034
1035 if (m_view)
1036 m_view->updateRendererConfig();
1037}
1038
1039uint KateRenderer::spaceWidth()
1040{
1041 return attribute(0)->width(*config()->fontStruct(), TQChar(' '), m_tabWidth);
1042}
KateAttribute
The Attribute class incorporates all text decorations supported by Kate.
Definition: kateattribute.h:33
KateRenderer
Handles all of the work of rendering the text (used for the views and printing)
Definition: katerenderer.h:43
KateRenderer::setShowTabs
void setShowTabs(bool showTabs)
Set whether a mark should be painted to help identifying tabs.
Definition: katerenderer.cpp:87
KateRenderer::setIndentWidth
void setIndentWidth(int indentWidth)
Sets the width of the tab.
Definition: katerenderer.cpp:107
KateRenderer::setShowSelections
void setShowSelections(bool showSelections)
Set whether the view's selections should be shown.
Definition: katerenderer.cpp:116
KateRenderer::config
KateRendererConfig * config()
Configuration.
Definition: katerenderer.h:264
KateRenderer::caretStyle
KateRenderer::caretStyles caretStyle() const
The style of the caret (text cursor) to be painted.
Definition: katerenderer.h:87
KateRenderer::setDrawCaret
void setDrawCaret(bool drawCaret)
Set whether the caret (text cursor) will be drawn.
Definition: katerenderer.cpp:77
KateRenderer::isPrinterFriendly
bool isPrinterFriendly() const
Definition: katerenderer.cpp:139
KateRenderer::textPos
uint textPos(uint line, int xPos, uint startCol=0, bool nearest=true)
Definition: katerenderer.cpp:943
KateRenderer::setPrinterFriendly
void setPrinterFriendly(bool printerFriendly)
Configure this renderer to paint in a printer-friendly fashion.
Definition: katerenderer.cpp:144
KateRenderer::showIndentLines
bool showIndentLines() const
Definition: katerenderer.cpp:97
KateRenderer::paintTextLineBackground
bool paintTextLineBackground(TQPainter &paint, int line, bool isCurrentLine, int xStart, int xEnd)
Paint the background of a line.
Definition: katerenderer.cpp:152
KateRenderer::attribute
KateAttribute * attribute(uint pos)
This takes an in index, and returns all the attributes for it.
Definition: katerenderer.cpp:69
KateRenderer::showTabs
bool showTabs() const
Definition: katerenderer.h:100
KateRenderer::drawCaret
bool drawCaret() const
Determine whether the caret (text cursor) will be drawn.
Definition: katerenderer.h:75
KateRenderer::showSelections
bool showSelections() const
Show the view's selection?
Definition: katerenderer.h:136
KateRenderer::paintTextLine
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.
Definition: katerenderer.cpp:253
KateRenderer::setTabWidth
void setTabWidth(int tabWidth)
Sets the width of the tab.
Definition: katerenderer.cpp:92
KateRenderer::caretStyles
caretStyles
Style of Caret (Insert or Replace mode)
Definition: katerenderer.h:48
KateRenderer::KateRenderer
KateRenderer(KateDocument *doc, KateView *view=0)
Constructor.
Definition: katerenderer.cpp:37
KateRenderer::increaseFontSizes
void increaseFontSizes()
Change to a different font (soon to be font set?)
Definition: katerenderer.cpp:121
KateRenderer::setCaretStyle
void setCaretStyle(KateRenderer::caretStyles style)
Set the style of caret to be painted.
Definition: katerenderer.cpp:82
KateRenderer::setShowIndentLines
void setShowIndentLines(bool showLines)
Set whether a guide should be painted to help identifying indent lines.
Definition: katerenderer.cpp:102
KateRenderer::updateAttributes
void updateAttributes()
update the highlighting attributes (for example after an hl change or after hl config changed)
Definition: katerenderer.cpp:63
KateRenderer::~KateRenderer
~KateRenderer()
Destructor.
Definition: katerenderer.cpp:57
KateRenderer::spaceWidth
uint spaceWidth()
Text width & height calculation functions...
Definition: katerenderer.cpp:1039
KateTextCursor
Simple cursor class with no document pointer.
Definition: katecursor.h:34
TDESharedPtr
TDEStdAccel::end
const TDEShortcut & end()

kate

Skip menu "kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kate

Skip menu "kate"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kate by doxygen 1.9.4
This website is maintained by Timothy Pearson.