Commit 7c2a1164 authored by Ahmad Samir's avatar Ahmad Samir Committed by Kurt Hindenburg
Browse files

Add support for Set Cursor Style (DECSCUSR) escape sequences

Summary:
This follows the XTerm escape sequences, which include a couple more
shapes than what VT520 supports.

BUG: 347323
FIXED-IN: 18.08

Test Plan:
To test the escape sequences:
printf '\e[ q'		#blinking block
printf '\e[0 q'		# blinking block
printf '\e[1 q'		# blinking block
printf '\e[2 q'		# steady block
printf '\e[3 q'		# blinking underscore
printf '\e[4 q'		# steady underscore
printf '\e[5 q'		# blinking ibeam/bar
printf '\e[6 q'		# steady ibeam/bar

Executing `reset` in terminal will reset the cursor shape and blinking
settings to the current profile values.

Reviewers: #konsole, hindenburg

Reviewed By: #konsole, hindenburg

Subscribers: #konsole

Tags: #konsole

Differential Revision: https://phabricator.kde.org/D12193
parent f2aa2ba6
......@@ -29,6 +29,7 @@
#include <QTimer>
// Konsole
#include "Enumeration.h"
#include "konsoleprivate_export.h"
class QKeyEvent;
......@@ -429,6 +430,19 @@ Q_SIGNALS:
*/
void sessionAttributeRequest(int id);
/**
* Emitted when Set Cursor Style (DECSCUSR) escape sequences are sent
* to the terminal.
* @p shape cursor shape
* @p isBlinking if true, the cursor will be set to blink
*/
void setCursorStyleRequest(Enum::CursorShapeEnum shape = Enum::BlockCursor, bool isBlinking = false);
/**
* Emitted when reset() is called to reset the cursor style to the
* current profile cursor shape and blinking settings.
*/
void resetCursorStyleRequest();
protected:
virtual void setMode(int mode) = 0;
virtual void resetMode(int mode) = 0;
......
......@@ -325,6 +325,9 @@ void Session::addView(TerminalDisplay* widget)
connect(widget, &Konsole::TerminalDisplay::focusLost, _emulation, &Konsole::Emulation::focusLost);
connect(widget, &Konsole::TerminalDisplay::focusGained, _emulation, &Konsole::Emulation::focusGained);
connect(_emulation, &Konsole::Emulation::setCursorStyleRequest, widget, &Konsole::TerminalDisplay::setCursorStyle);
connect(_emulation, &Konsole::Emulation::resetCursorStyleRequest, widget, &Konsole::TerminalDisplay::resetCursorStyle);
}
void Session::viewDestroyed(QObject* view)
......
......@@ -768,6 +768,36 @@ Enum::CursorShapeEnum TerminalDisplay::keyboardCursorShape() const
{
return _cursorShape;
}
void TerminalDisplay::setCursorStyle(Enum::CursorShapeEnum shape, bool isBlinking)
{
setKeyboardCursorShape(shape);
setBlinkingCursorEnabled(isBlinking);
// when the cursor shape and blinking state are changed via the
// Set Cursor Style (DECSCUSR) escape sequences in vim, and if the
// cursor isn't set to blink, the cursor shape doesn't actually
// change until the cursor is moved by the user; calling update()
// makes the cursor shape get updated sooner.
if (!isBlinking) {
update();
}
}
void TerminalDisplay::resetCursorStyle()
{
if (sessionController() != nullptr) {
Profile::Ptr currentProfile = SessionManager::instance()->sessionProfile(sessionController()->session());
if (currentProfile != nullptr) {
Enum::CursorShapeEnum shape = static_cast<Enum::CursorShapeEnum>(currentProfile->property<int>(Profile::CursorShape));
setKeyboardCursorShape(shape);
setBlinkingCursorEnabled(currentProfile->blinkingCursorEnabled());
}
}
}
void TerminalDisplay::setKeyboardCursorColor(const QColor& color)
{
_cursorColor = color;
......
......@@ -263,6 +263,18 @@ public:
*/
Enum::CursorShapeEnum keyboardCursorShape() const;
/**
* Sets the Cursor Style (DECSCUSR) via escape sequences
* @p shape cursor shape
* @p isBlinking if true, the cursor will be set to blink
*/
void setCursorStyle(Enum::CursorShapeEnum shape, bool isBlinking);
/**
* Resets the cursor style to the current profile cursor shape and
* blinking settings
*/
void resetCursorStyle();
/**
* Sets the color used to draw the keyboard cursor.
*
......
......@@ -107,6 +107,8 @@ void Vt102Emulation::reset()
setCodec(LocaleCodec);
}
emit resetCursorStyleRequest();
bufferedUpdate();
}
......@@ -154,6 +156,10 @@ void Vt102Emulation::reset()
- CSI_PS - Escape codes of the form <ESC>'[' {Pn} ';' ... C
- CSI_PR - Escape codes of the form <ESC>'[' '?' {Pn} ';' ... C
- CSI_PE - Escape codes of the form <ESC>'[' '!' {Pn} ';' ... C
- CSI_SP - Escape codes of the form <ESC>'[' ' ' C
(3rd field is a space)
- CSI_PSP - Escape codes of the form <ESC>'[' '{Pn}' ' ' C
(4th field is a space)
- VT52 - VT52 escape codes
- <ESC><Chr>
- <ESC>'Y'{Pc}{Pc}
......@@ -216,6 +222,14 @@ constexpr int token_csi_pe(int a)
{
return token_construct(10, a, 0);
}
constexpr int token_csi_sp(int a)
{
return token_construct(11, a, 0);
}
constexpr int token_csi_psp(int a, int n)
{
return token_construct(12, a, n);
}
const int MAX_ARGUMENT = 4096;
......@@ -325,6 +339,8 @@ void Vt102Emulation::initTokenizer()
#define epp( ) (p >= 3 && s[2] == '?')
#define epe( ) (p >= 3 && s[2] == '!')
#define egt( ) (p >= 3 && s[2] == '>')
#define esp( ) (p >= 4 && s[2] == SP )
#define epsp( ) (p >= 5 && s[3] == SP )
#define Xpe (tokenBufferPos >= 2 && tokenBuffer[1] == ']')
#define Xte (Xpe && (cc == 7 || cc == 27))
#define ces(C) (cc < 256 && (charClass[cc] & (C)) == (C) && !Xte)
......@@ -333,6 +349,7 @@ void Vt102Emulation::initTokenizer()
#define CNTL(c) ((c)-'@')
const int ESC = 27;
const int DEL = 127;
const int SP = 32;
// process an incoming unicode character
void Vt102Emulation::receiveChar(int cc)
......@@ -372,6 +389,8 @@ void Vt102Emulation::receiveChar(int cc)
if (lec(3,2,'?')) { return; }
if (lec(3,2,'>')) { return; }
if (lec(3,2,'!')) { return; }
if (lec(3,2,SP )) { return; }
if (lec(4,3,SP )) { return; }
if (lun( )) { processToken(token_chr(), applyCharset(cc), 0); resetTokenizer(); return; }
if (dcs ) { return; /* TODO We don't xterm DCS, so we just eat it */ }
if (lec(2,0,ESC)) { processToken(token_esc(s[1]), 0, 0); resetTokenizer(); return; }
......@@ -388,6 +407,10 @@ void Vt102Emulation::receiveChar(int cc)
}
if (epe( )) { processToken(token_csi_pe(cc), 0, 0); resetTokenizer(); return; }
if (esp ( )) { processToken(token_csi_sp(cc), 0, 0); resetTokenizer(); return; }
if (epsp( )) { processToken(token_csi_psp(cc, argv[0]), 0, 0); resetTokenizer(); return; }
if (ees(DIG)) { addDigit(cc-'0'); return; }
if (eec(';')) { addArgument(); return; }
for (int i = 0; i <= argc; i++)
......@@ -872,6 +895,17 @@ void Vt102Emulation::processToken(int token, int p, int q)
case token_csi_pr('s', 2004) : saveMode (MODE_BracketedPaste); break; //XTERM
case token_csi_pr('r', 2004) : restoreMode (MODE_BracketedPaste); break; //XTERM
// Set Cursor Style (DECSCUSR), VT520, with the extra xterm sequences
// the first one is a special case, 'ESC[ q', which mimics 'ESC[1 q'
case token_csi_sp ('q' ) : emit setCursorStyleRequest(Enum::BlockCursor, true); break;
case token_csi_psp('q', 0) : emit setCursorStyleRequest(Enum::BlockCursor, true); break;
case token_csi_psp('q', 1) : emit setCursorStyleRequest(Enum::BlockCursor, true); break;
case token_csi_psp('q', 2) : emit setCursorStyleRequest(Enum::BlockCursor, false); break;
case token_csi_psp('q', 3) : emit setCursorStyleRequest(Enum::UnderlineCursor, true); break;
case token_csi_psp('q', 4) : emit setCursorStyleRequest(Enum::UnderlineCursor, false); break;
case token_csi_psp('q', 5) : emit setCursorStyleRequest(Enum::IBeamCursor, true); break;
case token_csi_psp('q', 6) : emit setCursorStyleRequest(Enum::IBeamCursor, false); break;
//FIXME: weird DEC reset sequence
case token_csi_pe('p' ) : /* IGNORED: reset ( ) */ break;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment