GNU Octave  3.8.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 <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(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