• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • applications API Reference
  • KDE Home
  • Contact Us
 

Konsole

  • kde-4.14
  • applications
  • konsole
  • src
TerminalDisplay.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Konsole, a terminal emulator for KDE.
3 
4  Copyright 2006-2008 by Robert Knight <robertknight@gmail.com>
5  Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  02110-1301 USA.
21 */
22 
23 // Own
24 #include "TerminalDisplay.h"
25 
26 // Config
27 #include <config-konsole.h>
28 
29 // Qt
30 #include <QApplication>
31 #include <QtGui/QClipboard>
32 #include <QtGui/QKeyEvent>
33 #include <QtCore/QEvent>
34 #include <QtCore/QFileInfo>
35 #include <QGridLayout>
36 #include <QAction>
37 #include <QLabel>
38 #include <QtGui/QPainter>
39 #include <QtGui/QPixmap>
40 #include <QScrollBar>
41 #include <QStyle>
42 #include <QtCore/QTimer>
43 #include <QToolTip>
44 #include <QtGui/QAccessible>
45 
46 // KDE
47 #include <KShell>
48 #include <KColorScheme>
49 #include <KCursor>
50 #include <KDebug>
51 #include <KLocalizedString>
52 #include <KNotification>
53 #include <KGlobalSettings>
54 #include <KIO/NetAccess>
55 #if defined(HAVE_LIBKONQ)
56  #include <konq_operations.h>
57 #endif
58 
59 #include <KFileItem>
60 #include <KMessageBox>
61 
62 // Konsole
63 #include "Filter.h"
64 #include "konsole_wcwidth.h"
65 #include "TerminalCharacterDecoder.h"
66 #include "Screen.h"
67 #include "ScreenWindow.h"
68 #include "LineFont.h"
69 #include "SessionController.h"
70 #include "ExtendedCharTable.h"
71 #include "TerminalDisplayAccessible.h"
72 #include "SessionManager.h"
73 #include "Session.h"
74 
75 using namespace Konsole;
76 
77 #ifndef loc
78 #define loc(X,Y) ((Y)*_columns+(X))
79 #endif
80 
81 #define REPCHAR "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
82  "abcdefgjijklmnopqrstuvwxyz" \
83  "0123456789./+@"
84 
85 // we use this to force QPainter to display text in LTR mode
86 // more information can be found in: http://unicode.org/reports/tr9/
87 const QChar LTR_OVERRIDE_CHAR(0x202D);
88 
89 /* ------------------------------------------------------------------------- */
90 /* */
91 /* Colors */
92 /* */
93 /* ------------------------------------------------------------------------- */
94 
95 /* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb)
96 
97  Code 0 1 2 3 4 5 6 7
98  ----------- ------- ------- ------- ------- ------- ------- ------- -------
99  ANSI (bgr) Black Red Green Yellow Blue Magenta Cyan White
100  IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White
101 */
102 
103 ScreenWindow* TerminalDisplay::screenWindow() const
104 {
105  return _screenWindow;
106 }
107 void TerminalDisplay::setScreenWindow(ScreenWindow* window)
108 {
109  // disconnect existing screen window if any
110  if (_screenWindow) {
111  disconnect(_screenWindow , 0 , this , 0);
112  }
113 
114  _screenWindow = window;
115 
116  if (_screenWindow) {
117  connect(_screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties()));
118  connect(_screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage()));
119  connect(_screenWindow , SIGNAL(currentResultLineChanged()) , this , SLOT(updateImage()));
120  _screenWindow->setWindowLines(_lines);
121  }
122 }
123 
124 const ColorEntry* TerminalDisplay::colorTable() const
125 {
126  return _colorTable;
127 }
128 void TerminalDisplay::setBackgroundColor(const QColor& color)
129 {
130  _colorTable[DEFAULT_BACK_COLOR].color = color;
131 
132  QPalette p = palette();
133  p.setColor(backgroundRole(), color);
134  setPalette(p);
135 
136  // Avoid propagating the palette change to the scroll bar
137  _scrollBar->setPalette(QApplication::palette());
138 
139  update();
140 }
141 QColor TerminalDisplay::getBackgroundColor() const
142 {
143  QPalette p = palette();
144  return p.color(backgroundRole());
145 }
146 void TerminalDisplay::setForegroundColor(const QColor& color)
147 {
148  _colorTable[DEFAULT_FORE_COLOR].color = color;
149 
150  update();
151 }
152 void TerminalDisplay::setColorTable(const ColorEntry table[])
153 {
154  for (int i = 0; i < TABLE_COLORS; i++)
155  _colorTable[i] = table[i];
156 
157  setBackgroundColor(_colorTable[DEFAULT_BACK_COLOR].color);
158 }
159 
160 /* ------------------------------------------------------------------------- */
161 /* */
162 /* Font */
163 /* */
164 /* ------------------------------------------------------------------------- */
165 
166 static inline bool isLineCharString(const QString& string)
167 {
168  if (string.length() == 0)
169  return false;
170 
171  return isSupportedLineChar(string.at(0).unicode());
172 }
173 
174 void TerminalDisplay::fontChange(const QFont&)
175 {
176  QFontMetrics fm(font());
177  _fontHeight = fm.height() + _lineSpacing;
178 
179  // waba TerminalDisplay 1.123:
180  // "Base character width on widest ASCII character. This prevents too wide
181  // characters in the presence of double wide (e.g. Japanese) characters."
182  // Get the width from representative normal width characters
183  _fontWidth = qRound((static_cast<double>(fm.width(REPCHAR)) / static_cast<double>(qstrlen(REPCHAR))));
184 
185  _fixedFont = true;
186 
187  const int fw = fm.width(REPCHAR[0]);
188  for (unsigned int i = 1; i < qstrlen(REPCHAR); i++) {
189  if (fw != fm.width(REPCHAR[i])) {
190  _fixedFont = false;
191  break;
192  }
193  }
194 
195  if (_fontWidth < 1)
196  _fontWidth = 1;
197 
198  _fontAscent = fm.ascent();
199 
200  emit changedFontMetricSignal(_fontHeight, _fontWidth);
201  propagateSize();
202  update();
203 }
204 
205 void TerminalDisplay::setVTFont(const QFont& f)
206 {
207  QFont font = f;
208 
209  QFontMetrics metrics(font);
210 
211  if (!QFontInfo(font).fixedPitch()) {
212  kWarning() << "Using an unsupported variable-width font in the terminal. This may produce display errors.";
213  }
214 
215  if (metrics.height() < height() && metrics.maxWidth() < width()) {
216  // hint that text should be drawn without anti-aliasing.
217  // depending on the user's font configuration, this may not be respected
218  if (!_antialiasText)
219  font.setStyleStrategy(QFont::NoAntialias);
220 
221  // experimental optimization. Konsole assumes that the terminal is using a
222  // mono-spaced font, in which case kerning information should have an effect.
223  // Disabling kerning saves some computation when rendering text.
224  font.setKerning(false);
225 
226  // Konsole cannot handle non-integer font metrics
227  font.setStyleStrategy(QFont::StyleStrategy(font.styleStrategy() | QFont::ForceIntegerMetrics));
228 
229  QWidget::setFont(font);
230  fontChange(font);
231  }
232 }
233 
234 void TerminalDisplay::setFont(const QFont &)
235 {
236  // ignore font change request if not coming from konsole itself
237 }
238 
239 void TerminalDisplay::increaseFontSize()
240 {
241  QFont font = getVTFont();
242  font.setPointSizeF(font.pointSizeF() + 1);
243  setVTFont(font);
244 }
245 
246 void TerminalDisplay::decreaseFontSize()
247 {
248  const qreal MinimumFontSize = 6;
249 
250  QFont font = getVTFont();
251  font.setPointSizeF(qMax(font.pointSizeF() - 1, MinimumFontSize));
252  setVTFont(font);
253 }
254 
255 uint TerminalDisplay::lineSpacing() const
256 {
257  return _lineSpacing;
258 }
259 
260 void TerminalDisplay::setLineSpacing(uint i)
261 {
262  _lineSpacing = i;
263  setVTFont(font()); // Trigger an update.
264 }
265 
266 
267 /* ------------------------------------------------------------------------- */
268 /* */
269 /* Accessibility */
270 /* */
271 /* ------------------------------------------------------------------------- */
272 
273 namespace Konsole
274 {
279 QAccessibleInterface* accessibleInterfaceFactory(const QString &key, QObject *object)
280 {
281  Q_UNUSED(key)
282  if (TerminalDisplay *display = qobject_cast<TerminalDisplay*>(object))
283  return new TerminalDisplayAccessible(display);
284  return 0;
285 }
286 }
287 
288 /* ------------------------------------------------------------------------- */
289 /* */
290 /* Constructor / Destructor */
291 /* */
292 /* ------------------------------------------------------------------------- */
293 
294 TerminalDisplay::TerminalDisplay(QWidget* parent)
295  : QWidget(parent)
296  , _screenWindow(0)
297  , _bellMasked(false)
298  , _gridLayout(0)
299  , _fontHeight(1)
300  , _fontWidth(1)
301  , _fontAscent(1)
302  , _boldIntense(true)
303  , _lines(1)
304  , _columns(1)
305  , _usedLines(1)
306  , _usedColumns(1)
307  , _image(0)
308  , _randomSeed(0)
309  , _resizing(false)
310  , _showTerminalSizeHint(true)
311  , _bidiEnabled(false)
312  , _actSel(0)
313  , _wordSelectionMode(false)
314  , _lineSelectionMode(false)
315  , _preserveLineBreaks(false)
316  , _columnSelectionMode(false)
317  , _autoCopySelectedText(false)
318  , _middleClickPasteMode(Enum::PasteFromX11Selection)
319  , _scrollbarLocation(Enum::ScrollBarRight)
320  , _scrollFullPage(false)
321  , _wordCharacters(":@-./_~")
322  , _bellMode(Enum::NotifyBell)
323  , _allowBlinkingText(true)
324  , _allowBlinkingCursor(false)
325  , _textBlinking(false)
326  , _cursorBlinking(false)
327  , _hasTextBlinker(false)
328  , _underlineLinks(true)
329  , _openLinksByDirectClick(false)
330  , _ctrlRequiredForDrag(true)
331  , _tripleClickMode(Enum::SelectWholeLine)
332  , _possibleTripleClick(false)
333  , _resizeWidget(0)
334  , _resizeTimer(0)
335  , _flowControlWarningEnabled(false)
336  , _outputSuspendedLabel(0)
337  , _lineSpacing(0)
338  , _blendColor(qRgba(0, 0, 0, 0xff))
339  , _filterChain(new TerminalImageFilterChain())
340  , _cursorShape(Enum::BlockCursor)
341  , _antialiasText(true)
342  , _printerFriendly(false)
343  , _sessionController(0)
344  , _trimTrailingSpaces(false)
345  , _margin(1)
346  , _centerContents(false)
347  , _opacity(1.0)
348 {
349  // terminal applications are not designed with Right-To-Left in mind,
350  // so the layout is forced to Left-To-Right
351  setLayoutDirection(Qt::LeftToRight);
352 
353  _contentRect = QRect(_margin, _margin, 1, 1);
354 
355  // create scroll bar for scrolling output up and down
356  _scrollBar = new QScrollBar(this);
357  // set the scroll bar's slider to occupy the whole area of the scroll bar initially
358  setScroll(0, 0);
359  _scrollBar->setCursor(Qt::ArrowCursor);
360  connect(_scrollBar, SIGNAL(valueChanged(int)),
361  this, SLOT(scrollBarPositionChanged(int)));
362  connect(_scrollBar, SIGNAL(sliderMoved(int)),
363  this, SLOT(viewScrolledByUser()));
364 
365  // setup timers for blinking text
366  _blinkTextTimer = new QTimer(this);
367  _blinkTextTimer->setInterval(TEXT_BLINK_DELAY);
368  connect(_blinkTextTimer, SIGNAL(timeout()), this, SLOT(blinkTextEvent()));
369 
370  // setup timers for blinking cursor
371  _blinkCursorTimer = new QTimer(this);
372  _blinkCursorTimer->setInterval(QApplication::cursorFlashTime() / 2);
373  connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent()));
374 
375  // hide mouse cursor on keystroke or idle
376  KCursor::setAutoHideCursor(this, true);
377  setMouseTracking(true);
378 
379  setUsesMouse(true);
380  setBracketedPasteMode(false);
381 
382  setColorTable(ColorScheme::defaultTable);
383 
384  // Enable drag and drop support
385  setAcceptDrops(true);
386  _dragInfo.state = diNone;
387 
388  setFocusPolicy(Qt::WheelFocus);
389 
390  // enable input method support
391  setAttribute(Qt::WA_InputMethodEnabled, true);
392 
393  // this is an important optimization, it tells Qt
394  // that TerminalDisplay will handle repainting its entire area.
395  setAttribute(Qt::WA_OpaquePaintEvent);
396 
397  _gridLayout = new QGridLayout(this);
398  _gridLayout->setContentsMargins(0, 0, 0, 0);
399 
400  setLayout(_gridLayout);
401 
402  new AutoScrollHandler(this);
403 
404 
405 #ifndef QT_NO_ACCESSIBILITY
406  QAccessible::installFactory(Konsole::accessibleInterfaceFactory);
407 #endif
408 }
409 
410 TerminalDisplay::~TerminalDisplay()
411 {
412  disconnect(_blinkTextTimer);
413  disconnect(_blinkCursorTimer);
414 
415  delete[] _image;
416 
417  delete _gridLayout;
418  delete _outputSuspendedLabel;
419  delete _filterChain;
420 }
421 
422 /* ------------------------------------------------------------------------- */
423 /* */
424 /* Display Operations */
425 /* */
426 /* ------------------------------------------------------------------------- */
427 
446 enum LineEncode {
447  TopL = (1 << 1),
448  TopC = (1 << 2),
449  TopR = (1 << 3),
450 
451  LeftT = (1 << 5),
452  Int11 = (1 << 6),
453  Int12 = (1 << 7),
454  Int13 = (1 << 8),
455  RightT = (1 << 9),
456 
457  LeftC = (1 << 10),
458  Int21 = (1 << 11),
459  Int22 = (1 << 12),
460  Int23 = (1 << 13),
461  RightC = (1 << 14),
462 
463  LeftB = (1 << 15),
464  Int31 = (1 << 16),
465  Int32 = (1 << 17),
466  Int33 = (1 << 18),
467  RightB = (1 << 19),
468 
469  BotL = (1 << 21),
470  BotC = (1 << 22),
471  BotR = (1 << 23)
472 };
473 
474 static void drawLineChar(QPainter& paint, int x, int y, int w, int h, uchar code)
475 {
476  //Calculate cell midpoints, end points.
477  const int cx = x + w / 2;
478  const int cy = y + h / 2;
479  const int ex = x + w - 1;
480  const int ey = y + h - 1;
481 
482  const quint32 toDraw = LineChars[code];
483 
484  //Top _lines:
485  if (toDraw & TopL)
486  paint.drawLine(cx - 1, y, cx - 1, cy - 2);
487  if (toDraw & TopC)
488  paint.drawLine(cx, y, cx, cy - 2);
489  if (toDraw & TopR)
490  paint.drawLine(cx + 1, y, cx + 1, cy - 2);
491 
492  //Bot _lines:
493  if (toDraw & BotL)
494  paint.drawLine(cx - 1, cy + 2, cx - 1, ey);
495  if (toDraw & BotC)
496  paint.drawLine(cx, cy + 2, cx, ey);
497  if (toDraw & BotR)
498  paint.drawLine(cx + 1, cy + 2, cx + 1, ey);
499 
500  //Left _lines:
501  if (toDraw & LeftT)
502  paint.drawLine(x, cy - 1, cx - 2, cy - 1);
503  if (toDraw & LeftC)
504  paint.drawLine(x, cy, cx - 2, cy);
505  if (toDraw & LeftB)
506  paint.drawLine(x, cy + 1, cx - 2, cy + 1);
507 
508  //Right _lines:
509  if (toDraw & RightT)
510  paint.drawLine(cx + 2, cy - 1, ex, cy - 1);
511  if (toDraw & RightC)
512  paint.drawLine(cx + 2, cy, ex, cy);
513  if (toDraw & RightB)
514  paint.drawLine(cx + 2, cy + 1, ex, cy + 1);
515 
516  //Intersection points.
517  if (toDraw & Int11)
518  paint.drawPoint(cx - 1, cy - 1);
519  if (toDraw & Int12)
520  paint.drawPoint(cx, cy - 1);
521  if (toDraw & Int13)
522  paint.drawPoint(cx + 1, cy - 1);
523 
524  if (toDraw & Int21)
525  paint.drawPoint(cx - 1, cy);
526  if (toDraw & Int22)
527  paint.drawPoint(cx, cy);
528  if (toDraw & Int23)
529  paint.drawPoint(cx + 1, cy);
530 
531  if (toDraw & Int31)
532  paint.drawPoint(cx - 1, cy + 1);
533  if (toDraw & Int32)
534  paint.drawPoint(cx, cy + 1);
535  if (toDraw & Int33)
536  paint.drawPoint(cx + 1, cy + 1);
537 }
538 
539 void TerminalDisplay::drawLineCharString(QPainter& painter, int x, int y, const QString& str,
540  const Character* attributes)
541 {
542  const QPen& originalPen = painter.pen();
543 
544  if ((attributes->rendition & RE_BOLD) && _boldIntense) {
545  QPen boldPen(originalPen);
546  boldPen.setWidth(3);
547  painter.setPen(boldPen);
548  }
549 
550  for (int i = 0 ; i < str.length(); i++) {
551  const uchar code = str[i].cell();
552  if (LineChars[code])
553  drawLineChar(painter, x + (_fontWidth * i), y, _fontWidth, _fontHeight, code);
554  }
555 
556  painter.setPen(originalPen);
557 }
558 
559 void TerminalDisplay::setKeyboardCursorShape(Enum::CursorShapeEnum shape)
560 {
561  _cursorShape = shape;
562 }
563 Enum::CursorShapeEnum TerminalDisplay::keyboardCursorShape() const
564 {
565  return _cursorShape;
566 }
567 void TerminalDisplay::setKeyboardCursorColor(const QColor& color)
568 {
569  _cursorColor = color;
570 }
571 QColor TerminalDisplay::keyboardCursorColor() const
572 {
573  return _cursorColor;
574 }
575 
576 void TerminalDisplay::setOpacity(qreal opacity)
577 {
578  QColor color(_blendColor);
579  color.setAlphaF(opacity);
580  _opacity = opacity;
581 
582  // enable automatic background filling to prevent the display
583  // flickering if there is no transparency
584  /*if ( color.alpha() == 255 )
585  {
586  setAutoFillBackground(true);
587  }
588  else
589  {
590  setAutoFillBackground(false);
591  }*/
592 
593  _blendColor = color.rgba();
594 }
595 
596 void TerminalDisplay::setWallpaper(ColorSchemeWallpaper::Ptr p)
597 {
598  _wallpaper = p;
599 }
600 
601 void TerminalDisplay::drawBackground(QPainter& painter, const QRect& rect, const QColor& backgroundColor, bool useOpacitySetting)
602 {
603  // the area of the widget showing the contents of the terminal display is drawn
604  // using the background color from the color scheme set with setColorTable()
605  //
606  // the area of the widget behind the scroll-bar is drawn using the background
607  // brush from the scroll-bar's palette, to give the effect of the scroll-bar
608  // being outside of the terminal display and visual consistency with other KDE
609  // applications.
610  //
611  QRect scrollBarArea = _scrollBar->isVisible() ?
612  rect.intersected(_scrollBar->geometry()) :
613  QRect();
614  QRegion contentsRegion = QRegion(rect).subtracted(scrollBarArea);
615  QRect contentsRect = contentsRegion.boundingRect();
616 
617  if (useOpacitySetting && !_wallpaper->isNull() &&
618  _wallpaper->draw(painter, contentsRect, _opacity)) {
619  } else if (qAlpha(_blendColor) < 0xff && useOpacitySetting) {
620 #if defined(Q_OS_MAC)
621  // TODO - On MacOS, using CompositionMode doesn't work. Altering the
622  // transparency in the color scheme alters the brightness.
623  painter.fillRect(contentsRect, backgroundColor);
624 #else
625  QColor color(backgroundColor);
626  color.setAlpha(qAlpha(_blendColor));
627 
628  painter.save();
629  painter.setCompositionMode(QPainter::CompositionMode_Source);
630  painter.fillRect(contentsRect, color);
631  painter.restore();
632 #endif
633  } else {
634  painter.fillRect(contentsRect, backgroundColor);
635  }
636 
637  painter.fillRect(scrollBarArea, _scrollBar->palette().background());
638 }
639 
640 void TerminalDisplay::drawCursor(QPainter& painter,
641  const QRect& rect,
642  const QColor& foregroundColor,
643  const QColor& /*backgroundColor*/,
644  bool& invertCharacterColor)
645 {
646  // don't draw cursor which is currently blinking
647  if (_cursorBlinking)
648  return;
649 
650  QRect cursorRect = rect;
651  cursorRect.setHeight(_fontHeight - _lineSpacing - 1);
652 
653  QColor cursorColor = _cursorColor.isValid() ? _cursorColor : foregroundColor;
654  painter.setPen(cursorColor);
655 
656  if (_cursorShape == Enum::BlockCursor) {
657  // draw the cursor outline, adjusting the area so that
658  // it is draw entirely inside 'rect'
659  int penWidth = qMax(1, painter.pen().width());
660  painter.drawRect(cursorRect.adjusted(penWidth / 2,
661  penWidth / 2,
662  - penWidth / 2 - penWidth % 2,
663  - penWidth / 2 - penWidth % 2));
664 
665  // draw the cursor body only when the widget has focus
666  if (hasFocus()) {
667  painter.fillRect(cursorRect, cursorColor);
668 
669  if (!_cursorColor.isValid()) {
670  // invert the color used to draw the text to ensure that the character at
671  // the cursor position is readable
672  invertCharacterColor = true;
673  }
674  }
675  } else if (_cursorShape == Enum::UnderlineCursor) {
676  painter.drawLine(cursorRect.left(),
677  cursorRect.bottom(),
678  cursorRect.right(),
679  cursorRect.bottom());
680 
681  } else if (_cursorShape == Enum::IBeamCursor) {
682  painter.drawLine(cursorRect.left(),
683  cursorRect.top(),
684  cursorRect.left(),
685  cursorRect.bottom());
686  }
687 }
688 
689 void TerminalDisplay::drawCharacters(QPainter& painter,
690  const QRect& rect,
691  const QString& text,
692  const Character* style,
693  bool invertCharacterColor)
694 {
695  // don't draw text which is currently blinking
696  if (_textBlinking && (style->rendition & RE_BLINK))
697  return;
698 
699  // setup bold and underline
700  bool useBold;
701  ColorEntry::FontWeight weight = style->fontWeight(_colorTable);
702  if (weight == ColorEntry::UseCurrentFormat)
703  useBold = ((style->rendition & RE_BOLD) && _boldIntense) || font().bold();
704  else
705  useBold = (weight == ColorEntry::Bold) ? true : false;
706  const bool useUnderline = style->rendition & RE_UNDERLINE || font().underline();
707  const bool useItalic = style->rendition & RE_ITALIC || font().italic();
708 
709  QFont font = painter.font();
710  if (font.bold() != useBold
711  || font.underline() != useUnderline
712  || font.italic() != useItalic) {
713  font.setBold(useBold);
714  font.setUnderline(useUnderline);
715  font.setItalic(useItalic);
716  painter.setFont(font);
717  }
718 
719  // setup pen
720  const CharacterColor& textColor = (invertCharacterColor ? style->backgroundColor : style->foregroundColor);
721  const QColor color = textColor.color(_colorTable);
722  QPen pen = painter.pen();
723  if (pen.color() != color) {
724  pen.setColor(color);
725  painter.setPen(color);
726  }
727 
728  // draw text
729  if (isLineCharString(text)) {
730  drawLineCharString(painter, rect.x(), rect.y(), text, style);
731  } else {
732  // Force using LTR as the document layout for the terminal area, because
733  // there is no use cases for RTL emulator and RTL terminal application.
734  //
735  // This still allows RTL characters to be rendered in the RTL way.
736  painter.setLayoutDirection(Qt::LeftToRight);
737 
738  // the drawText(rect,flags,string) overload is used here with null flags
739  // instead of drawText(rect,string) because the (rect,string) overload causes
740  // the application's default layout direction to be used instead of
741  // the widget-specific layout direction, which should always be
742  // Qt::LeftToRight for this widget
743  //
744  // This was discussed in: http://lists.kde.org/?t=120552223600002&r=1&w=2
745  if (_bidiEnabled) {
746  painter.drawText(rect, 0, text);
747  } else {
748  // See bug 280896 for more info
749 #if QT_VERSION >= 0x040800
750  painter.drawText(rect, Qt::AlignBottom, LTR_OVERRIDE_CHAR + text);
751 #else
752  painter.drawText(rect, 0, LTR_OVERRIDE_CHAR + text);
753 #endif
754  }
755  }
756 }
757 
758 void TerminalDisplay::drawTextFragment(QPainter& painter ,
759  const QRect& rect,
760  const QString& text,
761  const Character* style)
762 {
763  painter.save();
764 
765  // setup painter
766  const QColor foregroundColor = style->foregroundColor.color(_colorTable);
767  const QColor backgroundColor = style->backgroundColor.color(_colorTable);
768 
769  // draw background if different from the display's background color
770  if (backgroundColor != palette().background().color())
771  drawBackground(painter, rect, backgroundColor,
772  false /* do not use transparency */);
773 
774  // draw cursor shape if the current character is the cursor
775  // this may alter the foreground and background colors
776  bool invertCharacterColor = false;
777  if (style->rendition & RE_CURSOR)
778  drawCursor(painter, rect, foregroundColor, backgroundColor, invertCharacterColor);
779 
780  // draw text
781  drawCharacters(painter, rect, text, style, invertCharacterColor);
782 
783  painter.restore();
784 }
785 
786 void TerminalDisplay::drawPrinterFriendlyTextFragment(QPainter& painter,
787  const QRect& rect,
788  const QString& text,
789  const Character* style)
790 {
791  painter.save();
792 
793  // Set the colors used to draw to black foreground and white
794  // background for printer friendly output when printing
795  Character print_style = *style;
796  print_style.foregroundColor = CharacterColor(COLOR_SPACE_RGB, 0x00000000);
797  print_style.backgroundColor = CharacterColor(COLOR_SPACE_RGB, 0xFFFFFFFF);
798 
799  // draw text
800  drawCharacters(painter, rect, text, &print_style, false);
801 
802  painter.restore();
803 }
804 
805 void TerminalDisplay::setRandomSeed(uint randomSeed)
806 {
807  _randomSeed = randomSeed;
808 }
809 uint TerminalDisplay::randomSeed() const
810 {
811  return _randomSeed;
812 }
813 
814 // scrolls the image by 'lines', down if lines > 0 or up otherwise.
815 //
816 // the terminal emulation keeps track of the scrolling of the character
817 // image as it receives input, and when the view is updated, it calls scrollImage()
818 // with the final scroll amount. this improves performance because scrolling the
819 // display is much cheaper than re-rendering all the text for the
820 // part of the image which has moved up or down.
821 // Instead only new lines have to be drawn
822 void TerminalDisplay::scrollImage(int lines , const QRect& screenWindowRegion)
823 {
824  // if the flow control warning is enabled this will interfere with the
825  // scrolling optimizations and cause artifacts. the simple solution here
826  // is to just disable the optimization whilst it is visible
827  if (_outputSuspendedLabel && _outputSuspendedLabel->isVisible())
828  return;
829 
830  // constrain the region to the display
831  // the bottom of the region is capped to the number of lines in the display's
832  // internal image - 2, so that the height of 'region' is strictly less
833  // than the height of the internal image.
834  QRect region = screenWindowRegion;
835  region.setBottom(qMin(region.bottom(), this->_lines - 2));
836 
837  // return if there is nothing to do
838  if (lines == 0
839  || _image == 0
840  || !region.isValid()
841  || (region.top() + abs(lines)) >= region.bottom()
842  || this->_lines <= region.height()) return;
843 
844  // hide terminal size label to prevent it being scrolled
845  if (_resizeWidget && _resizeWidget->isVisible())
846  _resizeWidget->hide();
847 
848  // Note: With Qt 4.4 the left edge of the scrolled area must be at 0
849  // to get the correct (newly exposed) part of the widget repainted.
850  //
851  // The right edge must be before the left edge of the scroll bar to
852  // avoid triggering a repaint of the entire widget, the distance is
853  // given by SCROLLBAR_CONTENT_GAP
854  //
855  // Set the QT_FLUSH_PAINT environment variable to '1' before starting the
856  // application to monitor repainting.
857  //
858  const int scrollBarWidth = _scrollBar->isHidden() ? 0 : _scrollBar->width();
859  const int SCROLLBAR_CONTENT_GAP = 1;
860  QRect scrollRect;
861  if (_scrollbarLocation == Enum::ScrollBarLeft) {
862  scrollRect.setLeft(scrollBarWidth + SCROLLBAR_CONTENT_GAP);
863  scrollRect.setRight(width());
864  } else {
865  scrollRect.setLeft(0);
866  scrollRect.setRight(width() - scrollBarWidth - SCROLLBAR_CONTENT_GAP);
867  }
868  void* firstCharPos = &_image[ region.top() * this->_columns ];
869  void* lastCharPos = &_image[(region.top() + abs(lines)) * this->_columns ];
870 
871  const int top = _contentRect.top() + (region.top() * _fontHeight);
872  const int linesToMove = region.height() - abs(lines);
873  const int bytesToMove = linesToMove * this->_columns * sizeof(Character);
874 
875  Q_ASSERT(linesToMove > 0);
876  Q_ASSERT(bytesToMove > 0);
877 
878  //scroll internal image
879  if (lines > 0) {
880  // check that the memory areas that we are going to move are valid
881  Q_ASSERT((char*)lastCharPos + bytesToMove <
882  (char*)(_image + (this->_lines * this->_columns)));
883 
884  Q_ASSERT((lines * this->_columns) < _imageSize);
885 
886  //scroll internal image down
887  memmove(firstCharPos , lastCharPos , bytesToMove);
888 
889  //set region of display to scroll
890  scrollRect.setTop(top);
891  } else {
892  // check that the memory areas that we are going to move are valid
893  Q_ASSERT((char*)firstCharPos + bytesToMove <
894  (char*)(_image + (this->_lines * this->_columns)));
895 
896  //scroll internal image up
897  memmove(lastCharPos , firstCharPos , bytesToMove);
898 
899  //set region of the display to scroll
900  scrollRect.setTop(top + abs(lines) * _fontHeight);
901  }
902  scrollRect.setHeight(linesToMove * _fontHeight);
903 
904  Q_ASSERT(scrollRect.isValid() && !scrollRect.isEmpty());
905 
906  //scroll the display vertically to match internal _image
907  scroll(0 , _fontHeight * (-lines) , scrollRect);
908 }
909 
910 QRegion TerminalDisplay::hotSpotRegion() const
911 {
912  QRegion region;
913  foreach(Filter::HotSpot * hotSpot , _filterChain->hotSpots()) {
914  QRect r;
915  if (hotSpot->startLine() == hotSpot->endLine()) {
916  r.setLeft(hotSpot->startColumn());
917  r.setTop(hotSpot->startLine());
918  r.setRight(hotSpot->endColumn());
919  r.setBottom(hotSpot->endLine());
920  region |= imageToWidget(r);
921  } else {
922  r.setLeft(hotSpot->startColumn());
923  r.setTop(hotSpot->startLine());
924  r.setRight(_columns);
925  r.setBottom(hotSpot->startLine());
926  region |= imageToWidget(r);
927  for (int line = hotSpot->startLine() + 1 ; line < hotSpot->endLine() ; line++) {
928  r.setLeft(0);
929  r.setTop(line);
930  r.setRight(_columns);
931  r.setBottom(line);
932  region |= imageToWidget(r);
933  }
934  r.setLeft(0);
935  r.setTop(hotSpot->endLine());
936  r.setRight(hotSpot->endColumn());
937  r.setBottom(hotSpot->endLine());
938  region |= imageToWidget(r);
939  }
940  }
941  return region;
942 }
943 
944 void TerminalDisplay::processFilters()
945 {
946  if (!_screenWindow)
947  return;
948 
949  QRegion preUpdateHotSpots = hotSpotRegion();
950 
951  // use _screenWindow->getImage() here rather than _image because
952  // other classes may call processFilters() when this display's
953  // ScreenWindow emits a scrolled() signal - which will happen before
954  // updateImage() is called on the display and therefore _image is
955  // out of date at this point
956  _filterChain->setImage(_screenWindow->getImage(),
957  _screenWindow->windowLines(),
958  _screenWindow->windowColumns(),
959  _screenWindow->getLineProperties());
960  _filterChain->process();
961 
962  QRegion postUpdateHotSpots = hotSpotRegion();
963 
964  update(preUpdateHotSpots | postUpdateHotSpots);
965 }
966 
967 void TerminalDisplay::updateImage()
968 {
969  if (!_screenWindow)
970  return;
971 
972  // optimization - scroll the existing image where possible and
973  // avoid expensive text drawing for parts of the image that
974  // can simply be moved up or down
975  if (_wallpaper->isNull()) {
976  scrollImage(_screenWindow->scrollCount() ,
977  _screenWindow->scrollRegion());
978  _screenWindow->resetScrollCount();
979  }
980 
981  if (!_image) {
982  // Create _image.
983  // The emitted changedContentSizeSignal also leads to getImage being recreated, so do this first.
984  updateImageSize();
985  }
986 
987  Character* const newimg = _screenWindow->getImage();
988  const int lines = _screenWindow->windowLines();
989  const int columns = _screenWindow->windowColumns();
990 
991  setScroll(_screenWindow->currentLine() , _screenWindow->lineCount());
992 
993  Q_ASSERT(this->_usedLines <= this->_lines);
994  Q_ASSERT(this->_usedColumns <= this->_columns);
995 
996  int y, x, len;
997 
998  const QPoint tL = contentsRect().topLeft();
999  const int tLx = tL.x();
1000  const int tLy = tL.y();
1001  _hasTextBlinker = false;
1002 
1003  CharacterColor cf; // undefined
1004 
1005  const int linesToUpdate = qMin(this->_lines, qMax(0, lines));
1006  const int columnsToUpdate = qMin(this->_columns, qMax(0, columns));
1007 
1008  char* dirtyMask = new char[columnsToUpdate + 2];
1009  QRegion dirtyRegion;
1010 
1011  // debugging variable, this records the number of lines that are found to
1012  // be 'dirty' ( ie. have changed from the old _image to the new _image ) and
1013  // which therefore need to be repainted
1014  int dirtyLineCount = 0;
1015 
1016  for (y = 0; y < linesToUpdate; ++y) {
1017  const Character* currentLine = &_image[y * this->_columns];
1018  const Character* const newLine = &newimg[y * columns];
1019 
1020  bool updateLine = false;
1021 
1022  // The dirty mask indicates which characters need repainting. We also
1023  // mark surrounding neighbors dirty, in case the character exceeds
1024  // its cell boundaries
1025  memset(dirtyMask, 0, columnsToUpdate + 2);
1026 
1027  for (x = 0 ; x < columnsToUpdate ; ++x) {
1028  if (newLine[x] != currentLine[x]) {
1029  dirtyMask[x] = true;
1030  }
1031  }
1032 
1033  if (!_resizing) // not while _resizing, we're expecting a paintEvent
1034  for (x = 0; x < columnsToUpdate; ++x) {
1035  _hasTextBlinker |= (newLine[x].rendition & RE_BLINK);
1036 
1037  // Start drawing if this character or the next one differs.
1038  // We also take the next one into account to handle the situation
1039  // where characters exceed their cell width.
1040  if (dirtyMask[x]) {
1041  if (!newLine[x + 0].character)
1042  continue;
1043  const bool lineDraw = newLine[x + 0].isLineChar();
1044  const bool doubleWidth = (x + 1 == columnsToUpdate) ? false : (newLine[x + 1].character == 0);
1045  const quint8 cr = newLine[x].rendition;
1046  const CharacterColor clipboard = newLine[x].backgroundColor;
1047  if (newLine[x].foregroundColor != cf) cf = newLine[x].foregroundColor;
1048  const int lln = columnsToUpdate - x;
1049  for (len = 1; len < lln; ++len) {
1050  const Character& ch = newLine[x + len];
1051 
1052  if (!ch.character)
1053  continue; // Skip trailing part of multi-col chars.
1054 
1055  const bool nextIsDoubleWidth = (x + len + 1 == columnsToUpdate) ? false : (newLine[x + len + 1].character == 0);
1056 
1057  if (ch.foregroundColor != cf ||
1058  ch.backgroundColor != clipboard ||
1059  (ch.rendition & ~RE_EXTENDED_CHAR) != (cr & ~RE_EXTENDED_CHAR) ||
1060  !dirtyMask[x + len] ||
1061  ch.isLineChar() != lineDraw ||
1062  nextIsDoubleWidth != doubleWidth)
1063  break;
1064  }
1065 
1066  const bool saveFixedFont = _fixedFont;
1067  if (lineDraw)
1068  _fixedFont = false;
1069  if (doubleWidth)
1070  _fixedFont = false;
1071 
1072  updateLine = true;
1073 
1074  _fixedFont = saveFixedFont;
1075  x += len - 1;
1076  }
1077  }
1078 
1079  //both the top and bottom halves of double height _lines must always be redrawn
1080  //although both top and bottom halves contain the same characters, only
1081  //the top one is actually
1082  //drawn.
1083  if (_lineProperties.count() > y)
1084  updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT);
1085 
1086  // if the characters on the line are different in the old and the new _image
1087  // then this line must be repainted.
1088  if (updateLine) {
1089  dirtyLineCount++;
1090 
1091  // add the area occupied by this line to the region which needs to be
1092  // repainted
1093  QRect dirtyRect = QRect(_contentRect.left() + tLx ,
1094  _contentRect.top() + tLy + _fontHeight * y ,
1095  _fontWidth * columnsToUpdate ,
1096  _fontHeight);
1097 
1098  dirtyRegion |= dirtyRect;
1099  }
1100 
1101  // replace the line of characters in the old _image with the
1102  // current line of the new _image
1103  memcpy((void*)currentLine, (const void*)newLine, columnsToUpdate * sizeof(Character));
1104  }
1105 
1106  // if the new _image is smaller than the previous _image, then ensure that the area
1107  // outside the new _image is cleared
1108  if (linesToUpdate < _usedLines) {
1109  dirtyRegion |= QRect(_contentRect.left() + tLx ,
1110  _contentRect.top() + tLy + _fontHeight * linesToUpdate ,
1111  _fontWidth * this->_columns ,
1112  _fontHeight * (_usedLines - linesToUpdate));
1113  }
1114  _usedLines = linesToUpdate;
1115 
1116  if (columnsToUpdate < _usedColumns) {
1117  dirtyRegion |= QRect(_contentRect.left() + tLx + columnsToUpdate * _fontWidth ,
1118  _contentRect.top() + tLy ,
1119  _fontWidth * (_usedColumns - columnsToUpdate) ,
1120  _fontHeight * this->_lines);
1121  }
1122  _usedColumns = columnsToUpdate;
1123 
1124  dirtyRegion |= _inputMethodData.previousPreeditRect;
1125 
1126  // update the parts of the display which have changed
1127  update(dirtyRegion);
1128 
1129  if (_allowBlinkingText && _hasTextBlinker && !_blinkTextTimer->isActive()) {
1130  _blinkTextTimer->start();
1131  }
1132  if (!_hasTextBlinker && _blinkTextTimer->isActive()) {
1133  _blinkTextTimer->stop();
1134  _textBlinking = false;
1135  }
1136  delete[] dirtyMask;
1137 
1138 #if QT_VERSION >= 0x040800 // added in Qt 4.8.0
1139 #ifndef QT_NO_ACCESSIBILITY
1140  QAccessible::updateAccessibility(this, 0, QAccessible::TextUpdated);
1141  QAccessible::updateAccessibility(this, 0, QAccessible::TextCaretMoved);
1142 #endif
1143 #endif
1144 }
1145 
1146 void TerminalDisplay::showResizeNotification()
1147 {
1148  if (_showTerminalSizeHint && isVisible()) {
1149  if (!_resizeWidget) {
1150  _resizeWidget = new QLabel(i18n("Size: XXX x XXX"), this);
1151  _resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width(i18n("Size: XXX x XXX")));
1152  _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height());
1153  _resizeWidget->setAlignment(Qt::AlignCenter);
1154 
1155  _resizeWidget->setStyleSheet("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)");
1156 
1157  _resizeTimer = new QTimer(this);
1158  _resizeTimer->setInterval(SIZE_HINT_DURATION);
1159  _resizeTimer->setSingleShot(true);
1160  connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide()));
1161  }
1162  QString sizeStr = i18n("Size: %1 x %2", _columns, _lines);
1163  _resizeWidget->setText(sizeStr);
1164  _resizeWidget->move((width() - _resizeWidget->width()) / 2,
1165  (height() - _resizeWidget->height()) / 2 + 20);
1166  _resizeWidget->show();
1167  _resizeTimer->start();
1168  }
1169 }
1170 
1171 void TerminalDisplay::paintEvent(QPaintEvent* pe)
1172 {
1173  QPainter paint(this);
1174 
1175  foreach(const QRect & rect, (pe->region() & contentsRect()).rects()) {
1176  drawBackground(paint, rect, palette().background().color(),
1177  true /* use opacity setting */);
1178  drawContents(paint, rect);
1179  }
1180  drawCurrentResultRect(paint);
1181  drawInputMethodPreeditString(paint, preeditRect());
1182  paintFilters(paint);
1183 }
1184 
1185 void TerminalDisplay::printContent(QPainter& painter, bool friendly)
1186 {
1187  // Reinitialize the font with the printers paint device so the font
1188  // measurement calculations will be done correctly
1189  QFont savedFont = getVTFont();
1190  QFont font(savedFont, painter.device());
1191  painter.setFont(font);
1192  setVTFont(font);
1193 
1194  QRect rect(0, 0, size().width(), size().height());
1195 
1196  _printerFriendly = friendly;
1197  if (!friendly) {
1198  drawBackground(painter, rect, getBackgroundColor(),
1199  true /* use opacity setting */);
1200  }
1201  drawContents(painter, rect);
1202  _printerFriendly = false;
1203  setVTFont(savedFont);
1204 }
1205 
1206 QPoint TerminalDisplay::cursorPosition() const
1207 {
1208  if (_screenWindow)
1209  return _screenWindow->cursorPosition();
1210  else
1211  return QPoint(0, 0);
1212 }
1213 
1214 FilterChain* TerminalDisplay::filterChain() const
1215 {
1216  return _filterChain;
1217 }
1218 
1219 void TerminalDisplay::paintFilters(QPainter& painter)
1220 {
1221  // get color of character under mouse and use it to draw
1222  // lines for filters
1223  QPoint cursorPos = mapFromGlobal(QCursor::pos());
1224  int cursorLine;
1225  int cursorColumn;
1226 
1227  getCharacterPosition(cursorPos , cursorLine , cursorColumn);
1228  Character cursorCharacter = _image[loc(cursorColumn, cursorLine)];
1229 
1230  painter.setPen(QPen(cursorCharacter.foregroundColor.color(colorTable())));
1231 
1232  // iterate over hotspots identified by the display's currently active filters
1233  // and draw appropriate visuals to indicate the presence of the hotspot
1234 
1235  QList<Filter::HotSpot*> spots = _filterChain->hotSpots();
1236  foreach(Filter::HotSpot* spot, spots) {
1237  QRegion region;
1238  if (_underlineLinks && spot->type() == Filter::HotSpot::Link) {
1239  QRect r;
1240  if (spot->startLine() == spot->endLine()) {
1241  r.setCoords(spot->startColumn()*_fontWidth + _contentRect.left(),
1242  spot->startLine()*_fontHeight + _contentRect.top(),
1243  (spot->endColumn())*_fontWidth + _contentRect.left() - 1,
1244  (spot->endLine() + 1)*_fontHeight + _contentRect.top() - 1);
1245  region |= r;
1246  } else {
1247  r.setCoords(spot->startColumn()*_fontWidth + _contentRect.left(),
1248  spot->startLine()*_fontHeight + _contentRect.top(),
1249  (_columns)*_fontWidth + _contentRect.left() - 1,
1250  (spot->startLine() + 1)*_fontHeight + _contentRect.top() - 1);
1251  region |= r;
1252  for (int line = spot->startLine() + 1 ; line < spot->endLine() ; line++) {
1253  r.setCoords(0 * _fontWidth + _contentRect.left(),
1254  line * _fontHeight + _contentRect.top(),
1255  (_columns)*_fontWidth + _contentRect.left() - 1,
1256  (line + 1)*_fontHeight + _contentRect.top() - 1);
1257  region |= r;
1258  }
1259  r.setCoords(0 * _fontWidth + _contentRect.left(),
1260  spot->endLine()*_fontHeight + _contentRect.top(),
1261  (spot->endColumn())*_fontWidth + _contentRect.left() - 1,
1262  (spot->endLine() + 1)*_fontHeight + _contentRect.top() - 1);
1263  region |= r;
1264  }
1265  }
1266 
1267  for (int line = spot->startLine() ; line <= spot->endLine() ; line++) {
1268  int startColumn = 0;
1269  int endColumn = _columns - 1; // TODO use number of _columns which are actually
1270  // occupied on this line rather than the width of the
1271  // display in _columns
1272 
1273  // Check image size so _image[] is valid (see makeImage)
1274  if (loc(endColumn, line) > _imageSize)
1275  break;
1276 
1277  // ignore whitespace at the end of the lines
1278  while (_image[loc(endColumn, line)].isSpace() && endColumn > 0)
1279  endColumn--;
1280 
1281  // increment here because the column which we want to set 'endColumn' to
1282  // is the first whitespace character at the end of the line
1283  endColumn++;
1284 
1285  if (line == spot->startLine())
1286  startColumn = spot->startColumn();
1287  if (line == spot->endLine())
1288  endColumn = spot->endColumn();
1289 
1290  // TODO: resolve this comment with the new margin/center code
1291  // subtract one pixel from
1292  // the right and bottom so that
1293  // we do not overdraw adjacent
1294  // hotspots
1295  //
1296  // subtracting one pixel from all sides also prevents an edge case where
1297  // moving the mouse outside a link could still leave it underlined
1298  // because the check below for the position of the cursor
1299  // finds it on the border of the target area
1300  QRect r;
1301  r.setCoords(startColumn * _fontWidth + _contentRect.left(),
1302  line * _fontHeight + _contentRect.top(),
1303  endColumn * _fontWidth + _contentRect.left() - 1,
1304  (line + 1)*_fontHeight + _contentRect.top() - 1);
1305  // Underline link hotspots
1306  if (_underlineLinks && spot->type() == Filter::HotSpot::Link) {
1307  QFontMetrics metrics(font());
1308 
1309  // find the baseline (which is the invisible line that the characters in the font sit on,
1310  // with some having tails dangling below)
1311  const int baseline = r.bottom() - metrics.descent();
1312  // find the position of the underline below that
1313  const int underlinePos = baseline + metrics.underlinePos();
1314  if (region.contains(mapFromGlobal(QCursor::pos()))) {
1315  painter.drawLine(r.left() , underlinePos ,
1316  r.right() , underlinePos);
1317  }
1318  // Marker hotspots simply have a transparent rectangular shape
1319  // drawn on top of them
1320  } else if (spot->type() == Filter::HotSpot::Marker) {
1321  //TODO - Do not use a hardcoded color for this
1322  const bool isCurrentResultLine = (_screenWindow->currentResultLine() == (spot->startLine() + _screenWindow->currentLine()));
1323  QColor color = isCurrentResultLine ? QColor(255, 255, 0, 120) : QColor(255, 0, 0, 120);
1324  painter.fillRect(r, color);
1325  }
1326  }
1327  }
1328 }
1329 void TerminalDisplay::drawContents(QPainter& paint, const QRect& rect)
1330 {
1331  const QPoint tL = contentsRect().topLeft();
1332  const int tLx = tL.x();
1333  const int tLy = tL.y();
1334 
1335  const int lux = qMin(_usedColumns - 1, qMax(0, (rect.left() - tLx - _contentRect.left()) / _fontWidth));
1336  const int luy = qMin(_usedLines - 1, qMax(0, (rect.top() - tLy - _contentRect.top()) / _fontHeight));
1337  const int rlx = qMin(_usedColumns - 1, qMax(0, (rect.right() - tLx - _contentRect.left()) / _fontWidth));
1338  const int rly = qMin(_usedLines - 1, qMax(0, (rect.bottom() - tLy - _contentRect.top()) / _fontHeight));
1339 
1340  const int numberOfColumns = _usedColumns;
1341  QString unistr;
1342  unistr.reserve(numberOfColumns);
1343  for (int y = luy; y <= rly; y++) {
1344  int x = lux;
1345  if (!_image[loc(lux, y)].character && x)
1346  x--; // Search for start of multi-column character
1347  for (; x <= rlx; x++) {
1348  int len = 1;
1349  int p = 0;
1350 
1351  // reset our buffer to the number of columns
1352  int bufferSize = numberOfColumns;
1353  unistr.resize(bufferSize);
1354  QChar *disstrU = unistr.data();
1355 
1356  // is this a single character or a sequence of characters ?
1357  if (_image[loc(x, y)].rendition & RE_EXTENDED_CHAR) {
1358  // sequence of characters
1359  ushort extendedCharLength = 0;
1360  const ushort* chars = ExtendedCharTable::instance.lookupExtendedChar(_image[loc(x, y)].character, extendedCharLength);
1361  if (chars) {
1362  Q_ASSERT(extendedCharLength > 1);
1363  bufferSize += extendedCharLength - 1;
1364  unistr.resize(bufferSize);
1365  disstrU = unistr.data();
1366  for (int index = 0 ; index < extendedCharLength ; index++) {
1367  Q_ASSERT(p < bufferSize);
1368  disstrU[p++] = chars[index];
1369  }
1370  }
1371  } else {
1372  // single character
1373  const quint16 c = _image[loc(x, y)].character;
1374  if (c) {
1375  Q_ASSERT(p < bufferSize);
1376  disstrU[p++] = c; //fontMap(c);
1377  }
1378  }
1379 
1380  const bool lineDraw = _image[loc(x, y)].isLineChar();
1381  const bool doubleWidth = (_image[ qMin(loc(x, y) + 1, _imageSize) ].character == 0);
1382  const CharacterColor currentForeground = _image[loc(x, y)].foregroundColor;
1383  const CharacterColor currentBackground = _image[loc(x, y)].backgroundColor;
1384  const quint8 currentRendition = _image[loc(x, y)].rendition;
1385 
1386  while (x + len <= rlx &&
1387  _image[loc(x + len, y)].foregroundColor == currentForeground &&
1388  _image[loc(x + len, y)].backgroundColor == currentBackground &&
1389  (_image[loc(x + len, y)].rendition & ~RE_EXTENDED_CHAR) == (currentRendition & ~RE_EXTENDED_CHAR) &&
1390  (_image[ qMin(loc(x + len, y) + 1, _imageSize) ].character == 0) == doubleWidth &&
1391  _image[loc(x + len, y)].isLineChar() == lineDraw) {
1392  const quint16 c = _image[loc(x + len, y)].character;
1393  if (_image[loc(x + len, y)].rendition & RE_EXTENDED_CHAR) {
1394  // sequence of characters
1395  ushort extendedCharLength = 0;
1396  const ushort* chars = ExtendedCharTable::instance.lookupExtendedChar(c, extendedCharLength);
1397  if (chars) {
1398  Q_ASSERT(extendedCharLength > 1);
1399  bufferSize += extendedCharLength - 1;
1400  unistr.resize(bufferSize);
1401  disstrU = unistr.data();
1402  for (int index = 0 ; index < extendedCharLength ; index++) {
1403  Q_ASSERT(p < bufferSize);
1404  disstrU[p++] = chars[index];
1405  }
1406  }
1407  } else {
1408  // single character
1409  if (c) {
1410  Q_ASSERT(p < bufferSize);
1411  disstrU[p++] = c; //fontMap(c);
1412  }
1413  }
1414 
1415  if (doubleWidth) // assert((_image[loc(x+len,y)+1].character == 0)), see above if condition
1416  len++; // Skip trailing part of multi-column character
1417  len++;
1418  }
1419  if ((x + len < _usedColumns) && (!_image[loc(x + len, y)].character))
1420  len++; // Adjust for trailing part of multi-column character
1421 
1422  const bool save__fixedFont = _fixedFont;
1423  if (lineDraw)
1424  _fixedFont = false;
1425  if (doubleWidth)
1426  _fixedFont = false;
1427  unistr.resize(p);
1428 
1429  // Create a text scaling matrix for double width and double height lines.
1430  QMatrix textScale;
1431 
1432  if (y < _lineProperties.size()) {
1433  if (_lineProperties[y] & LINE_DOUBLEWIDTH)
1434  textScale.scale(2, 1);
1435 
1436  if (_lineProperties[y] & LINE_DOUBLEHEIGHT)
1437  textScale.scale(1, 2);
1438  }
1439 
1440  //Apply text scaling matrix.
1441  paint.setWorldMatrix(textScale, true);
1442 
1443  //calculate the area in which the text will be drawn
1444  QRect textArea = QRect(_contentRect.left() + tLx + _fontWidth * x , _contentRect.top() + tLy + _fontHeight * y , _fontWidth * len , _fontHeight);
1445 
1446  //move the calculated area to take account of scaling applied to the painter.
1447  //the position of the area from the origin (0,0) is scaled
1448  //by the opposite of whatever
1449  //transformation has been applied to the painter. this ensures that
1450  //painting does actually start from textArea.topLeft()
1451  //(instead of textArea.topLeft() * painter-scale)
1452  textArea.moveTopLeft(textScale.inverted().map(textArea.topLeft()));
1453 
1454  //paint text fragment
1455  if (_printerFriendly) {
1456  drawPrinterFriendlyTextFragment(paint,
1457  textArea,
1458  unistr,
1459  &_image[loc(x, y)]);
1460  } else {
1461  drawTextFragment(paint,
1462  textArea,
1463  unistr,
1464  &_image[loc(x, y)]);
1465  }
1466 
1467  _fixedFont = save__fixedFont;
1468 
1469  //reset back to single-width, single-height _lines
1470  paint.setWorldMatrix(textScale.inverted(), true);
1471 
1472  if (y < _lineProperties.size() - 1) {
1473  //double-height _lines are represented by two adjacent _lines
1474  //containing the same characters
1475  //both _lines will have the LINE_DOUBLEHEIGHT attribute.
1476  //If the current line has the LINE_DOUBLEHEIGHT attribute,
1477  //we can therefore skip the next line
1478  if (_lineProperties[y] & LINE_DOUBLEHEIGHT)
1479  y++;
1480  }
1481 
1482  x += len - 1;
1483  }
1484  }
1485 }
1486 
1487 void TerminalDisplay::drawCurrentResultRect(QPainter& painter)
1488 {
1489  if(_screenWindow->currentResultLine() == -1) {
1490  return;
1491  }
1492 
1493  QRect r(0, (_screenWindow->currentResultLine() - _screenWindow->currentLine())*_fontHeight,
1494  contentsRect().width(), _fontHeight);
1495  painter.fillRect(r, QColor(0, 0, 255, 80));
1496 }
1497 
1498 QRect TerminalDisplay::imageToWidget(const QRect& imageArea) const
1499 {
1500  QRect result;
1501  result.setLeft(_contentRect.left() + _fontWidth * imageArea.left());
1502  result.setTop(_contentRect.top() + _fontHeight * imageArea.top());
1503  result.setWidth(_fontWidth * imageArea.width());
1504  result.setHeight(_fontHeight * imageArea.height());
1505 
1506  return result;
1507 }
1508 
1509 /* ------------------------------------------------------------------------- */
1510 /* */
1511 /* Blinking Text & Cursor */
1512 /* */
1513 /* ------------------------------------------------------------------------- */
1514 
1515 void TerminalDisplay::setBlinkingCursorEnabled(bool blink)
1516 {
1517  _allowBlinkingCursor = blink;
1518 
1519  if (!hasFocus())
1520  return;
1521 
1522  if (blink && !_blinkCursorTimer->isActive())
1523  _blinkCursorTimer->start();
1524 
1525  if (!blink && _blinkCursorTimer->isActive()) {
1526  _blinkCursorTimer->stop();
1527  if (_cursorBlinking) {
1528  // if cursor is blinking(hidden), blink it again to make it show
1529  blinkCursorEvent();
1530  }
1531  Q_ASSERT(_cursorBlinking == false);
1532  }
1533 }
1534 
1535 void TerminalDisplay::setBlinkingTextEnabled(bool blink)
1536 {
1537  _allowBlinkingText = blink;
1538 
1539  if (blink && !_blinkTextTimer->isActive())
1540  _blinkTextTimer->start();
1541 
1542  if (!blink && _blinkTextTimer->isActive()) {
1543  _blinkTextTimer->stop();
1544  _textBlinking = false;
1545  }
1546 }
1547 
1548 void TerminalDisplay::focusOutEvent(QFocusEvent*)
1549 {
1550  // trigger a repaint of the cursor so that it is both:
1551  //
1552  // * visible (in case it was hidden during blinking)
1553  // * drawn in a focused out state
1554  _cursorBlinking = false;
1555  updateCursor();
1556 
1557  // suppress further cursor blinking
1558  _blinkCursorTimer->stop();
1559  Q_ASSERT(_cursorBlinking == false);
1560 
1561  // if text is blinking (hidden), blink it again to make it shown
1562  if (_textBlinking)
1563  blinkTextEvent();
1564 
1565  // suppress further text blinking
1566  _blinkTextTimer->stop();
1567  Q_ASSERT(_textBlinking == false);
1568 }
1569 
1570 void TerminalDisplay::focusInEvent(QFocusEvent*)
1571 {
1572  if (_allowBlinkingCursor)
1573  _blinkCursorTimer->start();
1574 
1575  updateCursor();
1576 
1577  if (_allowBlinkingText && _hasTextBlinker)
1578  _blinkTextTimer->start();
1579 }
1580 
1581 void TerminalDisplay::blinkTextEvent()
1582 {
1583  Q_ASSERT(_allowBlinkingText);
1584 
1585  _textBlinking = !_textBlinking;
1586 
1587  // TODO: Optimize to only repaint the areas of the widget where there is
1588  // blinking text rather than repainting the whole widget.
1589  update();
1590 }
1591 
1592 void TerminalDisplay::blinkCursorEvent()
1593 {
1594  Q_ASSERT(_allowBlinkingCursor);
1595 
1596  _cursorBlinking = !_cursorBlinking;
1597  updateCursor();
1598 }
1599 
1600 void TerminalDisplay::updateCursor()
1601 {
1602  QRect cursorRect = imageToWidget(QRect(cursorPosition(), QSize(1, 1)));
1603  update(cursorRect);
1604 }
1605 
1606 /* ------------------------------------------------------------------------- */
1607 /* */
1608 /* Geometry & Resizing */
1609 /* */
1610 /* ------------------------------------------------------------------------- */
1611 
1612 void TerminalDisplay::resizeEvent(QResizeEvent*)
1613 {
1614  updateImageSize();
1615 }
1616 
1617 void TerminalDisplay::propagateSize()
1618 {
1619  if (_image)
1620  updateImageSize();
1621 }
1622 
1623 void TerminalDisplay::updateImageSize()
1624 {
1625  Character* oldImage = _image;
1626  const int oldLines = _lines;
1627  const int oldColumns = _columns;
1628 
1629  makeImage();
1630 
1631  if (oldImage) {
1632  // copy the old image to reduce flicker
1633  int lines = qMin(oldLines, _lines);
1634  int columns = qMin(oldColumns, _columns);
1635  for (int line = 0; line < lines; line++) {
1636  memcpy((void*)&_image[_columns * line],
1637  (void*)&oldImage[oldColumns * line],
1638  columns * sizeof(Character));
1639  }
1640  delete[] oldImage;
1641  }
1642 
1643  if (_screenWindow)
1644  _screenWindow->setWindowLines(_lines);
1645 
1646  _resizing = (oldLines != _lines) || (oldColumns != _columns);
1647 
1648  if (_resizing) {
1649  showResizeNotification();
1650  emit changedContentSizeSignal(_contentRect.height(), _contentRect.width()); // expose resizeEvent
1651  }
1652 
1653  _resizing = false;
1654 }
1655 
1656 void TerminalDisplay::makeImage()
1657 {
1658  _wallpaper->load();
1659 
1660  calcGeometry();
1661 
1662  // confirm that array will be of non-zero size, since the painting code
1663  // assumes a non-zero array length
1664  Q_ASSERT(_lines > 0 && _columns > 0);
1665  Q_ASSERT(_usedLines <= _lines && _usedColumns <= _columns);
1666 
1667  _imageSize = _lines * _columns;
1668 
1669  // We over-commit one character so that we can be more relaxed in dealing with
1670  // certain boundary conditions: _image[_imageSize] is a valid but unused position
1671  _image = new Character[_imageSize + 1];
1672 
1673  clearImage();
1674 }
1675 
1676 void TerminalDisplay::clearImage()
1677 {
1678  for (int i = 0; i <= _imageSize; ++i)
1679  _image[i] = Screen::DefaultChar;
1680 }
1681 
1682 void TerminalDisplay::calcGeometry()
1683 {
1684  _scrollBar->resize(_scrollBar->sizeHint().width(), contentsRect().height());
1685  _contentRect = contentsRect().adjusted(_margin, _margin, -_margin, -_margin);
1686 
1687  switch (_scrollbarLocation) {
1688  case Enum::ScrollBarHidden :
1689  break;
1690  case Enum::ScrollBarLeft :
1691  _contentRect.setLeft(_contentRect.left() + _scrollBar->width());
1692  _scrollBar->move(contentsRect().topLeft());
1693  break;
1694  case Enum::ScrollBarRight:
1695  _contentRect.setRight(_contentRect.right() - _scrollBar->width());
1696  _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width() - 1, 0));
1697  break;
1698  }
1699 
1700  // ensure that display is always at least one column wide
1701  _columns = qMax(1, _contentRect.width() / _fontWidth);
1702  _usedColumns = qMin(_usedColumns, _columns);
1703 
1704  // ensure that display is always at least one line high
1705  _lines = qMax(1, _contentRect.height() / _fontHeight);
1706  _usedLines = qMin(_usedLines, _lines);
1707 
1708  if(_centerContents) {
1709  QSize unusedPixels = _contentRect.size() - QSize(_columns * _fontWidth, _lines * _fontHeight);
1710  _contentRect.adjust(unusedPixels.width() / 2, unusedPixels.height() / 2, 0, 0);
1711  }
1712 }
1713 
1714 // calculate the needed size, this must be synced with calcGeometry()
1715 void TerminalDisplay::setSize(int columns, int lines)
1716 {
1717  const int scrollBarWidth = _scrollBar->isHidden() ? 0 : _scrollBar->sizeHint().width();
1718  const int horizontalMargin = _margin * 2;
1719  const int verticalMargin = _margin * 2;
1720 
1721  QSize newSize = QSize(horizontalMargin + scrollBarWidth + (columns * _fontWidth) ,
1722  verticalMargin + (lines * _fontHeight));
1723 
1724  if (newSize != size()) {
1725  _size = newSize;
1726  updateGeometry();
1727  }
1728 }
1729 
1730 QSize TerminalDisplay::sizeHint() const
1731 {
1732  return _size;
1733 }
1734 
1735 //showEvent and hideEvent are reimplemented here so that it appears to other classes that the
1736 //display has been resized when the display is hidden or shown.
1737 //
1738 //TODO: Perhaps it would be better to have separate signals for show and hide instead of using
1739 //the same signal as the one for a content size change
1740 void TerminalDisplay::showEvent(QShowEvent*)
1741 {
1742  emit changedContentSizeSignal(_contentRect.height(), _contentRect.width());
1743 }
1744 void TerminalDisplay::hideEvent(QHideEvent*)
1745 {
1746  emit changedContentSizeSignal(_contentRect.height(), _contentRect.width());
1747 }
1748 
1749 void TerminalDisplay::setMargin(int margin)
1750 {
1751  _margin = margin;
1752  updateImageSize();
1753 }
1754 
1755 void TerminalDisplay::setCenterContents(bool enable)
1756 {
1757  _centerContents = enable;
1758  calcGeometry();
1759  update();
1760 }
1761 
1762 /* ------------------------------------------------------------------------- */
1763 /* */
1764 /* Scrollbar */
1765 /* */
1766 /* ------------------------------------------------------------------------- */
1767 
1768 void TerminalDisplay::setScrollBarPosition(Enum::ScrollBarPositionEnum position)
1769 {
1770  if (_scrollbarLocation == position)
1771  return;
1772 
1773  if (position == Enum::ScrollBarHidden)
1774  _scrollBar->hide();
1775  else
1776  _scrollBar->show();
1777 
1778  _scrollbarLocation = position;
1779 
1780  propagateSize();
1781  update();
1782 }
1783 
1784 void TerminalDisplay::scrollBarPositionChanged(int)
1785 {
1786  if (!_screenWindow)
1787  return;
1788 
1789  _screenWindow->scrollTo(_scrollBar->value());
1790 
1791  // if the thumb has been moved to the bottom of the _scrollBar then set
1792  // the display to automatically track new output,
1793  // that is, scroll down automatically
1794  // to how new _lines as they are added
1795  const bool atEndOfOutput = (_scrollBar->value() == _scrollBar->maximum());
1796  _screenWindow->setTrackOutput(atEndOfOutput);
1797 
1798  updateImage();
1799 }
1800 
1801 void TerminalDisplay::setScroll(int cursor, int slines)
1802 {
1803  // update _scrollBar if the range or value has changed,
1804  // otherwise return
1805  //
1806  // setting the range or value of a _scrollBar will always trigger
1807  // a repaint, so it should be avoided if it is not necessary
1808  if (_scrollBar->minimum() == 0 &&
1809  _scrollBar->maximum() == (slines - _lines) &&
1810  _scrollBar->value() == cursor) {
1811  return;
1812  }
1813 
1814  disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int)));
1815  _scrollBar->setRange(0, slines - _lines);
1816  _scrollBar->setSingleStep(1);
1817  _scrollBar->setPageStep(_lines);
1818  _scrollBar->setValue(cursor);
1819  connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int)));
1820 }
1821 
1822 void TerminalDisplay::setScrollFullPage(bool fullPage)
1823 {
1824  _scrollFullPage = fullPage;
1825 }
1826 
1827 bool TerminalDisplay::scrollFullPage() const
1828 {
1829  return _scrollFullPage;
1830 }
1831 
1832 /* ------------------------------------------------------------------------- */
1833 /* */
1834 /* Mouse */
1835 /* */
1836 /* ------------------------------------------------------------------------- */
1837 void TerminalDisplay::mousePressEvent(QMouseEvent* ev)
1838 {
1839  if (_possibleTripleClick && (ev->button() == Qt::LeftButton)) {
1840  mouseTripleClickEvent(ev);
1841  return;
1842  }
1843 
1844  if (!contentsRect().contains(ev->pos())) return;
1845 
1846  if (!_screenWindow) return;
1847 
1848  int charLine;
1849  int charColumn;
1850  getCharacterPosition(ev->pos(), charLine, charColumn);
1851  QPoint pos = QPoint(charColumn, charLine);
1852 
1853  if (ev->button() == Qt::LeftButton) {
1854  // request the software keyboard, if any
1855  if (qApp->autoSipEnabled()) {
1856  QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
1857  style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
1858  if (hasFocus() || behavior == QStyle::RSIP_OnMouseClick) {
1859  QEvent event(QEvent::RequestSoftwareInputPanel);
1860  QApplication::sendEvent(this, &event);
1861  }
1862  }
1863 
1864  _lineSelectionMode = false;
1865  _wordSelectionMode = false;
1866 
1867  // The user clicked inside selected text
1868  bool selected = _screenWindow->isSelected(pos.x(), pos.y());
1869 
1870  // Drag only when the Control key is held
1871  if ((!_ctrlRequiredForDrag || ev->modifiers() & Qt::ControlModifier) && selected) {
1872  _dragInfo.state = diPending;
1873  _dragInfo.start = ev->pos();
1874  } else {
1875  // No reason to ever start a drag event
1876  _dragInfo.state = diNone;
1877 
1878  _preserveLineBreaks = !((ev->modifiers() & Qt::ControlModifier) && !(ev->modifiers() & Qt::AltModifier));
1879  _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier);
1880 
1881  if (_mouseMarks || (ev->modifiers() == Qt::ShiftModifier)) {
1882  // Only extend selection for programs not interested in mouse
1883  if (_mouseMarks && (ev->modifiers() == Qt::ShiftModifier)) {
1884  extendSelection(ev->pos());
1885  } else {
1886  _screenWindow->clearSelection();
1887 
1888  pos.ry() += _scrollBar->value();
1889  _iPntSel = _pntSel = pos;
1890  _actSel = 1; // left mouse button pressed but nothing selected yet.
1891  }
1892  } else {
1893  emit mouseSignal(0, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , 0);
1894  }
1895 
1896  if (_underlineLinks && (_openLinksByDirectClick || (ev->modifiers() & Qt::ControlModifier))) {
1897  Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine, charColumn);
1898  if (spot && spot->type() == Filter::HotSpot::Link) {
1899  QObject action;
1900  action.setObjectName("open-action");
1901  spot->activate(&action);
1902  }
1903  }
1904  }
1905  } else if (ev->button() == Qt::MidButton) {
1906  processMidButtonClick(ev);
1907  } else if (ev->button() == Qt::RightButton) {
1908  if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier))
1909  emit configureRequest(ev->pos());
1910  else
1911  emit mouseSignal(2, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , 0);
1912  }
1913 }
1914 
1915 QList<QAction*> TerminalDisplay::filterActions(const QPoint& position)
1916 {
1917  int charLine, charColumn;
1918  getCharacterPosition(position, charLine, charColumn);
1919 
1920  Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine, charColumn);
1921 
1922  return spot ? spot->actions() : QList<QAction*>();
1923 }
1924 
1925 void TerminalDisplay::mouseMoveEvent(QMouseEvent* ev)
1926 {
1927  int charLine = 0;
1928  int charColumn = 0;
1929  getCharacterPosition(ev->pos(), charLine, charColumn);
1930 
1931  // handle filters
1932  // change link hot-spot appearance on mouse-over
1933  Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine, charColumn);
1934  if (spot && spot->type() == Filter::HotSpot::Link) {
1935  if (_underlineLinks) {
1936  QRegion previousHotspotArea = _mouseOverHotspotArea;
1937  _mouseOverHotspotArea = QRegion();
1938  QRect r;
1939  if (spot->startLine() == spot->endLine()) {
1940  r.setCoords(spot->startColumn()*_fontWidth + _contentRect.left(),
1941  spot->startLine()*_fontHeight + _contentRect.top(),
1942  (spot->endColumn())*_fontWidth + _contentRect.left() - 1,
1943  (spot->endLine() + 1)*_fontHeight + _contentRect.top() - 1);
1944  _mouseOverHotspotArea |= r;
1945  } else {
1946  r.setCoords(spot->startColumn()*_fontWidth + _contentRect.left(),
1947  spot->startLine()*_fontHeight + _contentRect.top(),
1948  (_columns)*_fontWidth + _contentRect.left() - 1,
1949  (spot->startLine() + 1)*_fontHeight + _contentRect.top() - 1);
1950  _mouseOverHotspotArea |= r;
1951  for (int line = spot->startLine() + 1 ; line < spot->endLine() ; line++) {
1952  r.setCoords(0 * _fontWidth + _contentRect.left(),
1953  line * _fontHeight + _contentRect.top(),
1954  (_columns)*_fontWidth + _contentRect.left() - 1,
1955  (line + 1)*_fontHeight + _contentRect.top() - 1);
1956  _mouseOverHotspotArea |= r;
1957  }
1958  r.setCoords(0 * _fontWidth + _contentRect.left(),
1959  spot->endLine()*_fontHeight + _contentRect.top(),
1960  (spot->endColumn())*_fontWidth + _contentRect.left() - 1,
1961  (spot->endLine() + 1)*_fontHeight + _contentRect.top() - 1);
1962  _mouseOverHotspotArea |= r;
1963  }
1964 
1965  if ((_openLinksByDirectClick || (ev->modifiers() & Qt::ControlModifier)) && (cursor().shape() != Qt::PointingHandCursor))
1966  setCursor(Qt::PointingHandCursor);
1967 
1968  update(_mouseOverHotspotArea | previousHotspotArea);
1969  }
1970  } else if (!_mouseOverHotspotArea.isEmpty()) {
1971  if ((_underlineLinks && (_openLinksByDirectClick || (ev->modifiers() & Qt::ControlModifier))) || (cursor().shape() == Qt::PointingHandCursor))
1972  setCursor(_mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor);
1973 
1974  update(_mouseOverHotspotArea);
1975  // set hotspot area to an invalid rectangle
1976  _mouseOverHotspotArea = QRegion();
1977  }
1978 
1979  // for auto-hiding the cursor, we need mouseTracking
1980  if (ev->buttons() == Qt::NoButton) return;
1981 
1982  // if the terminal is interested in mouse movements
1983  // then emit a mouse movement signal, unless the shift
1984  // key is being held down, which overrides this.
1985  if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) {
1986  int button = 3;
1987  if (ev->buttons() & Qt::LeftButton)
1988  button = 0;
1989  if (ev->buttons() & Qt::MidButton)
1990  button = 1;
1991  if (ev->buttons() & Qt::RightButton)
1992  button = 2;
1993 
1994  emit mouseSignal(button,
1995  charColumn + 1,
1996  charLine + 1 + _scrollBar->value() - _scrollBar->maximum(),
1997  1);
1998 
1999  return;
2000  }
2001 
2002  if (_dragInfo.state == diPending) {
2003  // we had a mouse down, but haven't confirmed a drag yet
2004  // if the mouse has moved sufficiently, we will confirm
2005 
2006  const int distance = KGlobalSettings::dndEventDelay();
2007  if (ev->x() > _dragInfo.start.x() + distance || ev->x() < _dragInfo.start.x() - distance ||
2008  ev->y() > _dragInfo.start.y() + distance || ev->y() < _dragInfo.start.y() - distance) {
2009  // we've left the drag square, we can start a real drag operation now
2010 
2011  _screenWindow->clearSelection();
2012  doDrag();
2013  }
2014  return;
2015  } else if (_dragInfo.state == diDragging) {
2016  // this isn't technically needed because mouseMoveEvent is suppressed during
2017  // Qt drag operations, replaced by dragMoveEvent
2018  return;
2019  }
2020 
2021  if (_actSel == 0) return;
2022 
2023 // don't extend selection while pasting
2024  if (ev->buttons() & Qt::MidButton) return;
2025 
2026  extendSelection(ev->pos());
2027 }
2028 
2029 void TerminalDisplay::leaveEvent(QEvent *)
2030 {
2031  // remove underline from an active link when cursor leaves the widget area
2032  if(!_mouseOverHotspotArea.isEmpty()) {
2033  update(_mouseOverHotspotArea);
2034  _mouseOverHotspotArea = QRegion();
2035  }
2036 }
2037 
2038 void TerminalDisplay::extendSelection(const QPoint& position)
2039 {
2040  if (!_screenWindow)
2041  return;
2042 
2043  //if ( !contentsRect().contains(ev->pos()) ) return;
2044  const QPoint tL = contentsRect().topLeft();
2045  const int tLx = tL.x();
2046  const int tLy = tL.y();
2047  const int scroll = _scrollBar->value();
2048 
2049  // we're in the process of moving the mouse with the left button pressed
2050  // the mouse cursor will kept caught within the bounds of the text in
2051  // this widget.
2052 
2053  int linesBeyondWidget = 0;
2054 
2055  QRect textBounds(tLx + _contentRect.left(),
2056  tLy + _contentRect.top(),
2057  _usedColumns * _fontWidth - 1,
2058  _usedLines * _fontHeight - 1);
2059 
2060  QPoint pos = position;
2061 
2062  // Adjust position within text area bounds.
2063  const QPoint oldpos = pos;
2064 
2065  pos.setX(qBound(textBounds.left(), pos.x(), textBounds.right()));
2066  pos.setY(qBound(textBounds.top(), pos.y(), textBounds.bottom()));
2067 
2068  if (oldpos.y() > textBounds.bottom()) {
2069  linesBeyondWidget = (oldpos.y() - textBounds.bottom()) / _fontHeight;
2070  _scrollBar->setValue(_scrollBar->value() + linesBeyondWidget + 1); // scrollforward
2071  }
2072  if (oldpos.y() < textBounds.top()) {
2073  linesBeyondWidget = (textBounds.top() - oldpos.y()) / _fontHeight;
2074  _scrollBar->setValue(_scrollBar->value() - linesBeyondWidget - 1); // history
2075  }
2076 
2077  int charColumn = 0;
2078  int charLine = 0;
2079  getCharacterPosition(pos, charLine, charColumn);
2080 
2081  QPoint here = QPoint(charColumn, charLine);
2082  QPoint ohere;
2083  QPoint _iPntSelCorr = _iPntSel;
2084  _iPntSelCorr.ry() -= _scrollBar->value();
2085  QPoint _pntSelCorr = _pntSel;
2086  _pntSelCorr.ry() -= _scrollBar->value();
2087  bool swapping = false;
2088 
2089  if (_wordSelectionMode) {
2090  // Extend to word boundaries
2091  const bool left_not_right = (here.y() < _iPntSelCorr.y() ||
2092  (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));
2093  const bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||
2094  (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));
2095  swapping = left_not_right != old_left_not_right;
2096 
2097  if (left_not_right) {
2098  ohere = findWordEnd(_iPntSelCorr);
2099  here = findWordStart(here);
2100  } else {
2101  ohere = findWordStart(_iPntSelCorr);
2102  here = findWordEnd(here);
2103  }
2104  ohere.rx()++;
2105  }
2106 
2107  if (_lineSelectionMode) {
2108  // Extend to complete line
2109  const bool above_not_below = (here.y() < _iPntSelCorr.y());
2110  if (above_not_below) {
2111  ohere = findLineEnd(_iPntSelCorr);
2112  here = findLineStart(here);
2113  } else {
2114  ohere = findLineStart(_iPntSelCorr);
2115  here = findLineEnd(here);
2116  }
2117 
2118  swapping = !(_tripleSelBegin == ohere);
2119  _tripleSelBegin = ohere;
2120 
2121  ohere.rx()++;
2122  }
2123 
2124  int offset = 0;
2125  if (!_wordSelectionMode && !_lineSelectionMode) {
2126  QChar selClass;
2127 
2128  const bool left_not_right = (here.y() < _iPntSelCorr.y() ||
2129  (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));
2130  const bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||
2131  (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));
2132  swapping = left_not_right != old_left_not_right;
2133 
2134  // Find left (left_not_right ? from here : from start)
2135  const QPoint left = left_not_right ? here : _iPntSelCorr;
2136 
2137  // Find left (left_not_right ? from start : from here)
2138  QPoint right = left_not_right ? _iPntSelCorr : here;
2139  if (right.x() > 0 && !_columnSelectionMode) {
2140  int i = loc(right.x(), right.y());
2141  if (i >= 0 && i <= _imageSize) {
2142  selClass = charClass(_image[i - 1]);
2143  /* if (selClass == ' ')
2144  {
2145  while ( right.x() < _usedColumns-1 && charClass(_image[i+1].character) == selClass && (right.y()<_usedLines-1) &&
2146  !(_lineProperties[right.y()] & LINE_WRAPPED))
2147  { i++; right.rx()++; }
2148  if (right.x() < _usedColumns-1)
2149  right = left_not_right ? _iPntSelCorr : here;
2150  else
2151  right.rx()++; // will be balanced later because of offset=-1;
2152  }*/
2153  }
2154  }
2155 
2156  // Pick which is start (ohere) and which is extension (here)
2157  if (left_not_right) {
2158  here = left;
2159  ohere = right;
2160  offset = 0;
2161  } else {
2162  here = right;
2163  ohere = left;
2164  offset = -1;
2165  }
2166  }
2167 
2168  if ((here == _pntSelCorr) && (scroll == _scrollBar->value())) return; // not moved
2169 
2170  if (here == ohere) return; // It's not left, it's not right.
2171 
2172  if (_actSel < 2 || swapping) {
2173  if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) {
2174  _screenWindow->setSelectionStart(ohere.x() , ohere.y() , true);
2175  } else {
2176  _screenWindow->setSelectionStart(ohere.x() - 1 - offset , ohere.y() , false);
2177  }
2178  }
2179 
2180  _actSel = 2; // within selection
2181  _pntSel = here;
2182  _pntSel.ry() += _scrollBar->value();
2183 
2184  if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) {
2185  _screenWindow->setSelectionEnd(here.x() , here.y());
2186  } else {
2187  _screenWindow->setSelectionEnd(here.x() + offset , here.y());
2188  }
2189 }
2190 
2191 void TerminalDisplay::mouseReleaseEvent(QMouseEvent* ev)
2192 {
2193  if (!_screenWindow)
2194  return;
2195 
2196  int charLine;
2197  int charColumn;
2198  getCharacterPosition(ev->pos(), charLine, charColumn);
2199 
2200  if (ev->button() == Qt::LeftButton) {
2201  if (_dragInfo.state == diPending) {
2202  // We had a drag event pending but never confirmed. Kill selection
2203  _screenWindow->clearSelection();
2204  } else {
2205  if (_actSel > 1) {
2206  copyToX11Selection();
2207  }
2208 
2209  _actSel = 0;
2210 
2211  //FIXME: emits a release event even if the mouse is
2212  // outside the range. The procedure used in `mouseMoveEvent'
2213  // applies here, too.
2214 
2215  if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
2216  emit mouseSignal(0,
2217  charColumn + 1,
2218  charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , 2);
2219  }
2220  _dragInfo.state = diNone;
2221  }
2222 
2223  if (!_mouseMarks &&
2224  (ev->button() == Qt::RightButton || ev->button() == Qt::MidButton) &&
2225  !(ev->modifiers() & Qt::ShiftModifier)) {
2226  emit mouseSignal(ev->button() == Qt::MidButton ? 1 : 2,
2227  charColumn + 1,
2228  charLine + 1 + _scrollBar->value() - _scrollBar->maximum() ,
2229  2);
2230  }
2231 }
2232 
2233 void TerminalDisplay::getCharacterPosition(const QPoint& widgetPoint, int& line, int& column) const
2234 {
2235  column = (widgetPoint.x() + _fontWidth / 2 - contentsRect().left() - _contentRect.left()) / _fontWidth;
2236  line = (widgetPoint.y() - contentsRect().top() - _contentRect.top()) / _fontHeight;
2237 
2238  if (line < 0)
2239  line = 0;
2240  if (column < 0)
2241  column = 0;
2242 
2243  if (line >= _usedLines)
2244  line = _usedLines - 1;
2245 
2246  // the column value returned can be equal to _usedColumns, which
2247  // is the position just after the last character displayed in a line.
2248  //
2249  // this is required so that the user can select characters in the right-most
2250  // column (or left-most for right-to-left input)
2251  if (column > _usedColumns)
2252  column = _usedColumns;
2253 }
2254 
2255 void TerminalDisplay::updateLineProperties()
2256 {
2257  if (!_screenWindow)
2258  return;
2259 
2260  _lineProperties = _screenWindow->getLineProperties();
2261 }
2262 
2263 void TerminalDisplay::processMidButtonClick(QMouseEvent* ev)
2264 {
2265  if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) {
2266  const bool appendEnter = ev->modifiers() & Qt::ControlModifier;
2267 
2268  if (_middleClickPasteMode == Enum::PasteFromX11Selection) {
2269  pasteFromX11Selection(appendEnter);
2270  } else if (_middleClickPasteMode == Enum::PasteFromClipboard) {
2271  pasteFromClipboard(appendEnter);
2272  } else {
2273  Q_ASSERT(false);
2274  }
2275  } else {
2276  int charLine = 0;
2277  int charColumn = 0;
2278  getCharacterPosition(ev->pos(), charLine, charColumn);
2279 
2280  emit mouseSignal(1, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , 0);
2281  }
2282 }
2283 
2284 void TerminalDisplay::mouseDoubleClickEvent(QMouseEvent* ev)
2285 {
2286  // Yes, successive middle click can trigger this event
2287  if (ev->button() == Qt::MidButton) {
2288  processMidButtonClick(ev);
2289  return;
2290  }
2291 
2292  if (ev->button() != Qt::LeftButton) return;
2293  if (!_screenWindow) return;
2294 
2295  int charLine = 0;
2296  int charColumn = 0;
2297 
2298  getCharacterPosition(ev->pos(), charLine, charColumn);
2299 
2300  // pass on double click as two clicks.
2301  if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) {
2302  // Send just _ONE_ click event, since the first click of the double click
2303  // was already sent by the click handler
2304  emit mouseSignal(0, charColumn + 1,
2305  charLine + 1 + _scrollBar->value() - _scrollBar->maximum(),
2306  0); // left button
2307  return;
2308  }
2309 
2310  _screenWindow->clearSelection();
2311 
2312  _wordSelectionMode = true;
2313  _actSel = 2; // within selection
2314 
2315  _iPntSel = QPoint(charColumn, charLine);
2316  const QPoint bgnSel = findWordStart(_iPntSel);
2317  const QPoint endSel = findWordEnd(_iPntSel);
2318  _iPntSel.ry() += _scrollBar->value();
2319 
2320  _screenWindow->setSelectionStart(bgnSel.x() , bgnSel.y() , false);
2321  _screenWindow->setSelectionEnd(endSel.x() , endSel.y());
2322  copyToX11Selection();
2323 
2324  _possibleTripleClick = true;
2325 
2326  QTimer::singleShot(QApplication::doubleClickInterval(), this,
2327  SLOT(tripleClickTimeout()));
2328 }
2329 
2330 void TerminalDisplay::wheelEvent(QWheelEvent* ev)
2331 {
2332  // Only vertical scrolling is supported
2333  if (ev->orientation() != Qt::Vertical)
2334  return;
2335 
2336  const int modifiers = ev->modifiers();
2337  const int delta = ev->delta();
2338 
2339  // ctrl+<wheel> for zooming, like in konqueror and firefox
2340  if ((modifiers & Qt::ControlModifier) && mouseWheelZoom()) {
2341  if (delta > 0) {
2342  // wheel-up for increasing font size
2343  increaseFontSize();
2344  } else {
2345  // wheel-down for decreasing font size
2346  decreaseFontSize();
2347  }
2348 
2349  return;
2350  }
2351 
2352  // if the terminal program is not interested with mouse events:
2353  // * send the event to the scrollbar if the slider has room to move
2354  // * otherwise, send simulated up / down key presses to the terminal program
2355  // for the benefit of programs such as 'less'
2356  if (_mouseMarks) {
2357  const bool canScroll = _scrollBar->maximum() > 0;
2358  if (canScroll) {
2359  _scrollBar->event(ev);
2360  _sessionController->setSearchStartToWindowCurrentLine();
2361  } else {
2362  // assume that each Up / Down key event will cause the terminal application
2363  // to scroll by one line.
2364  //
2365  // to get a reasonable scrolling speed, scroll by one line for every 5 degrees
2366  // of mouse wheel rotation. Mouse wheels typically move in steps of 15 degrees,
2367  // giving a scroll of 3 lines
2368  const int keyCode = delta > 0 ? Qt::Key_Up : Qt::Key_Down;
2369  QKeyEvent keyEvent(QEvent::KeyPress, keyCode, Qt::NoModifier);
2370 
2371  // QWheelEvent::delta() gives rotation in eighths of a degree
2372  const int degrees = delta / 8;
2373  const int lines = abs(degrees) / 5;
2374 
2375  for (int i = 0; i < lines; i++)
2376  emit keyPressedSignal(&keyEvent);
2377  }
2378  } else {
2379  // terminal program wants notification of mouse activity
2380 
2381  int charLine;
2382  int charColumn;
2383  getCharacterPosition(ev->pos() , charLine , charColumn);
2384 
2385  emit mouseSignal(delta > 0 ? 4 : 5,
2386  charColumn + 1,
2387  charLine + 1 + _scrollBar->value() - _scrollBar->maximum() ,
2388  0);
2389  }
2390 }
2391 
2392 void TerminalDisplay::tripleClickTimeout()
2393 {
2394  _possibleTripleClick = false;
2395 }
2396 
2397 void TerminalDisplay::viewScrolledByUser()
2398 {
2399  _sessionController->setSearchStartToWindowCurrentLine();
2400 }
2401 
2402 /* Moving left/up from the line containing pnt, return the starting
2403  offset point which the given line is continiously wrapped
2404  (top left corner = 0,0; previous line not visible = 0,-1).
2405 */
2406 QPoint TerminalDisplay::findLineStart(const QPoint &pnt)
2407 {
2408  const int visibleScreenLines = _lineProperties.size();
2409  const int topVisibleLine = _screenWindow->currentLine();
2410  Screen *screen = _screenWindow->screen();
2411  int line = pnt.y();
2412  int lineInHistory= line + topVisibleLine;
2413 
2414  QVector<LineProperty> lineProperties = _lineProperties;
2415 
2416  while (lineInHistory > 0) {
2417  for (; line > 0; line--, lineInHistory--) {
2418  // Does previous line wrap around?
2419  if (!(lineProperties[line - 1] & LINE_WRAPPED)) {
2420  return QPoint(0, lineInHistory - topVisibleLine);
2421  }
2422  }
2423 
2424  if (lineInHistory < 1)
2425  break;
2426 
2427  // _lineProperties is only for the visible screen, so grab new data
2428  int newRegionStart = qMax(0, lineInHistory - visibleScreenLines);
2429  lineProperties = screen->getLineProperties(newRegionStart, lineInHistory - 1);
2430  line = lineInHistory - newRegionStart;
2431  }
2432  return QPoint(0, lineInHistory - topVisibleLine);
2433 }
2434 
2435 /* Moving right/down from the line containing pnt, return the ending
2436  offset point which the given line is continiously wrapped.
2437 */
2438 QPoint TerminalDisplay::findLineEnd(const QPoint &pnt)
2439 {
2440  const int visibleScreenLines = _lineProperties.size();
2441  const int topVisibleLine = _screenWindow->currentLine();
2442  const int maxY = _screenWindow->lineCount() - 1;
2443  Screen *screen = _screenWindow->screen();
2444  int line = pnt.y();
2445  int lineInHistory= line + topVisibleLine;
2446 
2447  QVector<LineProperty> lineProperties = _lineProperties;
2448 
2449  while (lineInHistory < maxY) {
2450  for (; line < lineProperties.count() && lineInHistory < maxY; line++, lineInHistory++) {
2451  // Does current line wrap around?
2452  if (!(lineProperties[line] & LINE_WRAPPED)) {
2453  return QPoint(_columns - 1, lineInHistory - topVisibleLine);
2454  }
2455  }
2456 
2457  line = 0;
2458  lineProperties = screen->getLineProperties(lineInHistory, qMin(lineInHistory + visibleScreenLines, maxY));
2459  }
2460  return QPoint(_columns - 1, lineInHistory - topVisibleLine);
2461 }
2462 
2463 QPoint TerminalDisplay::findWordStart(const QPoint &pnt)
2464 {
2465  const int regSize = qMax(_screenWindow->windowLines(), 10);
2466  const int curLine = _screenWindow->currentLine();
2467  int i = pnt.y();
2468  int x = pnt.x();
2469  int y = i + curLine;
2470  int j = loc(x, i);
2471  QVector<LineProperty> lineProperties = _lineProperties;
2472  Screen *screen = _screenWindow->screen();
2473  Character *image = _image;
2474  Character *tmp_image = NULL;
2475  const QChar selClass = charClass(image[j]);
2476  const int imageSize = regSize * _columns;
2477 
2478  while (true) {
2479  for (;;j--, x--) {
2480  if (x > 0) {
2481  if (charClass(image[j - 1]) == selClass)
2482  continue;
2483  goto out;
2484  } else if (i > 0) {
2485  if (lineProperties[i - 1] & LINE_WRAPPED &&
2486  charClass(image[j - 1]) == selClass) {
2487  x = _columns;
2488  i--;
2489  y--;
2490  continue;
2491  }
2492  goto out;
2493  } else if (y > 0) {
2494  break;
2495  } else {
2496  goto out;
2497  }
2498  }
2499  int newRegStart = qMax(0, y - regSize);
2500  lineProperties = screen->getLineProperties(newRegStart, y - 1);
2501  i = y - newRegStart;
2502  if (!tmp_image) {
2503  tmp_image = new Character[imageSize];
2504  image = tmp_image;
2505  }
2506  screen->getImage(tmp_image, imageSize, newRegStart, y - 1);
2507  j = loc(x, i);
2508  }
2509 out:
2510  if (tmp_image) {
2511  delete[] tmp_image;
2512  }
2513  return QPoint(x, y - curLine);
2514 }
2515 
2516 QPoint TerminalDisplay::findWordEnd(const QPoint &pnt)
2517 {
2518  const int regSize = qMax(_screenWindow->windowLines(), 10);
2519  const int curLine = _screenWindow->currentLine();
2520  int i = pnt.y();
2521  int x = pnt.x();
2522  int y = i + curLine;
2523  int j = loc(x, i);
2524  QVector<LineProperty> lineProperties = _lineProperties;
2525  Screen *screen = _screenWindow->screen();
2526  Character *image = _image;
2527  Character *tmp_image = NULL;
2528  const QChar selClass = charClass(image[j]);
2529  const int imageSize = regSize * _columns;
2530  const int maxY = _screenWindow->lineCount() - 1;
2531  const int maxX = _columns - 1;
2532 
2533  while (true) {
2534  const int lineCount = lineProperties.count();
2535  for (;;j++, x++) {
2536  if (x < maxX) {
2537  if (charClass(image[j + 1]) == selClass)
2538  continue;
2539  goto out;
2540  } else if (i < lineCount - 1) {
2541  if (lineProperties[i] & LINE_WRAPPED &&
2542  charClass(image[j + 1]) == selClass) {
2543  x = -1;
2544  i++;
2545  y++;
2546  continue;
2547  }
2548  goto out;
2549  } else if (y < maxY) {
2550  if (i < lineCount && !(lineProperties[i] & LINE_WRAPPED))
2551  goto out;
2552  break;
2553  } else {
2554  goto out;
2555  }
2556  }
2557  int newRegEnd = qMin(y + regSize - 1, maxY);
2558  lineProperties = screen->getLineProperties(y, newRegEnd);
2559  i = 0;
2560  if (!tmp_image) {
2561  tmp_image = new Character[imageSize];
2562  image = tmp_image;
2563  }
2564  screen->getImage(tmp_image, imageSize, y, newRegEnd);
2565  x--;
2566  j = loc(x, i);
2567  }
2568 out:
2569  y -= curLine;
2570  // In word selection mode don't select @ (64) if at end of word.
2571  if (((image[j].rendition & RE_EXTENDED_CHAR) == 0) &&
2572  (QChar(image[j].character) == '@') &&
2573  (y > pnt.y() || x > pnt.x())) {
2574  if (x > 0) {
2575  x--;
2576  } else {
2577  y--;
2578  }
2579  }
2580  if (tmp_image) {
2581  delete[] tmp_image;
2582  }
2583  return QPoint(x, y);
2584 }
2585 
2586 void TerminalDisplay::mouseTripleClickEvent(QMouseEvent* ev)
2587 {
2588  if (!_screenWindow) return;
2589 
2590  int charLine;
2591  int charColumn;
2592  getCharacterPosition(ev->pos(), charLine, charColumn);
2593  selectLine(QPoint(charColumn, charLine),
2594  _tripleClickMode == Enum::SelectWholeLine);
2595 }
2596 
2597 void TerminalDisplay::selectLine(QPoint pos, bool entireLine)
2598 {
2599  _iPntSel = pos;
2600 
2601  _screenWindow->clearSelection();
2602 
2603  _lineSelectionMode = true;
2604  _wordSelectionMode = false;
2605 
2606  _actSel = 2; // within selection
2607 
2608  if (!entireLine) { // Select from cursor to end of line
2609  _tripleSelBegin = findWordStart(_iPntSel);
2610  _screenWindow->setSelectionStart(_tripleSelBegin.x(),
2611  _tripleSelBegin.y() , false);
2612  } else {
2613  _tripleSelBegin = findLineStart(_iPntSel);
2614  _screenWindow->setSelectionStart(0 , _tripleSelBegin.y() , false);
2615  }
2616 
2617  _iPntSel = findLineEnd(_iPntSel);
2618  _screenWindow->setSelectionEnd(_iPntSel.x() , _iPntSel.y());
2619 
2620  copyToX11Selection();
2621 
2622  _iPntSel.ry() += _scrollBar->value();
2623 }
2624 
2625 void TerminalDisplay::selectCurrentLine()
2626 {
2627  if (!_screenWindow) return;
2628 
2629  selectLine(cursorPosition(), true);
2630 }
2631 
2632 bool TerminalDisplay::focusNextPrevChild(bool next)
2633 {
2634  // for 'Tab', always disable focus switching among widgets
2635  // for 'Shift+Tab', leave the decision to higher level
2636  if (next)
2637  return false;
2638  else
2639  return QWidget::focusNextPrevChild(next);
2640 }
2641 
2642 QChar TerminalDisplay::charClass(const Character& ch) const
2643 {
2644  if (ch.rendition & RE_EXTENDED_CHAR) {
2645  ushort extendedCharLength = 0;
2646  const ushort* chars = ExtendedCharTable::instance.lookupExtendedChar(ch.character, extendedCharLength);
2647  if (chars && extendedCharLength > 0) {
2648  const QString s = QString::fromUtf16(chars, extendedCharLength);
2649  if (_wordCharacters.contains(s, Qt::CaseInsensitive))
2650  return 'a';
2651  bool allLetterOrNumber = true;
2652  for (int i = 0; allLetterOrNumber && i < s.size(); ++i)
2653  allLetterOrNumber = s.at(i).isLetterOrNumber();
2654  return allLetterOrNumber ? 'a' : s.at(0);
2655  }
2656  return 0;
2657  } else {
2658  const QChar qch(ch.character);
2659  if (qch.isSpace()) return ' ';
2660 
2661  if (qch.isLetterOrNumber() || _wordCharacters.contains(qch, Qt::CaseInsensitive))
2662  return 'a';
2663 
2664  return qch;
2665  }
2666 }
2667 
2668 void TerminalDisplay::setWordCharacters(const QString& wc)
2669 {
2670  _wordCharacters = wc;
2671 }
2672 
2673 // FIXME: the actual value of _mouseMarks is the opposite of its semantic.
2674 // When using programs not interested with mouse(shell, less), it is true.
2675 // When using programs interested with mouse(vim,mc), it is false.
2676 void TerminalDisplay::setUsesMouse(bool on)
2677 {
2678  _mouseMarks = on;
2679  setCursor(_mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor);
2680 }
2681 bool TerminalDisplay::usesMouse() const
2682 {
2683  return _mouseMarks;
2684 }
2685 
2686 void TerminalDisplay::setBracketedPasteMode(bool on)
2687 {
2688  _bracketedPasteMode = on;
2689 }
2690 bool TerminalDisplay::bracketedPasteMode() const
2691 {
2692  return _bracketedPasteMode;
2693 }
2694 
2695 /* ------------------------------------------------------------------------- */
2696 /* */
2697 /* Clipboard */
2698 /* */
2699 /* ------------------------------------------------------------------------- */
2700 
2701 void TerminalDisplay::doPaste(QString text, bool appendReturn)
2702 {
2703  if (!_screenWindow)
2704  return;
2705 
2706  if (appendReturn)
2707  text.append("\r");
2708 
2709  if (text.length() > 8000) {
2710  if (KMessageBox::warningContinueCancel(window(),
2711  i18np("Are you sure you want to paste %1 character?",
2712  "Are you sure you want to paste %1 characters?",
2713  text.length()),
2714  i18n("Confirm Paste"),
2715  KStandardGuiItem::cont(),
2716  KStandardGuiItem::cancel(),
2717  "ShowPasteHugeTextWarning") == KMessageBox::Cancel)
2718  return;
2719  }
2720 
2721  if (!text.isEmpty()) {
2722  text.replace('\n', '\r');
2723  if (bracketedPasteMode()) {
2724  text.prepend("\e[200~");
2725  text.append("\e[201~");
2726  }
2727  // perform paste by simulating keypress events
2728  QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text);
2729  emit keyPressedSignal(&e);
2730  }
2731 }
2732 
2733 void TerminalDisplay::setAutoCopySelectedText(bool enabled)
2734 {
2735  _autoCopySelectedText = enabled;
2736 }
2737 
2738 void TerminalDisplay::setMiddleClickPasteMode(Enum::MiddleClickPasteModeEnum mode)
2739 {
2740  _middleClickPasteMode = mode;
2741 }
2742 
2743 void TerminalDisplay::copyToX11Selection()
2744 {
2745  if (!_screenWindow)
2746  return;
2747 
2748  QString text = _screenWindow->selectedText(_preserveLineBreaks, _trimTrailingSpaces);
2749  if (text.isEmpty())
2750  return;
2751 
2752  QApplication::clipboard()->setText(text, QClipboard::Selection);
2753 
2754  if (_autoCopySelectedText)
2755  QApplication::clipboard()->setText(text, QClipboard::Clipboard);
2756 }
2757 
2758 void TerminalDisplay::copyToClipboard()
2759 {
2760  if (!_screenWindow)
2761  return;
2762 
2763  QString text = _screenWindow->selectedText(_preserveLineBreaks, _trimTrailingSpaces);
2764  if (text.isEmpty())
2765  return;
2766 
2767  QApplication::clipboard()->setText(text, QClipboard::Clipboard);
2768 }
2769 
2770 void TerminalDisplay::pasteFromClipboard(bool appendEnter)
2771 {
2772  QString text = QApplication::clipboard()->text(QClipboard::Clipboard);
2773  doPaste(text, appendEnter);
2774 }
2775 
2776 void TerminalDisplay::pasteFromX11Selection(bool appendEnter)
2777 {
2778  QString text = QApplication::clipboard()->text(QClipboard::Selection);
2779  doPaste(text, appendEnter);
2780 }
2781 
2782 /* ------------------------------------------------------------------------- */
2783 /* */
2784 /* Input Method */
2785 /* */
2786 /* ------------------------------------------------------------------------- */
2787 
2788 void TerminalDisplay::inputMethodEvent(QInputMethodEvent* event)
2789 {
2790  if (!event->commitString().isEmpty()) {
2791  QKeyEvent keyEvent(QEvent::KeyPress, 0, Qt::NoModifier, event->commitString());
2792  emit keyPressedSignal(&keyEvent);
2793  }
2794 
2795  _inputMethodData.preeditString = event->preeditString();
2796  update(preeditRect() | _inputMethodData.previousPreeditRect);
2797 
2798  event->accept();
2799 }
2800 
2801 QVariant TerminalDisplay::inputMethodQuery(Qt::InputMethodQuery query) const
2802 {
2803  const QPoint cursorPos = cursorPosition();
2804  switch (query) {
2805  case Qt::ImMicroFocus:
2806  return imageToWidget(QRect(cursorPos.x(), cursorPos.y(), 1, 1));
2807  break;
2808  case Qt::ImFont:
2809  return font();
2810  break;
2811  case Qt::ImCursorPosition:
2812  // return the cursor position within the current line
2813  return cursorPos.x();
2814  break;
2815  case Qt::ImSurroundingText: {
2816  // return the text from the current line
2817  QString lineText;
2818  QTextStream stream(&lineText);
2819  PlainTextDecoder decoder;
2820  decoder.begin(&stream);
2821  decoder.decodeLine(&_image[loc(0, cursorPos.y())], _usedColumns, _lineProperties[cursorPos.y()]);
2822  decoder.end();
2823  return lineText;
2824  }
2825  break;
2826  case Qt::ImCurrentSelection:
2827  return QString();
2828  break;
2829  default:
2830  break;
2831  }
2832 
2833  return QVariant();
2834 }
2835 
2836 QRect TerminalDisplay::preeditRect() const
2837 {
2838  const int preeditLength = string_width(_inputMethodData.preeditString);
2839 
2840  if (preeditLength == 0)
2841  return QRect();
2842 
2843  return QRect(_contentRect.left() + _fontWidth * cursorPosition().x(),
2844  _contentRect.top() + _fontHeight * cursorPosition().y(),
2845  _fontWidth * preeditLength,
2846  _fontHeight);
2847 }
2848 
2849 void TerminalDisplay::drawInputMethodPreeditString(QPainter& painter , const QRect& rect)
2850 {
2851  if (_inputMethodData.preeditString.isEmpty())
2852  return;
2853 
2854  const QPoint cursorPos = cursorPosition();
2855 
2856  bool invertColors = false;
2857  const QColor background = _colorTable[DEFAULT_BACK_COLOR].color;
2858  const QColor foreground = _colorTable[DEFAULT_FORE_COLOR].color;
2859  const Character* style = &_image[loc(cursorPos.x(), cursorPos.y())];
2860 
2861  drawBackground(painter, rect, background, true);
2862  drawCursor(painter, rect, foreground, background, invertColors);
2863  drawCharacters(painter, rect, _inputMethodData.preeditString, style, invertColors);
2864 
2865  _inputMethodData.previousPreeditRect = rect;
2866 }
2867 
2868 /* ------------------------------------------------------------------------- */
2869 /* */
2870 /* Keyboard */
2871 /* */
2872 /* ------------------------------------------------------------------------- */
2873 
2874 void TerminalDisplay::setFlowControlWarningEnabled(bool enable)
2875 {
2876  _flowControlWarningEnabled = enable;
2877 
2878  // if the dialog is currently visible and the flow control warning has
2879  // been disabled then hide the dialog
2880  if (!enable)
2881  outputSuspended(false);
2882 }
2883 
2884 void TerminalDisplay::outputSuspended(bool suspended)
2885 {
2886  //create the label when this function is first called
2887  if (!_outputSuspendedLabel) {
2888  //This label includes a link to an English language website
2889  //describing the 'flow control' (Xon/Xoff) feature found in almost
2890  //all terminal emulators.
2891  //If there isn't a suitable article available in the target language the link
2892  //can simply be removed.
2893  _outputSuspendedLabel = new QLabel(i18n("<qt>Output has been "
2894  "<a href=\"http://en.wikipedia.org/wiki/Software_flow_control\">suspended</a>"
2895  " by pressing Ctrl+S."
2896  " Press <b>Ctrl+Q</b> to resume."
2897  " This message will be dismissed in 10 seconds.</qt>"),
2898  this);
2899 
2900  QPalette palette(_outputSuspendedLabel->palette());
2901  KColorScheme::adjustBackground(palette, KColorScheme::NeutralBackground);
2902  _outputSuspendedLabel->setPalette(palette);
2903  _outputSuspendedLabel->setAutoFillBackground(true);
2904  _outputSuspendedLabel->setBackgroundRole(QPalette::Base);
2905  _outputSuspendedLabel->setFont(KGlobalSettings::smallestReadableFont());
2906  _outputSuspendedLabel->setContentsMargins(5, 5, 5, 5);
2907  _outputSuspendedLabel->setWordWrap(true);
2908 
2909  //enable activation of "Xon/Xoff" link in label
2910  _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse |
2911  Qt::LinksAccessibleByKeyboard);
2912  _outputSuspendedLabel->setOpenExternalLinks(true);
2913  _outputSuspendedLabel->setVisible(false);
2914 
2915  _gridLayout->addWidget(_outputSuspendedLabel);
2916  _gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding,
2917  QSizePolicy::Expanding),
2918  1, 0);
2919  }
2920  // Remove message after a few seconds
2921  if (suspended) {
2922  QTimer::singleShot(10000, this, SLOT(dismissOutputSuspendedMessage()));
2923  }
2924 
2925  _outputSuspendedLabel->setVisible(suspended);
2926 }
2927 
2928 void TerminalDisplay::dismissOutputSuspendedMessage()
2929 {
2930  outputSuspended(false);
2931 }
2932 
2933 void TerminalDisplay::scrollScreenWindow(enum ScreenWindow::RelativeScrollMode mode, int amount)
2934 {
2935  _screenWindow->scrollBy(mode, amount, _scrollFullPage);
2936  _screenWindow->setTrackOutput(_screenWindow->atEndOfOutput());
2937  updateLineProperties();
2938  updateImage();
2939  viewScrolledByUser();
2940 }
2941 
2942 void TerminalDisplay::keyPressEvent(QKeyEvent* event)
2943 {
2944  _screenWindow->screen()->setCurrentTerminalDisplay(this);
2945 
2946  _actSel = 0; // Key stroke implies a screen update, so TerminalDisplay won't
2947  // know where the current selection is.
2948 
2949  if (_allowBlinkingCursor) {
2950  _blinkCursorTimer->start();
2951  if (_cursorBlinking) {
2952  // if cursor is blinking(hidden), blink it again to show it
2953  blinkCursorEvent();
2954  }
2955  Q_ASSERT(_cursorBlinking == false);
2956  }
2957 
2958  emit keyPressedSignal(event);
2959 
2960 #if QT_VERSION >= 0x040800 // added in Qt 4.8.0
2961 #ifndef QT_NO_ACCESSIBILITY
2962  QAccessible::updateAccessibility(this, 0, QAccessible::TextCaretMoved);
2963 #endif
2964 #endif
2965 
2966  event->accept();
2967 }
2968 
2969 bool TerminalDisplay::handleShortcutOverrideEvent(QKeyEvent* keyEvent)
2970 {
2971  const int modifiers = keyEvent->modifiers();
2972 
2973  // When a possible shortcut combination is pressed,
2974  // emit the overrideShortcutCheck() signal to allow the host
2975  // to decide whether the terminal should override it or not.
2976  if (modifiers != Qt::NoModifier) {
2977  int modifierCount = 0;
2978  unsigned int currentModifier = Qt::ShiftModifier;
2979 
2980  while (currentModifier <= Qt::KeypadModifier) {
2981  if (modifiers & currentModifier)
2982  modifierCount++;
2983  currentModifier <<= 1;
2984  }
2985  if (modifierCount < 2) {
2986  bool override = false;
2987  emit overrideShortcutCheck(keyEvent, override);
2988  if (override) {
2989  keyEvent->accept();
2990  return true;
2991  }
2992  }
2993  }
2994 
2995  // Override any of the following shortcuts because
2996  // they are needed by the terminal
2997  int keyCode = keyEvent->key() | modifiers;
2998  switch (keyCode) {
2999  // list is taken from the QLineEdit::event() code
3000  case Qt::Key_Tab:
3001  case Qt::Key_Delete:
3002  case Qt::Key_Home:
3003  case Qt::Key_End:
3004  case Qt::Key_Backspace:
3005  case Qt::Key_Left:
3006  case Qt::Key_Right:
3007  case Qt::Key_Slash:
3008  case Qt::Key_Period:
3009  case Qt::Key_Space:
3010  keyEvent->accept();
3011  return true;
3012  }
3013  return false;
3014 }
3015 
3016 bool TerminalDisplay::event(QEvent* event)
3017 {
3018  bool eventHandled = false;
3019  switch (event->type()) {
3020  case QEvent::ShortcutOverride:
3021  eventHandled = handleShortcutOverrideEvent(static_cast<QKeyEvent*>(event));
3022  break;
3023  case QEvent::PaletteChange:
3024  case QEvent::ApplicationPaletteChange:
3025  _scrollBar->setPalette(QApplication::palette());
3026  break;
3027  default:
3028  break;
3029  }
3030  return eventHandled ? true : QWidget::event(event);
3031 }
3032 
3033 void TerminalDisplay::contextMenuEvent(QContextMenuEvent* event)
3034 {
3035  // the logic for the mouse case is within MousePressEvent()
3036  if (event->reason() != QContextMenuEvent::Mouse) {
3037  emit configureRequest(mapFromGlobal(QCursor::pos()));
3038  }
3039 }
3040 
3041 /* --------------------------------------------------------------------- */
3042 /* */
3043 /* Bell */
3044 /* */
3045 /* --------------------------------------------------------------------- */
3046 
3047 void TerminalDisplay::setBellMode(int mode)
3048 {
3049  _bellMode = mode;
3050 }
3051 
3052 int TerminalDisplay::bellMode() const
3053 {
3054  return _bellMode;
3055 }
3056 
3057 void TerminalDisplay::unmaskBell()
3058 {
3059  _bellMasked = false;
3060 }
3061 
3062 void TerminalDisplay::bell(const QString& message)
3063 {
3064  if (_bellMasked)
3065  return;
3066 
3067  switch (_bellMode) {
3068  case Enum::SystemBeepBell:
3069  KNotification::beep();
3070  break;
3071  case Enum::NotifyBell:
3072  // STABLE API:
3073  // Please note that these event names, "BellVisible" and "BellInvisible",
3074  // should not change and should be kept stable, because other applications
3075  // that use this code via KPart rely on these names for notifications.
3076  KNotification::event(hasFocus() ? "BellVisible" : "BellInvisible",
3077  message, QPixmap(), this);
3078  break;
3079  case Enum::VisualBell:
3080  visualBell();
3081  break;
3082  default:
3083  break;
3084  }
3085 
3086  // limit the rate at which bells can occur.
3087  // ...mainly for sound effects where rapid bells in sequence
3088  // produce a horrible noise.
3089  _bellMasked = true;
3090  QTimer::singleShot(500, this, SLOT(unmaskBell()));
3091 }
3092 
3093 void TerminalDisplay::visualBell()
3094 {
3095  swapFGBGColors();
3096  QTimer::singleShot(200, this, SLOT(swapFGBGColors()));
3097 }
3098 
3099 void TerminalDisplay::swapFGBGColors()
3100 {
3101  // swap the default foreground & background color
3102  ColorEntry color = _colorTable[DEFAULT_BACK_COLOR];
3103  _colorTable[DEFAULT_BACK_COLOR] = _colorTable[DEFAULT_FORE_COLOR];
3104  _colorTable[DEFAULT_FORE_COLOR] = color;
3105 
3106  update();
3107 }
3108 
3109 /* --------------------------------------------------------------------- */
3110 /* */
3111 /* Drag & Drop */
3112 /* */
3113 /* --------------------------------------------------------------------- */
3114 
3115 void TerminalDisplay::dragEnterEvent(QDragEnterEvent* event)
3116 {
3117  // text/plain alone is enough for KDE-apps
3118  // text/uri-list is for supporting some non-KDE apps, such as thunar
3119  // and pcmanfm
3120  // That also applies in dropEvent()
3121  if (event->mimeData()->hasFormat("text/plain") ||
3122  event->mimeData()->hasFormat("text/uri-list")) {
3123  event->acceptProposedAction();
3124  }
3125 }
3126 
3127 void TerminalDisplay::dropEvent(QDropEvent* event)
3128 {
3129  KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
3130 
3131  QString dropText;
3132  if (!urls.isEmpty()) {
3133  for (int i = 0 ; i < urls.count() ; i++) {
3134  KUrl url = KIO::NetAccess::mostLocalUrl(urls[i] , 0);
3135  QString urlText;
3136 
3137  if (url.isLocalFile())
3138  urlText = url.path();
3139  else
3140  urlText = url.url();
3141 
3142  // in future it may be useful to be able to insert file names with drag-and-drop
3143  // without quoting them (this only affects paths with spaces in)
3144  urlText = KShell::quoteArg(urlText);
3145 
3146  dropText += urlText;
3147 
3148  // Each filename(including the last) should be followed by one space.
3149  dropText += ' ';
3150  }
3151 
3152 #if defined(HAVE_LIBKONQ)
3153  // If our target is local we will open a popup - otherwise the fallback kicks
3154  // in and the URLs will simply be pasted as text.
3155  if (_sessionController && _sessionController->url().isLocalFile()) {
3156  // A standard popup with Copy, Move and Link as options -
3157  // plus an additional Paste option.
3158 
3159  QAction* pasteAction = new QAction(i18n("&Paste Location"), this);
3160  pasteAction->setData(dropText);
3161  connect(pasteAction, SIGNAL(triggered()), this, SLOT(dropMenuPasteActionTriggered()));
3162 
3163  QList<QAction*> additionalActions;
3164  additionalActions.append(pasteAction);
3165 
3166  if (urls.count() == 1) {
3167  const KUrl url = KIO::NetAccess::mostLocalUrl(urls[0] , 0);
3168 
3169  if (url.isLocalFile()) {
3170  const QFileInfo fileInfo(url.path());
3171 
3172  if (fileInfo.isDir()) {
3173  QAction* cdAction = new QAction(i18n("Change &Directory To"), this);
3174  dropText = QLatin1String(" cd ") + dropText + QChar('\n');
3175  cdAction->setData(dropText);
3176  connect(cdAction, SIGNAL(triggered()), this, SLOT(dropMenuCdActionTriggered()));
3177  additionalActions.append(cdAction);
3178  }
3179  }
3180  }
3181 
3182  KUrl target(_sessionController->currentDir());
3183 
3184  KonqOperations::doDrop(KFileItem(), target, event, this, additionalActions);
3185 
3186  return;
3187  }
3188 #endif
3189 
3190  } else {
3191  dropText = event->mimeData()->text();
3192  }
3193 
3194  if (event->mimeData()->hasFormat("text/plain") ||
3195  event->mimeData()->hasFormat("text/uri-list")) {
3196  emit sendStringToEmu(dropText.toLocal8Bit());
3197  }
3198 }
3199 
3200 void TerminalDisplay::dropMenuPasteActionTriggered()
3201 {
3202  if (sender()) {
3203  const QAction* action = qobject_cast<const QAction*>(sender());
3204  if (action) {
3205  emit sendStringToEmu(action->data().toString().toLocal8Bit());
3206  }
3207  }
3208 }
3209 
3210 void TerminalDisplay::dropMenuCdActionTriggered()
3211 {
3212  if (sender()) {
3213  const QAction* action = qobject_cast<const QAction*>(sender());
3214  if (action) {
3215  emit sendStringToEmu(action->data().toString().toLocal8Bit());
3216  }
3217  }
3218 }
3219 
3220 void TerminalDisplay::doDrag()
3221 {
3222  _dragInfo.state = diDragging;
3223  _dragInfo.dragObject = new QDrag(this);
3224  QMimeData* mimeData = new QMimeData;
3225  mimeData->setText(QApplication::clipboard()->text(QClipboard::Selection));
3226  _dragInfo.dragObject->setMimeData(mimeData);
3227  _dragInfo.dragObject->exec(Qt::CopyAction);
3228 }
3229 
3230 void TerminalDisplay::setSessionController(SessionController* controller)
3231 {
3232  _sessionController = controller;
3233 }
3234 
3235 SessionController* TerminalDisplay::sessionController()
3236 {
3237  return _sessionController;
3238 }
3239 
3240 AutoScrollHandler::AutoScrollHandler(QWidget* parent)
3241  : QObject(parent)
3242  , _timerId(0)
3243 {
3244  parent->installEventFilter(this);
3245 }
3246 void AutoScrollHandler::timerEvent(QTimerEvent* event)
3247 {
3248  if (event->timerId() != _timerId)
3249  return;
3250 
3251  QMouseEvent mouseEvent(QEvent::MouseMove,
3252  widget()->mapFromGlobal(QCursor::pos()),
3253  Qt::NoButton,
3254  Qt::LeftButton,
3255  Qt::NoModifier);
3256 
3257  QApplication::sendEvent(widget(), &mouseEvent);
3258 }
3259 bool AutoScrollHandler::eventFilter(QObject* watched, QEvent* event)
3260 {
3261  Q_ASSERT(watched == parent());
3262  Q_UNUSED(watched);
3263 
3264  QMouseEvent* mouseEvent = (QMouseEvent*)event;
3265  switch (event->type()) {
3266  case QEvent::MouseMove: {
3267  bool mouseInWidget = widget()->rect().contains(mouseEvent->pos());
3268  if (mouseInWidget) {
3269  if (_timerId)
3270  killTimer(_timerId);
3271 
3272  _timerId = 0;
3273  } else {
3274  if (!_timerId && (mouseEvent->buttons() & Qt::LeftButton))
3275  _timerId = startTimer(100);
3276  }
3277 
3278  break;
3279  }
3280  case QEvent::MouseButtonRelease: {
3281  if (_timerId && (mouseEvent->buttons() & ~Qt::LeftButton)) {
3282  killTimer(_timerId);
3283  _timerId = 0;
3284  }
3285  break;
3286  }
3287  default:
3288  break;
3289  };
3290 
3291  return false;
3292 }
3293 
3294 #include "TerminalDisplay.moc"
QHideEvent
Konsole::TerminalDisplay::resizeEvent
virtual void resizeEvent(QResizeEvent *event)
Definition: TerminalDisplay.cpp:1612
QSpacerItem
Konsole::TerminalDisplay::setWordCharacters
void setWordCharacters(const QString &wc)
Sets which characters, in addition to letters and numbers, are regarded as being part of a word for t...
Definition: TerminalDisplay.cpp:2668
QTimer::setInterval
void setInterval(int msec)
Session.h
LineEncode
LineEncode
A table for emulating the simple (single width) unicode drawing chars.
Definition: TerminalDisplay.cpp:446
Konsole::PlainTextDecoder::end
virtual void end()
End decoding.
Definition: TerminalCharacterDecoder.cpp:55
Konsole::TerminalDisplay::setScroll
void setScroll(int cursor, int lines)
Sets the current position and range of the display's scroll bar.
Definition: TerminalDisplay.cpp:1801
QRect::setBottom
void setBottom(int y)
TABLE_COLORS
#define TABLE_COLORS
Definition: CharacterColor.h:117
QWidget::setStyleSheet
void setStyleSheet(const QString &styleSheet)
QEvent
QResizeEvent
QWidget
Konsole::TerminalDisplay::focusOutEvent
virtual void focusOutEvent(QFocusEvent *event)
Definition: TerminalDisplay.cpp:1548
QKeyEvent::modifiers
Qt::KeyboardModifiers modifiers() const
QScrollBar::sizeHint
virtual QSize sizeHint() const
Konsole::SessionController
Provides the menu actions to manipulate a single terminal session and view pair.
Definition: SessionController.h:85
Konsole::TerminalDisplay::mouseWheelZoom
bool mouseWheelZoom()
Returns the whether zoom terminal on Ctrl+mousewheel is enabled.
Definition: TerminalDisplay.h:354
QString::append
QString & append(QChar ch)
QRect::size
QSize size() const
QEvent::type
Type type() const
QApplication::doubleClickInterval
int doubleClickInterval()
QLayout::setContentsMargins
void setContentsMargins(int left, int top, int right, int bottom)
QWidget::palette
const QPalette & palette() const
Konsole::TerminalDisplay::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *event)
Definition: TerminalDisplay.cpp:2191
QFontMetrics::ascent
int ascent() const
QPoint::rx
int & rx()
QPoint::ry
int & ry()
QWidget::isHidden
bool isHidden() const
Konsole::AutoScrollHandler
Definition: TerminalDisplay.h:915
QSize::width
int width() const
Konsole::TerminalDisplay::diNone
Definition: TerminalDisplay.h:644
ExtendedCharTable.h
Konsole::TerminalDisplay::setBlinkingCursorEnabled
void setBlinkingCursorEnabled(bool blink)
Specifies whether or not the cursor can blink.
Definition: TerminalDisplay.cpp:1515
Konsole::TerminalDisplay::showEvent
virtual void showEvent(QShowEvent *event)
Definition: TerminalDisplay.cpp:1740
QWidget::setCursor
void setCursor(const QCursor &)
Konsole::TerminalDisplay::setWallpaper
void setWallpaper(ColorSchemeWallpaper::Ptr p)
Sets the background picture.
Definition: TerminalDisplay.cpp:596
Konsole::TerminalDisplay::setBackgroundColor
void setBackgroundColor(const QColor &color)
Sets the background of the display to the specified color.
Definition: TerminalDisplay.cpp:128
QDropEvent::mimeData
const QMimeData * mimeData() const
QPainter::fillRect
void fillRect(const QRectF &rectangle, const QBrush &brush)
Konsole::Character::character
quint16 character
The unicode character value for this character.
Definition: Character.h:108
QPainter::setCompositionMode
void setCompositionMode(CompositionMode mode)
QFont::setKerning
void setKerning(bool enable)
Konsole::Enum::CursorShapeEnum
CursorShapeEnum
This enum describes the shapes used to draw the cursor in terminal displays.
Definition: Enumeration.h:80
Konsole::TerminalDisplay::setVTFont
void setVTFont(const QFont &font)
Sets the font used to draw the display.
Definition: TerminalDisplay.cpp:205
Konsole::TerminalDisplay::setFlowControlWarningEnabled
void setFlowControlWarningEnabled(bool enabled)
Changes whether the flow control warning box should be shown when the flow control stop key (Ctrl+S) ...
Definition: TerminalDisplay.cpp:2874
Konsole::TerminalDisplay::updateImage
void updateImage()
Causes the terminal display to fetch the latest character image from the associated terminal screen (...
Definition: TerminalDisplay.cpp:967
Konsole::SessionController::url
virtual KUrl url() const
Returns the URL current associated with a view.
Definition: SessionController.cpp:290
QWidget::updateGeometry
void updateGeometry()
Konsole::TerminalDisplay::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *event)
Definition: TerminalDisplay.cpp:1925
BotL
Definition: TerminalDisplay.cpp:469
Konsole::TerminalDisplay::updateLineProperties
void updateLineProperties()
Causes the terminal display to fetch the latest line status flags from the associated terminal screen...
Definition: TerminalDisplay.cpp:2255
QPalette::setColor
void setColor(ColorGroup group, ColorRole role, const QColor &color)
QFont::styleStrategy
StyleStrategy styleStrategy() const
QGridLayout::addWidget
void addWidget(QWidget *widget, int row, int column, QFlags< Qt::AlignmentFlag > alignment)
QWidget::window
QWidget * window() const
QDrag::setMimeData
void setMimeData(QMimeData *data)
QRect::right
int right() const
QInputMethodEvent
QAbstractSlider::setRange
void setRange(int min, int max)
Konsole::Filter::HotSpot::activate
virtual void activate(QObject *object=0)=0
Causes the action associated with a hotspot to be triggered.
QWidget::contentsRect
QRect contentsRect() const
Konsole::ExtendedCharTable::instance
static ExtendedCharTable instance
The global ExtendedCharTable instance.
Definition: ExtendedCharTable.h:68
DEFAULT_FORE_COLOR
#define DEFAULT_FORE_COLOR
Definition: CharacterColor.h:119
Konsole::Enum::UnderlineCursor
Draw a line underneath the cursor's position.
Definition: Enumeration.h:88
COLOR_SPACE_RGB
#define COLOR_SPACE_RGB
Definition: CharacterColor.h:142
LeftB
Definition: TerminalDisplay.cpp:463
QFont::pointSizeF
qreal pointSizeF() const
Konsole::Filter::HotSpot
Represents an area of text which matched the pattern a particular filter has been looking for...
Definition: Filter.h:70
Konsole::FilterChain::hotSpotAt
Filter::HotSpot * hotSpotAt(int line, int column) const
Returns the first hotspot which occurs at line, column or 0 if no hotspot was found.
Definition: Filter.cpp:81
QPaintEvent::region
const QRegion & region() const
Konsole::TerminalDisplay::processFilters
void processFilters()
Updates the filters in the display's filter chain.
Definition: TerminalDisplay.cpp:944
QMimeData::hasFormat
virtual bool hasFormat(const QString &mimeType) const
Konsole::TerminalDisplay::bell
void bell(const QString &message)
Shows a notification that a bell event has occurred in the terminal.
Definition: TerminalDisplay.cpp:3062
Konsole::TerminalDisplay::contextMenuEvent
virtual void contextMenuEvent(QContextMenuEvent *event)
Definition: TerminalDisplay.cpp:3033
Konsole::TerminalDisplay::setBellMode
void setBellMode(int mode)
Sets the type of effect used to alert the user when a 'bell' occurs in the terminal session...
Definition: TerminalDisplay.cpp:3047
QWidget::setFocusPolicy
void setFocusPolicy(Qt::FocusPolicy policy)
QObject::sender
QObject * sender() const
QChar
QPainter::font
const QFont & font() const
QString::prepend
QString & prepend(QChar ch)
QAction::data
QVariant data() const
Konsole::TerminalDisplay::selectCurrentLine
void selectCurrentLine()
Definition: TerminalDisplay.cpp:2625
QLabel::setOpenExternalLinks
void setOpenExternalLinks(bool open)
QAccessibleInterface
QFont
TerminalDisplayAccessible.h
QWidget::style
QStyle * style() const
Konsole::Screen::getImage
void getImage(Character *dest, int size, int startLine, int endLine) const
Returns the current screen image.
Definition: Screen.cpp:450
QMouseEvent::x
int x() const
QMouseEvent::y
int y() const
QWidget::setMinimumWidth
void setMinimumWidth(int minw)
BotC
Definition: TerminalDisplay.cpp:470
Konsole::TerminalDisplay::charClass
QChar charClass(const Character &ch) const
Definition: TerminalDisplay.cpp:2642
Screen.h
QPalette::color
const QColor & color(ColorGroup group, ColorRole role) const
REPCHAR
#define REPCHAR
Definition: TerminalDisplay.cpp:81
QString::size
int size() const
QWheelEvent
Konsole::TerminalDisplay::outputSuspended
void outputSuspended(bool suspended)
Causes the widget to display or hide a message informing the user that terminal output has been suspe...
Definition: TerminalDisplay.cpp:2884
QPainter::setWorldMatrix
void setWorldMatrix(const QMatrix &matrix, bool combine)
Konsole::LINE_WRAPPED
const int LINE_WRAPPED
Definition: Character.h:34
QFont::setUnderline
void setUnderline(bool enable)
QWidget::y
int y() const
Konsole::TerminalDisplay::setBracketedPasteMode
void setBracketedPasteMode(bool bracketedPasteMode)
Definition: TerminalDisplay.cpp:2686
QWidget::isVisible
bool isVisible() const
Konsole::TerminalDisplay::inputMethodEvent
virtual void inputMethodEvent(QInputMethodEvent *event)
Definition: TerminalDisplay.cpp:2788
Konsole::LINE_DOUBLEWIDTH
const int LINE_DOUBLEWIDTH
Definition: Character.h:35
TopC
Definition: TerminalDisplay.cpp:448
QPainter::save
void save()
loc
#define loc(X, Y)
Definition: TerminalDisplay.cpp:78
QScrollBar
QWidget::setAttribute
void setAttribute(Qt::WidgetAttribute attribute, bool on)
QLabel::setAlignment
void setAlignment(QFlags< Qt::AlignmentFlag >)
RightB
Definition: TerminalDisplay.cpp:467
QRect::height
int height() const
QRegion::boundingRect
QRect boundingRect() const
Konsole::TerminalDisplay::mouseDoubleClickEvent
virtual void mouseDoubleClickEvent(QMouseEvent *event)
Definition: TerminalDisplay.cpp:2284
Konsole::RE_UNDERLINE
const int RE_UNDERLINE
Definition: Character.h:41
QRect::x
int x() const
QRect::y
int y() const
QGridLayout
QAbstractSlider::setPageStep
void setPageStep(int)
QPainter::setLayoutDirection
void setLayoutDirection(Qt::LayoutDirection direction)
LineChars
static const quint32 LineChars[]
Definition: LineFont.h:4
Konsole::Enum::PasteFromX11Selection
Paste from X11 Selection.
Definition: Enumeration.h:102
QWidget::hasFocus
bool hasFocus() const
QPoint
LTR_OVERRIDE_CHAR
const QChar LTR_OVERRIDE_CHAR(0x202D)
QFontMetrics
Konsole::Enum::SelectWholeLine
Select the whole line underneath the cursor.
Definition: Enumeration.h:94
QMouseEvent
Konsole::TerminalDisplay::keyPressedSignal
void keyPressedSignal(QKeyEvent *event)
Emitted when the user presses a key whilst the terminal widget has focus.
Konsole::Filter::HotSpot::startLine
int startLine() const
Returns the line when the hotspot area starts.
Definition: Filter.cpp:268
QMouseEvent::buttons
Qt::MouseButtons buttons() const
QWheelEvent::pos
const QPoint & pos() const
drawLineChar
static void drawLineChar(QPainter &paint, int x, int y, int w, int h, uchar code)
Definition: TerminalDisplay.cpp:474
QPainter::drawLine
void drawLine(const QLineF &line)
Konsole::Enum::ScrollBarPositionEnum
ScrollBarPositionEnum
This enum describes the positions where the terminal display's scroll bar may be placed.
Definition: Enumeration.h:58
Konsole::PlainTextDecoder::decodeLine
virtual void decodeLine(const Character *const characters, int count, LineProperty properties)
Converts a line of terminal characters with associated properties into a text string and writes the s...
Definition: TerminalCharacterDecoder.cpp:68
Int13
Definition: TerminalDisplay.cpp:454
Konsole::TerminalDisplay::getBackgroundColor
QColor getBackgroundColor() const
Gets the background of the display.
Definition: TerminalDisplay.cpp:141
QRect::moveTopLeft
void moveTopLeft(const QPoint &position)
QObject::disconnect
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
RightC
Definition: TerminalDisplay.cpp:461
Konsole::TerminalDisplay::setKeyboardCursorColor
void setKeyboardCursorColor(const QColor &color)
Sets the color used to draw the keyboard cursor.
Definition: TerminalDisplay.cpp:567
Konsole::Enum::ScrollBarHidden
Do not show the scroll-bar.
Definition: Enumeration.h:64
Konsole::Filter::HotSpot::endLine
int endLine() const
Returns the line where the hotspot area ends.
Definition: Filter.cpp:272
Konsole::TerminalDisplay::setScrollFullPage
void setScrollFullPage(bool fullPage)
Definition: TerminalDisplay.cpp:1822
Filter.h
QMimeData
QWidget::update
void update()
Konsole::RE_BLINK
const int RE_BLINK
Definition: Character.h:40
QPoint::x
int x() const
QPoint::y
int y() const
QTextStream
TopR
Definition: TerminalDisplay.cpp:449
QFont::bold
bool bold() const
QWidget::geometry
geometry
Konsole::Enum::BlockCursor
Use a solid rectangular block to draw the cursor.
Definition: Enumeration.h:82
Konsole::TerminalDisplay::setAutoCopySelectedText
void setAutoCopySelectedText(bool enabled)
Definition: TerminalDisplay.cpp:2733
QFont::italic
bool italic() const
Konsole::ColorEntry::Bold
Always draw text in this color with a bold weight.
Definition: CharacterColor.h:46
isLineCharString
static bool isLineCharString(const QString &string)
Definition: TerminalDisplay.cpp:166
Int22
Definition: TerminalDisplay.cpp:459
Konsole::PlainTextDecoder
A terminal character decoder which produces plain text, ignoring colors and other appearance-related ...
Definition: TerminalCharacterDecoder.h:72
Konsole::TerminalDisplay::paintEvent
virtual void paintEvent(QPaintEvent *event)
Definition: TerminalDisplay.cpp:1171
Konsole::TerminalDisplay::setUsesMouse
void setUsesMouse(bool usesMouse)
Sets whether the program whose output is being displayed in the view is interested in mouse events...
Definition: TerminalDisplay.cpp:2676
QWidget::width
int width() const
QFont::setBold
void setBold(bool enable)
Konsole::RE_ITALIC
const int RE_ITALIC
Definition: Character.h:44
Konsole::TerminalDisplay::overrideShortcutCheck
void overrideShortcutCheck(QKeyEvent *keyEvent, bool &override)
When a shortcut which is also a valid terminal key sequence is pressed while the terminal widget has ...
QDrag::exec
Qt::DropAction exec(QFlags< Qt::DropAction > supportedActions)
Konsole::Screen::DefaultChar
static const Character DefaultChar
Definition: Screen.h:586
Konsole::Character
A single character in the terminal which consists of a unicode character value, foreground and backgr...
Definition: Character.h:77
QWidget::size
QSize size() const
konsole_wcwidth.h
QApplication::cursorFlashTime
int cursorFlashTime()
QPainter::drawRect
void drawRect(const QRectF &rectangle)
QTimerEvent
Konsole::Enum::NotifyBell
trigger system notification.
Definition: Enumeration.h:116
QPen::color
QColor color() const
QRect
QPainter::setFont
void setFont(const QFont &font)
Konsole::TerminalDisplay::wheelEvent
virtual void wheelEvent(QWheelEvent *event)
Definition: TerminalDisplay.cpp:2330
QWidget::enabled
enabled
QString::resize
void resize(int size)
Int23
Definition: TerminalDisplay.cpp:460
Int33
Definition: TerminalDisplay.cpp:466
Int31
Definition: TerminalDisplay.cpp:464
QList::append
void append(const T &value)
QChar::isSpace
bool isSpace() const
TerminalDisplay.h
Konsole::TerminalDisplay::setForegroundColor
void setForegroundColor(const QColor &color)
Sets the text of the display to the specified color.
Definition: TerminalDisplay.cpp:146
Konsole::TerminalDisplay::mouseSignal
void mouseSignal(int button, int column, int line, int eventType)
A mouse event occurred.
QPainter::drawPoint
void drawPoint(const QPointF &position)
Konsole::TerminalDisplay::lines
int lines() const
Returns the number of lines of text which can be displayed in the widget.
Definition: TerminalDisplay.h:268
Konsole::SessionController::setSearchStartToWindowCurrentLine
void setSearchStartToWindowCurrentLine()
set start line to the first or last line (depending on the reverse search setting) in the terminal di...
Definition: SessionController.cpp:1100
Konsole::Filter::HotSpot::Marker
Definition: Filter.h:86
QAccessible::updateAccessibility
void updateAccessibility(QObject *object, int child, Event reason)
QWidget::setLayout
void setLayout(QLayout *layout)
Konsole::TerminalDisplay::keyboardCursorShape
Enum::CursorShapeEnum keyboardCursorShape() const
Returns the shape of the keyboard cursor.
Definition: TerminalDisplay.cpp:563
QObject::installEventFilter
void installEventFilter(QObject *filterObj)
LeftC
Definition: TerminalDisplay.cpp:457
Konsole::TerminalDisplay::changedContentSizeSignal
void changedContentSizeSignal(int height, int width)
QTimer
QWidget::x
int x() const
QWidget::setLayoutDirection
void setLayoutDirection(Qt::LayoutDirection direction)
QString::fromUtf16
QString fromUtf16(const ushort *unicode, int size)
Konsole::TerminalDisplay::keyboardCursorColor
QColor keyboardCursorColor() const
Returns the color of the keyboard cursor, or an invalid color if the keyboard cursor color is set to ...
Definition: TerminalDisplay.cpp:571
QApplication::clipboard
QClipboard * clipboard()
Konsole::TerminalDisplay::~TerminalDisplay
virtual ~TerminalDisplay()
Definition: TerminalDisplay.cpp:410
Konsole::TerminalDisplay::sessionController
SessionController * sessionController()
Definition: TerminalDisplay.cpp:3235
Konsole::ColorEntry
An entry in a terminal display's color palette.
Definition: CharacterColor.h:40
QRect::top
int top() const
QWheelEvent::orientation
Qt::Orientation orientation() const
Konsole::TerminalDisplay::focusNextPrevChild
virtual bool focusNextPrevChild(bool next)
Definition: TerminalDisplay.cpp:2632
Konsole::isSupportedLineChar
bool isSupportedLineChar(quint16 codePoint)
Unicode character in the range of U+2500 ~ U+257F are known as line characters, or box-drawing charac...
Definition: Character.h:56
Konsole::ColorSchemeWallpaper::Ptr
KSharedPtr< ColorSchemeWallpaper > Ptr
Definition: ColorScheme.h:47
QContextMenuEvent
QShowEvent
QObject
QRegion::subtracted
QRegion subtracted(const QRegion &r) const
QPainter::setPen
void setPen(const QColor &color)
QWidget::focusNextPrevChild
virtual bool focusNextPrevChild(bool next)
QRect::setTop
void setTop(int y)
Konsole::TerminalDisplay::selectLine
void selectLine(QPoint pos, bool entireLine)
Definition: TerminalDisplay.cpp:2597
QRect::left
int left() const
QMouseEvent::button
Qt::MouseButton button() const
QFontMetrics::maxWidth
int maxWidth() const
QWidget::backgroundRole
QPalette::ColorRole backgroundRole() const
QDropEvent
Konsole::ScreenWindow
Provides a window onto a section of a terminal screen.
Definition: ScreenWindow.h:52
Konsole::TerminalDisplay::bellMode
int bellMode() const
Returns the type of effect used to alert the user when a 'bell' occurs in the terminal session...
Definition: TerminalDisplay.cpp:3052
QPainter
QObject::setObjectName
void setObjectName(const QString &name)
QRect::setCoords
void setCoords(int x1, int y1, int x2, int y2)
Konsole::ColorEntry::FontWeight
FontWeight
Specifies the weight to use when drawing text with this color.
Definition: CharacterColor.h:44
QDrag
QRect::setWidth
void setWidth(int width)
QString::isEmpty
bool isEmpty() const
Konsole::Screen
An image of characters with associated attributes.
Definition: Screen.h:74
Konsole::TerminalDisplay::event
virtual bool event(QEvent *event)
Definition: TerminalDisplay.cpp:3016
Konsole::ExtendedCharTable::lookupExtendedChar
ushort * lookupExtendedChar(ushort hash, ushort &length) const
Looks up and returns a pointer to a sequence of unicode characters which was added to the table using...
Definition: ExtendedCharTable.cpp:113
Int32
Definition: TerminalDisplay.cpp:465
Konsole::TerminalDisplay::dragEnterEvent
virtual void dragEnterEvent(QDragEnterEvent *event)
Definition: TerminalDisplay.cpp:3115
QCoreApplication::sendEvent
bool sendEvent(QObject *receiver, QEvent *event)
Konsole::TerminalDisplay::copyToX11Selection
void copyToX11Selection()
Copies the selected text to the X11 Selection.
Definition: TerminalDisplay.cpp:2743
QFont::setStyleStrategy
void setStyleStrategy(StyleStrategy s)
BotR
Definition: TerminalDisplay.cpp:471
Konsole::TerminalDisplay::scrollFullPage
bool scrollFullPage() const
Definition: TerminalDisplay.cpp:1827
QPainter::device
QPaintDevice * device() const
Konsole::TerminalDisplay::setColorTable
void setColorTable(const ColorEntry table[])
Sets the terminal color palette used by the display.
Definition: TerminalDisplay.cpp:152
QWidget::move
void move(int x, int y)
QMimeData::setText
void setText(const QString &text)
QPainter::drawText
void drawText(const QPointF &position, const QString &text)
Konsole::TerminalDisplay::inputMethodQuery
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const
Definition: TerminalDisplay.cpp:2801
Konsole::TerminalDisplay::blinkTextEvent
void blinkTextEvent()
Definition: TerminalDisplay.cpp:1581
QFont::underline
bool underline() const
LineFont.h
QLabel::setText
void setText(const QString &)
Konsole::CharacterColor::color
QColor color(const ColorEntry *palette) const
Returns the color within the specified color palette.
Definition: CharacterColor.h:277
Konsole::Character::isLineChar
bool isLineChar() const
Definition: Character.h:154
Konsole::Character::backgroundColor
CharacterColor backgroundColor
The color used to draw this character's background.
Definition: Character.h:117
Konsole::TerminalDisplay::changedFontMetricSignal
void changedFontMetricSignal(int height, int width)
QString
QList
QWidget::hide
void hide()
QAbstractSlider::minimum
minimum
Konsole::TerminalDisplay::setScrollBarPosition
void setScrollBarPosition(Enum::ScrollBarPositionEnum position)
Specifies whether the terminal display has a vertical scroll bar, and if so whether it is shown on th...
Definition: TerminalDisplay.cpp:1768
QColor
Konsole::TerminalDisplay::setCenterContents
void setCenterContents(bool enable)
Sets whether the contents are centered between the margins.
Definition: TerminalDisplay.cpp:1755
Konsole::Enum::SystemBeepBell
trigger system beep.
Definition: Enumeration.h:114
Konsole::TerminalDisplay::setMiddleClickPasteMode
void setMiddleClickPasteMode(Enum::MiddleClickPasteModeEnum mode)
Definition: TerminalDisplay.cpp:2738
QPen::setColor
void setColor(const QColor &color)
Int21
Definition: TerminalDisplay.cpp:458
Int12
Definition: TerminalDisplay.cpp:453
Konsole::TerminalDisplay::setSessionController
void setSessionController(SessionController *controller)
Definition: TerminalDisplay.cpp:3230
Konsole::AutoScrollHandler::eventFilter
virtual bool eventFilter(QObject *watched, QEvent *event)
Definition: TerminalDisplay.cpp:3259
QApplication::palette
QPalette palette()
QRect::intersected
QRect intersected(const QRect &rectangle) const
Konsole::AutoScrollHandler::timerEvent
virtual void timerEvent(QTimerEvent *event)
Definition: TerminalDisplay.cpp:3246
Konsole::TerminalDisplay::columns
int columns() const
Returns the number of characters of text which can be displayed on each line in the widget...
Definition: TerminalDisplay.h:278
Konsole::Enum::PasteFromClipboard
Paste from Clipboard.
Definition: Enumeration.h:104
Konsole::TerminalDisplay::DragInfo::start
QPoint start
Definition: TerminalDisplay.h:648
QWidget::rect
QRect rect() const
Konsole::TerminalDisplay::diPending
Definition: TerminalDisplay.h:644
Konsole::TerminalDisplay::setOpacity
void setOpacity(qreal opacity)
Sets the opacity of the terminal display.
Definition: TerminalDisplay.cpp:576
QPixmap
QRect::adjusted
QRect adjusted(int dx1, int dy1, int dx2, int dy2) const
Konsole::TerminalDisplay::fontChange
virtual void fontChange(const QFont &)
Definition: TerminalDisplay.cpp:174
QWidget::setAcceptDrops
void setAcceptDrops(bool on)
QInputEvent::modifiers
Qt::KeyboardModifiers modifiers() const
QRegion::contains
bool contains(const QPoint &p) const
QFontInfo
QFileInfo
QAction::setData
void setData(const QVariant &userData)
QString::toLocal8Bit
QByteArray toLocal8Bit() const
QKeyEvent::key
int key() const
QScrollBar::event
virtual bool event(QEvent *event)
Konsole::TerminalDisplay::focusInEvent
virtual void focusInEvent(QFocusEvent *event)
Definition: TerminalDisplay.cpp:1570
QEvent::accept
void accept()
Konsole::TerminalDisplay::setFont
virtual void setFont(const QFont &)
Reimplemented.
Definition: TerminalDisplay.cpp:234
QString::contains
bool contains(QChar ch, Qt::CaseSensitivity cs) const
QSize
Konsole::TerminalDisplay::clearImage
void clearImage()
Definition: TerminalDisplay.cpp:1676
QWidget::font
const QFont & font() const
Konsole::TerminalDisplay::setLineSpacing
void setLineSpacing(uint)
Definition: TerminalDisplay.cpp:260
Konsole::TerminalDisplay::scrollBarPositionChanged
void scrollBarPositionChanged(int value)
Definition: TerminalDisplay.cpp:1784
QAbstractSlider::value
value
Konsole::Filter::HotSpot::type
Type type() const
Returns the type of the hotspot.
Definition: Filter.cpp:284
QRect::isEmpty
bool isEmpty() const
QFontMetrics::width
int width(const QString &text, int len) const
Konsole::TerminalDisplay::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event)
Definition: TerminalDisplay.cpp:1837
Konsole::Filter::HotSpot::actions
virtual QList< QAction * > actions()
Returns a list of actions associated with the hotspot which can be used in a menu or toolbar...
Definition: Filter.cpp:264
Konsole::CharacterColor
Describes the color of a single character in the terminal.
Definition: CharacterColor.h:147
QTimer::stop
void stop()
QRect::isValid
bool isValid() const
QFont::setItalic
void setItalic(bool enable)
QFont::setPointSizeF
void setPointSizeF(qreal pointSize)
Konsole::TerminalDisplay::setSize
void setSize(int columns, int lines)
Definition: TerminalDisplay.cpp:1715
Konsole::AutoScrollHandler::AutoScrollHandler
AutoScrollHandler(QWidget *parent)
Definition: TerminalDisplay.cpp:3240
QWheelEvent::delta
int delta() const
QPainter::restore
void restore()
QClipboard::text
QString text(Mode mode) const
Konsole::TerminalDisplay::setMargin
void setMargin(int margin)
Sets the display's contents margins.
Definition: TerminalDisplay.cpp:1749
Konsole::TerminalDisplay::setRandomSeed
void setRandomSeed(uint seed)
Sets the seed used to generate random colors for the display (in color schemes that support them)...
Definition: TerminalDisplay.cpp:805
Konsole::TerminalDisplay::setKeyboardCursorShape
void setKeyboardCursorShape(Enum::CursorShapeEnum shape)
Sets the shape of the keyboard cursor.
Definition: TerminalDisplay.cpp:559
Konsole::TerminalDisplay::hideEvent
virtual void hideEvent(QHideEvent *event)
Definition: TerminalDisplay.cpp:1744
QLabel::setTextInteractionFlags
void setTextInteractionFlags(QFlags< Qt::TextInteractionFlag > flags)
QString::replace
QString & replace(int position, int n, QChar after)
QKeyEvent
QRect::setRight
void setRight(int x)
Konsole::FilterChain
A chain which allows a group of filters to be processed as one.
Definition: Filter.h:312
QObject::startTimer
int startTimer(int interval)
RightT
Definition: TerminalDisplay.cpp:455
Konsole::Character::fontWeight
ColorEntry::FontWeight fontWeight(const ColorEntry *base) const
Returns true if this character should always be drawn in bold when it is drawn with the specified pal...
Definition: Character.h:188
Konsole::PlainTextDecoder::begin
virtual void begin(QTextStream *output)
Begin decoding characters.
Definition: TerminalCharacterDecoder.cpp:49
TerminalCharacterDecoder.h
QRect::width
int width() const
Konsole::TerminalDisplay::increaseFontSize
void increaseFontSize()
Increases the font size.
Definition: TerminalDisplay.cpp:239
QWidget::fontMetrics
QFontMetrics fontMetrics() const
Konsole::Enum::MiddleClickPasteModeEnum
MiddleClickPasteModeEnum
This enum describes the source from which mouse middle click pastes data .
Definition: Enumeration.h:100
QCursor::pos
QPoint pos()
QVector< LineProperty >
QDragEnterEvent
Konsole::TerminalDisplay::_dragInfo
struct Konsole::TerminalDisplay::DragInfo _dragInfo
QPen::width
int width() const
QAbstractSlider::setSingleStep
void setSingleStep(int)
Int11
Definition: TerminalDisplay.cpp:452
TopL
Definition: TerminalDisplay.cpp:447
QLatin1String
Konsole::TerminalDisplay::scrollScreenWindow
void scrollScreenWindow(enum ScreenWindow::RelativeScrollMode mode, int amount)
Scrolls current ScreenWindow.
Definition: TerminalDisplay.cpp:2933
Konsole::accessibleInterfaceFactory
QAccessibleInterface * accessibleInterfaceFactory(const QString &key, QObject *object)
This function installs the factory function which lets Qt instantiate the QAccessibleInterface for th...
Definition: TerminalDisplay.cpp:279
QRect::setHeight
void setHeight(int height)
Konsole::TerminalDisplay::setScreenWindow
void setScreenWindow(ScreenWindow *window)
Sets the terminal screen section which is displayed in this widget.
Definition: TerminalDisplay.cpp:107
QGridLayout::addItem
void addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, QFlags< Qt::AlignmentFlag > alignment)
QString::at
const QChar at(int position) const
Konsole::Filter::HotSpot::Link
Definition: Filter.h:84
QWidget::mapFromGlobal
QPoint mapFromGlobal(const QPoint &pos) const
QAction
QMatrix
Konsole::Enum::IBeamCursor
Use an 'I' shape, similar to that used in text editing applications, to draw the cursor.
Definition: Enumeration.h:86
QFontMetrics::height
int height() const
QLabel::sizeHint
virtual QSize sizeHint() const
QSize::height
int height() const
QVector::count
int count(const T &value) const
Konsole::TerminalDisplay::TerminalDisplay
TerminalDisplay(QWidget *parent=0)
Constructs a new terminal display widget with the specified parent.
Definition: TerminalDisplay.cpp:294
QRect::adjust
void adjust(int dx1, int dy1, int dx2, int dy2)
Konsole::TerminalDisplay::screenWindow
ScreenWindow * screenWindow() const
Returns the terminal screen section which is displayed in this widget.
Definition: TerminalDisplay.cpp:103
Konsole::Enum
This class serves as a place for putting enum definitions that are used or referenced in multiple pla...
Definition: Enumeration.h:31
QRect::bottom
int bottom() const
Konsole::TerminalImageFilterChain
A filter chain which processes character images from terminal displays.
Definition: Filter.h:343
QRect::topLeft
QPoint topLeft() const
LeftT
Definition: TerminalDisplay.cpp:451
QString::length
int length() const
QWidget::setMinimumHeight
void setMinimumHeight(int minh)
Konsole::TerminalDisplay::diDragging
Definition: TerminalDisplay.h:644
Konsole::Filter::HotSpot::endColumn
int endColumn() const
Returns the column on endLine() where the hotspot area ends.
Definition: Filter.cpp:280
Konsole::RE_BOLD
const int RE_BOLD
Definition: Character.h:39
QPoint::setX
void setX(int x)
Konsole::TerminalImageFilterChain::setImage
void setImage(const Character *const image, int lines, int columns, const QVector< LineProperty > &lineProperties)
Set the current terminal image to image.
Definition: Filter.cpp:118
QString::reserve
void reserve(int size)
QWidget::setMouseTracking
void setMouseTracking(bool enable)
QTimerEvent::timerId
int timerId() const
Konsole::TerminalDisplay::filterActions
QList< QAction * > filterActions(const QPoint &position)
Returns a list of menu actions created by the filters for the content at the given position...
Definition: TerminalDisplay.cpp:1915
Konsole::TerminalDisplay::pasteFromClipboard
void pasteFromClipboard(bool appendEnter=false)
Pastes the content of the clipboard into the display.
Definition: TerminalDisplay.cpp:2770
Konsole::TerminalDisplay::colorTable
const ColorEntry * colorTable() const
Returns the terminal color palette used by the display.
Definition: TerminalDisplay.cpp:124
Konsole::ColorScheme::defaultTable
static const ColorEntry defaultTable[]
Definition: ColorScheme.h:171
QRegion::isEmpty
bool isEmpty() const
QPen
QTimer::start
void start(int msec)
QColor::setAlphaF
void setAlphaF(qreal alpha)
Konsole::TerminalDisplay::copyToClipboard
void copyToClipboard()
Copies the selected text to the system clipboard.
Definition: TerminalDisplay.cpp:2758
Konsole::Enum::VisualBell
trigger visual bell(inverting the display's colors briefly).
Definition: Enumeration.h:118
SessionManager.h
Konsole::TerminalDisplay::lineSpacing
uint lineSpacing() const
Definition: TerminalDisplay.cpp:255
Konsole::Enum::ScrollBarRight
Show the scroll-bar on the right of the terminal display.
Definition: Enumeration.h:62
QClipboard::setText
void setText(const QString &text, Mode mode)
Konsole::TerminalDisplay::blinkCursorEvent
void blinkCursorEvent()
Definition: TerminalDisplay.cpp:1592
Konsole::TerminalDisplay::sizeHint
QSize sizeHint() const
Definition: TerminalDisplay.cpp:1730
Konsole::TerminalDisplay::keyPressEvent
virtual void keyPressEvent(QKeyEvent *event)
Definition: TerminalDisplay.cpp:2942
QWidget::setAutoFillBackground
void setAutoFillBackground(bool enabled)
QWidget::show
void show()
Konsole::ColorEntry::color
QColor color
The color value of this entry for display.
Definition: CharacterColor.h:80
Konsole::TerminalDisplay::pasteFromX11Selection
void pasteFromX11Selection(bool appendEnter=false)
Pastes the content of the X11 selection into the display.
Definition: TerminalDisplay.cpp:2776
Konsole::TerminalDisplay::DragInfo::dragObject
QDrag * dragObject
Definition: TerminalDisplay.h:649
Konsole::TerminalDisplay::mouseTripleClickEvent
void mouseTripleClickEvent(QMouseEvent *event)
Definition: TerminalDisplay.cpp:2586
QWidget::scroll
void scroll(int dx, int dy)
QMouseEvent::pos
const QPoint & pos() const
Konsole::TerminalDisplay::randomSeed
uint randomSeed() const
Returns the seed used to generate random colors for the display (in color schemes that support them)...
Definition: TerminalDisplay.cpp:809
QPaintEvent
Konsole::ColorEntry::UseCurrentFormat
Use the current font weight set by the terminal application.
Definition: CharacterColor.h:53
Konsole::ScreenWindow::RelativeScrollMode
RelativeScrollMode
Describes the units which scrollBy() moves the window by.
Definition: ScreenWindow.h:193
QWidget::setBackgroundRole
void setBackgroundRole(QPalette::ColorRole role)
QMatrix::inverted
QMatrix inverted(bool *invertible) const
Konsole::TerminalDisplay::doDrag
void doDrag()
Definition: TerminalDisplay.cpp:3220
QContextMenuEvent::reason
Reason reason() const
Konsole::TerminalDisplay::configureRequest
void configureRequest(const QPoint &position)
Emitted when the user right clicks on the display, or right-clicks with the Shift key held down if us...
Konsole::TerminalDisplay::setBlinkingTextEnabled
void setBlinkingTextEnabled(bool blink)
Specifies whether or not text can blink.
Definition: TerminalDisplay.cpp:1535
QTimer::isActive
bool isActive() const
QAbstractSlider::maximum
maximum
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Konsole::TerminalDisplayAccessible
Class implementing the QAccessibleInterface for the terminal display.
Definition: TerminalDisplayAccessible.h:41
QLabel
QMatrix::map
void map(int x, int y, int *tx, int *ty) const
QObject::parent
QObject * parent() const
QVector::size
int size() const
ScreenWindow.h
Konsole::TerminalDisplay
A widget which displays output from a terminal emulation and sends input keypresses and mouse activit...
Definition: TerminalDisplay.h:63
QAccessible::installFactory
void installFactory(InterfaceFactory factory)
Konsole::TerminalDisplay::visualBell
void visualBell()
Play a visual bell for prompt or warning.
Definition: TerminalDisplay.cpp:3093
QPainter::pen
const QPen & pen() const
Konsole::TerminalDisplay::dropEvent
virtual void dropEvent(QDropEvent *event)
Definition: TerminalDisplay.cpp:3127
QString::data
QChar * data()
QVariant::toString
QString toString() const
QWidget::event
virtual bool event(QEvent *event)
QRect::setLeft
void setLeft(int x)
Konsole::TerminalDisplay::usesMouse
bool usesMouse() const
See setUsesMouse()
Definition: TerminalDisplay.cpp:2681
QFocusEvent
Konsole::TerminalDisplay::bracketedPasteMode
bool bracketedPasteMode() const
Definition: TerminalDisplay.cpp:2690
QInputMethodEvent::commitString
const QString & commitString() const
Konsole::SessionController::currentDir
virtual QString currentDir() const
Returns the current directory associated with a view.
Definition: SessionController.cpp:285
Konsole::Screen::getLineProperties
QVector< LineProperty > getLineProperties(int startLine, int endLine) const
Returns the additional attributes associated with lines in the image.
Definition: Screen.cpp:485
QObject::killTimer
void killTimer(int id)
Konsole::Filter::HotSpot::startColumn
int startColumn() const
Returns the column on startLine() where the hotspot area starts.
Definition: Filter.cpp:276
Konsole::Character::rendition
quint8 rendition
A combination of RENDITION flags which specify options for drawing the character. ...
Definition: Character.h:111
Konsole::Enum::ScrollBarLeft
Show the scroll-bar on the left of the terminal display.
Definition: Enumeration.h:60
SessionController.h
Konsole::TerminalDisplay::getVTFont
QFont getVTFont()
Returns the font used to draw characters in the display.
Definition: TerminalDisplay.h:365
string_width
int string_width(const QString &text)
Definition: konsole_wcwidth.cpp:217
Konsole::TerminalDisplay::leaveEvent
virtual void leaveEvent(QEvent *event)
Definition: TerminalDisplay.cpp:2029
QLabel::setWordWrap
void setWordWrap(bool on)
Konsole::TerminalDisplay::sendStringToEmu
void sendStringToEmu(const char *)
Konsole::TerminalDisplay::DragInfo::state
DragState state
Definition: TerminalDisplay.h:647
Konsole::RE_CURSOR
const int RE_CURSOR
Definition: Character.h:45
QPalette
Konsole::FilterChain::process
void process()
Processes each filter in the chain.
Definition: Filter.cpp:71
QWidget::height
int height() const
Konsole::TerminalDisplay::filterChain
FilterChain * filterChain() const
Returns the display's filter chain.
Definition: TerminalDisplay.cpp:1214
Konsole::TerminalDisplay::decreaseFontSize
void decreaseFontSize()
Decreases the font size.
Definition: TerminalDisplay.cpp:246
QRegion
Konsole::Character::foregroundColor
CharacterColor foregroundColor
The foreground color used to draw this character.
Definition: Character.h:114
QMatrix::scale
QMatrix & scale(qreal sx, qreal sy)
QColor::rgba
QRgb rgba() const
Konsole::TerminalDisplay::extendSelection
virtual void extendSelection(const QPoint &pos)
Definition: TerminalDisplay.cpp:2038
QChar::isLetterOrNumber
bool isLetterOrNumber() const
QColor::isValid
bool isValid() const
Konsole::FilterChain::hotSpots
QList< Filter::HotSpot * > hotSpots() const
Returns a list of all the hotspots in all the chain's filters.
Definition: Filter.cpp:95
QCursor::shape
Qt::CursorShape shape() const
QWidget::setContentsMargins
void setContentsMargins(int left, int top, int right, int bottom)
Konsole::RE_EXTENDED_CHAR
const int RE_EXTENDED_CHAR
Definition: Character.h:46
QTimer::setSingleShot
void setSingleShot(bool singleShot)
QVariant
Konsole::TerminalDisplay::printContent
void printContent(QPainter &painter, bool friendly)
Definition: TerminalDisplay.cpp:1185
Konsole::LINE_DOUBLEHEIGHT
const int LINE_DOUBLEHEIGHT
Definition: Character.h:36
DEFAULT_BACK_COLOR
#define DEFAULT_BACK_COLOR
Definition: CharacterColor.h:120
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sat May 9 2020 03:56:27 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Konsole

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

applications API Reference

Skip menu "applications API Reference"
  •   kate
  •       kate
  •   KTextEditor
  •   Kate
  • Konsole

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal