File indexing completed on 2024-04-21 05:51:30
0001 /* 0002 SPDX-FileCopyrightText: 2007-2008 Robert Knight <robertknight@gmail.com> 0003 SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #ifndef VT102EMULATION_H 0009 #define VT102EMULATION_H 0010 0011 // Qt 0012 #include <QHash> 0013 #include <QMap> 0014 #include <QMediaPlayer> 0015 #include <QPair> 0016 #include <QVector> 0017 0018 // Konsole 0019 #include "Emulation.h" 0020 #include "Screen.h" 0021 #include "keyboardtranslator/KeyboardTranslator.h" 0022 0023 class QTimer; 0024 class QKeyEvent; 0025 0026 #define MODE_AppCuKeys (MODES_SCREEN + 0) // Application cursor keys (DECCKM) 0027 #define MODE_AppKeyPad (MODES_SCREEN + 1) // 0028 #define MODE_Mouse1000 (MODES_SCREEN + 2) // Send mouse X,Y position on press and release 0029 #define MODE_Mouse1001 (MODES_SCREEN + 3) // Use Highlight mouse tracking 0030 #define MODE_Mouse1002 (MODES_SCREEN + 4) // Use cell motion mouse tracking 0031 #define MODE_Mouse1003 (MODES_SCREEN + 5) // Use all motion mouse tracking 0032 #define MODE_Mouse1005 (MODES_SCREEN + 6) // Xterm-style extended coordinates 0033 #define MODE_Mouse1006 (MODES_SCREEN + 7) // 2nd Xterm-style extended coordinates 0034 #define MODE_Mouse1007 (MODES_SCREEN + 8) // XTerm Alternate Scroll mode; also check AlternateScrolling profile property 0035 #define MODE_Mouse1015 (MODES_SCREEN + 9) // Urxvt-style extended coordinates 0036 #define MODE_Ansi (MODES_SCREEN + 10) // Use US Ascii for character sets G0-G3 (DECANM) 0037 #define MODE_132Columns (MODES_SCREEN + 11) // 80 <-> 132 column mode switch (DECCOLM) 0038 #define MODE_Allow132Columns (MODES_SCREEN + 12) // Allow DECCOLM mode 0039 #define MODE_BracketedPaste (MODES_SCREEN + 13) // Xterm-style bracketed paste mode 0040 #define MODE_Sixel (MODES_SCREEN + 14) // Xterm-style bracketed paste mode 0041 #define MODE_total (MODES_SCREEN + 15) 0042 0043 namespace Konsole 0044 { 0045 extern unsigned short vt100_graphics[32]; 0046 0047 struct CharCodes { 0048 // coding info 0049 char charset[4]; // 0050 int cu_cs; // actual charset. 0051 bool graphic; // Some VT100 tricks 0052 bool pound; // Some VT100 tricks 0053 bool sa_graphic; // saved graphic 0054 bool sa_pound; // saved pound 0055 }; 0056 0057 /** 0058 * Provides an xterm compatible terminal emulation based on the DEC VT102 terminal. 0059 * A full description of this terminal can be found at https://vt100.net/docs/vt102-ug/ 0060 * 0061 * In addition, various additional xterm escape sequences are supported to provide 0062 * features such as mouse input handling. 0063 * See https://invisible-island.net/xterm/ctlseqs/ctlseqs.html for a description of xterm's escape 0064 * sequences. 0065 * 0066 */ 0067 class KONSOLEPRIVATE_EXPORT Vt102Emulation : public Emulation 0068 { 0069 Q_OBJECT 0070 0071 public: 0072 /** Constructs a new emulation */ 0073 Vt102Emulation(); 0074 ~Vt102Emulation() override; 0075 0076 // reimplemented from Emulation 0077 void clearEntireScreen() override; 0078 void reset(bool softReset = false, bool preservePrompt = false) override; 0079 char eraseChar() const override; 0080 0081 public Q_SLOTS: 0082 // reimplemented from Emulation 0083 void sendString(const QByteArray &string) override; 0084 void sendText(const QString &text) override; 0085 void sendKeyEvent(QKeyEvent *) override; 0086 void sendMouseEvent(int buttons, int column, int line, int eventType) override; 0087 void focusChanged(bool focused) override; 0088 void clearHistory() override; 0089 0090 protected: 0091 // reimplemented from Emulation 0092 void setMode(int mode) override; 0093 void resetMode(int mode) override; 0094 void receiveChars(const QVector<uint> &chars) override; 0095 0096 private Q_SLOTS: 0097 // Causes sessionAttributeChanged() to be emitted for each (int,QString) 0098 // pair in _pendingSessionAttributesUpdates. 0099 // Used to buffer multiple attribute updates in the current session 0100 void updateSessionAttributes(); 0101 void deletePlayer(QMediaPlayer::MediaStatus); 0102 0103 private: 0104 unsigned int applyCharset(uint c); 0105 void setCharset(int n, int cs); 0106 void useCharset(int n); 0107 void setAndUseCharset(int n, int cs); 0108 void saveCursor(); 0109 void restoreCursor(); 0110 void resetCharset(int scrno); 0111 0112 void setMargins(int top, int bottom); 0113 // set margins for all screens back to their defaults 0114 void setDefaultMargins(); 0115 0116 // returns true if 'mode' is set or false otherwise 0117 bool getMode(int mode); 0118 // saves the current boolean value of 'mode' 0119 void saveMode(int mode); 0120 // restores the boolean value of 'mode' 0121 void restoreMode(int mode); 0122 // resets all modes 0123 // (except MODE_Allow132Columns) 0124 void resetModes(); 0125 0126 void resetTokenizer(); 0127 #define MAX_TOKEN_LENGTH 256 // Max length of tokens (e.g. window title) 0128 void addToCurrentToken(uint cc); 0129 int tokenBufferPos; 0130 0131 protected: 0132 char32_t tokenBuffer[MAX_TOKEN_LENGTH]; // FIXME: overflow? 0133 0134 private: 0135 #define MAXARGS 16 0136 void addDigit(int dig); 0137 void addArgument(); 0138 void addSub(); 0139 0140 struct subParam { 0141 int value[MAXARGS]; // value[0] unused, it would correspond to the containing param value 0142 int count; 0143 }; 0144 0145 struct { 0146 int value[MAXARGS]; 0147 struct subParam sub[MAXARGS]; 0148 int count; 0149 bool hasSubParams; 0150 } params = {}; 0151 0152 void initTokenizer(); 0153 0154 enum ParserStates { 0155 Ground, 0156 Escape, 0157 EscapeIntermediate, 0158 CsiEntry, 0159 CsiParam, 0160 CsiIntermediate, 0161 CsiIgnore, 0162 DcsEntry, 0163 DcsParam, 0164 DcsIntermediate, 0165 DcsPassthrough, 0166 DcsIgnore, 0167 OscString, 0168 SosPmApcString, 0169 0170 Vt52Escape, 0171 Vt52CupRow, 0172 Vt52CupColumn, 0173 }; 0174 0175 enum { 0176 Sos, 0177 Pm, 0178 Apc, 0179 } _sosPmApc; 0180 0181 enum osc { 0182 // https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands 0183 ReportColors = 4, 0184 ResetColors = 104, 0185 // https://gitlab.freedesktop.org/Per_Bothner/specifications/blob/master/proposals/semantic-prompts.md 0186 SemanticPrompts = 133, 0187 // https://chromium.googlesource.com/apps/libapps/+/master/hterm/doc/ControlSequences.md#OSC 0188 Notification = 777, 0189 Image = 1337, 0190 }; 0191 0192 ParserStates _state = Ground; 0193 bool _ignore = false; 0194 int _nIntermediate = 0; 0195 unsigned char _intermediate[1]; 0196 0197 void switchState(const ParserStates newState, const uint cc); 0198 void esc_dispatch(const uint cc); 0199 void clear(); 0200 void collect(const uint cc); 0201 void param(const uint cc); 0202 void csi_dispatch(const uint cc); 0203 void osc_start(); 0204 void osc_put(const uint cc); 0205 void osc_end(const uint cc); 0206 void hook(const uint cc); 0207 void unhook(); 0208 void put(const uint cc); 0209 void apc_start(const uint cc); 0210 void apc_put(const uint cc); 0211 void apc_end(); 0212 0213 // State machine for escape sequences containing large amount of data 0214 int tokenState; 0215 const char *tokenStateChange; 0216 int tokenPos; 0217 QByteArray tokenData; 0218 0219 // Set of flags for each of the ASCII characters which indicates 0220 // what category they fall into (printable character, control, digit etc.) 0221 // for the purposes of decoding terminal output 0222 int charClass[256]; 0223 0224 QByteArray imageData; 0225 quint32 imageId; 0226 QMap<char, qint64> savedKeys; 0227 0228 protected: 0229 virtual void reportDecodingError(int token); 0230 0231 virtual void processToken(int code, int p, int q); 0232 virtual void processSessionAttributeRequest(const int tokenSize, const uint terminator); 0233 virtual void processChecksumRequest(int argc, int argv[]); 0234 0235 private: 0236 void processGraphicsToken(int tokenSize); 0237 0238 void sendGraphicsReply(const QString ¶ms, const QString &error); 0239 void reportTerminalType(); 0240 void reportTertiaryAttributes(); 0241 void reportSecondaryAttributes(); 0242 void reportVersion(); 0243 void reportStatus(); 0244 void reportAnswerBack(); 0245 void reportCursorPosition(); 0246 void reportPixelSize(); 0247 void reportCellSize(); 0248 void iTermReportCellSize(); 0249 void reportSize(); 0250 void reportColor(int c, QColor color); 0251 void reportTerminalParms(int p); 0252 0253 void emulateUpDown(bool up, KeyboardTranslator::Entry entry, QByteArray &textToSend, int toCol = -1); 0254 0255 // clears the screen and resizes it to the specified 0256 // number of columns 0257 void clearScreenAndSetColumns(int columnCount); 0258 0259 CharCodes _charset[2]; 0260 0261 class TerminalState 0262 { 0263 public: 0264 // Initializes all modes to false 0265 TerminalState() 0266 { 0267 memset(&mode, 0, MODE_total * sizeof(bool)); 0268 } 0269 0270 bool mode[MODE_total]; 0271 }; 0272 0273 TerminalState _currentModes; 0274 TerminalState _savedModes; 0275 0276 // Hash table and timer for buffering calls to update certain session 0277 // attributes (e.g. the name of the session, window title). 0278 // These calls occur when certain escape sequences are detected in the 0279 // output from the terminal. See Emulation::sessionAttributeChanged() 0280 QHash<int, QString> _pendingSessionAttributesUpdates; 0281 QTimer *_sessionAttributesUpdateTimer; 0282 0283 bool _reportFocusEvents; 0284 0285 QColor colorTable[256]; 0286 0287 // Sixel: 0288 #define MAX_SIXEL_COLORS 256 0289 #define MAX_IMAGE_DIM 16384 0290 void sixelQuery(int query); 0291 bool processSixel(uint cc); 0292 void SixelModeEnable(int width, int height /*, bool preserveBackground*/); 0293 void SixelModeAbort(); 0294 void SixelModeDisable(); 0295 void SixelColorChangeRGB(const int index, int red, int green, int blue); 0296 void SixelColorChangeHSL(const int index, int hue, int saturation, int value); 0297 void SixelCharacterAdd(uint8_t character, int repeat = 1); 0298 bool m_SixelPictureDefinition = false; 0299 bool m_SixelStarted = false; 0300 QImage m_currentImage; 0301 int m_currentX = 0; 0302 int m_verticalPosition = 0; 0303 uint8_t m_currentColor = 0; 0304 bool m_preserveBackground = true; 0305 QPair<int, int> m_aspect = qMakePair(1, 1); 0306 bool m_SixelScrolling = true; 0307 QSize m_actualSize; // For efficiency reasons, we keep the image in memory larger than what the end result is 0308 0309 // Kitty 0310 QHash<int, QPixmap> _graphicsImages; 0311 // For kitty graphics protocol - image cache 0312 int getFreeGraphicsImageId(); 0313 0314 QMediaPlayer *player; 0315 }; 0316 0317 } 0318 0319 #endif // VT102EMULATION_H