1 /* 2 This file is part of Konsole, an X terminal. 3 4 Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com> 5 Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> 6 7 Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008 8 9 This program is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 22 02110-1301 USA. 23 */ 24 25 #ifndef EMULATION_H 26 #define EMULATION_H 27 28 // System 29 #include <stdio.h> 30 31 // Qt 32 #include <QKeyEvent> 33 34 #include <QtCore/QTextCodec> 35 #include <QtCore/QTextStream> 36 #include <QtCore/QTimer> 37 38 class KeyboardTranslator; 39 class HistoryType; 40 class Screen; 41 class ScreenWindow; 42 class TerminalCharacterDecoder; 43 44 /** 45 * This enum describes the available states which 46 * the terminal emulation may be set to. 47 * 48 * These are the values used by Emulation::stateChanged() 49 */ 50 enum 51 { 52 /** The emulation is currently receiving user input. */ 53 NOTIFYNORMAL=0, 54 /** 55 * The terminal program has triggered a bell event 56 * to get the user's attention. 57 */ 58 NOTIFYBELL=1, 59 /** 60 * The emulation is currently receiving data from its 61 * terminal input. 62 */ 63 NOTIFYACTIVITY=2, 64 65 // unused here? 66 NOTIFYSILENCE=3 67 }; 68 69 /** 70 * Base class for terminal emulation back-ends. 71 * 72 * The back-end is responsible for decoding an incoming character stream and 73 * producing an output image of characters. 74 * 75 * When input from the terminal is received, the receiveData() slot should be called with 76 * the data which has arrived. The emulation will process the data and update the 77 * screen image accordingly. The codec used to decode the incoming character stream 78 * into the unicode characters used internally can be specified using setCodec() 79 * 80 * The size of the screen image can be specified by calling setImageSize() with the 81 * desired number of lines and columns. When new lines are added, old content 82 * is moved into a history store, which can be set by calling setHistory(). 83 * 84 * The screen image can be accessed by creating a ScreenWindow onto this emulation 85 * by calling createWindow(). Screen windows provide access to a section of the 86 * output. Each screen window covers the same number of lines and columns as the 87 * image size returned by imageSize(). The screen window can be moved up and down 88 * and provides transparent access to both the current on-screen image and the 89 * previous output. The screen windows emit an outputChanged signal 90 * when the section of the image they are looking at changes. 91 * Graphical views can then render the contents of a screen window, listening for notifications 92 * of output changes from the screen window which they are associated with and updating 93 * accordingly. 94 * 95 * The emulation also is also responsible for converting input from the connected views such 96 * as keypresses and mouse activity into a character string which can be sent 97 * to the terminal program. Key presses can be processed by calling the sendKeyEvent() slot, 98 * while mouse events can be processed using the sendMouseEvent() slot. When the character 99 * stream has been produced, the emulation will emit a sendData() signal with a pointer 100 * to the character buffer. This data should be fed to the standard input of the terminal 101 * process. The translation of key presses into an output character stream is performed 102 * using a lookup in a set of key bindings which map key sequences to output 103 * character sequences. The name of the key bindings set used can be specified using 104 * setKeyBindings() 105 * 106 * The emulation maintains certain state information which changes depending on the 107 * input received. The emulation can be reset back to its starting state by calling 108 * reset(). 109 * 110 * The emulation also maintains an activity state, which specifies whether 111 * terminal is currently active ( when data is received ), normal 112 * ( when the terminal is idle or receiving user input ) or trying 113 * to alert the user ( also known as a "Bell" event ). The stateSet() signal 114 * is emitted whenever the activity state is set. This can be used to determine 115 * how long the emulation has been active/idle for and also respond to 116 * a 'bell' event in different ways. 117 */ 118 class Emulation : public QObject 119 { 120 Q_OBJECT 121 122 public: 123 124 /** Constructs a new terminal emulation */ 125 Emulation(); 126 ~Emulation(); 127 128 /** 129 * Creates a new window onto the output from this emulation. The contents 130 * of the window are then rendered by views which are set to use this window using the 131 * TerminalDisplay::setScreenWindow() method. 132 */ 133 ScreenWindow* createWindow(); 134 135 /** Returns the size of the screen image which the emulation produces */ 136 QSize imageSize(); 137 138 /** 139 * Returns the total number of lines, including those stored in the history. 140 */ 141 int lineCount(); 142 143 144 /** 145 * Sets the history store used by this emulation. When new lines 146 * are added to the output, older lines at the top of the screen are transferred to a history 147 * store. 148 * 149 * The number of lines which are kept and the storage location depend on the 150 * type of store. 151 */ 152 void setHistory(const HistoryType&); 153 /** Returns the history store used by this emulation. See setHistory() */ 154 const HistoryType& history(); 155 /** Clears the history scroll. */ 156 void clearHistory(); 157 158 /** 159 * Copies the output history from @p startLine to @p endLine 160 * into @p stream, using @p decoder to convert the terminal 161 * characters into text. 162 * 163 * @param decoder A decoder which converts lines of terminal characters with 164 * appearance attributes into output text. PlainTextDecoder is the most commonly 165 * used decoder. 166 * @param startLine The first 167 */ 168 virtual void writeToStream(TerminalCharacterDecoder* decoder,int startLine,int endLine); 169 170 171 /** Returns the codec used to decode incoming characters. See setCodec() */ codec()172 const QTextCodec* codec() { return _codec; } 173 /** Sets the codec used to decode incoming characters. */ 174 void setCodec(const QTextCodec*); 175 176 /** 177 * Convenience method. 178 * Returns true if the current codec used to decode incoming 179 * characters is UTF-8 180 */ utf8()181 bool utf8() { Q_ASSERT(_codec); return _codec->mibEnum() == 106; } 182 183 184 /** TODO Document me */ 185 virtual char getErase() const; 186 187 /** 188 * Sets the key bindings used to key events 189 * ( received through sendKeyEvent() ) into character 190 * streams to send to the terminal. 191 */ 192 void setKeyBindings(const QString& name); 193 /** 194 * Returns the name of the emulation's current key bindings. 195 * See setKeyBindings() 196 */ 197 QString keyBindings(); 198 199 /** 200 * Copies the current image into the history and clears the screen. 201 */ 202 virtual void clearEntireScreen() =0; 203 204 /** Resets the state of the terminal. */ 205 virtual void reset() =0; 206 207 /** 208 * Returns true if the active terminal program wants 209 * mouse input events. 210 * 211 * The programUsesMouseChanged() signal is emitted when this 212 * changes. 213 */ 214 bool programUsesMouse() const; 215 216 bool programBracketedPasteMode() const; 217 218 public slots: 219 220 /** Change the size of the emulation's image */ 221 virtual void setImageSize(int lines, int columns); 222 223 /** 224 * Interprets a sequence of characters and sends the result to the terminal. 225 * This is equivalent to calling sendKeyEvent() for each character in @p text in succession. 226 */ 227 virtual void sendText(const QString& text) = 0; 228 229 /** 230 * Interprets a key press event and emits the sendData() signal with 231 * the resulting character stream. 232 */ 233 virtual void sendKeyEvent(QKeyEvent*); 234 235 /** 236 * Converts information about a mouse event into an xterm-compatible escape 237 * sequence and emits the character sequence via sendData() 238 */ 239 virtual void sendMouseEvent(int buttons, int column, int line, int eventType); 240 241 /** 242 * Sends a string of characters to the foreground terminal process. 243 * 244 * @param string The characters to send. 245 * @param length Length of @p string or if set to a negative value, @p string will 246 * be treated as a null-terminated string and its length will be determined automatically. 247 */ 248 virtual void sendString(const char* string, int length = -1) = 0; 249 250 /** 251 * Processes an incoming stream of characters. receiveData() decodes the incoming 252 * character buffer using the current codec(), and then calls receiveChar() for 253 * each unicode character in the resulting buffer. 254 * 255 * receiveData() also starts a timer which causes the outputChanged() signal 256 * to be emitted when it expires. The timer allows multiple updates in quick 257 * succession to be buffered into a single outputChanged() signal emission. 258 * 259 * @param buffer A string of characters received from the terminal program. 260 * @param len The length of @p buffer 261 */ 262 void receiveData(const char* buffer,int len); 263 264 signals: 265 266 /** 267 * Emitted when a buffer of data is ready to send to the 268 * standard input of the terminal. 269 * 270 * @param data The buffer of data ready to be sent 271 * @paran len The length of @p data in bytes 272 */ 273 void sendData(const char* data,int len); 274 275 /** 276 * Requests that sending of input to the emulation 277 * from the terminal process be suspended or resumed. 278 * 279 * @param suspend If true, requests that sending of 280 * input from the terminal process' stdout be 281 * suspended. Otherwise requests that sending of 282 * input be resumed. 283 */ 284 void lockPtyRequest(bool suspend); 285 286 /** 287 * Requests that the pty used by the terminal process 288 * be set to UTF 8 mode. 289 * 290 * TODO: More documentation 291 */ 292 void useUtf8Request(bool); 293 294 /** 295 * Emitted when the activity state of the emulation is set. 296 * 297 * @param state The new activity state, one of NOTIFYNORMAL, NOTIFYACTIVITY 298 * or NOTIFYBELL 299 */ 300 void stateSet(int state); 301 302 303 /** 304 * Requests that the color of the text used 305 * to represent the tabs associated with this 306 * emulation be changed. This is a Konsole-specific 307 * extension from pre-KDE 4 times. 308 * 309 * TODO: Document how the parameter works. 310 */ 311 void changeTabTextColorRequest(int color); 312 313 /** 314 * This is emitted when the program running in the shell indicates whether or 315 * not it is interested in mouse events. 316 * 317 * @param usesMouse This will be true if the program wants to be informed about 318 * mouse events or false otherwise. 319 */ 320 void programUsesMouseChanged(bool usesMouse); 321 322 void programBracketedPasteModeChanged(bool bracketedPasteMode); 323 324 /** 325 * Emitted when the contents of the screen image change. 326 * The emulation buffers the updates from successive image changes, 327 * and only emits outputChanged() at sensible intervals when 328 * there is a lot of terminal activity. 329 * 330 * Normally there is no need for objects other than the screen windows 331 * created with createWindow() to listen for this signal. 332 * 333 * ScreenWindow objects created using createWindow() will emit their 334 * own outputChanged() signal in response to this signal. 335 */ 336 void outputChanged(); 337 338 /** 339 * Emitted when the program running in the terminal wishes to update the 340 * session's title. This also allows terminal programs to customize other 341 * aspects of the terminal emulation display. 342 * 343 * This signal is emitted when the escape sequence "\033]ARG;VALUE\007" 344 * is received in the input string, where ARG is a number specifying what 345 * should change and VALUE is a string specifying the new value. 346 * 347 * TODO: The name of this method is not very accurate since this method 348 * is used to perform a whole range of tasks besides just setting 349 * the user-title of the session. 350 * 351 * @param title Specifies what to change. 352 * <ul> 353 * <li>0 - Set window icon text and session title to @p newTitle</li> 354 * <li>1 - Set window icon text to @p newTitle</li> 355 * <li>2 - Set session title to @p newTitle</li> 356 * <li>11 - Set the session's default background color to @p newTitle, 357 * where @p newTitle can be an HTML-style string (#RRGGBB) or a named 358 * color (eg 'red', 'blue'). 359 * See http://doc.trolltech.com/4.2/qcolor.html#setNamedColor for more 360 * details. 361 * </li> 362 * <li>31 - Supposedly treats @p newTitle as a URL and opens it (NOT IMPLEMENTED)</li> 363 * <li>32 - Sets the icon associated with the session. @p newTitle is the name 364 * of the icon to use, which can be the name of any icon in the current KDE icon 365 * theme (eg: 'konsole', 'kate', 'folder_home')</li> 366 * </ul> 367 * @param newTitle Specifies the new title 368 */ 369 370 void titleChanged(int title,const QString& newTitle); 371 372 /** 373 * Emitted when the program running in the terminal changes the 374 * screen size. 375 */ 376 void imageSizeChanged(int lineCount , int columnCount); 377 378 /** 379 * Emitted when the terminal program requests to change various properties 380 * of the terminal display. 381 * 382 * A profile change command occurs when a special escape sequence, followed 383 * by a string containing a series of name and value pairs is received. 384 * This string can be parsed using a ProfileCommandParser instance. 385 * 386 * @param text A string expected to contain a series of key and value pairs in 387 * the form: name=value;name2=value2 ... 388 */ 389 void profileChangeCommandReceived(const QString& text); 390 391 protected: 392 virtual void setMode (int mode) = 0; 393 virtual void resetMode(int mode) = 0; 394 395 /** 396 * Processes an incoming character. See receiveData() 397 * @p ch A unicode character code. 398 */ 399 virtual void receiveChar(int ch); 400 401 /** 402 * Sets the active screen. The terminal has two screens, primary and alternate. 403 * The primary screen is used by default. When certain interactive programs such 404 * as Vim are run, they trigger a switch to the alternate screen. 405 * 406 * @param index 0 to switch to the primary screen, or 1 to switch to the alternate screen 407 */ 408 void setScreen(int index); 409 410 enum EmulationCodec 411 { 412 LocaleCodec = 0, 413 Utf8Codec = 1 414 }; 415 void setCodec(EmulationCodec codec); // codec number, 0 = locale, 1=utf8 416 417 418 QList<ScreenWindow*> _windows; 419 420 Screen* _currentScreen; // pointer to the screen which is currently active, 421 // this is one of the elements in the screen[] array 422 423 Screen* _screen[2]; // 0 = primary screen ( used by most programs, including the shell 424 // scrollbars are enabled in this mode ) 425 // 1 = alternate ( used by vi , emacs etc. 426 // scrollbars are not enabled in this mode ) 427 428 429 //decodes an incoming C-style character stream into a unicode QString using 430 //the current text codec. (this allows for rendering of non-ASCII characters in text files etc.) 431 const QTextCodec* _codec; 432 QTextDecoder* _decoder; 433 434 const KeyboardTranslator* _keyTranslator; // the keyboard layout 435 436 protected slots: 437 /** 438 * Schedules an update of attached views. 439 * Repeated calls to bufferedUpdate() in close succession will result in only a single update, 440 * much like the Qt buffered update of widgets. 441 */ 442 void bufferedUpdate(); 443 444 private slots: 445 446 // triggered by timer, causes the emulation to send an updated screen image to each 447 // view 448 void showBulk(); 449 450 void usesMouseChanged(bool usesMouse); 451 452 void bracketedPasteModeChanged(bool bracketedPasteMode); 453 454 private: 455 456 bool _usesMouse; 457 bool _bracketedPasteMode; 458 QTimer _bulkTimer1; 459 QTimer _bulkTimer2; 460 461 }; 462 463 #endif // ifndef EMULATION_H 464