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

Konsole

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