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