mirror of
https://github.com/KDE/konsole.git
synced 2025-12-23 15:28:03 -05:00
Add dumb terminal emulation
A dumb terminal has only one control sequence: \r which moves the cursor to the start of the next line. Profile option `Emulation` selects which emulation to use. Any value other than `dumb` selects the standard Vt102 emulation. Updated version of !629
This commit is contained in:
committed by
Kurt Hindenburg
parent
8ab289866a
commit
774b655dd1
@@ -168,6 +168,7 @@ set(konsoleprivate_SRCS ${windowadaptors_SRCS}
|
||||
ViewManager.cpp
|
||||
ViewProperties.cpp
|
||||
Vt102Emulation.cpp
|
||||
DumbEmulation.cpp
|
||||
WindowSystemInfo.cpp
|
||||
ZModemDialog.cpp
|
||||
filterHotSpots/EscapeSequenceUrlFilter.cpp
|
||||
|
||||
199
src/DumbEmulation.cpp
Normal file
199
src/DumbEmulation.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2007-2008 Robert Knight <robert.knight@gmail.com>
|
||||
SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
// Own
|
||||
#include "DumbEmulation.h"
|
||||
#include "config-konsole.h"
|
||||
|
||||
// Standard
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
|
||||
// Qt
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
// KDE
|
||||
#include <KLocalizedString>
|
||||
|
||||
// Konsole
|
||||
#include "keyboardtranslator/KeyboardTranslator.h"
|
||||
#include "session/SessionController.h"
|
||||
#include "terminalDisplay/TerminalDisplay.h"
|
||||
|
||||
using Konsole::DumbEmulation;
|
||||
|
||||
DumbEmulation::DumbEmulation()
|
||||
: Emulation()
|
||||
{
|
||||
TERM = QStringLiteral("dumb");
|
||||
}
|
||||
|
||||
DumbEmulation::~DumbEmulation()
|
||||
{
|
||||
}
|
||||
|
||||
void DumbEmulation::clearEntireScreen()
|
||||
{
|
||||
_currentScreen->clearEntireScreen();
|
||||
bufferedUpdate();
|
||||
}
|
||||
|
||||
void DumbEmulation::reset([[maybe_unused]] bool softReset, [[maybe_unused]] bool preservePrompt)
|
||||
{
|
||||
|
||||
// Save the current codec so we can set it later.
|
||||
// Ideally we would want to use the profile setting
|
||||
const QByteArray currentCodec(encoder().name());
|
||||
|
||||
if (currentCodec != nullptr) {
|
||||
setCodec(currentCodec);
|
||||
} else {
|
||||
setCodec(LocaleCodec);
|
||||
}
|
||||
|
||||
Q_EMIT resetCursorStyleRequest();
|
||||
|
||||
bufferedUpdate();
|
||||
}
|
||||
|
||||
// process an incoming unicode character
|
||||
void DumbEmulation::receiveChars(const QVector<uint> &chars)
|
||||
{
|
||||
for (uint cc : chars) {
|
||||
if (cc == '\r') {
|
||||
_currentScreen->nextLine();
|
||||
continue;
|
||||
}
|
||||
_currentScreen->displayCharacter(cc);
|
||||
}
|
||||
}
|
||||
|
||||
void DumbEmulation::sendString(const QByteArray &s)
|
||||
{
|
||||
Q_EMIT sendData(s);
|
||||
}
|
||||
|
||||
void DumbEmulation::sendText(const QString &text)
|
||||
{
|
||||
if (!text.isEmpty()) {
|
||||
QKeyEvent event(QEvent::KeyPress, 0, Qt::NoModifier, text);
|
||||
sendKeyEvent(&event); // expose as a big fat keypress event
|
||||
}
|
||||
}
|
||||
|
||||
void DumbEmulation::sendKeyEvent(QKeyEvent *event)
|
||||
{
|
||||
const Qt::KeyboardModifiers modifiers = event->modifiers();
|
||||
KeyboardTranslator::States states = KeyboardTranslator::NoState;
|
||||
|
||||
TerminalDisplay *currentView = _currentScreen->currentTerminalDisplay();
|
||||
bool isReadOnly = false;
|
||||
if (currentView != nullptr) {
|
||||
isReadOnly = currentView->getReadOnly();
|
||||
}
|
||||
|
||||
if (!isReadOnly) {
|
||||
// check flow control state
|
||||
if ((modifiers & Qt::ControlModifier) != 0U) {
|
||||
switch (event->key()) {
|
||||
case Qt::Key_S:
|
||||
Q_EMIT flowControlKeyPressed(true);
|
||||
break;
|
||||
case Qt::Key_C:
|
||||
// No Sixel support
|
||||
case Qt::Key_Q: // cancel flow control
|
||||
Q_EMIT flowControlKeyPressed(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// look up key binding
|
||||
if (_keyTranslator != nullptr) {
|
||||
KeyboardTranslator::Entry entry = _keyTranslator->findEntry(event->key(), modifiers, states);
|
||||
|
||||
// send result to terminal
|
||||
QByteArray textToSend;
|
||||
|
||||
// special handling for the Alt (aka. Meta) modifier. pressing
|
||||
// Alt+[Character] results in Esc+[Character] being sent
|
||||
// (unless there is an entry defined for this particular combination
|
||||
// in the keyboard modifier)
|
||||
const bool wantsAltModifier = ((entry.modifiers() & entry.modifierMask() & Qt::AltModifier) != 0U);
|
||||
const bool wantsMetaModifier = ((entry.modifiers() & entry.modifierMask() & Qt::MetaModifier) != 0U);
|
||||
const bool wantsAnyModifier = ((entry.state() & entry.stateMask() & KeyboardTranslator::AnyModifierState) != 0);
|
||||
|
||||
if (((modifiers & Qt::AltModifier) != 0U) && !(wantsAltModifier || wantsAnyModifier) && !event->text().isEmpty()) {
|
||||
textToSend.prepend("\033");
|
||||
}
|
||||
if (((modifiers & Qt::MetaModifier) != 0U) && !(wantsMetaModifier || wantsAnyModifier) && !event->text().isEmpty()) {
|
||||
textToSend.prepend("\030@s");
|
||||
}
|
||||
|
||||
if (entry.command() != KeyboardTranslator::NoCommand) {
|
||||
if ((entry.command() & KeyboardTranslator::EraseCommand) != 0) {
|
||||
textToSend += eraseChar();
|
||||
}
|
||||
} else if (!entry.text().isEmpty()) {
|
||||
textToSend += entry.text(true, modifiers);
|
||||
} else {
|
||||
Q_ASSERT(_encoder.isValid());
|
||||
textToSend += _encoder.encode(event->text());
|
||||
}
|
||||
|
||||
if (!isReadOnly) {
|
||||
Q_EMIT sendData(textToSend);
|
||||
}
|
||||
} else {
|
||||
if (!isReadOnly) {
|
||||
// print an error message to the terminal if no key translator has been
|
||||
// set
|
||||
QString translatorError = i18n(
|
||||
"No keyboard translator available. "
|
||||
"The information needed to convert key presses "
|
||||
"into characters to send to the terminal "
|
||||
"is missing.");
|
||||
reset();
|
||||
receiveData(translatorError.toLatin1().constData(), translatorError.count());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DumbEmulation::setMode(int)
|
||||
{
|
||||
}
|
||||
|
||||
void DumbEmulation::resetMode(int)
|
||||
{
|
||||
}
|
||||
|
||||
void DumbEmulation::saveCursor()
|
||||
{
|
||||
_currentScreen->saveCursor();
|
||||
}
|
||||
|
||||
void DumbEmulation::restoreCursor()
|
||||
{
|
||||
_currentScreen->restoreCursor();
|
||||
}
|
||||
|
||||
void DumbEmulation::updateSessionAttributes()
|
||||
{
|
||||
}
|
||||
|
||||
char DumbEmulation::eraseChar() const
|
||||
{
|
||||
return '\b';
|
||||
}
|
||||
|
||||
void DumbEmulation::focusChanged([[maybe_unused]] bool focused)
|
||||
{
|
||||
}
|
||||
|
||||
void DumbEmulation::sendMouseEvent([[maybe_unused]] int cb, [[maybe_unused]] int cx, [[maybe_unused]] int cy, [[maybe_unused]] int eventType)
|
||||
{
|
||||
}
|
||||
77
src/DumbEmulation.h
Normal file
77
src/DumbEmulation.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2007-2008 Robert Knight <robert.knight@gmail.com>
|
||||
SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef DUMBEMULATION_H
|
||||
#define DUMBEMULATION_H
|
||||
|
||||
// Qt
|
||||
#include <QVector>
|
||||
|
||||
// Konsole
|
||||
#include "Emulation.h"
|
||||
#include "Screen.h"
|
||||
|
||||
class QTimer;
|
||||
class QKeyEvent;
|
||||
|
||||
namespace Konsole
|
||||
{
|
||||
/**
|
||||
* Provides a dumb terminal emulation.
|
||||
* The only non printable character is \n
|
||||
*/
|
||||
class KONSOLEPRIVATE_EXPORT DumbEmulation : public Emulation
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/** Constructs a new emulation */
|
||||
DumbEmulation();
|
||||
~DumbEmulation() override;
|
||||
|
||||
// reimplemented from Emulation
|
||||
void clearEntireScreen() override;
|
||||
void reset(bool softReset = false, bool preservePrompt = false) override;
|
||||
char eraseChar() const override;
|
||||
|
||||
public Q_SLOTS:
|
||||
// reimplemented from Emulation
|
||||
void sendString(const QByteArray &string) override;
|
||||
void sendText(const QString &text) override;
|
||||
void sendKeyEvent(QKeyEvent *) override;
|
||||
void sendMouseEvent(int buttons, int column, int line, int eventType) override;
|
||||
void focusChanged(bool focused) override;
|
||||
|
||||
protected:
|
||||
// reimplemented from Emulation
|
||||
void setMode(int mode) override;
|
||||
void resetMode(int mode) override;
|
||||
void receiveChars(const QVector<uint> &chars) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
// Causes sessionAttributeChanged() to be emitted for each (int,QString)
|
||||
// pair in _pendingSessionAttributesUpdates.
|
||||
// Used to buffer multiple attribute updates in the current session
|
||||
void updateSessionAttributes();
|
||||
|
||||
private:
|
||||
unsigned int applyCharset(uint c);
|
||||
void setCharset(int n, int cs);
|
||||
void useCharset(int n);
|
||||
void setAndUseCharset(int n, int cs);
|
||||
void saveCursor();
|
||||
void restoreCursor();
|
||||
void resetCharset(int scrno);
|
||||
|
||||
// clears the screen and resizes it to the specified
|
||||
// number of columns
|
||||
void clearScreenAndSetColumns(int columnCount);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // DUMBEMULATION_H
|
||||
@@ -89,6 +89,8 @@ public:
|
||||
Emulation();
|
||||
~Emulation() override;
|
||||
|
||||
QString TERM;
|
||||
|
||||
/**
|
||||
* Creates a new window onto the output from this emulation. The contents
|
||||
* of the window are then rendered by views which are set to use this window using the
|
||||
|
||||
@@ -78,6 +78,8 @@ Vt102Emulation::Vt102Emulation()
|
||||
_sessionAttributesUpdateTimer->setSingleShot(true);
|
||||
QObject::connect(_sessionAttributesUpdateTimer, &QTimer::timeout, this, &Konsole::Vt102Emulation::updateSessionAttributes);
|
||||
|
||||
TERM = QStringLiteral("xterm-256color");
|
||||
|
||||
initTokenizer();
|
||||
imageId = 0;
|
||||
savedKeys = QMap<char, qint64>();
|
||||
|
||||
@@ -144,6 +144,7 @@ const std::vector<Profile::PropertyInfo> Profile::DefaultProperties = {
|
||||
{PeekPrimaryKeySequence, "PeekPrimaryKeySequence", TERMINAL_GROUP, QString()},
|
||||
{LineNumbers, "LineNumbers", TERMINAL_GROUP, 0},
|
||||
{AutoSaveInterval, "AutoSaveInterval", TERMINAL_GROUP, 10000},
|
||||
{Emulation, "Emulation", TERMINAL_GROUP, QVariant::String},
|
||||
|
||||
// Cursor
|
||||
{UseCustomCursorColor, "UseCustomCursorColor", CURSOR_GROUP, false},
|
||||
|
||||
@@ -361,6 +361,8 @@ public:
|
||||
/** Shortcut for peeking primary screen */
|
||||
PeekPrimaryKeySequence,
|
||||
|
||||
Emulation,
|
||||
|
||||
/** (bool) If true, text that matches a color in hex format
|
||||
* when hovered by the mouse pointer.
|
||||
*/
|
||||
@@ -903,6 +905,11 @@ public:
|
||||
return property<bool>(Profile::SemanticInputClick);
|
||||
}
|
||||
|
||||
QString emulation() const
|
||||
{
|
||||
return property<QString>(Profile::Emulation);
|
||||
}
|
||||
|
||||
/** Return a list of all properties names and their type
|
||||
* (for use with -p option).
|
||||
*/
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <sessionadaptor.h>
|
||||
#endif
|
||||
|
||||
#include "DumbEmulation.h"
|
||||
#include "Pty.h"
|
||||
#include "SSHProcessInfo.h"
|
||||
#include "SessionController.h"
|
||||
@@ -79,8 +80,12 @@ using namespace Konsole;
|
||||
static bool show_disallow_certain_dbus_methods_message = true;
|
||||
|
||||
static const int ZMODEM_BUFFER_SIZE = 1048576; // 1 Mb
|
||||
|
||||
Session::Session(QObject *parent)
|
||||
{
|
||||
Session(parent, Profile::Ptr());
|
||||
}
|
||||
|
||||
Session::Session(QObject *parent, Profile::Ptr profile)
|
||||
: QObject(parent)
|
||||
{
|
||||
_uniqueIdentifier = QUuid::createUuid();
|
||||
@@ -101,7 +106,11 @@ Session::Session(QObject *parent)
|
||||
#endif
|
||||
|
||||
// create emulation backend
|
||||
_emulation = new Vt102Emulation();
|
||||
if (profile->emulation() == QStringLiteral("dumb")) {
|
||||
_emulation = new DumbEmulation();
|
||||
} else {
|
||||
_emulation = new Vt102Emulation();
|
||||
}
|
||||
_emulation->reset();
|
||||
|
||||
connect(_emulation, &Konsole::Emulation::sessionAttributeChanged, this, &Konsole::Session::setSessionAttribute);
|
||||
@@ -552,6 +561,7 @@ void Session::run()
|
||||
addEnvironmentEntry(QStringLiteral("SHELL_SESSION_ID=%1").arg(shellSessionId()));
|
||||
|
||||
addEnvironmentEntry(QStringLiteral("WINDOWID=%1").arg(QString::number(windowId())));
|
||||
addEnvironmentEntry(QStringLiteral("TERM=%1").arg(_emulation->TERM));
|
||||
|
||||
#if HAVE_DBUS
|
||||
const QString dbusService = QDBusConnection::sessionBus().baseService();
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "Shortcut_p.h"
|
||||
#include "config-konsole.h"
|
||||
#include "konsoleprivate_export.h"
|
||||
#include "profile/Profile.h"
|
||||
|
||||
class QColor;
|
||||
class QTextCodec;
|
||||
@@ -76,6 +77,7 @@ public:
|
||||
* variable.
|
||||
*/
|
||||
explicit Session(QObject *parent = nullptr);
|
||||
explicit Session(QObject *parent, Profile::Ptr profile);
|
||||
~Session() override;
|
||||
|
||||
/* Returns the process info so the plugins can peek at it's name */
|
||||
|
||||
@@ -93,7 +93,7 @@ Session *SessionManager::createSession(Profile::Ptr profile)
|
||||
}
|
||||
|
||||
// configuration information found, create a new session based on this
|
||||
auto session = new Session();
|
||||
auto session = new Session(nullptr, profile);
|
||||
Q_ASSERT(session);
|
||||
applyProfile(session, profile, false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user