• 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  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 
739 uint 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 
779 uint 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 
878 uint 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 
886 uint 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 
933 const TQFont *KateRenderer::currentFont()
934 {
935  return config()->font();
936 }
937 
938 const TQFontMetrics* KateRenderer::currentFontMetrics()
939 {
940  return config()->fontMetrics();
941 }
942 
943 uint KateRenderer::textPos(uint line, int xPos, uint startCol, bool nearest)
944 {
945  return textPos(m_doc->kateTextLine(line), xPos, startCol, nearest);
946 }
947 
948 uint 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 
979 uint KateRenderer::fontHeight()
980 {
981  return config()->fontStruct ()->fontHeight;
982 }
983 
984 uint KateRenderer::documentHeight()
985 {
986  return m_doc->numLines() * fontHeight();
987 }
988 
989 bool 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 
1030 void KateRenderer::updateConfig ()
1031 {
1032  // update the attibute list pointer
1033  updateAttributes ();
1034 
1035  if (m_view)
1036  m_view->updateRendererConfig();
1037 }
1038 
1039 uint KateRenderer::spaceWidth()
1040 {
1041  return attribute(0)->width(*config()->fontStruct(), TQChar(' '), m_tabWidth);
1042 }
KateTextCursor
Simple cursor class with no document pointer.
Definition: katecursor.h:33
KateRenderer::setShowSelections
void setShowSelections(bool showSelections)
Set whether the view&#39;s selections should be shown.
Definition: katerenderer.cpp:116
KateAttribute
The Attribute class incorporates all text decorations supported by Kate.
Definition: kateattribute.h:32
KateRenderer::textPos
uint textPos(uint line, int xPos, uint startCol=0, bool nearest=true)
Definition: katerenderer.cpp:943
KateRenderer::attribute
KateAttribute * attribute(uint pos)
This takes an in index, and returns all the attributes for it.
Definition: katerenderer.cpp:69
KateRenderer::showIndentLines
bool showIndentLines() const
Definition: katerenderer.cpp:97
KateRenderer::increaseFontSizes
void increaseFontSizes()
Change to a different font (soon to be font set?)
Definition: katerenderer.cpp:121
KateRenderer::showSelections
bool showSelections() const
Show the view&#39;s selection?
Definition: katerenderer.h:136
KateRenderer
Handles all of the work of rendering the text (used for the views and printing)
Definition: katerenderer.h:42
KateRenderer::setShowTabs
void setShowTabs(bool showTabs)
Set whether a mark should be painted to help identifying tabs.
Definition: katerenderer.cpp:87
KateRenderer::spaceWidth
uint spaceWidth()
Text width & height calculation functions...
Definition: katerenderer.cpp:1039
KateRenderer::setPrinterFriendly
void setPrinterFriendly(bool printerFriendly)
Configure this renderer to paint in a printer-friendly fashion.
Definition: katerenderer.cpp:144
KateRenderer::config
KateRendererConfig * config()
Configuration.
Definition: katerenderer.h:264
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::isPrinterFriendly
bool isPrinterFriendly() const
Definition: katerenderer.cpp:139
KateRenderer::setIndentWidth
void setIndentWidth(int indentWidth)
Sets the width of the tab.
Definition: katerenderer.cpp:107
KateRenderer::drawCaret
bool drawCaret() const
Determine whether the caret (text cursor) will be drawn.
Definition: katerenderer.h:75
KateRenderer::~KateRenderer
~KateRenderer()
Destructor.
Definition: katerenderer.cpp:57
KateRenderer::updateAttributes
void updateAttributes()
update the highlighting attributes (for example after an hl change or after hl config changed) ...
Definition: katerenderer.cpp:63
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::showTabs
bool showTabs() const
Definition: katerenderer.h:100
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::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::setDrawCaret
void setDrawCaret(bool drawCaret)
Set whether the caret (text cursor) will be drawn.
Definition: katerenderer.cpp:77
TDESharedPtr
KateRenderer::KateRenderer
KateRenderer(KateDocument *doc, KateView *view=0)
Constructor.
Definition: katerenderer.cpp:37
KateRenderer::caretStyle
KateRenderer::caretStyles caretStyle() const
The style of the caret (text cursor) to be painted.
Definition: katerenderer.h:87

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.8.13
This website is maintained by Timothy Pearson.