diff --git a/3rdparty/terminalwidget/lib/Emulation.h b/3rdparty/terminalwidget/lib/Emulation.h index e79587382..9eb1077f7 100644 --- a/3rdparty/terminalwidget/lib/Emulation.h +++ b/3rdparty/terminalwidget/lib/Emulation.h @@ -295,6 +295,16 @@ public slots: */ virtual void sendString(const char *string, int length = -1) = 0; + /** + * Send Cursor Change + * + * @param count count < 0 + * cursor left count times + * count > 0 + * cursor right count times + */ + virtual void sendCursor(int count) = 0; + /** * Processes an incoming stream of characters. receiveData() decodes the incoming * character buffer using the current codec(), and then calls receiveChar() for diff --git a/3rdparty/terminalwidget/lib/Session.cpp b/3rdparty/terminalwidget/lib/Session.cpp index adf74364d..f33df5c06 100644 --- a/3rdparty/terminalwidget/lib/Session.cpp +++ b/3rdparty/terminalwidget/lib/Session.cpp @@ -209,6 +209,8 @@ void Session::addView(TerminalDisplay * widget) SLOT(sendKeyEvent(QKeyEvent *)) ); connect( widget , SIGNAL(mouseSignal(int,int,int,int)) , _emulation , SLOT(sendMouseEvent(int,int,int,int)) ); + connect(widget, SIGNAL(changedCursonPosition(int)), _emulation, + SLOT(sendCursor(int))); // 先判断是否有远程连接,若有,则连接远程 // connect(widget, SIGNAL(sendStringToEmu(const char *)), _emulation, SLOT(sendString(const char *))); diff --git a/3rdparty/terminalwidget/lib/TerminalDisplay.cpp b/3rdparty/terminalwidget/lib/TerminalDisplay.cpp index 91cb877e0..b68cb7c2e 100644 --- a/3rdparty/terminalwidget/lib/TerminalDisplay.cpp +++ b/3rdparty/terminalwidget/lib/TerminalDisplay.cpp @@ -77,27 +77,27 @@ typedef quint16 RenditionFlags; #define yMouseScroll 1 #define REPCHAR "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ - "abcdefgjijklmnopqrstuvwxyz" \ - "0123456789./+@" + "abcdefgjijklmnopqrstuvwxyz" \ + "0123456789./+@" const ColorEntry Konsole::base_color_table[TABLE_COLORS] = // The following are almost IBM standard color codes, with some slight // gamma correction for the dim colors to compensate for bright X screens. // It contains the 8 ansiterm/xterm colors in 2 intensities. { - // Fixme: could add faint colors here, also. - // normal - ColorEntry(QColor(0x00,0x00,0x00), false), ColorEntry( QColor(0xB2,0xB2,0xB2), true), // Dfore, Dback - ColorEntry(QColor(0x00,0x00,0x00), false), ColorEntry( QColor(0xB2,0x18,0x18), false), // Black, Red - ColorEntry(QColor(0x18,0xB2,0x18), false), ColorEntry( QColor(0xB2,0x68,0x18), false), // Green, Yellow - ColorEntry(QColor(0x18,0x18,0xB2), false), ColorEntry( QColor(0xB2,0x18,0xB2), false), // Blue, Magenta - ColorEntry(QColor(0x18,0xB2,0xB2), false), ColorEntry( QColor(0xB2,0xB2,0xB2), false), // Cyan, White - // intensiv - ColorEntry(QColor(0x00,0x00,0x00), false), ColorEntry( QColor(0xFF,0xFF,0xFF), true), - ColorEntry(QColor(0x68,0x68,0x68), false), ColorEntry( QColor(0xFF,0x54,0x54), false), - ColorEntry(QColor(0x54,0xFF,0x54), false), ColorEntry( QColor(0xFF,0xFF,0x54), false), - ColorEntry(QColor(0x54,0x54,0xFF), false), ColorEntry( QColor(0xFF,0x54,0xFF), false), - ColorEntry(QColor(0x54,0xFF,0xFF), false), ColorEntry( QColor(0xFF,0xFF,0xFF), false) + // Fixme: could add faint colors here, also. + // normal + ColorEntry(QColor(0x00, 0x00, 0x00), false), ColorEntry(QColor(0xB2, 0xB2, 0xB2), true), // Dfore, Dback + ColorEntry(QColor(0x00, 0x00, 0x00), false), ColorEntry(QColor(0xB2, 0x18, 0x18), false), // Black, Red + ColorEntry(QColor(0x18, 0xB2, 0x18), false), ColorEntry(QColor(0xB2, 0x68, 0x18), false), // Green, Yellow + ColorEntry(QColor(0x18, 0x18, 0xB2), false), ColorEntry(QColor(0xB2, 0x18, 0xB2), false), // Blue, Magenta + ColorEntry(QColor(0x18, 0xB2, 0xB2), false), ColorEntry(QColor(0xB2, 0xB2, 0xB2), false), // Cyan, White + // intensiv + ColorEntry(QColor(0x00, 0x00, 0x00), false), ColorEntry(QColor(0xFF, 0xFF, 0xFF), true), + ColorEntry(QColor(0x68, 0x68, 0x68), false), ColorEntry(QColor(0xFF, 0x54, 0x54), false), + ColorEntry(QColor(0x54, 0xFF, 0x54), false), ColorEntry(QColor(0xFF, 0xFF, 0x54), false), + ColorEntry(QColor(0x54, 0x54, 0xFF), false), ColorEntry(QColor(0xFF, 0x54, 0xFF), false), + ColorEntry(QColor(0x54, 0xFF, 0xFF), false), ColorEntry(QColor(0xFF, 0xFF, 0xFF), false) }; // scroll increment used when dragging selection at top/bottom of window. @@ -113,7 +113,7 @@ int Konsole::__maxFontSize = 0x7fffffff; // we use this to force QPainter to display text in LTR mode // more information can be found in: http://unicode.org/reports/tr9/ -const QChar LTR_OVERRIDE_CHAR( 0x202D ); +const QChar LTR_OVERRIDE_CHAR(0x202D); /* ------------------------------------------------------------------------- */ /* */ @@ -129,53 +129,51 @@ const QChar LTR_OVERRIDE_CHAR( 0x202D ); IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White */ -ScreenWindow* TerminalDisplay::screenWindow() const +ScreenWindow *TerminalDisplay::screenWindow() const { return _screenWindow; } -void TerminalDisplay::setScreenWindow(ScreenWindow* window) +void TerminalDisplay::setScreenWindow(ScreenWindow *window) { // disconnect existing screen window if any - if ( _screenWindow ) - { - disconnect( _screenWindow , nullptr , this , nullptr ); + if (_screenWindow) { + disconnect(_screenWindow, nullptr, this, nullptr); } _screenWindow = window; - if ( window ) - { + if (window) { // TODO: Determine if this is an issue. //#warning "The order here is not specified - does it matter whether updateImage or updateLineProperties comes first?" - connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties()) ); - connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage()) ); - connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateFilters()) ); - connect( _screenWindow , SIGNAL(scrolled(int)) , this , SLOT(updateFilters()) ); - connect( _screenWindow, SIGNAL(selectionCleared()), this, SLOT(selectionCleared()) ); + connect(_screenWindow, SIGNAL(outputChanged()), this, SLOT(updateLineProperties())); + connect(_screenWindow, SIGNAL(outputChanged()), this, SLOT(updateImage())); + connect(_screenWindow, SIGNAL(outputChanged()), this, SLOT(updateFilters())); + connect(_screenWindow, SIGNAL(scrolled(int)), this, SLOT(updateFilters())); + connect(_screenWindow, SIGNAL(selectionCleared()), this, SLOT(selectionCleared())); window->setWindowLines(_lines); window->screen()->setSessionId(_sessionId); window->screen()->setReflowLines(true); } } -const ColorEntry* TerminalDisplay::colorTable() const +const ColorEntry *TerminalDisplay::colorTable() const { - return _colorTable; + return _colorTable; } -void TerminalDisplay::setBackgroundColor(const QColor& color) +void TerminalDisplay::setBackgroundColor(const QColor &color) { _colorTable[DEFAULT_BACK_COLOR].color = color; QPalette p = palette(); - p.setColor( backgroundRole(), color ); - setPalette( p ); + p.setColor(backgroundRole(), color); + setPalette(p); - // Avoid propagating the palette change to the scroll bar - _scrollBar->setPalette( QApplication::palette() ); + // Avoid propagating the palette change to the scroll bar + _scrollBar->setPalette(QApplication::palette()); update(); } -void TerminalDisplay::setForegroundColor(const QColor& color) +void TerminalDisplay::setForegroundColor(const QColor &color) { _colorTable[DEFAULT_FORE_COLOR].color = color; @@ -183,10 +181,10 @@ void TerminalDisplay::setForegroundColor(const QColor& color) } void TerminalDisplay::setColorTable(const ColorEntry table[]) { - for (int i = 0; i < TABLE_COLORS; i++) - _colorTable[i] = table[i]; + for (int i = 0; i < TABLE_COLORS; i++) + _colorTable[i] = table[i]; - setBackgroundColor(_colorTable[DEFAULT_BACK_COLOR].color); + setBackgroundColor(_colorTable[DEFAULT_BACK_COLOR].color); } /* ------------------------------------------------------------------------- */ @@ -207,11 +205,13 @@ void TerminalDisplay::setColorTable(const ColorEntry table[]) QCodec. */ -bool TerminalDisplay::canDraw(uint ucs4cp) const { +bool TerminalDisplay::canDraw(uint ucs4cp) const +{ return (0x2500 <= ucs4cp && ucs4cp <= 0x259F); } -bool TerminalDisplay::isLineCharString(const QString& string) const { +bool TerminalDisplay::isLineCharString(const QString &string) const +{ if (string.length() == 0) { return false; } @@ -219,6 +219,11 @@ bool TerminalDisplay::isLineCharString(const QString& string) const { return canDraw(string.at(0).unicode()); } +void TerminalDisplay::setCursorPositionEnable(bool enable) +{ + _cursorPositionSetEnable = enable; +} + /******************************************************************************* 1. @函数: setIsAllowScroll 2. @作者: ut000610 戴正文 @@ -246,15 +251,15 @@ bool TerminalDisplay::getIsAllowScroll() const // assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i. -unsigned short Konsole::vt100_graphics[32] = -{ // 0/8 1/9 2/10 3/11 4/12 5/13 6/14 7/15 - 0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, - 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, - 0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534, - 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7 +unsigned short Konsole::vt100_graphics[32] = { + // 0/8 1/9 2/10 3/11 4/12 5/13 6/14 7/15 + 0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, + 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, + 0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534, + 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7 }; -void TerminalDisplay::fontChange(const QFont&) +void TerminalDisplay::fontChange(const QFont &) { QFontMetrics fm(font()); _fontHeight = fm.height() + _lineSpacing; @@ -285,11 +290,11 @@ void TerminalDisplay::fontChange(const QFont&) } if (_fontWidth < 1) - _fontWidth=1; + _fontWidth = 1; _fontAscent = fm.ascent(); - emit changedFontMetricSignal( _fontHeight, _fontWidth ); + emit changedFontMetricSignal(_fontHeight, _fontWidth); propagateSize(); // We will run paint event testing procedure. @@ -302,7 +307,7 @@ void TerminalDisplay::fontChange(const QFont&) update(); } -void TerminalDisplay::calDrawTextAdditionHeight(QPainter& painter) +void TerminalDisplay::calDrawTextAdditionHeight(QPainter &painter) { QRect test_rect, feedback_rect; test_rect.setRect(1, 1, _fontWidth * 4, _fontHeight); @@ -311,8 +316,8 @@ void TerminalDisplay::calDrawTextAdditionHeight(QPainter& painter) //qDebug() << "test_rect:" << test_rect << "feeback_rect:" << feedback_rect; _drawTextAdditionHeight = (feedback_rect.height() - _fontHeight) / 2; - if(_drawTextAdditionHeight < 0) { - _drawTextAdditionHeight = 0; + if (_drawTextAdditionHeight < 0) { + _drawTextAdditionHeight = 0; } // update the original content @@ -320,11 +325,11 @@ void TerminalDisplay::calDrawTextAdditionHeight(QPainter& painter) update(); } -void TerminalDisplay::setVTFont(const QFont& f) +void TerminalDisplay::setVTFont(const QFont &f) { /***add begin by ut001121 zhangmeng 20200908 限制字体大小 修复BUG42250***/ /***add begin by ut001121 zhangmeng 20200908 限制字体大小 修复BUG42412***/ - if(f.pointSize() < __minFontSize || f.pointSize() > __maxFontSize){ + if (f.pointSize() < __minFontSize || f.pointSize() > __maxFontSize) { return; } /***add end by ut001121***/ @@ -353,14 +358,14 @@ void TerminalDisplay::setVTFont(const QFont& f) // will cause Konsole to crash later. QFontMetrics fontMetrics2(newFont); if (fontMetrics2.height() < 1) { - qDebug()<<"The font "<(fontInfo.styleHint()), - fontInfo.weight(), - static_cast(fontInfo.style()), - static_cast(fontInfo.underline()), - static_cast(fontInfo.strikeOut()), - // Intentional newFont use - fixedPitch is bugged, see comment above - static_cast(newFont.fixedPitch()), - static_cast(fontInfo.rawMode())); + qPrintable(fontInfo.family()), + fontInfo.pointSizeF(), + -1, // pixelSize is not used + static_cast(fontInfo.styleHint()), + fontInfo.weight(), + static_cast(fontInfo.style()), + static_cast(fontInfo.underline()), + static_cast(fontInfo.strikeOut()), + // Intentional newFont use - fixedPitch is bugged, see comment above + static_cast(newFont.fixedPitch()), + static_cast(fontInfo.rawMode())); qDebug() << "The font to use in the terminal can not be matched exactly on your system."; qDebug() << " Selected: " << newFont.toString(); qDebug() << " System : " << nonMatching; @@ -413,7 +418,7 @@ void TerminalDisplay::setVTFont(const QFont& f) void TerminalDisplay::setFont(const QFont &) { - // ignore font change request if not coming from konsole itself + // ignore font change request if not coming from konsole itself } /* ------------------------------------------------------------------------- */ @@ -423,149 +428,150 @@ void TerminalDisplay::setFont(const QFont &) /* ------------------------------------------------------------------------- */ TerminalDisplay::TerminalDisplay(QWidget *parent) -:QWidget(parent) -,_screenWindow(nullptr) -,_allowBell(true) -,_gridLayout(nullptr) -,_fontHeight(1) -,_fontWidth(1) -,_fontAscent(1) -,_boldIntense(true) -,_lines(1) -,_columns(1) -,_usedLines(1) -,_usedColumns(1) -,_contentRect(QRect()) -,_contentHeight(1) -,_contentWidth(1) -,_image(nullptr) -,_randomSeed(0) -,_resizing(false) -,_terminalSizeHint(false) -,_terminalSizeStartup(true) -,_bidiEnabled(true) //默认开启双向文本(Bi-directional text)mode,和konsole保持同步 -,_mouseMarks(false) -, _alternateScrolling(true) -,_actSel(0) -,_wordSelectionMode(false) -,_lineSelectionMode(false) -,_preserveLineBreaks(false) -,_columnSelectionMode(false) -,_scrollbarLocation(QTermWidget::NoScrollBar) -,_wordCharacters(QLatin1String(":@-./_~")) -,_bellMode(SystemBeepBell) -,_blinking(false) -,_hasBlinker(false) -,_cursorBlinking(false) -,_hasBlinkingCursor(false) -,_allowBlinkingText(true) -,_ctrlDrag(false) -,_tripleClickMode(SelectWholeLine) -,_isFixedSize(false) -,_possibleTripleClick(false) -,_resizeWidget(nullptr) -,_resizeTimer(nullptr) -,_flowControlWarningEnabled(false) -,_hideCursor(false) -,_outputSuspendedLabel(nullptr) -,_lineSpacing(0) -,_colorsInverted(false) -,_blendColor(qRgba(0,0,0,0xff)) -,_filterChain(new TerminalImageFilterChain()) -,_cursorShape(Emulation::KeyboardCursorShape::BlockCursor) -,mMotionAfterPasting(NoMoveScreenWindow) -,_leftBaseMargin(1) -,_topBaseMargin(1) -,_drawLineChars(true) + : QWidget(parent) + , _screenWindow(nullptr) + , _allowBell(true) + , _gridLayout(nullptr) + , _fontHeight(1) + , _fontWidth(1) + , _fontAscent(1) + , _boldIntense(true) + , _lines(1) + , _columns(1) + , _usedLines(1) + , _usedColumns(1) + , _contentRect(QRect()) + , _contentHeight(1) + , _contentWidth(1) + , _image(nullptr) + , _randomSeed(0) + , _resizing(false) + , _terminalSizeHint(false) + , _terminalSizeStartup(true) + , _bidiEnabled(true) //默认开启双向文本(Bi-directional text)mode,和konsole保持同步 + , _mouseMarks(false) + , _alternateScrolling(true) + , _actSel(0) + , _wordSelectionMode(false) + , _lineSelectionMode(false) + , _preserveLineBreaks(false) + , _columnSelectionMode(false) + , _scrollbarLocation(QTermWidget::NoScrollBar) + , _wordCharacters(QLatin1String(":@-./_~")) + , _bellMode(SystemBeepBell) + , _blinking(false) + , _hasBlinker(false) + , _cursorBlinking(false) + , _hasBlinkingCursor(false) + , _cursorPositionSetEnable(false) + , _allowBlinkingText(true) + , _ctrlDrag(false) + , _tripleClickMode(SelectWholeLine) + , _isFixedSize(false) + , _possibleTripleClick(false) + , _resizeWidget(nullptr) + , _resizeTimer(nullptr) + , _flowControlWarningEnabled(false) + , _hideCursor(false) + , _outputSuspendedLabel(nullptr) + , _lineSpacing(0) + , _colorsInverted(false) + , _blendColor(qRgba(0, 0, 0, 0xff)) + , _filterChain(new TerminalImageFilterChain()) + , _cursorShape(Emulation::KeyboardCursorShape::BlockCursor) + , mMotionAfterPasting(NoMoveScreenWindow) + , _leftBaseMargin(1) + , _topBaseMargin(1) + , _drawLineChars(true) //,_headerBar(new TerminalHeaderBar(this)) { - // variables for draw text - _drawTextAdditionHeight = 0; - _drawTextTestFlag = false; - - // terminal applications are not designed with Right-To-Left in mind, - // so the layout is forced to Left-To-Right - setLayoutDirection(Qt::LeftToRight); - - // The offsets are not yet calculated. - // Do not calculate these too often to be more smoothly when resizing - // konsole in opaque mode. - _topMargin = _topBaseMargin; - _leftMargin = _leftBaseMargin; - - // create scroll bar for scrolling output up and down - // set the scroll bar's slider to occupy the whole area of the scroll bar initially - _scrollBar = new QScrollBar(this); - /******** Modify by ut000439 wangpeili 2020-06-24: 适应窗口特效圆角 ****************/ - //qDebug()<<"_scrollBar->width()"<<_scrollBar->width(); - // 设置15px宽度=6? - _scrollBar->setStyleSheet("margin: 0px 0 15px 0;width: 15"); - //qDebug()<<"_scrollBar->width()"<<_scrollBar->width(); - /********************* Modify by n014361 wangpeili End ************************/ - - // since the contrast with the terminal background may not be enough, - // the scrollbar should be auto-filled if not transient - if (!_scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, _scrollBar)) - _scrollBar->setAutoFillBackground(true); - setScroll(0,0); - _scrollBar->setCursor( Qt::ArrowCursor ); - connect(_scrollBar, SIGNAL(valueChanged(int)), this, - SLOT(scrollBarPositionChanged(int))); - // qtermwidget: we have to hide it here due the _scrollbarLocation==NoScrollBar - // check in TerminalDisplay::setScrollBarPosition(ScrollBarPosition position) - _scrollBar->hide(); - - // setup timers for blinking cursor and text - _blinkTimer = new QTimer(this); - connect(_blinkTimer, SIGNAL(timeout()), this, SLOT(blinkEvent())); - _blinkCursorTimer = new QTimer(this); - connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent())); + // variables for draw text + _drawTextAdditionHeight = 0; + _drawTextTestFlag = false; + + // terminal applications are not designed with Right-To-Left in mind, + // so the layout is forced to Left-To-Right + setLayoutDirection(Qt::LeftToRight); + + // The offsets are not yet calculated. + // Do not calculate these too often to be more smoothly when resizing + // konsole in opaque mode. + _topMargin = _topBaseMargin; + _leftMargin = _leftBaseMargin; + + // create scroll bar for scrolling output up and down + // set the scroll bar's slider to occupy the whole area of the scroll bar initially + _scrollBar = new QScrollBar(this); + /******** Modify by ut000439 wangpeili 2020-06-24: 适应窗口特效圆角 ****************/ + //qDebug()<<"_scrollBar->width()"<<_scrollBar->width(); + // 设置15px宽度=6? + _scrollBar->setStyleSheet("margin: 0px 0 15px 0;width: 15"); + //qDebug()<<"_scrollBar->width()"<<_scrollBar->width(); + /********************* Modify by n014361 wangpeili End ************************/ + + // since the contrast with the terminal background may not be enough, + // the scrollbar should be auto-filled if not transient + if (!_scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, _scrollBar)) + _scrollBar->setAutoFillBackground(true); + setScroll(0, 0); + _scrollBar->setCursor(Qt::ArrowCursor); + connect(_scrollBar, SIGNAL(valueChanged(int)), this, + SLOT(scrollBarPositionChanged(int))); + // qtermwidget: we have to hide it here due the _scrollbarLocation==NoScrollBar + // check in TerminalDisplay::setScrollBarPosition(ScrollBarPosition position) + _scrollBar->hide(); + + // setup timers for blinking cursor and text + _blinkTimer = new QTimer(this); + connect(_blinkTimer, SIGNAL(timeout()), this, SLOT(blinkEvent())); + _blinkCursorTimer = new QTimer(this); + connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent())); // KCursor::setAutoHideCursor( this, true ); - setUsesMouse(true); - setBracketedPasteMode(false); - setColorTable(base_color_table); - setMouseTracking(true); + setUsesMouse(true); + setBracketedPasteMode(false); + setColorTable(base_color_table); + setMouseTracking(true); - // Enable drag and drop - setAcceptDrops(true); // attempt - dragInfo.state = diNone; + // Enable drag and drop + setAcceptDrops(true); // attempt + dragInfo.state = diNone; - setFocusPolicy( Qt::WheelFocus ); + setFocusPolicy(Qt::WheelFocus); - // enable input method support - setAttribute(Qt::WA_InputMethodEnabled, true); + // enable input method support + setAttribute(Qt::WA_InputMethodEnabled, true); - // this is an important optimization, it tells Qt - // that TerminalDisplay will handle repainting its entire area. - setAttribute(Qt::WA_OpaquePaintEvent); + // this is an important optimization, it tells Qt + // that TerminalDisplay will handle repainting its entire area. + setAttribute(Qt::WA_OpaquePaintEvent); - _gridLayout = new QGridLayout(this); - _gridLayout->setContentsMargins(0, 0, 0, 0); - //_gridLayout->addWidget(_headerBar); + _gridLayout = new QGridLayout(this); + _gridLayout->setContentsMargins(0, 0, 0, 0); + //_gridLayout->addWidget(_headerBar); - setLayout( _gridLayout ); + setLayout(_gridLayout); - new AutoScrollHandler(this); + new AutoScrollHandler(this); - m_bUserIsResizing = false; + m_bUserIsResizing = false; - // 隐藏QScrollBar默认的右键菜单 - hideQScrollBarRightMenu(); + // 隐藏QScrollBar默认的右键菜单 + hideQScrollBarRightMenu(); } TerminalDisplay::~TerminalDisplay() { - disconnect(_blinkTimer); - disconnect(_blinkCursorTimer); - qApp->removeEventFilter( this ); + disconnect(_blinkTimer); + disconnect(_blinkCursorTimer); + qApp->removeEventFilter(this); - delete[] _image; + delete[] _image; - delete _gridLayout; - delete _outputSuspendedLabel; - delete _filterChain; + delete _gridLayout; + delete _outputSuspendedLabel; + delete _filterChain; } /* ------------------------------------------------------------------------- */ @@ -593,37 +599,36 @@ where _ = none */ -enum LineEncode -{ - TopL = (1<<1), - TopC = (1<<2), - TopR = (1<<3), - - LeftT = (1<<5), - Int11 = (1<<6), - Int12 = (1<<7), - Int13 = (1<<8), - RightT = (1<<9), - - LeftC = (1<<10), - Int21 = (1<<11), - Int22 = (1<<12), - Int23 = (1<<13), - RightC = (1<<14), - - LeftB = (1<<15), - Int31 = (1<<16), - Int32 = (1<<17), - Int33 = (1<<18), - RightB = (1<<19), - - BotL = (1<<21), - BotC = (1<<22), - BotR = (1<<23) +enum LineEncode { + TopL = (1 << 1), + TopC = (1 << 2), + TopR = (1 << 3), + + LeftT = (1 << 5), + Int11 = (1 << 6), + Int12 = (1 << 7), + Int13 = (1 << 8), + RightT = (1 << 9), + + LeftC = (1 << 10), + Int21 = (1 << 11), + Int22 = (1 << 12), + Int23 = (1 << 13), + RightC = (1 << 14), + + LeftB = (1 << 15), + Int31 = (1 << 16), + Int32 = (1 << 17), + Int33 = (1 << 18), + RightB = (1 << 19), + + BotL = (1 << 21), + BotC = (1 << 22), + BotR = (1 << 23) }; -void TerminalDisplay::drawLineCharString(QPainter& painter, int x, int y, const QString& str, - const Character* attributes) +void TerminalDisplay::drawLineCharString(QPainter &painter, int x, int y, const QString &str, + const Character *attributes) { // only turn on anti-aliasing during this short time for the "text" // for the normal text we have TextAntialiasing on demand on @@ -636,7 +641,7 @@ void TerminalDisplay::drawLineCharString(QPainter& painter, int x, int y, const QRect cellRect = {x, y, _fontWidth, _fontHeight}; for (int i = 0 ; i < str.length(); i++) { LineBlockCharacters::draw(painter, cellRect.translated(i * _fontWidth, 0), str[i], - useBoldPen); + useBoldPen); } painter.setRenderHint(QPainter::Antialiasing, false); @@ -653,13 +658,13 @@ QTermWidget::KeyboardCursorShape TerminalDisplay::keyboardCursorShape() const { return _cursorShape; } -void TerminalDisplay::setKeyboardCursorColor(bool useForegroundColor, const QColor& color) +void TerminalDisplay::setKeyboardCursorColor(bool useForegroundColor, const QColor &color) { if (useForegroundColor) _cursorColor = QColor(); // an invalid color means that - // the foreground color of the - // current character should - // be used + // the foreground color of the + // current character should + // be used else _cursorColor = color; @@ -690,127 +695,111 @@ void TerminalDisplay::setOpacity(qreal opacity) void TerminalDisplay::setBackgroundImage(QString backgroundImage) { - if (!backgroundImage.isEmpty()) - { + if (!backgroundImage.isEmpty()) { _backgroundImage.load(backgroundImage); setAttribute(Qt::WA_OpaquePaintEvent, false); - } - else - { + } else { _backgroundImage = QPixmap(); setAttribute(Qt::WA_OpaquePaintEvent, true); } } -void TerminalDisplay::drawBackground(QPainter& painter, const QRect& rect, const QColor& backgroundColor, bool useOpacitySetting ) +void TerminalDisplay::drawBackground(QPainter &painter, const QRect &rect, const QColor &backgroundColor, bool useOpacitySetting) { - // The whole widget rectangle is filled by the background color from - // the color scheme set in setColorTable(), while the scrollbar is - // left to the widget style for a consistent look. - if ( HAVE_TRANSPARENCY && qAlpha(_blendColor) < 0xff && useOpacitySetting ) - { - if (_backgroundImage.isNull()) { - QColor color(backgroundColor); - color.setAlpha(qAlpha(_blendColor)); + // The whole widget rectangle is filled by the background color from + // the color scheme set in setColorTable(), while the scrollbar is + // left to the widget style for a consistent look. + if (HAVE_TRANSPARENCY && qAlpha(_blendColor) < 0xff && useOpacitySetting) { + if (_backgroundImage.isNull()) { + QColor color(backgroundColor); + color.setAlpha(qAlpha(_blendColor)); - painter.save(); - painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.fillRect(rect, color); - painter.restore(); - } + painter.save(); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(rect, color); + painter.restore(); } - else - painter.fillRect(rect, backgroundColor); + } else + painter.fillRect(rect, backgroundColor); } -void TerminalDisplay::drawCursor(QPainter& painter, - const QRect& rect, - const QColor& foregroundColor, - const QColor& /*backgroundColor*/, - bool& invertCharacterColor) +void TerminalDisplay::drawCursor(QPainter &painter, + const QRect &rect, + const QColor &foregroundColor, + const QColor & /*backgroundColor*/, + bool &invertCharacterColor) { QRectF cursorRect = rect; cursorRect.setHeight(_fontHeight - _lineSpacing - 1); - if (!_cursorBlinking) - { - if ( _cursorColor.isValid() ) - painter.setPen(_cursorColor); - else - painter.setPen(foregroundColor); - // Todo (Archie Meng): 绘制偏移量用于很脏地修复光标显示问题,如果找到刷新问题的根因,应该改成不使用偏移量的形式。 - if ( _cursorShape == Emulation::KeyboardCursorShape::BlockCursor ) - { - - if ( hasFocus() ) - { + if (!_cursorBlinking) { + if (_cursorColor.isValid()) + painter.setPen(_cursorColor); + else + painter.setPen(foregroundColor); + // Todo (Archie Meng): 绘制偏移量用于很脏地修复光标显示问题,如果找到刷新问题的根因,应该改成不使用偏移量的形式。 + if (_cursorShape == Emulation::KeyboardCursorShape::BlockCursor) { + + if (hasFocus()) { cursorRect.translate(1, 1); painter.fillRect(cursorRect, _cursorColor.isValid() ? _cursorColor : foregroundColor); - if ( !_cursorColor.isValid() ) - { + if (!_cursorColor.isValid()) { // invert the colour used to draw the text to ensure that the character at // the cursor position is readable invertCharacterColor = true; } - } - else - { + } else { // draw the cursor outline, adjusting the area so that // it is draw entirely inside 'rect' - float penWidth = qMax(1,painter.pen().width()); + float penWidth = qMax(1, painter.pen().width()); - painter.drawRect(cursorRect.adjusted(penWidth/2, - penWidth/2, - - penWidth/2, - - penWidth/2)); + painter.drawRect(cursorRect.adjusted(penWidth / 2, + penWidth / 2, + - penWidth / 2, + - penWidth / 2)); } - } - else if ( _cursorShape == Emulation::KeyboardCursorShape::UnderlineCursor ) + } else if (_cursorShape == Emulation::KeyboardCursorShape::UnderlineCursor) painter.drawLine(QLineF( QPointF(cursorRect.left() + 2, cursorRect.bottom()), QPointF(cursorRect.right(), cursorRect.bottom()))); - else if ( _cursorShape == Emulation::KeyboardCursorShape::IBeamCursor ) + else if (_cursorShape == Emulation::KeyboardCursorShape::IBeamCursor) painter.drawLine(QLineF( - QPointF(cursorRect.left() + 2, - cursorRect.top() + 2), - QPointF(cursorRect.left() + 2, - cursorRect.bottom()))); - else if ( _cursorShape == Emulation::KeyboardCursorShape::BoldUnderlineCursor ) - { - if ( hasFocus() ) - { - cursorRect.translate(1,cursorRect.height() - 4); + QPointF(cursorRect.left() + 2, + cursorRect.top() + 2), + QPointF(cursorRect.left() + 2, + cursorRect.bottom()))); + else if (_cursorShape == Emulation::KeyboardCursorShape::BoldUnderlineCursor) { + if (hasFocus()) { + cursorRect.translate(1, cursorRect.height() - 4); cursorRect.setHeight(4); painter.fillRect(cursorRect, _cursorColor.isValid() ? _cursorColor : foregroundColor); - } - else - { + } else { painter.drawRect( - cursorRect.left(), - cursorRect.bottom() - 4, - cursorRect.width(), - 4); + cursorRect.left(), + cursorRect.bottom() - 4, + cursorRect.width(), + 4); } } } } -void TerminalDisplay::drawCharacters(QPainter& painter, - const QRect& rect, - const QString& text, - const Character* style, +void TerminalDisplay::drawCharacters(QPainter &painter, + const QRect &rect, + const QString &text, + const Character *style, bool invertCharacterColor) { // don't draw text which is currently blinking - if ( _blinking && (style->rendition & RE_BLINK) ) + if (_blinking && (style->rendition & RE_BLINK)) return; // don't draw concealed characters if (style->rendition & RE_CONCEAL) - return; + return; // setup bold and underline bool useBold = ((style->rendition & RE_BOLD) && _boldIntense) || font().bold(); @@ -820,34 +809,32 @@ void TerminalDisplay::drawCharacters(QPainter& painter, const bool useOverline = style->rendition & RE_OVERLINE || font().overline(); QFont font = painter.font(); - if ( font.bold() != useBold - || font.underline() != useUnderline - || font.italic() != useItalic - || font.strikeOut() != useStrikeOut - || font.overline() != useOverline) { - font.setBold(useBold); - font.setUnderline(useUnderline); - font.setItalic(useItalic); - font.setStrikeOut(useStrikeOut); - font.setOverline(useOverline); - painter.setFont(font); + if (font.bold() != useBold + || font.underline() != useUnderline + || font.italic() != useItalic + || font.strikeOut() != useStrikeOut + || font.overline() != useOverline) { + font.setBold(useBold); + font.setUnderline(useUnderline); + font.setItalic(useItalic); + font.setStrikeOut(useStrikeOut); + font.setOverline(useOverline); + painter.setFont(font); } // setup pen - const CharacterColor& textColor = ( invertCharacterColor ? style->backgroundColor : style->foregroundColor ); + const CharacterColor &textColor = (invertCharacterColor ? style->backgroundColor : style->foregroundColor); const QColor color = textColor.color(_colorTable); QPen pen = painter.pen(); - if ( pen.color() != color ) - { + if (pen.color() != color) { pen.setColor(color); painter.setPen(color); } // draw text - if ( isLineCharString(text) ) - drawLineCharString(painter,rect.x(),rect.y(),text,style); - else - { + if (isLineCharString(text)) + drawLineCharString(painter, rect.x(), rect.y(), text, style); + else { // Force using LTR as the document layout for the terminal area, because // there is no use cases for RTL emulator and RTL terminal application. // @@ -857,19 +844,19 @@ void TerminalDisplay::drawCharacters(QPainter& painter, if (_bidiEnabled) { painter.drawText(QPointF(rect.x(), rect.y() + _fontAscent + _lineSpacing), text); } else { - { - QRectF drawRect(rect.topLeft(), rect.size()); - drawRect.setHeight(rect.height() + _drawTextAdditionHeight); - painter.drawText(drawRect, Qt::AlignBottom, LTR_OVERRIDE_CHAR + text); - } + { + QRectF drawRect(rect.topLeft(), rect.size()); + drawRect.setHeight(rect.height() + _drawTextAdditionHeight); + painter.drawText(drawRect, Qt::AlignBottom, LTR_OVERRIDE_CHAR + text); + } } } } -void TerminalDisplay::drawTextFragment(QPainter& painter , - const QRect& rect, - const QString& text, - const Character* style) +void TerminalDisplay::drawTextFragment(QPainter &painter, + const QRect &rect, + const QString &text, + const Character *style) { painter.save(); @@ -878,26 +865,24 @@ void TerminalDisplay::drawTextFragment(QPainter& painter , const QColor backgroundColor = style->backgroundColor.color(_colorTable); // draw background if different from the display's background color - if ( backgroundColor != palette().background().color() ) - drawBackground(painter,rect,backgroundColor, + if (backgroundColor != palette().background().color()) + drawBackground(painter, rect, backgroundColor, false /* do not use transparency */); // draw cursor shape if the current character is the cursor // this may alter the foreground and background colors bool invertCharacterColor = false; - if (!_hideCursor) - { - if ( style->rendition & RE_CURSOR ) - { + if (!_hideCursor) { + if (style->rendition & RE_CURSOR) { const QColor cursorBackground = _colorTable[DEFAULT_BACK_COLOR].color; const QColor cursorForeground = _colorTable[DEFAULT_FORE_COLOR].color; - drawCursor(painter,rect,cursorForeground,cursorBackground,invertCharacterColor); + drawCursor(painter, rect, cursorForeground, cursorBackground, invertCharacterColor); } } // draw text - drawCharacters(painter,rect,text,style,invertCharacterColor); + drawCharacters(painter, rect, text, style, invertCharacterColor); painter.restore(); } @@ -916,8 +901,8 @@ void TerminalDisplay::setCursorPos(const int curx, const int cury) int tLy = tL.y(); int xpos, ypos; - ypos = _topMargin + tLy + _fontHeight*(cury-1) + _fontAscent; - xpos = _leftMargin + tLx + _fontWidth*curx; + ypos = _topMargin + tLy + _fontHeight * (cury - 1) + _fontAscent; + xpos = _leftMargin + tLx + _fontWidth * curx; //setMicroFocusHint(xpos, ypos, 0, _fontHeight); //### ??? // fprintf(stderr, "x/y = %d/%d\txpos/ypos = %d/%d\n", curx, cury, xpos, ypos); _cursorLine = cury; @@ -933,12 +918,12 @@ void TerminalDisplay::setCursorPos(const int curx, const int cury) // display is much cheaper than re-rendering all the text for the // part of the image which has moved up or down. // Instead only new lines have to be drawn -void TerminalDisplay::scrollImage(int lines , const QRect& screenWindowRegion) +void TerminalDisplay::scrollImage(int lines, const QRect &screenWindowRegion) { // if the flow control warning is enabled this will interfere with the // scrolling optimizations and cause artifacts. the simple solution here // is to just disable the optimization whilst it is visible - if ( _outputSuspendedLabel && _outputSuspendedLabel->isVisible() ) + if (_outputSuspendedLabel && _outputSuspendedLabel->isVisible()) return; // constrain the region to the display @@ -946,14 +931,14 @@ void TerminalDisplay::scrollImage(int lines , const QRect& screenWindowRegion) // internal image - 2, so that the height of 'region' is strictly less // than the height of the internal image. QRect region = screenWindowRegion; - region.setBottom( qMin(region.bottom(),this->_lines-2) ); + region.setBottom(qMin(region.bottom(), this->_lines - 2)); // return if there is nothing to do - if ( lines == 0 - || _image == nullptr - || !region.isValid() - || (region.top() + abs(lines)) >= region.bottom() - || this->_lines <= region.height() ) return; + if (lines == 0 + || _image == nullptr + || !region.isValid() + || (region.top() + abs(lines)) >= region.bottom() + || this->_lines <= region.height()) return; // hide terminal size label to prevent it being scrolled if (_resizeWidget && _resizeWidget->isVisible()) @@ -974,18 +959,15 @@ void TerminalDisplay::scrollImage(int lines , const QRect& screenWindowRegion) 0 : _scrollBar->width(); const int SCROLLBAR_CONTENT_GAP = scrollBarWidth == 0 ? 0 : 1; QRect scrollRect; - if ( _scrollbarLocation == QTermWidget::ScrollBarLeft ) - { - scrollRect.setLeft(scrollBarWidth+SCROLLBAR_CONTENT_GAP); + if (_scrollbarLocation == QTermWidget::ScrollBarLeft) { + scrollRect.setLeft(scrollBarWidth + SCROLLBAR_CONTENT_GAP); scrollRect.setRight(width()); - } - else - { + } else { scrollRect.setLeft(0); scrollRect.setRight(width() - scrollBarWidth - SCROLLBAR_CONTENT_GAP); } - void* firstCharPos = &_image[ region.top() * this->_columns ]; - void* lastCharPos = &_image[ (region.top() + abs(lines)) * this->_columns ]; + void *firstCharPos = &_image[ region.top() * this->_columns ]; + void *lastCharPos = &_image[(region.top() + abs(lines)) * this->_columns ]; int top = _topMargin + (region.top() * _fontHeight); int linesToMove = region.height() - abs(lines); @@ -993,52 +975,48 @@ void TerminalDisplay::scrollImage(int lines , const QRect& screenWindowRegion) this->_columns * sizeof(Character); - Q_ASSERT( linesToMove > 0 ); - Q_ASSERT( bytesToMove > 0 ); + Q_ASSERT(linesToMove > 0); + Q_ASSERT(bytesToMove > 0); //scroll internal image - if ( lines > 0 ) - { + if (lines > 0) { // check that the memory areas that we are going to move are valid - Q_ASSERT( (char*)lastCharPos + bytesToMove < - (char*)(_image + (this->_lines * this->_columns)) ); + Q_ASSERT((char *)lastCharPos + bytesToMove < + (char *)(_image + (this->_lines * this->_columns))); - Q_ASSERT( (lines*this->_columns) < _imageSize ); + Q_ASSERT((lines * this->_columns) < _imageSize); //scroll internal image down - memmove( firstCharPos , lastCharPos , bytesToMove ); + memmove(firstCharPos, lastCharPos, bytesToMove); //set region of display to scroll scrollRect.setTop(top); - } - else - { + } else { // check that the memory areas that we are going to move are valid - Q_ASSERT( (char*)firstCharPos + bytesToMove < - (char*)(_image + (this->_lines * this->_columns)) ); + Q_ASSERT((char *)firstCharPos + bytesToMove < + (char *)(_image + (this->_lines * this->_columns))); //scroll internal image up - memmove( lastCharPos , firstCharPos , bytesToMove ); + memmove(lastCharPos, firstCharPos, bytesToMove); //set region of the display to scroll scrollRect.setTop(top + abs(lines) * _fontHeight); } - scrollRect.setHeight(linesToMove * _fontHeight ); + scrollRect.setHeight(linesToMove * _fontHeight); Q_ASSERT(scrollRect.isValid() && !scrollRect.isEmpty()); //scroll the display vertically to match internal _image - scroll( 0 , _fontHeight * (-lines) , scrollRect ); + scroll(0, _fontHeight * (-lines), scrollRect); } QRegion TerminalDisplay::hotSpotRegion() const { QRegion region; const auto hotSpots = _filterChain->hotSpots(); - for( Filter::HotSpot* const hotSpot : hotSpots ) - { + for (Filter::HotSpot *const hotSpot : hotSpots) { QRect r; - if (hotSpot->startLine()==hotSpot->endLine()) { + if (hotSpot->startLine() == hotSpot->endLine()) { r.setLeft(hotSpot->startColumn()); r.setTop(hotSpot->startLine()); r.setRight(hotSpot->endColumn()); @@ -1050,7 +1028,7 @@ QRegion TerminalDisplay::hotSpotRegion() const r.setRight(_columns); r.setBottom(hotSpot->startLine()); region |= imageToWidget(r);; - for ( int line = hotSpot->startLine()+1 ; line < hotSpot->endLine() ; line++ ) { + for (int line = hotSpot->startLine() + 1 ; line < hotSpot->endLine() ; line++) { r.setLeft(0); r.setTop(line); r.setRight(_columns); @@ -1079,267 +1057,250 @@ void TerminalDisplay::processFilters() // ScreenWindow emits a scrolled() signal - which will happen before // updateImage() is called on the display and therefore _image is // out of date at this point - _filterChain->setImage( _screenWindow->getImage(), - _screenWindow->windowLines(), - _screenWindow->windowColumns(), - _screenWindow->getLineProperties() ); + _filterChain->setImage(_screenWindow->getImage(), + _screenWindow->windowLines(), + _screenWindow->windowColumns(), + _screenWindow->getLineProperties()); _filterChain->process(); QRegion postUpdateHotSpots = hotSpotRegion(); - update( preUpdateHotSpots | postUpdateHotSpots ); + update(preUpdateHotSpots | postUpdateHotSpots); } void TerminalDisplay::updateImage() { - if ( !_screenWindow ) - return; + if (!_screenWindow) + return; - // optimization - scroll the existing image where possible and - // avoid expensive text drawing for parts of the image that - // can simply be moved up or down - scrollImage( _screenWindow->scrollCount() , - _screenWindow->scrollRegion() ); + // optimization - scroll the existing image where possible and + // avoid expensive text drawing for parts of the image that + // can simply be moved up or down + scrollImage(_screenWindow->scrollCount(), + _screenWindow->scrollRegion()); - if (!_image) { - // Create _image. - // The emitted changedContentSizeSignal also leads to getImage being recreated, so do this first. - updateImageSize(); - } + if (!_image) { + // Create _image. + // The emitted changedContentSizeSignal also leads to getImage being recreated, so do this first. + updateImageSize(); + } - Character* const newimg = _screenWindow->getImage(); - int lines = _screenWindow->windowLines(); - int columns = _screenWindow->windowColumns(); + Character *const newimg = _screenWindow->getImage(); + int lines = _screenWindow->windowLines(); + int columns = _screenWindow->windowColumns(); - setScroll( _screenWindow->currentLine() , _screenWindow->lineCount() ); - //--added by qinyaning(nyq) to slove the problem of scroll init show--/ - setScrollBarPosition(_lines > 1 && _screenWindow->lineCount() > _lines? - QTermWidget::ScrollBarRight : QTermWidget::NoScrollBar); - //--------------------------------------------------------------------/ + setScroll(_screenWindow->currentLine(), _screenWindow->lineCount()); + //--added by qinyaning(nyq) to slove the problem of scroll init show--/ + setScrollBarPosition(_lines > 1 && _screenWindow->lineCount() > _lines ? + QTermWidget::ScrollBarRight : QTermWidget::NoScrollBar); + //--------------------------------------------------------------------/ - Q_ASSERT( this->_usedLines <= this->_lines ); - Q_ASSERT( this->_usedColumns <= this->_columns ); + Q_ASSERT(this->_usedLines <= this->_lines); + Q_ASSERT(this->_usedColumns <= this->_columns); - int y,x,len; + int y, x, len; - QPoint tL = contentsRect().topLeft(); - int tLx = tL.x(); - int tLy = tL.y(); - _hasBlinker = false; + QPoint tL = contentsRect().topLeft(); + int tLx = tL.x(); + int tLy = tL.y(); + _hasBlinker = false; - CharacterColor cf; // undefined + CharacterColor cf; // undefined - const int linesToUpdate = qMin(this->_lines, qMax(0,lines )); - const int columnsToUpdate = qMin(this->_columns,qMax(0,columns)); + const int linesToUpdate = qMin(this->_lines, qMax(0, lines)); + const int columnsToUpdate = qMin(this->_columns, qMax(0, columns)); - auto dirtyMask = new char[columnsToUpdate + 2]; - QRegion dirtyRegion; + auto dirtyMask = new char[columnsToUpdate + 2]; + QRegion dirtyRegion; - // debugging variable, this records the number of lines that are found to - // be 'dirty' ( ie. have changed from the old _image to the new _image ) and - // which therefore need to be repainted - int dirtyLineCount = 0; + // debugging variable, this records the number of lines that are found to + // be 'dirty' ( ie. have changed from the old _image to the new _image ) and + // which therefore need to be repainted + int dirtyLineCount = 0; - for (y = 0; y < linesToUpdate; ++y) - { - const Character* currentLine = &_image[y*this->_columns]; - const Character* const newLine = &newimg[y*columns]; + for (y = 0; y < linesToUpdate; ++y) { + const Character *currentLine = &_image[y * this->_columns]; + const Character *const newLine = &newimg[y * columns]; - bool updateLine = false; + bool updateLine = false; - // The dirty mask indicates which characters need repainting. We also - // mark surrounding neighbours dirty, in case the character exceeds - // its cell boundaries - memset(dirtyMask, 0, columnsToUpdate+2); + // The dirty mask indicates which characters need repainting. We also + // mark surrounding neighbours dirty, in case the character exceeds + // its cell boundaries + memset(dirtyMask, 0, columnsToUpdate + 2); - for( x = 0 ; x < columnsToUpdate ; ++x) - { - if ( newLine[x] != currentLine[x] ) - { - dirtyMask[x] = 1; + for (x = 0 ; x < columnsToUpdate ; ++x) { + if (newLine[x] != currentLine[x]) { + dirtyMask[x] = 1; + } } - } - if (!_resizing) // not while _resizing, we're expecting a paintEvent - for (x = 0; x < columnsToUpdate; ++x) - { - _hasBlinker |= (newLine[x].rendition & RE_BLINK); - - // Start drawing if this character or the next one differs. - // We also take the next one into account to handle the situation - // where characters exceed their cell width. - if (dirtyMask[x]) - { - if (newLine[x + 0].character == 0u) - { - continue; - } - bool lineDraw = canDraw(newLine[x + 0].character); - bool doubleWidth = (x + 1 == columnsToUpdate) ? false : (newLine[x + 1].character == 0); - RenditionFlags cr = newLine[x].rendition; - CharacterColor clipboard = newLine[x].backgroundColor; - if (newLine[x].foregroundColor != cf) - { - cf = newLine[x].foregroundColor; - } - const int lln = columnsToUpdate - x; - for (len = 1; len < lln; ++len) - { - const Character& ch = newLine[x+len]; - - if (!ch.character) - continue; // Skip trailing part of multi-col chars. - - bool nextIsDoubleWidth = (x + len + 1 == columnsToUpdate) ? false : (newLine[x + len + 1].character == 0); - - if (ch.foregroundColor != cf || - ch.backgroundColor != clipboard || - (ch.rendition & ~RE_EXTENDED_CHAR) != (cr & ~RE_EXTENDED_CHAR) || - (dirtyMask[x + len] == 0) || - canDraw(ch.character) != lineDraw || - nextIsDoubleWidth != doubleWidth) { - break; + if (!_resizing) // not while _resizing, we're expecting a paintEvent + for (x = 0; x < columnsToUpdate; ++x) { + _hasBlinker |= (newLine[x].rendition & RE_BLINK); + + // Start drawing if this character or the next one differs. + // We also take the next one into account to handle the situation + // where characters exceed their cell width. + if (dirtyMask[x]) { + if (newLine[x + 0].character == 0u) { + continue; + } + bool lineDraw = canDraw(newLine[x + 0].character); + bool doubleWidth = (x + 1 == columnsToUpdate) ? false : (newLine[x + 1].character == 0); + RenditionFlags cr = newLine[x].rendition; + CharacterColor clipboard = newLine[x].backgroundColor; + if (newLine[x].foregroundColor != cf) { + cf = newLine[x].foregroundColor; + } + const int lln = columnsToUpdate - x; + for (len = 1; len < lln; ++len) { + const Character &ch = newLine[x + len]; + + if (!ch.character) + continue; // Skip trailing part of multi-col chars. + + bool nextIsDoubleWidth = (x + len + 1 == columnsToUpdate) ? false : (newLine[x + len + 1].character == 0); + + if (ch.foregroundColor != cf || + ch.backgroundColor != clipboard || + (ch.rendition & ~RE_EXTENDED_CHAR) != (cr & ~RE_EXTENDED_CHAR) || + (dirtyMask[x + len] == 0) || + canDraw(ch.character) != lineDraw || + nextIsDoubleWidth != doubleWidth) { + break; + } + } + + bool saveFixedFont = _fixedFont; + if (lineDraw) + _fixedFont = false; + if (doubleWidth) + _fixedFont = false; + + updateLine = true; + + _fixedFont = saveFixedFont; + x += len - 1; + } + } - } - bool saveFixedFont = _fixedFont; - if (lineDraw) - _fixedFont = false; - if (doubleWidth) - _fixedFont = false; + //both the top and bottom halves of double height _lines must always be redrawn + //although both top and bottom halves contain the same characters, only + //the top one is actually + //drawn. + if (_lineProperties.count() > y) + updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT); + + // if the characters on the line are different in the old and the new _image + // then this line must be repainted. + if (updateLine) { + dirtyLineCount++; + + // add the area occupied by this line to the region which needs to be + // repainted + QRect dirtyRect = QRect(_leftMargin + tLx, + _topMargin + tLy + _fontHeight * y, + _fontWidth * columnsToUpdate, + _fontHeight); + + dirtyRegion |= dirtyRect; + } - updateLine = true; + // replace the line of characters in the old _image with the + // current line of the new _image + memcpy((void *)currentLine, (const void *)newLine, columnsToUpdate * sizeof(Character)); + } - _fixedFont = saveFixedFont; - x += len - 1; - } + // if the new _image is smaller than the previous _image, then ensure that the area + // outside the new _image is cleared + if (linesToUpdate < _usedLines) { + dirtyRegion |= QRect(_leftMargin + tLx, + _topMargin + tLy + _fontHeight * linesToUpdate, + _fontWidth * this->_columns, + _fontHeight * (_usedLines - linesToUpdate)); + } + _usedLines = linesToUpdate; + if (columnsToUpdate < _usedColumns) { + dirtyRegion |= QRect(_leftMargin + tLx + columnsToUpdate * _fontWidth, + _topMargin + tLy, + _fontWidth * (_usedColumns - columnsToUpdate), + _fontHeight * this->_lines); } + _usedColumns = columnsToUpdate; - //both the top and bottom halves of double height _lines must always be redrawn - //although both top and bottom halves contain the same characters, only - //the top one is actually - //drawn. - if (_lineProperties.count() > y) - updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT); + dirtyRegion |= _inputMethodData.previousPreeditRect; - // if the characters on the line are different in the old and the new _image - // then this line must be repainted. - if (updateLine) - { - dirtyLineCount++; - - // add the area occupied by this line to the region which needs to be - // repainted - QRect dirtyRect = QRect( _leftMargin+tLx , - _topMargin+tLy+_fontHeight*y , - _fontWidth * columnsToUpdate , - _fontHeight ); - - dirtyRegion |= dirtyRect; - } - - // replace the line of characters in the old _image with the - // current line of the new _image - memcpy((void*)currentLine,(const void*)newLine,columnsToUpdate*sizeof(Character)); - } - - // if the new _image is smaller than the previous _image, then ensure that the area - // outside the new _image is cleared - if ( linesToUpdate < _usedLines ) - { - dirtyRegion |= QRect( _leftMargin+tLx , - _topMargin+tLy+_fontHeight*linesToUpdate , - _fontWidth * this->_columns , - _fontHeight * (_usedLines-linesToUpdate) ); - } - _usedLines = linesToUpdate; - - if ( columnsToUpdate < _usedColumns ) - { - dirtyRegion |= QRect( _leftMargin+tLx+columnsToUpdate*_fontWidth , - _topMargin+tLy , - _fontWidth * (_usedColumns-columnsToUpdate) , - _fontHeight * this->_lines ); - } - _usedColumns = columnsToUpdate; - - dirtyRegion |= _inputMethodData.previousPreeditRect; - - _screenWindow->resetScrollCount(); - // update the parts of the display which have changed - //--modified and added by qinyaning(nyq) to solve When the screen zooms to 1.25 and 2.75, - /*the terminal interface will display colored lines. time: 2020.4.10 14:18 - * */ - //update(dirtyRegion); - update(); - //------------------------------------------------- - - if ( _hasBlinker && !_blinkTimer->isActive()) _blinkTimer->start( TEXT_BLINK_DELAY ); - if (!_hasBlinker && _blinkTimer->isActive()) { _blinkTimer->stop(); _blinking = false; } - delete[] dirtyMask; + _screenWindow->resetScrollCount(); + // update the parts of the display which have changed + //--modified and added by qinyaning(nyq) to solve When the screen zooms to 1.25 and 2.75, + /*the terminal interface will display colored lines. time: 2020.4.10 14:18 + * */ + //update(dirtyRegion); + update(); + //------------------------------------------------- + + if (_hasBlinker && !_blinkTimer->isActive()) _blinkTimer->start(TEXT_BLINK_DELAY); + if (!_hasBlinker && _blinkTimer->isActive()) { _blinkTimer->stop(); _blinking = false; } + delete[] dirtyMask; } void TerminalDisplay::showResizeNotification() { - if (_terminalSizeHint && isVisible()) - { - if (_terminalSizeStartup) { - _terminalSizeStartup=false; - return; - } - if (!_resizeWidget) - { - const QString label = tr("Size: XXX x XXX"); - _resizeWidget = new QLabel(label, this); - _resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width(label)); - _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height()); - _resizeWidget->setAlignment(Qt::AlignCenter); - - _resizeWidget->setStyleSheet(QLatin1String("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)")); - - _resizeTimer = new QTimer(this); - _resizeTimer->setSingleShot(true); - connect(_resizeTimer, &QTimer::timeout, this, [this](){ - //计时器timeout,终端控件结束调整大小 - this->m_bUserIsResizing = false; - SessionManager::instance()->setTerminalResizing(_sessionId, m_bUserIsResizing); - }); - } - //显示resizeWidget的时候,标记当前session对应终端控件正在调整大小 - SessionManager::instance()->setTerminalResizing(_sessionId, true); - _resizeWidget->setText(tr("Size: %1 x %2").arg(_columns).arg(_lines)); - _resizeWidget->move((width()-_resizeWidget->width())/2, - (height()-_resizeWidget->height())/2+20); - - //fix bug 17684 在放大,正常窗口,最大化之间切换,终端窗口会显示size - _resizeWidget->hide(); - _resizeTimer->start(1000); - } + if (_terminalSizeHint && isVisible()) { + if (_terminalSizeStartup) { + _terminalSizeStartup = false; + return; + } + if (!_resizeWidget) { + const QString label = tr("Size: XXX x XXX"); + _resizeWidget = new QLabel(label, this); + _resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width(label)); + _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height()); + _resizeWidget->setAlignment(Qt::AlignCenter); + + _resizeWidget->setStyleSheet(QLatin1String("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)")); + + _resizeTimer = new QTimer(this); + _resizeTimer->setSingleShot(true); + connect(_resizeTimer, &QTimer::timeout, this, [this]() { + //计时器timeout,终端控件结束调整大小 + this->m_bUserIsResizing = false; + SessionManager::instance()->setTerminalResizing(_sessionId, m_bUserIsResizing); + }); + } + //显示resizeWidget的时候,标记当前session对应终端控件正在调整大小 + SessionManager::instance()->setTerminalResizing(_sessionId, true); + _resizeWidget->setText(tr("Size: %1 x %2").arg(_columns).arg(_lines)); + _resizeWidget->move((width() - _resizeWidget->width()) / 2, + (height() - _resizeWidget->height()) / 2 + 20); + + //fix bug 17684 在放大,正常窗口,最大化之间切换,终端窗口会显示size + _resizeWidget->hide(); + _resizeTimer->start(1000); + } } void TerminalDisplay::setBlinkingCursor(bool blink) { - _hasBlinkingCursor=blink; + _hasBlinkingCursor = blink; if (blink && !_blinkCursorTimer->isActive()) - _blinkCursorTimer->start(QApplication::cursorFlashTime() / 2); + _blinkCursorTimer->start(QApplication::cursorFlashTime() / 2); - if (!blink && _blinkCursorTimer->isActive()) - { + if (!blink && _blinkCursorTimer->isActive()) { _blinkCursorTimer->stop(); if (_cursorBlinking) - blinkCursorEvent(); + blinkCursorEvent(); else - _cursorBlinking = false; + _cursorBlinking = false; } /******** Modify by n014361 wangpeili 2020-02-13: 修复“设置光标闪烁后,非焦点光标也在闪烁”***********×****/ - if (hasFocus()) - { + if (hasFocus()) { focusInEvent(nullptr); - } - else - { + } else { focusOutEvent(nullptr); } /***************** Modify by n014361 End *************************/ @@ -1352,14 +1313,13 @@ void TerminalDisplay::setBlinkingTextEnabled(bool blink) if (blink && !_blinkTimer->isActive()) _blinkTimer->start(TEXT_BLINK_DELAY); - if (!blink && _blinkTimer->isActive()) - { + if (!blink && _blinkTimer->isActive()) { _blinkTimer->stop(); _blinking = false; } } -void TerminalDisplay::focusOutEvent(QFocusEvent*) +void TerminalDisplay::focusOutEvent(QFocusEvent *) { emit termLostFocus(); // trigger a repaint of the cursor so that it is both visible (in case @@ -1374,12 +1334,11 @@ void TerminalDisplay::focusOutEvent(QFocusEvent*) _blinkTimer->stop(); } -void TerminalDisplay::focusInEvent(QFocusEvent*) +void TerminalDisplay::focusInEvent(QFocusEvent *) { //qDebug()<<"focusInEvent"; emit termGetFocus(); - if (_hasBlinkingCursor) - { + if (_hasBlinkingCursor) { _blinkCursorTimer->start(); } updateCursor(); @@ -1388,41 +1347,39 @@ void TerminalDisplay::focusInEvent(QFocusEvent*) _blinkTimer->start(); } -void TerminalDisplay::paintEvent( QPaintEvent* pe ) +void TerminalDisplay::paintEvent(QPaintEvent *pe) { - QPainter paint(this); + QPainter paint(this); - if ( !_backgroundImage.isNull() && qAlpha(_blendColor) < 0xff ) - { - paint.drawPixmap(0, 0, _backgroundImage); - QColor background = _colorTable[DEFAULT_BACK_COLOR].color; - background.setAlpha(qAlpha(_blendColor)); - paint.fillRect(contentsRect(), background); - } + if (!_backgroundImage.isNull() && qAlpha(_blendColor) < 0xff) { + paint.drawPixmap(0, 0, _backgroundImage); + QColor background = _colorTable[DEFAULT_BACK_COLOR].color; + background.setAlpha(qAlpha(_blendColor)); + paint.fillRect(contentsRect(), background); + } - if(_drawTextTestFlag) - { - calDrawTextAdditionHeight(paint); - } + if (_drawTextTestFlag) { + calDrawTextAdditionHeight(paint); + } - // Determine which characters should be repainted (1 region unit = 1 character) - QRegion dirtyImageRegion; - const QRegion region = pe->region() & contentsRect(); + // Determine which characters should be repainted (1 region unit = 1 character) + QRegion dirtyImageRegion; + const QRegion region = pe->region() & contentsRect(); - for (const QRect &rect : region) { - dirtyImageRegion += widgetToImage(rect); - drawBackground(paint, rect, palette().background().color(), true /* use opacity setting */); - } + for (const QRect &rect : region) { + dirtyImageRegion += widgetToImage(rect); + drawBackground(paint, rect, palette().background().color(), true /* use opacity setting */); + } - // only turn on text anti-aliasing, never turn on normal antialiasing - // set https://bugreports.qt.io/browse/QTBUG-66036 - paint.setRenderHint(QPainter::TextAntialiasing, _antialiasText); + // only turn on text anti-aliasing, never turn on normal antialiasing + // set https://bugreports.qt.io/browse/QTBUG-66036 + paint.setRenderHint(QPainter::TextAntialiasing, _antialiasText); - for (const QRect &rect : qAsConst(dirtyImageRegion)) { - drawContents(paint, rect); - } - drawInputMethodPreeditString(paint, preeditRect()); - paintFilters(paint); + for (const QRect &rect : qAsConst(dirtyImageRegion)) { + drawContents(paint, rect); + } + drawInputMethodPreeditString(paint, preeditRect()); + paintFilters(paint); } QPoint TerminalDisplay::cursorPosition() const @@ -1430,25 +1387,25 @@ QPoint TerminalDisplay::cursorPosition() const if (_screenWindow) return _screenWindow->cursorPosition(); else - return {0,0}; + return {0, 0}; } QRect TerminalDisplay::preeditRect() const { const int preeditLength = Character::stringWidth(_inputMethodData.preeditString); - if ( preeditLength == 0 ) + if (preeditLength == 0) return {}; - return QRect(_leftMargin + _fontWidth*cursorPosition().x(), - _topMargin + _fontHeight*cursorPosition().y(), - _fontWidth*preeditLength, + return QRect(_leftMargin + _fontWidth * cursorPosition().x(), + _topMargin + _fontHeight * cursorPosition().y(), + _fontWidth * preeditLength, _fontHeight); } -void TerminalDisplay::drawInputMethodPreeditString(QPainter& painter , const QRect& rect) +void TerminalDisplay::drawInputMethodPreeditString(QPainter &painter, const QRect &rect) { - if ( _inputMethodData.preeditString.isEmpty() ) + if (_inputMethodData.preeditString.isEmpty()) return; const QPoint cursorPos = cursorPosition(); @@ -1456,21 +1413,21 @@ void TerminalDisplay::drawInputMethodPreeditString(QPainter& painter , const QRe bool invertColors = false; const QColor background = _colorTable[DEFAULT_BACK_COLOR].color; const QColor foreground = _colorTable[DEFAULT_FORE_COLOR].color; - const Character* style = &_image[loc(cursorPos.x(),cursorPos.y())]; + const Character *style = &_image[loc(cursorPos.x(), cursorPos.y())]; - drawBackground(painter,rect,background,true); - drawCursor(painter,rect,foreground,background,invertColors); - drawCharacters(painter,rect,_inputMethodData.preeditString,style,invertColors); + drawBackground(painter, rect, background, true); + drawCursor(painter, rect, foreground, background, invertColors); + drawCharacters(painter, rect, _inputMethodData.preeditString, style, invertColors); _inputMethodData.previousPreeditRect = rect; } -FilterChain* TerminalDisplay::filterChain() const +FilterChain *TerminalDisplay::filterChain() const { return _filterChain; } -void TerminalDisplay::paintFilters(QPainter& painter) +void TerminalDisplay::paintFilters(QPainter &painter) { // get color of character under mouse and use it to draw // lines for filters @@ -1482,10 +1439,10 @@ void TerminalDisplay::paintFilters(QPainter& painter) && !_scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, _scrollBar)) ? _scrollBar->width() : 0); - getCharacterPosition( cursorPos , cursorLine , cursorColumn ); - Character cursorCharacter = _image[loc(cursorColumn,cursorLine)]; + getCharacterPosition(cursorPos, cursorLine, cursorColumn); + Character cursorCharacter = _image[loc(cursorColumn, cursorLine)]; - painter.setPen( QPen(cursorCharacter.foregroundColor.color(colorTable())) ); + painter.setPen(QPen(cursorCharacter.foregroundColor.color(colorTable()))); /***add begin by ut001121 zhangmeng 20200624 光标悬浮在链接上面时变成手形光标 修复BUG34676***/ bool bDrawLineForHotSpotLink = false; @@ -1493,60 +1450,58 @@ void TerminalDisplay::paintFilters(QPainter& painter) // iterate over hotspots identified by the display's currently active filters // and draw appropriate visuals to indicate the presence of the hotspot - QList spots = _filterChain->hotSpots(); - QListIterator iter(spots); - while (iter.hasNext()) - { - Filter::HotSpot* spot = iter.next(); + QList spots = _filterChain->hotSpots(); + QListIterator iter(spots); + while (iter.hasNext()) { + Filter::HotSpot *spot = iter.next(); QRegion region; - if ( spot->type() == Filter::HotSpot::Link ) { + if (spot->type() == Filter::HotSpot::Link) { QRect r; - if (spot->startLine()==spot->endLine()) { - r.setCoords( spot->startColumn()*_fontWidth + 1 + leftMargin, - spot->startLine()*_fontHeight + 1 + _topBaseMargin, - spot->endColumn()*_fontWidth - 1 + leftMargin, - (spot->endLine()+1)*_fontHeight - 1 + _topBaseMargin ); + if (spot->startLine() == spot->endLine()) { + r.setCoords(spot->startColumn()*_fontWidth + 1 + leftMargin, + spot->startLine()*_fontHeight + 1 + _topBaseMargin, + spot->endColumn()*_fontWidth - 1 + leftMargin, + (spot->endLine() + 1)*_fontHeight - 1 + _topBaseMargin); region |= r; } else { - r.setCoords( spot->startColumn()*_fontWidth + 1 + leftMargin, - spot->startLine()*_fontHeight + 1 + _topBaseMargin, - _columns*_fontWidth - 1 + leftMargin, - (spot->startLine()+1)*_fontHeight - 1 + _topBaseMargin ); + r.setCoords(spot->startColumn()*_fontWidth + 1 + leftMargin, + spot->startLine()*_fontHeight + 1 + _topBaseMargin, + _columns * _fontWidth - 1 + leftMargin, + (spot->startLine() + 1)*_fontHeight - 1 + _topBaseMargin); region |= r; - for ( int line = spot->startLine()+1 ; line < spot->endLine() ; line++ ) { - r.setCoords( 0*_fontWidth + 1 + leftMargin, - line*_fontHeight + 1 + _topBaseMargin, - _columns*_fontWidth - 1 + leftMargin, - (line+1)*_fontHeight - 1 + _topBaseMargin ); + for (int line = spot->startLine() + 1 ; line < spot->endLine() ; line++) { + r.setCoords(0 * _fontWidth + 1 + leftMargin, + line * _fontHeight + 1 + _topBaseMargin, + _columns * _fontWidth - 1 + leftMargin, + (line + 1)*_fontHeight - 1 + _topBaseMargin); region |= r; } - r.setCoords( 0*_fontWidth + 1 + leftMargin, - spot->endLine()*_fontHeight + 1 + _topBaseMargin, - spot->endColumn()*_fontWidth - 1 + leftMargin, - (spot->endLine()+1)*_fontHeight - 1 + _topBaseMargin ); + r.setCoords(0 * _fontWidth + 1 + leftMargin, + spot->endLine()*_fontHeight + 1 + _topBaseMargin, + spot->endColumn()*_fontWidth - 1 + leftMargin, + (spot->endLine() + 1)*_fontHeight - 1 + _topBaseMargin); region |= r; } } - for ( int line = spot->startLine() ; line <= spot->endLine() ; line++ ) - { + for (int line = spot->startLine() ; line <= spot->endLine() ; line++) { int startColumn = 0; - int endColumn = _columns-1; // TODO use number of _columns which are actually - // occupied on this line rather than the width of the - // display in _columns + int endColumn = _columns - 1; // TODO use number of _columns which are actually + // occupied on this line rather than the width of the + // display in _columns // ignore whitespace at the end of the lines - while ( QChar(_image[loc(endColumn,line)].character).isSpace() && endColumn > 0 ) + while (QChar(_image[loc(endColumn, line)].character).isSpace() && endColumn > 0) endColumn--; // increment here because the column which we want to set 'endColumn' to // is the first whitespace character at the end of the line endColumn++; - if ( line == spot->startLine() ) + if (line == spot->startLine()) startColumn = spot->startColumn(); - if ( line == spot->endLine() ) + if (line == spot->endLine()) endColumn = spot->endColumn(); // subtract one pixel from @@ -1559,13 +1514,12 @@ void TerminalDisplay::paintFilters(QPainter& painter) // because the check below for the position of the cursor // finds it on the border of the target area QRect r; - r.setCoords( startColumn*_fontWidth + 1 + leftMargin, - line*_fontHeight + 1 + _topBaseMargin, - endColumn*_fontWidth - 1 + leftMargin, - (line+1)*_fontHeight - 1 + _topBaseMargin ); + r.setCoords(startColumn * _fontWidth + 1 + leftMargin, + line * _fontHeight + 1 + _topBaseMargin, + endColumn * _fontWidth - 1 + leftMargin, + (line + 1)*_fontHeight - 1 + _topBaseMargin); // Underline link hotspots - if ( spot->type() == Filter::HotSpot::Link ) - { + if (spot->type() == Filter::HotSpot::Link) { QFontMetrics metrics(font()); // find the baseline (which is the invisible line that the characters in the font sit on, @@ -1573,31 +1527,29 @@ void TerminalDisplay::paintFilters(QPainter& painter) int baseline = r.bottom() - metrics.descent(); // find the position of the underline below that int underlinePos = baseline + metrics.underlinePos(); - if ( region.contains( mapFromGlobal(QCursor::pos()) ) ){ - painter.drawLine( r.left() , underlinePos , - r.right() , underlinePos ); + if (region.contains(mapFromGlobal(QCursor::pos()))) { + painter.drawLine(r.left(), underlinePos, + r.right(), underlinePos); /***add begin by ut001121 zhangmeng 20200624 光标悬浮在链接上面时变成手形光标 修复BUG34676***/ bDrawLineForHotSpotLink = true; } } // Marker hotspots simply have a transparent rectanglular shape // drawn on top of them - else if ( spot->type() == Filter::HotSpot::Marker ) - { - //TODO - Do not use a hardcoded colour for this - painter.fillRect(r,QBrush(QColor(255,0,0,120))); + else if (spot->type() == Filter::HotSpot::Marker) { + //TODO - Do not use a hardcoded colour for this + painter.fillRect(r, QBrush(QColor(255, 0, 0, 120))); } } } /***add begin by ut001121 zhangmeng 20200624 光标悬浮在链接上面时变成手形光标 修复BUG34676***/ /** modify by ut001121 zhangmeng 20201215 for 1040-4 Ctrl键+鼠标点击超链接打开网页 */ - if(bDrawLineForHotSpotLink && (QApplication::queryKeyboardModifiers() & Qt::ControlModifier)){ - if(cursor().shape() != Qt::PointingHandCursor) { - setCursor(Qt::PointingHandCursor); + if (bDrawLineForHotSpotLink && (QApplication::queryKeyboardModifiers() & Qt::ControlModifier)) { + if (cursor().shape() != Qt::PointingHandCursor) { + setCursor(Qt::PointingHandCursor); } - } - else if(cursor().shape() != Qt::IBeamCursor){ + } else if (cursor().shape() != Qt::IBeamCursor) { setCursor(Qt::IBeamCursor); } /***add end by ut001121***/ @@ -1605,29 +1557,31 @@ void TerminalDisplay::paintFilters(QPainter& painter) int TerminalDisplay::textWidth(const int startColumn, const int length, const int line) const { - QFontMetrics fm(font()); - int result = 0; - for (int column = 0; column < length; column++) { - result += fm.width(_image[loc(startColumn + column, line)].character); - } - return result; + QFontMetrics fm(font()); + int result = 0; + for (int column = 0; column < length; column++) { + result += fm.width(_image[loc(startColumn + column, line)].character); + } + return result; } -QRect TerminalDisplay::calculateTextArea(int topLeftX, int topLeftY, int startColumn, int line, int length) { - int left = _fixedFont ? _fontWidth * startColumn : textWidth(0, startColumn, line); - int top = _fontHeight * line; - int width = _fixedFont ? _fontWidth * length : textWidth(startColumn, length, line); - return {_leftMargin + topLeftX + left, - _topMargin + topLeftY + top, - width, - _fontHeight}; +QRect TerminalDisplay::calculateTextArea(int topLeftX, int topLeftY, int startColumn, int line, int length) +{ + int left = _fixedFont ? _fontWidth * startColumn : textWidth(0, startColumn, line); + int top = _fontHeight * line; + int width = _fixedFont ? _fontWidth * length : textWidth(startColumn, length, line); + return {_leftMargin + topLeftX + left, + _topMargin + topLeftY + top, + width, + _fontHeight}; } -static uint baseCodePoint(const Character &ch) { +static uint baseCodePoint(const Character &ch) +{ if (ch.rendition & RE_EXTENDED_CHAR) { // sequence of characters ushort extendedCharLength = 0; - const uint* chars = ExtendedCharTable::instance.lookupExtendedChar(ch.character, extendedCharLength); + const uint *chars = ExtendedCharTable::instance.lookupExtendedChar(ch.character, extendedCharLength); return chars[0]; } else { return ch.character; @@ -1657,7 +1611,7 @@ void TerminalDisplay::drawContents(QPainter &paint, const QRect &rect) if ((_image[loc(x, y)].rendition & RE_EXTENDED_CHAR) != 0) { // sequence of characters ushort extendedCharLength = 0; - const uint* chars = ExtendedCharTable::instance.lookupExtendedChar(_image[loc(x, y)].character, extendedCharLength); + const uint *chars = ExtendedCharTable::instance.lookupExtendedChar(_image[loc(x, y)].character, extendedCharLength); if (chars != nullptr) { Q_ASSERT(extendedCharLength > 1); bufferSize += extendedCharLength - 1; @@ -1687,11 +1641,11 @@ void TerminalDisplay::drawContents(QPainter &paint, const QRect &rect) const auto isInsideDrawArea = [&](int column) { return column <= rect.right(); }; const auto hasSameColors = [&](int column) { return _image[loc(column, y)].foregroundColor == currentForeground - && _image[loc(column, y)].backgroundColor == currentBackground; + && _image[loc(column, y)].backgroundColor == currentBackground; }; const auto hasSameRendition = [&](int column) { return (_image[loc(column, y)].rendition & ~RE_EXTENDED_CHAR) - == (currentRendition & ~RE_EXTENDED_CHAR); + == (currentRendition & ~RE_EXTENDED_CHAR); }; const auto hasSameWidth = [&](int column) { const int characterLoc = qMin(loc(column, y) + 1, _imageSize - 1); @@ -1699,12 +1653,12 @@ void TerminalDisplay::drawContents(QPainter &paint, const QRect &rect) }; const auto hasSameLineDrawStatus = [&](int column) { return canDraw(_image[loc(column, y)].character) - == lineDraw; + == lineDraw; }; const auto isSameScript = [&](int column) { const QChar::Script script = QChar::script(baseCodePoint(_image[loc(column, y)])); if (currentScript == QChar::Script_Common || script == QChar::Script_Common - || currentScript == QChar::Script_Inherited || script == QChar::Script_Inherited) { + || currentScript == QChar::Script_Inherited || script == QChar::Script_Inherited) { return true; } return currentScript == script; @@ -1717,14 +1671,14 @@ void TerminalDisplay::drawContents(QPainter &paint, const QRect &rect) if (canBeGrouped(x)) { while (isInsideDrawArea(x + len) && hasSameColors(x + len) - && hasSameRendition(x + len) && hasSameWidth(x + len) - && hasSameLineDrawStatus(x + len) && isSameScript(x + len) - && canBeGrouped(x + len)) { + && hasSameRendition(x + len) && hasSameWidth(x + len) + && hasSameLineDrawStatus(x + len) && isSameScript(x + len) + && canBeGrouped(x + len)) { const uint c = _image[loc(x + len, y)].character; if ((_image[loc(x + len, y)].rendition & RE_EXTENDED_CHAR) != 0) { // sequence of characters ushort extendedCharLength = 0; - const uint* chars = ExtendedCharTable::instance.lookupExtendedChar(c, extendedCharLength); + const uint *chars = ExtendedCharTable::instance.lookupExtendedChar(c, extendedCharLength); if (chars != nullptr) { Q_ASSERT(extendedCharLength > 1); bufferSize += extendedCharLength - 1; @@ -1832,23 +1786,23 @@ void TerminalDisplay::drawContents(QPainter &paint, const QRect &rect) void TerminalDisplay::blinkEvent() { - if (!_allowBlinkingText) return; + if (!_allowBlinkingText) return; - _blinking = !_blinking; + _blinking = !_blinking; - //TODO: Optimize to only repaint the areas of the widget - // where there is blinking text - // rather than repainting the whole widget. - update(); + //TODO: Optimize to only repaint the areas of the widget + // where there is blinking text + // rather than repainting the whole widget. + update(); } -QRect TerminalDisplay::imageToWidget(const QRect& imageArea) const +QRect TerminalDisplay::imageToWidget(const QRect &imageArea) const { QRect result; - result.setLeft( _leftMargin + _fontWidth * imageArea.left() ); - result.setTop( _topMargin + _fontHeight * imageArea.top() ); - result.setWidth( _fontWidth * imageArea.width() ); - result.setHeight( _fontHeight * imageArea.height() ); + result.setLeft(_leftMargin + _fontWidth * imageArea.left()); + result.setTop(_topMargin + _fontHeight * imageArea.top()); + result.setWidth(_fontWidth * imageArea.width()); + result.setHeight(_fontHeight * imageArea.height()); return result; } @@ -1856,23 +1810,23 @@ QRect TerminalDisplay::imageToWidget(const QRect& imageArea) const QRect TerminalDisplay::widgetToImage(const QRect &widgetArea) const { QRect result; - result.setLeft(qMin(_usedColumns - 1, qMax(0, (widgetArea.left()) / _fontWidth ))); - result.setTop(qMin(_usedLines - 1, qMax(0, (widgetArea.top()) / _fontHeight ))); - result.setRight(qMin(_usedColumns - 1, qMax(0, (widgetArea.right()) / _fontWidth ))); + result.setLeft(qMin(_usedColumns - 1, qMax(0, (widgetArea.left()) / _fontWidth))); + result.setTop(qMin(_usedLines - 1, qMax(0, (widgetArea.top()) / _fontHeight))); + result.setRight(qMin(_usedColumns - 1, qMax(0, (widgetArea.right()) / _fontWidth))); result.setBottom(qMin(_usedLines - 1, qMax(0, (widgetArea.bottom()) / _fontHeight))); return result; } void TerminalDisplay::updateCursor() { - QRect cursorRect = imageToWidget( QRect(cursorPosition(),QSize(1,1)) ); - update(cursorRect); + QRect cursorRect = imageToWidget(QRect(cursorPosition(), QSize(1, 1))); + update(cursorRect); } void TerminalDisplay::blinkCursorEvent() { - _cursorBlinking = !_cursorBlinking; - updateCursor(); + _cursorBlinking = !_cursorBlinking; + updateCursor(); } /* ------------------------------------------------------------------------- */ @@ -1881,61 +1835,57 @@ void TerminalDisplay::blinkCursorEvent() /* */ /* ------------------------------------------------------------------------- */ -void TerminalDisplay::resizeEvent(QResizeEvent*) +void TerminalDisplay::resizeEvent(QResizeEvent *) { - initKeyBoardSelection(); - updateImageSize(); - processFilters(); + initKeyBoardSelection(); + updateImageSize(); + processFilters(); } void TerminalDisplay::propagateSize() { - if (_isFixedSize) - { - setSize(_columns, _lines); - QWidget::setFixedSize(sizeHint()); - parentWidget()->adjustSize(); - parentWidget()->setFixedSize(parentWidget()->sizeHint()); - return; - } - if (_image) - updateImageSize(); + if (_isFixedSize) { + setSize(_columns, _lines); + QWidget::setFixedSize(sizeHint()); + parentWidget()->adjustSize(); + parentWidget()->setFixedSize(parentWidget()->sizeHint()); + return; + } + if (_image) + updateImageSize(); } void TerminalDisplay::updateImageSize() { - Character* oldimg = _image; - int oldlin = _lines; - int oldcol = _columns; + Character *oldimg = _image; + int oldlin = _lines; + int oldcol = _columns; - makeImage(); + makeImage(); - // copy the old image to reduce flicker - int lines = qMin(oldlin,_lines); - int columns = qMin(oldcol,_columns); + // copy the old image to reduce flicker + int lines = qMin(oldlin, _lines); + int columns = qMin(oldcol, _columns); - if (oldimg) - { - for (int line = 0; line < lines; line++) - { - memcpy((void*)&_image[_columns*line], - (void*)&oldimg[oldcol*line],columns*sizeof(Character)); + if (oldimg) { + for (int line = 0; line < lines; line++) { + memcpy((void *)&_image[_columns * line], + (void *)&oldimg[oldcol * line], columns * sizeof(Character)); + } + delete[] oldimg; } - delete[] oldimg; - } - if (_screenWindow) - _screenWindow->setWindowLines(_lines); + if (_screenWindow) + _screenWindow->setWindowLines(_lines); - _resizing = (oldlin!=_lines) || (oldcol!=_columns); + _resizing = (oldlin != _lines) || (oldcol != _columns); - if ( _resizing ) - { - showResizeNotification(); - emit changedContentSizeSignal(oldlin, oldcol); // expose resizeEvent - } + if (_resizing) { + showResizeNotification(); + emit changedContentSizeSignal(oldlin, oldcol); // expose resizeEvent + } - _resizing = false; + _resizing = false; } //showEvent and hideEvent are reimplemented here so that it appears to other classes that the @@ -1943,13 +1893,13 @@ void TerminalDisplay::updateImageSize() // //TODO: Perhaps it would be better to have separate signals for show and hide instead of using //the same signal as the one for a content size change -void TerminalDisplay::showEvent(QShowEvent*) +void TerminalDisplay::showEvent(QShowEvent *) { - emit changedContentSizeSignal(_contentHeight,_contentWidth); + emit changedContentSizeSignal(_contentHeight, _contentWidth); } -void TerminalDisplay::hideEvent(QHideEvent*) +void TerminalDisplay::hideEvent(QHideEvent *) { - emit changedContentSizeSignal(_contentHeight,_contentWidth); + emit changedContentSizeSignal(_contentHeight, _contentWidth); } /* ------------------------------------------------------------------------- */ @@ -1960,74 +1910,72 @@ void TerminalDisplay::hideEvent(QHideEvent*) void TerminalDisplay::scrollBarPositionChanged(int) { - if ( !_screenWindow ) - return; + if (!_screenWindow) + return; - _screenWindow->scrollTo( _scrollBar->value() ); + _screenWindow->scrollTo(_scrollBar->value()); - // if the thumb has been moved to the bottom of the _scrollBar then set - // the display to automatically track new output, - // that is, scroll down automatically - // to how new _lines as they are added - const bool atEndOfOutput = (_scrollBar->value() == _scrollBar->maximum()); - _screenWindow->setTrackOutput( atEndOfOutput ); + // if the thumb has been moved to the bottom of the _scrollBar then set + // the display to automatically track new output, + // that is, scroll down automatically + // to how new _lines as they are added + const bool atEndOfOutput = (_scrollBar->value() == _scrollBar->maximum()); + _screenWindow->setTrackOutput(atEndOfOutput); - updateImage(); + updateImage(); } void TerminalDisplay::setScroll(int cursor, int slines) { - // update _scrollBar if the range or value has changed, - // otherwise return - // - // setting the range or value of a _scrollBar will always trigger - // a repaint, so it should be avoided if it is not necessary - if ( _scrollBar->minimum() == 0 && - _scrollBar->maximum() == (slines - _lines) && - _scrollBar->value() == cursor ) - { + // update _scrollBar if the range or value has changed, + // otherwise return + // + // setting the range or value of a _scrollBar will always trigger + // a repaint, so it should be avoided if it is not necessary + if (_scrollBar->minimum() == 0 && + _scrollBar->maximum() == (slines - _lines) && + _scrollBar->value() == cursor) { return; - } + } - disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); - _scrollBar->setRange(0,slines - _lines); - _scrollBar->setSingleStep(1); - _scrollBar->setPageStep(_lines); - _scrollBar->setValue(cursor); - connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); + disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); + _scrollBar->setRange(0, slines - _lines); + _scrollBar->setSingleStep(1); + _scrollBar->setPageStep(_lines); + _scrollBar->setValue(cursor); + connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); } void TerminalDisplay::scrollToEnd() { - disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); - _scrollBar->setValue( _scrollBar->maximum() ); - connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); + disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); + _scrollBar->setValue(_scrollBar->maximum()); + connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); - _screenWindow->scrollTo( _scrollBar->value() + 1 ); - _screenWindow->setTrackOutput( _screenWindow->atEndOfOutput() ); + _screenWindow->scrollTo(_scrollBar->value() + 1); + _screenWindow->setTrackOutput(_screenWindow->atEndOfOutput()); } void TerminalDisplay::setScrollBarPosition(QTermWidget::ScrollBarPosition position) { - if (_scrollbarLocation == position) - return; + if (_scrollbarLocation == position) + return; - if ( position == QTermWidget::NoScrollBar ) - _scrollBar->hide(); - else - _scrollBar->show(); + if (position == QTermWidget::NoScrollBar) + _scrollBar->hide(); + else + _scrollBar->show(); - _topMargin = _leftMargin = 1; - _scrollbarLocation = position; + _topMargin = _leftMargin = 1; + _scrollbarLocation = position; - propagateSize(); - update(); + propagateSize(); + update(); } void TerminalDisplay::initSelectionStates() { - if (!_screenWindow) - { + if (!_screenWindow) { return; } @@ -2045,494 +1993,487 @@ void TerminalDisplay::initKeyBoardSelection() initSelectionStates(); } -void TerminalDisplay::mousePressEvent(QMouseEvent* ev) +void TerminalDisplay::mousePressEvent(QMouseEvent *ev) { - //判断有鼠标点击的时候,初始化键盘选择状态 - initKeyBoardSelection(); + //判断有鼠标点击的时候,初始化键盘选择状态 + initKeyBoardSelection(); - if ( _possibleTripleClick && (ev->button()==Qt::LeftButton) ) { - mouseTripleClickEvent(ev); - return; - } + if (_possibleTripleClick && (ev->button() == Qt::LeftButton)) { + mouseTripleClickEvent(ev); + return; + } - if ( !contentsRect().contains(ev->pos()) ) return; + if (!contentsRect().contains(ev->pos())) return; - if ( !_screenWindow ) return; + if (!_screenWindow) return; - int charLine; - int charColumn; - getCharacterPosition(ev->pos(),charLine,charColumn); - QPoint pos = QPoint(charColumn,charLine); + int charLine; + int charColumn; + getCharacterPosition(ev->pos(), charLine, charColumn); + QPoint pos = QPoint(charColumn, charLine); + + if (ev->button() == Qt::LeftButton) { + _lineSelectionMode = false; + _wordSelectionMode = false; + if (!hasFocus()) { + setFocus(); + } + emit leftMouseClick(); + emit isBusySelecting(true); // Keep it steady... + // Drag only when the Control key is hold + bool selected = false; + + // The receiver of the testIsSelected() signal will adjust + // 'selected' accordingly. + //emit testIsSelected(pos.x(), pos.y(), selected); + + selected = _screenWindow->isSelected(pos.x(), pos.y()); + + if (_cursorPositionSetEnable && (ev->modifiers() & Qt::ControlModifier)) { + int line; + int column; + getExactCharacterPosition(ev->pos(), line, column); + line -= cursorPosition().y(); + column -= cursorPosition().x(); + int count = 0; + count += line * _columns + column; + emit changedCursonPosition(count); + } - if ( ev->button() == Qt::LeftButton) - { - _lineSelectionMode = false; - _wordSelectionMode = false; - if(!hasFocus()) - { - setFocus(); - } - emit leftMouseClick(); - emit isBusySelecting(true); // Keep it steady... - // Drag only when the Control key is hold - bool selected = false; + if ((!_ctrlDrag || ev->modifiers() & Qt::ControlModifier) && selected) { + // The user clicked inside selected text + dragInfo.state = diPending; + dragInfo.start = ev->pos(); + } else { + // No reason to ever start a drag event + dragInfo.state = diNone; - // The receiver of the testIsSelected() signal will adjust - // 'selected' accordingly. - //emit testIsSelected(pos.x(), pos.y(), selected); + _preserveLineBreaks = !((ev->modifiers() & Qt::ControlModifier) && !(ev->modifiers() & Qt::AltModifier)); + _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier); - selected = _screenWindow->isSelected(pos.x(),pos.y()); + if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) { + _screenWindow->clearSelection(); - if ((!_ctrlDrag || ev->modifiers() & Qt::ControlModifier) && selected ) { - // The user clicked inside selected text - dragInfo.state = diPending; - dragInfo.start = ev->pos(); + //emit clearSelectionSignal(); + pos.ry() += _scrollBar->value(); + _iPntSel = _pntSel = pos; + _actSel = 1; // left mouse button pressed but nothing selected yet. + + } else { + emit mouseSignal(0, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum(), 0); + } + + Filter::HotSpot *spot = _filterChain->hotSpotAt(charLine, charColumn); + if (spot && spot->type() == Filter::HotSpot::Link) + spot->activate(QLatin1String("click-action")); + } + } else if (ev->button() == Qt::MidButton) { + if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) + emitSelection(true, ev->modifiers() & Qt::ControlModifier); + else + emit mouseSignal(1, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum(), 0); + } else if (ev->button() == Qt::RightButton) { + if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) + emit configureRequest(ev->pos()); + else + emit mouseSignal(2, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum(), 0); } - else { - // No reason to ever start a drag event - dragInfo.state = diNone; - - _preserveLineBreaks = !( ( ev->modifiers() & Qt::ControlModifier ) && !(ev->modifiers() & Qt::AltModifier) ); - _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier); - - if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) - { - _screenWindow->clearSelection(); - - //emit clearSelectionSignal(); - pos.ry() += _scrollBar->value(); - _iPntSel = _pntSel = pos; - _actSel = 1; // left mouse button pressed but nothing selected yet. - - } - else - { - emit mouseSignal( 0, charColumn + 1, charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0); - } - - Filter::HotSpot *spot = _filterChain->hotSpotAt(charLine, charColumn); - if (spot && spot->type() == Filter::HotSpot::Link) - spot->activate(QLatin1String("click-action")); - } - } - else if ( ev->button() == Qt::MidButton ) - { - if ( _mouseMarks || (ev->modifiers() & Qt::ShiftModifier) ) - emitSelection(true,ev->modifiers() & Qt::ControlModifier); - else - emit mouseSignal( 1, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0); - } - else if ( ev->button() == Qt::RightButton ) - { - if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) - emit configureRequest(ev->pos()); - else - emit mouseSignal( 2, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0); - } /******** Modify by m000714 daizhengwen 2020-04-28: 调用父类的QMousePressEvent****************/ QWidget::mousePressEvent(ev); /********************* Modify by m000714 daizhengwen End ************************/ } -QList TerminalDisplay::filterActions(const QPoint& position) +QList TerminalDisplay::filterActions(const QPoint &position) { - int charLine, charColumn; - getCharacterPosition(position,charLine,charColumn); + int charLine, charColumn; + getCharacterPosition(position, charLine, charColumn); - Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn); + Filter::HotSpot *spot = _filterChain->hotSpotAt(charLine, charColumn); - return spot ? spot->actions() : QList(); + return spot ? spot->actions() : QList(); } -void TerminalDisplay::mouseMoveEvent(QMouseEvent* ev) +void TerminalDisplay::mouseMoveEvent(QMouseEvent *ev) { - int charLine = 0; - int charColumn = 0; - int leftMargin = _leftBaseMargin - + ((_scrollbarLocation == QTermWidget::ScrollBarLeft - && !_scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, _scrollBar)) - ? _scrollBar->width() : 0); + int charLine = 0; + int charColumn = 0; + int leftMargin = _leftBaseMargin + + ((_scrollbarLocation == QTermWidget::ScrollBarLeft + && !_scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, _scrollBar)) + ? _scrollBar->width() : 0); - getCharacterPosition(ev->pos(),charLine,charColumn); + getCharacterPosition(ev->pos(), charLine, charColumn); - // handle filters - // change link hot-spot appearance on mouse-over - Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn); - if ( spot && spot->type() == Filter::HotSpot::Link) - { - QRegion previousHotspotArea = _mouseOverHotspotArea; - _mouseOverHotspotArea = QRegion(); - QRect r; - if (spot->startLine()==spot->endLine()) { - r.setCoords( spot->startColumn()*_fontWidth + leftMargin, - spot->startLine()*_fontHeight + _topBaseMargin, - spot->endColumn()*_fontWidth + leftMargin, - (spot->endLine()+1)*_fontHeight - 1 + _topBaseMargin ); - _mouseOverHotspotArea |= r; - } else { - r.setCoords( spot->startColumn()*_fontWidth + leftMargin, - spot->startLine()*_fontHeight + _topBaseMargin, - _columns*_fontWidth - 1 + leftMargin, - (spot->startLine()+1)*_fontHeight + _topBaseMargin ); - _mouseOverHotspotArea |= r; - for ( int line = spot->startLine()+1 ; line < spot->endLine() ; line++ ) { - r.setCoords( 0*_fontWidth + leftMargin, - line*_fontHeight + _topBaseMargin, - _columns*_fontWidth + leftMargin, - (line+1)*_fontHeight + _topBaseMargin ); + // handle filters + // change link hot-spot appearance on mouse-over + Filter::HotSpot *spot = _filterChain->hotSpotAt(charLine, charColumn); + if (spot && spot->type() == Filter::HotSpot::Link) { + QRegion previousHotspotArea = _mouseOverHotspotArea; + _mouseOverHotspotArea = QRegion(); + QRect r; + if (spot->startLine() == spot->endLine()) { + r.setCoords(spot->startColumn()*_fontWidth + leftMargin, + spot->startLine()*_fontHeight + _topBaseMargin, + spot->endColumn()*_fontWidth + leftMargin, + (spot->endLine() + 1)*_fontHeight - 1 + _topBaseMargin); + _mouseOverHotspotArea |= r; + } else { + r.setCoords(spot->startColumn()*_fontWidth + leftMargin, + spot->startLine()*_fontHeight + _topBaseMargin, + _columns * _fontWidth - 1 + leftMargin, + (spot->startLine() + 1)*_fontHeight + _topBaseMargin); + _mouseOverHotspotArea |= r; + for (int line = spot->startLine() + 1 ; line < spot->endLine() ; line++) { + r.setCoords(0 * _fontWidth + leftMargin, + line * _fontHeight + _topBaseMargin, + _columns * _fontWidth + leftMargin, + (line + 1)*_fontHeight + _topBaseMargin); + _mouseOverHotspotArea |= r; + } + r.setCoords(0 * _fontWidth + leftMargin, + spot->endLine()*_fontHeight + _topBaseMargin, + spot->endColumn()*_fontWidth + leftMargin, + (spot->endLine() + 1)*_fontHeight + _topBaseMargin); _mouseOverHotspotArea |= r; } - r.setCoords( 0*_fontWidth + leftMargin, - spot->endLine()*_fontHeight + _topBaseMargin, - spot->endColumn()*_fontWidth + leftMargin, - (spot->endLine()+1)*_fontHeight + _topBaseMargin ); - _mouseOverHotspotArea |= r; - } - - update( _mouseOverHotspotArea | previousHotspotArea ); - } - else if ( !_mouseOverHotspotArea.isEmpty() ) - { - update( _mouseOverHotspotArea ); + + update(_mouseOverHotspotArea | previousHotspotArea); + } else if (!_mouseOverHotspotArea.isEmpty()) { + update(_mouseOverHotspotArea); // set hotspot area to an invalid rectangle _mouseOverHotspotArea = QRegion(); - } - - // for auto-hiding the cursor, we need mouseTracking - if (ev->buttons() == Qt::NoButton ) return; - - // if the terminal is interested in mouse movements - // then emit a mouse movement signal, unless the shift - // key is being held down, which overrides this. - if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) - { - int button = 3; - if (ev->buttons() & Qt::LeftButton) - button = 0; - if (ev->buttons() & Qt::MidButton) - button = 1; - if (ev->buttons() & Qt::RightButton) - button = 2; - - - emit mouseSignal( button, - charColumn + 1, - charLine + 1 +_scrollBar->value() -_scrollBar->maximum(), - 1 ); - - return; - } - - if (dragInfo.state == diPending) - { - // we had a mouse down, but haven't confirmed a drag yet - // if the mouse has moved sufficiently, we will confirm + } -// int distance = KGlobalSettings::dndEventDelay(); - int distance = QApplication::startDragDistance(); - if ( ev->x() > dragInfo.start.x() + distance || ev->x() < dragInfo.start.x() - distance || - ev->y() > dragInfo.start.y() + distance || ev->y() < dragInfo.start.y() - distance) - { - // we've left the drag square, we can start a real drag operation now - emit isBusySelecting(false); // Ok.. we can breath again. + // for auto-hiding the cursor, we need mouseTracking + if (ev->buttons() == Qt::NoButton) return; + + // if the terminal is interested in mouse movements + // then emit a mouse movement signal, unless the shift + // key is being held down, which overrides this. + if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) { + int button = 3; + if (ev->buttons() & Qt::LeftButton) + button = 0; + if (ev->buttons() & Qt::MidButton) + button = 1; + if (ev->buttons() & Qt::RightButton) + button = 2; + + + emit mouseSignal(button, + charColumn + 1, + charLine + 1 + _scrollBar->value() - _scrollBar->maximum(), + 1); - _screenWindow->clearSelection(); - doDrag(); + return; } - return; - } - else if (dragInfo.state == diDragging) - { - // this isn't technically needed because mouseMoveEvent is suppressed during - // Qt drag operations, replaced by dragMoveEvent - return; - } - if (_actSel == 0) return; + if (dragInfo.state == diPending) { + // we had a mouse down, but haven't confirmed a drag yet + // if the mouse has moved sufficiently, we will confirm + +// int distance = KGlobalSettings::dndEventDelay(); + int distance = QApplication::startDragDistance(); + if (ev->x() > dragInfo.start.x() + distance || ev->x() < dragInfo.start.x() - distance || + ev->y() > dragInfo.start.y() + distance || ev->y() < dragInfo.start.y() - distance) { + // we've left the drag square, we can start a real drag operation now + emit isBusySelecting(false); // Ok.. we can breath again. + + _screenWindow->clearSelection(); + doDrag(); + } + return; + } else if (dragInfo.state == diDragging) { + // this isn't technically needed because mouseMoveEvent is suppressed during + // Qt drag operations, replaced by dragMoveEvent + return; + } - // don't extend selection while pasting - if (ev->buttons() & Qt::MidButton) return; + if (_actSel == 0) return; - extendSelection( ev->pos() ); +// don't extend selection while pasting + if (ev->buttons() & Qt::MidButton) return; + + extendSelection(ev->pos()); } -void TerminalDisplay::extendSelection( const QPoint& position ) +void TerminalDisplay::extendSelection(const QPoint &position) { - QPoint pos = position; + QPoint pos = position; - if ( !_screenWindow ) - return; + if (!_screenWindow) + return; - //if ( !contentsRect().contains(ev->pos()) ) return; - QPoint tL = contentsRect().topLeft(); - int tLx = tL.x(); - int tLy = tL.y(); - int scroll = _scrollBar->value(); + //if ( !contentsRect().contains(ev->pos()) ) return; + QPoint tL = contentsRect().topLeft(); + int tLx = tL.x(); + int tLy = tL.y(); + int scroll = _scrollBar->value(); - // we're in the process of moving the mouse with the left button pressed - // the mouse cursor will kept caught within the bounds of the text in - // this widget. + // we're in the process of moving the mouse with the left button pressed + // the mouse cursor will kept caught within the bounds of the text in + // this widget. - int linesBeyondWidget = 0; + int linesBeyondWidget = 0; - QRect textBounds(tLx + _leftMargin, + QRect textBounds(tLx + _leftMargin, tLy + _topMargin, - _usedColumns*_fontWidth-1, - _usedLines*_fontHeight-1); - - // Adjust position within text area bounds. - QPoint oldpos = pos; - - pos.setX( qBound(textBounds.left(),pos.x(),textBounds.right()) ); - pos.setY( qBound(textBounds.top(),pos.y(),textBounds.bottom()) ); - - if ( oldpos.y() > textBounds.bottom() ) - { - linesBeyondWidget = (oldpos.y()-textBounds.bottom()) / _fontHeight; - _scrollBar->setValue(_scrollBar->value()+linesBeyondWidget+1); // scrollforward - } - if ( oldpos.y() < textBounds.top() ) - { - linesBeyondWidget = (textBounds.top()-oldpos.y()) / _fontHeight; - _scrollBar->setValue(_scrollBar->value()-linesBeyondWidget-1); // history - } - - int charColumn = 0; - int charLine = 0; - getCharacterPosition(pos,charLine,charColumn); - - QPoint here = QPoint(charColumn,charLine); //QPoint((pos.x()-tLx-_leftMargin+(_fontWidth/2))/_fontWidth,(pos.y()-tLy-_topMargin)/_fontHeight); - QPoint ohere; - QPoint _iPntSelCorr = _iPntSel; - _iPntSelCorr.ry() -= _scrollBar->value(); - QPoint _pntSelCorr = _pntSel; - _pntSelCorr.ry() -= _scrollBar->value(); - bool swapping = false; - - if ( _wordSelectionMode ) - { - // Extend to word boundaries - int i; - QChar selClass; - - bool left_not_right = ( here.y() < _iPntSelCorr.y() || - ( here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x() ) ); - bool old_left_not_right = ( _pntSelCorr.y() < _iPntSelCorr.y() || - ( _pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x() ) ); - swapping = left_not_right != old_left_not_right; - - // Find left (left_not_right ? from here : from start) - QPoint left = left_not_right ? here : _iPntSelCorr; - i = loc(left.x(),left.y()); - if (i>=0 && i<=_imageSize) { - selClass = charClass(_image[i].character); - while ( ((left.x()>0) || (left.y()>0 && (_lineProperties[left.y()-1] & LINE_WRAPPED) )) - && charClass(_image[i-1].character) == selClass ) - { i--; if (left.x()>0) left.rx()--; else {left.rx()=_usedColumns-1; left.ry()--;} } - } - - // Find left (left_not_right ? from start : from here) - QPoint right = left_not_right ? _iPntSelCorr : here; - i = loc(right.x(),right.y()); - if (i>=0 && i<=_imageSize) { - selClass = charClass(_image[i].character); - while( ((right.x()<_usedColumns-1) || (right.y()<_usedLines-1 && (_lineProperties[right.y()] & LINE_WRAPPED) )) - && charClass(_image[i+1].character) == selClass ) - { i++; if (right.x()<_usedColumns-1) right.rx()++; else {right.rx()=0; right.ry()++; } } - } - - // Pick which is start (ohere) and which is extension (here) - if ( left_not_right ) - { - here = left; ohere = right; - } - else - { - here = right; ohere = left; - } - ohere.rx()++; - } - - if ( _lineSelectionMode ) - { - // Extend to complete line - bool above_not_below = ( here.y() < _iPntSelCorr.y() ); - - QPoint above = above_not_below ? here : _iPntSelCorr; - QPoint below = above_not_below ? _iPntSelCorr : here; - - while (above.y()>0 && (_lineProperties[above.y()-1] & LINE_WRAPPED) ) - above.ry()--; - while (below.y()<_usedLines-1 && (_lineProperties[below.y()] & LINE_WRAPPED) ) - below.ry()++; + _usedColumns * _fontWidth - 1, + _usedLines * _fontHeight - 1); + + // Adjust position within text area bounds. + QPoint oldpos = pos; + + pos.setX(qBound(textBounds.left(), pos.x(), textBounds.right())); + pos.setY(qBound(textBounds.top(), pos.y(), textBounds.bottom())); + + if (oldpos.y() > textBounds.bottom()) { + linesBeyondWidget = (oldpos.y() - textBounds.bottom()) / _fontHeight; + _scrollBar->setValue(_scrollBar->value() + linesBeyondWidget + 1); // scrollforward + } + if (oldpos.y() < textBounds.top()) { + linesBeyondWidget = (textBounds.top() - oldpos.y()) / _fontHeight; + _scrollBar->setValue(_scrollBar->value() - linesBeyondWidget - 1); // history + } + + int charColumn = 0; + int charLine = 0; + getCharacterPosition(pos, charLine, charColumn); + + QPoint here = QPoint(charColumn, charLine); //QPoint((pos.x()-tLx-_leftMargin+(_fontWidth/2))/_fontWidth,(pos.y()-tLy-_topMargin)/_fontHeight); + QPoint ohere; + QPoint _iPntSelCorr = _iPntSel; + _iPntSelCorr.ry() -= _scrollBar->value(); + QPoint _pntSelCorr = _pntSel; + _pntSelCorr.ry() -= _scrollBar->value(); + bool swapping = false; + + if (_wordSelectionMode) { + // Extend to word boundaries + int i; + QChar selClass; + + bool left_not_right = (here.y() < _iPntSelCorr.y() || + (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x())); + bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() || + (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x())); + swapping = left_not_right != old_left_not_right; + + // Find left (left_not_right ? from here : from start) + QPoint left = left_not_right ? here : _iPntSelCorr; + i = loc(left.x(), left.y()); + if (i >= 0 && i <= _imageSize) { + selClass = charClass(_image[i].character); + while (((left.x() > 0) || (left.y() > 0 && (_lineProperties[left.y() - 1] & LINE_WRAPPED))) + && charClass(_image[i - 1].character) == selClass) + { i--; if (left.x() > 0) left.rx()--; else {left.rx() = _usedColumns - 1; left.ry()--;} } + } - above.setX(0); - below.setX(_usedColumns-1); + // Find left (left_not_right ? from start : from here) + QPoint right = left_not_right ? _iPntSelCorr : here; + i = loc(right.x(), right.y()); + if (i >= 0 && i <= _imageSize) { + selClass = charClass(_image[i].character); + while (((right.x() < _usedColumns - 1) || (right.y() < _usedLines - 1 && (_lineProperties[right.y()] & LINE_WRAPPED))) + && charClass(_image[i + 1].character) == selClass) + { i++; if (right.x() < _usedColumns - 1) right.rx()++; else {right.rx() = 0; right.ry()++; } } + } - // Pick which is start (ohere) and which is extension (here) - if ( above_not_below ) - { - here = above; ohere = below; - } - else - { - here = below; ohere = above; + // Pick which is start (ohere) and which is extension (here) + if (left_not_right) { + here = left; ohere = right; + } else { + here = right; ohere = left; + } + ohere.rx()++; } - QPoint newSelBegin = QPoint( ohere.x(), ohere.y() ); - swapping = !(_tripleSelBegin==newSelBegin); - _tripleSelBegin = newSelBegin; + if (_lineSelectionMode) { + // Extend to complete line + bool above_not_below = (here.y() < _iPntSelCorr.y()); - ohere.rx()++; - } + QPoint above = above_not_below ? here : _iPntSelCorr; + QPoint below = above_not_below ? _iPntSelCorr : here; - int offset = 0; - if ( !_wordSelectionMode && !_lineSelectionMode ) - { - QChar selClass; + while (above.y() > 0 && (_lineProperties[above.y() - 1] & LINE_WRAPPED)) + above.ry()--; + while (below.y() < _usedLines - 1 && (_lineProperties[below.y()] & LINE_WRAPPED)) + below.ry()++; - bool left_not_right = ( here.y() < _iPntSelCorr.y() || - ( here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x() ) ); - bool old_left_not_right = ( _pntSelCorr.y() < _iPntSelCorr.y() || - ( _pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x() ) ); - swapping = left_not_right != old_left_not_right; + above.setX(0); + below.setX(_usedColumns - 1); - // Find left (left_not_right ? from here : from start) - QPoint left = left_not_right ? here : _iPntSelCorr; + // Pick which is start (ohere) and which is extension (here) + if (above_not_below) { + here = above; ohere = below; + } else { + here = below; ohere = above; + } - // Find left (left_not_right ? from start : from here) - QPoint right = left_not_right ? _iPntSelCorr : here; - if ( right.x() > 0 && !_columnSelectionMode ) - { - int i = loc(right.x(),right.y()); - if (i>=0 && i<=_imageSize) { - selClass = charClass(_image[i-1].character); - /* if (selClass == ' ') - { - while ( right.x() < _usedColumns-1 && charClass(_image[i+1].character) == selClass && (right.y()<_usedLines-1) && - !(_lineProperties[right.y()] & LINE_WRAPPED)) - { i++; right.rx()++; } - if (right.x() < _usedColumns-1) - right = left_not_right ? _iPntSelCorr : here; - else - right.rx()++; // will be balanced later because of offset=-1; - }*/ - } - } - - // Pick which is start (ohere) and which is extension (here) - if ( left_not_right ) - { - here = left; ohere = right; offset = 0; - } - else - { - here = right; ohere = left; offset = -1; + QPoint newSelBegin = QPoint(ohere.x(), ohere.y()); + swapping = !(_tripleSelBegin == newSelBegin); + _tripleSelBegin = newSelBegin; + + ohere.rx()++; + } + + int offset = 0; + if (!_wordSelectionMode && !_lineSelectionMode) { + QChar selClass; + + bool left_not_right = (here.y() < _iPntSelCorr.y() || + (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x())); + bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() || + (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x())); + swapping = left_not_right != old_left_not_right; + + // Find left (left_not_right ? from here : from start) + QPoint left = left_not_right ? here : _iPntSelCorr; + + // Find left (left_not_right ? from start : from here) + QPoint right = left_not_right ? _iPntSelCorr : here; + if (right.x() > 0 && !_columnSelectionMode) { + int i = loc(right.x(), right.y()); + if (i >= 0 && i <= _imageSize) { + selClass = charClass(_image[i - 1].character); + /* if (selClass == ' ') + { + while ( right.x() < _usedColumns-1 && charClass(_image[i+1].character) == selClass && (right.y()<_usedLines-1) && + !(_lineProperties[right.y()] & LINE_WRAPPED)) + { i++; right.rx()++; } + if (right.x() < _usedColumns-1) + right = left_not_right ? _iPntSelCorr : here; + else + right.rx()++; // will be balanced later because of offset=-1; + }*/ + } + } + + // Pick which is start (ohere) and which is extension (here) + if (left_not_right) { + here = left; ohere = right; offset = 0; + } else { + here = right; ohere = left; offset = -1; + } } - } - if ((here == _pntSelCorr) && (scroll == _scrollBar->value())) return; // not moved + if ((here == _pntSelCorr) && (scroll == _scrollBar->value())) return; // not moved - if (here == ohere) return; // It's not left, it's not right. + if (here == ohere) return; // It's not left, it's not right. - if ( _actSel < 2 || swapping ) - { - if ( _columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode ) - { - _screenWindow->setSelectionStart( ohere.x() , ohere.y() , true ); - } - else - { - _screenWindow->setSelectionStart( ohere.x()-1-offset , ohere.y() , false ); - } + if (_actSel < 2 || swapping) { + if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) { + _screenWindow->setSelectionStart(ohere.x(), ohere.y(), true); + } else { + _screenWindow->setSelectionStart(ohere.x() - 1 - offset, ohere.y(), false); + } - } + } - _actSel = 2; // within selection - _pntSel = here; - _pntSel.ry() += _scrollBar->value(); + _actSel = 2; // within selection + _pntSel = here; + _pntSel.ry() += _scrollBar->value(); - if ( _columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode ) - { - _screenWindow->setSelectionEnd( here.x() , here.y() ); - } - else - { - _screenWindow->setSelectionEnd( here.x()+offset , here.y() ); - } + if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) { + _screenWindow->setSelectionEnd(here.x(), here.y()); + } else { + _screenWindow->setSelectionEnd(here.x() + offset, here.y()); + } } -void TerminalDisplay::mouseReleaseEvent(QMouseEvent* ev) +void TerminalDisplay::mouseReleaseEvent(QMouseEvent *ev) { - if ( !_screenWindow ) + if (!_screenWindow) return; int charLine; int charColumn; - getCharacterPosition(ev->pos(),charLine,charColumn); + getCharacterPosition(ev->pos(), charLine, charColumn); + + if (ev->button() == Qt::LeftButton) { + emit isBusySelecting(false); + if (dragInfo.state == diPending) { + // We had a drag event pending but never confirmed. Kill selection + _screenWindow->clearSelection(); + //emit clearSelectionSignal(); + } else { + if (_actSel > 1) { + setSelection(_screenWindow->selectedText(currentDecodingOptions())); + } - if ( ev->button() == Qt::LeftButton) - { - emit isBusySelecting(false); - if(dragInfo.state == diPending) - { - // We had a drag event pending but never confirmed. Kill selection - _screenWindow->clearSelection(); - //emit clearSelectionSignal(); + _actSel = 0; + + //FIXME: emits a release event even if the mouse is + // outside the range. The procedure used in `mouseMoveEvent' + // applies here, too. + + if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) + emit mouseSignal(0, + charColumn + 1, + charLine + 1 + _scrollBar->value() - _scrollBar->maximum(), 2); + } + dragInfo.state = diNone; } - else - { - if ( _actSel > 1 ) - { - setSelection( _screenWindow->selectedText(currentDecodingOptions()) ); - } - _actSel = 0; - //FIXME: emits a release event even if the mouse is - // outside the range. The procedure used in `mouseMoveEvent' - // applies here, too. + if (!_mouseMarks && + ((ev->button() == Qt::RightButton && !(ev->modifiers() & Qt::ShiftModifier)) + || ev->button() == Qt::MidButton)) { + emit mouseSignal(ev->button() == Qt::MidButton ? 1 : 2, + charColumn + 1, + charLine + 1 + _scrollBar->value() - _scrollBar->maximum(), + 2); + } +} + +void TerminalDisplay::getCharacterPosition(const QPoint &widgetPoint, int &line, int &column) const +{ + line = (widgetPoint.y() - contentsRect().top() - _topMargin) / _fontHeight; + if (line < 0) + line = 0; + if (line >= _usedLines) + line = _usedLines - 1; - if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) - emit mouseSignal( 0, - charColumn + 1, - charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 2); + int x = widgetPoint.x() + _fontWidth / 2 - contentsRect().left() - _leftMargin; + if (_fixedFont) + column = x / _fontWidth; + else { + column = 0; + while (column + 1 < _usedColumns && x > textWidth(0, column + 1, line)) + column++; } - dragInfo.state = diNone; - } + if (column < 0) + column = 0; - if ( !_mouseMarks && - ((ev->button() == Qt::RightButton && !(ev->modifiers() & Qt::ShiftModifier)) - || ev->button() == Qt::MidButton) ) - { - emit mouseSignal( ev->button() == Qt::MidButton ? 1 : 2, - charColumn + 1, - charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , - 2); - } + // the column value returned can be equal to _usedColumns, which + // is the position just after the last character displayed in a line. + // + // this is required so that the user can select characters in the right-most + // column (or left-most for right-to-left input) + if (column > _usedColumns) + column = _usedColumns; } -void TerminalDisplay::getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const +void TerminalDisplay::getExactCharacterPosition(const QPoint &widgetPoint, int &line, int &column) const { - line = (widgetPoint.y()-contentsRect().top()-_topMargin) / _fontHeight; + line = (widgetPoint.y() - contentsRect().top() - _topMargin) / _fontHeight; if (line < 0) line = 0; if (line >= _usedLines) line = _usedLines - 1; - int x = widgetPoint.x() + _fontWidth / 2 - contentsRect().left() - _leftMargin; - if ( _fixedFont ) + int x = widgetPoint.x() - contentsRect().left() - _leftMargin; + if (_fixedFont) column = x / _fontWidth; - else - { + else { column = 0; - while(column + 1 < _usedColumns && x > textWidth(0, column + 1, line)) + while (column + 1 < _usedColumns && x > textWidth(0, column + 1, line)) column++; } - if ( column < 0 ) + if (column < 0) column = 0; // the column value returned can be equal to _usedColumns, which @@ -2540,7 +2481,7 @@ void TerminalDisplay::getCharacterPosition(const QPoint& widgetPoint,int& line,i // // this is required so that the user can select characters in the right-most // column (or left-most for right-to-left input) - if ( column > _usedColumns ) + if (column > _usedColumns) column = _usedColumns; } @@ -2558,7 +2499,7 @@ void TerminalDisplay::setSessionId(int sessionId) void TerminalDisplay::updateFilters() { - if ( !_screenWindow ) + if (!_screenWindow) return; processFilters(); @@ -2566,103 +2507,98 @@ void TerminalDisplay::updateFilters() void TerminalDisplay::updateLineProperties() { - if ( !_screenWindow ) + if (!_screenWindow) return; _lineProperties = _screenWindow->getLineProperties(); } -void TerminalDisplay::mouseDoubleClickEvent(QMouseEvent* ev) +void TerminalDisplay::mouseDoubleClickEvent(QMouseEvent *ev) { - if ( ev->button() != Qt::LeftButton) return; - if ( !_screenWindow ) return; + if (ev->button() != Qt::LeftButton) return; + if (!_screenWindow) return; - int charLine = 0; - int charColumn = 0; + int charLine = 0; + int charColumn = 0; - getCharacterPosition(ev->pos(),charLine,charColumn); + getCharacterPosition(ev->pos(), charLine, charColumn); - QPoint pos(charColumn,charLine); + QPoint pos(charColumn, charLine); - // pass on double click as two clicks. - if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) - { - // Send just _ONE_ click event, since the first click of the double click - // was already sent by the click handler - emit mouseSignal( 0, - pos.x()+1, - pos.y()+1 +_scrollBar->value() -_scrollBar->maximum(), - 0 ); // left button - return; - } - - _screenWindow->clearSelection(); - QPoint bgnSel = pos; - QPoint endSel = pos; - int i = loc(bgnSel.x(),bgnSel.y()); - _iPntSel = bgnSel; - _iPntSel.ry() += _scrollBar->value(); + // pass on double click as two clicks. + if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) { + // Send just _ONE_ click event, since the first click of the double click + // was already sent by the click handler + emit mouseSignal(0, + pos.x() + 1, + pos.y() + 1 + _scrollBar->value() - _scrollBar->maximum(), + 0); // left button + return; + } - _wordSelectionMode = true; + _screenWindow->clearSelection(); + QPoint bgnSel = pos; + QPoint endSel = pos; + int i = loc(bgnSel.x(), bgnSel.y()); + _iPntSel = bgnSel; + _iPntSel.ry() += _scrollBar->value(); - // find word boundaries... - QChar selClass = charClass(_image[i].character); - { - // find the start of the word - int x = bgnSel.x(); - while ( ((x>0) || (bgnSel.y()>0 && (_lineProperties[bgnSel.y()-1] & LINE_WRAPPED) )) - && charClass(_image[i-1].character) == selClass ) - { - i--; - if (x>0) - x--; - else - { - x=_usedColumns-1; - bgnSel.ry()--; - } - } + _wordSelectionMode = true; - bgnSel.setX(x); - _screenWindow->setSelectionStart( bgnSel.x() , bgnSel.y() , false ); + // find word boundaries... + QChar selClass = charClass(_image[i].character); + { + // find the start of the word + int x = bgnSel.x(); + while (((x > 0) || (bgnSel.y() > 0 && (_lineProperties[bgnSel.y() - 1] & LINE_WRAPPED))) + && charClass(_image[i - 1].character) == selClass) { + i--; + if (x > 0) + x--; + else { + x = _usedColumns - 1; + bgnSel.ry()--; + } + } - // find the end of the word - i = loc( endSel.x(), endSel.y() ); - x = endSel.x(); - while( ((x<_usedColumns-1) || (endSel.y()<_usedLines-1 && (_lineProperties[endSel.y()] & LINE_WRAPPED) )) - && charClass(_image[i+1].character) == selClass ) - { - i++; - if (x<_usedColumns-1) - x++; - else - { - x=0; - endSel.ry()++; - } - } + bgnSel.setX(x); + _screenWindow->setSelectionStart(bgnSel.x(), bgnSel.y(), false); + + // find the end of the word + i = loc(endSel.x(), endSel.y()); + x = endSel.x(); + while (((x < _usedColumns - 1) || (endSel.y() < _usedLines - 1 && (_lineProperties[endSel.y()] & LINE_WRAPPED))) + && charClass(_image[i + 1].character) == selClass) { + i++; + if (x < _usedColumns - 1) + x++; + else { + x = 0; + endSel.ry()++; + } + } - endSel.setX(x); + endSel.setX(x); - // In word selection mode don't select @ (64) if at end of word. - if ( ( QChar( _image[i].character ) == QLatin1Char('@') ) && ( ( endSel.x() - bgnSel.x() ) > 0 ) ) - endSel.setX( x - 1 ); + // In word selection mode don't select @ (64) if at end of word. + if ((QChar(_image[i].character) == QLatin1Char('@')) && ((endSel.x() - bgnSel.x()) > 0)) + endSel.setX(x - 1); - _actSel = 2; // within selection + _actSel = 2; // within selection - _screenWindow->setSelectionEnd( endSel.x() , endSel.y() ); + _screenWindow->setSelectionEnd(endSel.x(), endSel.y()); - setSelection( _screenWindow->selectedText(currentDecodingOptions()) ); - } + setSelection(_screenWindow->selectedText(currentDecodingOptions())); + } - _possibleTripleClick=true; + _possibleTripleClick = true; - QTimer::singleShot(QApplication::doubleClickInterval(),this, - SLOT(tripleClickTimeout())); + QTimer::singleShot(QApplication::doubleClickInterval(), this, + SLOT(tripleClickTimeout())); } -void TerminalDisplay::wheelEvent( QWheelEvent* ev ) +void TerminalDisplay::wheelEvent(QWheelEvent *ev) { // 当前窗口被激活,且有焦点,不处理Ctrl+滚轮事件 if (isActiveWindow() && hasFocus()) { @@ -2682,10 +2618,9 @@ void TerminalDisplay::wheelEvent( QWheelEvent* ev ) // or otherwise send simulated up / down key presses to the terminal program // for the benefit of programs such as 'less' - if ( _mouseMarks && _scrollBar->maximum() > 0) - { + if (_mouseMarks && _scrollBar->maximum() > 0) { _scrollBar->event(ev); - } else if(_mouseMarks && !SessionManager::instance()->idToSession(_sessionId)->isPrimaryScreen() && _alternateScrolling) { + } else if (_mouseMarks && !SessionManager::instance()->idToSession(_sessionId)->isPrimaryScreen() && _alternateScrolling) { // assume that each Up / Down key event will cause the terminal application // to scroll by one line. // @@ -2698,27 +2633,27 @@ void TerminalDisplay::wheelEvent( QWheelEvent* ev ) int wheelDegrees = ev->delta() / 8; int linesToScroll = abs(wheelDegrees) / 5; - QKeyEvent keyScrollEvent(QEvent::KeyPress,key,Qt::NoModifier); + QKeyEvent keyScrollEvent(QEvent::KeyPress, key, Qt::NoModifier); - for (int i=0;ipos() , charLine , charColumn ); + getCharacterPosition(ev->pos(), charLine, charColumn); - emit mouseSignal( ev->delta() > 0 ? 4 : 5, - charColumn + 1, - charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , - 0); + emit mouseSignal(ev->delta() > 0 ? 4 : 5, + charColumn + 1, + charLine + 1 + _scrollBar->value() - _scrollBar->maximum(), + 0); } } void TerminalDisplay::tripleClickTimeout() { - _possibleTripleClick=false; + _possibleTripleClick = false; } Screen::DecodingOptions TerminalDisplay::currentDecodingOptions() @@ -2731,86 +2666,83 @@ Screen::DecodingOptions TerminalDisplay::currentDecodingOptions() return decodingOptions; } -void TerminalDisplay::mouseTripleClickEvent(QMouseEvent* ev) +void TerminalDisplay::mouseTripleClickEvent(QMouseEvent *ev) { - if ( !_screenWindow ) return; - - int charLine; - int charColumn; - getCharacterPosition(ev->pos(),charLine,charColumn); - _iPntSel = QPoint(charColumn,charLine); + if (!_screenWindow) return; - _screenWindow->clearSelection(); - - _lineSelectionMode = true; - _wordSelectionMode = false; + int charLine; + int charColumn; + getCharacterPosition(ev->pos(), charLine, charColumn); + _iPntSel = QPoint(charColumn, charLine); - _actSel = 2; // within selection - emit isBusySelecting(true); // Keep it steady... + _screenWindow->clearSelection(); - while (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) ) - _iPntSel.ry()--; + _lineSelectionMode = true; + _wordSelectionMode = false; - if (_tripleClickMode == SelectForwardsFromCursor) { - // find word boundary start - int i = loc(_iPntSel.x(),_iPntSel.y()); - QChar selClass = charClass(_image[i].character); - int x = _iPntSel.x(); + _actSel = 2; // within selection + emit isBusySelecting(true); // Keep it steady... - while ( ((x>0) || - (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) ) - ) - && charClass(_image[i-1].character) == selClass ) - { - i--; - if (x>0) - x--; - else - { - x=_columns-1; - _iPntSel.ry()--; + while (_iPntSel.y() > 0 && (_lineProperties[_iPntSel.y() - 1] & LINE_WRAPPED)) + _iPntSel.ry()--; + + if (_tripleClickMode == SelectForwardsFromCursor) { + // find word boundary start + int i = loc(_iPntSel.x(), _iPntSel.y()); + QChar selClass = charClass(_image[i].character); + int x = _iPntSel.x(); + + while (((x > 0) || + (_iPntSel.y() > 0 && (_lineProperties[_iPntSel.y() - 1] & LINE_WRAPPED)) + ) + && charClass(_image[i - 1].character) == selClass) { + i--; + if (x > 0) + x--; + else { + x = _columns - 1; + _iPntSel.ry()--; + } } - } - _screenWindow->setSelectionStart( x , _iPntSel.y() , false ); - _tripleSelBegin = QPoint( x, _iPntSel.y() ); - } - else if (_tripleClickMode == SelectWholeLine) { - _screenWindow->setSelectionStart( 0 , _iPntSel.y() , false ); - _tripleSelBegin = QPoint( 0, _iPntSel.y() ); - } + _screenWindow->setSelectionStart(x, _iPntSel.y(), false); + _tripleSelBegin = QPoint(x, _iPntSel.y()); + } else if (_tripleClickMode == SelectWholeLine) { + _screenWindow->setSelectionStart(0, _iPntSel.y(), false); + _tripleSelBegin = QPoint(0, _iPntSel.y()); + } - while (_iPntSel.y()<_lines-1 && (_lineProperties[_iPntSel.y()] & LINE_WRAPPED) ) - _iPntSel.ry()++; + while (_iPntSel.y() < _lines - 1 && (_lineProperties[_iPntSel.y()] & LINE_WRAPPED)) + _iPntSel.ry()++; - _screenWindow->setSelectionEnd( _columns - 1 , _iPntSel.y() ); + _screenWindow->setSelectionEnd(_columns - 1, _iPntSel.y()); - setSelection(_screenWindow->selectedText(currentDecodingOptions())); + setSelection(_screenWindow->selectedText(currentDecodingOptions())); - _iPntSel.ry() += _scrollBar->value(); + _iPntSel.ry() += _scrollBar->value(); } -bool TerminalDisplay::focusNextPrevChild( bool next ) +bool TerminalDisplay::focusNextPrevChild(bool next) { - if (next) - return false; // This disables changing the active part in konqueror - // when pressing Tab - return QWidget::focusNextPrevChild( next ); + if (next) + return false; // This disables changing the active part in konqueror + // when pressing Tab + return QWidget::focusNextPrevChild(next); } QChar TerminalDisplay::charClass(QChar qch) const { - if ( qch.isSpace() ) return QLatin1Char(' '); + if (qch.isSpace()) return QLatin1Char(' '); - if ( qch.isLetterOrNumber() || _wordCharacters.contains(qch, Qt::CaseInsensitive ) ) - return QLatin1Char('a'); + if (qch.isLetterOrNumber() || _wordCharacters.contains(qch, Qt::CaseInsensitive)) + return QLatin1Char('a'); return qch; } -void TerminalDisplay::setWordCharacters(const QString& wc) +void TerminalDisplay::setWordCharacters(const QString &wc) { _wordCharacters = wc; } @@ -2819,7 +2751,7 @@ void TerminalDisplay::setUsesMouse(bool on) { if (_mouseMarks != on) { _mouseMarks = on; - setCursor( _mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor ); + setCursor(_mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor); emit usesMouseChanged(); } } @@ -2851,41 +2783,38 @@ bool TerminalDisplay::bracketedPasteMode() const #undef KeyPress -void TerminalDisplay::emitSelection(bool useXselection,bool appendReturn) +void TerminalDisplay::emitSelection(bool useXselection, bool appendReturn) { - if ( !_screenWindow ) - return; + if (!_screenWindow) + return; - // Paste Clipboard by simulating keypress events - QString text = QApplication::clipboard()->text(useXselection ? QClipboard::Selection : - QClipboard::Clipboard); - if(appendReturn) - text.append(QLatin1Char('\r')); - if ( ! text.isEmpty() ) - { - text.replace(QLatin1Char('\n'), QLatin1Char('\r')); - bracketText(text); - QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text); - emit keyPressedSignal(&e); // expose as a big fat keypress event + // Paste Clipboard by simulating keypress events + QString text = QApplication::clipboard()->text(useXselection ? QClipboard::Selection : + QClipboard::Clipboard); + if (appendReturn) + text.append(QLatin1Char('\r')); + if (! text.isEmpty()) { + text.replace(QLatin1Char('\n'), QLatin1Char('\r')); + bracketText(text); + QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text); + emit keyPressedSignal(&e); // expose as a big fat keypress event - _screenWindow->clearSelection(); - } + _screenWindow->clearSelection(); + } } -void TerminalDisplay::bracketText(QString& text) +void TerminalDisplay::bracketText(QString &text) { - if (bracketedPasteMode()) - { + if (bracketedPasteMode()) { text.prepend(QLatin1String("\033[200~")); text.append(QLatin1String("\033[201~")); } } -void TerminalDisplay::setSelection(const QString& t) +void TerminalDisplay::setSelection(const QString &t) { /******** Modify by n014361 wangpeili 2020-02-12: 自动拷贝功能,需发出可拷贝信号***********×****/ - if(t != QApplication::clipboard()->text(QClipboard::Clipboard)) - { + if (t != QApplication::clipboard()->text(QClipboard::Clipboard)) { selectionChanged(); } QApplication::clipboard()->setText(t, QClipboard::Selection); @@ -2905,22 +2834,22 @@ void TerminalDisplay::setSelectionAll() void TerminalDisplay::copyClipboard() { - if ( !_screenWindow ) - return; + if (!_screenWindow) + return; - QString text = _screenWindow->selectedText(currentDecodingOptions()); - if (!text.isEmpty()) - QApplication::clipboard()->setText(text); + QString text = _screenWindow->selectedText(currentDecodingOptions()); + if (!text.isEmpty()) + QApplication::clipboard()->setText(text); } void TerminalDisplay::pasteClipboard() { - emitSelection(false,false); + emitSelection(false, false); } void TerminalDisplay::pasteSelection() { - emitSelection(true,false); + emitSelection(true, false); } /* ------------------------------------------------------------------------- */ @@ -2929,7 +2858,7 @@ void TerminalDisplay::pasteSelection() /* */ /* ------------------------------------------------------------------------- */ -void TerminalDisplay::setFlowControlWarningEnabled( bool enable ) +void TerminalDisplay::setFlowControlWarningEnabled(bool enable) { _flowControlWarningEnabled = enable; @@ -2953,90 +2882,71 @@ int TerminalDisplay::motionAfterPasting() void TerminalDisplay::checkAndInitSelectionState() { if (_selStartColumn != _screenWindow->cursorPosition().x() - || _selStartLine != _screenWindow->cursorPosition().y() ) - { + || _selStartLine != _screenWindow->cursorPosition().y()) { qDebug() << "checkAndInitSelectionState!" << endl; initKeyBoardSelection(); } } -void TerminalDisplay::keyPressEvent( QKeyEvent* event ) +void TerminalDisplay::keyPressEvent(QKeyEvent *event) { bool emitKeyPressSignal = true; // Keyboard-based navigation - if ( event->modifiers() == Qt::ShiftModifier ) - { + if (event->modifiers() == Qt::ShiftModifier) { bool update = true; //列的index从0开始,所以最大index需要减1 int maxColumnIndex = _screenWindow->windowColumns() - 1; - if ( event->key() == Qt::Key_PageUp ) - { - if (_scrollBar->value() != _scrollBar->maximum()) - { + if (event->key() == Qt::Key_PageUp) { + if (_scrollBar->value() != _scrollBar->maximum()) { initKeyBoardSelection(); } - _screenWindow->scrollBy( ScreenWindow::ScrollPages , -1 ); - } - else if ( event->key() == Qt::Key_PageDown ) - { - if (_scrollBar->value() != _scrollBar->maximum()) - { + _screenWindow->scrollBy(ScreenWindow::ScrollPages, -1); + } else if (event->key() == Qt::Key_PageDown) { + if (_scrollBar->value() != _scrollBar->maximum()) { initKeyBoardSelection(); } - _screenWindow->scrollBy( ScreenWindow::ScrollPages , 1 ); - } - else if ( event->key() == Qt::Key_Left ) - { - if (!_selBegin) - { + _screenWindow->scrollBy(ScreenWindow::ScrollPages, 1); + } else if (event->key() == Qt::Key_Left) { + if (!_selBegin) { checkAndInitSelectionState(); _selBegin = true; //键盘按下时设置--开始选择 //判断只有开始结束选择位置相等时,才允许开始选择 - if (_selStartLine == _selEndLine && _selStartColumn == _selEndColumn) - { + if (_selStartLine == _selEndLine && _selStartColumn == _selEndColumn) { _screenWindow->scrollTo(_scrollBar->maximum()); qDebug() << "left selection start"; _screenWindow->setSelectionStart(_selStartColumn, _selStartLine, false); } - } - else - { + } else { //每一格设置一次选择结束状态,这样才能看到选择的区域;键盘一直按住则一直选 _screenWindow->setSelectionEnd(_selEndColumn, _selEndLine); } //向左选择 - if (_selEndColumn >= 1) - { + if (_selEndColumn >= 1) { _selEndColumn--; } //左键选择到最左边的时候,向上选中上一行末尾(如果当前没到第一行的话) - else if (_selEndLine > 0) - { + else if (_selEndLine > 0) { _selEndColumn = maxColumnIndex; _selEndLine--; } qDebug() << "left: _selStartColumn" << _selStartColumn - << "_selStartLine" << _selStartLine - << "_selEndColumn" << _selEndColumn - << "_selEndLine" << _selEndLine; - } - else if ( event->key() == Qt::Key_Right ) - { - if (!_selBegin) - { + << "_selStartLine" << _selStartLine + << "_selEndColumn" << _selEndColumn + << "_selEndLine" << _selEndLine; + } else if (event->key() == Qt::Key_Right) { + if (!_selBegin) { checkAndInitSelectionState(); _selBegin = true; //键盘按下时设置--开始选择 - if (_selStartLine == _selEndLine && _selStartColumn == _selEndColumn) - { + if (_selStartLine == _selEndLine && _selStartColumn == _selEndColumn) { //滚动到光标所在位置开始选择 _screenWindow->scrollTo(_scrollBar->maximum()); @@ -3044,61 +2954,46 @@ void TerminalDisplay::keyPressEvent( QKeyEvent* event ) qDebug() << "right selection start"; _screenWindow->setSelectionStart(_selStartColumn, _selStartLine, false); } - } - else - { + } else { _screenWindow->setSelectionEnd(_selEndColumn, _selEndLine); } //向右选择,最大行数为屏幕当前显示的最大行数(即屏幕当前显示了多少行就算多少行,并不包含历史行的行数) int maxLineIndex = _screenWindow->windowLines() - 1; //向右选择 - if (_selEndColumn < maxColumnIndex) - { + if (_selEndColumn < maxColumnIndex) { _selEndColumn++; } //右边到了最右边时,向下选中下一行的开头(如果当前没到最后一行的话) - else if (_selEndLine < maxLineIndex) - { + else if (_selEndLine < maxLineIndex) { _selEndColumn = 0; _selEndLine++; } qDebug() << "maxLineIndex: " << maxLineIndex << endl; qDebug() << "right: _selStartColumn" << _selStartColumn - << "_selStartLine" << _selStartLine - << "_selEndColumn" << _selEndColumn - << "_selEndLine" << _selEndLine; - } - else if ( event->key() == Qt::Key_Up ) - { + << "_selStartLine" << _selStartLine + << "_selEndColumn" << _selEndColumn + << "_selEndLine" << _selEndLine; + } else if (event->key() == Qt::Key_Up) { //使用了Shift+上下键,由于屏幕发生滚动,会导致计算的行列位置不对,需要重新初始化选择状态 initKeyBoardSelection(); - _screenWindow->scrollBy( ScreenWindow::ScrollLines , -1 ); - } - else if ( event->key() == Qt::Key_Down ) - { + _screenWindow->scrollBy(ScreenWindow::ScrollLines, -1); + } else if (event->key() == Qt::Key_Down) { //使用了Shift+上下键,由于屏幕发生滚动,会导致计算的行列位置不对,需要重新初始化选择状态 - initKeyBoardSelection(); - _screenWindow->scrollBy( ScreenWindow::ScrollLines , 1 ); - } - else if ( event->key() == Qt::Key_End) - { + initKeyBoardSelection(); + _screenWindow->scrollBy(ScreenWindow::ScrollLines, 1); + } else if (event->key() == Qt::Key_End) { scrollToEnd(); - } - else if ( event->key() == Qt::Key_Home) - { + } else if (event->key() == Qt::Key_Home) { //使用了Shift+Home键,由于屏幕发生滚动,会导致计算的行列位置不对,需要重新初始化选择状态 initKeyBoardSelection(); _screenWindow->scrollTo(0); - } - else - { + } else { update = false; } - if ( update ) - { - _screenWindow->setTrackOutput( _screenWindow->atEndOfOutput() ); + if (update) { + _screenWindow->setTrackOutput(_screenWindow->atEndOfOutput()); updateLineProperties(); updateImage(); @@ -3106,26 +3001,22 @@ void TerminalDisplay::keyPressEvent( QKeyEvent* event ) // do not send key press to terminal emitKeyPressSignal = false; } - } - else - { + } else { initKeyBoardSelection(); } - _actSel=0; // Key stroke implies a screen update, so TerminalDisplay won't - // know where the current selection is. + _actSel = 0; // Key stroke implies a screen update, so TerminalDisplay won't + // know where the current selection is. - if (_hasBlinkingCursor) - { - _blinkCursorTimer->start(QApplication::cursorFlashTime() / 2); - if (_cursorBlinking) - blinkCursorEvent(); - else - _cursorBlinking = false; + if (_hasBlinkingCursor) { + _blinkCursorTimer->start(QApplication::cursorFlashTime() / 2); + if (_cursorBlinking) + blinkCursorEvent(); + else + _cursorBlinking = false; } - if ( emitKeyPressSignal ) - { + if (emitKeyPressSignal) { emit keyPressedSignal(event); /******** Modify by wangpeili n014361 2020-02-14: 按键滚动功能***********/ @@ -3155,38 +3046,30 @@ void TerminalDisplay::keyPressEvent( QKeyEvent* event ) void TerminalDisplay::keyReleaseEvent(QKeyEvent *event) { //处理使用Shift+左右键选择文字,处理键盘释放的情况 - if ( event->modifiers() == Qt::ShiftModifier ) - { - if ( event->key() == Qt::Key_Left ) - { + if (event->modifiers() == Qt::ShiftModifier) { + if (event->key() == Qt::Key_Left) { //由于会有一定概率出现,长按后再同时短按一次Shift+左或者右方向键,出现一次选择两个字符的情况 //这里做了一个数据纠正 - if (2 == abs(_lastLeftEndColumn - _selEndColumn)) - { + if (2 == abs(_lastLeftEndColumn - _selEndColumn)) { _selEndColumn = _lastEndColumn; } _screenWindow->setSelectionEnd(_selEndColumn, _selEndLine); _lastLeftEndColumn = _selEndColumn; - setSelection( _screenWindow->selectedText(currentDecodingOptions()) ); - } - else if ( event->key() == Qt::Key_Right) - { + setSelection(_screenWindow->selectedText(currentDecodingOptions())); + } else if (event->key() == Qt::Key_Right) { //由于会有一定概率出现,长按后再短按Shift+左或者右方向键,出现一次选择两个字符的情况 //这里做了一个数据纠正 - if (2 == abs(_lastRightEndColumn - _selEndColumn)) - { + if (2 == abs(_lastRightEndColumn - _selEndColumn)) { _selEndColumn = _lastEndColumn; } _screenWindow->setSelectionEnd(_selEndColumn, _selEndLine); _lastRightEndColumn = _selEndColumn; - setSelection( _screenWindow->selectedText(currentDecodingOptions()) ); - } - else - { + setSelection(_screenWindow->selectedText(currentDecodingOptions())); + } else { _selBegin = false; _lastEndColumn = _selEndColumn; } @@ -3195,9 +3078,9 @@ void TerminalDisplay::keyReleaseEvent(QKeyEvent *event) event->accept(); } -void TerminalDisplay::inputMethodEvent( QInputMethodEvent* event ) +void TerminalDisplay::inputMethodEvent(QInputMethodEvent *event) { - QKeyEvent keyEvent(QEvent::KeyPress,0,Qt::NoModifier,event->commitString()); + QKeyEvent keyEvent(QEvent::KeyPress, 0, Qt::NoModifier, event->commitString()); emit keyPressedSignal(&keyEvent); _inputMethodData.preeditString = event->preeditString(); @@ -3205,67 +3088,61 @@ void TerminalDisplay::inputMethodEvent( QInputMethodEvent* event ) event->accept(); } -QVariant TerminalDisplay::inputMethodQuery( Qt::InputMethodQuery query ) const +QVariant TerminalDisplay::inputMethodQuery(Qt::InputMethodQuery query) const { - const QPoint cursorPos = _screenWindow ? _screenWindow->cursorPosition() : QPoint(0,0); - switch ( query ) - { - case Qt::ImMicroFocus: - return imageToWidget(QRect(cursorPos.x(),cursorPos.y(),1,1)); - break; - case Qt::ImFont: - return font(); - break; - case Qt::ImCursorPosition: - // return the cursor position within the current line - return cursorPos.x(); - break; - case Qt::ImSurroundingText: - { - // return the text from the current line - QString lineText; - QTextStream stream(&lineText); - PlainTextDecoder decoder; - decoder.begin(&stream); - decoder.decodeLine(&_image[loc(0,cursorPos.y())],_usedColumns,_lineProperties[cursorPos.y()]); - decoder.end(); - return lineText; - } - break; - case Qt::ImCurrentSelection: - return QString(); - break; - default: - break; + const QPoint cursorPos = _screenWindow ? _screenWindow->cursorPosition() : QPoint(0, 0); + switch (query) { + case Qt::ImMicroFocus: + return imageToWidget(QRect(cursorPos.x(), cursorPos.y(), 1, 1)); + break; + case Qt::ImFont: + return font(); + break; + case Qt::ImCursorPosition: + // return the cursor position within the current line + return cursorPos.x(); + break; + case Qt::ImSurroundingText: { + // return the text from the current line + QString lineText; + QTextStream stream(&lineText); + PlainTextDecoder decoder; + decoder.begin(&stream); + decoder.decodeLine(&_image[loc(0, cursorPos.y())], _usedColumns, _lineProperties[cursorPos.y()]); + decoder.end(); + return lineText; + } + break; + case Qt::ImCurrentSelection: + return QString(); + break; + default: + break; } return QVariant(); } -bool TerminalDisplay::handleShortcutOverrideEvent(QKeyEvent* keyEvent) +bool TerminalDisplay::handleShortcutOverrideEvent(QKeyEvent *keyEvent) { int modifiers = keyEvent->modifiers(); // When a possible shortcut combination is pressed, // emit the overrideShortcutCheck() signal to allow the host // to decide whether the terminal should override it or not. - if (modifiers != Qt::NoModifier) - { + if (modifiers != Qt::NoModifier) { int modifierCount = 0; unsigned int currentModifier = Qt::ShiftModifier; - while (currentModifier <= Qt::KeypadModifier) - { + while (currentModifier <= Qt::KeypadModifier) { if (modifiers & currentModifier) modifierCount++; currentModifier <<= 1; } - if (modifierCount < 2) - { + if (modifierCount < 2) { bool override = false; - emit overrideShortcutCheck(keyEvent,override); - if (override) - { + emit overrideShortcutCheck(keyEvent, override); + if (override) { keyEvent->accept(); return true; } @@ -3275,44 +3152,42 @@ bool TerminalDisplay::handleShortcutOverrideEvent(QKeyEvent* keyEvent) // Override any of the following shortcuts because // they are needed by the terminal int keyCode = keyEvent->key() | modifiers; - switch ( keyCode ) - { - // list is taken from the QLineEdit::event() code - case Qt::Key_Tab: - case Qt::Key_Delete: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_Backspace: - case Qt::Key_Left: - case Qt::Key_Right: - case Qt::Key_Escape: + switch (keyCode) { + // list is taken from the QLineEdit::event() code + case Qt::Key_Tab: + case Qt::Key_Delete: + case Qt::Key_Home: + case Qt::Key_End: + case Qt::Key_Backspace: + case Qt::Key_Left: + case Qt::Key_Right: + case Qt::Key_Escape: keyEvent->accept(); return true; } return false; } -bool TerminalDisplay::event(QEvent* event) +bool TerminalDisplay::event(QEvent *event) { - bool eventHandled = false; - switch (event->type()) - { + bool eventHandled = false; + switch (event->type()) { case QEvent::ShortcutOverride: - eventHandled = handleShortcutOverrideEvent((QKeyEvent*)event); + eventHandled = handleShortcutOverrideEvent((QKeyEvent *)event); break; case QEvent::PaletteChange: case QEvent::ApplicationPaletteChange: - _scrollBar->setPalette( QApplication::palette() ); + _scrollBar->setPalette(QApplication::palette()); break; default: break; - } - return eventHandled ? true : QWidget::event(event); + } + return eventHandled ? true : QWidget::event(event); } void TerminalDisplay::setBellMode(int mode) { - _bellMode=mode; + _bellMode = mode; } void TerminalDisplay::enableBell() @@ -3320,32 +3195,26 @@ void TerminalDisplay::enableBell() _allowBell = true; } -void TerminalDisplay::bell(const QString& message) +void TerminalDisplay::bell(const QString &message) { - if (_bellMode==NoBell) return; + if (_bellMode == NoBell) return; - //limit the rate at which bells can occur - //...mainly for sound effects where rapid bells in sequence - //produce a horrible noise - if ( _allowBell ) - { - _allowBell = false; - QTimer::singleShot(500,this,SLOT(enableBell())); + //limit the rate at which bells can occur + //...mainly for sound effects where rapid bells in sequence + //produce a horrible noise + if (_allowBell) { + _allowBell = false; + QTimer::singleShot(500, this, SLOT(enableBell())); - if (_bellMode==SystemBeepBell) - { - QApplication::beep(); - } - else if (_bellMode==NotifyBell) - { - emit notifyBell(message); - } - else if (_bellMode==VisualBell) - { - swapColorTable(); - QTimer::singleShot(200,this,SLOT(swapColorTable())); + if (_bellMode == SystemBeepBell) { + QApplication::beep(); + } else if (_bellMode == NotifyBell) { + emit notifyBell(message); + } else if (_bellMode == VisualBell) { + swapColorTable(); + QTimer::singleShot(200, this, SLOT(swapColorTable())); + } } - } } void TerminalDisplay::selectionChanged() @@ -3368,12 +3237,10 @@ void TerminalDisplay::hideQScrollBarRightMenu() { // fix bug 63308: 鼠标放置在右侧滚动条上点击鼠标右键,界面出现黑色长条 QWidgetList widgetList = qApp->allWidgets(); - for(int i=0; i(widget); - if(scrollBar) - { + QScrollBar *scrollBar = dynamic_cast(widget); + if (scrollBar) { scrollBar->setContextMenuPolicy(Qt::NoContextMenu); } } @@ -3381,124 +3248,119 @@ void TerminalDisplay::hideQScrollBarRightMenu() void TerminalDisplay::swapColorTable() { - ColorEntry color = _colorTable[1]; - _colorTable[1]=_colorTable[0]; - _colorTable[0]= color; - _colorsInverted = !_colorsInverted; - update(); + ColorEntry color = _colorTable[1]; + _colorTable[1] = _colorTable[0]; + _colorTable[0] = color; + _colorsInverted = !_colorsInverted; + update(); } void TerminalDisplay::clearImage() { - // We initialize _image[_imageSize] too. See makeImage() - for (int i = 0; i <= _imageSize; i++) - { - _image[i].character = ' '; - _image[i].foregroundColor = CharacterColor(COLOR_SPACE_DEFAULT, - DEFAULT_FORE_COLOR); - _image[i].backgroundColor = CharacterColor(COLOR_SPACE_DEFAULT, - DEFAULT_BACK_COLOR); - _image[i].rendition = DEFAULT_RENDITION; - } + // We initialize _image[_imageSize] too. See makeImage() + for (int i = 0; i <= _imageSize; i++) { + _image[i].character = ' '; + _image[i].foregroundColor = CharacterColor(COLOR_SPACE_DEFAULT, + DEFAULT_FORE_COLOR); + _image[i].backgroundColor = CharacterColor(COLOR_SPACE_DEFAULT, + DEFAULT_BACK_COLOR); + _image[i].rendition = DEFAULT_RENDITION; + } } void TerminalDisplay::calcGeometry() { - _scrollBar->resize(_scrollBar->sizeHint().width(), contentsRect().height()); - int scrollBarWidth = _scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, _scrollBar) - ? 0 : _scrollBar->width(); - switch(_scrollbarLocation) - { + _scrollBar->resize(_scrollBar->sizeHint().width(), contentsRect().height()); + int scrollBarWidth = _scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, _scrollBar) + ? 0 : _scrollBar->width(); + switch (_scrollbarLocation) { case QTermWidget::NoScrollBar : - _leftMargin = _leftBaseMargin; - _contentWidth = contentsRect().width() - 2 * _leftBaseMargin; - break; + _leftMargin = _leftBaseMargin; + _contentWidth = contentsRect().width() - 2 * _leftBaseMargin; + break; case QTermWidget::ScrollBarLeft : - _leftMargin = _leftBaseMargin + scrollBarWidth; - _contentWidth = contentsRect().width() - 2 * _leftBaseMargin - scrollBarWidth; - _scrollBar->move(contentsRect().topLeft()); - break; + _leftMargin = _leftBaseMargin + scrollBarWidth; + _contentWidth = contentsRect().width() - 2 * _leftBaseMargin - scrollBarWidth; + _scrollBar->move(contentsRect().topLeft()); + break; case QTermWidget::ScrollBarRight: - _leftMargin = _leftBaseMargin; - _contentWidth = contentsRect().width() - 2 * _leftBaseMargin - scrollBarWidth; - _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width()-1, 0)); - break; - } + _leftMargin = _leftBaseMargin; + _contentWidth = contentsRect().width() - 2 * _leftBaseMargin - scrollBarWidth; + _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width() - 1, 0)); + break; + } - _topMargin = _topBaseMargin; - _contentHeight = contentsRect().height() - 2 * _topBaseMargin + /* mysterious */ 1; + _topMargin = _topBaseMargin; + _contentHeight = contentsRect().height() - 2 * _topBaseMargin + /* mysterious */ 1; - if (!_isFixedSize) - { - // ensure that display is always at least one column wide - _columns = qMax(1,_contentWidth / _fontWidth); - _usedColumns = qMin(_usedColumns,_columns); + if (!_isFixedSize) { + // ensure that display is always at least one column wide + _columns = qMax(1, _contentWidth / _fontWidth); + _usedColumns = qMin(_usedColumns, _columns); - // ensure that display is always at least one line high - _lines = qMax(1,_contentHeight / _fontHeight); - _usedLines = qMin(_usedLines,_lines); - } + // ensure that display is always at least one line high + _lines = qMax(1, _contentHeight / _fontHeight); + _usedLines = qMin(_usedLines, _lines); + } } void TerminalDisplay::makeImage() { - calcGeometry(); + calcGeometry(); - // confirm that array will be of non-zero size, since the painting code - // assumes a non-zero array length - Q_ASSERT( _lines > 0 && _columns > 0 ); - Q_ASSERT( _usedLines <= _lines && _usedColumns <= _columns ); + // confirm that array will be of non-zero size, since the painting code + // assumes a non-zero array length + Q_ASSERT(_lines > 0 && _columns > 0); + Q_ASSERT(_usedLines <= _lines && _usedColumns <= _columns); - _imageSize=_lines*_columns; + _imageSize = _lines * _columns; - // We over-commit one character so that we can be more relaxed in dealing with - // certain boundary conditions: _image[_imageSize] is a valid but unused position - _image = new Character[_imageSize+1]; + // We over-commit one character so that we can be more relaxed in dealing with + // certain boundary conditions: _image[_imageSize] is a valid but unused position + _image = new Character[_imageSize + 1]; - clearImage(); + clearImage(); } // calculate the needed size, this must be synced with calcGeometry() void TerminalDisplay::setSize(int columns, int lines) { - int scrollBarWidth = (_scrollBar->isHidden() - || _scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, _scrollBar)) - ? 0 : _scrollBar->sizeHint().width(); - int horizontalMargin = 2 * _leftBaseMargin; - int verticalMargin = 2 * _topBaseMargin; + int scrollBarWidth = (_scrollBar->isHidden() + || _scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, _scrollBar)) + ? 0 : _scrollBar->sizeHint().width(); + int horizontalMargin = 2 * _leftBaseMargin; + int verticalMargin = 2 * _topBaseMargin; - QSize newSize = QSize( horizontalMargin + scrollBarWidth + (columns * _fontWidth) , - verticalMargin + (lines * _fontHeight) ); + QSize newSize = QSize(horizontalMargin + scrollBarWidth + (columns * _fontWidth), + verticalMargin + (lines * _fontHeight)); - if ( newSize != size() ) - { - _size = newSize; - updateGeometry(); - } + if (newSize != size()) { + _size = newSize; + updateGeometry(); + } } void TerminalDisplay::setFixedSize(int cols, int lins) { - _isFixedSize = true; + _isFixedSize = true; - //ensure that display is at least one line by one column in size - _columns = qMax(1,cols); - _lines = qMax(1,lins); - _usedColumns = qMin(_usedColumns,_columns); - _usedLines = qMin(_usedLines,_lines); + //ensure that display is at least one line by one column in size + _columns = qMax(1, cols); + _lines = qMax(1, lins); + _usedColumns = qMin(_usedColumns, _columns); + _usedLines = qMin(_usedLines, _lines); - if (_image) - { - delete[] _image; - makeImage(); - } - setSize(cols, lins); - QWidget::setFixedSize(_size); + if (_image) { + delete[] _image; + makeImage(); + } + setSize(cols, lins); + QWidget::setFixedSize(_size); } QSize TerminalDisplay::sizeHint() const { - return _size; + return _size; } @@ -3508,104 +3370,99 @@ QSize TerminalDisplay::sizeHint() const /* */ /* --------------------------------------------------------------------- */ -void TerminalDisplay::dragEnterEvent(QDragEnterEvent* event) +void TerminalDisplay::dragEnterEvent(QDragEnterEvent *event) { - if (event->mimeData()->hasFormat(QLatin1String("text/plain"))) - event->acceptProposedAction(); - if (event->mimeData()->urls().count()) - event->acceptProposedAction(); + if (event->mimeData()->hasFormat(QLatin1String("text/plain"))) + event->acceptProposedAction(); + if (event->mimeData()->urls().count()) + event->acceptProposedAction(); } -void TerminalDisplay::dropEvent(QDropEvent* event) +void TerminalDisplay::dropEvent(QDropEvent *event) { - //KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); - QList urls = event->mimeData()->urls(); + //KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); + QList urls = event->mimeData()->urls(); - QString dropText; - if (!urls.isEmpty()) - { - // TODO/FIXME: escape or quote pasted things if neccessary... - qDebug() << "TerminalDisplay: handling urls. It can be broken. Report any errors, please"; - for ( int i = 0 ; i < urls.count() ; i++ ) - { - //KUrl url = KIO::NetAccess::mostLocalUrl( urls[i] , 0 ); - QUrl url = urls[i]; + QString dropText; + if (!urls.isEmpty()) { + // TODO/FIXME: escape or quote pasted things if neccessary... + qDebug() << "TerminalDisplay: handling urls. It can be broken. Report any errors, please"; + for (int i = 0 ; i < urls.count() ; i++) { + //KUrl url = KIO::NetAccess::mostLocalUrl( urls[i] , 0 ); + QUrl url = urls[i]; - QString urlText; + QString urlText; - if (url.isLocalFile()) - urlText = url.path(); - else - urlText = url.toString(); + if (url.isLocalFile()) + urlText = url.path(); + else + urlText = url.toString(); - // in future it may be useful to be able to insert file names with drag-and-drop - // without quoting them (this only affects paths with spaces in) - //urlText = KShell::quoteArg(urlText); + // in future it may be useful to be able to insert file names with drag-and-drop + // without quoting them (this only affects paths with spaces in) + //urlText = KShell::quoteArg(urlText); - dropText += urlText; + dropText += urlText; - if ( i != urls.count()-1 ) - dropText += QLatin1Char(' '); + if (i != urls.count() - 1) + dropText += QLatin1Char(' '); + } + } else { + dropText = event->mimeData()->text(); } - } - else - { - dropText = event->mimeData()->text(); - } - /***add begin by ut001121 zhangmeng 20201030 for SP4.1 拖拽文件到工作区文件路径加引号***/ - dropText.insert(0, '\''); - dropText.append('\''); - /***add end ut001121***/ + /***add begin by ut001121 zhangmeng 20201030 for SP4.1 拖拽文件到工作区文件路径加引号***/ + dropText.insert(0, '\''); + dropText.append('\''); + /***add end ut001121***/ emit sendStringToEmu(dropText.toLocal8Bit().constData()); } void TerminalDisplay::doDrag() { - dragInfo.state = diDragging; - dragInfo.dragObject = new QDrag(this); - QMimeData *mimeData = new QMimeData; - mimeData->setText(QApplication::clipboard()->text(QClipboard::Selection)); - dragInfo.dragObject->setMimeData(mimeData); - dragInfo.dragObject->start(Qt::CopyAction); - // Don't delete the QTextDrag object. Qt will delete it when it's done with it. + dragInfo.state = diDragging; + dragInfo.dragObject = new QDrag(this); + QMimeData *mimeData = new QMimeData; + mimeData->setText(QApplication::clipboard()->text(QClipboard::Selection)); + dragInfo.dragObject->setMimeData(mimeData); + dragInfo.dragObject->start(Qt::CopyAction); + // Don't delete the QTextDrag object. Qt will delete it when it's done with it. } void TerminalDisplay::outputSuspended(bool suspended) { //create the label when this function is first called - if (!_outputSuspendedLabel) - { - //This label includes a link to an English language website - //describing the 'flow control' (Xon/Xoff) feature found in almost - //all terminal emulators. - //If there isn't a suitable article available in the target language the link - //can simply be removed. - _outputSuspendedLabel = new QLabel( tr("Output has been " - "suspended" - " by pressing Ctrl+S." - " Press Ctrl+Q to resume."), - this ); - - QPalette palette(_outputSuspendedLabel->palette()); - //KColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground); - _outputSuspendedLabel->setPalette(palette); - _outputSuspendedLabel->setAutoFillBackground(true); - _outputSuspendedLabel->setBackgroundRole(QPalette::Base); - _outputSuspendedLabel->setFont(QApplication::font()); - _outputSuspendedLabel->setContentsMargins(5, 5, 5, 5); - - //enable activation of "Xon/Xoff" link in label - _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse | - Qt::LinksAccessibleByKeyboard); - _outputSuspendedLabel->setOpenExternalLinks(true); - _outputSuspendedLabel->setVisible(false); - - _gridLayout->addWidget(_outputSuspendedLabel); - _gridLayout->addItem( new QSpacerItem(0,0,QSizePolicy::Expanding, - QSizePolicy::Expanding), - 1,0); + if (!_outputSuspendedLabel) { + //This label includes a link to an English language website + //describing the 'flow control' (Xon/Xoff) feature found in almost + //all terminal emulators. + //If there isn't a suitable article available in the target language the link + //can simply be removed. + _outputSuspendedLabel = new QLabel(tr("Output has been " + "suspended" + " by pressing Ctrl+S." + " Press Ctrl+Q to resume."), + this); + + QPalette palette(_outputSuspendedLabel->palette()); + //KColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground); + _outputSuspendedLabel->setPalette(palette); + _outputSuspendedLabel->setAutoFillBackground(true); + _outputSuspendedLabel->setBackgroundRole(QPalette::Base); + _outputSuspendedLabel->setFont(QApplication::font()); + _outputSuspendedLabel->setContentsMargins(5, 5, 5, 5); + + //enable activation of "Xon/Xoff" link in label + _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse | + Qt::LinksAccessibleByKeyboard); + _outputSuspendedLabel->setOpenExternalLinks(true); + _outputSuspendedLabel->setVisible(false); + + _gridLayout->addWidget(_outputSuspendedLabel); + _gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, + QSizePolicy::Expanding), + 1, 0); } @@ -3614,13 +3471,13 @@ void TerminalDisplay::outputSuspended(bool suspended) uint TerminalDisplay::lineSpacing() const { - return _lineSpacing; + return _lineSpacing; } void TerminalDisplay::setLineSpacing(uint i) { - _lineSpacing = i; - setVTFont(font()); // Trigger an update. + _lineSpacing = i; + setVTFont(font()); // Trigger an update. } int TerminalDisplay::margin() const @@ -3634,58 +3491,52 @@ void TerminalDisplay::setMargin(int i) _leftBaseMargin = i; } -AutoScrollHandler::AutoScrollHandler(QWidget* parent) -: QObject(parent) -, _timerId(0) +AutoScrollHandler::AutoScrollHandler(QWidget *parent) + : QObject(parent) + , _timerId(0) { parent->installEventFilter(this); } -void AutoScrollHandler::timerEvent(QTimerEvent* event) +void AutoScrollHandler::timerEvent(QTimerEvent *event) { if (event->timerId() != _timerId) return; - QMouseEvent mouseEvent( QEvent::MouseMove, - widget()->mapFromGlobal(QCursor::pos()), - Qt::NoButton, - Qt::LeftButton, - Qt::NoModifier); + QMouseEvent mouseEvent(QEvent::MouseMove, + widget()->mapFromGlobal(QCursor::pos()), + Qt::NoButton, + Qt::LeftButton, + Qt::NoModifier); - QApplication::sendEvent(widget(),&mouseEvent); + QApplication::sendEvent(widget(), &mouseEvent); } -bool AutoScrollHandler::eventFilter(QObject* watched,QEvent* event) +bool AutoScrollHandler::eventFilter(QObject *watched, QEvent *event) { - Q_ASSERT( watched == parent() ); - Q_UNUSED( watched ); + Q_ASSERT(watched == parent()); + Q_UNUSED(watched); - switch (event->type()) - { - case QEvent::MouseMove: - { - QMouseEvent* mouseEvent = static_cast(event); - bool mouseInWidget = widget()->rect().contains(mouseEvent->pos()); + switch (event->type()) { + case QEvent::MouseMove: { + QMouseEvent *mouseEvent = static_cast(event); + bool mouseInWidget = widget()->rect().contains(mouseEvent->pos()); - if (mouseInWidget) - { - if (_timerId) - killTimer(_timerId); - _timerId = 0; - } - else - { - if (!_timerId && (mouseEvent->buttons() & Qt::LeftButton)) - _timerId = startTimer(100); - } - break; - } - case QEvent::MouseButtonRelease: - if (_timerId && (static_cast(event)->buttons() & ~Qt::LeftButton)) - { + if (mouseInWidget) { + if (_timerId) killTimer(_timerId); - _timerId = 0; - } + _timerId = 0; + } else { + if (!_timerId && (mouseEvent->buttons() & Qt::LeftButton)) + _timerId = startTimer(100); + } + break; + } + case QEvent::MouseButtonRelease: + if (_timerId && (static_cast(event)->buttons() & ~Qt::LeftButton)) { + killTimer(_timerId); + _timerId = 0; + } break; - default: + default: break; }; @@ -3694,7 +3545,7 @@ bool AutoScrollHandler::eventFilter(QObject* watched,QEvent* event) //#include "TerminalDisplay.moc" -TerminalScreen::TerminalScreen(QWidget *parent):TerminalDisplay (parent) +TerminalScreen::TerminalScreen(QWidget *parent): TerminalDisplay(parent) { setAttribute(Qt::WA_AcceptTouchEvents); grabGesture(Qt::TapGesture); @@ -3737,25 +3588,22 @@ bool TerminalScreen::gestureEvent(QGestureEvent *event) 3. @日期: 2020-08-18 4. @说明: 单指点击手势 *******************************************************************************/ -void TerminalScreen::tapGestureTriggered(QTapGesture* tap) +void TerminalScreen::tapGestureTriggered(QTapGesture *tap) { //qDebug()<<"------"<<"tapGestureTriggered" << tap ; switch (tap->state()) { - case Qt::GestureStarted: - { + case Qt::GestureStarted: { m_gestureAction = GA_tap; m_tapBeginTime = QDateTime::currentDateTime().toMSecsSinceEpoch(); break; } - case Qt::GestureUpdated: - { + case Qt::GestureUpdated: { break; } - case Qt::GestureCanceled: - { + case Qt::GestureCanceled: { //根据时间长短区分轻触滑动 qint64 timeSpace = QDateTime::currentDateTime().toMSecsSinceEpoch() - m_tapBeginTime; - if(timeSpace < TAP_MOVE_DELAY || m_slideContinue){ + if (timeSpace < TAP_MOVE_DELAY || m_slideContinue) { m_slideContinue = false; m_gestureAction = GA_slide; qDebug() << "slide start" << timeSpace; @@ -3766,14 +3614,12 @@ void TerminalScreen::tapGestureTriggered(QTapGesture* tap) } break; } - case Qt::GestureFinished: - { + case Qt::GestureFinished: { /***add by ut001121 zhangmeng 20200917 修复BUG48402***/ m_gestureAction = GA_null; break; } - default: - { + default: { Q_ASSERT(false); break; } @@ -3786,7 +3632,7 @@ void TerminalScreen::tapGestureTriggered(QTapGesture* tap) 3. @日期: 2020-08-18 4. @说明: 单指长按手势 *******************************************************************************/ -void TerminalScreen::tapAndHoldGestureTriggered(QTapAndHoldGesture* tapAndHold) +void TerminalScreen::tapAndHoldGestureTriggered(QTapAndHoldGesture *tapAndHold) { //qDebug()<<"------"<<"tapAndHoldGestureTriggered"<state()) { @@ -3846,49 +3692,44 @@ void TerminalScreen::pinchTriggered(QPinchGesture *pinch) { //qDebug()<<"------"<<"pinchTriggered"<state()) { - case Qt::GestureStarted: - { - qDebug()<<"------"<<"pinchTriggered start"; + case Qt::GestureStarted: { + qDebug() << "------" << "pinchTriggered start"; m_gestureAction = GA_pinch; /**add begin by ut001121 zhangmeng 20200812 捏合手势触发时判断是否重新获取字体大小 修复BUG42424 */ QFont font = getVTFont(); - if(static_cast(m_scaleFactor) != font.pointSize()){ + if (static_cast(m_scaleFactor) != font.pointSize()) { m_scaleFactor = font.pointSize(); } /**add end by ut001121 */ break; } - case Qt::GestureUpdated: - { + case Qt::GestureUpdated: { QPinchGesture::ChangeFlags changeFlags = pinch->changeFlags(); if (changeFlags & QPinchGesture::ScaleFactorChanged) { m_currentStepScaleFactor = pinch->totalScaleFactor(); } break; } - case Qt::GestureCanceled: - { + case Qt::GestureCanceled: { Q_ASSERT(false); break; } - case Qt::GestureFinished: - { + case Qt::GestureFinished: { /***del by ut001121 zhangmeng 20200915 修复BUG46979 m_gestureAction = GA_null;***/ m_scaleFactor *= m_currentStepScaleFactor; m_currentStepScaleFactor = 1; - qDebug()<<"------"<<"pinchTriggered over"; + qDebug() << "------" << "pinchTriggered over"; break; } - default: - { + default: { Q_ASSERT(false); break; } }//switch QFont font = getVTFont(); - font.setPointSize(static_cast(m_scaleFactor*m_currentStepScaleFactor)); + font.setPointSize(static_cast(m_scaleFactor * m_currentStepScaleFactor)); setVTFont(font); } @@ -3898,7 +3739,7 @@ void TerminalScreen::pinchTriggered(QPinchGesture *pinch) 3. @日期: 2020-08-18 4. @说明: 三指滑动手势 *******************************************************************************/ -void TerminalScreen::swipeTriggered(QSwipeGesture* swipe) +void TerminalScreen::swipeTriggered(QSwipeGesture *swipe) { //qDebug()<<"------"<<"swipeTriggered"<state()) { @@ -3930,10 +3771,10 @@ void TerminalScreen::swipeTriggered(QSwipeGesture* swipe) void TerminalScreen::slideGesture(qreal diff) { static qreal delta = 0.0; - int step = static_cast(diff+delta); - delta = diff+delta - step; + int step = static_cast(diff + delta); + delta = diff + delta - step; - getScrollBar()->setValue(getScrollBar()->value()+step); + getScrollBar()->setValue(getScrollBar()->value() + step); } /******************************************************************************* @@ -3942,66 +3783,60 @@ void TerminalScreen::slideGesture(qreal diff) 3. @日期: 2020-08-18 4. @说明: 事件处理 *******************************************************************************/ -bool TerminalScreen::event(QEvent* event) +bool TerminalScreen::event(QEvent *event) { static FlashTween tween; static qreal change = 0.0; static qreal duration = 0.0; if (event->type() == QEvent::Gesture) - return gestureEvent(static_cast(event)); + return gestureEvent(static_cast(event)); - if (event->type() == QEvent::MouseButtonRelease && static_cast(event)->source() == Qt::MouseEventSynthesizedByQt) - { - qDebug()<< "action is over" << m_gestureAction; + if (event->type() == QEvent::MouseButtonRelease && static_cast(event)->source() == Qt::MouseEventSynthesizedByQt) { + qDebug() << "action is over" << m_gestureAction; - if(m_gestureAction == GA_slide){ + if (m_gestureAction == GA_slide) { tween.start(0, 0, change, duration, std::bind(&TerminalScreen::slideGesture, this, std::placeholders::_1)); } m_gestureAction = GA_null; } - if (event->type() == QEvent::MouseButtonPress && static_cast(event)->source() == Qt::MouseEventSynthesizedByQt) - { - QMouseEvent* mouseEvent = static_cast(event); + if (event->type() == QEvent::MouseButtonPress && static_cast(event)->source() == Qt::MouseEventSynthesizedByQt) { + QMouseEvent *mouseEvent = static_cast(event); m_lastMouseTime = mouseEvent->timestamp(); m_lastMouseYpos = mouseEvent->pos().y(); - if(tween.active()) - { + if (tween.active()) { m_slideContinue = true; tween.stop(); } } - if (event->type() == QEvent::MouseMove && static_cast(event)->source() == Qt::MouseEventSynthesizedByQt) - { + if (event->type() == QEvent::MouseMove && static_cast(event)->source() == Qt::MouseEventSynthesizedByQt) { QMouseEvent *mouseEvent = static_cast(event); const ulong diffTime = mouseEvent->timestamp() - m_lastMouseTime; const int diffYpos = mouseEvent->pos().y() - m_lastMouseYpos; m_lastMouseTime = mouseEvent->timestamp(); m_lastMouseYpos = mouseEvent->pos().y(); - if(m_gestureAction == GA_slide) - { + if (m_gestureAction == GA_slide) { QFont font = getVTFont(); /*开根号时数值越大衰减比例越大*/ - qreal direction = diffYpos>0?1.0:-1.0; - slideGesture(-direction*sqrt(abs(diffYpos))/font.pointSize()); + qreal direction = diffYpos > 0 ? 1.0 : -1.0; + slideGesture(-direction * sqrt(abs(diffYpos)) / font.pointSize()); /*预算惯性滑动时间*/ - m_stepSpeed = static_cast(diffYpos)/static_cast(diffTime+0.000001); - duration = sqrt(abs(m_stepSpeed))*1000; + m_stepSpeed = static_cast(diffYpos) / static_cast(diffTime + 0.000001); + duration = sqrt(abs(m_stepSpeed)) * 1000; /*预算惯性滑动距离,4.0为调优数值*/ - m_stepSpeed /= sqrt(font.pointSize()*4.0); - change = m_stepSpeed*sqrt(abs(m_stepSpeed))*100; + m_stepSpeed /= sqrt(font.pointSize() * 4.0); + change = m_stepSpeed * sqrt(abs(m_stepSpeed)) * 100; return true; } - if(m_gestureAction != GA_null) - { + if (m_gestureAction != GA_null) { return true; } } @@ -4009,7 +3844,7 @@ bool TerminalScreen::event(QEvent* event) /***add by ut001121 zhangmeng 20200915 修复BUG46979***/ if (event->type() == QEvent::MouseMove && static_cast(event)->source() != Qt::MouseEventSynthesizedByQt - && m_gestureAction == GA_slide){ + && m_gestureAction == GA_slide) { return true; } /***add end ut001121***/ @@ -4038,7 +3873,7 @@ bool TerminalScreen::event(QEvent* event) FlashTween::FlashTween() { m_timer = new QTimer(this); - connect(m_timer, &QTimer::timeout, this ,&FlashTween::__run); + connect(m_timer, &QTimer::timeout, this, &FlashTween::__run); } /******************************************************************************* @@ -4047,9 +3882,9 @@ FlashTween::FlashTween() 3. @日期: 2020-08-18 4. @说明: 开始惯性 *******************************************************************************/ -void FlashTween::start(qreal t,qreal b,qreal c,qreal d, FunSlideInertial f) +void FlashTween::start(qreal t, qreal b, qreal c, qreal d, FunSlideInertial f) { - if(c==0.0 || d==0.0) return; + if (c == 0.0 || d == 0.0) return; m_currentTime = t; m_beginValue = b; m_changeValue = c; @@ -4057,7 +3892,7 @@ void FlashTween::start(qreal t,qreal b,qreal c,qreal d, FunSlideInertial f) m_lastValue = 0; m_fSlideGesture = f; - m_direction = m_changeValue<0?1:-1; + m_direction = m_changeValue < 0 ? 1 : -1; m_timer->stop(); m_timer->start(CELL_TIME); @@ -4073,13 +3908,12 @@ void FlashTween::__run() { qreal tempValue = m_lastValue; m_lastValue = FlashTween::sinusoidalEaseOut(m_currentTime, m_beginValue, abs(m_changeValue), m_durationTime); - m_fSlideGesture(m_direction*(m_lastValue-tempValue)); + m_fSlideGesture(m_direction * (m_lastValue - tempValue)); //qDebug()<<"###############################"<stop(); } } diff --git a/3rdparty/terminalwidget/lib/TerminalDisplay.h b/3rdparty/terminalwidget/lib/TerminalDisplay.h index ec3ad68f4..5000269d7 100644 --- a/3rdparty/terminalwidget/lib/TerminalDisplay.h +++ b/3rdparty/terminalwidget/lib/TerminalDisplay.h @@ -437,6 +437,7 @@ class KONSOLEPRIVATE_EXPORT TerminalDisplay : public QWidget // maps a point on the widget to the position ( ie. line and column ) // of the character at that point. void getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const; + void getExactCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const; void setHideCursor(bool hideCursor); @@ -573,6 +574,7 @@ public slots: void mouseSignal(int button, int column, int line, int eventType); void changedFontMetricSignal(int height, int width); void changedContentSizeSignal(int height, int width); + void changedCursonPosition(int count); /** * Emitted when the user right clicks on the display, or right-clicks with the Shift @@ -827,6 +829,7 @@ private slots: bool _blinking; // hide text in paintEvent bool _hasBlinker; // has characters to blink bool _cursorBlinking; // hide cursor in paintEvent + bool _cursorPositionSetEnable; // set cursor position enable bool _hasBlinkingCursor; // has blinking cursor enabled bool _allowBlinkingText; // allow text to blink bool _ctrlDrag; // require Ctrl key for drag @@ -924,6 +927,7 @@ private slots: } QScrollBar* getScrollBar() {return _scrollBar;} + void setCursorPositionEnable(bool enable); }; class AutoScrollHandler : public QObject diff --git a/3rdparty/terminalwidget/lib/Vt102Emulation.cpp b/3rdparty/terminalwidget/lib/Vt102Emulation.cpp index 89c8087b9..aba69871d 100644 --- a/3rdparty/terminalwidget/lib/Vt102Emulation.cpp +++ b/3rdparty/terminalwidget/lib/Vt102Emulation.cpp @@ -985,6 +985,16 @@ void Vt102Emulation::sendMouseEvent( int cb, int cx, int cy , int eventType ) sendString(command); } +void Vt102Emulation::sendCursor(int count) +{ + char command[32]; + command[0] = '\0'; + snprintf(command, sizeof(command), "\033[%c", count < 0 ? 'D' : 'C'); + for (int i = 0; i < qAbs(count); ++i) { + sendString(command); + } +} + /** * The focus lost event can be used by Vim (or other terminal applications) * to recognize that the konsole window has lost focus. diff --git a/3rdparty/terminalwidget/lib/Vt102Emulation.h b/3rdparty/terminalwidget/lib/Vt102Emulation.h index 4e751775a..d712cd465 100644 --- a/3rdparty/terminalwidget/lib/Vt102Emulation.h +++ b/3rdparty/terminalwidget/lib/Vt102Emulation.h @@ -95,6 +95,7 @@ public slots: void sendText(const QString& text) override; void sendKeyEvent(QKeyEvent*) override; void sendMouseEvent(int buttons, int column, int line, int eventType) override; + void sendCursor(int count) override; virtual void focusLost(); virtual void focusGained(); diff --git a/3rdparty/terminalwidget/lib/qtermwidget.cpp b/3rdparty/terminalwidget/lib/qtermwidget.cpp index 776398da0..4542ce0b6 100644 --- a/3rdparty/terminalwidget/lib/qtermwidget.cpp +++ b/3rdparty/terminalwidget/lib/qtermwidget.cpp @@ -321,7 +321,7 @@ void QTermWidget::addSnapShotTimer() m_termDisplay = m_impl->m_terminalDisplay; connect(m_interactionTimer, &QTimer::timeout, this, &QTermWidget::snapshot); connect(m_termDisplay.data(), &Konsole::TerminalDisplay::keyPressedSignal, this, &QTermWidget::interactionHandler); - connect(currSession, &Session::almostFinished, m_termDisplay, [=] { + connect(currSession, &Session::almostFinished, m_termDisplay, [ = ] { connect(m_termDisplay, &TerminalDisplay::keyPressedSignal, currSession, &Session::finished); }); @@ -372,6 +372,11 @@ void QTermWidget::setNoHasSelect() m_bHasSelect = false; } +void QTermWidget::enableSetCursorPosition(bool enable) +{ + m_impl->m_terminalDisplay->setCursorPositionEnable(enable); +} + /******************************************************************************* 1. @函数: getisAllowScroll 2. @作者: ut000610 戴正文 diff --git a/3rdparty/terminalwidget/lib/qtermwidget.h b/3rdparty/terminalwidget/lib/qtermwidget.h index 2850cae1e..1123a9fed 100644 --- a/3rdparty/terminalwidget/lib/qtermwidget.h +++ b/3rdparty/terminalwidget/lib/qtermwidget.h @@ -284,6 +284,8 @@ class TERMINALWIDGET_EXPORT QTermWidget : public QWidget //避免搜索框隐藏再显示之后,继续走m_bHasSelect为true流程,导致崩溃 void setNoHasSelect(); + // 是否允许ctrl + 鼠标左键移动光标 + void enableSetCursorPosition(bool enable); signals: void finished(); void copyAvailable(bool); diff --git a/src/assets/other/default-config.json b/src/assets/other/default-config.json index 7619c22a1..50517fa4e 100644 --- a/src/assets/other/default-config.json +++ b/src/assets/other/default-config.json @@ -335,6 +335,12 @@ "type": "checkbox", "text": "Copy on select", "default": true + }, + { + "key": "set_cursor_position", + "type": "checkbox", + "text": "Allow Ctrl + left mouse click to set cursor position", + "default": false } ] }, diff --git a/src/settings/settings.cpp b/src/settings/settings.cpp index 64e230850..dc74975b6 100644 --- a/src/settings/settings.cpp +++ b/src/settings/settings.cpp @@ -316,6 +316,11 @@ void Settings::initConnection() emit wordCharactersChanged(value.toString()); }); + QPointer cursorPositionSet = settings->option("advanced.cursor.set_cursor_position"); + connect(cursorPositionSet, &Dtk::Core::DSettingsOption::valueChanged, this, [ = ](QVariant value) { + emit enableSetCursorPosition(value.toBool()); + }); + QPointer backgroundBlur = settings->option("basic.interface.blurred_background"); connect(backgroundBlur, &Dtk::Core::DSettingsOption::valueChanged, this, [ = ](QVariant value) { emit backgroundBlurChanged(value.toBool()); @@ -472,6 +477,11 @@ bool Settings::cursorBlink() const return settings->option("advanced.cursor.cursor_blink")->value().toBool(); } +bool Settings::enableSetCursorPosition() const +{ + return settings->option("advanced.cursor.set_cursor_position")->value().toBool(); +} + bool Settings::backgroundBlur() const { return settings->option("basic.interface.blurred_background")->value().toBool(); diff --git a/src/settings/settings.h b/src/settings/settings.h index 69f21aab3..fe768e443 100644 --- a/src/settings/settings.h +++ b/src/settings/settings.h @@ -66,6 +66,11 @@ class Settings : public QObject * @return */ bool cursorBlink() const; + /** + * @brief enableSetCursorPosition + * @return + */ + bool enableSetCursorPosition() const; /** * @brief 设置界面获取背景模糊属性 * @author ut001121 zhangmeng @@ -296,6 +301,7 @@ class Settings : public QObject void opacityChanged(qreal opacity); void cursorShapeChanged(int shape); void cursorBlinkChanged(bool blink); + void enableSetCursorPosition(bool enable); void backgroundBlurChanged(bool enabled); void pressingScrollChanged(bool enabled); void OutputScrollChanged(bool enabled); diff --git a/src/settings/settings_translation.cpp b/src/settings/settings_translation.cpp index 60ec649e4..e74e70e32 100644 --- a/src/settings/settings_translation.cpp +++ b/src/settings/settings_translation.cpp @@ -148,4 +148,6 @@ void GenerateSettingTranslate() Q_UNUSED(history_size); auto include_special_characters_in_double_click_selectionisText = QObject::tr("Include special character(s) in double click selections"); Q_UNUSED(include_special_characters_in_double_click_selectionisText); + auto set_cursor_position = QObject::tr("Allow Ctrl + left mouse click to set cursor position"); + Q_UNUSED(set_cursor_position); } diff --git a/src/views/termwidget.cpp b/src/views/termwidget.cpp index 509e92cdf..810b53003 100644 --- a/src/views/termwidget.cpp +++ b/src/views/termwidget.cpp @@ -114,6 +114,8 @@ TermWidget::TermWidget(const TermProperties &properties, QWidget *parent) : QTer setKeyboardCursorShape(static_cast(Settings::instance()->cursorShape())); // 光标闪烁 setBlinkingCursor(Settings::instance()->cursorBlink()); + // 是否允许移动光标 + enableSetCursorPosition(Settings::instance()->enableSetCursorPosition()); // 按键滚动 setPressingScroll(Settings::instance()->PressingScroll()); @@ -1127,6 +1129,10 @@ void TermWidget::onSettingValueChanged(const QString &keyName) return; } + if ("advanced.cursor.set_cursor_position" == keyName) { + enableSetCursorPosition(Settings::instance()->enableSetCursorPosition()); + } + if ("advanced.scroll.scroll_on_key" == keyName) { setPressingScroll(Settings::instance()->PressingScroll()); return; diff --git a/translations/deepin-terminal_zh_CN.ts b/translations/deepin-terminal_zh_CN.ts index e142ee17c..3b9e35d6a 100644 --- a/translations/deepin-terminal_zh_CN.ts +++ b/translations/deepin-terminal_zh_CN.ts @@ -713,6 +713,11 @@ Include special character(s) in double click selections 在双击选中区域包含特殊符号 + + + Allow Ctrl + left mouse click to set cursor position + 允许Ctrl+鼠标左键点击设置光标位置 +