diff --git a/src/Emulation.cpp b/src/Emulation.cpp index 02ed4be..80d93ba 100644 --- a/src/Emulation.cpp +++ b/src/Emulation.cpp @@ -39,6 +39,7 @@ Emulation::Emulation() : _decoder(0), _keyTranslator(0), _usesMouse(false), + _bracketedPasteMode(false), _imageSizeInitialized(false) { // create screens with a default size @@ -52,6 +53,8 @@ Emulation::Emulation() : // listen for mouse status changes connect(this , SIGNAL(programUsesMouseChanged(bool)) , SLOT(usesMouseChanged(bool))); + connect(this , SIGNAL(programBracketedPasteModeChanged(bool)) , + SLOT(bracketedPasteModeChanged(bool))); } bool Emulation::programUsesMouse() const @@ -64,6 +67,16 @@ void Emulation::usesMouseChanged(bool usesMouse) _usesMouse = usesMouse; } +bool Emulation::programBracketedPasteMode() const +{ + return _bracketedPasteMode; +} + +void Emulation::bracketedPasteModeChanged(bool bracketedPasteMode) +{ + _bracketedPasteMode = bracketedPasteMode; +} + ScreenWindow* Emulation::createWindow() { ScreenWindow* window = new ScreenWindow(); diff --git a/src/Emulation.h b/src/Emulation.h index aa24d69..966b423 100644 --- a/src/Emulation.h +++ b/src/Emulation.h @@ -215,6 +215,8 @@ public: */ bool programUsesMouse() const; + bool programBracketedPasteMode() const; + public slots: /** Change the size of the emulation's image */ @@ -314,6 +316,8 @@ signals: */ void programUsesMouseChanged(bool usesMouse); + void programBracketedPasteModeChanged(bool bracketedPasteMode); + /** * Emitted when the contents of the screen image change. * The emulation buffers the updates from successive image changes, @@ -474,8 +478,11 @@ private slots: void usesMouseChanged(bool usesMouse); + void bracketedPasteModeChanged(bool bracketedPasteMode); + private: bool _usesMouse; + bool _bracketedPasteMode; QTimer _bulkTimer1; QTimer _bulkTimer2; bool _imageSizeInitialized; diff --git a/src/Session.cpp b/src/Session.cpp index 2d8ca89..68e8ef7 100644 --- a/src/Session.cpp +++ b/src/Session.cpp @@ -326,6 +326,11 @@ void Session::addView(TerminalDisplay* widget) widget->setUsesMouse(_emulation->programUsesMouse()); + connect(_emulation, SIGNAL(programBracketedPasteModeChanged(bool)), + widget, SLOT(setBracketedPasteMode(bool))); + + widget->setBracketedPasteMode(_emulation->programBracketedPasteMode()); + widget->setScreenWindow(_emulation->createWindow()); //connect view signals and slots diff --git a/src/TerminalDisplay.cpp b/src/TerminalDisplay.cpp index 871dc9f..be80e7c 100644 --- a/src/TerminalDisplay.cpp +++ b/src/TerminalDisplay.cpp @@ -51,6 +51,7 @@ #include #include #include +#include // Konsole #include "Filter.h" @@ -367,6 +368,7 @@ TerminalDisplay::TerminalDisplay(QWidget* parent) setMouseTracking(true); setUsesMouse(true); + setBracketedPasteMode(false); setColorTable(ColorScheme::defaultTable); @@ -2554,6 +2556,15 @@ bool TerminalDisplay::usesMouse() const return _mouseMarks; } +void TerminalDisplay::setBracketedPasteMode(bool on) +{ + _bracketedPasteMode = on; +} +bool TerminalDisplay::bracketedPasteMode() const +{ + return _bracketedPasteMode; +} + /* ------------------------------------------------------------------------- */ /* */ /* Clipboard */ @@ -2568,8 +2579,84 @@ void TerminalDisplay::doPaste(QString text, bool appendReturn) if (appendReturn) text.append("\r"); + QStringList unsafeCharacters; + Q_FOREACH (const QChar &c, text) { + if (!c.isPrint() && c != QLatin1Char('\t') && c != QLatin1Char('\n')) { + QString description; + switch(c.unicode()) { + case '\x03': + description = i18n("^C Interrupt: May abort the current process"); + break; + case '\x04': + description = i18n("^D End of transmission: May exit the current process"); + break; + case '\x07': + description = i18n("^G Bell: Will try to emit an audible warning"); + break; + case '\x08': + description = i18n("^H Backspace"); + break; + case '\x13': + description = i18n("^S Scroll lock: Locks terminal output"); + break; + case '\x1a': + description = i18n("^Z Suspend: Stops current process"); + break; + case '\x1b': + description = i18n("ESC: Used for special commands to the current process"); + break; + default: + description = i18n("Other unprintable character (\\x%1)").arg(QString::number(c.unicode(), 16)); + break; + } + unsafeCharacters.append(description); + } + } + unsafeCharacters.removeDuplicates(); + + if (!unsafeCharacters.isEmpty()) { + int result = KMessageBox::warningYesNoCancelList(window(), + i18n("The text you're trying to paste contains hidden unprintable characters, " + "do you want to filter them out?"), + unsafeCharacters, + i18nc("@title", "Filter"), + KGuiItem(i18nc("@action:button", + "&Remove unprintable"), + QLatin1String("filter-symbolic")), + KGuiItem(i18nc("@action:button", + "Confirm &paste"), + QLatin1String("edit-paste")), + KGuiItem(i18nc("@action:button", + "&Cancel paste"), + QLatin1String("dialog-cancel")), + QLatin1String("ShowPasteUnprintableWarning") + ); + switch(result){ + case KMessageBox::Cancel: + return; + case KMessageBox::Yes: { + QString sanitized; + Q_FOREACH (const QChar &c, text) { + if (c.isPrint() || c == QLatin1Char('\t') || c == QLatin1Char('\n')) { + sanitized.append(c); + } + } + text = sanitized; + } + case KMessageBox::No: + break; + default: + break; + } + } + if (!text.isEmpty()) { text.replace('\n', '\r'); + if (bracketedPasteMode()) { + text.remove(QLatin1String("\033")); + text.prepend("\033[200~"); + text.append("\033[201~"); + } // perform paste by simulating keypress events QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text); emit keyPressedSignal(&e); diff --git a/src/TerminalDisplay.h b/src/TerminalDisplay.h index 8e246b8..23913d1 100644 --- a/src/TerminalDisplay.h +++ b/src/TerminalDisplay.h @@ -512,6 +512,9 @@ public slots: /** See setUsesMouse() */ bool usesMouse() const; + void setBracketedPasteMode(bool bracketedPasteMode); + bool bracketedPasteMode() const; + /** * Shows a notification that a bell event has occurred in the terminal. * TODO: More documentation here @@ -770,6 +773,7 @@ private: bool _showTerminalSizeHint; bool _bidiEnabled; bool _mouseMarks; + bool _bracketedPasteMode; QPoint _iPntSel; // initial selection point QPoint _pntSel; // current selection point diff --git a/src/Vt102Emulation.cpp b/src/Vt102Emulation.cpp index 7f663f2..76b3ac5 100644 --- a/src/Vt102Emulation.cpp +++ b/src/Vt102Emulation.cpp @@ -787,6 +787,11 @@ void Vt102Emulation::processToken(int token, int p, int q) case TY_CSI_PR('h', 1049) : saveCursor(); _screen[1]->clearEntireScreen(); setMode(MODE_AppScreen); break; //XTERM case TY_CSI_PR('l', 1049) : resetMode(MODE_AppScreen); restoreCursor(); break; //XTERM + case TY_CSI_PR('h', 2004) : setMode (MODE_BracketedPaste); break; //XTERM + case TY_CSI_PR('l', 2004) : resetMode (MODE_BracketedPaste); break; //XTERM + case TY_CSI_PR('s', 2004) : saveMode (MODE_BracketedPaste); break; //XTERM + case TY_CSI_PR('r', 2004) : restoreMode (MODE_BracketedPaste); break; //XTERM + //FIXME: weird DEC reset sequence case TY_CSI_PE('p' ) : /* IGNORED: reset ( ) */ break; @@ -1194,6 +1199,7 @@ void Vt102Emulation::resetModes() resetMode(MODE_Mouse1005); saveMode(MODE_Mouse1005); resetMode(MODE_Mouse1006); saveMode(MODE_Mouse1006); resetMode(MODE_Mouse1015); saveMode(MODE_Mouse1015); + resetMode(MODE_BracketedPaste); saveMode(MODE_BracketedPaste); resetMode(MODE_AppScreen); saveMode(MODE_AppScreen); resetMode(MODE_AppCuKeys); saveMode(MODE_AppCuKeys); @@ -1219,6 +1225,10 @@ void Vt102Emulation::setMode(int m) emit programUsesMouseChanged(false); break; + case MODE_BracketedPaste: + emit programBracketedPasteModeChanged(true); + break; + case MODE_AppScreen : _screen[1]->clearSelection(); setScreen(1); @@ -1245,6 +1255,10 @@ void Vt102Emulation::resetMode(int m) emit programUsesMouseChanged(true); break; + case MODE_BracketedPaste: + emit programBracketedPasteModeChanged(false); + break; + case MODE_AppScreen : _screen[0]->clearSelection(); setScreen(0); diff --git a/src/Vt102Emulation.h b/src/Vt102Emulation.h index c15f6ea..8d678e0 100644 --- a/src/Vt102Emulation.h +++ b/src/Vt102Emulation.h @@ -46,7 +46,8 @@ class QKeyEvent; #define MODE_Ansi (MODES_SCREEN+10) // Use US Ascii for character sets G0-G3 (DECANM) #define MODE_132Columns (MODES_SCREEN+11) // 80 <-> 132 column mode switch (DECCOLM) #define MODE_Allow132Columns (MODES_SCREEN+12) // Allow DECCOLM mode -#define MODE_total (MODES_SCREEN+13) +#define MODE_BracketedPaste (MODES_SCREEN+13) // Xterm-style bracketed paste mode +#define MODE_total (MODES_SCREEN+14) namespace Konsole {