GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
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 <robertknight@gmail.com>
5  Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
6  Copyright (C) 1996, 2013 by Matthias Ettrich <ettrich@kde.org>
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(nullptr),
54  _codec(nullptr),
55  _decoder(nullptr),
56  _keyTranslator(nullptr),
57  _usesMouse(false),
58  _bracketedPasteMode(false)
59 {
60 
61  // create screens with a default size
62  _screen[0] = new Screen(40,80);
63  _screen[1] = new Screen(40,80);
65 
66  QObject::connect(&_bulkTimer1, SIGNAL(timeout()), this, SLOT(showBulk()) );
67  QObject::connect(&_bulkTimer2, SIGNAL(timeout()), this, SLOT(showBulk()) );
68 
69  // listen for mouse status changes
70  connect( this , SIGNAL(programUsesMouseChanged(bool)) ,
71  SLOT(usesMouseChanged(bool)) );
72  connect(this , SIGNAL(programBracketedPasteModeChanged(bool)) ,
73  SLOT(bracketedPasteModeChanged(bool)));
74 }
75 
77 {
78  return _usesMouse;
79 }
80 
81 void Emulation::usesMouseChanged(bool usesMouse)
82 {
83  _usesMouse = usesMouse;
84 }
85 
87 {
88  return _bracketedPasteMode;
89 }
90 
91 void Emulation::bracketedPasteModeChanged(bool bracketedPasteMode)
92 {
93  _bracketedPasteMode = bracketedPasteMode;
94 }
95 
97 {
98  ScreenWindow* window = new ScreenWindow();
99  window->setScreen(_currentScreen);
100  _windows << window;
101 
102  connect(window , SIGNAL(selectionChanged()),
103  this , SLOT(bufferedUpdate()));
104 
105  connect(this , SIGNAL(outputChanged()),
106  window , SLOT(notifyOutputChanged()) );
107  return window;
108 }
109 
110 /*!
111 */
112 
114 {
115  QListIterator<ScreenWindow*> windowIter(_windows);
116 
117  while (windowIter.hasNext())
118  {
119  delete windowIter.next();
120  }
121 
122  delete _screen[0];
123  delete _screen[1];
124  delete _decoder;
125 }
126 
127 /*! change between primary and alternate _screen
128 */
129 
131 {
132  Screen *old = _currentScreen;
133  _currentScreen = _screen[n&1];
134  if (_currentScreen != old)
135  {
136  old->setBusySelecting(false);
137 
138  // tell all windows onto this emulation to switch to the newly active _screen
139  QListIterator<ScreenWindow*> windowIter(_windows);
140  while ( windowIter.hasNext() )
141  {
142  windowIter.next()->setScreen(_currentScreen);
143  }
144  }
145 }
146 
148 {
149  _screen[0]->setScroll( _screen[0]->getScroll() , false );
150 }
152 {
153  _screen[0]->setScroll(t);
154 
155  showBulk();
156 }
157 
159 {
160  return _screen[0]->getScroll();
161 }
162 
163 void Emulation::setCodec(const QTextCodec * qtc)
164 {
165  Q_ASSERT( qtc );
166 
167  _codec = qtc;
168  delete _decoder;
169  _decoder = _codec->makeDecoder();
170 
171  emit useUtf8Request(utf8());
172 }
173 
175 {
176  if ( codec == Utf8Codec )
177  setCodec( QTextCodec::codecForName("utf8") );
178  else if ( codec == LocaleCodec )
179  setCodec( QTextCodec::codecForLocale() );
180 }
181 
182 void Emulation::setKeyBindings(const QString& name)
183 {
185 }
186 
188 {
189  return _keyTranslator->name();
190 }
191 
192 
193 // Interpreting Codes ---------------------------------------------------------
194 
195 /*
196  This section deals with decoding the incoming character stream.
197  Decoding means here, that the stream is first separated into `tokens'
198  which are then mapped to a `meaning' provided as operations by the
199  `Screen' class.
200 */
201 
202 /*!
203 */
204 
206 // process application unicode input to terminal
207 // this is a trivial scanner
208 {
209  c &= 0xff;
210  switch (c)
211  {
212  case '\b' : _currentScreen->BackSpace(); break;
213  case '\t' : _currentScreen->Tabulate(); break;
214  case '\n' : _currentScreen->NewLine(); break;
215  case '\r' : _currentScreen->Return(); break;
216  case 0x07 : emit stateSet(NOTIFYBELL);
217  break;
218  default : _currentScreen->ShowCharacter(c); break;
219  };
220 }
221 
222 /* ------------------------------------------------------------------------- */
223 /* */
224 /* Keyboard Handling */
225 /* */
226 /* ------------------------------------------------------------------------- */
227 
228 /*!
229 */
230 
231 void Emulation::sendKeyEvent( QKeyEvent* ev )
232 {
233  emit stateSet(NOTIFYNORMAL);
234 
235  if (!ev->text().isEmpty())
236  { // A block of text
237  // Note that the text is proper unicode.
238  // We should do a conversion here, but since this
239  // routine will never be used, we simply emit plain ascii.
240  //emit sendBlock(ev->text().toAscii(),ev->text().length());
241  emit sendData(ev->text().toUtf8(),ev->text().length());
242  }
243 }
244 
245 void Emulation::sendString(const char*,int)
246 {
247  // default implementation does nothing
248 }
249 
250 void Emulation::sendMouseEvent(int /*buttons*/, int /*column*/, int /*row*/, int /*eventType*/)
251 {
252  // default implementation does nothing
253 }
254 
255 // Unblocking, Byte to Unicode translation --------------------------------- --
256 
257 /*
258  We are doing code conversion from locale to unicode first.
259 TODO: Character composition from the old code. See #96536
260 */
261 
262 void Emulation::receiveData(const char* text, int length)
263 {
264  emit stateSet(NOTIFYACTIVITY);
265 
266  bufferedUpdate();
267 
268  QString unicodeText = _decoder->toUnicode(text,length);
269 
270  //send characters to terminal emulator
271  for (int i=0;i<unicodeText.length();i++)
272  {
273  receiveChar(unicodeText[i].unicode());
274  }
275 }
276 
277 // Selection --------------------------------------------------------------- --
278 
280  int startLine ,
281  int endLine)
282 {
283  _currentScreen->writeToStream(_decoder,startLine,endLine);
284 }
285 
287 {
288  // sum number of lines currently on _screen plus number of lines in history
290 }
291 
292 // Refreshing -------------------------------------------------------------- --
293 
294 #define BULK_TIMEOUT1 10
295 #define BULK_TIMEOUT2 40
296 
297 /*!
298 */
300 {
301  _bulkTimer1.stop();
302  _bulkTimer2.stop();
303 
304  emit outputChanged();
305 
308 }
309 
311 {
312  _bulkTimer1.setSingleShot(true);
313  _bulkTimer1.start(BULK_TIMEOUT1);
314  if (!_bulkTimer2.isActive())
315  {
316  _bulkTimer2.setSingleShot(true);
317  _bulkTimer2.start(BULK_TIMEOUT2);
318  }
319 }
320 
322 {
323  return '\b';
324 }
325 
326 void Emulation::setImageSize(int lines, int columns)
327 {
328  //kDebug() << "Resizing image to: " << lines << "by" << columns << QTime::currentTime().msec();
329  Q_ASSERT( lines > 0 );
330  Q_ASSERT( columns > 0 );
331 
332  _screen[0]->resizeImage(lines,columns);
333  _screen[1]->resizeImage(lines,columns);
334 
335  emit imageSizeChanged(lines,columns);
336 
337  bufferedUpdate();
338 }
339 
341 {
342  return QSize(_currentScreen->getColumns(), _currentScreen->getLines());
343 }
344 
345 ushort ExtendedCharTable::extendedCharHash(ushort* unicodePoints , ushort length) const
346 {
347  ushort hash = 0;
348  for ( ushort i = 0 ; i < length ; i++ )
349  {
350  hash = 31*hash + unicodePoints[i];
351  }
352  return hash;
353 }
354 bool ExtendedCharTable::extendedCharMatch(ushort hash , ushort* unicodePoints , ushort length) const
355 {
356  ushort* entry = extendedCharTable[hash];
357 
358  // compare given length with stored sequence length ( given as the first ushort in the
359  // stored buffer )
360  if ( entry == nullptr || entry[0] != length )
361  return false;
362  // if the lengths match, each character must be checked. the stored buffer starts at
363  // entry[1]
364  for ( int i = 0 ; i < length ; i++ )
365  {
366  if ( entry[i+1] != unicodePoints[i] )
367  return false;
368  }
369  return true;
370 }
371 ushort ExtendedCharTable::createExtendedChar(ushort* unicodePoints , ushort length)
372 {
373  // look for this sequence of points in the table
374  ushort hash = extendedCharHash(unicodePoints,length);
375 
376  // check existing entry for match
377  while ( extendedCharTable.contains(hash) )
378  {
379  if ( extendedCharMatch(hash,unicodePoints,length) )
380  {
381  // this sequence already has an entry in the table,
382  // return its hash
383  return hash;
384  }
385  else
386  {
387  // if hash is already used by another, different sequence of unicode character
388  // points then try next hash
389  hash++;
390  }
391  }
392 
393 
394  // add the new sequence to the table and
395  // return that index
396  ushort* buffer = new ushort[length+1];
397  buffer[0] = length;
398  for ( int i = 0 ; i < length ; i++ )
399  buffer[i+1] = unicodePoints[i];
400 
401  extendedCharTable.insert(hash,buffer);
402 
403  return hash;
404 }
405 
406 ushort* ExtendedCharTable::lookupExtendedChar(ushort hash , ushort& length) const
407 {
408  // lookup index in table and if found, set the length
409  // argument and return a pointer to the character sequence
410 
411  ushort* buffer = extendedCharTable[hash];
412  if ( buffer )
413  {
414  length = buffer[0];
415  return buffer+1;
416  }
417  else
418  {
419  length = 0;
420  return nullptr;
421  }
422 }
423 
425 {
426 }
428 {
429  // free all allocated character buffers
430  QHashIterator<ushort,ushort*> iter(extendedCharTable);
431  while ( iter.hasNext() )
432  {
433  iter.next();
434  delete[] iter.value();
435  }
436 }
437 
438 // global instance
#define BULK_TIMEOUT1
Definition: Emulation.cpp:294
#define BULK_TIMEOUT2
Definition: Emulation.cpp:295
@ NOTIFYBELL
The terminal program has triggered a bell event to get the user's attention.
Definition: Emulation.h:58
@ NOTIFYACTIVITY
The emulation is currently receiving data from its terminal input.
Definition: Emulation.h:63
@ NOTIFYNORMAL
The emulation is currently receiving user input.
Definition: Emulation.h:53
virtual void receiveChar(int ch)
Processes an incoming character.
Definition: Emulation.cpp:205
void usesMouseChanged(bool usesMouse)
Definition: Emulation.cpp:81
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:250
const QTextCodec * _codec
Definition: Emulation.h:431
Screen * _currentScreen
Definition: Emulation.h:420
bool programUsesMouse() const
Returns true if the active terminal program wants mouse input events.
Definition: Emulation.cpp:76
void bracketedPasteModeChanged(bool bracketedPasteMode)
Definition: Emulation.cpp:91
void showBulk()
Definition: Emulation.cpp:299
virtual void sendKeyEvent(QKeyEvent *)
Interprets a key press event and emits the sendData() signal with the resulting character stream.
Definition: Emulation.cpp:231
void receiveData(const char *buffer, int len)
Processes an incoming stream of characters.
Definition: Emulation.cpp:262
void programUsesMouseChanged(bool usesMouse)
This is emitted when the program running in the shell indicates whether or not it is interested in mo...
Emulation()
Constructs a new terminal emulation.
Definition: Emulation.cpp:52
void bufferedUpdate()
Schedules an update of attached views.
Definition: Emulation.cpp:310
int lineCount()
Returns the total number of lines, including those stored in the history.
Definition: Emulation.cpp:286
const KeyboardTranslator * _keyTranslator
Definition: Emulation.h:434
void programBracketedPasteModeChanged(bool bracketedPasteMode)
QString keyBindings()
Returns the name of the emulation's current key bindings.
Definition: Emulation.cpp:187
const HistoryType & history()
Returns the history store used by this emulation.
Definition: Emulation.cpp:158
void useUtf8Request(bool)
Requests that the pty used by the terminal process be set to UTF 8 mode.
ScreenWindow * createWindow()
Creates a new window onto the output from this emulation.
Definition: Emulation.cpp:96
QTimer _bulkTimer2
Definition: Emulation.h:459
QTextDecoder * _decoder
Definition: Emulation.h:432
bool _usesMouse
Definition: Emulation.h:456
QTimer _bulkTimer1
Definition: Emulation.h:458
@ LocaleCodec
Definition: Emulation.h:412
void imageSizeChanged(int lineCount, int columnCount)
Emitted when the program running in the terminal changes the screen size.
const QTextCodec * codec()
Returns the codec used to decode incoming characters.
Definition: Emulation.h:172
void sendData(const char *data, int len)
Emitted when a buffer of data is ready to send to the standard input of the terminal.
QSize imageSize()
Returns the size of the screen image which the emulation produces.
Definition: Emulation.cpp:340
virtual void setImageSize(int lines, int columns)
Change the size of the emulation's image.
Definition: Emulation.cpp:326
QList< ScreenWindow * > _windows
Definition: Emulation.h:418
bool programBracketedPasteMode() const
Definition: Emulation.cpp:86
bool _bracketedPasteMode
Definition: Emulation.h:457
void setScreen(int index)
Sets the active screen.
Definition: Emulation.cpp:130
Screen * _screen[2]
Definition: Emulation.h:423
void clearHistory()
Clears the history scroll.
Definition: Emulation.cpp:147
void setKeyBindings(const QString &name)
Sets the key bindings used to key events ( received through sendKeyEvent() ) into character streams t...
Definition: Emulation.cpp:182
void setHistory(const HistoryType &)
Sets the history store used by this emulation.
Definition: Emulation.cpp:151
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:279
void outputChanged()
Emitted when the contents of the screen image change.
void stateSet(int state)
Emitted when the activity state of the emulation is set.
virtual char getErase() const
TODO Document me.
Definition: Emulation.cpp:321
void setCodec(const QTextCodec *)
Sets the codec used to decode incoming characters.
Definition: Emulation.cpp:163
virtual void sendString(const char *string, int length=-1)=0
Sends a string of characters to the foreground terminal process.
Definition: Emulation.cpp:245
bool utf8()
Convenience method.
Definition: Emulation.h:181
A table which stores sequences of unicode characters, referenced by hash keys.
Definition: Character.h:160
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:406
static ExtendedCharTable instance
The global ExtendedCharTable instance.
Definition: Character.h:191
ushort extendedCharHash(ushort *unicodePoints, ushort length) const
Definition: Emulation.cpp:345
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:371
QHash< ushort, ushort * > extendedCharTable
Definition: Character.h:201
ExtendedCharTable()
Constructs a new character table.
Definition: Emulation.cpp:424
bool extendedCharMatch(ushort hash, ushort *unicodePoints, ushort length) const
Definition: Emulation.cpp:354
const KeyboardTranslator * findTranslator(const QString &name)
Returns the keyboard translator with the given name or 0 if no translator with that name exists.
static KeyboardTranslatorManager * instance()
Returns the global KeyboardTranslatorManager instance.
QString name() const
Returns the name of this keyboard translator.
Provides a window onto a section of a terminal screen.
Definition: ScreenWindow.h:52
void setScreen(Screen *screen)
Sets the screen which this window looks onto.
An image of characters with associated attributes.
Definition: Screen.h:76
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
int getColumns()
Return the number of columns.
Definition: Screen.h:379
void setScroll(const HistoryType &, bool copyPreviousScroll=true)
Sets the type of storage used to keep lines in the history.
Definition: Screen.cpp:1527
void setBusySelecting(bool busy)
Definition: Screen.h:428
void writeToStream(TerminalCharacterDecoder *decoder, int from, int to)
Copies part of the output to a stream.
Definition: Screen.cpp:1444
void BackSpace()
Moves the cursor one column to the left and erases the character at the new cursor position.
Definition: Screen.cpp:667
void Return()
Moves the cursor to the beginning of the current line.
Definition: Screen.cpp:935
int getHistLines()
Return the number of lines in the history buffer.
Definition: Screen.cpp:1522
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 Tabulate(int n=1)
Moves the cursor n tab-stops to the right.
Definition: Screen.cpp:679
void resetScrolledLines()
Resets the count of the number of lines that the image has been scrolled up or down by,...
Definition: Screen.cpp:846
void resetDroppedLines()
Resets the count of the number of lines dropped from the history.
Definition: Screen.cpp:842
const HistoryType & getScroll()
Returns the type of storage used to keep lines in the history.
Definition: Screen.cpp:1546
void ShowCharacter(unsigned short c)
Displays a new character at the current cursor position.
Definition: Screen.cpp:752
int getLines()
Return the number of lines.
Definition: Screen.h:377
Base class for terminal character decoders.
QString name
octave_idx_type n
Definition: mx-inlines.cc:753
std::string hash(hash_fptr hash_fcn, const std::string &str, int result_buf_len)
Definition: lo-hash.cc:45