• 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 
37 KateRenderer::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 
57 KateRenderer::~KateRenderer()
58 {
59  delete m_config;
60  KateFactory::self()->deregisterRenderer ( this );
61 }
62 
63 void KateRenderer::updateAttributes ()
64 {
65  m_schema = config()->schema ();
66  m_attributes = m_doc->highlight()->attributes (m_schema);
67 }
68 
69 KateAttribute* 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 
77 void KateRenderer::setDrawCaret(bool drawCaret)
78 {
79  m_drawCaret = drawCaret;
80 }
81 
82 void KateRenderer::setCaretStyle(KateRenderer::caretStyles style)
83 {
84  m_caretStyle = style;
85 }
86 
87 void KateRenderer::setShowTabs(bool showTabs)
88 {
89  m_showTabs = showTabs;
90 }
91 
92 void KateRenderer::setTabWidth(int tabWidth)
93 {
94  m_tabWidth = tabWidth;
95 }
96 
97 bool KateRenderer::showIndentLines() const
98 {
99  return m_config->showIndentationLines();
100 }
101 
102 void KateRenderer::setShowIndentLines(bool showIndentLines)
103 {
104  m_config->setShowIndentationLines(showIndentLines);
105 }
106 
107 void 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 
116 void KateRenderer::setShowSelections(bool showSelections)
117 {
118  m_showSelections = showSelections;
119 }
120 
121 void KateRenderer::increaseFontSizes()
122 {
123  TQFont f ( *config()->font () );
124  f.setPointSize (f.pointSize ()+1);
125 
126  config()->setFont (f);
127 }
128 
129 void 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 
139 bool KateRenderer::isPrinterFriendly() const
140 {
141  return m_printerFriendly;
142 }
143 
144 void KateRenderer::setPrinterFriendly(bool printerFriendly)
145 {
146  m_printerFriendly = printerFriendly;
147  setShowTabs(false);
148  setShowSelections(false);
149  setDrawCaret(false);
150 }
151 
152 bool 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 
217 void 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 
228 void 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 
253 void 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  // make sure curPos is updated correctly.
425  // ### if uncommented, causes an O(n^2) behaviour
426  //Q_ASSERT(curPos == textLine->cursorX(curCol, m_tabWidth));
427 
428  TQChar curChar = textLine->string()[curCol];
429  // Decide if this character is a tab - we treat the spacing differently
430  // TODO: move tab width calculation elsewhere?
431  bool isTab = curChar == TQChar('\t');
432 
433  // Determine current syntax highlighting attribute
434  // A bit legacy but doesn't need to change
435  KateAttribute* curAt = (noAttribs || ((*textAttributes) >= atLen)) ? &attr[0] : &attr[*textAttributes];
436 
437  // X position calculation. Incorrect for fonts with non-zero leftBearing() and rightBearing() results.
438  // TODO: make internal charWidth() function, use TQFontMetrics::charWidth().
439  xPosAfter += curAt->width(*fs, curChar, m_tabWidth);
440 
441  // Tab special treatment, move to charWidth().
442  if (isTab)
443  xPosAfter -= (xPosAfter % curAt->width(*fs, curChar, m_tabWidth));
444 
445  // Only draw after the starting X value
446  // Haha, this was always wrong, due to the use of individual char width calculations...?? :(
447  if ((int)xPosAfter >= xStart)
448  {
449  // Determine if we're in a selection and should be drawing it
450  isSel = (showSelections() && hasSel && (curCol >= startSel) && (curCol < endSel));
451 
452  // input method edit area
453  isIMEdit = m_view && m_view->isIMEdit( line, curCol );
454 
455  // input method selection
456  isIMSel = m_view && m_view->isIMSelection( line, curCol );
457 
458  // Determine current color, taking into account selection
459  curColor = isSel ? &(curAt->selectedTextColor()) : &(curAt->textColor());
460 
461  // Incorporate in arbitrary highlighting
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));
465 
466  KateAttribute hl = customHL;
467 
468  hl += *curAt;
469 
470  // use default highlighting color if we haven't defined one above.
471  if (!hl.itemSet(KateAttribute::TextColor))
472  hl.setTextColor(*curColor);
473 
474  if (!isSel)
475  paint.setPen(hl.textColor());
476  else
477  paint.setPen(hl.selectedTextColor());
478 
479  paint.setFont(hl.font(*currentFont()));
480 
481  if (superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos)
482  superRanges.nextBoundary();
483 
484  currentHL = hl;
485  }
486 
487  // Determine whether we can delay painting to draw a block of similarly formatted
488  // characters or not
489  // Reasons for NOT delaying the drawing until the next character
490  // You have to detect the change one character in advance.
491  // TODO: KateAttribute::canBatchRender()
492  bool renderNow = false;
493  if ((isTab)
494  // formatting has changed OR
495  || (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == KateTextCursor(line, nextCol))
496 
497  // it is the end of the line OR
498  || (curCol - startcol >= len - 1)
499 
500  // the rest of the line is trailing whitespace OR
501  || (curCol + 1 >= trailingWhitespaceColumn)
502 
503  // indentation lines OR
504  || (showIndentLines() && curCol < lastIndentColumn)
505 
506  // the x position is past the end OR
507  || ((int)xPos > xEnd)
508 
509  // it is a different attribute OR
510  || (!noAttribs && curAt != &attr[*(textAttributes+1)])
511 
512  // the selection boundary was crossed OR
513  || (isSel != (hasSel && (nextCol >= startSel) && (nextCol < endSel)))
514 
515  // the next char is a tab (removed the "and this isn't" because that's dealt with above)
516  // i.e. we have to draw the current text so the tab can be rendered as above.
517  || (textLine->string()[nextCol] == TQChar('\t'))
518 
519  // input method edit area
520  || ( m_view && (isIMEdit != m_view->isIMEdit( line, nextCol )) )
521 
522  // input method selection
523  || ( m_view && (isIMSel != m_view->isIMSelection( line, nextCol )) )
524  )
525  {
526  renderNow = true;
527  }
528 
529  if (renderNow)
530  {
531  if (!isPrinterFriendly())
532  {
533  bool paintBackground = true;
534  uint width = xPosAfter - oldXPos;
535  TQColor fillColor;
536 
537  if (isIMSel && !isTab)
538  {
539  // input method selection
540  fillColor = m_view->colorGroup().color(TQColorGroup::Foreground);
541  }
542  else if (isIMEdit && !isTab)
543  {
544  // XIM support
545  // input method edit area
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 );
551  }
552  else if (!selectionPainted && (isSel || currentHL.itemSet(KateAttribute::BGColor)))
553  {
554  if (isSel)
555  {
556  fillColor = config()->selectionColor();
557 
558  // If this is the last block of text, fill up to the end of the line if the
559  // selection stretches that far
560  if ((curCol >= len - 1) && m_view->lineEndSelected (line, endcol))
561  width = xEnd - oldXPos;
562  }
563  else
564  {
565  fillColor = currentHL.bgColor();
566  }
567  }
568  else
569  {
570  paintBackground = false;
571  }
572 
573  if (paintBackground)
574  paint.fillRect(oldXPos - xStart, 0, width, fs->fontHeight, fillColor);
575 
576  if (isIMSel && paintBackground && !isTab)
577  {
578  paint.save();
579  paint.setPen( m_view->colorGroup().color( TQColorGroup::BrightText ) );
580  }
581 
582  // Draw indentation markers.
583  if (showIndentLines() && curCol < lastIndentColumn)
584  {
585  // Draw multiple guides when tab width greater than indent width.
586  const int charWidth = isTab ? m_tabWidth - curPos % m_tabWidth : 1;
587 
588  // Do not draw indent guides on the first line.
589  int i = 0;
590  if (curPos == 0 || curPos % m_indentWidth > 0)
591  i = m_indentWidth - curPos % m_indentWidth;
592 
593  for (; i < charWidth; i += m_indentWidth)
594  {
595  // In most cases this is done one or zero times.
596  paintIndentMarker(paint, xPos - xStart + i * spaceWidth, line);
597 
598  // Draw highlighted line.
599  if (curPos+i == minIndent)
600  {
601  paintIndentMarker(paint, xPos - xStart + 1 + i * spaceWidth, line+1);
602  }
603  }
604  }
605  }
606 
607  // or we will see no text ;)
608  int y = fs->fontAscent;
609 
610  // make sure we redraw the right character groups on attrib/selection changes
611  // Special case... de-special case some of it
612  if (isTab || (curCol >= trailingWhitespaceColumn))
613  {
614  // Draw spaces too, because it might be eg. underlined
615  static TQString spaces;
616  if (int(spaces.length()) != m_tabWidth)
617  spaces.fill(' ', m_tabWidth);
618 
619  paint.drawText(oldXPos-xStart, y, isTab ? spaces : TQString(" "));
620 
621  if (showTabs())
622  {
623  // trailing spaces and tabs may also have to be different options.
624  // if( curCol >= lastIndentColumn )
625  paintWhitespaceMarker(paint, xPos - xStart, y);
626  }
627 
628  // variable advancement
629  blockStartCol = nextCol;
630  oldXPos = xPosAfter;
631  }
632  else
633  {
634  // Here's where the money is...
635  paint.drawText(oldXPos-xStart, y, textLine->string(), blockStartCol, nextCol-blockStartCol);
636 
637  // Draw preedit's underline
638  if (isIMEdit) {
639  TQRect r( oldXPos - xStart, 0, xPosAfter - oldXPos, fs->fontHeight );
640  paint.drawLine( r.bottomLeft(), r.bottomRight() );
641  }
642 
643  // Put pen color back
644  if (isIMSel) paint.restore();
645 
646  // We're done drawing?
647  if ((int)xPos > xEnd)
648  break;
649 
650  // variable advancement
651  blockStartCol = nextCol;
652  oldXPos = xPosAfter;
653  //oldS = s+1;
654  }
655  } // renderNow
656 
657  // determine cursor X position
658  if (showCursor && (cursor->col() == int(curCol)))
659  {
660  cursorVisible = true;
661  cursorXPos = xPos;
662  cursorMaxWidth = xPosAfter - xPos;
663  cursorColor = &curAt->textColor();
664  }
665  } // xPosAfter >= xStart
666  else
667  {
668  // variable advancement
669  blockStartCol = nextCol;
670  oldXPos = xPosAfter;
671  }
672 
673  // increase xPos
674  xPos = xPosAfter;
675 
676  // increase attribs pos
677  textAttributes++;
678 
679  // to only switch font/color if needed
680  oldAt = curAt;
681  oldColor = curColor;
682 
683  // col move
684  curCol++;
685  nextCol++;
686  currentPos.setCol(currentPos.col() + 1);
687 
688  // Update the current indentation pos.
689  if (isTab)
690  {
691  curPos += m_tabWidth - (curPos % m_tabWidth);
692  }
693  else
694  {
695  curPos++;
696  }
697  }
698 
699  // If this line has a partial selection that's the start of a multi-line selection,
700  // we have to fill areas on the right side of the text with the selection color.
701  if (showSelections() && hasSel && !selectionPainted && xStart >= (int)xPos && m_view->lineEndSelected(line, -1))
702  {
703  paint.fillRect(0, 0, xEnd-xStart, fs->fontHeight, config()->selectionColor());
704  }
705 
706  // Determine cursor position (if it is not within the range being drawn)
707  if (showCursor && (cursor->col() >= int(curCol)))
708  {
709  cursorVisible = true;
710  cursorXPos = xPos + (cursor->col() - int(curCol)) * fs->myFontMetrics.width(TQChar(' '));
711  cursorMaxWidth = xPosAfter - xPos;
712  cursorColor = &oldAt->textColor();
713  }
714  }
715 
716  // Paint cursor
717  if (cursorVisible)
718  {
719  uint cursorWidth = (caretStyle() == Replace && (cursorMaxWidth > 2)) ? cursorMaxWidth : 2;
720  paint.fillRect(cursorXPos-xStart, 0, cursorWidth, fs->fontHeight, *cursorColor);
721  }
722 
723  // show word wrap marker if desirable
724  if (!isPrinterFriendly() && config()->wordWrapMarker() && fs->fixedPitch())
725  {
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 );
729  }
730 
731  // cleanup ;)
732  delete bracketStartRange;
733  delete bracketEndRange;
734 }
735 
736 uint KateRenderer::textWidth(const KateTextLine::Ptr &textLine, int cursorCol)
737 {
738  if (!textLine)
739  return 0;
740 
741  const int len = textLine->length();
742 
743  if (cursorCol < 0)
744  cursorCol = len;
745 
746  KateFontStruct *fs = config()->fontStruct();
747 
748  const TQChar *unicode = textLine->text();
749  const TQString &textString = textLine->string();
750 
751  int x = 0;
752  int width;
753  for (int z = 0; z < cursorCol; z++) {
754  KateAttribute* a = attribute(textLine->attribute(z));
755 
756  if (z < len) {
757  width = a->width(*fs, textString, z, m_tabWidth);
758  } else {
759  // DF: commented out. It happens all the time.
760  //Q_ASSERT(!m_doc->wrapCursor());
761  width = a->width(*fs, TQChar(' '), m_tabWidth);
762  }
763 
764  x += width;
765 
766  if (z < len && unicode[z] == TQChar('\t'))
767  x -= x % width;
768  }
769 
770  return x;
771 }
772 
773 uint KateRenderer::textWidth(const KateTextLine::Ptr &textLine, uint startcol, uint maxwidth, bool *needWrap, int *endX)
774 {
775  KateFontStruct *fs = config()->fontStruct();
776  uint x = 0;
777  uint endcol = startcol;
778  int endX2 = 0;
779  int lastWhiteSpace = -1;
780  int lastWhiteSpaceX = -1;
781 
782  // used to not wrap a solitary word off the first line, ie. the
783  // first line should not wrap until some characters have been displayed if possible
784  bool foundNonWhitespace = startcol != 0;
785  bool foundWhitespaceAfterNonWhitespace = startcol != 0;
786 
787  *needWrap = false;
788 
789  const uint len = textLine->length();
790  const TQChar *unicode = textLine->text();
791  const TQString &textString = textLine->string();
792 
793  uint z = startcol;
794  for (; z < len; z++)
795  {
796  KateAttribute* a = attribute(textLine->attribute(z));
797  int width = a->width(*fs, textString, z, m_tabWidth);
798  Q_ASSERT(width);
799  x += width;
800 
801  // How should tabs be treated when they word-wrap on a print-out?
802  // if startcol != 0, this messes up (then again, word wrapping messes up anyway)
803  if (unicode[z] == TQChar('\t'))
804  x -= x % width;
805 
806  if (unicode[z].isSpace())
807  {
808  lastWhiteSpace = z+1;
809  lastWhiteSpaceX = x;
810 
811  if (foundNonWhitespace)
812  foundWhitespaceAfterNonWhitespace = true;
813  }
814  else
815  {
816  if (!foundWhitespaceAfterNonWhitespace) {
817  foundNonWhitespace = true;
818 
819  lastWhiteSpace = z+1;
820  lastWhiteSpaceX = x;
821  }
822  }
823 
824  if (x <= maxwidth)
825  {
826  if (lastWhiteSpace > -1)
827  {
828  endcol = lastWhiteSpace;
829  endX2 = lastWhiteSpaceX;
830  }
831  else
832  {
833  endcol = z+1;
834  endX2 = x;
835  }
836  }
837  else if (z == startcol)
838  {
839  // require a minimum of 1 character advancement per call, even if it means drawing gets cut off
840  // (geez gideon causes troubles with starting the views very small)
841  endcol = z+1;
842  endX2 = x;
843  }
844 
845  if (x >= maxwidth)
846  {
847  *needWrap = true;
848  break;
849  }
850  }
851 
852  if (*needWrap)
853  {
854  if (endX)
855  *endX = endX2;
856 
857  return endcol;
858  }
859  else
860  {
861  if (endX)
862  *endX = x;
863 
864  return z+1;
865  }
866 }
867 
868 uint KateRenderer::textWidth(const KateTextCursor &cursor)
869 {
870  int line = kMin(kMax(0, cursor.line()), (int)m_doc->numLines() - 1);
871  int col = kMax(0, cursor.col());
872 
873  return textWidth(m_doc->kateTextLine(line), col);
874 }
875 
876 uint KateRenderer::textWidth( KateTextCursor &cursor, int xPos, uint startCol)
877 {
878  bool wrapCursor = m_view->wrapCursor();
879  int x, oldX;
880 
881  KateFontStruct *fs = config()->fontStruct();
882 
883  if (cursor.line() < 0) cursor.setLine(0);
884  if (cursor.line() > (int)m_doc->lastLine()) cursor.setLine(m_doc->lastLine());
885  KateTextLine::Ptr textLine = m_doc->kateTextLine(cursor.line());
886 
887  if (!textLine) return 0;
888 
889  const uint len = textLine->length();
890  const TQChar *unicode = textLine->text();
891  const TQString &textString = textLine->string();
892 
893  x = oldX = 0;
894  uint z = startCol;
895  while (x < xPos && (!wrapCursor || z < len)) {
896  oldX = x;
897 
898  KateAttribute* a = attribute(textLine->attribute(z));
899 
900  int width = 0;
901 
902  if (z < len)
903  width = a->width(*fs, textString, z, m_tabWidth);
904  else
905  width = a->width(*fs, TQChar(' '), m_tabWidth);
906 
907  x += width;
908 
909  if (z < len && unicode[z] == TQChar('\t'))
910  x -= x % width;
911 
912  z++;
913  }
914  if (xPos - oldX < x - xPos && z > 0) {
915  z--;
916  x = oldX;
917  }
918  cursor.setCol(z);
919  return x;
920 }
921 
922 const TQFont *KateRenderer::currentFont()
923 {
924  return config()->font();
925 }
926 
927 const TQFontMetrics* KateRenderer::currentFontMetrics()
928 {
929  return config()->fontMetrics();
930 }
931 
932 uint KateRenderer::textPos(uint line, int xPos, uint startCol, bool nearest)
933 {
934  return textPos(m_doc->kateTextLine(line), xPos, startCol, nearest);
935 }
936 
937 uint KateRenderer::textPos(const KateTextLine::Ptr &textLine, int xPos, uint startCol, bool nearest)
938 {
939  Q_ASSERT(textLine);
940  if (!textLine)
941  return 0;
942 
943  KateFontStruct *fs = config()->fontStruct();
944 
945  int x, oldX;
946  x = oldX = 0;
947 
948  uint z = startCol;
949  const uint len = textLine->length();
950  const TQString &textString = textLine->string();
951 
952  while ( (x < xPos) && (z < len)) {
953  oldX = x;
954 
955  KateAttribute* a = attribute(textLine->attribute(z));
956  x += a->width(*fs, textString, z, m_tabWidth);
957 
958  z++;
959  }
960  if ( ( (! nearest) || xPos - oldX < x - xPos ) && z > 0 ) {
961  z--;
962  // newXPos = oldX;
963  }// else newXPos = x;
964  return z;
965 }
966 
967 uint KateRenderer::fontHeight()
968 {
969  return config()->fontStruct ()->fontHeight;
970 }
971 
972 uint KateRenderer::documentHeight()
973 {
974  return m_doc->numLines() * fontHeight();
975 }
976 
977 bool KateRenderer::getSelectionBounds(uint line, uint lineLength, uint &start, uint &end)
978 {
979  bool hasSel = false;
980 
981  if (m_view->hasSelection() && !m_view->blockSelectionMode())
982  {
983  if (m_view->lineIsSelection(line))
984  {
985  start = m_view->selStartCol();
986  end = m_view->selEndCol();
987  hasSel = true;
988  }
989  else if ((int)line == m_view->selStartLine())
990  {
991  start = m_view->selStartCol();
992  end = lineLength;
993  hasSel = true;
994  }
995  else if ((int)line == m_view->selEndLine())
996  {
997  start = 0;
998  end = m_view->selEndCol();
999  hasSel = true;
1000  }
1001  }
1002  else if (m_view->lineHasSelected(line))
1003  {
1004  start = m_view->selStartCol();
1005  end = m_view->selEndCol();
1006  hasSel = true;
1007  }
1008 
1009  if (start > end) {
1010  int temp = end;
1011  end = start;
1012  start = temp;
1013  }
1014 
1015  return hasSel;
1016 }
1017 
1018 void KateRenderer::updateConfig ()
1019 {
1020  // update the attibute list pointer
1021  updateAttributes ();
1022 
1023  if (m_view)
1024  m_view->updateRendererConfig();
1025 }
1026 
1027 uint KateRenderer::spaceWidth()
1028 {
1029  return attribute(0)->width(*config()->fontStruct(), TQChar(' '), m_tabWidth);
1030 }
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::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:932
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::config
KateRendererConfig * config()
Configuration.
Definition: katerenderer.h:264
KateRenderer::spaceWidth
uint spaceWidth()
Text width & height calculation functions...
Definition: katerenderer.cpp:1027
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.1
This website is maintained by Timothy Pearson.