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