Bug Summary

File:libgui/qterminal/libqterminal/unix/Emulation.cpp
Location:line 156, column 14
Description:Called C++ object pointer is null

Annotated Source Code

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
47#include "unix/KeyboardTranslator.h"
48#include "unix/Screen.h"
49#include "unix/TerminalCharacterDecoder.h"
50#include "unix/ScreenWindow.h"
51
52Emulation::Emulation() :
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);
63 _currentScreen = _screen[0];
64
65 QObject::connect(&_bulkTimer1, SIGNAL(timeout())qFlagLocation("2""timeout()" "\0" "qterminal/libqterminal/unix/Emulation.cpp"
":" "65")
, this, SLOT(showBulk())qFlagLocation("1""showBulk()" "\0" "qterminal/libqterminal/unix/Emulation.cpp"
":" "65")
);
66 QObject::connect(&_bulkTimer2, SIGNAL(timeout())qFlagLocation("2""timeout()" "\0" "qterminal/libqterminal/unix/Emulation.cpp"
":" "66")
, this, SLOT(showBulk())qFlagLocation("1""showBulk()" "\0" "qterminal/libqterminal/unix/Emulation.cpp"
":" "66")
);
67
68 // listen for mouse status changes
69 connect( this , SIGNAL(programUsesMouseChanged(bool))qFlagLocation("2""programUsesMouseChanged(bool)" "\0" "qterminal/libqterminal/unix/Emulation.cpp"
":" "69")
,
70 SLOT(usesMouseChanged(bool))qFlagLocation("1""usesMouseChanged(bool)" "\0" "qterminal/libqterminal/unix/Emulation.cpp"
":" "70")
);
71}
72
73bool Emulation::programUsesMouse() const
74{
75 return _usesMouse;
76}
77
78void Emulation::usesMouseChanged(bool usesMouse)
79{
80 _usesMouse = usesMouse;
81}
82
83ScreenWindow* Emulation::createWindow()
84{
85 ScreenWindow* window = new ScreenWindow();
86 window->setScreen(_currentScreen);
87 _windows << window;
88
89 connect(window , SIGNAL(selectionChanged())qFlagLocation("2""selectionChanged()" "\0" "qterminal/libqterminal/unix/Emulation.cpp"
":" "89")
,
90 this , SLOT(bufferedUpdate())qFlagLocation("1""bufferedUpdate()" "\0" "qterminal/libqterminal/unix/Emulation.cpp"
":" "90")
);
91
92 connect(this , SIGNAL(outputChanged())qFlagLocation("2""outputChanged()" "\0" "qterminal/libqterminal/unix/Emulation.cpp"
":" "92")
,
93 window , SLOT(notifyOutputChanged())qFlagLocation("1""notifyOutputChanged()" "\0" "qterminal/libqterminal/unix/Emulation.cpp"
":" "93")
);
94 return window;
95}
96
97/*!
98*/
99
100Emulation::~Emulation()
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
117void Emulation::setScreen(int n)
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
134void Emulation::clearHistory()
135{
136 _screen[0]->setScroll( _screen[0]->getScroll() , false );
137}
138void Emulation::setHistory(const HistoryType& t)
139{
140 _screen[0]->setScroll(t);
141
142 showBulk();
143}
144
145const HistoryType& Emulation::history()
146{
147 return _screen[0]->getScroll();
148}
149
150void Emulation::setCodec(const QTextCodec * qtc)
151{
152 Q_ASSERT( qtc )((!(qtc)) ? qt_assert("qtc","qterminal/libqterminal/unix/Emulation.cpp"
,152) : qt_noop())
;
7
Within the expansion of the macro 'Q_ASSERT':
a
Assuming 'qtc' is null
153
154 _codec = qtc;
8
Null pointer value stored to field '_codec'
155 delete _decoder;
156 _decoder = _codec->makeDecoder();
9
Called C++ object pointer is null
157
158 emit useUtf8Request(utf8());
159}
160
161void Emulation::setCodec(EmulationCodec codec)
162{
163 if ( codec == Utf8Codec )
1
Assuming 'codec' is not equal to Utf8Codec
2
Taking false branch
164 setCodec( QTextCodec::codecForName("utf8") );
165 else if ( codec == LocaleCodec )
3
Assuming 'codec' is equal to LocaleCodec
4
Taking true branch
166 setCodec( QTextCodec::codecForLocale() );
5
Passing value via 1st parameter 'qtc'
6
Calling 'Emulation::setCodec'
167}
168
169void Emulation::setKeyBindings(const QString& name)
170{
171 _keyTranslator = KeyboardTranslatorManager::instance()->findTranslator(name);
172}
173
174QString Emulation::keyBindings()
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
192void Emulation::receiveChar(int c)
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
218void 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
232void Emulation::sendString(const char*,int)
233{
234 // default implementation does nothing
235}
236
237void 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.
246TODO: Character composition from the old code. See #96536
247*/
248
249void 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
266void Emulation::writeToStream( TerminalCharacterDecoder* _decoder ,
267 int startLine ,
268 int endLine)
269{
270 _currentScreen->writeToStream(_decoder,startLine,endLine);
271}
272
273int Emulation::lineCount()
274{
275 // sum number of lines currently on _screen plus number of lines in history
276 return _currentScreen->getLines() + _currentScreen->getHistLines();
277}
278
279// Refreshing -------------------------------------------------------------- --
280
281#define BULK_TIMEOUT110 10
282#define BULK_TIMEOUT240 40
283
284/*!
285*/
286void Emulation::showBulk()
287{
288 _bulkTimer1.stop();
289 _bulkTimer2.stop();
290
291 emit outputChanged();
292
293 _currentScreen->resetScrolledLines();
294 _currentScreen->resetDroppedLines();
295}
296
297void Emulation::bufferedUpdate()
298{
299 _bulkTimer1.setSingleShot(true);
300 _bulkTimer1.start(BULK_TIMEOUT110);
301 if (!_bulkTimer2.isActive())
302 {
303 _bulkTimer2.setSingleShot(true);
304 _bulkTimer2.start(BULK_TIMEOUT240);
305 }
306}
307
308char Emulation::getErase() const
309{
310 return '\b';
311}
312
313void Emulation::setImageSize(int lines, int columns)
314{
315 //kDebug() << "Resizing image to: " << lines << "by" << columns << QTime::currentTime().msec();
316 Q_ASSERT( lines > 0 )((!(lines > 0)) ? qt_assert("lines > 0","qterminal/libqterminal/unix/Emulation.cpp"
,316) : qt_noop())
;
317 Q_ASSERT( columns > 0 )((!(columns > 0)) ? qt_assert("columns > 0","qterminal/libqterminal/unix/Emulation.cpp"
,317) : qt_noop())
;
318
319 _screen[0]->resizeImage(lines,columns);
320 _screen[1]->resizeImage(lines,columns);
321
322 emit imageSizeChanged(lines,columns);
323
324 bufferedUpdate();
325}
326
327QSize Emulation::imageSize()
328{
329 return QSize(_currentScreen->getColumns(), _currentScreen->getLines());
330}
331
332ushort 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}
341bool 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}
358ushort 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
393ushort* 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
411ExtendedCharTable::ExtendedCharTable()
412{
413}
414ExtendedCharTable::~ExtendedCharTable()
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
426ExtendedCharTable ExtendedCharTable::instance;