GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
TerminalView.cpp
Go to the documentation of this file.
1/*
2 This file is part of Konsole, a terminal emulator for KDE.
3
4 Copyright (C) 2006-7 by Robert Knight <robertknight@gmail.com>
5 Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
6
7 Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
8 Copyright (C) 2012-2019 Jacob Dawid <jacob.dawid@cybercatalyst.com>
9
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 02110-1301 USA.
24*/
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include "qt-utils.h"
31
32// Own
33#include "unix/TerminalView.h"
34
35// Qt
36#include <QApplication>
37#include <QBoxLayout>
38#include <QClipboard>
39#include <QKeyEvent>
40#include <QtCore/QEvent>
41#include <QtCore/QTime>
42#include <QtCore/QFile>
43#include <QGridLayout>
44#include <QLabel>
45#include <QLayout>
46#include <QPainter>
47#include <QPixmap>
48#include <QScrollBar>
49#include <QStyle>
50#include <QToolTip>
51#include <QtCore>
52#include <QtGui>
53
54#include "unix/Filter.h"
56#include "unix/ScreenWindow.h"
58
59#include <signal.h>
60
61#ifndef loc
62#define loc(X,Y) ((Y)*_columns+(X))
63#endif
64
65#define yMouseScroll 1
66
67#define REPCHAR "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
68 "abcdefgjijklmnopqrstuvwxyz" \
69 "0123456789./+@"
70
71// scroll increment used when dragging selection at top/bottom of window.
72
73// static
75
76/* ------------------------------------------------------------------------- */
77/* */
78/* Colors */
79/* */
80/* ------------------------------------------------------------------------- */
81
82/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb)
83
84 Code 0 1 2 3 4 5 6 7
85 ----------- ------- ------- ------- ------- ------- ------- ------- -------
86 ANSI (bgr) Black Red Green Yellow Blue Magenta Cyan White
87 IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White
88*/
89
91{
92 return _screenWindow;
93}
95{
96 // disconnect existing screen window if any
97 if ( _screenWindow )
98 {
99 disconnect( _screenWindow , nullptr , this , nullptr );
100 }
101
102 _screenWindow = window;
103
104 if ( window )
105 {
106 //#warning "The order here is not specified - does it matter whether updateImage or updateLineProperties comes first?"
107 connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties()) );
108 connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage()) );
109 window->setWindowLines(_lines);
110 }
111}
112
114{
115 return _colorTable;
116}
117
119{
120 for (int i = 0; i < TABLE_COLORS; i++)
121 _colorTable[i] = table[i];
122
123 QPalette p = palette();
124 p.setColor( backgroundRole(), _colorTable[DEFAULT_BACK_COLOR].color );
125 setPalette( p );
126
127 // Avoid propagating the palette change to the scroll bar
128 _scrollBar->setPalette( QApplication::palette() );
129
130 update();
131}
132
133/* ------------------------------------------------------------------------- */
134/* */
135/* Font */
136/* */
137/* ------------------------------------------------------------------------- */
138
139/*
140 The VT100 has 32 special graphical characters. The usual vt100 extended
141 xterm fonts have these at 0x00..0x1f.
142
143 QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals
144 come in here as proper unicode characters.
145
146 We treat non-iso10646 fonts as VT100 extended and do the required mapping
147 from unicode to 0x00..0x1f. The remaining translation is then left to the
148 QCodec.
149*/
150
151// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.
152
153unsigned short vt100_graphics[32] =
154{ // 0/8 1/9 2/10 3/11 4/12 5/13 6/14 7/15
155 0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0,
156 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,
157 0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534,
158 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7
159};
160
161void TerminalView::fontChange(const QFont&)
162{
163 QFontMetrics fm(font());
164 _fontHeight = fm.height() + _lineSpacing;
165
166
167 // waba TerminalDisplay 1.123:
168 // "Base character width on widest ASCII character. This prevents too wide
169 // characters in the presence of double wide (e.g. Japanese) characters."
170 // Get the width from representative normal width characters
172 / (double)strlen(REPCHAR));
173
174 _fixedFont = true;
175
177 for(unsigned int i=1; i< strlen(REPCHAR); i++)
178 {
180 {
181 _fixedFont = false;
182 break;
183 }
184 }
185
186
187 if (_fontWidth < 1)
188 _fontWidth = 1;
189
190 _fontAscent = fm.ascent();
191
193 //parentWidget()->setFixedWidth(_fontWidth * 80 + _leftMargin);
195 update();
196}
197
198void TerminalView::setVTFont(const QFont& f)
199{
200 QFont font = f;
201
202 QFontMetrics metrics(font);
203
204 if ( metrics.height() < height() && metrics.maxWidth() < width() )
205 {
206 // hint that text should be drawn without anti-aliasing.
207 // depending on the user's font configuration, this may not be respected
208 if (!_antialiasText)
209 font.setStyleStrategy( QFont::NoAntialias );
210
211 // experimental optimization. Konsole assumes that the terminal is using a
212 // mono-spaced font, in which case kerning information should have an effect.
213 // Disabling kerning saves some computation when rendering text.
214 // font.setKerning(false);
215
216 int strategy = font.styleStrategy();
217#if defined (HAVE_QFONT_FORCE_INTEGER_METRICS)
218 strategy |= QFont::ForceIntegerMetrics;
219#endif
220 font.setStyleStrategy(QFont::StyleStrategy(strategy));
221
222 QWidget::setFont(font);
223 fontChange(font);
224 }
225}
226
227void TerminalView::setFont(const QFont &)
228{
229 // ignore font change request if not coming from konsole itself
230}
231
232/* ------------------------------------------------------------------------- */
233/* */
234/* Constructor / Destructor */
235/* */
236/* ------------------------------------------------------------------------- */
237
239 :QWidget(parent)
240 ,_screenWindow(nullptr)
241 ,_allowBell(true)
242 ,_gridLayout(nullptr)
243 ,_fontHeight(1)
244 ,_fontWidth(1)
245 ,_fontAscent(1)
246 ,_lines(1)
247 ,_columns(1)
248 ,_usedLines(1)
249 ,_usedColumns(1)
250 ,_contentHeight(1)
251 ,_contentWidth(1)
252 ,_image(nullptr)
253 ,_randomSeed(0)
254 ,_resizing(false)
255 ,_terminalSizeHint(false)
256 ,_terminalSizeStartup(true)
257 ,_disabledBracketedPasteMode(false)
258 ,_actSel(0)
259 ,_wordSelectionMode(false)
260 ,_lineSelectionMode(false)
261 ,_preserveLineBreaks(false)
262 ,_columnSelectionMode(false)
263 ,_scrollbarLocation(NoScrollBar)
264 ,_wordCharacters(":@-./_~")
265 ,_bellMode(SystemBeepBell)
266 ,_blinking(false)
267 ,_cursorBlinking(false)
268 ,_hasBlinkingCursor(false)
269 ,_ctrlDrag(false)
270 ,_tripleClickMode(SelectWholeLine)
271 ,_isFixedSize(false)
272 ,_possibleTripleClick(false)
273 ,_resizeWidget(nullptr)
274 ,_resizeTimer(nullptr)
275 ,_outputSuspendedLabel(nullptr)
276 ,_lineSpacing(0)
277 ,_colorsInverted(false)
278 ,_blendColor(qRgba(0,0,0,0xff))
279 ,_filterChain(new TerminalImageFilterChain())
280 ,_cursorShape(BlockCursor)
281 ,_readonly(false)
282{
283 // terminal applications are not designed with Right-To-Left in mind,
284 // so the layout is forced to Left-To-Right
285 setLayoutDirection(Qt::LeftToRight);
286
287 // The offsets are not yet calculated.
288 // Do not calculate these too often to be more smoothly when resizing
289 // konsole in opaque mode.
292
293 // create scroll bar for scrolling output up and down
294 // set the scroll bar's slider to occupy the whole area of the scroll bar initially
295 _scrollBar = new QScrollBar(this);
296 setScroll(0,0);
297 _scrollBar->setCursor( Qt::ArrowCursor );
298 connect(_scrollBar, SIGNAL(valueChanged(int)), this,
299 SLOT(scrollBarPositionChanged(int)));
300
301 // setup timers for blinking cursor and text
302 _blinkTimer = new QTimer(this);
303 connect(_blinkTimer, SIGNAL(timeout()), this, SLOT(blinkEvent()));
304
305 _blinkCursorTimer = new QTimer(this);
306 connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent()));
307
308 _process_filter_timer = new QTimer (this);
309 connect (_process_filter_timer, SIGNAL (timeout ()),
310 this, SLOT (processFilters ()));
311 _process_filter_timer->start (300);
312
313 // QCursor::setAutoHideCursor( this, true );
314
315 setUsesMouse(true);
318 setMouseTracking(true);
319
320 // Enable drag and drop
321 setAcceptDrops(true); // attempt
323
324 setFocusPolicy( Qt::WheelFocus );
325
326 // enable input method support
327 setAttribute(Qt::WA_InputMethodEnabled, true);
328
329 // this is an important optimization, it tells Qt
330 // that TerminalDisplay will handle repainting its entire area.
331 setAttribute(Qt::WA_OpaquePaintEvent);
332
333 _gridLayout = new QGridLayout(this);
334 _gridLayout->setMargin(0);
335
336 setLayout( _gridLayout );
337}
338
340{
341 qApp->removeEventFilter( this );
342
343 delete[] _image;
344
345 delete _gridLayout;
347 delete _filterChain;
348}
349
350/* ------------------------------------------------------------------------- */
351/* */
352/* Display Operations */
353/* */
354/* ------------------------------------------------------------------------- */
355
356/**
357 A table for emulating the simple (single width) unicode drawing chars.
358 It represents the 250x - 257x glyphs. If it's zero, we can't use it.
359 if it's not, it's encoded as follows: imagine a 5x5 grid where the points are numbered
360 0 to 24 left to top, top to bottom. Each point is represented by the corresponding bit.
361
362 Then, the pixels basically have the following interpretation:
363 _|||_
364 -...-
365 -...-
366 -...-
367 _|||_
368
369where _ = none
370 | = vertical line.
371 - = horizontal line.
372 */
373
374
376{
377 TopL = (1<<1),
378 TopC = (1<<2),
379 TopR = (1<<3),
380
381 LeftT = (1<<5),
382 Int11 = (1<<6),
383 Int12 = (1<<7),
384 Int13 = (1<<8),
385 RightT = (1<<9),
386
387 LeftC = (1<<10),
388 Int21 = (1<<11),
389 Int22 = (1<<12),
390 Int23 = (1<<13),
391 RightC = (1<<14),
392
393 LeftB = (1<<15),
394 Int31 = (1<<16),
395 Int32 = (1<<17),
396 Int33 = (1<<18),
397 RightB = (1<<19),
398
399 BotL = (1<<21),
400 BotC = (1<<22),
401 BotR = (1<<23)
403
405{
406 _cursorShape = shape;
407}
409{
410 return _cursorShape;
411}
412void TerminalView::setKeyboardCursorColor(bool useForegroundColor, const QColor& color)
413{
414 if (useForegroundColor)
415 _cursorColor = QColor(); // an invalid color means that
416 // the foreground color of the
417 // current character should
418 // be used
419
420 else
421 _cursorColor = color;
422}
424{
425 return _cursorColor;
426}
427
428void TerminalView::drawBackground(QPainter& painter, const QRect& rect, const QColor& backgroundColor)
429{
430 // the area of the widget showing the contents of the terminal display is drawn
431 // using the background color from the color scheme set with setColorTable()
432 //
433 // the area of the widget behind the scroll-bar is drawn using the background
434 // brush from the scroll-bar's palette, to give the effect of the scroll-bar
435 // being outside of the terminal display and visual consistency with other KDE
436 // applications.
437 //
438 QRect scrollBarArea = _scrollBar->isVisible() ?
439 rect.intersected(_scrollBar->geometry()) :
440 QRect();
441
442 QRegion contentsRegion = QRegion(rect).subtracted(scrollBarArea);
443 QRect contentsRect = contentsRegion.boundingRect();
444
445 painter.fillRect(contentsRect, backgroundColor);
446 painter.fillRect(scrollBarArea,_scrollBar->palette().window());
447}
448
450 const QRect& rect,
451 const QColor& foregroundColor,
452 const QColor& /*backgroundColor*/,
453 bool& invertCharacterColor)
454{
455 QRect cursorRect = rect;
456 cursorRect.setHeight(_fontHeight - _lineSpacing - 1);
457
458 if (!_cursorBlinking)
459 {
460 if ( _cursorColor.isValid() )
461 painter.setPen(_cursorColor);
462 else {
463 painter.setPen(foregroundColor);
464 }
465
466 if ( _cursorShape == BlockCursor )
467 {
468 // draw the cursor outline, adjusting the area so that
469 // it is draw entirely inside 'rect'
470 int penWidth = qMax(1,painter.pen().width());
471
472 painter.drawRect(cursorRect.adjusted(penWidth/2,
473 penWidth/2,
474 - penWidth/2 - penWidth%2,
475 - penWidth/2 - penWidth%2));
476 if ( hasFocus() )
477 {
478 painter.fillRect(cursorRect, _cursorColor.isValid() ? _cursorColor : foregroundColor);
479
480 if ( !_cursorColor.isValid() )
481 {
482 // invert the colour used to draw the text to ensure that the character at
483 // the cursor position is readable
484 invertCharacterColor = true;
485 }
486 }
487 }
488 else if ( _cursorShape == UnderlineCursor )
489 painter.drawLine(cursorRect.left(),
490 cursorRect.bottom(),
491 cursorRect.right(),
492 cursorRect.bottom());
493 else if ( _cursorShape == IBeamCursor )
494 painter.drawLine(cursorRect.left(),
495 cursorRect.top(),
496 cursorRect.left(),
497 cursorRect.bottom());
498
499 }
500}
501
503 const QRect& rect,
504 const QString& text,
505 const Character* style,
506 bool invertCharacterColor)
507{
508 // don't draw text which is currently blinking
509 if ( _blinking && (style->rendition & RE_BLINK) )
510 return;
511
512 // setup bold and underline
513 bool useBold = style->rendition & RE_BOLD || style->isBold(_colorTable) || font().bold();
514 bool useUnderline = style->rendition & RE_UNDERLINE || font().underline();
515
516 QFont font = painter.font();
517 if ( font.bold() != useBold
518 || font.underline() != useUnderline )
519 {
520 font.setBold(useBold);
521 font.setUnderline(useUnderline);
522 painter.setFont(font);
523 }
524
525 const CharacterColor& textColor = ( invertCharacterColor ? style->backgroundColor : style->foregroundColor );
526 const QColor color = textColor.color(_colorTable);
527
528 QPen pen = painter.pen();
529 if ( pen.color() != color )
530 {
531 pen.setColor(color);
532 painter.setPen(color);
533 }
534 // draw text
535 // the drawText(rect,flags,string) overload is used here with null flags
536 // instead of drawText(rect,string) because the (rect,string) overload causes
537 // the application's default layout direction to be used instead of
538 // the widget-specific layout direction, which should always be
539 // Qt::LeftToRight for this widget
540 painter.drawText(rect,0,text);
541}
542
544 const QRect& rect,
545 const QString& text,
546 const Character* style)
547{
548 painter.save();
549
550 // setup painter
551 const QColor foregroundColor = style->foregroundColor.color(_colorTable);
552 const QColor backgroundColor = style->backgroundColor.color(_colorTable);
553
554 // draw background if different from the display's background color
555 if ( backgroundColor != palette().window().color() )
556 drawBackground(painter,rect,backgroundColor);
557
558 // draw cursor shape if the current character is the cursor
559 // this may alter the foreground and background colors
560 bool invertCharacterColor = false;
561
562 if ( style->rendition & RE_CURSOR )
563 drawCursor(painter,rect,foregroundColor,backgroundColor,invertCharacterColor);
564 // draw text
565 drawCharacters(painter,rect,text,style,invertCharacterColor);
566
567 painter.restore();
568}
569
571uint TerminalView::randomSeed() const { return _randomSeed; }
572
573#if 0
574/*!
575 Set XIM Position
576*/
577void TerminalDisplay::setCursorPos(const int curx, const int cury)
578{
579 QPoint tL = contentsRect().topLeft();
580 int tLx = tL.x();
581 int tLy = tL.y();
582
583 int xpos, ypos;
584 ypos = _topMargin + tLy + _fontHeight*(cury-1) + _fontAscent;
585 xpos = _leftMargin + tLx + _fontWidth*curx;
586 //setMicroFocusHint(xpos, ypos, 0, _fontHeight); //### ???
587 // fprintf(stderr, "x/y = %d/%d\txpos/ypos = %d/%d\n", curx, cury, xpos, ypos);
588 _cursorLine = cury;
589 _cursorCol = curx;
590}
591#endif
592
593// scrolls the image by 'lines', down if lines > 0 or up otherwise.
594//
595// the terminal emulation keeps track of the scrolling of the character
596// image as it receives input, and when the view is updated, it calls scrollImage()
597// with the final scroll amount. this improves performance because scrolling the
598// display is much cheaper than re-rendering all the text for the
599// part of the image which has moved up or down.
600// Instead only new lines have to be drawn
601//
602// note: it is important that the area of the display which is
603// scrolled aligns properly with the character grid -
604// which has a top left point at (_leftMargin,_topMargin) ,
605// a cell width of _fontWidth and a cell height of _fontHeight).
606void TerminalView::scrollImage(int lines , const QRect& screenWindowRegion)
607{
608 // if the flow control warning is enabled this will interfere with the
609 // scrolling optimisations and cause artifacts. the simple solution here
610 // is to just disable the optimisation whilst it is visible
611 if ( _outputSuspendedLabel && _outputSuspendedLabel->isVisible() ) {
612 return;
613 }
614
615 // constrain the region to the display
616 // the bottom of the region is capped to the number of lines in the display's
617 // internal image - 2, so that the height of 'region' is strictly less
618 // than the height of the internal image.
619 QRect region = screenWindowRegion;
620 region.setBottom( qMin(region.bottom(),this->_lines-2) );
621
622 if (lines == 0
623 || _image == nullptr
624 || !region.isValid()
625 || (region.top() + abs(lines)) >= region.bottom()
626 || this->_lines <= region.height() )
627 return;
628
629 QRect scrollRect;
630
631 void* firstCharPos = &_image[ region.top() * this->_columns ];
632 void* lastCharPos = &_image[ (region.top() + abs(lines)) * this->_columns ];
633
634 int top = _topMargin + (region.top() * _fontHeight);
635 int linesToMove = region.height() - abs(lines);
636 int bytesToMove = linesToMove *
637 this->_columns *
638 sizeof(Character);
639
640 Q_ASSERT( linesToMove > 0 );
641 Q_ASSERT( bytesToMove > 0 );
642
643 //scroll internal image
644 if ( lines > 0 )
645 {
646 // check that the memory areas that we are going to move are valid
647 Q_ASSERT( (char*)lastCharPos + bytesToMove <
648 (char*)(_image + (this->_lines * this->_columns)) );
649
650 Q_ASSERT( (lines*this->_columns) < _imageSize );
651
652 //scroll internal image down
653 memmove( firstCharPos , lastCharPos , bytesToMove );
654
655 //set region of display to scroll, making sure that
656 //the region aligns correctly to the character grid
657 scrollRect = QRect( _leftMargin , top,
658 this->_usedColumns * _fontWidth ,
659 linesToMove * _fontHeight );
660 }
661 else
662 {
663 // check that the memory areas that we are going to move are valid
664 Q_ASSERT( (char*)firstCharPos + bytesToMove <
665 (char*)(_image + (this->_lines * this->_columns)) );
666
667 //scroll internal image up
668 memmove( lastCharPos , firstCharPos , bytesToMove );
669
670 //set region of the display to scroll, making sure that
671 //the region aligns correctly to the character grid
672 QPoint topPoint( _leftMargin , top + abs(lines)*_fontHeight );
673
674 scrollRect = QRect( topPoint ,
675 QSize( this->_usedColumns*_fontWidth ,
676 linesToMove * _fontHeight ));
677 }
678
679 //scroll the display vertically to match internal _image
680 scroll( 0 , _fontHeight * (-lines) , scrollRect );
681}
682
684{
685 QRegion region;
686 foreach( Filter::HotSpot* hotSpot , _filterChain->hotSpots() )
687 {
688 QRect rect;
689 rect.setLeft(hotSpot->startColumn());
690 rect.setTop(hotSpot->startLine());
691 rect.setRight(hotSpot->endColumn());
692 rect.setBottom(hotSpot->endLine());
693
694 region |= imageToWidget(rect);
695 }
696 return region;
697}
698
700{
701 if (!_screenWindow)
702 return;
703
704 QRegion preUpdateHotSpots = hotSpotRegion();
705
706 // use _screenWindow->getImage() here rather than _image because
707 // other classes may call processFilters() when this display's
708 // ScreenWindow emits a scrolled() signal - which will happen before
709 // updateImage() is called on the display and therefore _image is
710 // out of date at this point
711 _filterChain->setImage( _screenWindow->getImage(),
712 _screenWindow->windowLines(),
713 _screenWindow->windowColumns(),
714 _screenWindow->getLineProperties() );
716
717 QRegion postUpdateHotSpots = hotSpotRegion();
718
719 update( preUpdateHotSpots | postUpdateHotSpots );
720}
721
723{
724 if ( !_screenWindow )
725 return;
727
728 // optimization - scroll the existing image where possible and
729 // avoid expensive text drawing for parts of the image that
730 // can simply be moved up or down
731 scrollImage( _screenWindow->scrollCount() ,
732 _screenWindow->scrollRegion() );
733 _screenWindow->resetScrollCount();
734
735 Character* const newimg = _screenWindow->getImage();
736 int lines = _screenWindow->windowLines();
737 int columns = _screenWindow->windowColumns();
738
739 setScroll( _screenWindow->currentLine() , _screenWindow->lineCount() );
740
741 if (!_image)
742 updateImageSize(); // Create _image
743
744 Q_ASSERT( this->_usedLines <= this->_lines );
745 Q_ASSERT( this->_usedColumns <= this->_columns );
746
747 int y,x,len;
748
749 QPoint tL = contentsRect().topLeft();
750
751 int tLx = tL.x();
752 int tLy = tL.y();
753 _hasBlinker = false;
754
755 CharacterColor cf; // undefined
756 CharacterColor _clipboard; // undefined
757 int cr = -1; // undefined
758
759 const int linesToUpdate = qMin(this->_lines, qMax(0,lines ));
760 const int columnsToUpdate = qMin(this->_columns,qMax(0,columns));
761
762 QChar *disstrU = new QChar[columnsToUpdate];
763 char *dirtyMask = new char[columnsToUpdate+2];
764 QRegion dirtyRegion;
765
766 // debugging variable, this records the number of lines that are found to
767 // be 'dirty' ( ie. have changed from the old _image to the new _image ) and
768 // which therefore need to be repainted
769 int dirtyLineCount = 0;
770
771 for (y = 0; y < linesToUpdate; y++)
772 {
773 const Character* currentLine = &_image[y*this->_columns];
774 const Character* const newLine = &newimg[y*columns];
775
776 bool updateLine = false;
777
778 // The dirty mask indicates which characters need repainting. We also
779 // mark surrounding neighbours dirty, in case the character exceeds
780 // its cell boundaries
781 memset(dirtyMask, 0, columnsToUpdate+2);
782
783 for( x = 0 ; x < columnsToUpdate ; x++)
784 {
785 if ( newLine[x] != currentLine[x] )
786 {
787 dirtyMask[x] = true;
788 }
789 }
790
791 if (!_resizing) // not while _resizing, we're expecting a paintEvent
792 for (x = 0; x < columnsToUpdate; x++)
793 {
794 _hasBlinker |= (newLine[x].rendition & RE_BLINK);
795
796 // Start drawing if this character or the next one differs.
797 // We also take the next one into account to handle the situation
798 // where characters exceed their cell width.
799 if (dirtyMask[x])
800 {
801 quint16 c = newLine[x+0].character;
802 if ( !c )
803 continue;
804 int p = 0;
805 disstrU[p++] = c; //fontMap(c);
806 bool doubleWidth = (x+1 == columnsToUpdate) ? false : (newLine[x+1].character == 0);
807 cr = newLine[x].rendition;
808 _clipboard = newLine[x].backgroundColor;
809 if (newLine[x].foregroundColor != cf) cf = newLine[x].foregroundColor;
810 int lln = columnsToUpdate - x;
811 for (len = 1; len < lln; len++)
812 {
813 const Character& ch = newLine[x+len];
814
815 if (!ch.character)
816 continue; // Skip trailing part of multi-col chars.
817
818 bool nextIsDoubleWidth = (x+len+1 == columnsToUpdate) ? false : (newLine[x+len+1].character == 0);
819
820 if ( ch.foregroundColor != cf ||
822 ch.rendition != cr ||
823 !dirtyMask[x+len] ||
824 nextIsDoubleWidth != doubleWidth )
825 break;
826
827 disstrU[p++] = c; //fontMap(c);
828 }
829
830 QString unistr(disstrU, p);
831
832 bool saveFixedFont = _fixedFont;
833 if (doubleWidth)
834 _fixedFont = false;
835
836 updateLine = true;
837
838 _fixedFont = saveFixedFont;
839 x += len - 1;
840 }
841
842 }
843
844 //both the top and bottom halves of double height _lines must always be redrawn
845 //although both top and bottom halves contain the same characters, only
846 //the top one is actually
847 //drawn.
848 if (_lineProperties.count() > y)
849 updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT);
850
851 // if the characters on the line are different in the old and the new _image
852 // then this line must be repainted.
853 if (updateLine)
854 {
855 dirtyLineCount++;
856
857 // add the area occupied by this line to the region which needs to be
858 // repainted
859 QRect dirtyRect = QRect( _leftMargin+tLx ,
860 _topMargin+tLy+_fontHeight*y ,
861 _fontWidth * columnsToUpdate ,
862 _fontHeight );
863
864 dirtyRegion |= dirtyRect;
865 }
866
867 // replace the line of characters in the old _image with the
868 // current line of the new _image
869 memcpy((void*)currentLine,(const void*)newLine,columnsToUpdate*sizeof(Character));
870 }
871
872 // if the new _image is smaller than the previous _image, then ensure that the area
873 // outside the new _image is cleared
874 if ( linesToUpdate < _usedLines )
875 {
876 dirtyRegion |= QRect( _leftMargin+tLx ,
877 _topMargin+tLy+_fontHeight*linesToUpdate ,
878 _fontWidth * this->_columns ,
879 _fontHeight * (_usedLines-linesToUpdate) );
880 }
881 _usedLines = linesToUpdate;
882
883 if ( columnsToUpdate < _usedColumns )
884 {
885 dirtyRegion |= QRect( _leftMargin+tLx+columnsToUpdate*_fontWidth ,
886 _topMargin+tLy ,
887 _fontWidth * (_usedColumns-columnsToUpdate) ,
888 _fontHeight * this->_lines );
889 }
890 _usedColumns = columnsToUpdate;
891
893
894 // update the parts of the display which have changed
895 update(dirtyRegion);
896
897 if ( _hasBlinker && !_blinkTimer->isActive()) _blinkTimer->start( BLINK_DELAY );
898 if (!_hasBlinker && _blinkTimer->isActive()) { _blinkTimer->stop(); _blinking = false; }
899 delete[] dirtyMask;
900 delete[] disstrU;
901
902}
903
905{
906 if (_terminalSizeHint && isVisible())
907 {
910 return;
911 }
912 if (!_resizeWidget)
913 {
914 _resizeWidget = new QLabel(("Size: XXX x XXX"), this);
915 _resizeWidget->setMinimumWidth(octave::qt_fontmetrics_horizontal_advance(_resizeWidget->fontMetrics(), "Size: XXX x XXX"));
916 _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height());
917 _resizeWidget->setAlignment(Qt::AlignCenter);
918
919 _resizeWidget->setStyleSheet("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)");
920
921 _resizeTimer = new QTimer(this);
922 _resizeTimer->setSingleShot(true);
923 connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide()));
924
925 }
926 QString sizeStr = QString("Size: %1 x %2").arg(_columns).arg(_lines);
927 _resizeWidget->setText(sizeStr);
928 _resizeWidget->move((width()-_resizeWidget->width())/2,
929 (height()-_resizeWidget->height())/2+20);
930 _resizeWidget->show();
931 _resizeTimer->start(1000);
932 }
933}
934
936{
937 _hasBlinkingCursor=blink;
938
940}
941
943{
944 if (blink && !_blinkCursorTimer->isActive())
946
947 if (!blink && _blinkCursorTimer->isActive())
948 {
949 _blinkCursorTimer->stop();
950 if (_cursorBlinking)
952 }
953}
954
955void TerminalView::paintEvent( QPaintEvent* pe )
956{
957 updateImage();
958 //qDebug("%s %d paintEvent", __FILE__, __LINE__);
959 QPainter paint(this);
960 //qDebug("%s %d paintEvent %d %d", __FILE__, __LINE__, paint.window().top(), paint.window().right());
961
962#if defined (HAVE_QREGION_ITERATORS)
963 for (QRect rect : (pe->region() & contentsRect()))
964#else
965 foreach (QRect rect, (pe->region() & contentsRect()).rects())
966#endif
967 {
968 drawBackground(paint,rect,palette().window().color());
969 drawContents(paint, rect);
970 }
971 // drawBackground(paint,contentsRect(),palette().background().color(), true /* use opacity setting */);
972 // drawContents(paint, contentsRect());
974 paintFilters(paint);
975 paint.end();
976}
977
978void TerminalView::focusInEvent(QFocusEvent *focusEvent)
979{
981 updateImage();
982 repaint();
983 update();
984
985 QWidget::focusInEvent(focusEvent);
986}
987
988void TerminalView::focusOutEvent(QFocusEvent *focusEvent)
989{
990 // Force the cursor to be redrawn.
991 _cursorBlinking = true;
993
994 QWidget::focusOutEvent(focusEvent);
995}
996
998{
999 if (_screenWindow)
1000 return _screenWindow->cursorPosition();
1001 else
1002 return QPoint(0,0);
1003}
1004
1006{
1007 const int preeditLength = string_width(_inputMethodData.preeditString);
1008
1009 if ( preeditLength == 0 )
1010 return QRect();
1011
1012 return QRect(_leftMargin + _fontWidth*cursorPosition().x(),
1014 _fontWidth*preeditLength,
1015 _fontHeight);
1016}
1017
1019{
1020 if ( _inputMethodData.preeditString.isEmpty() ) {
1021 return;
1022 }
1023 const QPoint cursorPos = cursorPosition();
1024
1025 bool invertColors = false;
1026 const QColor background = _colorTable[DEFAULT_BACK_COLOR].color;
1027 const QColor foreground = _colorTable[DEFAULT_FORE_COLOR].color;
1028 const Character* style = &_image[loc(cursorPos.x(),cursorPos.y())];
1029
1030 drawBackground(painter,rect,background);
1031 drawCursor(painter,rect,foreground,background,invertColors);
1032 drawCharacters(painter,rect,_inputMethodData.preeditString,style,invertColors);
1033
1035}
1036
1038{
1039 return _filterChain;
1040}
1041
1043{
1044 //qDebug("%s %d paintFilters", __FILE__, __LINE__);
1045
1046 // get color of character under mouse and use it to draw
1047 // lines for filters
1048 QPoint cursorPos = mapFromGlobal(QCursor::pos());
1049 int cursorLine;
1050 int cursorColumn;
1051 getCharacterPosition( cursorPos , cursorLine , cursorColumn );
1052 Character cursorCharacter = _image[loc(cursorColumn,cursorLine)];
1053
1054 painter.setPen( QPen(cursorCharacter.foregroundColor.color(colorTable())) );
1055
1056 // iterate over hotspots identified by the display's currently active filters
1057 // and draw appropriate visuals to indicate the presence of the hotspot
1058
1060 QListIterator<Filter::HotSpot*> iter(spots);
1061 while (iter.hasNext())
1062 {
1063 Filter::HotSpot* spot = iter.next();
1064
1065 for ( int line = spot->startLine() ; line <= spot->endLine() ; line++ )
1066 {
1067 int startColumn = 0;
1068 int endColumn = _columns-1; // TODO use number of _columns which are actually
1069 // occupied on this line rather than the width of the
1070 // display in _columns
1071
1072 // ignore whitespace at the end of the lines
1073 while ( QChar(_image[loc(endColumn,line)].character).isSpace() && endColumn > 0 )
1074 endColumn--;
1075
1076 // increment here because the column which we want to set 'endColumn' to
1077 // is the first whitespace character at the end of the line
1078 endColumn++;
1079
1080 if ( line == spot->startLine() )
1081 startColumn = spot->startColumn();
1082 if ( line == spot->endLine() )
1083 endColumn = spot->endColumn();
1084
1085 // subtract one pixel from
1086 // the right and bottom so that
1087 // we do not overdraw adjacent
1088 // hotspots
1089 //
1090 // subtracting one pixel from all sides also prevents an edge case where
1091 // moving the mouse outside a link could still leave it underlined
1092 // because the check below for the position of the cursor
1093 // finds it on the border of the target area
1094 QRect r;
1095 r.setCoords( startColumn*_fontWidth + 1, line*_fontHeight + 1,
1096 endColumn*_fontWidth - 1, (line+1)*_fontHeight - 1 );
1097
1098 // Underline link hotspots
1099 if ( spot->type() == Filter::Link ||
1100 spot->type() == Filter::ErrorLink)
1101 {
1102 QFontMetrics metrics(font());
1103
1104 // find the baseline (which is the invisible line that the
1105 // characters in the font sit on
1106 int baseline = r.bottom() + 1;
1107 // find the position of the underline below that
1108 int underlinePos = baseline + metrics.underlinePos();
1109
1110 if (r.contains (mapFromGlobal(QCursor::pos())))
1111 {
1112 if (spot->type () == Filter::ErrorLink)
1113 painter.setPen (QColor (255,0,0));
1114 painter.drawLine (r.left(), underlinePos,
1115 r.right() + 2, underlinePos);
1116 }
1117 }
1118 // Marker hotspots simply have a transparent rectanglular shape
1119 // drawn on top of them
1120 else if ( spot->type() == Filter::Marker )
1121 {
1122 //TODO - Do not use a hardcoded colour for this
1123 painter.fillRect(r,QBrush(QColor(255,0,0,120)));
1124 }
1125
1126 }
1127 }
1128}
1129void TerminalView::drawContents(QPainter &paint, const QRect &rect)
1130{
1131 //qDebug("%s %d drawContents and rect x=%d y=%d w=%d h=%d", __FILE__, __LINE__, rect.x(), rect.y(),rect.width(),rect.height());
1132
1133 QPoint topLeft = contentsRect().topLeft();
1134 // Take the topmost vertical position for the view.
1135 int topLeftY = topLeft.y();
1136
1137 // In Konsole, the view has been centered. Don't do that here, since there
1138 // are strange hopping effects during a resize when the view does no match
1139 // exactly the widget width.
1140 // int topLeftX = (_contentWidth - _usedColumns * _fontWidth) / 2;
1141 int topLeftX = 0;
1142
1143 int leftUpperX = qMin(_usedColumns-1, qMax(0, qFloor((rect.left() - topLeftX - _leftMargin ) / _fontWidth)));
1144 int leftUpperY = qMin(_usedLines-1, qMax(0, qFloor((rect.top() - topLeftY - _topMargin ) / _fontHeight)));
1145 int rightLowerX = qMin(_usedColumns-1, qMax(0, qFloor((rect.right() - topLeftX - _leftMargin ) / _fontWidth)));
1146 int rightLowerY = qMin(_usedLines-1, qMax(0, qFloor((rect.bottom() - topLeftY - _topMargin ) / _fontHeight)));
1147
1148 const int bufferSize = _usedColumns;
1149 QChar *disstrU = new QChar[bufferSize];
1150 for (int y = leftUpperY; y <= rightLowerY; y++)
1151 {
1152 quint16 c = _image[loc(leftUpperX,y)].character;
1153 int x = leftUpperX;
1154 if(!c && x)
1155 x--; // Search for start of multi-column character
1156 for (; x <= rightLowerX; x++)
1157 {
1158 int len = 1;
1159 int p = 0;
1160
1161 // is this a single character or a sequence of characters ?
1162 if ( _image[loc(x,y)].rendition & RE_EXTENDED_CHAR )
1163 {
1164 // sequence of characters
1165 ushort extendedCharLength = 0;
1166 ushort* chars = ExtendedCharTable::instance
1167 .lookupExtendedChar(_image[loc(x,y)].charSequence,extendedCharLength);
1168 for ( int index = 0 ; index < extendedCharLength ; index++ )
1169 {
1170 Q_ASSERT( p < bufferSize );
1171 disstrU[p++] = chars[index];
1172 }
1173 }
1174 else
1175 {
1176 // single character
1177 c = _image[loc(x,y)].character;
1178 if (c)
1179 {
1180 Q_ASSERT( p < bufferSize );
1181 disstrU[p++] = c; //fontMap(c);
1182 }
1183 }
1184
1185 bool doubleWidth = (_image[ qMin(loc(x,y)+1,_imageSize) ].character == 0);
1186 CharacterColor currentForeground = _image[loc(x,y)].foregroundColor;
1187 CharacterColor currentBackground = _image[loc(x,y)].backgroundColor;
1188 quint8 currentRendition = _image[loc(x,y)].rendition;
1189
1190 while (x+len <= rightLowerX &&
1191 _image[loc(x+len,y)].foregroundColor == currentForeground &&
1192 _image[loc(x+len,y)].backgroundColor == currentBackground &&
1193 _image[loc(x+len,y)].rendition == currentRendition &&
1194 (_image[ qMin(loc(x+len,y)+1,_imageSize) ].character == 0) == doubleWidth)
1195 {
1196 c = _image[loc(x+len,y)].character;
1197 if (c)
1198 disstrU[p++] = c; //fontMap(c);
1199 if (doubleWidth) // assert((_image[loc(x+len,y)+1].character == 0)), see above if condition
1200 len++; // Skip trailing part of multi-column character
1201 len++;
1202 }
1203 if ((x+len < _usedColumns) && (!_image[loc(x+len,y)].character))
1204 len++; // Adjust for trailing part of multi-column character
1205
1206 bool save__fixedFont = _fixedFont;
1207 if (doubleWidth)
1208 _fixedFont = false;
1209 QString unistr(disstrU,p);
1210
1211 if (y < _lineProperties.size())
1212 {
1214 paint.scale(2,1);
1215 }
1216
1218 paint.scale(1,2);
1219 }
1220 }
1221
1222 // calculate the area in which the text will be drawn
1223 QRect textArea = QRect( _leftMargin+topLeftX+_fontWidth*x ,
1224 _topMargin+topLeftY+_fontHeight*y ,
1226 _fontHeight);
1227
1228 // move the calculated area to take account of scaling applied to the painter.
1229 // the position of the area from the origin (0,0) is scaled
1230 // by the opposite of whatever
1231 // transformation has been applied to the painter. this ensures that
1232 // painting does actually start from textArea.topLeft()
1233 // (instead of textArea.topLeft() * painter-scale)
1234 QTransform inverted = paint.transform().inverted();
1235 textArea.moveCenter( inverted.map(textArea.center()) );
1236
1237
1238 //paint text fragment
1239 drawTextFragment( paint,
1240 textArea,
1241 unistr,
1242 &_image[loc(x,y)] );
1243
1244
1245 _fixedFont = save__fixedFont;
1246
1247 //reset back to single-width, single-height _lines
1248 paint.resetTransform();
1249
1250 if (y < _lineProperties.size()-1)
1251 {
1252 //double-height _lines are represented by two adjacent _lines
1253 //containing the same characters
1254 //both _lines will have the LINE_DOUBLEHEIGHT attribute.
1255 //If the current line has the LINE_DOUBLEHEIGHT attribute,
1256 //we can therefore skip the next line
1258 y++;
1259 }
1260 x += len - 1;
1261 } // for x
1262 } // for y
1263 delete [] disstrU;
1264}
1265
1267{
1269
1270 //TODO: Optimise to only repaint the areas of the widget
1271 // where there is blinking text
1272 // rather than repainting the whole widget.
1273 update();
1274}
1275
1276QRect TerminalView::imageToWidget(const QRect& imageArea) const
1277{
1278 //qDebug("%s %d imageToWidget", __FILE__, __LINE__);
1279 QRect result;
1280 result.setLeft( _leftMargin + _fontWidth * imageArea.left() );
1281 result.setTop( _topMargin + _fontHeight * imageArea.top() );
1282 result.setWidth( _fontWidth * imageArea.width() );
1283 result.setHeight( _fontHeight * imageArea.height() );
1284
1285 return result;
1286}
1287
1289{
1292 else
1293 _cursorBlinking = false;
1294
1295 QRect cursorRect = imageToWidget( QRect(cursorPosition(),QSize(1,1)) );
1296
1297 update(cursorRect);
1298}
1299
1300/* ------------------------------------------------------------------------- */
1301/* */
1302/* Resizing */
1303/* */
1304/* ------------------------------------------------------------------------- */
1305
1306void TerminalView::resizeEvent(QResizeEvent*)
1307{
1309}
1310
1312{
1313 if (_isFixedSize)
1314 {
1316 QWidget::setFixedSize(sizeHint());
1317 parentWidget()->adjustSize();
1318 parentWidget()->setFixedSize(parentWidget()->sizeHint());
1319 return;
1320 }
1321 if (_image)
1323}
1324
1326{
1327 //qDebug("%s %d updateImageSize", __FILE__, __LINE__);
1328 Character* oldimg = _image;
1329 int oldlin = _lines;
1330 int oldcol = _columns;
1331
1332 makeImage();
1333
1334
1335 // copy the old image to reduce flicker
1336 int lines = qMin(oldlin,_lines);
1337 int columns = qMin(oldcol,_columns);
1338
1339 //qDebug("%s %d updateImageSize", __FILE__, __LINE__);
1340 if (oldimg)
1341 {
1342 for (int line = 0; line < lines; line++)
1343 {
1344 memcpy((void*)&_image[_columns*line],
1345 (void*)&oldimg[oldcol*line],columns*sizeof(Character));
1346 }
1347 delete[] oldimg;
1348 }
1349
1350 //qDebug("%s %d updateImageSize", __FILE__, __LINE__);
1351 if (_screenWindow)
1352 _screenWindow->setWindowLines(_lines);
1353
1354 _resizing = (oldlin!=_lines) || (oldcol!=_columns);
1355
1356 if ( _resizing )
1357 {
1358 //qDebug("%s %d updateImageSize", __FILE__, __LINE__);
1360#if defined (SIGWINCH)
1361 ::raise (SIGWINCH);
1362#endif
1363 emit changedContentSizeSignal(_contentHeight, _contentWidth); // expose resizeEvent
1364 }
1365 //qDebug("%s %d updateImageSize", __FILE__, __LINE__);
1366
1367 _resizing = false;
1368}
1369
1370//showEvent and hideEvent are reimplemented here so that it appears to other classes that the
1371//display has been resized when the display is hidden or shown.
1372//
1373//this allows
1374//TODO: Perhaps it would be better to have separate signals for show and hide instead of using
1375//the same signal as the one for a content size change
1377{
1379}
1381{
1383}
1384
1385/* ------------------------------------------------------------------------- */
1386/* */
1387/* Scrollbar */
1388/* */
1389/* ------------------------------------------------------------------------- */
1390
1392{
1393 if ( !_screenWindow )
1394 return;
1395
1396 _screenWindow->scrollTo( _scrollBar->value() );
1397
1398 // if the thumb has been moved to the bottom of the _scrollBar then set
1399 // the display to automatically track new output,
1400 // that is, scroll down automatically
1401 // to how new _lines as they are added
1402 const bool atEndOfOutput = (_scrollBar->value() == _scrollBar->maximum());
1403 _screenWindow->setTrackOutput( atEndOfOutput );
1404
1405 updateImage();
1406}
1407
1408void TerminalView::setScroll(int cursor, int slines)
1409{
1410 //qDebug("%s %d setScroll", __FILE__, __LINE__);
1411 // update _scrollBar if the range or value has changed,
1412 // otherwise return
1413 //
1414 // setting the range or value of a _scrollBar will always trigger
1415 // a repaint, so it should be avoided if it is not necessary
1416 if ( _scrollBar->minimum() == 0 &&
1417 _scrollBar->maximum() == (slines - _lines) &&
1418 _scrollBar->value() == cursor )
1419 {
1420 return;
1421 }
1422
1423 disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int)));
1424 _scrollBar->setRange(0,slines - _lines);
1425 _scrollBar->setSingleStep(1);
1426 _scrollBar->setPageStep(_lines);
1427 _scrollBar->setValue(cursor);
1428 connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int)));
1429}
1430
1432{
1433 if (_scrollbarLocation == position) {
1434 // return;
1435 }
1436
1437 if ( position == NoScrollBar )
1438 _scrollBar->hide();
1439 else
1440 _scrollBar->show();
1441
1442 _topMargin = _leftMargin = 1;
1443 _scrollbarLocation = position;
1444
1445 propagateSize();
1446 update();
1447}
1448
1450{
1451 if ( _possibleTripleClick && (ev->button()==Qt::LeftButton) ) {
1453 return;
1454 }
1455
1456 if ( !contentsRect().contains(ev->pos()) ) return;
1457
1458 if ( !_screenWindow ) return;
1459
1460 int charLine;
1461 int charColumn;
1462 getCharacterPosition(ev->pos(),charLine,charColumn);
1463 QPoint pos = QPoint(charColumn,charLine);
1464
1465 if ( ev->button() == Qt::LeftButton)
1466 {
1467
1468 Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn);
1469 if ( spot &&
1470 (spot->type() == Filter::Link || spot->type() == Filter::ErrorLink))
1471 {
1472 QList<QAction*> actions = spot->actions ();
1473 if (actions.length ())
1474 actions.at (0)->activate (QAction::Trigger);
1475 return;
1476 }
1477
1478 _lineSelectionMode = false;
1479 _wordSelectionMode = false;
1480
1481 emit isBusySelecting(true); // Keep it steady...
1482 // Drag only when the Control key is hold
1483 bool selected = false;
1484
1485 // The receiver of the testIsSelected() signal will adjust
1486 // 'selected' accordingly.
1487 //emit testIsSelected(pos.x(), pos.y(), selected);
1488
1489 selected = _screenWindow->isSelected(pos.x(),pos.y());
1490
1491 if ((!_ctrlDrag || ev->modifiers() & Qt::ControlModifier) && selected ) {
1492 // The user clicked inside selected text
1494 dragInfo.start = ev->pos();
1495 }
1496 else {
1497 // No reason to ever start a drag event
1499
1500 _preserveLineBreaks = !( ( ev->modifiers() & Qt::ControlModifier ) && !(ev->modifiers() & Qt::AltModifier) );
1501 _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier);
1502
1503 if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier))
1504 {
1505 _screenWindow->clearSelection();
1506
1507 //emit clearSelectionSignal();
1508 pos.ry() += _scrollBar->value();
1509 _iPntSel = _pntSel = pos;
1510 _actSel = 1; // left mouse button pressed but nothing selected yet.
1511
1512 }
1513 else
1514 {
1515 emit mouseSignal( 0, charColumn + 1, charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0);
1516 }
1517 }
1518 }
1519 else if ( ev->button() == Qt::MiddleButton )
1520 {
1521 if ( _mouseMarks || (!_mouseMarks && (ev->modifiers() & Qt::ShiftModifier)) )
1522 emitSelection(true,ev->modifiers() & Qt::ControlModifier);
1523 else
1524 emit mouseSignal( 1, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0);
1525 }
1526 else if ( ev->button() == Qt::RightButton )
1527 {
1528 if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier))
1529 {
1530 emit configureRequest( this,
1531 ev->modifiers() & (Qt::ShiftModifier|Qt::ControlModifier),
1532 ev->pos()
1533 );
1534 }
1535 else
1536 emit mouseSignal( 2, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0);
1537 }
1538
1539 QWidget::mousePressEvent (ev);
1540}
1541
1543{
1544 int charLine, charColumn;
1545 getCharacterPosition(position,charLine,charColumn);
1546
1547 Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn);
1548
1549 return spot ? spot->actions() : QList<QAction*>();
1550}
1551
1552void TerminalView::mouseMoveEvent(QMouseEvent* ev)
1553{
1554 int charLine = 0;
1555 int charColumn = 0;
1556
1557 getCharacterPosition(ev->pos(),charLine,charColumn);
1558
1559 // handle filters
1560 // change link hot-spot appearance on mouse-over
1561 Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn);
1562 if ( spot &&
1563 (spot->type() == Filter::Link || spot->type() == Filter::ErrorLink))
1564 {
1565 // change mouse cursor when mouse is over links
1566 if (! _mouseOverHotspotArea.isValid())
1567 setCursor (Qt::PointingHandCursor);
1568
1569 QRect previousHotspotArea = _mouseOverHotspotArea;
1570 _mouseOverHotspotArea.setCoords( qMin(spot->startColumn() , spot->endColumn()) * _fontWidth,
1571 spot->startLine() * _fontHeight,
1572 qMax(spot->startColumn() , spot->endColumn()) * _fontHeight,
1573 (spot->endLine()+1) * _fontHeight );
1574
1575 // display tooltips when mousing over links
1576 // TODO: Extend this to work with filter types other than links
1577 const QString& tooltip = spot->tooltip();
1578 if ( !tooltip.isEmpty() )
1579 {
1580 QToolTip::showText( mapToGlobal(ev->pos()) , tooltip , this , _mouseOverHotspotArea );
1581 }
1582
1583 update( _mouseOverHotspotArea | previousHotspotArea );
1584 }
1585 else if ( _mouseOverHotspotArea.isValid() )
1586 {
1587 setUsesMouse (true);
1588 update( _mouseOverHotspotArea );
1589 // set hotspot area to an invalid rectangle
1590 _mouseOverHotspotArea = QRect();
1591 }
1592
1593 // for auto-hiding the cursor, we need mouseTracking
1594 if (ev->buttons() == Qt::NoButton ) return;
1595
1596 // if the terminal is interested in mouse movements
1597 // then emit a mouse movement signal, unless the shift
1598 // key is being held down, which overrides this.
1599 if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
1600 {
1601 int button = 3;
1602 if (ev->buttons() & Qt::LeftButton)
1603 button = 0;
1604 if (ev->buttons() & Qt::MiddleButton)
1605 button = 1;
1606 if (ev->buttons() & Qt::RightButton)
1607 button = 2;
1608
1609
1610 emit mouseSignal( button,
1611 charColumn + 1,
1612 charLine + 1 +_scrollBar->value() -_scrollBar->maximum(),
1613 1 );
1614
1615 return;
1616 }
1617
1618 if (dragInfo.state == diPending)
1619 {
1620 // we had a mouse down, but haven't confirmed a drag yet
1621 // if the mouse has moved sufficiently, we will confirm
1622
1623 int distance = 10; //KGlobalSettings::dndEventDelay();
1624 if ( ev->x() > dragInfo.start.x() + distance || ev->x() < dragInfo.start.x() - distance ||
1625 ev->y() > dragInfo.start.y() + distance || ev->y() < dragInfo.start.y() - distance)
1626 {
1627 // we've left the drag square, we can start a real drag operation now
1628 emit isBusySelecting(false); // Ok.. we can breath again.
1629
1630 _screenWindow->clearSelection();
1631 doDrag();
1632 }
1633 return;
1634 }
1635 else if (dragInfo.state == diDragging)
1636 {
1637 // this isn't technically needed because mouseMoveEvent is suppressed during
1638 // Qt drag operations, replaced by dragMoveEvent
1639 return;
1640 }
1641
1642 if (_actSel == 0) return;
1643
1644 // don't extend selection while pasting
1645 if (ev->buttons() & Qt::MiddleButton) return;
1646
1647 extendSelection( ev->pos() );
1648}
1649
1650#if 0
1651void TerminalDisplay::setSelectionEnd()
1652{
1653 extendSelection( _configureRequestPoint );
1654}
1655#endif
1656
1657void TerminalView::extendSelection(const QPoint& position) {
1658 QPoint pos = position;
1659
1660 if (!_screenWindow) {
1661 return;
1662 }
1663
1664 QPoint tL = contentsRect().topLeft();
1665 int tLx = tL.x();
1666 int tLy = tL.y();
1667 int scroll = _scrollBar->value();
1668
1669 // we're in the process of moving the mouse with the left button pressed
1670 // the mouse cursor will kept caught within the bounds of the text in
1671 // this widget.
1672
1673 // Adjust position within text area bounds. See FIXME above.
1674 if (pos.x() < tLx + _leftMargin) {
1675 pos.setX(tLx + _leftMargin);
1676 }
1677 if (pos.x() > tLx + _leftMargin + _usedColumns * _fontWidth - 1) {
1678 pos.setX(tLx + _leftMargin + _usedColumns * _fontWidth);
1679 }
1680 if (pos.y() < tLy + _topMargin) {
1681 pos.setY(tLy + _topMargin);
1682 }
1683 if (pos.y() > tLy + _topMargin + _usedLines * _fontHeight - 1) {
1684 pos.setY(tLy + _topMargin + _usedLines * _fontHeight - 1);
1685 }
1686
1687 if (pos.y() == tLy + _topMargin + _usedLines * _fontHeight - 1) {
1688 _scrollBar->setValue(_scrollBar->value() + yMouseScroll); // scrollforward
1689 }
1690 if (pos.y() == tLy + _topMargin) {
1691 _scrollBar->setValue(_scrollBar->value() - yMouseScroll); // scrollback
1692 }
1693
1694 int charColumn = 0;
1695 int charLine = 0;
1696 getCharacterPosition(pos, charLine, charColumn);
1697
1698 QPoint here = QPoint(charColumn, charLine);
1699 QPoint ohere(here);
1700 QPoint _iPntSelCorr = _iPntSel;
1701 _iPntSelCorr.ry() -= _scrollBar->value();
1702 QPoint _pntSelCorr = _pntSel;
1703 _pntSelCorr.ry() -= _scrollBar->value();
1704 bool swapping = false;
1705
1706 if (_wordSelectionMode) {
1707 // Extend to word boundaries
1708 int i = 0;
1709 int selClass = 0;
1710
1711 bool left_not_right = (here.y() < _iPntSelCorr.y() ||
1712 (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));
1713 bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||
1714 (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));
1715 swapping = left_not_right != old_left_not_right;
1716
1717 // Find left (left_not_right ? from here : from start)
1718 QPoint left = left_not_right ? here : _iPntSelCorr;
1719 i = loc(left.x(), left.y());
1720 if (i >= 0 && i <= _imageSize) {
1721 selClass = charClass(_image[i].character);
1722 while (((left.x() > 0) || (left.y() > 0 && (_lineProperties[left.y() - 1] & LINE_WRAPPED)))
1723 && charClass(_image[i - 1].character) == selClass) {
1724 i--;
1725 if (left.x() > 0) {
1726 left.rx()--;
1727 } else {
1728 left.rx() = _usedColumns - 1;
1729 left.ry()--;
1730 }
1731 }
1732 }
1733
1734 // Find left (left_not_right ? from start : from here)
1735 QPoint right = left_not_right ? _iPntSelCorr : here;
1736 i = loc(right.x(), right.y());
1737 if (i >= 0 && i <= _imageSize) {
1738 selClass = charClass(_image[i].character);
1739 while (((right.x() < _usedColumns - 1) || (right.y() < _usedLines - 1 && (_lineProperties[right.y()] & LINE_WRAPPED)))
1740 && charClass(_image[i + 1].character) == selClass) {
1741 i++;
1742 if (right.x() < _usedColumns - 1) {
1743 right.rx()++;
1744 } else {
1745 right.rx() = 0;
1746 right.ry()++;
1747 }
1748 }
1749 }
1750
1751 // Pick which is start (ohere) and which is extension (here)
1752 if (left_not_right) {
1753 here = left;
1754 ohere = right;
1755 } else {
1756 here = right;
1757 ohere = left;
1758 }
1759 ohere.rx()++;
1760 }
1761
1762 if (_lineSelectionMode) {
1763 // Extend to complete line
1764 bool above_not_below = (here.y() < _iPntSelCorr.y());
1765
1766 QPoint above = above_not_below ? here : _iPntSelCorr;
1767 QPoint below = above_not_below ? _iPntSelCorr : here;
1768
1769 while (above.y() > 0 && (_lineProperties[above.y() - 1] & LINE_WRAPPED)) {
1770 above.ry()--;
1771 }
1772 while (below.y() < _usedLines - 1 && (_lineProperties[below.y()] & LINE_WRAPPED)) {
1773 below.ry()++;
1774 }
1775
1776 above.setX(0);
1777 below.setX(_usedColumns - 1);
1778
1779 // Pick which is start (ohere) and which is extension (here)
1780 if (above_not_below) {
1781 here = above;
1782 ohere = below;
1783 } else {
1784 here = below;
1785 ohere = above;
1786 }
1787
1788 QPoint newSelBegin = QPoint(ohere.x(), ohere.y());
1789 swapping = !(_tripleSelBegin == newSelBegin);
1790 _tripleSelBegin = newSelBegin;
1791
1792 ohere.rx()++;
1793 }
1794
1795 int offset = 0;
1797 int i = 0;
1798 int selClass = 0;
1799
1800 bool left_not_right = (here.y() < _iPntSelCorr.y() ||
1801 (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));
1802 bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||
1803 (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));
1804 swapping = left_not_right != old_left_not_right;
1805
1806 // Find left (left_not_right ? from here : from start)
1807 QPoint left = left_not_right ? here : _iPntSelCorr;
1808
1809 // Find left (left_not_right ? from start : from here)
1810 QPoint right = left_not_right ? _iPntSelCorr : here;
1811 if (right.x() > 0 && !_columnSelectionMode) {
1812 i = loc(right.x(), right.y());
1813 if (i >= 0 && i <= _imageSize) {
1814 selClass = charClass(_image[i - 1].character);
1815 if (selClass == ' ') {
1816 while (right.x() < _usedColumns - 1 && charClass(_image[i + 1].character) == selClass && (right.y() < _usedLines - 1) &&
1817 !(_lineProperties[right.y()] & LINE_WRAPPED)) {
1818 i++;
1819 right.rx()++;
1820 }
1821 if (right.x() < _usedColumns - 1) {
1822 right = left_not_right ? _iPntSelCorr : here;
1823 } else {
1824 right.rx()++; // will be balanced later because of offset=-1;
1825 }
1826 }
1827 }
1828 }
1829
1830 // Pick which is start (ohere) and which is extension (here)
1831 if (left_not_right) {
1832 here = left;
1833 ohere = right;
1834 offset = 0;
1835 } else {
1836 here = right;
1837 ohere = left;
1838 offset = -1;
1839 }
1840 }
1841
1842 if ((here == _pntSelCorr) && (scroll == _scrollBar->value())) {
1843 return; // not moved
1844 }
1845
1846 if (here == ohere) {
1847 return; // It's not left, it's not right.
1848 }
1849
1850 if (_actSel < 2 || swapping) {
1852 _screenWindow->setSelectionStart(ohere.x(), ohere.y(), true);
1853 } else {
1854 _screenWindow->setSelectionStart(ohere.x() - 1 - offset , ohere.y(), false);
1855 }
1856
1857 }
1858
1859 _actSel = 2; // within selection
1860 _pntSel = here;
1861 _pntSel.ry() += _scrollBar->value();
1862
1864 _screenWindow->setSelectionEnd(here.x(), here.y());
1865 } else {
1866 _screenWindow->setSelectionEnd(here.x() + offset, here.y());
1867 }
1868}
1869
1871{
1872 if ( !_screenWindow )
1873 return;
1874
1875 int charLine;
1876 int charColumn;
1877 getCharacterPosition(ev->pos(),charLine,charColumn);
1878
1879 if ( ev->button() == Qt::LeftButton)
1880 {
1881 emit isBusySelecting(false);
1882 if(dragInfo.state == diPending)
1883 {
1884 // We had a drag event pending but never confirmed. Kill selection
1885 _screenWindow->clearSelection();
1886 //emit clearSelectionSignal();
1887 }
1888 else
1889 {
1890 if ( _actSel > 1 )
1891 {
1893 }
1894
1895 _actSel = 0;
1896
1897 //FIXME: emits a release event even if the mouse is
1898 // outside the range. The procedure used in `mouseMoveEvent'
1899 // applies here, too.
1900
1901 if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
1902 emit mouseSignal( 3, // release
1903 charColumn + 1,
1904 charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0);
1905 }
1907 }
1908
1909
1910 if ( !_mouseMarks &&
1911 ((ev->button() == Qt::RightButton && !(ev->modifiers() & Qt::ShiftModifier))
1912 || ev->button() == Qt::MiddleButton) )
1913 {
1914 emit mouseSignal( 3,
1915 charColumn + 1,
1916 charLine + 1 +_scrollBar->value() -_scrollBar->maximum() ,
1917 0);
1918 }
1919
1920 QWidget::mouseReleaseEvent(ev);
1921}
1922
1923void TerminalView::getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const
1924{
1925
1926 column = (widgetPoint.x() + _fontWidth/2 -contentsRect().left()-_leftMargin) / _fontWidth;
1927 line = (widgetPoint.y()-contentsRect().top()-_topMargin) / _fontHeight;
1928
1929 if ( line < 0 )
1930 line = 0;
1931 if ( column < 0 )
1932 column = 0;
1933
1934 if ( line >= _usedLines )
1935 line = _usedLines-1;
1936
1937 // the column value returned can be equal to _usedColumns, which
1938 // is the position just after the last character displayed in a line.
1939 //
1940 // this is required so that the user can select characters in the right-most
1941 // column (or left-most for right-to-left input)
1942 if ( column > _usedColumns )
1943 column = _usedColumns;
1944}
1945
1947{
1948 if ( !_screenWindow )
1949 return;
1950
1951 _lineProperties = _screenWindow->getLineProperties();
1952}
1953
1955{
1956 if ( ev->button() != Qt::LeftButton) return;
1957 if ( !_screenWindow ) return;
1958
1959 int charLine = 0;
1960 int charColumn = 0;
1961
1962 getCharacterPosition(ev->pos(),charLine,charColumn);
1963
1964 QPoint pos(charColumn,charLine);
1965
1966 // pass on double click as two clicks.
1967 if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
1968 {
1969 // Send just _ONE_ click event, since the first click of the double click
1970 // was already sent by the click handler
1971 emit mouseSignal( 0,
1972 pos.x()+1,
1973 pos.y()+1 +_scrollBar->value() -_scrollBar->maximum(),
1974 0 ); // left button
1975 return;
1976 }
1977
1978 _screenWindow->clearSelection();
1979 QPoint bgnSel = pos;
1980 QPoint endSel = pos;
1981 int i = loc(bgnSel.x(),bgnSel.y());
1982 _iPntSel = bgnSel;
1983 _iPntSel.ry() += _scrollBar->value();
1984
1985 _wordSelectionMode = true;
1986
1987 // find word boundaries...
1988 int selClass = charClass(_image[i].character);
1989 {
1990 // find the start of the word
1991 int x = bgnSel.x();
1992 while ( ((x>0) || (bgnSel.y()>0 && (_lineProperties[bgnSel.y()-1] & LINE_WRAPPED) ))
1993 && charClass(_image[i-1].character) == selClass )
1994 {
1995 i--;
1996 if (x>0)
1997 x--;
1998 else
1999 {
2000 x=_usedColumns-1;
2001 bgnSel.ry()--;
2002 }
2003 }
2004
2005 bgnSel.setX(x);
2006 _screenWindow->setSelectionStart( bgnSel.x() , bgnSel.y() , false );
2007
2008 // find the end of the word
2009 i = loc( endSel.x(), endSel.y() );
2010 x = endSel.x();
2011 while( ((x<_usedColumns-1) || (endSel.y()<_usedLines-1 && (_lineProperties[endSel.y()] & LINE_WRAPPED) ))
2012 && charClass(_image[i+1].character) == selClass )
2013 {
2014 i++;
2015 if (x<_usedColumns-1)
2016 x++;
2017 else
2018 {
2019 x=0;
2020 endSel.ry()++;
2021 }
2022 }
2023
2024 endSel.setX(x);
2025
2026 // In word selection mode don't select @ (64) if at end of word.
2027 if ( ( QChar( _image[i].character ) == '@' ) && ( ( endSel.x() - bgnSel.x() ) > 0 ) )
2028 endSel.setX( x - 1 );
2029
2030
2031 _actSel = 2; // within selection
2032
2033 _screenWindow->setSelectionEnd( endSel.x() , endSel.y() );
2034
2036 }
2037
2039
2040 QTimer::singleShot(QApplication::doubleClickInterval(),this,
2041 SLOT(tripleClickTimeout()));
2042}
2043
2044void TerminalView::wheelEvent( QWheelEvent* ev )
2045{
2046#if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
2047 if (ev->angleDelta().y() == 0)
2048 return;
2049#else
2050 if (ev->orientation() != Qt::Vertical)
2051 return;
2052#endif
2053
2054 if ( _mouseMarks )
2055 _scrollBar->event(ev);
2056 else
2057 {
2058 int charLine;
2059 int charColumn;
2060#if defined (HAVE_QWHEELEVENT_POSITION)
2061 QPoint pos = ev->position().toPoint();
2062#else
2063 QPoint pos = ev->pos();
2064#endif
2065 getCharacterPosition( pos , charLine , charColumn );
2066
2067#if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
2068 int delta = ev->angleDelta().y();
2069#else
2070 int delta = ev->delta();
2071#endif
2072 emit mouseSignal( delta > 0 ? 4 : 5,
2073 charColumn + 1,
2074 charLine + 1 +_scrollBar->value() -_scrollBar->maximum() ,
2075 0);
2076 }
2077}
2078
2080{
2082}
2083
2085{
2086 if ( !_screenWindow ) return;
2087
2088 int charLine;
2089 int charColumn;
2090 getCharacterPosition(ev->pos(),charLine,charColumn);
2091 _iPntSel = QPoint(charColumn,charLine);
2092
2093 _screenWindow->clearSelection();
2094
2095 _lineSelectionMode = true;
2096 _wordSelectionMode = false;
2097
2098 _actSel = 2; // within selection
2099 emit isBusySelecting(true); // Keep it steady...
2100
2101 while (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) )
2102 _iPntSel.ry()--;
2103
2105 // find word boundary start
2106 int i = loc(_iPntSel.x(),_iPntSel.y());
2107 int selClass = charClass(_image[i].character);
2108 int x = _iPntSel.x();
2109
2110 while ( ((x>0) ||
2111 (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) )
2112 )
2113 && charClass(_image[i-1].character) == selClass )
2114 {
2115 i--;
2116 if (x>0)
2117 x--;
2118 else
2119 {
2120 x=_columns-1;
2121 _iPntSel.ry()--;
2122 }
2123 }
2124
2125 _screenWindow->setSelectionStart( x , _iPntSel.y() , false );
2126 _tripleSelBegin = QPoint( x, _iPntSel.y() );
2127 }
2128 else if (_tripleClickMode == SelectWholeLine) {
2129 _screenWindow->setSelectionStart( 0 , _iPntSel.y() , false );
2130 _tripleSelBegin = QPoint( 0, _iPntSel.y() );
2131 }
2132
2133 while (_iPntSel.y()<_lines-1 && (_lineProperties[_iPntSel.y()] & LINE_WRAPPED) )
2134 _iPntSel.ry()++;
2135
2136 _screenWindow->setSelectionEnd( _columns - 1 , _iPntSel.y() );
2137
2139
2140 _iPntSel.ry() += _scrollBar->value();
2141
2142 emit tripleClicked( _screenWindow->selectedText( _preserveLineBreaks ) );
2143}
2144
2145
2147{
2148 if (next)
2149 return false; // This disables changing the active part in konqueror
2150 // when pressing Tab
2151 return QWidget::focusNextPrevChild( next );
2152}
2153
2154
2155int TerminalView::charClass(quint16 ch) const
2156{
2157 QChar qch=QChar(ch);
2158 if ( qch.isSpace() ) return ' ';
2159
2160 if ( qch.isLetterOrNumber() || _wordCharacters.contains(qch, Qt::CaseInsensitive ) )
2161 return 'a';
2162
2163 // Everything else is weird
2164 return 1;
2165}
2166
2167void TerminalView::setWordCharacters(const QString& wc)
2168{
2169 _wordCharacters = wc;
2170}
2171
2173{
2174 _mouseMarks = on;
2175 setCursor( _mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor );
2176}
2178{
2179 return _mouseMarks;
2180}
2181
2183{
2185}
2187{
2188 return _bracketedPasteMode;
2189}
2190
2191
2192/* ------------------------------------------------------------------------- */
2193/* */
2194/* Clipboard */
2195/* */
2196/* ------------------------------------------------------------------------- */
2197
2198#undef KeyPress
2199
2200void TerminalView::emitSelection(bool useXselection,bool appendReturn)
2201{
2202 if ( !_screenWindow )
2203 return;
2204
2205 // Paste Clipboard by simulating keypress events
2206 QString text = QApplication::clipboard()->text(useXselection ? QClipboard::Selection :
2207 QClipboard::Clipboard);
2208 if(appendReturn)
2209 text.append("\r");
2210 if ( ! text.isEmpty() )
2211 {
2212 text.replace("\n", "\r");
2214 bracketText(text);
2215 else if (text.contains ("\t"))
2216 {
2217 qWarning ("converting TAB to SPC in pasted text before processing");
2218 text.replace ("\t", " ");
2219 }
2220 QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text);
2221 emit keyPressedSignal(&e); // expose as a big fat keypress event
2222
2223 _screenWindow->clearSelection();
2224 }
2225}
2226
2227void TerminalView::bracketText(QString& text)
2228{
2229 text.prepend("\033[200~");
2230 text.append("\033[201~");
2231}
2232
2233void TerminalView::setSelection(const QString& t)
2234{
2235 QApplication::clipboard()->setText(t, QClipboard::Selection);
2236}
2237
2238void TerminalView::copyClipboard(bool extra_interrupt)
2239{
2240 if ( !_screenWindow || !hasFocus())
2241 return;
2242
2243 QString text = _screenWindow->selectedText(_preserveLineBreaks);
2244
2245 if (text.isEmpty ())
2246 {
2247 if (! extra_interrupt)
2248 emit interrupt_signal ();
2249 }
2250 else
2251 QApplication::clipboard()->setText(text);
2252}
2253
2255{
2256 if(hasFocus ())
2257 {
2258 emitSelection(false,false);
2259 }
2260}
2261
2263{
2264 if ( !_screenWindow || !hasFocus())
2265 return;
2266
2267 _screenWindow->setSelectionStart(0,-_screenWindow->currentLine(), false);
2268 //_screenWindow->setSelectionEnd(_screenWindow->windowColumns(),
2269 // _screenWindow->windowLines());
2270
2271 _screenWindow->setSelectionEnd(_screenWindow->columnCount(),
2272 _screenWindow->windowLines());
2273}
2274
2275
2277{
2278 emitSelection(true,false);
2279}
2280
2281
2282/* ------------------------------------------------------------------------- */
2283/* */
2284/* Keyboard */
2285/* */
2286/* ------------------------------------------------------------------------- */
2287
2288void TerminalView::keyPressEvent( QKeyEvent* event )
2289{
2290 //qDebug("%s %d keyPressEvent and key is %d", __FILE__, __LINE__, event->key());
2291
2292 bool emitKeyPressSignal = true;
2293
2294 // Keyboard-based navigation
2295 if ( event->modifiers() == Qt::ShiftModifier )
2296 {
2297 bool update = true;
2298
2299 if ( event->key() == Qt::Key_PageUp )
2300 {
2301 //qDebug("%s %d pageup", __FILE__, __LINE__);
2302 _screenWindow->scrollBy( ScreenWindow::ScrollPages , -1 );
2303 }
2304 else if ( event->key() == Qt::Key_PageDown )
2305 {
2306 //qDebug("%s %d pagedown", __FILE__, __LINE__);
2308 }
2309 else if ( event->key() == Qt::Key_Up )
2310 {
2311 //qDebug("%s %d keyup", __FILE__, __LINE__);
2312 _screenWindow->scrollBy( ScreenWindow::ScrollLines , -1 );
2313 }
2314 else if ( event->key() == Qt::Key_Down )
2315 {
2316 //qDebug("%s %d keydown", __FILE__, __LINE__);
2318 }
2319 else {
2320 update = false;
2321 }
2322
2323 if ( update )
2324 {
2325 //qDebug("%s %d updating", __FILE__, __LINE__);
2326 _screenWindow->setTrackOutput( _screenWindow->atEndOfOutput() );
2327
2329 updateImage();
2330
2331 // do not send key press to terminal
2332 emitKeyPressSignal = false;
2333 }
2334 }
2335
2336 _screenWindow->setTrackOutput( true );
2337
2338 _actSel=0; // Key stroke implies a screen update, so TerminalDisplay won't
2339 // know where the current selection is.
2340
2342 {
2344 if (_cursorBlinking)
2346 else
2347 _cursorBlinking = false;
2348 }
2349
2350 if ( emitKeyPressSignal && !_readonly )
2351 emit keyPressedSignal(event);
2352
2353 if (_readonly) {
2354 event->ignore();
2355 }
2356 else {
2357 event->accept();
2358 }
2359}
2360
2361void TerminalView::inputMethodEvent( QInputMethodEvent* event )
2362{
2363 QKeyEvent keyEvent(QEvent::KeyPress,0,Qt::NoModifier,event->commitString());
2364 emit keyPressedSignal(&keyEvent);
2365
2366 _inputMethodData.preeditString = event->preeditString();
2368
2369 event->accept();
2370}
2371QVariant TerminalView::inputMethodQuery( Qt::InputMethodQuery query ) const
2372{
2373 const QPoint cursorPos = _screenWindow ? _screenWindow->cursorPosition() : QPoint(0,0);
2374 switch ( query )
2375 {
2376#if defined (HAVE_QT_IMCURSORRECTANGLE_ENUM_VALUE)
2377 case Qt::ImCursorRectangle:
2378#else
2379 case Qt::ImMicroFocus:
2380#endif
2381 return imageToWidget(QRect(cursorPos.x(),cursorPos.y(),1,1));
2382 break;
2383 case Qt::ImFont:
2384 return font();
2385 break;
2386 case Qt::ImCursorPosition:
2387 // return the cursor position within the current line
2388 return cursorPos.x();
2389 break;
2390 case Qt::ImSurroundingText:
2391 {
2392 // return the text from the current line
2393 QString lineText;
2394 QTextStream stream(&lineText);
2395 PlainTextDecoder decoder;
2396 decoder.begin(&stream);
2397 decoder.decodeLine(&_image[loc(0,cursorPos.y())],_usedColumns,_lineProperties[cursorPos.y()]);
2398 decoder.end();
2399 return lineText;
2400 }
2401 break;
2402 case Qt::ImCurrentSelection:
2403 return QString();
2404 break;
2405 default:
2406 break;
2407 }
2408
2409 return QVariant();
2410}
2411
2413{
2414 _bellMode=mode;
2415}
2416
2418{
2419 _allowBell = true;
2420}
2421
2423{
2424 ColorEntry color = _colorTable[1];
2426 _colorTable[0]= color;
2428 update();
2429}
2430
2432{
2433 // We initialize _image[_imageSize] too. See makeImage()
2434 for (int i = 0; i <= _imageSize; i++)
2435 {
2436 _image[i].character = ' ';
2442 }
2443}
2444
2446{
2447 _scrollBar->resize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent),
2448 contentsRect().height());
2449 switch(_scrollbarLocation)
2450 {
2451 case NoScrollBar :
2453 _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN;
2454 break;
2455 case ScrollBarLeft :
2457 _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width();
2458 _scrollBar->move(contentsRect().topLeft());
2459 break;
2460 case ScrollBarRight:
2462 _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width();
2463 _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width()-1,0));
2464 break;
2465 }
2466
2468 _contentHeight = contentsRect().height() - 2 * DEFAULT_TOP_MARGIN + /* mysterious */ 1;
2469
2470 if (!_isFixedSize)
2471 {
2472 // ensure that display is always at least one column wide
2473 _columns = qMax(1,qFloor(_contentWidth / _fontWidth));
2475
2476 // ensure that display is always at least one line high
2477 _lines = qMax(1, qFloor(_contentHeight / _fontHeight));
2479 }
2480}
2481
2483{
2484 //qDebug("%s %d makeImage", __FILE__, __LINE__);
2485 calcGeometry();
2486
2487 // confirm that array will be of non-zero size, since the painting code
2488 // assumes a non-zero array length
2489 Q_ASSERT( _lines > 0 && _columns > 0 );
2490 Q_ASSERT( _usedLines <= _lines && _usedColumns <= _columns );
2491
2493
2494 // We over-commit one character so that we can be more relaxed in dealing with
2495 // certain boundary conditions: _image[_imageSize] is a valid but unused position
2496 _image = new Character[_imageSize+1];
2497
2498 clearImage();
2499}
2500
2501// calculate the needed size
2502void TerminalView::setSize(int columns, int lines)
2503{
2504 //FIXME - Not quite correct, a small amount of additional space
2505 // will be used for margins, the scrollbar etc.
2506 // we need to allow for this so that '_size' does allow
2507 // enough room for the specified number of columns and lines to fit
2508
2509 QSize newSize = QSize( columns * _fontWidth ,
2510 lines * _fontHeight );
2511
2512 if ( newSize != size() )
2513 {
2514 _size = newSize;
2515 updateGeometry();
2516 }
2517}
2518
2519void TerminalView::setFixedSize(int cols, int lins)
2520{
2521 _isFixedSize = true;
2522
2523 //ensure that display is at least one line by one column in size
2524 _columns = qMax(1,cols);
2525 _lines = qMax(1,lins);
2528
2529 if (_image)
2530 {
2531 delete[] _image;
2532 makeImage();
2533 }
2534 setSize(cols, lins);
2535 QWidget::setFixedSize(_size);
2536}
2537
2539{
2540 return _size;
2541}
2542
2543
2544/* --------------------------------------------------------------------- */
2545/* */
2546/* Drag & Drop */
2547/* */
2548/* --------------------------------------------------------------------- */
2549
2550void TerminalView::dragEnterEvent(QDragEnterEvent* event)
2551{
2552 if (event->mimeData()->hasFormat("text/plain"))
2553 event->acceptProposedAction();
2554}
2555
2556void TerminalView::dropEvent(QDropEvent* event)
2557{
2558 // KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
2559
2560 QString dropText;
2561
2562 if (event->mimeData ()->hasUrls ())
2563 {
2564 foreach (QUrl url, event->mimeData ()->urls ())
2565 {
2566 if(dropText.length () > 0)
2567 dropText += '\n';
2568 dropText += url.toLocalFile ();
2569 }
2570 }
2571
2572 /* if (!urls.isEmpty())
2573 {
2574 for ( int i = 0 ; i < urls.count() ; i++ )
2575 {
2576 KUrl url = KIO::NetAccess::mostLocalUrl( urls[i] , 0 );
2577 QString urlText;
2578
2579 if (url.isLocalFile())
2580 urlText = url.path();
2581 else
2582 urlText = url.url();
2583
2584 // in future it may be useful to be able to insert file names with drag-and-drop
2585 // without quoting them (this only affects paths with spaces in)
2586 urlText = KShell::quoteArg(urlText);
2587
2588 dropText += urlText;
2589
2590 if ( i != urls.count()-1 )
2591 dropText += ' ';
2592 }
2593 }
2594 else
2595 {
2596 dropText = event->mimeData()->text();
2597 }
2598*/
2599 if(event->mimeData()->hasFormat("text/plain"))
2600 {
2601 emit sendStringToEmu(dropText.toLocal8Bit());
2602 }
2603}
2604
2606{
2608 dragInfo.dragObject = new QDrag(this);
2609 QMimeData *mimeData = new QMimeData;
2610 mimeData->setText(QApplication::clipboard()->text(QClipboard::Selection));
2611 dragInfo.dragObject->setMimeData(mimeData);
2612 dragInfo.dragObject->exec(Qt::CopyAction);
2613 // Don't delete the QTextDrag object. Qt will delete it when it's done with it.
2614}
2615
2617{
2618 //create the label when this function is first called
2620 {
2621 //This label includes a link to an English language website
2622 //describing the 'flow control' (Xon/Xoff) feature found in almost
2623 //all terminal emulators.
2624 //If there isn't a suitable article available in the target language the link
2625 //can simply be removed.
2626 _outputSuspendedLabel = new QLabel( ("<qt>Output has been "
2627 "<a href=\"http://en.wikipedia.org/wiki/XON\">suspended</a>"
2628 " by pressing Ctrl+S."
2629 " Press <b>Ctrl+Q</b> to resume.</qt>"),
2630 this );
2631
2632 QPalette palette(_outputSuspendedLabel->palette());
2633
2634 palette.setColor(QPalette::Normal, QPalette::WindowText, QColor(Qt::white));
2635 palette.setColor(QPalette::Normal, QPalette::Window, QColor(Qt::black));
2636 // KColorScheme::adjustForeground(palette,KColorScheme::NeutralText);
2637 // KColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground);
2638 _outputSuspendedLabel->setPalette(palette);
2639 _outputSuspendedLabel->setAutoFillBackground(true);
2640 _outputSuspendedLabel->setBackgroundRole(QPalette::Base);
2641 _outputSuspendedLabel->setFont(QApplication::font());
2642 _outputSuspendedLabel->setMargin(5);
2643
2644 //enable activation of "Xon/Xoff" link in label
2645 _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse |
2646 Qt::LinksAccessibleByKeyboard);
2647 _outputSuspendedLabel->setOpenExternalLinks(true);
2648 _outputSuspendedLabel->setVisible(false);
2649
2651 _gridLayout->addItem( new QSpacerItem(0,0,QSizePolicy::Expanding,
2652 QSizePolicy::Expanding),
2653 1,0);
2654
2655 }
2656
2657 _outputSuspendedLabel->setVisible(suspended);
2658}
2659
2661{
2662 return _lineSpacing;
2663}
2664
2666{
2667 _lineSpacing = i;
2668 setVTFont(font()); // Trigger an update.
2669}
2670
2672{
2673 QString text = _screenWindow->selectedText (_preserveLineBreaks);
2674 return text;
2675}
2676
2677void
2679{
2680 // Disable the timer for processing the filter chain, since this might time
2681 // consuming
2682 if (visible)
2683 _process_filter_timer->start (300);
2684 else
2685 _process_filter_timer->stop ();
2686}
#define COLOR_SPACE_DEFAULT
#define TABLE_COLORS
#define DEFAULT_FORE_COLOR
#define DEFAULT_BACK_COLOR
static const ColorEntry base_color_table[(2 *(2+8))]
static const int LINE_DOUBLEHEIGHT
Definition: Character.h:39
#define RE_UNDERLINE
Definition: Character.h:44
#define RE_EXTENDED_CHAR
Definition: Character.h:48
#define RE_CURSOR
Definition: Character.h:47
static const int LINE_WRAPPED
Definition: Character.h:37
#define DEFAULT_RENDITION
Definition: Character.h:41
static const int LINE_DOUBLEWIDTH
Definition: Character.h:38
#define RE_BOLD
Definition: Character.h:42
#define RE_BLINK
Definition: Character.h:43
#define yMouseScroll
#define REPCHAR
LineEncode
A table for emulating the simple (single width) unicode drawing chars.
@ BotR
@ Int21
@ LeftB
@ Int31
@ Int12
@ Int33
@ RightT
@ Int22
@ TopR
@ TopL
@ TopC
@ Int32
@ Int13
@ Int11
@ Int23
@ BotL
@ LeftC
@ LeftT
@ BotC
@ RightB
@ RightC
unsigned short vt100_graphics[32]
#define loc(X, Y)
Describes the color of a single character in the terminal.
QColor color(const ColorEntry *palette) const
Returns the color within the specified color @palette.
A single character in the terminal which consists of a unicode character value, foreground and backgr...
Definition: Character.h:56
CharacterColor backgroundColor
The color used to draw this character's background.
Definition: Character.h:92
CharacterColor foregroundColor
The foreground color used to draw this character.
Definition: Character.h:90
quint16 character
The unicode character value for this character.
Definition: Character.h:75
quint8 rendition
A combination of RENDITION flags which specify options for drawing the character.
Definition: Character.h:87
bool isBold(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:142
An entry in a terminal display's color palette.
QColor color
The color value of this entry for display.
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: Emulation.cpp:406
static ExtendedCharTable instance
The global ExtendedCharTable instance.
Definition: Character.h:191
A chain which allows a group of filters to be processed as one.
Definition: Filter.h:362
void process()
Processes each filter in the chain.
Definition: Filter.cpp:75
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:85
QList< Filter::HotSpot * > hotSpots() const
Returns a list of all the hotspots in all the chain's filters.
Definition: Filter.cpp:101
virtual QString tooltip() const
Returns the text of a tooltip to be shown when the mouse moves over the hotspot, or an empty string i...
Definition: Filter.cpp:294
int endLine() const
Returns the line where the hotspot area ends.
Definition: Filter.cpp:306
int startLine() const
Returns the line when the hotspot area starts.
Definition: Filter.cpp:302
int endColumn() const
Returns the column on endLine() where the hotspot area ends.
Definition: Filter.cpp:314
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:298
Type type() const
Returns the type of the hotspot.
Definition: Filter.cpp:318
int startColumn() const
Returns the column on startLine() where the hotspot area starts.
Definition: Filter.cpp:310
@ Link
Definition: Filter.h:79
@ Marker
Definition: Filter.h:81
@ ErrorLink
Definition: Filter.h:83
A terminal character decoder which produces plain text, ignoring colours and other appearance-related...
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...
virtual void begin(QTextStream *output)
Begin decoding characters.
virtual void end()
End decoding.
Provides a window onto a section of a terminal screen.
Definition: ScreenWindow.h:52
void setWindowLines(int lines)
Sets the number of lines in the window.
A filter chain which processes character images from terminal displays.
Definition: Filter.h:396
void setImage(const Character *const image, int lines, int columns, const QVector< LineProperty > &lineProperties)
Set the current terminal image to image.
Definition: Filter.cpp:125
void selectAll()
selects all content
virtual void showEvent(QShowEvent *)
double _fontWidth
Definition: TerminalView.h:635
QPoint _tripleSelBegin
Definition: TerminalView.h:674
FilterChain * filterChain() const
Returns the display's filter chain.
QGridLayout * _gridLayout
Definition: TerminalView.h:630
uint randomSeed() const
Returns the seed used to generate random colors for the display (in color schemes that support them).
QRect preeditRect() const
virtual void inputMethodEvent(QInputMethodEvent *event)
bool _columnSelectionMode
Definition: TerminalView.h:679
void setWordCharacters(const QString &wc)
Sets which characters, in addition to letters and numbers, are regarded as being part of a word for t...
void processFilters()
Updates the filters in the display's filter chain.
static const int BLINK_DELAY
Definition: TerminalView.h:745
bool _colorsInverted
Definition: TerminalView.h:717
void updateLineProperties()
Causes the terminal display to fetch the latest line status flags from the associated terminal screen...
virtual void extendSelection(const QPoint &pos)
void pasteClipboard()
Pastes the content of the clipboard into the display.
static const int DEFAULT_TOP_MARGIN
Definition: TerminalView.h:747
void sendStringToEmu(const char *)
virtual void resizeEvent(QResizeEvent *)
bool _wordSelectionMode
Definition: TerminalView.h:676
QVector< LineProperty > _lineProperties
Definition: TerminalView.h:660
void drawInputMethodPreeditString(QPainter &painter, const QRect &rect)
void drawBackground(QPainter &painter, const QRect &rect, const QColor &color)
virtual void setFont(const QFont &)
Reimplemented.
void drawCursor(QPainter &painter, const QRect &rect, const QColor &foregroundColor, const QColor &backgroundColor, bool &invertColors)
void drawTextFragment(QPainter &painter, const QRect &rect, const QString &text, const Character *style)
void getCharacterPosition(const QPoint &widgetPoint, int &line, int &column) const
virtual void hideEvent(QHideEvent *)
QTimer * _blinkCursorTimer
Definition: TerminalView.h:695
void setBellMode(int mode)
Sets the type of effect used to alert the user when a 'bell' occurs in the terminal session.
bool _bracketedPasteMode
Definition: TerminalView.h:669
void setUsesMouse(bool usesMouse)
Sets whether the program whoose output is being displayed in the view is interested in mouse events.
void changedFontMetricSignal(int height, int width)
virtual void mouseReleaseEvent(QMouseEvent *)
void scrollBarPositionChanged(int value)
static const int DEFAULT_LEFT_MARGIN
Definition: TerminalView.h:746
void setScroll(int cursor, int lines)
Sets the current position and range of the display's scroll bar.
void configureRequest(TerminalView *, int state, const QPoint &position)
Emitted when the user right clicks on the display, or right-clicks with the Shift key held down if us...
void setRandomSeed(uint seed)
Sets the seed used to generate random colors for the display (in color schemes that support them).
void isBusySelecting(bool)
void copyClipboard(bool extra_interrupt)
Copies the selected text to the clipboard.
void interrupt_signal(void)
QPoint cursorPosition() const
@ SelectForwardsFromCursor
Select from the current cursor position to the end of the line.
Definition: TerminalView.h:151
@ SelectWholeLine
Select the whole line underneath the cursor.
Definition: TerminalView.h:149
void setColorTable(const ColorEntry table[])
Sets the terminal color palette used by the display.
void setScrollBarPosition(ScrollBarPosition position)
Specifies whether the terminal display has a vertical scroll bar, and if so whether it is shown on th...
ScreenWindow * screenWindow() const
Returns the terminal screen section which is displayed in this widget.
void setKeyboardCursorShape(KeyboardCursorShape shape)
Sets the shape of the keyboard cursor.
bool _lineSelectionMode
Definition: TerminalView.h:677
Character * _image
Definition: TerminalView.h:656
void focusInEvent(QFocusEvent *focusEvent)
QScrollBar * _scrollBar
Definition: TerminalView.h:682
QPointer< ScreenWindow > _screenWindow
Definition: TerminalView.h:626
TerminalImageFilterChain * _filterChain
Definition: TerminalView.h:725
virtual bool focusNextPrevChild(bool next)
void setScreenWindow(ScreenWindow *window)
Sets the terminal screen section which is displayed in this widget.
virtual int charClass(quint16) const
void setKeyboardCursorColor(bool useForegroundColor, const QColor &color)
Sets the color used to draw the keyboard cursor.
ColorEntry _colorTable[TABLE_COLORS]
Definition: TerminalView.h:662
bool _hasBlinkingCursor
Definition: TerminalView.h:690
TripleClickMode _tripleClickMode
Definition: TerminalView.h:692
bool _terminalSizeStartup
Definition: TerminalView.h:667
bool _preserveLineBreaks
Definition: TerminalView.h:678
void bracketText(QString &text)
change and wrap text corresponding to paste mode
void setVTFont(const QFont &font)
Sets the font used to draw the display.
QString selectedText()
QRect _mouseOverHotspotArea
Definition: TerminalView.h:726
QSize sizeHint() const
void updateImage()
Causes the terminal display to fetch the latest character image from the associated terminal screen (...
int columns()
Returns the number of characters of text which can be displayed on each line in the widget.
Definition: TerminalView.h:237
virtual ~TerminalView()
void propagateSize()
void blinkCursorEvent()
virtual void mouseMoveEvent(QMouseEvent *)
InputMethodData _inputMethodData
Definition: TerminalView.h:740
void focusOutEvent(QFocusEvent *focusEvent)
void mouseSignal(int button, int column, int line, int eventType)
A mouse event occurred.
bool _cursorBlinking
Definition: TerminalView.h:689
void setSelection(const QString &t)
void setBlinkingCursor(bool blink)
Specifies whether or not the cursor blinks.
void drawCharacters(QPainter &painter, const QRect &rect, const QString &text, const Character *style, bool invertCharacterColor)
bool usesMouse() const
See setUsesMouse()
virtual void mousePressEvent(QMouseEvent *)
KeyboardCursorShape _cursorShape
Definition: TerminalView.h:728
QTimer * _blinkTimer
Definition: TerminalView.h:694
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const
virtual void mouseDoubleClickEvent(QMouseEvent *ev)
QClipboard * _clipboard
Definition: TerminalView.h:681
void paintFilters(QPainter &painter)
QList< QAction * > filterActions(const QPoint &position)
Returns a list of menu actions created by the filters for the content at the given position.
virtual void keyPressEvent(QKeyEvent *event)
ScrollBarPosition
This enum describes the location where the scroll bar is positioned in the display widget.
Definition: TerminalView.h:92
@ ScrollBarLeft
Show the scroll bar on the left side of the display.
Definition: TerminalView.h:96
@ NoScrollBar
Do not show the scroll bar.
Definition: TerminalView.h:94
@ ScrollBarRight
Show the scroll bar on the right side of the display.
Definition: TerminalView.h:98
QPoint _pntSel
Definition: TerminalView.h:673
virtual void dropEvent(QDropEvent *event)
QRect imageToWidget(const QRect &imageArea) const
void updateImageSize()
virtual void dragEnterEvent(QDragEnterEvent *event)
void setFixedSize(int cols, int lins)
void setBlinkingCursorState(bool blink)
int lines()
Returns the number of lines of text which can be displayed in the widget.
Definition: TerminalView.h:229
virtual void fontChange(const QFont &font)
void tripleClickTimeout()
virtual void wheelEvent(QWheelEvent *)
QLabel * _outputSuspendedLabel
Definition: TerminalView.h:713
struct TerminalView::_dragInfo dragInfo
bool _terminalSizeHint
Definition: TerminalView.h:666
KeyboardCursorShape
This enum describes the available shapes for the keyboard cursor.
Definition: TerminalView.h:171
@ UnderlineCursor
A single flat line which occupies the space at the bottom of the cursor character's area.
Definition: TerminalView.h:178
@ IBeamCursor
An cursor shaped like the capital letter 'I', similar to the IBeam cursor used in Qt/KDE text editors...
Definition: TerminalView.h:183
@ BlockCursor
A rectangular block which covers the entire area of the cursor character.
Definition: TerminalView.h:173
QColor keyboardCursorColor() const
Returns the color of the keyboard cursor, or an invalid color if the keyboard cursor color is set to ...
KeyboardCursorShape keyboardCursorShape() const
Returns the shape of the keyboard cursor.
void setLineSpacing(uint)
QPoint _iPntSel
Definition: TerminalView.h:672
void outputSuspended(bool suspended)
Causes the widget to display or hide a message informing the user that terminal output has been suspe...
void swapColorTable()
double _fontHeight
Definition: TerminalView.h:634
bool _disabledBracketedPasteMode
Definition: TerminalView.h:670
const ColorEntry * colorTable() const
Returns the terminal color palette used by the display.
virtual void paintEvent(QPaintEvent *)
bool bracketedPasteMode() const
void pasteSelection()
Pastes the content of the selection into the display.
void visibility_changed(bool visible)
Is called, when the terminal's visibility has changed in order to stop orstart timers etc.
void tripleClicked(const QString &text)
uint lineSpacing() const
QTimer * _resizeTimer
Definition: TerminalView.h:707
void setSize(int cols, int lins)
void showResizeNotification()
QRegion hotSpotRegion() const
QString _wordCharacters
Definition: TerminalView.h:684
ScrollBarPosition _scrollbarLocation
Definition: TerminalView.h:683
TerminalView(QWidget *parent=nullptr)
Constructs a new terminal display widget with the specified parent.
void keyPressedSignal(QKeyEvent *e)
Emitted when the user presses a key whilst the terminal widget has focus.
void setBracketedPasteMode(bool bracketedPasteMode)
QLabel * _resizeWidget
Definition: TerminalView.h:706
void changedContentSizeSignal(int height, int width)
void mouseTripleClickEvent(QMouseEvent *ev)
static bool _antialiasText
Definition: TerminalView.h:742
void emitSelection(bool useXselection, bool appendReturn)
void drawContents(QPainter &paint, const QRect &rect)
bool _possibleTripleClick
Definition: TerminalView.h:702
QTimer * _process_filter_timer
Definition: TerminalView.h:696
void scrollImage(int lines, const QRect &region)
QColor _cursorColor
Definition: TerminalView.h:732
int string_width(const QString &txt)
F77_RET_T const F77_DBLE * x
F77_RET_T const F77_DBLE const F77_DBLE * f
static uint32_t * next
Definition: randmtzig.cc:191
static int left
Definition: randmtzig.cc:193
int qt_fontmetrics_horizontal_advance(const QFontMetrics &fm, QChar ch)
Definition: qt-utils.h:48
T::size_type strlen(const typename T::value_type *str)
Definition: oct-string.cc:85
static T abs(T x)
Definition: pr-output.cc:1678
F77_RET_T len
Definition: xerbla.cc:61