GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Emulation.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Konsole, an X terminal.
3 
4  Copyright (C) 2007, 2013 Robert Knight <[email protected]>
5  Copyright (C) 1997,1998 by Lars Doelle <[email protected]>
6  Copyright (C) 1996, 2013 by Matthias Ettrich <[email protected]>
7 
8  Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
9 
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23  02110-1301 USA.
24 */
25 
26 // Own
27 #include "unix/Emulation.h"
28 
29 // System
30 #include <assert.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 
35 // Qt
36 #include <QApplication>
37 #include <QClipboard>
38 #include <QtCore/QHash>
39 #include <QKeyEvent>
40 #include <QtCore/QRegExp>
41 #include <QtCore/QTextStream>
42 #include <QtCore/QThread>
43 
44 #include <QtCore/QTime>
45 
46 // Konsole
48 #include "unix/Screen.h"
50 #include "unix/ScreenWindow.h"
51 
53  _currentScreen(0),
54  _codec(0),
55  _decoder(0),
56  _keyTranslator(0),
57  _usesMouse(false)
58 {
59 
60  // create screens with a default size
61  _screen[0] = new Screen(40,80);
62  _screen[1] = new Screen(40,80);
64 
65  QObject::connect(&_bulkTimer1, SIGNAL(timeout()), this, SLOT(showBulk()) );
66  QObject::connect(&_bulkTimer2, SIGNAL(timeout()), this, SLOT(showBulk()) );
67 
68  // listen for mouse status changes
69  connect( this , SIGNAL(programUsesMouseChanged(bool)) ,
70  SLOT(usesMouseChanged(bool)) );
71 }
72 
74 {
75  return _usesMouse;
76 }
77 
78 void Emulation::usesMouseChanged(bool usesMouse)
79 {
80  _usesMouse = usesMouse;
81 }
82 
84 {
85  ScreenWindow* window = new ScreenWindow();
86  window->setScreen(_currentScreen);
87  _windows << window;
88 
89  connect(window , SIGNAL(selectionChanged()),
90  this , SLOT(bufferedUpdate()));
91 
92  connect(this , SIGNAL(outputChanged()),
93  window , SLOT(notifyOutputChanged()) );
94  return window;
95 }
96 
97 /*!
98 */
99 
101 {
102  QListIterator<ScreenWindow*> windowIter(_windows);
103 
104  while (windowIter.hasNext())
105  {
106  delete windowIter.next();
107  }
108 
109  delete _screen[0];
110  delete _screen[1];
111  delete _decoder;
112 }
113 
114 /*! change between primary and alternate _screen
115 */
116 
118 {
119  Screen *old = _currentScreen;
120  _currentScreen = _screen[n&1];
121  if (_currentScreen != old)
122  {
123  old->setBusySelecting(false);
124 
125  // tell all windows onto this emulation to switch to the newly active _screen
126  QListIterator<ScreenWindow*> windowIter(_windows);
127  while ( windowIter.hasNext() )
128  {
129  windowIter.next()->setScreen(_currentScreen);
130  }
131  }
132 }
133 
135 {
136  _screen[0]->setScroll( _screen[0]->getScroll() , false );
137 }
139 {
140  _screen[0]->setScroll(t);
141 
142  showBulk();
143 }
144 
146 {
147  return _screen[0]->getScroll();
148 }
149 
150 void Emulation::setCodec(const QTextCodec * qtc)
151 {
152  Q_ASSERT( qtc );
153 
154  _codec = qtc;
155  delete _decoder;
156  _decoder = _codec->makeDecoder();
157 
158  emit useUtf8Request(utf8());
159 }
160 
162 {
163  if ( codec == Utf8Codec )
164  setCodec( QTextCodec::codecForName("utf8") );
165  else if ( codec == LocaleCodec )
166  setCodec( QTextCodec::codecForLocale() );
167 }
168 
169 void Emulation::setKeyBindings(const QString& name)
170 {
172 }
173 
175 {
176  return _keyTranslator->name();
177 }
178 
179 
180 // Interpreting Codes ---------------------------------------------------------
181 
182 /*
183  This section deals with decoding the incoming character stream.
184  Decoding means here, that the stream is first separated into `tokens'
185  which are then mapped to a `meaning' provided as operations by the
186  `Screen' class.
187 */
188 
189 /*!
190 */
191 
193 // process application unicode input to terminal
194 // this is a trivial scanner
195 {
196  c &= 0xff;
197  switch (c)
198  {
199  case '\b' : _currentScreen->BackSpace(); break;
200  case '\t' : _currentScreen->Tabulate(); break;
201  case '\n' : _currentScreen->NewLine(); break;
202  case '\r' : _currentScreen->Return(); break;
203  case 0x07 : emit stateSet(NOTIFYBELL);
204  break;
205  default : _currentScreen->ShowCharacter(c); break;
206  };
207 }
208 
209 /* ------------------------------------------------------------------------- */
210 /* */
211 /* Keyboard Handling */
212 /* */
213 /* ------------------------------------------------------------------------- */
214 
215 /*!
216 */
217 
218 void Emulation::sendKeyEvent( QKeyEvent* ev )
219 {
220  emit stateSet(NOTIFYNORMAL);
221 
222  if (!ev->text().isEmpty())
223  { // A block of text
224  // Note that the text is proper unicode.
225  // We should do a conversion here, but since this
226  // routine will never be used, we simply emit plain ascii.
227  //emit sendBlock(ev->text().toAscii(),ev->text().length());
228  emit sendData(ev->text().toUtf8(),ev->text().length());
229  }
230 }
231 
232 void Emulation::sendString(const char*,int)
233 {
234  // default implementation does nothing
235 }
236 
237 void Emulation::sendMouseEvent(int /*buttons*/, int /*column*/, int /*row*/, int /*eventType*/)
238 {
239  // default implementation does nothing
240 }
241 
242 // Unblocking, Byte to Unicode translation --------------------------------- --
243 
244 /*
245  We are doing code conversion from locale to unicode first.
246 TODO: Character composition from the old code. See #96536
247 */
248 
249 void Emulation::receiveData(const char* text, int length)
250 {
251  emit stateSet(NOTIFYACTIVITY);
252 
253  bufferedUpdate();
254 
255  QString unicodeText = _decoder->toUnicode(text,length);
256 
257  //send characters to terminal emulator
258  for (int i=0;i<unicodeText.length();i++)
259  {
260  receiveChar(unicodeText[i].unicode());
261  }
262 }
263 
264 // Selection --------------------------------------------------------------- --
265 
267  int startLine ,
268  int endLine)
269 {
270  _currentScreen->writeToStream(_decoder,startLine,endLine);
271 }
272 
274 {
275  // sum number of lines currently on _screen plus number of lines in history
277 }
278 
279 // Refreshing -------------------------------------------------------------- --
280 
281 #define BULK_TIMEOUT1 10
282 #define BULK_TIMEOUT2 40
283 
284 /*!
285 */
287 {
288  _bulkTimer1.stop();
289  _bulkTimer2.stop();
290 
291  emit outputChanged();
292 
295 }
296 
298 {
299  _bulkTimer1.setSingleShot(true);
300  _bulkTimer1.start(BULK_TIMEOUT1);
301  if (!_bulkTimer2.isActive())
302  {
303  _bulkTimer2.setSingleShot(true);
304  _bulkTimer2.start(BULK_TIMEOUT2);
305  }
306 }
307 
309 {
310  return '\b';
311 }
312 
313 void Emulation::setImageSize(int lines, int columns)
314 {
315  //kDebug() << "Resizing image to: " << lines << "by" << columns << QTime::currentTime().msec();
316  Q_ASSERT( lines > 0 );
317  Q_ASSERT( columns > 0 );
318 
319  _screen[0]->resizeImage(lines,columns);
320  _screen[1]->resizeImage(lines,columns);
321 
322  emit imageSizeChanged(lines,columns);
323 
324  bufferedUpdate();
325 }
326 
328 {
329  return QSize(_currentScreen->getColumns(), _currentScreen->getLines());
330 }
331 
332 ushort ExtendedCharTable::extendedCharHash(ushort* unicodePoints , ushort length) const
333 {
334  ushort hash = 0;
335  for ( ushort i = 0 ; i < length ; i++ )
336  {
337  hash = 31*hash + unicodePoints[i];
338  }
339  return hash;
340 }
341 bool ExtendedCharTable::extendedCharMatch(ushort hash , ushort* unicodePoints , ushort length) const
342 {
343  ushort* entry = extendedCharTable[hash];
344 
345  // compare given length with stored sequence length ( given as the first ushort in the
346  // stored buffer )
347  if ( entry == 0 || entry[0] != length )
348  return false;
349  // if the lengths match, each character must be checked. the stored buffer starts at
350  // entry[1]
351  for ( int i = 0 ; i < length ; i++ )
352  {
353  if ( entry[i+1] != unicodePoints[i] )
354  return false;
355  }
356  return true;
357 }
358 ushort ExtendedCharTable::createExtendedChar(ushort* unicodePoints , ushort length)
359 {
360  // look for this sequence of points in the table
361  ushort hash = extendedCharHash(unicodePoints,length);
362 
363  // check existing entry for match
364  while ( extendedCharTable.contains(hash) )
365  {
366  if ( extendedCharMatch(hash,unicodePoints,length) )
367  {
368  // this sequence already has an entry in the table,
369  // return its hash
370  return hash;
371  }
372  else
373  {
374  // if hash is already used by another, different sequence of unicode character
375  // points then try next hash
376  hash++;
377  }
378  }
379 
380 
381  // add the new sequence to the table and
382  // return that index
383  ushort* buffer = new ushort[length+1];
384  buffer[0] = length;
385  for ( int i = 0 ; i < length ; i++ )
386  buffer[i+1] = unicodePoints[i];
387 
388  extendedCharTable.insert(hash,buffer);
389 
390  return hash;
391 }
392 
393 ushort* ExtendedCharTable::lookupExtendedChar(ushort hash , ushort& length) const
394 {
395  // lookup index in table and if found, set the length
396  // argument and return a pointer to the character sequence
397 
398  ushort* buffer = extendedCharTable[hash];
399  if ( buffer )
400  {
401  length = buffer[0];
402  return buffer+1;
403  }
404  else
405  {
406  length = 0;
407  return 0;
408  }
409 }
410 
412 {
413 }
415 {
416  // free all allocated character buffers
417  QHashIterator<ushort,ushort*> iter(extendedCharTable);
418  while ( iter.hasNext() )
419  {
420  iter.next();
421  delete[] iter.value();
422  }
423 }
424 
425 // global instance
The terminal program has triggered a bell event to get the user's attention.
Definition: Emulation.h:58
#define BULK_TIMEOUT1
Definition: Emulation.cpp:281
void resetScrolledLines()
Resets the count of the number of lines that the image has been scrolled up or down by...
Definition: Screen.cpp:846
Provides a window onto a section of a terminal screen.
Definition: ScreenWindow.h:51
void setScroll(const HistoryType &, bool copyPreviousScroll=true)
Sets the type of storage used to keep lines in the history.
Definition: Screen.cpp:1527
void outputChanged()
Emitted when the contents of the screen image change.
void setScreen(Screen *screen)
Sets the screen which this window looks onto.
void setScreen(int index)
Sets the active screen.
Definition: Emulation.cpp:117
void Tabulate(int n=1)
Moves the cursor n tab-stops to the right.
Definition: Screen.cpp:679
void bufferedUpdate()
Schedules an update of attached views.
Definition: Emulation.cpp:297
An image of characters with associated attributes.
Definition: Screen.h:75
int getLines()
Return the number of lines.
Definition: Screen.h:377
int getColumns()
Return the number of columns.
Definition: Screen.h:379
ushort extendedCharHash(ushort *unicodePoints, ushort length) const
Definition: Emulation.cpp:332
QList< ScreenWindow * > _windows
Definition: Emulation.h:414
virtual void setImageSize(int lines, int columns)
Change the size of the emulation's image.
Definition: Emulation.cpp:313
QSize imageSize()
Returns the size of the screen image which the emulation produces.
Definition: Emulation.cpp:327
The emulation is currently receiving data from its terminal input.
Definition: Emulation.h:63
void sendData(const char *data, int len)
Emitted when a buffer of data is ready to send to the standard input of the terminal.
#define BULK_TIMEOUT2
Definition: Emulation.cpp:282
bool _usesMouse
Definition: Emulation.h:450
void BackSpace()
Moves the cursor one column to the left and erases the character at the new cursor position...
Definition: Screen.cpp:667
int lineCount()
Returns the total number of lines, including those stored in the history.
Definition: Emulation.cpp:273
ushort createExtendedChar(ushort *unicodePoints, ushort length)
Adds a sequences of unicode characters to the table and returns a hash code which can be used later t...
Definition: Emulation.cpp:358
void Return()
Moves the cursor to the beginning of the current line.
Definition: Screen.cpp:935
void NewLine()
Moves the cursor down one line, if the MODE_NewLine mode flag is enabled then the cursor is returned ...
Definition: Screen.cpp:729
void showBulk()
Definition: Emulation.cpp:286
QHash< ushort, ushort * > extendedCharTable
Definition: Character.h:201
virtual void writeToStream(TerminalCharacterDecoder *decoder, int startLine, int endLine)
Copies the output history from startLine to endLine into stream, using decoder to convert the termina...
Definition: Emulation.cpp:266
void resizeImage(int new_lines, int new_columns)
Resizes the image to a new fixed size of new_lines by new_columns.
Definition: Screen.cpp:380
bool programUsesMouse() const
Returns true if the active terminal program wants mouse input events.
Definition: Emulation.cpp:73
void programUsesMouseChanged(bool usesMouse)
This is emitted when the program running in the shell indicates whether or not it is interested in mo...
QString keyBindings()
Returns the name of the emulation's current key bindings.
Definition: Emulation.cpp:174
const KeyboardTranslator * findTranslator(const QString &name)
Returns the keyboard translator with the given name or 0 if no translator with that name exists...
void useUtf8Request(bool)
Requests that the pty used by the terminal process be set to UTF 8 mode.
ExtendedCharTable()
Constructs a new character table.
Definition: Emulation.cpp:411
void stateSet(int state)
Emitted when the activity state of the emulation is set.
Screen * _currentScreen
Definition: Emulation.h:416
const QTextCodec * _codec
Definition: Emulation.h:427
void clearHistory()
Clears the history scroll.
Definition: Emulation.cpp:134
virtual void sendKeyEvent(QKeyEvent *)
Interprets a key press event and emits the sendData() signal with the resulting character stream...
Definition: Emulation.cpp:218
A table which stores sequences of unicode characters, referenced by hash keys.
Definition: Character.h:159
virtual void receiveChar(int ch)
Processes an incoming character.
Definition: Emulation.cpp:192
void writeToStream(TerminalCharacterDecoder *decoder, int from, int to)
Copies part of the output to a stream.
Definition: Screen.cpp:1444
virtual char getErase() const
TODO Document me.
Definition: Emulation.cpp:308
bool extendedCharMatch(ushort hash, ushort *unicodePoints, ushort length) const
Definition: Emulation.cpp:341
Emulation()
Constructs a new terminal emulation.
Definition: Emulation.cpp:52
const HistoryType & history()
Returns the history store used by this emulation.
Definition: Emulation.cpp:145
virtual void sendMouseEvent(int buttons, int column, int line, int eventType)
Converts information about a mouse event into an xterm-compatible escape sequence and emits the chara...
Definition: Emulation.cpp:237
static KeyboardTranslatorManager * instance()
Returns the global KeyboardTranslatorManager instance.
ushort * lookupExtendedChar(ushort hash, ushort &length) const
Looks up and returns a pointer to a sequence of unicode characters which was added to the table using...
Definition: Emulation.cpp:393
void resetDroppedLines()
Resets the count of the number of lines dropped from the history.
Definition: Screen.cpp:842
void setBusySelecting(bool busy)
Definition: Screen.h:428
virtual void sendString(const char *string, int length=-1)=0
Sends a string of characters to the foreground terminal process.
Definition: Emulation.cpp:232
ScreenWindow * createWindow()
Creates a new window onto the output from this emulation.
Definition: Emulation.cpp:83
Base class for terminal character decoders.
QString name() const
Returns the name of this keyboard translator.
QTextDecoder * _decoder
Definition: Emulation.h:428
const KeyboardTranslator * _keyTranslator
Definition: Emulation.h:430
const HistoryType & getScroll()
Returns the type of storage used to keep lines in the history.
Definition: Screen.cpp:1546
void setCodec(const QTextCodec *)
Sets the codec used to decode incoming characters.
Definition: Emulation.cpp:150
QTimer _bulkTimer2
Definition: Emulation.h:452
The emulation is currently receiving user input.
Definition: Emulation.h:53
void imageSizeChanged(int lineCount, int columnCount)
Emitted when the program running in the terminal changes the screen size.
static ExtendedCharTable instance
The global ExtendedCharTable instance.
Definition: Character.h:191
Screen * _screen[2]
Definition: Emulation.h:419
void receiveData(const char *buffer, int len)
Processes an incoming stream of characters.
Definition: Emulation.cpp:249
void setHistory(const HistoryType &)
Sets the history store used by this emulation.
Definition: Emulation.cpp:138
void setKeyBindings(const QString &name)
Sets the key bindings used to key events ( received through sendKeyEvent() ) into character streams t...
Definition: Emulation.cpp:169
bool utf8()
Convenience method.
Definition: Emulation.h:181
void ShowCharacter(unsigned short c)
Displays a new character at the current cursor position.
Definition: Screen.cpp:752
int getHistLines()
Return the number of lines in the history buffer.
Definition: Screen.cpp:1522
QTimer _bulkTimer1
Definition: Emulation.h:451
void usesMouseChanged(bool usesMouse)
Definition: Emulation.cpp:78