changeset 15638:95a3b4c4a729 draft

Renamed classes.
author Jacob Dawid <jacob.dawid@googlemail.com>
date Tue, 24 Jan 2012 00:36:01 +0100
parents 29c817466160
children 0fad530cb34e
files libqterminal/QTerminal.cpp libqterminal/QTerminal.h libqterminal/Session.cpp libqterminal/Session.h libqterminal/SessionModel.cpp libqterminal/SessionModel.h libqterminal/SessionView.cpp libqterminal/SessionView.h libqterminal/TerminalDisplay.cpp libqterminal/TerminalDisplay.h libqterminal/libqterminal.pro
diffstat 11 files changed, 5161 insertions(+), 5162 deletions(-) [+]
line wrap: on
line diff
--- a/libqterminal/QTerminal.cpp
+++ b/libqterminal/QTerminal.cpp
@@ -41,9 +41,9 @@
     dup2 (fds, 1);
     dup2 (fds, 2);
 
-    m_session = new Session(fdm, fds);
+    m_session = new SessionModel(fdm, fds);
 
-    m_session->setTitle(Session::NameRole, "QTermWidget");
+    m_session->setTitle(SessionModel::NameRole, "QTermWidget");
     m_session->setProgram("/bin/bash");
     QStringList args("");
     m_session->setArguments(args);
@@ -54,10 +54,10 @@
     m_session->setDarkBackground(true);
     m_session->setKeyBindings("");
 
-    m_terminalDisplay = new TerminalDisplay(this);
-    m_terminalDisplay->setBellMode(TerminalDisplay::NotifyBell);
+    m_terminalDisplay = new SessionView(this);
+    m_terminalDisplay->setBellMode(SessionView::NotifyBell);
     m_terminalDisplay->setTerminalSizeHint(true);
-    m_terminalDisplay->setTripleClickMode(TerminalDisplay::SelectWholeLine);
+    m_terminalDisplay->setTripleClickMode(SessionView::SelectWholeLine);
     m_terminalDisplay->setTerminalSizeStartup(true);
     m_terminalDisplay->setRandomSeed(m_session->sessionId() * 31);
     m_terminalDisplay->setSize(80, 40);
@@ -70,7 +70,7 @@
 
     m_session->run();
     m_session->addView(m_terminalDisplay);
-    m_terminalDisplay->setScrollBarPosition(TerminalDisplay::ScrollBarRight);
+    m_terminalDisplay->setScrollBarPosition(SessionView::ScrollBarRight);
 
     connect(m_session, SIGNAL(finished()), this, SLOT(sessionFinished()));
 }
--- a/libqterminal/QTerminal.h
+++ b/libqterminal/QTerminal.h
@@ -21,8 +21,8 @@
 #define Q_TERMINAL
 
 #include <QtGui>
-#include "Session.h"
-#include "TerminalDisplay.h"
+#include "SessionModel.h"
+#include "SessionView.h"
 
 class QTerminal : public QWidget
 {
@@ -78,8 +78,8 @@
     
 private:
     void init();
-    TerminalDisplay *m_terminalDisplay;
-    Session *m_session;
+    SessionView *m_terminalDisplay;
+    SessionModel *m_session;
 };
 
 #endif // Q_TERMINAL
deleted file mode 100644
--- a/libqterminal/Session.cpp
+++ /dev/null
@@ -1,1029 +0,0 @@
-/*
-    This file is part of Konsole
-
-    Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com>
-    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
-
-    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-    02110-1301  USA.
-*/
-
-// Own
-#include "Session.h"
-
-// Standard
-#include <assert.h>
-#include <stdlib.h>
-
-// Qt
-#include <QtGui/QApplication>
-#include <QtCore/QByteRef>
-#include <QtCore/QDir>
-#include <QtCore/QFile>
-#include <QtCore/QRegExp>
-#include <QtCore/QStringList>
-#include <QtCore>
-
-#include "PseudoTerminal.h"
-#include "TerminalDisplay.h"
-#include "ShellCommand.h"
-#include "Vt102Emulation.h"
-
-int Session::lastSessionId = 0;
-
-Session::Session(int masterFd, int slaveFd) :
-    _shellProcess(0)
-  , _emulation(0)
-  , _monitorActivity(false)
-  , _monitorSilence(false)
-  , _notifiedActivity(false)
-  , _autoClose(true)
-  , _wantedClose(false)
-  , _silenceSeconds(10)
-  , _addToUtmp(false)  // disabled by default because of a bug encountered on certain systems
-  // which caused Konsole to hang when closing a tab and then opening a new
-  // one.  A 'QProcess destroyed while still running' warning was being
-  // printed to the terminal.  Likely a problem in KPty::logout()
-  // or KPty::login() which uses a QProcess to start /usr/bin/utempter
-  , _flowControl(true)
-  , _fullScripting(false)
-  , _sessionId(0)
-  //   , _zmodemBusy(false)
-  //   , _zmodemProc(0)
-  //   , _zmodemProgress(0)
-  , _hasDarkBackground(false)
-{
-    _masterFd = masterFd;
-    _slaveFd = slaveFd;
-
-    //prepare DBus communication
-    //    new SessionAdaptor(this);
-    _sessionId = ++lastSessionId;
-    //    QDBusConnection::sessionBus().registerObject(QLatin1String("/Sessions/")+QString::number(_sessionId), this);
-
-    //create teletype for I/O with shell process
-    if(_masterFd >= 0) {
-        _shellProcess = new PseudoTerminal(_masterFd, _slaveFd);
-    } else {
-        _shellProcess = new PseudoTerminal();
-    }
-
-    //create emulation backend
-    _emulation = new Vt102Emulation();
-
-    connect( _emulation, SIGNAL( titleChanged( int, const QString & ) ),
-             this, SLOT( setUserTitle( int, const QString & ) ) );
-    connect( _emulation, SIGNAL( stateSet(int) ),
-             this, SLOT( activityStateSet(int) ) );
-    //    connect( _emulation, SIGNAL( zmodemDetected() ), this ,
-    //            SLOT( fireZModemDetected() ) );
-    connect( _emulation, SIGNAL( changeTabTextColorRequest( int ) ),
-             this, SIGNAL( changeTabTextColorRequest( int ) ) );
-    connect( _emulation, SIGNAL(profileChangeCommandReceived(const QString&)),
-             this, SIGNAL( profileChangeCommandReceived(const QString&)) );
-    // TODO
-    // connect( _emulation,SIGNAL(imageSizeChanged(int,int)) , this ,
-    //        SLOT(onEmulationSizeChange(int,int)) );
-
-    //connect teletype to emulation backend
-    _shellProcess->setUtf8Mode(_emulation->utf8());
-
-    connect( _shellProcess,SIGNAL(receivedData(const char*,int)),this,
-             SLOT(onReceiveBlock(const char*,int)) );
-    connect( _emulation,SIGNAL(sendData(const char*,int)),_shellProcess,
-             SLOT(sendData(const char*,int)) );
-    connect( _emulation,SIGNAL(lockPtyRequest(bool)),_shellProcess,SLOT(lockPty(bool)) );
-    connect( _emulation,SIGNAL(useUtf8Request(bool)),_shellProcess,SLOT(setUtf8Mode(bool)) );
-
-
-    connect( _shellProcess,SIGNAL(done(int)), this, SLOT(done(int)) );
-
-    //setup timer for monitoring session activity
-    _monitorTimer = new QTimer(this);
-    _monitorTimer->setSingleShot(true);
-    connect(_monitorTimer, SIGNAL(timeout()), this, SLOT(monitorTimerDone()));
-}
-
-WId Session::windowId() const
-{
-    // Returns a window ID for this session which is used
-    // to set the WINDOWID environment variable in the shell
-    // process.
-    //
-    // Sessions can have multiple views or no views, which means
-    // that a single ID is not always going to be accurate.
-    //
-    // If there are no views, the window ID is just 0.  If
-    // there are multiple views, then the window ID for the
-    // top-level window which contains the first view is
-    // returned
-
-    if ( _views.count() == 0 )
-        return 0;
-    else
-    {
-        QWidget* window = _views.first();
-
-        Q_ASSERT( window );
-
-        while ( window->parentWidget() != 0 )
-            window = window->parentWidget();
-
-        return window->winId();
-    }
-}
-
-void Session::setDarkBackground(bool darkBackground)
-{
-    _hasDarkBackground = darkBackground;
-}
-bool Session::hasDarkBackground() const
-{
-    return _hasDarkBackground;
-}
-bool Session::isRunning() const
-{
-    return _shellProcess->isRunning();
-}
-
-void Session::setCodec(QTextCodec* codec)
-{
-    emulation()->setCodec(codec);
-}
-
-void Session::setProgram(const QString& program)
-{
-    _program = ShellCommand::expand(program);
-}
-void Session::setInitialWorkingDirectory(const QString& dir)
-{
-    _initialWorkingDir = ShellCommand::expand(dir);
-}
-void Session::setArguments(const QStringList& arguments)
-{
-    _arguments = ShellCommand::expand(arguments);
-}
-
-QList<TerminalDisplay*> Session::views() const
-{
-    return _views;
-}
-
-void Session::addView(TerminalDisplay* widget)
-{
-    Q_ASSERT( !_views.contains(widget) );
-
-    _views.append(widget);
-
-    if ( _emulation != 0 )
-    {
-        // connect emulation - view signals and slots
-        connect( widget , SIGNAL(keyPressedSignal(QKeyEvent*)) , _emulation ,
-                 SLOT(sendKeyEvent(QKeyEvent*)) );
-        connect( widget , SIGNAL(mouseSignal(int,int,int,int)) , _emulation ,
-                 SLOT(sendMouseEvent(int,int,int,int)) );
-        connect( widget , SIGNAL(sendStringToEmu(const char*)) , _emulation ,
-                 SLOT(sendString(const char*)) );
-
-        // allow emulation to notify view when the foreground process
-        // indicates whether or not it is interested in mouse signals
-        connect( _emulation , SIGNAL(programUsesMouseChanged(bool)) , widget ,
-                 SLOT(setUsesMouse(bool)) );
-
-        widget->setUsesMouse( _emulation->programUsesMouse() );
-
-        widget->setScreenWindow(_emulation->createWindow());
-    }
-
-    //connect view signals and slots
-    QObject::connect( widget ,SIGNAL(changedContentSizeSignal(int,int)),this,
-                      SLOT(onViewSizeChange(int,int)));
-
-    QObject::connect( widget ,SIGNAL(destroyed(QObject*)) , this ,
-                      SLOT(viewDestroyed(QObject*)) );
-    //slot for close
-    QObject::connect(this, SIGNAL(finished()), widget, SLOT(close()));		    
-    
-}
-
-void Session::viewDestroyed(QObject* view)
-{
-    TerminalDisplay* display = (TerminalDisplay*)view;
-
-    Q_ASSERT( _views.contains(display) );
-
-    removeView(display);
-}
-
-void Session::removeView(TerminalDisplay* widget)
-{
-    _views.removeAll(widget);
-
-    disconnect(widget,0,this,0);
-
-    if ( _emulation != 0 )
-    {
-        // disconnect
-        //  - key presses signals from widget
-        //  - mouse activity signals from widget
-        //  - string sending signals from widget
-        //
-        //  ... and any other signals connected in addView()
-        disconnect( widget, 0, _emulation, 0);
-
-        // disconnect state change signals emitted by emulation
-        disconnect( _emulation , 0 , widget , 0);
-    }
-
-    // close the session automatically when the last view is removed
-    if ( _views.count() == 0 )
-    {
-        close();
-    }
-}
-
-void Session::run()
-{
-    //check that everything is in place to run the session
-    if (_program.isEmpty())
-        qDebug() << "Session::run() - program to run not set.";
-    if (_arguments.isEmpty())
-        qDebug() << "Session::run() - no command line arguments specified.";
-
-    // Upon a KPty error, there is no description on what that error was...
-    // Check to see if the given program is executable.
-    QString exec = QFile::encodeName(_program);
-
-    // if 'exec' is not specified, fall back to default shell.  if that
-    // is not set then fall back to /bin/sh
-    if ( exec.isEmpty() )
-        exec = getenv("SHELL");
-    if ( exec.isEmpty() )
-        exec = "/bin/sh";
-
-    // if no arguments are specified, fall back to shell
-    QStringList arguments =  _arguments.join(QChar(' ')).isEmpty() ?
-                QStringList() << exec : _arguments;
-    QString pexec = exec;
-
-    if ( pexec.isEmpty() ) {
-        qDebug()<<"can not execute "<<exec<<endl;
-        QTimer::singleShot(1, this, SIGNAL(finished()));
-        return;
-    }
-
-    //  QString cwd_save = QDir::currentPath();
-    QString cwd = QDir::currentPath();
-    if (!_initialWorkingDir.isEmpty())
-        _shellProcess->setWorkingDirectory(_initialWorkingDir);
-    else
-        _shellProcess->setWorkingDirectory(cwd);
-    //    _shellProcess->setWorkingDirectory(QDir::homePath());
-
-    _shellProcess->setXonXoff(_flowControl);
-    _shellProcess->setErase(_emulation->getErase());
-
-    // this is not strictly accurate use of the COLORFGBG variable.  This does not
-    // tell the terminal exactly which colors are being used, but instead approximates
-    // the color scheme as "black on white" or "white on black" depending on whether
-    // the background color is deemed dark or not
-    QString backgroundColorHint = _hasDarkBackground ? "COLORFGBG=15;0" : "COLORFGBG=0;15";
-
-    int result = _shellProcess->start(QFile::encodeName(_program),
-                                      arguments,
-                                      _environment << backgroundColorHint,
-                                      windowId(),
-                                      _addToUtmp,
-                                      _masterFd,
-                                      _slaveFd);
-
-    if (result < 0)
-    {
-        return;
-    }
-
-    _shellProcess->setWriteable(false);  // We are reachable via kwrited.
-
-    emit started();
-}
-
-void Session::setUserTitle( int what, const QString &caption )
-{
-    //set to true if anything is actually changed (eg. old _nameTitle != new _nameTitle )
-    bool modified = false;
-
-    // (btw: what=0 changes _userTitle and icon, what=1 only icon, what=2 only _nameTitle
-    if ((what == 0) || (what == 2)) 
-    {
-       	if ( _userTitle != caption ) {
-            _userTitle = caption;
-            modified = true;
-        }
-    }
-
-    if ((what == 0) || (what == 1))
-    {
-        if ( _iconText != caption ) {
-            _iconText = caption;
-            modified = true;
-        }
-    }
-
-    if (what == 11) 
-    {
-        QString colorString = caption.section(';',0,0);
-        qDebug() << __FILE__ << __LINE__ << ": setting background colour to " << colorString;
-        QColor backColor = QColor(colorString);
-        if (backColor.isValid()){// change color via \033]11;Color\007
-            if (backColor != _modifiedBackground)
-            {
-                _modifiedBackground = backColor;
-
-                // bail out here until the code to connect the terminal display
-                // to the changeBackgroundColor() signal has been written
-                // and tested - just so we don't forget to do this.
-                Q_ASSERT( 0 );
-
-                emit changeBackgroundColorRequest(backColor);
-            }
-        }
-    }
-
-    if (what == 30)
-    {
-        if ( _nameTitle != caption ) {
-            setTitle(Session::NameRole,caption);
-            return;
-        }
-    }
-
-    if (what == 31) 
-    {
-        QString cwd=caption;
-        cwd=cwd.replace( QRegExp("^~"), QDir::homePath() );
-        emit openUrlRequest(cwd);
-    }
-
-    // change icon via \033]32;Icon\007
-    if (what == 32) 
-    { 
-    	if ( _iconName != caption ) {
-            _iconName = caption;
-
-            modified = true;
-        }
-    }
-
-    if (what == 50) 
-    {
-        emit profileChangeCommandReceived(caption);
-        return;
-    }
-
-    if ( modified )
-    	emit titleChanged();
-}
-
-QString Session::userTitle() const
-{
-    return _userTitle;
-}
-void Session::setTabTitleFormat(TabTitleContext context , const QString& format)
-{
-    if ( context == LocalTabTitle )
-        _localTabTitleFormat = format;
-    else if ( context == RemoteTabTitle )
-        _remoteTabTitleFormat = format;
-}
-QString Session::tabTitleFormat(TabTitleContext context) const
-{
-    if ( context == LocalTabTitle )
-        return _localTabTitleFormat;
-    else if ( context == RemoteTabTitle )
-        return _remoteTabTitleFormat;
-
-    return QString();
-}
-
-void Session::monitorTimerDone()
-{
-    //FIXME: The idea here is that the notification popup will appear to tell the user than output from
-    //the terminal has stopped and the popup will disappear when the user activates the session.
-    //
-    //This breaks with the addition of multiple views of a session.  The popup should disappear
-    //when any of the views of the session becomes active
-
-
-    //FIXME: Make message text for this notification and the activity notification more descriptive.
-    if (_monitorSilence) {
-        //    KNotification::event("Silence", ("Silence in session '%1'", _nameTitle), QPixmap(),
-        //                    QApplication::activeWindow(),
-        //                    KNotification::CloseWhenWidgetActivated);
-        emit stateChanged(NOTIFYSILENCE);
-    }
-    else
-    {
-        emit stateChanged(NOTIFYNORMAL);
-    }
-
-    _notifiedActivity=false;
-}
-
-void Session::activityStateSet(int state)
-{
-    if (state==NOTIFYBELL)
-    {
-        QString s; s.sprintf("Bell in session '%s'",_nameTitle.toAscii().data());
-
-        emit bellRequest( s );
-    }
-    else if (state==NOTIFYACTIVITY)
-    {
-        if (_monitorSilence) {
-            _monitorTimer->start(_silenceSeconds*1000);
-        }
-
-        if ( _monitorActivity ) {
-            //FIXME:  See comments in Session::monitorTimerDone()
-            if (!_notifiedActivity) {
-                //        KNotification::event("Activity", ("Activity in session '%1'", _nameTitle), QPixmap(),
-                //                        QApplication::activeWindow(),
-                //        KNotification::CloseWhenWidgetActivated);
-                _notifiedActivity=true;
-            }
-        }
-    }
-
-    if ( state==NOTIFYACTIVITY && !_monitorActivity )
-        state = NOTIFYNORMAL;
-    if ( state==NOTIFYSILENCE && !_monitorSilence )
-        state = NOTIFYNORMAL;
-
-    emit stateChanged(state);
-}
-
-void Session::onViewSizeChange(int /*height*/, int /*width*/)
-{
-    updateTerminalSize();
-}
-void Session::onEmulationSizeChange(int lines , int columns)
-{
-    setSize( QSize(lines,columns) );
-}
-
-void Session::updateTerminalSize()
-{
-    QListIterator<TerminalDisplay*> viewIter(_views);
-
-    int minLines = -1;
-    int minColumns = -1;
-
-    // minimum number of lines and columns that views require for
-    // their size to be taken into consideration ( to avoid problems
-    // with new view widgets which haven't yet been set to their correct size )
-    const int VIEW_LINES_THRESHOLD = 2;
-    const int VIEW_COLUMNS_THRESHOLD = 2;
-
-    //select largest number of lines and columns that will fit in all visible views
-    while ( viewIter.hasNext() )
-    {
-        TerminalDisplay* view = viewIter.next();
-        if ( view->isHidden() == false &&
-             view->lines() >= VIEW_LINES_THRESHOLD &&
-             view->columns() >= VIEW_COLUMNS_THRESHOLD )
-        {
-            minLines = (minLines == -1) ? view->lines() : qMin( minLines , view->lines() );
-            minColumns = (minColumns == -1) ? view->columns() : qMin( minColumns , view->columns() );
-        }
-    }
-
-    // backend emulation must have a _terminal of at least 1 column x 1 line in size
-    if ( minLines > 0 && minColumns > 0 )
-    {
-        _emulation->setImageSize( minLines , minColumns );
-        _shellProcess->setWindowSize( minLines , minColumns );
-    }
-}
-
-void Session::refresh()
-{
-    // attempt to get the shell process to redraw the display
-    //
-    // this requires the program running in the shell
-    // to cooperate by sending an update in response to
-    // a window size change
-    //
-    // the window size is changed twice, first made slightly larger and then
-    // resized back to its normal size so that there is actually a change
-    // in the window size (some shells do nothing if the
-    // new and old sizes are the same)
-    //
-    // if there is a more 'correct' way to do this, please
-    // send an email with method or patches to konsole-devel@kde.org
-
-    const QSize existingSize = _shellProcess->windowSize();
-    _shellProcess->setWindowSize(existingSize.height(),existingSize.width()+1);
-    _shellProcess->setWindowSize(existingSize.height(),existingSize.width());
-}
-
-bool Session::sendSignal(int signal)
-{
-    return _shellProcess->kill(signal);
-}
-
-void Session::close()
-{
-    _autoClose = true;
-    _wantedClose = true;
-    if (!_shellProcess->isRunning() || !sendSignal(SIGHUP))
-    {
-        // Forced close.
-        QTimer::singleShot(1, this, SIGNAL(finished()));
-    }
-}
-
-void Session::sendText(const QString &text) const
-{
-    _emulation->sendText(text);
-}
-
-Session::~Session()
-{
-    delete _emulation;
-    delete _shellProcess;
-    //  delete _zmodemProc;
-}
-
-void Session::setProfileKey(const QString& key)
-{
-    _profileKey = key;
-    emit profileChanged(key);
-}
-QString Session::profileKey() const { return _profileKey; }
-
-void Session::done(int exitStatus)
-{
-    if (!_autoClose)
-    {
-        _userTitle = ("<Finished>");
-        emit titleChanged();
-        return;
-    }
-    if (!_wantedClose && (exitStatus || _shellProcess->signalled()))
-    {
-        QString message;
-
-        if (_shellProcess->normalExit())
-            message.sprintf ("Session '%s' exited with status %d.", _nameTitle.toAscii().data(), exitStatus);
-        else if (_shellProcess->signalled())
-        {
-            if (_shellProcess->coreDumped())
-            {
-
-                message.sprintf("Session '%s' exited with signal %d and dumped core.", _nameTitle.toAscii().data(), _shellProcess->exitSignal());
-            }
-            else {
-                message.sprintf("Session '%s' exited with signal %d.", _nameTitle.toAscii().data(), _shellProcess->exitSignal());
-            }
-        }
-        else
-            message.sprintf ("Session '%s' exited unexpectedly.", _nameTitle.toAscii().data());
-
-        //FIXME: See comments in Session::monitorTimerDone()
-        //    KNotification::event("Finished", message , QPixmap(),
-        //                         QApplication::activeWindow(),
-        //                         KNotification::CloseWhenWidgetActivated);
-    }
-    emit finished();
-}
-
-Emulation* Session::emulation() const
-{
-    return _emulation;
-}
-
-QString Session::keyBindings() const
-{
-    return _emulation->keyBindings();
-}
-
-QStringList Session::environment() const
-{
-    return _environment;
-}
-
-void Session::setEnvironment(const QStringList& environment)
-{
-    _environment = environment;
-}
-
-int Session::sessionId() const
-{
-    return _sessionId;
-}
-
-void Session::setKeyBindings(const QString &id)
-{
-    _emulation->setKeyBindings(id);
-}
-
-void Session::setTitle(TitleRole role , const QString& newTitle)
-{
-    if ( title(role) != newTitle )
-    {
-        if ( role == NameRole )
-            _nameTitle = newTitle;
-        else if ( role == DisplayedTitleRole )
-            _displayTitle = newTitle;
-
-        emit titleChanged();
-    }
-}
-
-QString Session::title(TitleRole role) const
-{
-    if ( role == NameRole )
-        return _nameTitle;
-    else if ( role == DisplayedTitleRole )
-        return _displayTitle;
-    else
-        return QString();
-}
-
-void Session::setIconName(const QString& iconName)
-{
-    if ( iconName != _iconName )
-    {
-        _iconName = iconName;
-        emit titleChanged();
-    }
-}
-
-void Session::setIconText(const QString& iconText)
-{
-    _iconText = iconText;
-    //kDebug(1211)<<"Session setIconText " <<  _iconText;
-}
-
-QString Session::iconName() const
-{
-    return _iconName;
-}
-
-QString Session::iconText() const
-{
-    return _iconText;
-}
-
-void Session::setHistoryType(const HistoryType &hType)
-{
-    _emulation->setHistory(hType);
-}
-
-const HistoryType& Session::historyType() const
-{
-    return _emulation->history();
-}
-
-void Session::clearHistory()
-{
-    _emulation->clearHistory();
-}
-
-QStringList Session::arguments() const
-{
-    return _arguments;
-}
-
-QString Session::program() const
-{
-    return _program;
-}
-
-// unused currently
-bool Session::isMonitorActivity() const { return _monitorActivity; }
-// unused currently
-bool Session::isMonitorSilence()  const { return _monitorSilence; }
-
-void Session::setMonitorActivity(bool _monitor)
-{
-    _monitorActivity=_monitor;
-    _notifiedActivity=false;
-
-    activityStateSet(NOTIFYNORMAL);
-}
-
-void Session::setMonitorSilence(bool _monitor)
-{
-    if (_monitorSilence==_monitor)
-        return;
-
-    _monitorSilence=_monitor;
-    if (_monitorSilence)
-    {
-        _monitorTimer->start(_silenceSeconds*1000);
-    }
-    else
-        _monitorTimer->stop();
-
-    activityStateSet(NOTIFYNORMAL);
-}
-
-void Session::setMonitorSilenceSeconds(int seconds)
-{
-    _silenceSeconds=seconds;
-    if (_monitorSilence) {
-        _monitorTimer->start(_silenceSeconds*1000);
-    }
-}
-
-void Session::setAddToUtmp(bool set)
-{
-    _addToUtmp = set;
-}
-
-void Session::setFlowControlEnabled(bool enabled)
-{
-    if (_flowControl == enabled)
-  	return;
-
-    _flowControl = enabled;
-
-    if (_shellProcess)
-	_shellProcess->setXonXoff(_flowControl);
-
-    emit flowControlEnabledChanged(enabled);
-}
-bool Session::flowControlEnabled() const
-{
-    return _flowControl;
-}
-//void Session::fireZModemDetected()
-//{
-//  if (!_zmodemBusy)
-//  {
-//    QTimer::singleShot(10, this, SIGNAL(zmodemDetected()));
-//    _zmodemBusy = true;
-//  }
-//}
-
-//void Session::cancelZModem()
-//{
-//  _shellProcess->sendData("\030\030\030\030", 4); // Abort
-//  _zmodemBusy = false;
-//}
-
-//void Session::startZModem(const QString &zmodem, const QString &dir, const QStringList &list)
-//{
-//  _zmodemBusy = true;
-//  _zmodemProc = new KProcess();
-//  _zmodemProc->setOutputChannelMode( KProcess::SeparateChannels );
-//
-//  *_zmodemProc << zmodem << "-v" << list;
-//
-//  if (!dir.isEmpty())
-//     _zmodemProc->setWorkingDirectory(dir);
-//
-//  _zmodemProc->start();
-//
-//  connect(_zmodemProc,SIGNAL (readyReadStandardOutput()),
-//          this, SLOT(zmodemReadAndSendBlock()));
-//  connect(_zmodemProc,SIGNAL (readyReadStandardError()),
-//          this, SLOT(zmodemReadStatus()));
-//  connect(_zmodemProc,SIGNAL (finished(int,QProcess::ExitStatus)),
-//          this, SLOT(zmodemFinished()));
-//
-//  disconnect( _shellProcess,SIGNAL(block_in(const char*,int)), this, SLOT(onReceiveBlock(const char*,int)) );
-//  connect( _shellProcess,SIGNAL(block_in(const char*,int)), this, SLOT(zmodemRcvBlock(const char*,int)) );
-//
-//  _zmodemProgress = new ZModemDialog(QApplication::activeWindow(), false,
-//                                    i18n("ZModem Progress"));
-//
-//  connect(_zmodemProgress, SIGNAL(user1Clicked()),
-//          this, SLOT(zmodemDone()));
-//
-//  _zmodemProgress->show();
-//}
-
-/*void Session::zmodemReadAndSendBlock()
-{
-  _zmodemProc->setReadChannel( QProcess::StandardOutput );
-  QByteArray data = _zmodemProc->readAll();
-
-  if ( data.count() == 0 )
-      return;
-
-  _shellProcess->sendData(data.constData(),data.count());
-}
-*/
-/*
-void Session::zmodemReadStatus()
-{
-  _zmodemProc->setReadChannel( QProcess::StandardError );
-  QByteArray msg = _zmodemProc->readAll();
-  while(!msg.isEmpty())
-  {
-     int i = msg.indexOf('\015');
-     int j = msg.indexOf('\012');
-     QByteArray txt;
-     if ((i != -1) && ((j == -1) || (i < j)))
-     {
-       msg = msg.mid(i+1);
-     }
-     else if (j != -1)
-     {
-       txt = msg.left(j);
-       msg = msg.mid(j+1);
-     }
-     else
-     {
-       txt = msg;
-       msg.truncate(0);
-     }
-     if (!txt.isEmpty())
-       _zmodemProgress->addProgressText(QString::fromLocal8Bit(txt));
-  }
-}
-*/
-/*
-void Session::zmodemRcvBlock(const char *data, int len)
-{
-  QByteArray ba( data, len );
-
-  _zmodemProc->write( ba );
-}
-*/
-/*
-void Session::zmodemFinished()
-{
-  if (_zmodemProc)
-  {
-    delete _zmodemProc;
-    _zmodemProc = 0;
-    _zmodemBusy = false;
-
-    disconnect( _shellProcess,SIGNAL(block_in(const char*,int)), this ,SLOT(zmodemRcvBlock(const char*,int)) );
-    connect( _shellProcess,SIGNAL(block_in(const char*,int)), this, SLOT(onReceiveBlock(const char*,int)) );
-
-    _shellProcess->sendData("\030\030\030\030", 4); // Abort
-    _shellProcess->sendData("\001\013\n", 3); // Try to get prompt back
-    _zmodemProgress->transferDone();
-  }
-}
-*/
-void Session::onReceiveBlock( const char* buf, int len )
-{
-    _emulation->receiveData( buf, len );
-    emit receivedData( QString::fromLatin1( buf, len ) );
-}
-
-QSize Session::size()
-{
-    return _emulation->imageSize();
-}
-
-void Session::setSize(const QSize& size)
-{
-    if ((size.width() <= 1) || (size.height() <= 1))
-        return;
-
-    emit resizeRequest(size);
-}
-int Session::foregroundProcessId() const
-{
-    return _shellProcess->foregroundProcessGroup();
-}
-int Session::processId() const
-{
-    return _shellProcess->pid();
-}
-
-SessionGroup::SessionGroup()
-    : _masterMode(0)
-{
-}
-SessionGroup::~SessionGroup()
-{
-    // disconnect all
-    connectAll(false);
-}
-int SessionGroup::masterMode() const { return _masterMode; }
-QList<Session*> SessionGroup::sessions() const { return _sessions.keys(); }
-bool SessionGroup::masterStatus(Session* session) const { return _sessions[session]; }
-
-void SessionGroup::addSession(Session* session)
-{
-    _sessions.insert(session,false);
-
-    QListIterator<Session*> masterIter(masters());
-
-    while ( masterIter.hasNext() )
-        connectPair(masterIter.next(),session);
-}
-void SessionGroup::removeSession(Session* session)
-{
-    setMasterStatus(session,false);
-
-    QListIterator<Session*> masterIter(masters());
-
-    while ( masterIter.hasNext() )
-        disconnectPair(masterIter.next(),session);
-
-    _sessions.remove(session);
-}
-void SessionGroup::setMasterMode(int mode)
-{
-    _masterMode = mode;
-
-    connectAll(false);
-    connectAll(true);
-}
-QList<Session*> SessionGroup::masters() const
-{
-    return _sessions.keys(true);
-}
-void SessionGroup::connectAll(bool connect)
-{
-    QListIterator<Session*> masterIter(masters());
-
-    while ( masterIter.hasNext() )
-    {
-        Session* master = masterIter.next();
-
-        QListIterator<Session*> otherIter(_sessions.keys());
-        while ( otherIter.hasNext() )
-        {
-            Session* other = otherIter.next();
-
-            if ( other != master )
-            {
-                if ( connect )
-                    connectPair(master,other);
-                else
-                    disconnectPair(master,other);
-            }
-        }
-    }
-}
-void SessionGroup::setMasterStatus(Session* session, bool master) {
-    bool wasMaster = _sessions[session];
-    _sessions[session] = master;
-
-    if ((!wasMaster && !master)
-            || (wasMaster && master)) {
-        return;
-    }
-
-    QListIterator<Session*> iter(_sessions.keys());
-    while (iter.hasNext()) {
-        Session* other = iter.next();
-
-        if (other != session) {
-            if (master) {
-                connectPair(session, other);
-            } else {
-                disconnectPair(session, other);
-            }
-        }
-    }
-}
-
-void SessionGroup::connectPair(Session* master , Session* other)
-{
-    //    qDebug() << k_funcinfo;
-
-    if ( _masterMode & CopyInputToAll )
-    {
-        qDebug() << "Connection session " << master->nameTitle() << "to" << other->nameTitle();
-
-        connect( master->emulation() , SIGNAL(sendData(const char*,int)) , other->emulation() ,
-                 SLOT(sendString(const char*,int)) );
-    }
-}
-void SessionGroup::disconnectPair(Session* master , Session* other)
-{
-    //    qDebug() << k_funcinfo;
-
-    if ( _masterMode & CopyInputToAll )
-    {
-        qDebug() << "Disconnecting session " << master->nameTitle() << "from" << other->nameTitle();
-
-        disconnect( master->emulation() , SIGNAL(sendData(const char*,int)) , other->emulation() ,
-                    SLOT(sendString(const char*,int)) );
-    }
-}
-
deleted file mode 100644
--- a/libqterminal/Session.h
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
-    This file is part of Konsole, an X terminal.
-
-    Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
-    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
-
-    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-    02110-1301  USA.
-*/
-
-#ifndef SESSION_H
-#define SESSION_H
-
-// Qt
-#include <QtCore/QStringList>
-#include <QtCore>
-#include <QWidget>
-
-// Konsole
-#include "History.h"
-
-class KProcess;
-
-class Emulation;
-class PseudoTerminal;
-class TerminalDisplay;
-
-/**
- * Represents a terminal session consisting of a pseudo-teletype and a terminal emulation.
- * The pseudo-teletype (or PTY) handles I/O between the terminal process and Konsole.
- * The terminal emulation ( Emulation and subclasses ) processes the output stream from the
- * PTY and produces a character image which is then shown on views connected to the session.
- *
- * Each Session can be connected to one or more views by using the addView() method.
- * The attached views can then display output from the program running in the terminal
- * or send input to the program in the terminal in the form of keypresses and mouse
- * activity.
- */
-class Session : public QObject
-{
-Q_OBJECT
-
-public:
-  Q_PROPERTY(QString name READ nameTitle)
-  Q_PROPERTY(int processId READ processId)
-  Q_PROPERTY(QString keyBindings READ keyBindings WRITE setKeyBindings)
-  Q_PROPERTY(QSize size READ size WRITE setSize)
-
-  /**
-   * Constructs a new session.
-   *
-   * To start the terminal process, call the run() method,
-   * after specifying the program and arguments
-   * using setProgram() and setArguments()
-   *
-   * If no program or arguments are specified explicitly, the Session
-   * falls back to using the program specified in the SHELL environment
-   * variable.
-   */
-  Session(int masterFd = -1, int slaveFd = -1);
-  ~Session();
-
-  /**
-   * Returns true if the session is currently running.  This will be true
-   * after run() has been called successfully.
-   */
-  bool isRunning() const;
-
-  /**
-   * Sets the profile associated with this session.
-   *
-   * @param profileKey A key which can be used to obtain the current
-   * profile settings from the SessionManager
-   */
-  void setProfileKey(const QString& profileKey);
-  /**
-   * Returns the profile key associated with this session.
-   * This can be passed to the SessionManager to obtain the current
-   * profile settings.
-   */
-  QString profileKey() const;
-
-  /**
-   * Adds a new view for this session.
-   *
-   * The viewing widget will display the output from the terminal and
-   * input from the viewing widget (key presses, mouse activity etc.)
-   * will be sent to the terminal.
-   *
-   * Views can be removed using removeView().  The session is automatically
-   * closed when the last view is removed.
-   */
-  void addView(TerminalDisplay* widget);
-  /**
-   * Removes a view from this session.  When the last view is removed,
-   * the session will be closed automatically.
-   *
-   * @p widget will no longer display output from or send input
-   * to the terminal
-   */
-  void removeView(TerminalDisplay* widget);
-
-  /**
-   * Returns the views connected to this session
-   */
-  QList<TerminalDisplay*> views() const;
-
-  /**
-   * Returns the terminal emulation instance being used to encode / decode
-   * characters to / from the process.
-   */
-  Emulation*  emulation() const;
-
-  /**
-   * Returns the environment of this session as a list of strings like
-   * VARIABLE=VALUE
-   */
-  QStringList environment() const;
-  /**
-   * Sets the environment for this session.
-   * @p environment should be a list of strings like
-   * VARIABLE=VALUE
-   */
-  void setEnvironment(const QStringList& environment);
-
-  /** Returns the unique ID for this session. */
-  int sessionId() const;
-
-  /**
-   * Return the session title set by the user (ie. the program running
-   * in the terminal), or an empty string if the user has not set a custom title
-   */
-  QString userTitle() const;
-
-  /**
-   * This enum describes the contexts for which separate
-   * tab title formats may be specified.
-   */
-  enum TabTitleContext
-  {
-    /** Default tab title format */
-    LocalTabTitle,
-    /**
-     * Tab title format used session currently contains
-     * a connection to a remote computer (via SSH)
-     */
-    RemoteTabTitle
-  };
-  /**
-   * Sets the format used by this session for tab titles.
-   *
-   * @param context The context whoose format should be set.
-   * @param format The tab title format.  This may be a mixture
-   * of plain text and dynamic elements denoted by a '%' character
-   * followed by a letter.  (eg. %d for directory).  The dynamic
-   * elements available depend on the @p context
-   */
-  void setTabTitleFormat(TabTitleContext context , const QString& format);
-  /** Returns the format used by this session for tab titles. */
-  QString tabTitleFormat(TabTitleContext context) const;
-
-
-  /** Returns the arguments passed to the shell process when run() is called. */
-  QStringList arguments() const;
-  /** Returns the program name of the shell process started when run() is called. */
-  QString program() const;
-
-  /**
-   * Sets the command line arguments which the session's program will be passed when
-   * run() is called.
-   */
-  void setArguments(const QStringList& arguments);
-  /** Sets the program to be executed when run() is called. */
-  void setProgram(const QString& program);
-
-  /** Returns the session's current working directory. */
-  QString initialWorkingDirectory() { return _initialWorkingDir; }
-
-  /**
-   * Sets the initial working directory for the session when it is run
-   * This has no effect once the session has been started.
-   */
-  void setInitialWorkingDirectory( const QString& dir );
-
-  /**
-   * Sets the type of history store used by this session.
-   * Lines of output produced by the terminal are added
-   * to the history store.  The type of history store
-   * used affects the number of lines which can be
-   * remembered before they are lost and the storage
-   * (in memory, on-disk etc.) used.
-   */
-  void setHistoryType(const HistoryType& type);
-  /**
-   * Returns the type of history store used by this session.
-   */
-  const HistoryType& historyType() const;
-  /**
-   * Clears the history store used by this session.
-   */
-  void clearHistory();
-
-  /**
-   * Enables monitoring for activity in the session.
-   * This will cause notifySessionState() to be emitted
-   * with the NOTIFYACTIVITY state flag when output is
-   * received from the terminal.
-   */
-  void setMonitorActivity(bool);
-  /** Returns true if monitoring for activity is enabled. */
-  bool isMonitorActivity() const;
-
-  /**
-   * Enables monitoring for silence in the session.
-   * This will cause notifySessionState() to be emitted
-   * with the NOTIFYSILENCE state flag when output is not
-   * received from the terminal for a certain period of
-   * time, specified with setMonitorSilenceSeconds()
-   */
-  void setMonitorSilence(bool);
-  /**
-   * Returns true if monitoring for inactivity (silence)
-   * in the session is enabled.
-   */
-  bool isMonitorSilence()  const;
-  /** See setMonitorSilence() */
-  void setMonitorSilenceSeconds(int seconds);
-
-  /**
-   * Sets the key bindings used by this session.  The bindings
-   * specify how input key sequences are translated into
-   * the character stream which is sent to the terminal.
-   *
-   * @param id The name of the key bindings to use.  The
-   * names of available key bindings can be determined using the
-   * KeyboardTranslatorManager class.
-   */
-  void setKeyBindings(const QString& id);
-  /** Returns the name of the key bindings used by this session. */
-  QString keyBindings() const;
-
-  /**
-   * This enum describes the available title roles.
-   */
-  enum TitleRole
-  {
-      /** The name of the session. */
-      NameRole,
-      /** The title of the session which is displayed in tabs etc. */
-      DisplayedTitleRole
-  };
-
-  /** Sets the session's title for the specified @p role to @p title. */
-  void setTitle(TitleRole role , const QString& title);
-  /** Returns the session's title for the specified @p role. */
-  QString title(TitleRole role) const;
-  /** Convenience method used to read the name property.  Returns title(Session::NameRole). */
-  QString nameTitle() const { return title(Session::NameRole); }
-
-  /** Sets the name of the icon associated with this session. */
-  void setIconName(const QString& iconName);
-  /** Returns the name of the icon associated with this session. */
-  QString iconName() const;
-
-  /** Sets the text of the icon associated with this session. */
-  void setIconText(const QString& iconText);
-  /** Returns the text of the icon associated with this session. */
-  QString iconText() const;
-
-  /** Specifies whether a utmp entry should be created for the pty used by this session. */
-  void setAddToUtmp(bool);
-
-  /** Sends the specified @p signal to the terminal process. */
-  bool sendSignal(int signal);
-
-  /**
-   * Specifies whether to close the session automatically when the terminal
-   * process terminates.
-   */
-  void setAutoClose(bool b) { _autoClose = b; }
-
-  /**
-   * Sets whether flow control is enabled for this terminal
-   * session.
-   */
-  void setFlowControlEnabled(bool enabled);
-
-  /** Returns whether flow control is enabled for this terminal session. */
-  bool flowControlEnabled() const;
-
-  /**
-   * Sends @p text to the current foreground terminal program.
-   */
-  void sendText(const QString& text) const;
-
-  /**
-   * Returns the process id of the terminal process.
-   * This is the id used by the system API to refer to the process.
-   */
-  int processId() const;
-
-  /**
-   * Returns the process id of the terminal's foreground process.
-   * This is initially the same as processId() but can change
-   * as the user starts other programs inside the terminal.
-   */
-  int foregroundProcessId() const;
-
-  /** Returns the terminal session's window size in lines and columns. */
-  QSize size();
-  /**
-   * Emits a request to resize the session to accommodate
-   * the specified window size.
-   *
-   * @param size The size in lines and columns to request.
-   */
-  void setSize(const QSize& size);
-
-  /** Sets the text codec used by this session's terminal emulation. */
-  void setCodec(QTextCodec* codec);
-
-  /**
-   * Sets whether the session has a dark background or not.  The session
-   * uses this information to set the COLORFGBG variable in the process's
-   * environment, which allows the programs running in the terminal to determine
-   * whether the background is light or dark and use appropriate colors by default.
-   *
-   * This has no effect once the session is running.
-   */
-  void setDarkBackground(bool darkBackground);
-  /**
-   * Returns true if the session has a dark background.
-   * See setDarkBackground()
-   */
-  bool hasDarkBackground() const;
-
-  /**
-   * Attempts to get the shell program to redraw the current display area.
-   * This can be used after clearing the screen, for example, to get the
-   * shell to redraw the prompt line.
-   */
-  void refresh();
-
-//  void startZModem(const QString &rz, const QString &dir, const QStringList &list);
-//  void cancelZModem();
-//  bool isZModemBusy() { return _zmodemBusy; }
-
-public slots:
-
-  /**
-   * Starts the terminal session.
-   *
-   * This creates the terminal process and connects the teletype to it.
-   */
-  void run();
-
-  /**
-   * Closes the terminal session.  This sends a hangup signal
-   * (SIGHUP) to the terminal process and causes the done(Session*)
-   * signal to be emitted.
-   */
-  void close();
-
-  /**
-   * Changes the session title or other customizable aspects of the terminal
-   * emulation display. For a list of what may be changed see the
-   * Emulation::titleChanged() signal.
-   */
-  void setUserTitle( int, const QString &caption );
-
-signals:
-
-  /** Emitted when the terminal process starts. */
-  void started();
-
-  /**
-   * Emitted when the terminal process exits.
-   */
-  void finished();
-
-  /**
-   * Emitted when output is received from the terminal process.
-   */
-  void receivedData( const QString& text );
-
-  /** Emitted when the session's title has changed. */
-  void titleChanged();
-
-  /** Emitted when the session's profile has changed. */
-  void profileChanged(const QString& profile);
-
-  /**
-   * Emitted when the activity state of this session changes.
-   *
-   * @param state The new state of the session.  This may be one
-   * of NOTIFYNORMAL, NOTIFYSILENCE or NOTIFYACTIVITY
-   */
-  void stateChanged(int state);
-
-  /** Emitted when a bell event occurs in the session. */
-  void bellRequest( const QString& message );
-
-  /**
-   * Requests that the color the text for any tabs associated with
-   * this session should be changed;
-   *
-   * TODO: Document what the parameter does
-   */
-  void changeTabTextColorRequest(int);
-
-  /**
-   * Requests that the background color of views on this session
-   * should be changed.
-   */
-  void changeBackgroundColorRequest(const QColor&);
-
-  /** TODO: Document me. */
-  void openUrlRequest(const QString& url);
-
-  /** TODO: Document me. */
-//  void zmodemDetected();
-
-  /**
-   * Emitted when the terminal process requests a change
-   * in the size of the terminal window.
-   *
-   * @param size The requested window size in terms of lines and columns.
-   */
-  void resizeRequest(const QSize& size);
-
-  /**
-   * Emitted when a profile change command is received from the terminal.
-   *
-   * @param text The text of the command.  This is a string of the form
-   * "PropertyName=Value;PropertyName=Value ..."
-   */
-  void profileChangeCommandReceived(const QString& text);
-
- /**
-  * Emitted when the flow control state changes.
-  *
-  * @param enabled True if flow control is enabled or false otherwise.
-  */
-  void flowControlEnabledChanged(bool enabled);
-
-private slots:
-  void done(int);
-
-//  void fireZModemDetected();
-
-  void onReceiveBlock( const char* buffer, int len );
-  void monitorTimerDone();
-
-  void onViewSizeChange(int height, int width);
-  void onEmulationSizeChange(int lines , int columns);
-
-  void activityStateSet(int);
-
-  //automatically detach views from sessions when view is destroyed
-  void viewDestroyed(QObject* view);
-
-//  void zmodemReadStatus();
-//  void zmodemReadAndSendBlock();
-//  void zmodemRcvBlock(const char *data, int len);
-//  void zmodemFinished();
-
-private:
-
-  void updateTerminalSize();
-  WId windowId() const;
-
-  int            _uniqueIdentifier;
-
-  PseudoTerminal*          _shellProcess;
-  Emulation*    _emulation;
-
-  QList<TerminalDisplay*> _views;
-
-  bool           _monitorActivity;
-  bool           _monitorSilence;
-  bool           _notifiedActivity;
-  bool           _masterMode;
-  bool           _autoClose;
-  bool           _wantedClose;
-  QTimer*        _monitorTimer;
-
-  int            _silenceSeconds;
-
-  QString        _nameTitle;
-  QString        _displayTitle;
-  QString        _userTitle;
-
-  QString        _localTabTitleFormat;
-  QString        _remoteTabTitleFormat;
-
-  QString        _iconName;
-  QString        _iconText; // as set by: echo -en '\033]1;IconText\007
-  bool           _addToUtmp;
-  bool           _flowControl;
-  bool           _fullScripting;
-
-  QString        _program;
-  QStringList    _arguments;
-
-  QStringList    _environment;
-  int            _sessionId;
-  int            _masterFd;
-  int            _slaveFd;
-  QString        _initialWorkingDir;
-
-  // ZModem
-//  bool           _zmodemBusy;
-//  KProcess*      _zmodemProc;
-//  ZModemDialog*  _zmodemProgress;
-
-  // Color/Font Changes by ESC Sequences
-
-  QColor         _modifiedBackground; // as set by: echo -en '\033]11;Color\007
-
-  QString        _profileKey;
-
-  bool _hasDarkBackground;
-
-  static int lastSessionId;
-
-};
-
-/**
- * Provides a group of sessions which is divided into master and slave sessions.
- * Activity in master sessions can be propagated to all sessions within the group.
- * The type of activity which is propagated and method of propagation is controlled
- * by the masterMode() flags.
- */
-class SessionGroup : public QObject
-{
-Q_OBJECT
-
-public:
-    /** Constructs an empty session group. */
-    SessionGroup();
-    /** Destroys the session group and removes all connections between master and slave sessions. */
-    ~SessionGroup();
-
-    /** Adds a session to the group. */
-    void addSession( Session* session );
-    /** Removes a session from the group. */
-    void removeSession( Session* session );
-
-    /** Returns the list of sessions currently in the group. */
-    QList<Session*> sessions() const;
-
-    /**
-     * Sets whether a particular session is a master within the group.
-     * Changes or activity in the group's master sessions may be propagated
-     * to all the sessions in the group, depending on the current masterMode()
-     *
-     * @param session The session whoose master status should be changed.
-     * @param master True to make this session a master or false otherwise
-     */
-    void setMasterStatus( Session* session , bool master );
-    /** Returns the master status of a session.  See setMasterStatus() */
-    bool masterStatus( Session* session ) const;
-
-    /**
-     * This enum describes the options for propagating certain activity or
-     * changes in the group's master sessions to all sessions in the group.
-     */
-    enum MasterMode
-    {
-        /**
-         * Any input key presses in the master sessions are sent to all
-         * sessions in the group.
-         */
-        CopyInputToAll = 1
-    };
-
-    /**
-     * Specifies which activity in the group's master sessions is propagated
-     * to all sessions in the group.
-     *
-     * @param mode A bitwise OR of MasterMode flags.
-     */
-    void setMasterMode( int mode );
-    /**
-     * Returns a bitwise OR of the active MasterMode flags for this group.
-     * See setMasterMode()
-     */
-    int masterMode() const;
-
-private:
-    void connectPair(Session* master , Session* other);
-    void disconnectPair(Session* master , Session* other);
-    void connectAll(bool connect);
-    QList<Session*> masters() const;
-
-    // maps sessions to their master status
-    QHash<Session*,bool> _sessions;
-
-    int _masterMode;
-};
-
-#endif
new file mode 100644
--- /dev/null
+++ b/libqterminal/SessionModel.cpp
@@ -0,0 +1,1029 @@
+/*
+    This file is part of Konsole
+
+    Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com>
+    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301  USA.
+*/
+
+// Own
+#include "SessionModel.h"
+
+// Standard
+#include <assert.h>
+#include <stdlib.h>
+
+// Qt
+#include <QtGui/QApplication>
+#include <QtCore/QByteRef>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QRegExp>
+#include <QtCore/QStringList>
+#include <QtCore>
+
+#include "PseudoTerminal.h"
+#include "SessionView.h"
+#include "ShellCommand.h"
+#include "Vt102Emulation.h"
+
+int SessionModel::lastSessionId = 0;
+
+SessionModel::SessionModel(int masterFd, int slaveFd) :
+    _shellProcess(0)
+  , _emulation(0)
+  , _monitorActivity(false)
+  , _monitorSilence(false)
+  , _notifiedActivity(false)
+  , _autoClose(true)
+  , _wantedClose(false)
+  , _silenceSeconds(10)
+  , _addToUtmp(false)  // disabled by default because of a bug encountered on certain systems
+  // which caused Konsole to hang when closing a tab and then opening a new
+  // one.  A 'QProcess destroyed while still running' warning was being
+  // printed to the terminal.  Likely a problem in KPty::logout()
+  // or KPty::login() which uses a QProcess to start /usr/bin/utempter
+  , _flowControl(true)
+  , _fullScripting(false)
+  , _sessionId(0)
+  //   , _zmodemBusy(false)
+  //   , _zmodemProc(0)
+  //   , _zmodemProgress(0)
+  , _hasDarkBackground(false)
+{
+    _masterFd = masterFd;
+    _slaveFd = slaveFd;
+
+    //prepare DBus communication
+    //    new SessionAdaptor(this);
+    _sessionId = ++lastSessionId;
+    //    QDBusConnection::sessionBus().registerObject(QLatin1String("/Sessions/")+QString::number(_sessionId), this);
+
+    //create teletype for I/O with shell process
+    if(_masterFd >= 0) {
+        _shellProcess = new PseudoTerminal(_masterFd, _slaveFd);
+    } else {
+        _shellProcess = new PseudoTerminal();
+    }
+
+    //create emulation backend
+    _emulation = new Vt102Emulation();
+
+    connect( _emulation, SIGNAL( titleChanged( int, const QString & ) ),
+             this, SLOT( setUserTitle( int, const QString & ) ) );
+    connect( _emulation, SIGNAL( stateSet(int) ),
+             this, SLOT( activityStateSet(int) ) );
+    //    connect( _emulation, SIGNAL( zmodemDetected() ), this ,
+    //            SLOT( fireZModemDetected() ) );
+    connect( _emulation, SIGNAL( changeTabTextColorRequest( int ) ),
+             this, SIGNAL( changeTabTextColorRequest( int ) ) );
+    connect( _emulation, SIGNAL(profileChangeCommandReceived(const QString&)),
+             this, SIGNAL( profileChangeCommandReceived(const QString&)) );
+    // TODO
+    // connect( _emulation,SIGNAL(imageSizeChanged(int,int)) , this ,
+    //        SLOT(onEmulationSizeChange(int,int)) );
+
+    //connect teletype to emulation backend
+    _shellProcess->setUtf8Mode(_emulation->utf8());
+
+    connect( _shellProcess,SIGNAL(receivedData(const char*,int)),this,
+             SLOT(onReceiveBlock(const char*,int)) );
+    connect( _emulation,SIGNAL(sendData(const char*,int)),_shellProcess,
+             SLOT(sendData(const char*,int)) );
+    connect( _emulation,SIGNAL(lockPtyRequest(bool)),_shellProcess,SLOT(lockPty(bool)) );
+    connect( _emulation,SIGNAL(useUtf8Request(bool)),_shellProcess,SLOT(setUtf8Mode(bool)) );
+
+
+    connect( _shellProcess,SIGNAL(done(int)), this, SLOT(done(int)) );
+
+    //setup timer for monitoring session activity
+    _monitorTimer = new QTimer(this);
+    _monitorTimer->setSingleShot(true);
+    connect(_monitorTimer, SIGNAL(timeout()), this, SLOT(monitorTimerDone()));
+}
+
+WId SessionModel::windowId() const
+{
+    // Returns a window ID for this session which is used
+    // to set the WINDOWID environment variable in the shell
+    // process.
+    //
+    // Sessions can have multiple views or no views, which means
+    // that a single ID is not always going to be accurate.
+    //
+    // If there are no views, the window ID is just 0.  If
+    // there are multiple views, then the window ID for the
+    // top-level window which contains the first view is
+    // returned
+
+    if ( _views.count() == 0 )
+        return 0;
+    else
+    {
+        QWidget* window = _views.first();
+
+        Q_ASSERT( window );
+
+        while ( window->parentWidget() != 0 )
+            window = window->parentWidget();
+
+        return window->winId();
+    }
+}
+
+void SessionModel::setDarkBackground(bool darkBackground)
+{
+    _hasDarkBackground = darkBackground;
+}
+bool SessionModel::hasDarkBackground() const
+{
+    return _hasDarkBackground;
+}
+bool SessionModel::isRunning() const
+{
+    return _shellProcess->isRunning();
+}
+
+void SessionModel::setCodec(QTextCodec* codec)
+{
+    emulation()->setCodec(codec);
+}
+
+void SessionModel::setProgram(const QString& program)
+{
+    _program = ShellCommand::expand(program);
+}
+void SessionModel::setInitialWorkingDirectory(const QString& dir)
+{
+    _initialWorkingDir = ShellCommand::expand(dir);
+}
+void SessionModel::setArguments(const QStringList& arguments)
+{
+    _arguments = ShellCommand::expand(arguments);
+}
+
+QList<SessionView*> SessionModel::views() const
+{
+    return _views;
+}
+
+void SessionModel::addView(SessionView* widget)
+{
+    Q_ASSERT( !_views.contains(widget) );
+
+    _views.append(widget);
+
+    if ( _emulation != 0 )
+    {
+        // connect emulation - view signals and slots
+        connect( widget , SIGNAL(keyPressedSignal(QKeyEvent*)) , _emulation ,
+                 SLOT(sendKeyEvent(QKeyEvent*)) );
+        connect( widget , SIGNAL(mouseSignal(int,int,int,int)) , _emulation ,
+                 SLOT(sendMouseEvent(int,int,int,int)) );
+        connect( widget , SIGNAL(sendStringToEmu(const char*)) , _emulation ,
+                 SLOT(sendString(const char*)) );
+
+        // allow emulation to notify view when the foreground process
+        // indicates whether or not it is interested in mouse signals
+        connect( _emulation , SIGNAL(programUsesMouseChanged(bool)) , widget ,
+                 SLOT(setUsesMouse(bool)) );
+
+        widget->setUsesMouse( _emulation->programUsesMouse() );
+
+        widget->setScreenWindow(_emulation->createWindow());
+    }
+
+    //connect view signals and slots
+    QObject::connect( widget ,SIGNAL(changedContentSizeSignal(int,int)),this,
+                      SLOT(onViewSizeChange(int,int)));
+
+    QObject::connect( widget ,SIGNAL(destroyed(QObject*)) , this ,
+                      SLOT(viewDestroyed(QObject*)) );
+    //slot for close
+    QObject::connect(this, SIGNAL(finished()), widget, SLOT(close()));		    
+    
+}
+
+void SessionModel::viewDestroyed(QObject* view)
+{
+    SessionView* display = (SessionView*)view;
+
+    Q_ASSERT( _views.contains(display) );
+
+    removeView(display);
+}
+
+void SessionModel::removeView(SessionView* widget)
+{
+    _views.removeAll(widget);
+
+    disconnect(widget,0,this,0);
+
+    if ( _emulation != 0 )
+    {
+        // disconnect
+        //  - key presses signals from widget
+        //  - mouse activity signals from widget
+        //  - string sending signals from widget
+        //
+        //  ... and any other signals connected in addView()
+        disconnect( widget, 0, _emulation, 0);
+
+        // disconnect state change signals emitted by emulation
+        disconnect( _emulation , 0 , widget , 0);
+    }
+
+    // close the session automatically when the last view is removed
+    if ( _views.count() == 0 )
+    {
+        close();
+    }
+}
+
+void SessionModel::run()
+{
+    //check that everything is in place to run the session
+    if (_program.isEmpty())
+        qDebug() << "Session::run() - program to run not set.";
+    if (_arguments.isEmpty())
+        qDebug() << "Session::run() - no command line arguments specified.";
+
+    // Upon a KPty error, there is no description on what that error was...
+    // Check to see if the given program is executable.
+    QString exec = QFile::encodeName(_program);
+
+    // if 'exec' is not specified, fall back to default shell.  if that
+    // is not set then fall back to /bin/sh
+    if ( exec.isEmpty() )
+        exec = getenv("SHELL");
+    if ( exec.isEmpty() )
+        exec = "/bin/sh";
+
+    // if no arguments are specified, fall back to shell
+    QStringList arguments =  _arguments.join(QChar(' ')).isEmpty() ?
+                QStringList() << exec : _arguments;
+    QString pexec = exec;
+
+    if ( pexec.isEmpty() ) {
+        qDebug()<<"can not execute "<<exec<<endl;
+        QTimer::singleShot(1, this, SIGNAL(finished()));
+        return;
+    }
+
+    //  QString cwd_save = QDir::currentPath();
+    QString cwd = QDir::currentPath();
+    if (!_initialWorkingDir.isEmpty())
+        _shellProcess->setWorkingDirectory(_initialWorkingDir);
+    else
+        _shellProcess->setWorkingDirectory(cwd);
+    //    _shellProcess->setWorkingDirectory(QDir::homePath());
+
+    _shellProcess->setXonXoff(_flowControl);
+    _shellProcess->setErase(_emulation->getErase());
+
+    // this is not strictly accurate use of the COLORFGBG variable.  This does not
+    // tell the terminal exactly which colors are being used, but instead approximates
+    // the color scheme as "black on white" or "white on black" depending on whether
+    // the background color is deemed dark or not
+    QString backgroundColorHint = _hasDarkBackground ? "COLORFGBG=15;0" : "COLORFGBG=0;15";
+
+    int result = _shellProcess->start(QFile::encodeName(_program),
+                                      arguments,
+                                      _environment << backgroundColorHint,
+                                      windowId(),
+                                      _addToUtmp,
+                                      _masterFd,
+                                      _slaveFd);
+
+    if (result < 0)
+    {
+        return;
+    }
+
+    _shellProcess->setWriteable(false);  // We are reachable via kwrited.
+
+    emit started();
+}
+
+void SessionModel::setUserTitle( int what, const QString &caption )
+{
+    //set to true if anything is actually changed (eg. old _nameTitle != new _nameTitle )
+    bool modified = false;
+
+    // (btw: what=0 changes _userTitle and icon, what=1 only icon, what=2 only _nameTitle
+    if ((what == 0) || (what == 2)) 
+    {
+       	if ( _userTitle != caption ) {
+            _userTitle = caption;
+            modified = true;
+        }
+    }
+
+    if ((what == 0) || (what == 1))
+    {
+        if ( _iconText != caption ) {
+            _iconText = caption;
+            modified = true;
+        }
+    }
+
+    if (what == 11) 
+    {
+        QString colorString = caption.section(';',0,0);
+        qDebug() << __FILE__ << __LINE__ << ": setting background colour to " << colorString;
+        QColor backColor = QColor(colorString);
+        if (backColor.isValid()){// change color via \033]11;Color\007
+            if (backColor != _modifiedBackground)
+            {
+                _modifiedBackground = backColor;
+
+                // bail out here until the code to connect the terminal display
+                // to the changeBackgroundColor() signal has been written
+                // and tested - just so we don't forget to do this.
+                Q_ASSERT( 0 );
+
+                emit changeBackgroundColorRequest(backColor);
+            }
+        }
+    }
+
+    if (what == 30)
+    {
+        if ( _nameTitle != caption ) {
+            setTitle(SessionModel::NameRole,caption);
+            return;
+        }
+    }
+
+    if (what == 31) 
+    {
+        QString cwd=caption;
+        cwd=cwd.replace( QRegExp("^~"), QDir::homePath() );
+        emit openUrlRequest(cwd);
+    }
+
+    // change icon via \033]32;Icon\007
+    if (what == 32) 
+    { 
+    	if ( _iconName != caption ) {
+            _iconName = caption;
+
+            modified = true;
+        }
+    }
+
+    if (what == 50) 
+    {
+        emit profileChangeCommandReceived(caption);
+        return;
+    }
+
+    if ( modified )
+    	emit titleChanged();
+}
+
+QString SessionModel::userTitle() const
+{
+    return _userTitle;
+}
+void SessionModel::setTabTitleFormat(TabTitleContext context , const QString& format)
+{
+    if ( context == LocalTabTitle )
+        _localTabTitleFormat = format;
+    else if ( context == RemoteTabTitle )
+        _remoteTabTitleFormat = format;
+}
+QString SessionModel::tabTitleFormat(TabTitleContext context) const
+{
+    if ( context == LocalTabTitle )
+        return _localTabTitleFormat;
+    else if ( context == RemoteTabTitle )
+        return _remoteTabTitleFormat;
+
+    return QString();
+}
+
+void SessionModel::monitorTimerDone()
+{
+    //FIXME: The idea here is that the notification popup will appear to tell the user than output from
+    //the terminal has stopped and the popup will disappear when the user activates the session.
+    //
+    //This breaks with the addition of multiple views of a session.  The popup should disappear
+    //when any of the views of the session becomes active
+
+
+    //FIXME: Make message text for this notification and the activity notification more descriptive.
+    if (_monitorSilence) {
+        //    KNotification::event("Silence", ("Silence in session '%1'", _nameTitle), QPixmap(),
+        //                    QApplication::activeWindow(),
+        //                    KNotification::CloseWhenWidgetActivated);
+        emit stateChanged(NOTIFYSILENCE);
+    }
+    else
+    {
+        emit stateChanged(NOTIFYNORMAL);
+    }
+
+    _notifiedActivity=false;
+}
+
+void SessionModel::activityStateSet(int state)
+{
+    if (state==NOTIFYBELL)
+    {
+        QString s; s.sprintf("Bell in session '%s'",_nameTitle.toAscii().data());
+
+        emit bellRequest( s );
+    }
+    else if (state==NOTIFYACTIVITY)
+    {
+        if (_monitorSilence) {
+            _monitorTimer->start(_silenceSeconds*1000);
+        }
+
+        if ( _monitorActivity ) {
+            //FIXME:  See comments in Session::monitorTimerDone()
+            if (!_notifiedActivity) {
+                //        KNotification::event("Activity", ("Activity in session '%1'", _nameTitle), QPixmap(),
+                //                        QApplication::activeWindow(),
+                //        KNotification::CloseWhenWidgetActivated);
+                _notifiedActivity=true;
+            }
+        }
+    }
+
+    if ( state==NOTIFYACTIVITY && !_monitorActivity )
+        state = NOTIFYNORMAL;
+    if ( state==NOTIFYSILENCE && !_monitorSilence )
+        state = NOTIFYNORMAL;
+
+    emit stateChanged(state);
+}
+
+void SessionModel::onViewSizeChange(int /*height*/, int /*width*/)
+{
+    updateTerminalSize();
+}
+void SessionModel::onEmulationSizeChange(int lines , int columns)
+{
+    setSize( QSize(lines,columns) );
+}
+
+void SessionModel::updateTerminalSize()
+{
+    QListIterator<SessionView*> viewIter(_views);
+
+    int minLines = -1;
+    int minColumns = -1;
+
+    // minimum number of lines and columns that views require for
+    // their size to be taken into consideration ( to avoid problems
+    // with new view widgets which haven't yet been set to their correct size )
+    const int VIEW_LINES_THRESHOLD = 2;
+    const int VIEW_COLUMNS_THRESHOLD = 2;
+
+    //select largest number of lines and columns that will fit in all visible views
+    while ( viewIter.hasNext() )
+    {
+        SessionView* view = viewIter.next();
+        if ( view->isHidden() == false &&
+             view->lines() >= VIEW_LINES_THRESHOLD &&
+             view->columns() >= VIEW_COLUMNS_THRESHOLD )
+        {
+            minLines = (minLines == -1) ? view->lines() : qMin( minLines , view->lines() );
+            minColumns = (minColumns == -1) ? view->columns() : qMin( minColumns , view->columns() );
+        }
+    }
+
+    // backend emulation must have a _terminal of at least 1 column x 1 line in size
+    if ( minLines > 0 && minColumns > 0 )
+    {
+        _emulation->setImageSize( minLines , minColumns );
+        _shellProcess->setWindowSize( minLines , minColumns );
+    }
+}
+
+void SessionModel::refresh()
+{
+    // attempt to get the shell process to redraw the display
+    //
+    // this requires the program running in the shell
+    // to cooperate by sending an update in response to
+    // a window size change
+    //
+    // the window size is changed twice, first made slightly larger and then
+    // resized back to its normal size so that there is actually a change
+    // in the window size (some shells do nothing if the
+    // new and old sizes are the same)
+    //
+    // if there is a more 'correct' way to do this, please
+    // send an email with method or patches to konsole-devel@kde.org
+
+    const QSize existingSize = _shellProcess->windowSize();
+    _shellProcess->setWindowSize(existingSize.height(),existingSize.width()+1);
+    _shellProcess->setWindowSize(existingSize.height(),existingSize.width());
+}
+
+bool SessionModel::sendSignal(int signal)
+{
+    return _shellProcess->kill(signal);
+}
+
+void SessionModel::close()
+{
+    _autoClose = true;
+    _wantedClose = true;
+    if (!_shellProcess->isRunning() || !sendSignal(SIGHUP))
+    {
+        // Forced close.
+        QTimer::singleShot(1, this, SIGNAL(finished()));
+    }
+}
+
+void SessionModel::sendText(const QString &text) const
+{
+    _emulation->sendText(text);
+}
+
+SessionModel::~SessionModel()
+{
+    delete _emulation;
+    delete _shellProcess;
+    //  delete _zmodemProc;
+}
+
+void SessionModel::setProfileKey(const QString& key)
+{
+    _profileKey = key;
+    emit profileChanged(key);
+}
+QString SessionModel::profileKey() const { return _profileKey; }
+
+void SessionModel::done(int exitStatus)
+{
+    if (!_autoClose)
+    {
+        _userTitle = ("<Finished>");
+        emit titleChanged();
+        return;
+    }
+    if (!_wantedClose && (exitStatus || _shellProcess->signalled()))
+    {
+        QString message;
+
+        if (_shellProcess->normalExit())
+            message.sprintf ("Session '%s' exited with status %d.", _nameTitle.toAscii().data(), exitStatus);
+        else if (_shellProcess->signalled())
+        {
+            if (_shellProcess->coreDumped())
+            {
+
+                message.sprintf("Session '%s' exited with signal %d and dumped core.", _nameTitle.toAscii().data(), _shellProcess->exitSignal());
+            }
+            else {
+                message.sprintf("Session '%s' exited with signal %d.", _nameTitle.toAscii().data(), _shellProcess->exitSignal());
+            }
+        }
+        else
+            message.sprintf ("Session '%s' exited unexpectedly.", _nameTitle.toAscii().data());
+
+        //FIXME: See comments in Session::monitorTimerDone()
+        //    KNotification::event("Finished", message , QPixmap(),
+        //                         QApplication::activeWindow(),
+        //                         KNotification::CloseWhenWidgetActivated);
+    }
+    emit finished();
+}
+
+Emulation* SessionModel::emulation() const
+{
+    return _emulation;
+}
+
+QString SessionModel::keyBindings() const
+{
+    return _emulation->keyBindings();
+}
+
+QStringList SessionModel::environment() const
+{
+    return _environment;
+}
+
+void SessionModel::setEnvironment(const QStringList& environment)
+{
+    _environment = environment;
+}
+
+int SessionModel::sessionId() const
+{
+    return _sessionId;
+}
+
+void SessionModel::setKeyBindings(const QString &id)
+{
+    _emulation->setKeyBindings(id);
+}
+
+void SessionModel::setTitle(TitleRole role , const QString& newTitle)
+{
+    if ( title(role) != newTitle )
+    {
+        if ( role == NameRole )
+            _nameTitle = newTitle;
+        else if ( role == DisplayedTitleRole )
+            _displayTitle = newTitle;
+
+        emit titleChanged();
+    }
+}
+
+QString SessionModel::title(TitleRole role) const
+{
+    if ( role == NameRole )
+        return _nameTitle;
+    else if ( role == DisplayedTitleRole )
+        return _displayTitle;
+    else
+        return QString();
+}
+
+void SessionModel::setIconName(const QString& iconName)
+{
+    if ( iconName != _iconName )
+    {
+        _iconName = iconName;
+        emit titleChanged();
+    }
+}
+
+void SessionModel::setIconText(const QString& iconText)
+{
+    _iconText = iconText;
+    //kDebug(1211)<<"Session setIconText " <<  _iconText;
+}
+
+QString SessionModel::iconName() const
+{
+    return _iconName;
+}
+
+QString SessionModel::iconText() const
+{
+    return _iconText;
+}
+
+void SessionModel::setHistoryType(const HistoryType &hType)
+{
+    _emulation->setHistory(hType);
+}
+
+const HistoryType& SessionModel::historyType() const
+{
+    return _emulation->history();
+}
+
+void SessionModel::clearHistory()
+{
+    _emulation->clearHistory();
+}
+
+QStringList SessionModel::arguments() const
+{
+    return _arguments;
+}
+
+QString SessionModel::program() const
+{
+    return _program;
+}
+
+// unused currently
+bool SessionModel::isMonitorActivity() const { return _monitorActivity; }
+// unused currently
+bool SessionModel::isMonitorSilence()  const { return _monitorSilence; }
+
+void SessionModel::setMonitorActivity(bool _monitor)
+{
+    _monitorActivity=_monitor;
+    _notifiedActivity=false;
+
+    activityStateSet(NOTIFYNORMAL);
+}
+
+void SessionModel::setMonitorSilence(bool _monitor)
+{
+    if (_monitorSilence==_monitor)
+        return;
+
+    _monitorSilence=_monitor;
+    if (_monitorSilence)
+    {
+        _monitorTimer->start(_silenceSeconds*1000);
+    }
+    else
+        _monitorTimer->stop();
+
+    activityStateSet(NOTIFYNORMAL);
+}
+
+void SessionModel::setMonitorSilenceSeconds(int seconds)
+{
+    _silenceSeconds=seconds;
+    if (_monitorSilence) {
+        _monitorTimer->start(_silenceSeconds*1000);
+    }
+}
+
+void SessionModel::setAddToUtmp(bool set)
+{
+    _addToUtmp = set;
+}
+
+void SessionModel::setFlowControlEnabled(bool enabled)
+{
+    if (_flowControl == enabled)
+  	return;
+
+    _flowControl = enabled;
+
+    if (_shellProcess)
+	_shellProcess->setXonXoff(_flowControl);
+
+    emit flowControlEnabledChanged(enabled);
+}
+bool SessionModel::flowControlEnabled() const
+{
+    return _flowControl;
+}
+//void Session::fireZModemDetected()
+//{
+//  if (!_zmodemBusy)
+//  {
+//    QTimer::singleShot(10, this, SIGNAL(zmodemDetected()));
+//    _zmodemBusy = true;
+//  }
+//}
+
+//void Session::cancelZModem()
+//{
+//  _shellProcess->sendData("\030\030\030\030", 4); // Abort
+//  _zmodemBusy = false;
+//}
+
+//void Session::startZModem(const QString &zmodem, const QString &dir, const QStringList &list)
+//{
+//  _zmodemBusy = true;
+//  _zmodemProc = new KProcess();
+//  _zmodemProc->setOutputChannelMode( KProcess::SeparateChannels );
+//
+//  *_zmodemProc << zmodem << "-v" << list;
+//
+//  if (!dir.isEmpty())
+//     _zmodemProc->setWorkingDirectory(dir);
+//
+//  _zmodemProc->start();
+//
+//  connect(_zmodemProc,SIGNAL (readyReadStandardOutput()),
+//          this, SLOT(zmodemReadAndSendBlock()));
+//  connect(_zmodemProc,SIGNAL (readyReadStandardError()),
+//          this, SLOT(zmodemReadStatus()));
+//  connect(_zmodemProc,SIGNAL (finished(int,QProcess::ExitStatus)),
+//          this, SLOT(zmodemFinished()));
+//
+//  disconnect( _shellProcess,SIGNAL(block_in(const char*,int)), this, SLOT(onReceiveBlock(const char*,int)) );
+//  connect( _shellProcess,SIGNAL(block_in(const char*,int)), this, SLOT(zmodemRcvBlock(const char*,int)) );
+//
+//  _zmodemProgress = new ZModemDialog(QApplication::activeWindow(), false,
+//                                    i18n("ZModem Progress"));
+//
+//  connect(_zmodemProgress, SIGNAL(user1Clicked()),
+//          this, SLOT(zmodemDone()));
+//
+//  _zmodemProgress->show();
+//}
+
+/*void Session::zmodemReadAndSendBlock()
+{
+  _zmodemProc->setReadChannel( QProcess::StandardOutput );
+  QByteArray data = _zmodemProc->readAll();
+
+  if ( data.count() == 0 )
+      return;
+
+  _shellProcess->sendData(data.constData(),data.count());
+}
+*/
+/*
+void Session::zmodemReadStatus()
+{
+  _zmodemProc->setReadChannel( QProcess::StandardError );
+  QByteArray msg = _zmodemProc->readAll();
+  while(!msg.isEmpty())
+  {
+     int i = msg.indexOf('\015');
+     int j = msg.indexOf('\012');
+     QByteArray txt;
+     if ((i != -1) && ((j == -1) || (i < j)))
+     {
+       msg = msg.mid(i+1);
+     }
+     else if (j != -1)
+     {
+       txt = msg.left(j);
+       msg = msg.mid(j+1);
+     }
+     else
+     {
+       txt = msg;
+       msg.truncate(0);
+     }
+     if (!txt.isEmpty())
+       _zmodemProgress->addProgressText(QString::fromLocal8Bit(txt));
+  }
+}
+*/
+/*
+void Session::zmodemRcvBlock(const char *data, int len)
+{
+  QByteArray ba( data, len );
+
+  _zmodemProc->write( ba );
+}
+*/
+/*
+void Session::zmodemFinished()
+{
+  if (_zmodemProc)
+  {
+    delete _zmodemProc;
+    _zmodemProc = 0;
+    _zmodemBusy = false;
+
+    disconnect( _shellProcess,SIGNAL(block_in(const char*,int)), this ,SLOT(zmodemRcvBlock(const char*,int)) );
+    connect( _shellProcess,SIGNAL(block_in(const char*,int)), this, SLOT(onReceiveBlock(const char*,int)) );
+
+    _shellProcess->sendData("\030\030\030\030", 4); // Abort
+    _shellProcess->sendData("\001\013\n", 3); // Try to get prompt back
+    _zmodemProgress->transferDone();
+  }
+}
+*/
+void SessionModel::onReceiveBlock( const char* buf, int len )
+{
+    _emulation->receiveData( buf, len );
+    emit receivedData( QString::fromLatin1( buf, len ) );
+}
+
+QSize SessionModel::size()
+{
+    return _emulation->imageSize();
+}
+
+void SessionModel::setSize(const QSize& size)
+{
+    if ((size.width() <= 1) || (size.height() <= 1))
+        return;
+
+    emit resizeRequest(size);
+}
+int SessionModel::foregroundProcessId() const
+{
+    return _shellProcess->foregroundProcessGroup();
+}
+int SessionModel::processId() const
+{
+    return _shellProcess->pid();
+}
+
+SessionGroup::SessionGroup()
+    : _masterMode(0)
+{
+}
+SessionGroup::~SessionGroup()
+{
+    // disconnect all
+    connectAll(false);
+}
+int SessionGroup::masterMode() const { return _masterMode; }
+QList<SessionModel*> SessionGroup::sessions() const { return _sessions.keys(); }
+bool SessionGroup::masterStatus(SessionModel* session) const { return _sessions[session]; }
+
+void SessionGroup::addSession(SessionModel* session)
+{
+    _sessions.insert(session,false);
+
+    QListIterator<SessionModel*> masterIter(masters());
+
+    while ( masterIter.hasNext() )
+        connectPair(masterIter.next(),session);
+}
+void SessionGroup::removeSession(SessionModel* session)
+{
+    setMasterStatus(session,false);
+
+    QListIterator<SessionModel*> masterIter(masters());
+
+    while ( masterIter.hasNext() )
+        disconnectPair(masterIter.next(),session);
+
+    _sessions.remove(session);
+}
+void SessionGroup::setMasterMode(int mode)
+{
+    _masterMode = mode;
+
+    connectAll(false);
+    connectAll(true);
+}
+QList<SessionModel*> SessionGroup::masters() const
+{
+    return _sessions.keys(true);
+}
+void SessionGroup::connectAll(bool connect)
+{
+    QListIterator<SessionModel*> masterIter(masters());
+
+    while ( masterIter.hasNext() )
+    {
+        SessionModel* master = masterIter.next();
+
+        QListIterator<SessionModel*> otherIter(_sessions.keys());
+        while ( otherIter.hasNext() )
+        {
+            SessionModel* other = otherIter.next();
+
+            if ( other != master )
+            {
+                if ( connect )
+                    connectPair(master,other);
+                else
+                    disconnectPair(master,other);
+            }
+        }
+    }
+}
+void SessionGroup::setMasterStatus(SessionModel* session, bool master) {
+    bool wasMaster = _sessions[session];
+    _sessions[session] = master;
+
+    if ((!wasMaster && !master)
+            || (wasMaster && master)) {
+        return;
+    }
+
+    QListIterator<SessionModel*> iter(_sessions.keys());
+    while (iter.hasNext()) {
+        SessionModel* other = iter.next();
+
+        if (other != session) {
+            if (master) {
+                connectPair(session, other);
+            } else {
+                disconnectPair(session, other);
+            }
+        }
+    }
+}
+
+void SessionGroup::connectPair(SessionModel* master , SessionModel* other)
+{
+    //    qDebug() << k_funcinfo;
+
+    if ( _masterMode & CopyInputToAll )
+    {
+        qDebug() << "Connection session " << master->nameTitle() << "to" << other->nameTitle();
+
+        connect( master->emulation() , SIGNAL(sendData(const char*,int)) , other->emulation() ,
+                 SLOT(sendString(const char*,int)) );
+    }
+}
+void SessionGroup::disconnectPair(SessionModel* master , SessionModel* other)
+{
+    //    qDebug() << k_funcinfo;
+
+    if ( _masterMode & CopyInputToAll )
+    {
+        qDebug() << "Disconnecting session " << master->nameTitle() << "from" << other->nameTitle();
+
+        disconnect( master->emulation() , SIGNAL(sendData(const char*,int)) , other->emulation() ,
+                    SLOT(sendString(const char*,int)) );
+    }
+}
+
new file mode 100644
--- /dev/null
+++ b/libqterminal/SessionModel.h
@@ -0,0 +1,615 @@
+/*
+    This file is part of Konsole, an X terminal.
+
+    Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
+    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301  USA.
+*/
+
+#ifndef SESSION_H
+#define SESSION_H
+
+// Qt
+#include <QtCore/QStringList>
+#include <QtCore>
+#include <QWidget>
+
+// Konsole
+#include "History.h"
+
+class KProcess;
+
+class Emulation;
+class PseudoTerminal;
+class SessionView;
+
+/**
+ * Represents a terminal session consisting of a pseudo-teletype and a terminal emulation.
+ * The pseudo-teletype (or PTY) handles I/O between the terminal process and Konsole.
+ * The terminal emulation ( Emulation and subclasses ) processes the output stream from the
+ * PTY and produces a character image which is then shown on views connected to the session.
+ *
+ * Each Session can be connected to one or more views by using the addView() method.
+ * The attached views can then display output from the program running in the terminal
+ * or send input to the program in the terminal in the form of keypresses and mouse
+ * activity.
+ */
+class SessionModel : public QObject {
+Q_OBJECT
+
+public:
+  Q_PROPERTY(QString name READ nameTitle)
+  Q_PROPERTY(int processId READ processId)
+  Q_PROPERTY(QString keyBindings READ keyBindings WRITE setKeyBindings)
+  Q_PROPERTY(QSize size READ size WRITE setSize)
+
+  /**
+   * Constructs a new session.
+   *
+   * To start the terminal process, call the run() method,
+   * after specifying the program and arguments
+   * using setProgram() and setArguments()
+   *
+   * If no program or arguments are specified explicitly, the Session
+   * falls back to using the program specified in the SHELL environment
+   * variable.
+   */
+  SessionModel(int masterFd = -1, int slaveFd = -1);
+  ~SessionModel();
+
+  /**
+   * Returns true if the session is currently running.  This will be true
+   * after run() has been called successfully.
+   */
+  bool isRunning() const;
+
+  /**
+   * Sets the profile associated with this session.
+   *
+   * @param profileKey A key which can be used to obtain the current
+   * profile settings from the SessionManager
+   */
+  void setProfileKey(const QString& profileKey);
+  /**
+   * Returns the profile key associated with this session.
+   * This can be passed to the SessionManager to obtain the current
+   * profile settings.
+   */
+  QString profileKey() const;
+
+  /**
+   * Adds a new view for this session.
+   *
+   * The viewing widget will display the output from the terminal and
+   * input from the viewing widget (key presses, mouse activity etc.)
+   * will be sent to the terminal.
+   *
+   * Views can be removed using removeView().  The session is automatically
+   * closed when the last view is removed.
+   */
+  void addView(SessionView* widget);
+  /**
+   * Removes a view from this session.  When the last view is removed,
+   * the session will be closed automatically.
+   *
+   * @p widget will no longer display output from or send input
+   * to the terminal
+   */
+  void removeView(SessionView* widget);
+
+  /**
+   * Returns the views connected to this session
+   */
+  QList<SessionView*> views() const;
+
+  /**
+   * Returns the terminal emulation instance being used to encode / decode
+   * characters to / from the process.
+   */
+  Emulation*  emulation() const;
+
+  /**
+   * Returns the environment of this session as a list of strings like
+   * VARIABLE=VALUE
+   */
+  QStringList environment() const;
+  /**
+   * Sets the environment for this session.
+   * @p environment should be a list of strings like
+   * VARIABLE=VALUE
+   */
+  void setEnvironment(const QStringList& environment);
+
+  /** Returns the unique ID for this session. */
+  int sessionId() const;
+
+  /**
+   * Return the session title set by the user (ie. the program running
+   * in the terminal), or an empty string if the user has not set a custom title
+   */
+  QString userTitle() const;
+
+  /**
+   * This enum describes the contexts for which separate
+   * tab title formats may be specified.
+   */
+  enum TabTitleContext
+  {
+    /** Default tab title format */
+    LocalTabTitle,
+    /**
+     * Tab title format used session currently contains
+     * a connection to a remote computer (via SSH)
+     */
+    RemoteTabTitle
+  };
+  /**
+   * Sets the format used by this session for tab titles.
+   *
+   * @param context The context whoose format should be set.
+   * @param format The tab title format.  This may be a mixture
+   * of plain text and dynamic elements denoted by a '%' character
+   * followed by a letter.  (eg. %d for directory).  The dynamic
+   * elements available depend on the @p context
+   */
+  void setTabTitleFormat(TabTitleContext context , const QString& format);
+  /** Returns the format used by this session for tab titles. */
+  QString tabTitleFormat(TabTitleContext context) const;
+
+
+  /** Returns the arguments passed to the shell process when run() is called. */
+  QStringList arguments() const;
+  /** Returns the program name of the shell process started when run() is called. */
+  QString program() const;
+
+  /**
+   * Sets the command line arguments which the session's program will be passed when
+   * run() is called.
+   */
+  void setArguments(const QStringList& arguments);
+  /** Sets the program to be executed when run() is called. */
+  void setProgram(const QString& program);
+
+  /** Returns the session's current working directory. */
+  QString initialWorkingDirectory() { return _initialWorkingDir; }
+
+  /**
+   * Sets the initial working directory for the session when it is run
+   * This has no effect once the session has been started.
+   */
+  void setInitialWorkingDirectory( const QString& dir );
+
+  /**
+   * Sets the type of history store used by this session.
+   * Lines of output produced by the terminal are added
+   * to the history store.  The type of history store
+   * used affects the number of lines which can be
+   * remembered before they are lost and the storage
+   * (in memory, on-disk etc.) used.
+   */
+  void setHistoryType(const HistoryType& type);
+  /**
+   * Returns the type of history store used by this session.
+   */
+  const HistoryType& historyType() const;
+  /**
+   * Clears the history store used by this session.
+   */
+  void clearHistory();
+
+  /**
+   * Enables monitoring for activity in the session.
+   * This will cause notifySessionState() to be emitted
+   * with the NOTIFYACTIVITY state flag when output is
+   * received from the terminal.
+   */
+  void setMonitorActivity(bool);
+  /** Returns true if monitoring for activity is enabled. */
+  bool isMonitorActivity() const;
+
+  /**
+   * Enables monitoring for silence in the session.
+   * This will cause notifySessionState() to be emitted
+   * with the NOTIFYSILENCE state flag when output is not
+   * received from the terminal for a certain period of
+   * time, specified with setMonitorSilenceSeconds()
+   */
+  void setMonitorSilence(bool);
+  /**
+   * Returns true if monitoring for inactivity (silence)
+   * in the session is enabled.
+   */
+  bool isMonitorSilence()  const;
+  /** See setMonitorSilence() */
+  void setMonitorSilenceSeconds(int seconds);
+
+  /**
+   * Sets the key bindings used by this session.  The bindings
+   * specify how input key sequences are translated into
+   * the character stream which is sent to the terminal.
+   *
+   * @param id The name of the key bindings to use.  The
+   * names of available key bindings can be determined using the
+   * KeyboardTranslatorManager class.
+   */
+  void setKeyBindings(const QString& id);
+  /** Returns the name of the key bindings used by this session. */
+  QString keyBindings() const;
+
+  /**
+   * This enum describes the available title roles.
+   */
+  enum TitleRole
+  {
+      /** The name of the session. */
+      NameRole,
+      /** The title of the session which is displayed in tabs etc. */
+      DisplayedTitleRole
+  };
+
+  /** Sets the session's title for the specified @p role to @p title. */
+  void setTitle(TitleRole role , const QString& title);
+  /** Returns the session's title for the specified @p role. */
+  QString title(TitleRole role) const;
+  /** Convenience method used to read the name property.  Returns title(Session::NameRole). */
+  QString nameTitle() const { return title(SessionModel::NameRole); }
+
+  /** Sets the name of the icon associated with this session. */
+  void setIconName(const QString& iconName);
+  /** Returns the name of the icon associated with this session. */
+  QString iconName() const;
+
+  /** Sets the text of the icon associated with this session. */
+  void setIconText(const QString& iconText);
+  /** Returns the text of the icon associated with this session. */
+  QString iconText() const;
+
+  /** Specifies whether a utmp entry should be created for the pty used by this session. */
+  void setAddToUtmp(bool);
+
+  /** Sends the specified @p signal to the terminal process. */
+  bool sendSignal(int signal);
+
+  /**
+   * Specifies whether to close the session automatically when the terminal
+   * process terminates.
+   */
+  void setAutoClose(bool b) { _autoClose = b; }
+
+  /**
+   * Sets whether flow control is enabled for this terminal
+   * session.
+   */
+  void setFlowControlEnabled(bool enabled);
+
+  /** Returns whether flow control is enabled for this terminal session. */
+  bool flowControlEnabled() const;
+
+  /**
+   * Sends @p text to the current foreground terminal program.
+   */
+  void sendText(const QString& text) const;
+
+  /**
+   * Returns the process id of the terminal process.
+   * This is the id used by the system API to refer to the process.
+   */
+  int processId() const;
+
+  /**
+   * Returns the process id of the terminal's foreground process.
+   * This is initially the same as processId() but can change
+   * as the user starts other programs inside the terminal.
+   */
+  int foregroundProcessId() const;
+
+  /** Returns the terminal session's window size in lines and columns. */
+  QSize size();
+  /**
+   * Emits a request to resize the session to accommodate
+   * the specified window size.
+   *
+   * @param size The size in lines and columns to request.
+   */
+  void setSize(const QSize& size);
+
+  /** Sets the text codec used by this session's terminal emulation. */
+  void setCodec(QTextCodec* codec);
+
+  /**
+   * Sets whether the session has a dark background or not.  The session
+   * uses this information to set the COLORFGBG variable in the process's
+   * environment, which allows the programs running in the terminal to determine
+   * whether the background is light or dark and use appropriate colors by default.
+   *
+   * This has no effect once the session is running.
+   */
+  void setDarkBackground(bool darkBackground);
+  /**
+   * Returns true if the session has a dark background.
+   * See setDarkBackground()
+   */
+  bool hasDarkBackground() const;
+
+  /**
+   * Attempts to get the shell program to redraw the current display area.
+   * This can be used after clearing the screen, for example, to get the
+   * shell to redraw the prompt line.
+   */
+  void refresh();
+
+//  void startZModem(const QString &rz, const QString &dir, const QStringList &list);
+//  void cancelZModem();
+//  bool isZModemBusy() { return _zmodemBusy; }
+
+public slots:
+
+  /**
+   * Starts the terminal session.
+   *
+   * This creates the terminal process and connects the teletype to it.
+   */
+  void run();
+
+  /**
+   * Closes the terminal session.  This sends a hangup signal
+   * (SIGHUP) to the terminal process and causes the done(Session*)
+   * signal to be emitted.
+   */
+  void close();
+
+  /**
+   * Changes the session title or other customizable aspects of the terminal
+   * emulation display. For a list of what may be changed see the
+   * Emulation::titleChanged() signal.
+   */
+  void setUserTitle( int, const QString &caption );
+
+signals:
+
+  /** Emitted when the terminal process starts. */
+  void started();
+
+  /**
+   * Emitted when the terminal process exits.
+   */
+  void finished();
+
+  /**
+   * Emitted when output is received from the terminal process.
+   */
+  void receivedData( const QString& text );
+
+  /** Emitted when the session's title has changed. */
+  void titleChanged();
+
+  /** Emitted when the session's profile has changed. */
+  void profileChanged(const QString& profile);
+
+  /**
+   * Emitted when the activity state of this session changes.
+   *
+   * @param state The new state of the session.  This may be one
+   * of NOTIFYNORMAL, NOTIFYSILENCE or NOTIFYACTIVITY
+   */
+  void stateChanged(int state);
+
+  /** Emitted when a bell event occurs in the session. */
+  void bellRequest( const QString& message );
+
+  /**
+   * Requests that the color the text for any tabs associated with
+   * this session should be changed;
+   *
+   * TODO: Document what the parameter does
+   */
+  void changeTabTextColorRequest(int);
+
+  /**
+   * Requests that the background color of views on this session
+   * should be changed.
+   */
+  void changeBackgroundColorRequest(const QColor&);
+
+  /** TODO: Document me. */
+  void openUrlRequest(const QString& url);
+
+  /** TODO: Document me. */
+//  void zmodemDetected();
+
+  /**
+   * Emitted when the terminal process requests a change
+   * in the size of the terminal window.
+   *
+   * @param size The requested window size in terms of lines and columns.
+   */
+  void resizeRequest(const QSize& size);
+
+  /**
+   * Emitted when a profile change command is received from the terminal.
+   *
+   * @param text The text of the command.  This is a string of the form
+   * "PropertyName=Value;PropertyName=Value ..."
+   */
+  void profileChangeCommandReceived(const QString& text);
+
+ /**
+  * Emitted when the flow control state changes.
+  *
+  * @param enabled True if flow control is enabled or false otherwise.
+  */
+  void flowControlEnabledChanged(bool enabled);
+
+private slots:
+  void done(int);
+
+//  void fireZModemDetected();
+
+  void onReceiveBlock( const char* buffer, int len );
+  void monitorTimerDone();
+
+  void onViewSizeChange(int height, int width);
+  void onEmulationSizeChange(int lines , int columns);
+
+  void activityStateSet(int);
+
+  //automatically detach views from sessions when view is destroyed
+  void viewDestroyed(QObject* view);
+
+//  void zmodemReadStatus();
+//  void zmodemReadAndSendBlock();
+//  void zmodemRcvBlock(const char *data, int len);
+//  void zmodemFinished();
+
+private:
+
+  void updateTerminalSize();
+  WId windowId() const;
+
+  int            _uniqueIdentifier;
+
+  PseudoTerminal*          _shellProcess;
+  Emulation*    _emulation;
+
+  QList<SessionView*> _views;
+
+  bool           _monitorActivity;
+  bool           _monitorSilence;
+  bool           _notifiedActivity;
+  bool           _masterMode;
+  bool           _autoClose;
+  bool           _wantedClose;
+  QTimer*        _monitorTimer;
+
+  int            _silenceSeconds;
+
+  QString        _nameTitle;
+  QString        _displayTitle;
+  QString        _userTitle;
+
+  QString        _localTabTitleFormat;
+  QString        _remoteTabTitleFormat;
+
+  QString        _iconName;
+  QString        _iconText; // as set by: echo -en '\033]1;IconText\007
+  bool           _addToUtmp;
+  bool           _flowControl;
+  bool           _fullScripting;
+
+  QString        _program;
+  QStringList    _arguments;
+
+  QStringList    _environment;
+  int            _sessionId;
+  int            _masterFd;
+  int            _slaveFd;
+  QString        _initialWorkingDir;
+
+  // ZModem
+//  bool           _zmodemBusy;
+//  KProcess*      _zmodemProc;
+//  ZModemDialog*  _zmodemProgress;
+
+  // Color/Font Changes by ESC Sequences
+
+  QColor         _modifiedBackground; // as set by: echo -en '\033]11;Color\007
+
+  QString        _profileKey;
+
+  bool _hasDarkBackground;
+
+  static int lastSessionId;
+
+};
+
+/**
+ * Provides a group of sessions which is divided into master and slave sessions.
+ * Activity in master sessions can be propagated to all sessions within the group.
+ * The type of activity which is propagated and method of propagation is controlled
+ * by the masterMode() flags.
+ */
+class SessionGroup : public QObject
+{
+Q_OBJECT
+
+public:
+    /** Constructs an empty session group. */
+    SessionGroup();
+    /** Destroys the session group and removes all connections between master and slave sessions. */
+    ~SessionGroup();
+
+    /** Adds a session to the group. */
+    void addSession( SessionModel* session );
+    /** Removes a session from the group. */
+    void removeSession( SessionModel* session );
+
+    /** Returns the list of sessions currently in the group. */
+    QList<SessionModel*> sessions() const;
+
+    /**
+     * Sets whether a particular session is a master within the group.
+     * Changes or activity in the group's master sessions may be propagated
+     * to all the sessions in the group, depending on the current masterMode()
+     *
+     * @param session The session whoose master status should be changed.
+     * @param master True to make this session a master or false otherwise
+     */
+    void setMasterStatus( SessionModel* session , bool master );
+    /** Returns the master status of a session.  See setMasterStatus() */
+    bool masterStatus( SessionModel* session ) const;
+
+    /**
+     * This enum describes the options for propagating certain activity or
+     * changes in the group's master sessions to all sessions in the group.
+     */
+    enum MasterMode
+    {
+        /**
+         * Any input key presses in the master sessions are sent to all
+         * sessions in the group.
+         */
+        CopyInputToAll = 1
+    };
+
+    /**
+     * Specifies which activity in the group's master sessions is propagated
+     * to all sessions in the group.
+     *
+     * @param mode A bitwise OR of MasterMode flags.
+     */
+    void setMasterMode( int mode );
+    /**
+     * Returns a bitwise OR of the active MasterMode flags for this group.
+     * See setMasterMode()
+     */
+    int masterMode() const;
+
+private:
+    void connectPair(SessionModel* master , SessionModel* other);
+    void disconnectPair(SessionModel* master , SessionModel* other);
+    void connectAll(bool connect);
+    QList<SessionModel*> masters() const;
+
+    // maps sessions to their master status
+    QHash<SessionModel*,bool> _sessions;
+
+    int _masterMode;
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/libqterminal/SessionView.cpp
@@ -0,0 +1,2743 @@
+/*
+    This file is part of Konsole, a terminal emulator for KDE.
+    
+    Copyright (C) 2006-7 by Robert Knight <robertknight@gmail.com>
+    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+    
+    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301  USA.
+*/
+
+// Own
+#include "SessionView.h"
+
+// Qt
+#include <QtGui/QApplication>
+#include <QtGui/QBoxLayout>
+#include <QtGui/QClipboard>
+#include <QtGui/QKeyEvent>
+#include <QtCore/QEvent>
+#include <QtCore/QTime>
+#include <QtCore/QFile>
+#include <QtGui/QGridLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QLayout>
+#include <QtGui/QPainter>
+#include <QtGui/QPixmap>
+#include <QtGui/QScrollBar>
+#include <QtGui/QStyle>
+#include <QtCore>
+#include <QtGui>
+
+#include "Filter.h"
+#include "konsole_wcwidth.h"
+#include "ScreenWindow.h"
+#include "TerminalCharacterDecoder.h"
+
+#ifndef loc
+#define loc(X,Y) ((Y)*_columns+(X))
+#endif
+
+#define yMouseScroll 1
+
+#define REPCHAR   "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+                  "abcdefgjijklmnopqrstuvwxyz" \
+                  "0123456789./+@"
+
+// scroll increment used when dragging selection at top/bottom of window.
+
+// static
+bool SessionView::_antialiasText = true;
+bool SessionView::HAVE_TRANSPARENCY = false;
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                                Colors                                     */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb)
+
+   Code        0       1       2       3       4       5       6       7
+   ----------- ------- ------- ------- ------- ------- ------- ------- -------
+   ANSI  (bgr) Black   Red     Green   Yellow  Blue    Magenta Cyan    White
+   IBMPC (rgb) Black   Blue    Green   Cyan    Red     Magenta Yellow  White
+*/
+
+ScreenWindow* SessionView::screenWindow() const
+{
+    return _screenWindow;
+}
+void SessionView::setScreenWindow(ScreenWindow* window)
+{
+    // disconnect existing screen window if any
+    if ( _screenWindow )
+    {
+        disconnect( _screenWindow , 0 , this , 0 );
+    }
+
+    _screenWindow = window;
+
+    if ( window )
+    {
+//#warning "The order here is not specified - does it matter whether updateImage or updateLineProperties comes first?"
+        connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties()) );
+        connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage()) );
+	window->setWindowLines(_lines);
+    }
+}
+
+const ColorEntry* SessionView::colorTable() const
+{
+  return _colorTable;
+}
+
+void SessionView::setColorTable(const ColorEntry table[])
+{
+  for (int i = 0; i < TABLE_COLORS; i++)
+      _colorTable[i] = table[i];
+
+  QPalette p = palette();
+  p.setColor( backgroundRole(), _colorTable[DEFAULT_BACK_COLOR].color );
+  setPalette( p );
+
+  // Avoid propagating the palette change to the scroll bar 
+  _scrollBar->setPalette( QApplication::palette() );  
+
+  update();
+}
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                                   Font                                    */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+/*
+   The VT100 has 32 special graphical characters. The usual vt100 extended
+   xterm fonts have these at 0x00..0x1f.
+
+   QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals
+   come in here as proper unicode characters.
+
+   We treat non-iso10646 fonts as VT100 extended and do the requiered mapping
+   from unicode to 0x00..0x1f. The remaining translation is then left to the
+   QCodec.
+*/
+
+static inline bool isLineChar(quint16 c) { return ((c & 0xFF80) == 0x2500);}
+static inline bool isLineCharString(const QString& string)
+{
+		return (string.length() > 0) && (isLineChar(string.at(0).unicode()));
+}
+						
+
+// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.
+
+unsigned short vt100_graphics[32] =
+{ // 0/8     1/9    2/10    3/11    4/12    5/13    6/14    7/15
+  0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0,
+  0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,
+  0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534,
+  0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7
+};
+
+void SessionView::fontChange(const QFont&)
+{
+  QFontMetrics fm(font());
+  _fontHeight = fm.height() + _lineSpacing;
+
+
+  // waba TerminalDisplay 1.123:
+  // "Base character width on widest ASCII character. This prevents too wide
+  //  characters in the presence of double wide (e.g. Japanese) characters."
+  // Get the width from representative normal width characters
+  _fontWidth = qRound((double)fm.width(REPCHAR)/(double)strlen(REPCHAR));
+
+  _fixedFont = true;
+
+  int fw = fm.width(REPCHAR[0]);
+  for(unsigned int i=1; i< strlen(REPCHAR); i++)
+  {
+    if (fw != fm.width(REPCHAR[i]))
+    {
+      _fixedFont = false;
+      break;
+    }
+  }
+
+  if (_fontWidth < 1)
+    _fontWidth=1;
+
+  _fontAscent = fm.ascent();
+
+  emit changedFontMetricSignal( _fontHeight, _fontWidth );
+  propagateSize();
+  update();
+}
+
+void SessionView::setVTFont(const QFont& f)
+{
+  QFont font = f;
+
+  QFontMetrics metrics(font);
+
+  if ( metrics.height() < height() && metrics.maxWidth() < width() )
+  {
+    // hint that text should be drawn without anti-aliasing.  
+    // depending on the user's font configuration, this may not be respected
+    if (!_antialiasText)
+        font.setStyleStrategy( QFont::NoAntialias );
+ 
+    // experimental optimization.  Konsole assumes that the terminal is using a 
+    // mono-spaced font, in which case kerning information should have an effect.
+    // Disabling kerning saves some computation when rendering text. 
+    font.setKerning(false);
+
+    QWidget::setFont(font);
+    fontChange(font);
+  }
+}
+
+void SessionView::setFont(const QFont &)
+{
+  // ignore font change request if not coming from konsole itself
+}
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                         Constructor / Destructor                          */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+SessionView::SessionView(QWidget *parent)
+:QWidget(parent)
+,_screenWindow(0)
+,_allowBell(true)
+,_gridLayout(0)
+,_fontHeight(1)
+,_fontWidth(1)
+,_fontAscent(1)
+,_lines(1)
+,_columns(1)
+,_usedLines(1)
+,_usedColumns(1)
+,_contentHeight(1)
+,_contentWidth(1)
+,_image(0)
+,_randomSeed(0)
+,_resizing(false)
+,_terminalSizeHint(false)
+,_terminalSizeStartup(true)
+,_bidiEnabled(false)
+,_actSel(0)
+,_wordSelectionMode(false)
+,_lineSelectionMode(false)
+,_preserveLineBreaks(false)
+,_columnSelectionMode(false)
+,_scrollbarLocation(NoScrollBar)
+,_wordCharacters(":@-./_~")
+,_bellMode(SystemBeepBell)
+,_blinking(false)
+,_cursorBlinking(false)
+,_hasBlinkingCursor(false)
+,_ctrlDrag(false)
+,_tripleClickMode(SelectWholeLine)
+,_isFixedSize(false)
+,_possibleTripleClick(false)
+,_resizeWidget(0)
+,_resizeTimer(0)
+,_flowControlWarningEnabled(false)
+,_outputSuspendedLabel(0)
+,_lineSpacing(0)
+,_colorsInverted(false)
+,_blendColor(qRgba(0,0,0,0xff))
+,_filterChain(new TerminalImageFilterChain())
+,_cursorShape(BlockCursor)
+,_readonly(false)
+{
+  // terminal applications are not designed with Right-To-Left in mind,
+  // so the layout is forced to Left-To-Right
+  setLayoutDirection(Qt::LeftToRight);
+
+  // The offsets are not yet calculated.
+  // Do not calculate these too often to be more smoothly when resizing
+  // konsole in opaque mode.
+  _topMargin = DEFAULT_TOP_MARGIN;
+  _leftMargin = DEFAULT_LEFT_MARGIN;
+
+  // create scroll bar for scrolling output up and down
+  // set the scroll bar's slider to occupy the whole area of the scroll bar initially
+  _scrollBar = new QScrollBar(this);
+  setScroll(0,0); 
+  _scrollBar->setCursor( Qt::ArrowCursor );
+  connect(_scrollBar, SIGNAL(valueChanged(int)), this, 
+  					  SLOT(scrollBarPositionChanged(int)));
+
+  // setup timers for blinking cursor and text
+  _blinkTimer   = new QTimer(this);
+  connect(_blinkTimer, SIGNAL(timeout()), this, SLOT(blinkEvent()));
+  _blinkCursorTimer   = new QTimer(this);
+  connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent()));
+
+//  QCursor::setAutoHideCursor( this, true );
+  
+  setUsesMouse(true);
+  setColorTable(base_color_table);
+  setMouseTracking(true);
+
+  // Enable drag and drop 
+  setAcceptDrops(true); // attempt
+  dragInfo.state = diNone;
+
+  setFocusPolicy( Qt::WheelFocus );
+
+  // enable input method support
+  setAttribute(Qt::WA_InputMethodEnabled, true);
+
+  // this is an important optimization, it tells Qt
+  // that TerminalDisplay will handle repainting its entire area.
+  setAttribute(Qt::WA_OpaquePaintEvent);
+
+  _gridLayout = new QGridLayout(this);
+  _gridLayout->setMargin(0);
+
+  setLayout( _gridLayout ); 
+
+  //set up a warning message when the user presses Ctrl+S to avoid confusion
+  connect( this,SIGNAL(flowControlKeyPressed(bool)),this,SLOT(outputSuspended(bool)) );
+}
+
+SessionView::~SessionView()
+{
+  qApp->removeEventFilter( this );
+  
+  delete[] _image;
+
+  delete _gridLayout;
+  delete _outputSuspendedLabel;
+  delete _filterChain;
+}
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                             Display Operations                            */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+/**
+ A table for emulating the simple (single width) unicode drawing chars.
+ It represents the 250x - 257x glyphs. If it's zero, we can't use it.
+ if it's not, it's encoded as follows: imagine a 5x5 grid where the points are numbered
+ 0 to 24 left to top, top to bottom. Each point is represented by the corresponding bit.
+
+ Then, the pixels basically have the following interpretation:
+ _|||_
+ -...-
+ -...-
+ -...-
+ _|||_
+
+where _ = none
+      | = vertical line.
+      - = horizontal line.
+ */
+
+
+enum LineEncode
+{
+    TopL  = (1<<1),
+    TopC  = (1<<2),
+    TopR  = (1<<3),
+
+    LeftT = (1<<5),
+    Int11 = (1<<6),
+    Int12 = (1<<7),
+    Int13 = (1<<8),
+    RightT = (1<<9),
+
+    LeftC = (1<<10),
+    Int21 = (1<<11),
+    Int22 = (1<<12),
+    Int23 = (1<<13),
+    RightC = (1<<14),
+
+    LeftB = (1<<15),
+    Int31 = (1<<16),
+    Int32 = (1<<17),
+    Int33 = (1<<18),
+    RightB = (1<<19),
+
+    BotL  = (1<<21),
+    BotC  = (1<<22),
+    BotR  = (1<<23)
+};
+
+#include "LineFont.h"
+
+static void drawLineChar(QPainter& paint, int x, int y, int w, int h, uchar code)
+{
+    //Calculate cell midpoints, end points.
+    int cx = x + w/2;
+    int cy = y + h/2;
+    int ex = x + w - 1;
+    int ey = y + h - 1;
+
+    quint32 toDraw = LineChars[code];
+
+    //Top _lines:
+    if (toDraw & TopL)
+        paint.drawLine(cx-1, y, cx-1, cy-2);
+    if (toDraw & TopC)
+        paint.drawLine(cx, y, cx, cy-2);
+    if (toDraw & TopR)
+        paint.drawLine(cx+1, y, cx+1, cy-2);
+
+    //Bot _lines:
+    if (toDraw & BotL)
+        paint.drawLine(cx-1, cy+2, cx-1, ey);
+    if (toDraw & BotC)
+        paint.drawLine(cx, cy+2, cx, ey);
+    if (toDraw & BotR)
+        paint.drawLine(cx+1, cy+2, cx+1, ey);
+
+    //Left _lines:
+    if (toDraw & LeftT)
+        paint.drawLine(x, cy-1, cx-2, cy-1);
+    if (toDraw & LeftC)
+        paint.drawLine(x, cy, cx-2, cy);
+    if (toDraw & LeftB)
+        paint.drawLine(x, cy+1, cx-2, cy+1);
+
+    //Right _lines:
+    if (toDraw & RightT)
+        paint.drawLine(cx+2, cy-1, ex, cy-1);
+    if (toDraw & RightC)
+        paint.drawLine(cx+2, cy, ex, cy);
+    if (toDraw & RightB)
+        paint.drawLine(cx+2, cy+1, ex, cy+1);
+
+    //Intersection points.
+    if (toDraw & Int11)
+        paint.drawPoint(cx-1, cy-1);
+    if (toDraw & Int12)
+        paint.drawPoint(cx, cy-1);
+    if (toDraw & Int13)
+        paint.drawPoint(cx+1, cy-1);
+
+    if (toDraw & Int21)
+        paint.drawPoint(cx-1, cy);
+    if (toDraw & Int22)
+        paint.drawPoint(cx, cy);
+    if (toDraw & Int23)
+        paint.drawPoint(cx+1, cy);
+
+    if (toDraw & Int31)
+        paint.drawPoint(cx-1, cy+1);
+    if (toDraw & Int32)
+        paint.drawPoint(cx, cy+1);
+    if (toDraw & Int33)
+        paint.drawPoint(cx+1, cy+1);
+
+}
+
+void SessionView::drawLineCharString(	QPainter& painter, int x, int y, const QString& str,
+									const Character* attributes)
+{
+		const QPen& currentPen = painter.pen();
+		
+		if ( attributes->rendition & RE_BOLD )
+		{
+			QPen boldPen(currentPen);
+			boldPen.setWidth(3);
+			painter.setPen( boldPen );
+		}	
+		
+		for (int i=0 ; i < str.length(); i++)
+		{
+			uchar code = str[i].cell();
+        	if (LineChars[code])
+            	drawLineChar(painter, x + (_fontWidth*i), y, _fontWidth, _fontHeight, code);
+		}
+
+		painter.setPen( currentPen );
+}
+
+void SessionView::setKeyboardCursorShape(KeyboardCursorShape shape)
+{
+    _cursorShape = shape;
+}
+SessionView::KeyboardCursorShape SessionView::keyboardCursorShape() const
+{
+    return _cursorShape;
+}
+void SessionView::setKeyboardCursorColor(bool useForegroundColor, const QColor& color)
+{
+    if (useForegroundColor)
+        _cursorColor = QColor(); // an invalid color means that
+                                 // the foreground color of the
+                                 // current character should
+                                 // be used
+
+    else
+        _cursorColor = color;
+}
+QColor SessionView::keyboardCursorColor() const
+{
+    return _cursorColor;
+}
+
+void SessionView::setOpacity(qreal opacity)
+{
+    QColor color(_blendColor);
+    color.setAlphaF(opacity);
+
+    // enable automatic background filling to prevent the display
+    // flickering if there is no transparency
+    if ( color.alpha() == 255 ) 
+    {
+        setAutoFillBackground(true);
+    }
+    else
+    {
+        setAutoFillBackground(false);
+    }
+
+    _blendColor = color.rgba();
+}
+
+void SessionView::drawBackground(QPainter& painter, const QRect& rect, const QColor& backgroundColor, bool useOpacitySetting )
+{
+        // the area of the widget showing the contents of the terminal display is drawn
+        // using the background color from the color scheme set with setColorTable()
+        //
+        // the area of the widget behind the scroll-bar is drawn using the background
+        // brush from the scroll-bar's palette, to give the effect of the scroll-bar
+        // being outside of the terminal display and visual consistency with other KDE
+        // applications.  
+        //
+        QRect scrollBarArea = _scrollBar->isVisible() ? 
+                                    rect.intersected(_scrollBar->geometry()) :
+                                    QRect();
+        QRegion contentsRegion = QRegion(rect).subtracted(scrollBarArea);
+        QRect contentsRect = contentsRegion.boundingRect();
+
+        if ( HAVE_TRANSPARENCY && qAlpha(_blendColor) < 0xff && useOpacitySetting ) 
+        {
+            QColor color(backgroundColor);
+            color.setAlpha(qAlpha(_blendColor));
+
+            painter.save();
+            painter.setCompositionMode(QPainter::CompositionMode_Source);
+            painter.fillRect(contentsRect, color);
+            painter.restore();
+        } 
+        else {
+	    painter.fillRect(contentsRect, backgroundColor);
+	}
+
+        painter.fillRect(scrollBarArea,_scrollBar->palette().background());
+}
+
+void SessionView::drawCursor(QPainter& painter,
+                                 const QRect& rect,
+                                 const QColor& foregroundColor,
+                                 const QColor& /*backgroundColor*/,
+                                 bool& invertCharacterColor)
+{
+    QRect cursorRect = rect;
+    cursorRect.setHeight(_fontHeight - _lineSpacing - 1);
+    
+    if (!_cursorBlinking)
+    {
+       if ( _cursorColor.isValid() )
+           painter.setPen(_cursorColor);
+       else {
+    	    painter.setPen(foregroundColor);
+	}
+
+       if ( _cursorShape == BlockCursor )
+       {
+            // draw the cursor outline, adjusting the area so that
+            // it is draw entirely inside 'rect'
+            int penWidth = qMax(1,painter.pen().width());
+
+            painter.drawRect(cursorRect.adjusted(penWidth/2,
+                                                 penWidth/2,
+                                                 - penWidth/2 - penWidth%2,
+                                                 - penWidth/2 - penWidth%2));
+            if ( hasFocus() )
+            {
+                painter.fillRect(cursorRect, _cursorColor.isValid() ? _cursorColor : foregroundColor);
+	    
+                if ( !_cursorColor.isValid() )
+                {
+                    // invert the colour used to draw the text to ensure that the character at
+                    // the cursor position is readable
+                    invertCharacterColor = true;
+                }
+            }
+       }
+       else if ( _cursorShape == UnderlineCursor )
+            painter.drawLine(cursorRect.left(),
+                             cursorRect.bottom(),
+                             cursorRect.right(),
+                             cursorRect.bottom());
+       else if ( _cursorShape == IBeamCursor )
+            painter.drawLine(cursorRect.left(),
+                             cursorRect.top(),
+                             cursorRect.left(),
+                             cursorRect.bottom());
+    
+    }
+}
+
+void SessionView::drawCharacters(QPainter& painter,
+                                     const QRect& rect,
+                                     const QString& text,
+                                     const Character* style,
+                                     bool invertCharacterColor)
+{
+    // don't draw text which is currently blinking
+    if ( _blinking && (style->rendition & RE_BLINK) )
+            return;
+   
+    // setup bold and underline
+    bool useBold = style->rendition & RE_BOLD || style->isBold(_colorTable) || font().bold();
+    bool useUnderline = style->rendition & RE_UNDERLINE || font().underline();
+
+    QFont font = painter.font();
+    if (    font.bold() != useBold 
+         || font.underline() != useUnderline )
+    {
+       font.setBold(useBold);
+       font.setUnderline(useUnderline);
+       painter.setFont(font);
+    }
+
+    const CharacterColor& textColor = ( invertCharacterColor ? style->backgroundColor : style->foregroundColor );
+    const QColor color = textColor.color(_colorTable);
+
+    QPen pen = painter.pen();
+    if ( pen.color() != color )
+    {
+        pen.setColor(color);
+        painter.setPen(color);
+    }
+    // draw text
+    if ( isLineCharString(text) ) {
+	  	drawLineCharString(painter,rect.x(),rect.y(),text,style);
+    }
+    else
+	{
+		// the drawText(rect,flags,string) overload is used here with null flags
+		// instead of drawText(rect,string) because the (rect,string) overload causes 
+		// the application's default layout direction to be used instead of 
+		// the widget-specific layout direction, which should always be
+		// Qt::LeftToRight for this widget
+        painter.drawText(rect,0,text);
+	}
+}
+
+void SessionView::drawTextFragment(QPainter& painter ,
+                                       const QRect& rect,
+                                       const QString& text, 
+                                       const Character* style)
+{
+    painter.save();
+
+    // setup painter 
+    const QColor foregroundColor = style->foregroundColor.color(_colorTable);
+    const QColor backgroundColor = style->backgroundColor.color(_colorTable);
+    
+    // draw background if different from the display's background color
+    if ( backgroundColor != palette().background().color() )
+        drawBackground(painter,rect,backgroundColor, false /* do not use transparency */);
+
+    // draw cursor shape if the current character is the cursor
+    // this may alter the foreground and background colors
+    bool invertCharacterColor = false;
+
+    if ( style->rendition & RE_CURSOR )
+        drawCursor(painter,rect,foregroundColor,backgroundColor,invertCharacterColor);
+    // draw text
+    drawCharacters(painter,rect,text,style,invertCharacterColor);
+
+    painter.restore();
+}
+
+void SessionView::setRandomSeed(uint randomSeed) { _randomSeed = randomSeed; }
+uint SessionView::randomSeed() const { return _randomSeed; }
+
+#if 0
+/*!
+    Set XIM Position
+*/
+void TerminalDisplay::setCursorPos(const int curx, const int cury)
+{
+    QPoint tL  = contentsRect().topLeft();
+    int    tLx = tL.x();
+    int    tLy = tL.y();
+
+    int xpos, ypos;
+    ypos = _topMargin + tLy + _fontHeight*(cury-1) + _fontAscent;
+    xpos = _leftMargin + tLx + _fontWidth*curx;
+    //setMicroFocusHint(xpos, ypos, 0, _fontHeight); //### ???
+    // fprintf(stderr, "x/y = %d/%d\txpos/ypos = %d/%d\n", curx, cury, xpos, ypos);
+    _cursorLine = cury;
+    _cursorCol = curx;
+}
+#endif
+
+// scrolls the image by 'lines', down if lines > 0 or up otherwise.
+//
+// the terminal emulation keeps track of the scrolling of the character 
+// image as it receives input, and when the view is updated, it calls scrollImage() 
+// with the final scroll amount.  this improves performance because scrolling the 
+// display is much cheaper than re-rendering all the text for the 
+// part of the image which has moved up or down.  
+// Instead only new lines have to be drawn
+//
+// note:  it is important that the area of the display which is 
+// scrolled aligns properly with the character grid - 
+// which has a top left point at (_leftMargin,_topMargin) , 
+// a cell width of _fontWidth and a cell height of _fontHeight).    
+void SessionView::scrollImage(int lines , const QRect& screenWindowRegion)
+{
+	// if the flow control warning is enabled this will interfere with the 
+	// scrolling optimisations and cause artifacts.  the simple solution here
+	// is to just disable the optimisation whilst it is visible
+	if ( _outputSuspendedLabel && _outputSuspendedLabel->isVisible() ) {
+		return;
+	}
+
+    // constrain the region to the display
+    // the bottom of the region is capped to the number of lines in the display's
+    // internal image - 2, so that the height of 'region' is strictly less
+    // than the height of the internal image.
+    QRect region = screenWindowRegion;
+    region.setBottom( qMin(region.bottom(),this->_lines-2) ); 
+
+    if (    lines == 0 
+         || _image == 0
+         || !region.isValid() 
+         || (region.top() + abs(lines)) >= region.bottom() 
+         || this->_lines <= region.height() ) return;
+
+    QRect scrollRect;
+
+    void* firstCharPos = &_image[ region.top() * this->_columns ];
+    void* lastCharPos = &_image[ (region.top() + abs(lines)) * this->_columns ];
+
+    int top = _topMargin + (region.top() * _fontHeight);
+    int linesToMove = region.height() - abs(lines);
+    int bytesToMove = linesToMove * 
+                      this->_columns *
+                      sizeof(Character);
+
+    Q_ASSERT( linesToMove > 0 );
+    Q_ASSERT( bytesToMove > 0 );
+
+    //scroll internal image
+    if ( lines > 0 )
+    {
+        // check that the memory areas that we are going to move are valid
+        Q_ASSERT( (char*)lastCharPos + bytesToMove < 
+                  (char*)(_image + (this->_lines * this->_columns)) );
+        
+        Q_ASSERT( (lines*this->_columns) < _imageSize ); 
+
+        //scroll internal image down
+        memmove( firstCharPos , lastCharPos , bytesToMove ); 
+      
+        //set region of display to scroll, making sure that
+        //the region aligns correctly to the character grid 
+        scrollRect = QRect( _leftMargin , top, 
+                            this->_usedColumns * _fontWidth , 
+                            linesToMove * _fontHeight );
+    }
+    else
+    {
+        // check that the memory areas that we are going to move are valid
+        Q_ASSERT( (char*)firstCharPos + bytesToMove < 
+                  (char*)(_image + (this->_lines * this->_columns)) );
+
+        //scroll internal image up
+        memmove( lastCharPos , firstCharPos , bytesToMove ); 
+     
+        //set region of the display to scroll, making sure that
+        //the region aligns correctly to the character grid
+        QPoint topPoint( _leftMargin , top + abs(lines)*_fontHeight );
+
+        scrollRect = QRect( topPoint ,
+                     QSize( this->_usedColumns*_fontWidth , 
+                            linesToMove * _fontHeight ));
+    }
+
+    //scroll the display vertically to match internal _image
+    scroll( 0 , _fontHeight * (-lines) , scrollRect );
+}
+
+QRegion SessionView::hotSpotRegion() const
+{
+	QRegion region;
+	foreach( Filter::HotSpot* hotSpot , _filterChain->hotSpots() )
+	{
+		QRect rect;
+		rect.setLeft(hotSpot->startColumn());
+		rect.setTop(hotSpot->startLine());
+		rect.setRight(hotSpot->endColumn());
+		rect.setBottom(hotSpot->endLine());
+
+		region |= imageToWidget(rect); 
+	}
+	return region;
+}
+
+void SessionView::processFilters()
+{
+	if (!_screenWindow)
+		return;
+
+	QRegion preUpdateHotSpots = hotSpotRegion();
+
+	// use _screenWindow->getImage() here rather than _image because
+	// other classes may call processFilters() when this display's
+	// ScreenWindow emits a scrolled() signal - which will happen before
+	// updateImage() is called on the display and therefore _image is 
+	// out of date at this point
+	_filterChain->setImage( _screenWindow->getImage(),
+							_screenWindow->windowLines(),
+							_screenWindow->windowColumns(),
+							_screenWindow->getLineProperties() );
+    _filterChain->process();
+
+	QRegion postUpdateHotSpots = hotSpotRegion();
+
+	update( preUpdateHotSpots | postUpdateHotSpots );
+}
+
+void SessionView::updateImage()
+{
+  if ( !_screenWindow )
+      return;
+
+  // optimization - scroll the existing image where possible and 
+  // avoid expensive text drawing for parts of the image that 
+  // can simply be moved up or down
+  scrollImage( _screenWindow->scrollCount() ,
+               _screenWindow->scrollRegion() );
+  _screenWindow->resetScrollCount();
+
+  Character* const newimg = _screenWindow->getImage();
+  int lines = _screenWindow->windowLines();
+  int columns = _screenWindow->windowColumns();
+
+  setScroll( _screenWindow->currentLine() , _screenWindow->lineCount() );
+
+  if (!_image)
+     updateImageSize(); // Create _image
+
+  Q_ASSERT( this->_usedLines <= this->_lines );
+  Q_ASSERT( this->_usedColumns <= this->_columns );
+
+  int y,x,len;
+
+  QPoint tL  = contentsRect().topLeft();
+
+  int    tLx = tL.x();
+  int    tLy = tL.y();
+  _hasBlinker = false;
+
+  CharacterColor cf;       // undefined
+  CharacterColor _clipboard;       // undefined
+  int cr  = -1;   // undefined
+
+  const int linesToUpdate = qMin(this->_lines, qMax(0,lines  ));
+  const int columnsToUpdate = qMin(this->_columns,qMax(0,columns));
+
+  QChar *disstrU = new QChar[columnsToUpdate];
+  char *dirtyMask = new char[columnsToUpdate+2]; 
+  QRegion dirtyRegion;
+
+  // debugging variable, this records the number of lines that are found to
+  // be 'dirty' ( ie. have changed from the old _image to the new _image ) and
+  // which therefore need to be repainted
+  int dirtyLineCount = 0;
+
+  for (y = 0; y < linesToUpdate; y++)
+  {
+    const Character*       currentLine = &_image[y*this->_columns];
+    const Character* const newLine = &newimg[y*columns];
+
+    bool updateLine = false;
+    
+    // The dirty mask indicates which characters need repainting. We also
+    // mark surrounding neighbours dirty, in case the character exceeds
+    // its cell boundaries
+    memset(dirtyMask, 0, columnsToUpdate+2);
+   
+    for( x = 0 ; x < columnsToUpdate ; x++)
+    {
+        if ( newLine[x] != currentLine[x] ) 
+        {
+            dirtyMask[x] = true;
+        }
+    }
+
+    if (!_resizing) // not while _resizing, we're expecting a paintEvent
+    for (x = 0; x < columnsToUpdate; x++)
+    {
+      _hasBlinker |= (newLine[x].rendition & RE_BLINK);
+    
+      // Start drawing if this character or the next one differs.
+      // We also take the next one into account to handle the situation
+      // where characters exceed their cell width.
+      if (dirtyMask[x])
+      {
+        quint16 c = newLine[x+0].character;
+        if ( !c )
+            continue;
+        int p = 0;
+        disstrU[p++] = c; //fontMap(c);
+        bool lineDraw = isLineChar(c);
+        bool doubleWidth = (x+1 == columnsToUpdate) ? false : (newLine[x+1].character == 0);
+        cr = newLine[x].rendition;
+        _clipboard = newLine[x].backgroundColor;
+        if (newLine[x].foregroundColor != cf) cf = newLine[x].foregroundColor;
+        int lln = columnsToUpdate - x;
+        for (len = 1; len < lln; len++)
+        {
+            const Character& ch = newLine[x+len];
+
+            if (!ch.character)
+                continue; // Skip trailing part of multi-col chars.
+
+			bool nextIsDoubleWidth = (x+len+1 == columnsToUpdate) ? false : (newLine[x+len+1].character == 0);
+
+            if (  ch.foregroundColor != cf || 
+                  ch.backgroundColor != _clipboard || 
+                  ch.rendition != cr ||
+                  !dirtyMask[x+len] || 
+                  isLineChar(c) != lineDraw || 
+                  nextIsDoubleWidth != doubleWidth )
+            break;
+
+          disstrU[p++] = c; //fontMap(c);
+        }
+
+        QString unistr(disstrU, p);
+
+        bool saveFixedFont = _fixedFont;
+        if (lineDraw)
+           _fixedFont = false;
+        if (doubleWidth)
+           _fixedFont = false;
+
+		updateLine = true;
+
+		_fixedFont = saveFixedFont;
+        x += len - 1;
+      }
+      
+    }
+
+	//both the top and bottom halves of double height _lines must always be redrawn
+	//although both top and bottom halves contain the same characters, only 
+    //the top one is actually 
+	//drawn.
+    if (_lineProperties.count() > y)
+        updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT);
+
+    // if the characters on the line are different in the old and the new _image
+    // then this line must be repainted.    
+    if (updateLine)
+    {
+        dirtyLineCount++;
+
+        // add the area occupied by this line to the region which needs to be
+        // repainted
+        QRect dirtyRect = QRect( _leftMargin+tLx , 
+                                 _topMargin+tLy+_fontHeight*y , 
+                                 _fontWidth * columnsToUpdate , 
+                                 _fontHeight ); 	
+
+        dirtyRegion |= dirtyRect;
+    }
+
+    // replace the line of characters in the old _image with the 
+    // current line of the new _image 
+    memcpy((void*)currentLine,(const void*)newLine,columnsToUpdate*sizeof(Character));
+  }
+
+  // if the new _image is smaller than the previous _image, then ensure that the area
+  // outside the new _image is cleared 
+  if ( linesToUpdate < _usedLines )
+  {
+    dirtyRegion |= QRect(   _leftMargin+tLx , 
+                            _topMargin+tLy+_fontHeight*linesToUpdate , 
+                            _fontWidth * this->_columns , 
+                            _fontHeight * (_usedLines-linesToUpdate) );
+  }
+  _usedLines = linesToUpdate;
+  
+  if ( columnsToUpdate < _usedColumns )
+  {
+    dirtyRegion |= QRect(   _leftMargin+tLx+columnsToUpdate*_fontWidth , 
+                            _topMargin+tLy , 
+                            _fontWidth * (_usedColumns-columnsToUpdate) , 
+                            _fontHeight * this->_lines );
+  }
+  _usedColumns = columnsToUpdate;
+
+  dirtyRegion |= _inputMethodData.previousPreeditRect;
+
+  // update the parts of the display which have changed
+  update(dirtyRegion);
+
+  if ( _hasBlinker && !_blinkTimer->isActive()) _blinkTimer->start( BLINK_DELAY ); 
+  if (!_hasBlinker && _blinkTimer->isActive()) { _blinkTimer->stop(); _blinking = false; }
+  delete[] dirtyMask;
+  delete[] disstrU;
+
+}
+
+void SessionView::showResizeNotification()
+{
+  if (_terminalSizeHint && isVisible())
+  {
+     if (_terminalSizeStartup) {
+       		_terminalSizeStartup=false;
+       return;
+     }
+     if (!_resizeWidget)
+     {
+        _resizeWidget = new QLabel(("Size: XXX x XXX"), this);
+        _resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width(("Size: XXX x XXX")));
+        _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height());
+		_resizeWidget->setAlignment(Qt::AlignCenter);
+
+        _resizeWidget->setStyleSheet("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)");
+
+		_resizeTimer = new QTimer(this);
+		_resizeTimer->setSingleShot(true);
+        connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide()));
+
+     }
+     QString sizeStr;
+     sizeStr.sprintf("Size: %d x %d", _columns, _lines);
+     _resizeWidget->setText(sizeStr);
+     _resizeWidget->move((width()-_resizeWidget->width())/2,
+                         (height()-_resizeWidget->height())/2+20);
+     _resizeWidget->show();
+     _resizeTimer->start(1000);
+  }
+}
+
+void SessionView::setBlinkingCursor(bool blink)
+{
+  _hasBlinkingCursor=blink;
+  
+  if (blink && !_blinkCursorTimer->isActive()) 
+      _blinkCursorTimer->start(BLINK_DELAY);
+  
+  if (!blink && _blinkCursorTimer->isActive()) 
+  {
+    _blinkCursorTimer->stop();
+    if (_cursorBlinking)
+      blinkCursorEvent();
+    else
+      _cursorBlinking = false;
+  }
+}
+
+void SessionView::paintEvent( QPaintEvent* pe )
+{
+//qDebug("%s %d paintEvent", __FILE__, __LINE__);
+  QPainter paint(this);
+//qDebug("%s %d paintEvent %d %d", __FILE__, __LINE__, paint.window().top(), paint.window().right());
+
+  foreach (QRect rect, (pe->region() & contentsRect()).rects())
+  {
+    drawBackground(paint,rect,palette().background().color(),	true /* use opacity setting */);
+    drawContents(paint, rect);    
+  }
+//    drawBackground(paint,contentsRect(),palette().background().color(),	true /* use opacity setting */);
+//    drawContents(paint, contentsRect());    
+  drawInputMethodPreeditString(paint,preeditRect());
+  paintFilters(paint);
+
+  paint.end();
+}
+
+QPoint SessionView::cursorPosition() const
+{
+	if (_screenWindow)
+		return _screenWindow->cursorPosition();
+	else
+		return QPoint(0,0);
+}
+
+QRect SessionView::preeditRect() const
+{
+    const int preeditLength = string_width(_inputMethodData.preeditString);
+
+    if ( preeditLength == 0 )
+        return QRect();
+
+    return QRect(_leftMargin + _fontWidth*cursorPosition().x(),
+                 _topMargin + _fontHeight*cursorPosition().y(),
+                 _fontWidth*preeditLength,
+                 _fontHeight);
+}   
+
+void SessionView::drawInputMethodPreeditString(QPainter& painter , const QRect& rect)
+{
+    if ( _inputMethodData.preeditString.isEmpty() ) {
+        return;
+    }
+    const QPoint cursorPos = cursorPosition(); 
+
+    bool invertColors = false;
+    const QColor background = _colorTable[DEFAULT_BACK_COLOR].color;
+    const QColor foreground = _colorTable[DEFAULT_FORE_COLOR].color;
+    const Character* style = &_image[loc(cursorPos.x(),cursorPos.y())];
+
+    drawBackground(painter,rect,background,true);
+    drawCursor(painter,rect,foreground,background,invertColors);
+    drawCharacters(painter,rect,_inputMethodData.preeditString,style,invertColors);
+
+    _inputMethodData.previousPreeditRect = rect; 
+}
+
+FilterChain* SessionView::filterChain() const
+{
+    return _filterChain;
+}
+
+void SessionView::paintFilters(QPainter& painter)
+{
+//qDebug("%s %d paintFilters", __FILE__, __LINE__);
+
+    // get color of character under mouse and use it to draw
+    // lines for filters
+    QPoint cursorPos = mapFromGlobal(QCursor::pos());
+    int cursorLine;
+    int cursorColumn;
+    getCharacterPosition( cursorPos , cursorLine , cursorColumn );
+    Character cursorCharacter = _image[loc(cursorColumn,cursorLine)];
+
+    painter.setPen( QPen(cursorCharacter.foregroundColor.color(colorTable())) );
+
+    // iterate over hotspots identified by the display's currently active filters 
+    // and draw appropriate visuals to indicate the presence of the hotspot
+
+    QList<Filter::HotSpot*> spots = _filterChain->hotSpots();
+    QListIterator<Filter::HotSpot*> iter(spots);
+    while (iter.hasNext())
+    {
+        Filter::HotSpot* spot = iter.next();
+
+        for ( int line = spot->startLine() ; line <= spot->endLine() ; line++ )
+        {
+            int startColumn = 0;
+            int endColumn = _columns-1; // TODO use number of _columns which are actually 
+                                        // occupied on this line rather than the width of the 
+                                        // display in _columns
+
+            // ignore whitespace at the end of the lines
+            while ( QChar(_image[loc(endColumn,line)].character).isSpace() && endColumn > 0 )
+                endColumn--;
+              
+            // increment here because the column which we want to set 'endColumn' to
+            // is the first whitespace character at the end of the line
+            endColumn++;
+
+            if ( line == spot->startLine() )
+                startColumn = spot->startColumn();
+            if ( line == spot->endLine() )
+                endColumn = spot->endColumn();
+
+            // subtract one pixel from
+            // the right and bottom so that
+            // we do not overdraw adjacent
+            // hotspots
+            //
+            // subtracting one pixel from all sides also prevents an edge case where
+            // moving the mouse outside a link could still leave it underlined 
+            // because the check below for the position of the cursor
+            // finds it on the border of the target area
+            QRect r;
+            r.setCoords( startColumn*_fontWidth + 1, line*_fontHeight + 1,
+                             endColumn*_fontWidth - 1, (line+1)*_fontHeight - 1 ); 
+                                                                           
+            // Underline link hotspots 
+            if ( spot->type() == Filter::HotSpot::Link )
+            {
+                QFontMetrics metrics(font());
+        
+                // find the baseline (which is the invisible line that the characters in the font sit on,
+                // with some having tails dangling below)
+                int baseline = r.bottom() - metrics.descent();
+                // find the position of the underline below that
+                int underlinePos = baseline + metrics.underlinePos();
+
+                if ( r.contains( mapFromGlobal(QCursor::pos()) ) )
+                    painter.drawLine( r.left() , underlinePos , 
+                                      r.right() , underlinePos );
+            }
+            // Marker hotspots simply have a transparent rectanglular shape
+            // drawn on top of them
+            else if ( spot->type() == Filter::HotSpot::Marker )
+            {
+            //TODO - Do not use a hardcoded colour for this
+                painter.fillRect(r,QBrush(QColor(255,0,0,120)));
+            }
+        }
+    }
+}
+void SessionView::drawContents(QPainter &paint, const QRect &rect)
+{
+//qDebug("%s %d drawContents and rect x=%d y=%d w=%d h=%d", __FILE__, __LINE__, rect.x(), rect.y(),rect.width(),rect.height());
+
+  QPoint tL  = contentsRect().topLeft();
+//  int    tLx = tL.x();
+  int    tLy = tL.y();
+
+  int tLx = (_contentWidth - _usedColumns * _fontWidth)/2;
+//  int tLy = (_contentHeight - _usedLines * _fontHeight)/2; 
+//qDebug("%d %d %d %d", tLx, tLy, _contentWidth, _usedColumns * _fontWidth);  
+
+  int lux = qMin(_usedColumns-1, qMax(0,(rect.left()   - tLx - _leftMargin ) / _fontWidth));
+  int luy = qMin(_usedLines-1,  qMax(0, (rect.top()    - tLy - _topMargin  ) / _fontHeight));
+  int rlx = qMin(_usedColumns-1, qMax(0, (rect.right()  - tLx - _leftMargin ) / _fontWidth));
+  int rly = qMin(_usedLines-1,  qMax(0, (rect.bottom() - tLy - _topMargin  ) / _fontHeight));
+
+  const int bufferSize = _usedColumns;
+  QChar *disstrU = new QChar[bufferSize];
+  for (int y = luy; y <= rly; y++)
+  {
+    quint16 c = _image[loc(lux,y)].character;
+    int x = lux;
+    if(!c && x)
+      x--; // Search for start of multi-column character
+    for (; x <= rlx; x++)
+    {
+      int len = 1;
+      int p = 0;
+
+      // is this a single character or a sequence of characters ?
+      if ( _image[loc(x,y)].rendition & RE_EXTENDED_CHAR )
+      {
+        // sequence of characters
+        ushort extendedCharLength = 0;
+        ushort* chars = ExtendedCharTable::instance
+                            .lookupExtendedChar(_image[loc(x,y)].charSequence,extendedCharLength);
+        for ( int index = 0 ; index < extendedCharLength ; index++ ) 
+        {
+            Q_ASSERT( p < bufferSize );
+            disstrU[p++] = chars[index];
+        }
+      }
+      else
+      {
+        // single character
+        c = _image[loc(x,y)].character;
+        if (c)
+        {
+             Q_ASSERT( p < bufferSize );
+             disstrU[p++] = c; //fontMap(c);
+        }
+      }
+
+      bool lineDraw = isLineChar(c);
+      bool doubleWidth = (_image[ qMin(loc(x,y)+1,_imageSize) ].character == 0);
+      CharacterColor currentForeground = _image[loc(x,y)].foregroundColor;
+      CharacterColor currentBackground = _image[loc(x,y)].backgroundColor;
+      quint8 currentRendition = _image[loc(x,y)].rendition;
+	  
+      while (x+len <= rlx &&
+             _image[loc(x+len,y)].foregroundColor == currentForeground &&
+             _image[loc(x+len,y)].backgroundColor == currentBackground &&
+             _image[loc(x+len,y)].rendition == currentRendition &&
+             (_image[ qMin(loc(x+len,y)+1,_imageSize) ].character == 0) == doubleWidth &&
+             isLineChar( c = _image[loc(x+len,y)].character) == lineDraw) // Assignment!
+      {
+        if (c)
+          disstrU[p++] = c; //fontMap(c);
+        if (doubleWidth) // assert((_image[loc(x+len,y)+1].character == 0)), see above if condition
+          len++; // Skip trailing part of multi-column character
+        len++;
+      }
+      if ((x+len < _usedColumns) && (!_image[loc(x+len,y)].character))
+        len++; // Adjust for trailing part of multi-column character
+
+   	     bool save__fixedFont = _fixedFont;
+         if (lineDraw)
+            _fixedFont = false;
+         if (doubleWidth)
+            _fixedFont = false;
+         QString unistr(disstrU,p);
+		 
+		 if (y < _lineProperties.size())
+		 {
+			if (_lineProperties[y] & LINE_DOUBLEWIDTH) {
+				paint.scale(2,1);
+			}
+			
+			if (_lineProperties[y] & LINE_DOUBLEHEIGHT) {
+  		 		paint.scale(1,2);
+			}
+		 }
+
+		 //calculate the area in which the text will be drawn
+		 QRect textArea = QRect( _leftMargin+tLx+_fontWidth*x , 
+					_topMargin+tLy+_fontHeight*y , 
+					_fontWidth*len, 
+					_fontHeight);
+		
+		 //move the calculated area to take account of scaling applied to the painter.
+		 //the position of the area from the origin (0,0) is scaled 
+         //by the opposite of whatever
+		 //transformation has been applied to the painter.  this ensures that 
+		 //painting does actually start from textArea.topLeft() 
+         //(instead of textArea.topLeft() * painter-scale)	
+		 QMatrix inverted = paint.matrix().inverted();
+//		 textArea.moveTopLeft( inverted.map(textArea.topLeft()) );
+		 textArea.moveCenter( inverted.map(textArea.center()) );
+
+		 
+		 //paint text fragment
+         drawTextFragment(	paint,
+                		    textArea,
+                		    unistr, 
+					    	&_image[loc(x,y)] ); //, 
+						    //0, 
+						    //!_isPrinting );
+         
+		 _fixedFont = save__fixedFont;
+     
+		 //reset back to single-width, single-height _lines 
+		 paint.resetMatrix();
+
+		 if (y < _lineProperties.size()-1)
+		 {
+			//double-height _lines are represented by two adjacent _lines 
+            //containing the same characters
+			//both _lines will have the LINE_DOUBLEHEIGHT attribute.  
+            //If the current line has the LINE_DOUBLEHEIGHT attribute, 
+            //we can therefore skip the next line
+			if (_lineProperties[y] & LINE_DOUBLEHEIGHT)
+				y++;
+		 }
+		 
+	    x += len - 1;
+    }
+  }
+  delete [] disstrU;
+}
+
+void SessionView::blinkEvent()
+{
+  _blinking = !_blinking;
+
+  //TODO:  Optimise to only repaint the areas of the widget 
+  // where there is blinking text
+  // rather than repainting the whole widget.
+  update();
+}
+
+QRect SessionView::imageToWidget(const QRect& imageArea) const
+{
+//qDebug("%s %d imageToWidget", __FILE__, __LINE__);
+    QRect result;
+    result.setLeft( _leftMargin + _fontWidth * imageArea.left() );
+    result.setTop( _topMargin + _fontHeight * imageArea.top() );
+    result.setWidth( _fontWidth * imageArea.width() );
+    result.setHeight( _fontHeight * imageArea.height() );
+
+    return result;
+}
+
+void SessionView::blinkCursorEvent()
+{
+  _cursorBlinking = !_cursorBlinking;
+
+  QRect cursorRect = imageToWidget( QRect(cursorPosition(),QSize(1,1)) ); 
+
+  update(cursorRect);
+}
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                                  Resizing                                 */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+void SessionView::resizeEvent(QResizeEvent*)
+{
+  updateImageSize();
+}
+
+void SessionView::propagateSize()
+{
+  if (_isFixedSize)
+  {
+     setSize(_columns, _lines);
+     QWidget::setFixedSize(sizeHint());
+     parentWidget()->adjustSize();
+     parentWidget()->setFixedSize(parentWidget()->sizeHint());
+     return;
+  }
+  if (_image)
+     updateImageSize();
+}
+
+void SessionView::updateImageSize()
+{
+//qDebug("%s %d updateImageSize", __FILE__, __LINE__);
+  Character* oldimg = _image;
+  int oldlin = _lines;
+  int oldcol = _columns;
+
+  makeImage();
+
+  
+  // copy the old image to reduce flicker
+  int lines = qMin(oldlin,_lines);
+  int columns = qMin(oldcol,_columns);
+
+//qDebug("%s %d updateImageSize", __FILE__, __LINE__);
+  if (oldimg)
+  {
+    for (int line = 0; line < lines; line++) 
+    {
+      memcpy((void*)&_image[_columns*line],
+             (void*)&oldimg[oldcol*line],columns*sizeof(Character));
+    }
+    delete[] oldimg;
+  }
+
+//qDebug("%s %d updateImageSize", __FILE__, __LINE__);
+  if (_screenWindow)
+  	_screenWindow->setWindowLines(_lines);
+
+  _resizing = (oldlin!=_lines) || (oldcol!=_columns);
+
+  if ( _resizing )
+  {
+//qDebug("%s %d updateImageSize", __FILE__, __LINE__);
+  	showResizeNotification();
+    emit changedContentSizeSignal(_contentHeight, _contentWidth); // expose resizeEvent
+  }
+//qDebug("%s %d updateImageSize", __FILE__, __LINE__);
+  
+  _resizing = false;
+}
+
+//showEvent and hideEvent are reimplemented here so that it appears to other classes that the 
+//display has been resized when the display is hidden or shown.
+//
+//this allows  
+//TODO: Perhaps it would be better to have separate signals for show and hide instead of using
+//the same signal as the one for a content size change 
+void SessionView::showEvent(QShowEvent*)
+{
+    emit changedContentSizeSignal(_contentHeight,_contentWidth);
+}
+void SessionView::hideEvent(QHideEvent*)
+{
+    emit changedContentSizeSignal(_contentHeight,_contentWidth);
+}
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                                Scrollbar                                  */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+void SessionView::scrollBarPositionChanged(int)
+{
+  if ( !_screenWindow ) 
+      return;
+
+  _screenWindow->scrollTo( _scrollBar->value() );
+
+  // if the thumb has been moved to the bottom of the _scrollBar then set
+  // the display to automatically track new output, 
+  // that is, scroll down automatically
+  // to how new _lines as they are added
+  const bool atEndOfOutput = (_scrollBar->value() == _scrollBar->maximum());
+  _screenWindow->setTrackOutput( atEndOfOutput );
+
+  updateImage();
+}
+
+void SessionView::setScroll(int cursor, int slines)
+{
+//qDebug("%s %d setScroll", __FILE__, __LINE__);
+  // update _scrollBar if the range or value has changed,
+  // otherwise return
+  //
+  // setting the range or value of a _scrollBar will always trigger
+  // a repaint, so it should be avoided if it is not necessary
+  if ( _scrollBar->minimum() == 0                 &&
+       _scrollBar->maximum() == (slines - _lines) &&
+       _scrollBar->value()   == cursor )
+  {
+        return;
+  }
+
+  disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int)));
+  _scrollBar->setRange(0,slines - _lines);
+  _scrollBar->setSingleStep(1);
+  _scrollBar->setPageStep(_lines);
+  _scrollBar->setValue(cursor);
+  connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int)));
+}
+
+void SessionView::setScrollBarPosition(ScrollBarPosition position)
+{
+  if (_scrollbarLocation == position) {
+//      return; 
+  }
+ 
+  if ( position == NoScrollBar )
+     _scrollBar->hide();
+  else 
+     _scrollBar->show(); 
+
+  _topMargin = _leftMargin = 1;
+  _scrollbarLocation = position;
+  
+  propagateSize();
+  update();
+}
+
+void SessionView::mousePressEvent(QMouseEvent* ev)
+{
+  if ( _possibleTripleClick && (ev->button()==Qt::LeftButton) ) {
+    mouseTripleClickEvent(ev);
+    return;
+  }
+
+  if ( !contentsRect().contains(ev->pos()) ) return;
+  
+  if ( !_screenWindow ) return;
+
+  int charLine;
+  int charColumn;
+  getCharacterPosition(ev->pos(),charLine,charColumn);
+  QPoint pos = QPoint(charColumn,charLine);
+
+  if ( ev->button() == Qt::LeftButton)
+  {
+    _lineSelectionMode = false;
+    _wordSelectionMode = false;
+
+    emit isBusySelecting(true); // Keep it steady...
+    // Drag only when the Control key is hold
+    bool selected = false;
+    
+    // The receiver of the testIsSelected() signal will adjust
+    // 'selected' accordingly.
+    //emit testIsSelected(pos.x(), pos.y(), selected);
+    
+    selected =  _screenWindow->isSelected(pos.x(),pos.y());
+
+    if ((!_ctrlDrag || ev->modifiers() & Qt::ControlModifier) && selected ) {
+      // The user clicked inside selected text
+      dragInfo.state = diPending;
+      dragInfo.start = ev->pos();
+    }
+    else {
+      // No reason to ever start a drag event
+      dragInfo.state = diNone;
+
+      _preserveLineBreaks = !( ( ev->modifiers() & Qt::ControlModifier ) && !(ev->modifiers() & Qt::AltModifier) );
+      _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier);
+
+      if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier))
+      {
+         _screenWindow->clearSelection();
+
+        //emit clearSelectionSignal();
+        pos.ry() += _scrollBar->value();
+        _iPntSel = _pntSel = pos;
+        _actSel = 1; // left mouse button pressed but nothing selected yet.
+        
+      }
+      else
+      {
+        emit mouseSignal( 0, charColumn + 1, charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0);
+      }
+    }
+  }
+  else if ( ev->button() == Qt::MidButton )
+  {
+    if ( _mouseMarks || (!_mouseMarks && (ev->modifiers() & Qt::ShiftModifier)) )
+      emitSelection(true,ev->modifiers() & Qt::ControlModifier);
+    else
+      emit mouseSignal( 1, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0);
+  }
+  else if ( ev->button() == Qt::RightButton )
+  {
+    if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) 
+    {
+        emit configureRequest( this, 
+                               ev->modifiers() & (Qt::ShiftModifier|Qt::ControlModifier), 
+                               ev->pos()
+                             );
+    }
+    else
+      emit mouseSignal( 2, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0);
+  }
+}
+
+QList<QAction*> SessionView::filterActions(const QPoint& position)
+{
+  int charLine, charColumn;
+  getCharacterPosition(position,charLine,charColumn);
+
+  Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn);
+
+  return spot ? spot->actions() : QList<QAction*>();
+}
+
+void SessionView::mouseMoveEvent(QMouseEvent* ev)
+{
+  int charLine = 0;
+  int charColumn = 0;
+
+  getCharacterPosition(ev->pos(),charLine,charColumn); 
+
+  // handle filters
+  // change link hot-spot appearance on mouse-over
+  Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn);
+  if ( spot && spot->type() == Filter::HotSpot::Link)
+  {
+    QRect previousHotspotArea = _mouseOverHotspotArea;
+    _mouseOverHotspotArea.setCoords( qMin(spot->startColumn() , spot->endColumn()) * _fontWidth,
+                                     spot->startLine() * _fontHeight,
+                                     qMax(spot->startColumn() , spot->endColumn()) * _fontHeight,
+                                     (spot->endLine()+1) * _fontHeight );
+
+    // display tooltips when mousing over links
+    // TODO: Extend this to work with filter types other than links
+    const QString& tooltip = spot->tooltip();
+    if ( !tooltip.isEmpty() )
+    {
+        QToolTip::showText( mapToGlobal(ev->pos()) , tooltip , this , _mouseOverHotspotArea );
+    }
+
+    update( _mouseOverHotspotArea | previousHotspotArea );
+  }
+  else if ( _mouseOverHotspotArea.isValid() )
+  {
+        update( _mouseOverHotspotArea );
+        // set hotspot area to an invalid rectangle
+        _mouseOverHotspotArea = QRect();
+  }
+  
+  // for auto-hiding the cursor, we need mouseTracking
+  if (ev->buttons() == Qt::NoButton ) return;
+
+  // if the terminal is interested in mouse movements 
+  // then emit a mouse movement signal, unless the shift
+  // key is being held down, which overrides this.
+  if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
+  {
+	int button = 3;
+	if (ev->buttons() & Qt::LeftButton)
+		button = 0;
+	if (ev->buttons() & Qt::MidButton)
+		button = 1;
+	if (ev->buttons() & Qt::RightButton)
+		button = 2;
+
+        
+        emit mouseSignal( button, 
+                        charColumn + 1,
+                        charLine + 1 +_scrollBar->value() -_scrollBar->maximum(),
+			 1 );
+      
+	return;
+  }
+      
+  if (dragInfo.state == diPending) 
+  {
+    // we had a mouse down, but haven't confirmed a drag yet
+    // if the mouse has moved sufficiently, we will confirm
+
+   int distance = 10; //KGlobalSettings::dndEventDelay();
+   if ( ev->x() > dragInfo.start.x() + distance || ev->x() < dragInfo.start.x() - distance ||
+        ev->y() > dragInfo.start.y() + distance || ev->y() < dragInfo.start.y() - distance) 
+   {
+      // we've left the drag square, we can start a real drag operation now
+      emit isBusySelecting(false); // Ok.. we can breath again.
+      
+       _screenWindow->clearSelection();
+      doDrag();
+    }
+    return;
+  } 
+  else if (dragInfo.state == diDragging) 
+  {
+    // this isn't technically needed because mouseMoveEvent is suppressed during
+    // Qt drag operations, replaced by dragMoveEvent
+    return;
+  }
+
+  if (_actSel == 0) return;
+
+ // don't extend selection while pasting
+  if (ev->buttons() & Qt::MidButton) return;
+
+  extendSelection( ev->pos() );
+}
+
+#if 0
+void TerminalDisplay::setSelectionEnd()
+{
+  extendSelection( _configureRequestPoint );
+}
+#endif
+
+void SessionView::extendSelection(const QPoint& position) {
+  QPoint pos = position;
+
+  if (!_screenWindow) {
+      return;
+  }
+
+  QPoint tL  = contentsRect().topLeft();
+  int    tLx = tL.x();
+  int    tLy = tL.y();
+  int    scroll = _scrollBar->value();
+
+  // we're in the process of moving the mouse with the left button pressed
+  // the mouse cursor will kept caught within the bounds of the text in
+  // this widget.
+
+  // Adjust position within text area bounds. See FIXME above.
+  QPoint oldpos = pos;
+  if (pos.x() < tLx + _leftMargin) {
+      pos.setX(tLx + _leftMargin);
+  }
+  if (pos.x() > tLx + _leftMargin + _usedColumns * _fontWidth - 1) {
+      pos.setX(tLx + _leftMargin + _usedColumns * _fontWidth);
+  }
+  if (pos.y() < tLy + _topMargin) {
+      pos.setY(tLy + _topMargin);
+  }
+  if (pos.y() > tLy + _topMargin + _usedLines * _fontHeight - 1) {
+      pos.setY(tLy + _topMargin + _usedLines * _fontHeight - 1);
+  }
+
+  if (pos.y() == tLy + _topMargin + _usedLines * _fontHeight - 1) {
+    _scrollBar->setValue(_scrollBar->value() + yMouseScroll); // scrollforward
+  }
+  if (pos.y() == tLy + _topMargin) {
+    _scrollBar->setValue(_scrollBar->value() - yMouseScroll); // scrollback
+  }
+
+  int charColumn = 0;
+  int charLine = 0;
+  getCharacterPosition(pos, charLine, charColumn);
+
+  QPoint here = QPoint(charColumn, charLine);
+  QPoint ohere(here);
+  QPoint _iPntSelCorr = _iPntSel;
+  _iPntSelCorr.ry() -= _scrollBar->value();
+  QPoint _pntSelCorr = _pntSel;
+  _pntSelCorr.ry() -= _scrollBar->value();
+  bool swapping = false;
+
+  if (_wordSelectionMode) {
+    // Extend to word boundaries
+    int i = 0;
+    int selClass = 0;
+
+    bool left_not_right = (here.y() < _iPntSelCorr.y() ||
+						   (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));
+    bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||
+							   (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));
+    swapping = left_not_right != old_left_not_right;
+
+    // Find left (left_not_right ? from here : from start)
+    QPoint left = left_not_right ? here : _iPntSelCorr;
+    i = loc(left.x(), left.y());
+    if (i >= 0 && i <= _imageSize) {
+      selClass = charClass(_image[i].character);
+      while (((left.x() > 0) || (left.y() > 0 && (_lineProperties[left.y() - 1] & LINE_WRAPPED))) 
+					  && charClass(_image[i - 1].character) == selClass) {
+		i--;
+		if (left.x() > 0) {
+		  left.rx()--;
+		} else {
+		  left.rx() = _usedColumns - 1;
+		  left.ry()--;
+		}
+	  }
+    }
+
+    // Find left (left_not_right ? from start : from here)
+    QPoint right = left_not_right ? _iPntSelCorr : here;
+    i = loc(right.x(), right.y());
+    if (i >= 0 && i <= _imageSize) {
+      selClass = charClass(_image[i].character);
+      while (((right.x() < _usedColumns - 1) || (right.y() < _usedLines - 1 && (_lineProperties[right.y()] & LINE_WRAPPED))) 
+					  && charClass(_image[i + 1].character) == selClass) {
+		i++;
+		if (right.x() < _usedColumns - 1) {
+		  right.rx()++;
+		} else {
+		  right.rx() = 0;
+		  right.ry()++;
+		}
+	  }
+    }
+
+    // Pick which is start (ohere) and which is extension (here)
+    if (left_not_right) {
+      here = left;
+	  ohere = right;
+    } else {
+      here = right;
+	  ohere = left;
+    }
+    ohere.rx()++;
+  }
+
+  if (_lineSelectionMode) {
+    // Extend to complete line
+    bool above_not_below = (here.y() < _iPntSelCorr.y());
+
+    QPoint above = above_not_below ? here : _iPntSelCorr;
+    QPoint below = above_not_below ? _iPntSelCorr : here;
+
+    while (above.y() > 0 && (_lineProperties[above.y() - 1] & LINE_WRAPPED)) {
+      above.ry()--;
+	}
+    while (below.y() < _usedLines - 1 && (_lineProperties[below.y()] & LINE_WRAPPED)) {
+      below.ry()++;
+	}
+
+    above.setX(0);
+    below.setX(_usedColumns - 1);
+
+    // Pick which is start (ohere) and which is extension (here)
+    if (above_not_below) {
+      here = above;
+	  ohere = below;
+    } else {
+      here = below;
+	  ohere = above;
+    }
+
+    QPoint newSelBegin = QPoint(ohere.x(), ohere.y());
+    swapping = !(_tripleSelBegin == newSelBegin);
+    _tripleSelBegin = newSelBegin;
+
+    ohere.rx()++;
+  }
+
+  int offset = 0;
+  if (!_wordSelectionMode && !_lineSelectionMode) {
+    int i = 0;
+    int selClass = 0;
+
+    bool left_not_right = (here.y() < _iPntSelCorr.y() ||
+						   (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));
+    bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||
+							   (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));
+    swapping = left_not_right != old_left_not_right;
+
+    // Find left (left_not_right ? from here : from start)
+    QPoint left = left_not_right ? here : _iPntSelCorr;
+
+    // Find left (left_not_right ? from start : from here)
+    QPoint right = left_not_right ? _iPntSelCorr : here;
+    if (right.x() > 0 && !_columnSelectionMode) {
+      i = loc(right.x(), right.y());
+      if (i >= 0 && i <= _imageSize) {
+        selClass = charClass(_image[i - 1].character);
+        if (selClass == ' ') {
+          while (right.x() < _usedColumns - 1 && charClass(_image[i + 1].character) == selClass && (right.y() < _usedLines - 1) && 
+						  !(_lineProperties[right.y()] & LINE_WRAPPED)) {
+			i++;
+			right.rx()++;
+		  }
+          if (right.x() < _usedColumns - 1) {
+            right = left_not_right ? _iPntSelCorr : here;
+          } else {
+            right.rx()++;  // will be balanced later because of offset=-1;
+		  }
+        }
+      }
+    }
+
+    // Pick which is start (ohere) and which is extension (here)
+    if (left_not_right) {
+      here = left;
+	  ohere = right;
+	  offset = 0;
+    } else {
+      here = right;
+	  ohere = left;
+	  offset = -1;
+    }
+  }
+
+  if ((here == _pntSelCorr) && (scroll == _scrollBar->value())) {
+	return; // not moved
+  }
+
+  if (here == ohere) {
+	return; // It's not left, it's not right.
+  }
+
+  if (_actSel < 2 || swapping) {
+    if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) {
+        _screenWindow->setSelectionStart(ohere.x(), ohere.y(), true);
+    } else {
+        _screenWindow->setSelectionStart(ohere.x() - 1 - offset , ohere.y(), false);
+    }
+
+  }
+
+  _actSel = 2; // within selection
+  _pntSel = here;
+  _pntSel.ry() += _scrollBar->value();
+
+  if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) {
+     _screenWindow->setSelectionEnd(here.x(), here.y());
+  } else {
+     _screenWindow->setSelectionEnd(here.x() + offset, here.y());
+  }
+}
+
+void SessionView::mouseReleaseEvent(QMouseEvent* ev)
+{
+    if ( !_screenWindow )
+        return;
+
+    int charLine;
+    int charColumn;
+    getCharacterPosition(ev->pos(),charLine,charColumn);
+
+  if ( ev->button() == Qt::LeftButton)
+  {
+    emit isBusySelecting(false); 
+    if(dragInfo.state == diPending)
+    {
+      // We had a drag event pending but never confirmed.  Kill selection
+       _screenWindow->clearSelection();
+      //emit clearSelectionSignal();
+    }
+    else
+    {
+      if ( _actSel > 1 )
+      {
+          setSelection(  _screenWindow->selectedText(_preserveLineBreaks)  );
+      }
+
+      _actSel = 0;
+
+      //FIXME: emits a release event even if the mouse is
+      //       outside the range. The procedure used in `mouseMoveEvent'
+      //       applies here, too.
+
+      if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
+        emit mouseSignal( 3, // release
+                        charColumn + 1,
+                        charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0);
+    }
+    dragInfo.state = diNone;
+  }
+  
+  
+  if ( !_mouseMarks && 
+       ((ev->button() == Qt::RightButton && !(ev->modifiers() & Qt::ShiftModifier))
+                        || ev->button() == Qt::MidButton) ) 
+  {
+    emit mouseSignal( 3, 
+                      charColumn + 1, 
+                      charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 
+                      0);
+  }
+}
+
+void SessionView::getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const
+{
+
+    column = (widgetPoint.x() + _fontWidth/2 -contentsRect().left()-_leftMargin) / _fontWidth;
+    line = (widgetPoint.y()-contentsRect().top()-_topMargin) / _fontHeight;
+
+    if ( line < 0 )
+        line = 0;
+    if ( column < 0 )
+        column = 0;
+
+    if ( line >= _usedLines )
+        line = _usedLines-1;
+
+    // the column value returned can be equal to _usedColumns, which
+    // is the position just after the last character displayed in a line.
+    //
+    // this is required so that the user can select characters in the right-most
+    // column (or left-most for right-to-left input)
+    if ( column > _usedColumns )
+        column = _usedColumns;
+}
+
+void SessionView::updateLineProperties()
+{
+    if ( !_screenWindow ) 
+        return;
+
+    _lineProperties = _screenWindow->getLineProperties();    
+}
+
+void SessionView::mouseDoubleClickEvent(QMouseEvent* ev)
+{
+  if ( ev->button() != Qt::LeftButton) return;
+  if ( !_screenWindow ) return;
+
+  int charLine = 0;
+  int charColumn = 0;
+
+  getCharacterPosition(ev->pos(),charLine,charColumn);
+
+  QPoint pos(charColumn,charLine);
+
+  // pass on double click as two clicks.
+  if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
+  {
+    // Send just _ONE_ click event, since the first click of the double click
+    // was already sent by the click handler
+    emit mouseSignal( 0, 
+                      pos.x()+1, 
+                      pos.y()+1 +_scrollBar->value() -_scrollBar->maximum(),
+                      0 ); // left button
+    return;
+  }
+
+  _screenWindow->clearSelection();
+  QPoint bgnSel = pos;
+  QPoint endSel = pos;
+  int i = loc(bgnSel.x(),bgnSel.y());
+  _iPntSel = bgnSel;
+  _iPntSel.ry() += _scrollBar->value();
+
+  _wordSelectionMode = true;
+
+  // find word boundaries...
+  int selClass = charClass(_image[i].character);
+  {
+     // find the start of the word
+     int x = bgnSel.x();
+     while ( ((x>0) || (bgnSel.y()>0 && (_lineProperties[bgnSel.y()-1] & LINE_WRAPPED) )) 
+					 && charClass(_image[i-1].character) == selClass )
+     {  
+       i--; 
+       if (x>0) 
+           x--; 
+       else 
+       {
+           x=_usedColumns-1; 
+           bgnSel.ry()--;
+       } 
+     }
+
+     bgnSel.setX(x);
+     _screenWindow->setSelectionStart( bgnSel.x() , bgnSel.y() , false );
+
+     // find the end of the word
+     i = loc( endSel.x(), endSel.y() );
+     x = endSel.x();
+     while( ((x<_usedColumns-1) || (endSel.y()<_usedLines-1 && (_lineProperties[endSel.y()] & LINE_WRAPPED) )) 
+					 && charClass(_image[i+1].character) == selClass )
+     { 
+         i++; 
+         if (x<_usedColumns-1) 
+             x++; 
+         else 
+         {  
+             x=0; 
+             endSel.ry()++; 
+         } 
+     }
+
+     endSel.setX(x);
+
+     // In word selection mode don't select @ (64) if at end of word.
+     if ( ( QChar( _image[i].character ) == '@' ) && ( ( endSel.x() - bgnSel.x() ) > 0 ) )
+       endSel.setX( x - 1 );
+
+
+     _actSel = 2; // within selection
+     
+     _screenWindow->setSelectionEnd( endSel.x() , endSel.y() );
+    
+     setSelection( _screenWindow->selectedText(_preserveLineBreaks) ); 
+   }
+
+  _possibleTripleClick=true;
+
+  QTimer::singleShot(QApplication::doubleClickInterval(),this,
+                     SLOT(tripleClickTimeout()));
+}
+
+void SessionView::wheelEvent( QWheelEvent* ev )
+{
+  if (ev->orientation() != Qt::Vertical)
+    return;
+
+  if ( _mouseMarks )
+    _scrollBar->event(ev);
+  else
+  {
+    int charLine;
+    int charColumn;
+    getCharacterPosition( ev->pos() , charLine , charColumn );
+    
+    emit mouseSignal( ev->delta() > 0 ? 4 : 5, 
+                      charColumn + 1, 
+                      charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 
+                      0);
+  }
+}
+
+void SessionView::tripleClickTimeout()
+{
+  _possibleTripleClick=false;
+}
+
+void SessionView::mouseTripleClickEvent(QMouseEvent* ev)
+{
+  if ( !_screenWindow ) return;
+
+  int charLine;
+  int charColumn;
+  getCharacterPosition(ev->pos(),charLine,charColumn);
+  _iPntSel = QPoint(charColumn,charLine);
+
+  _screenWindow->clearSelection();
+
+  _lineSelectionMode = true;
+  _wordSelectionMode = false;
+
+  _actSel = 2; // within selection
+  emit isBusySelecting(true); // Keep it steady...
+
+  while (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) )
+    _iPntSel.ry()--;
+  
+  if (_tripleClickMode == SelectForwardsFromCursor) {
+    // find word boundary start
+    int i = loc(_iPntSel.x(),_iPntSel.y());
+    int selClass = charClass(_image[i].character);
+    int x = _iPntSel.x();
+    
+    while ( ((x>0) || 
+             (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) )
+            ) 
+            && charClass(_image[i-1].character) == selClass )
+    {
+        i--; 
+        if (x>0) 
+            x--; 
+        else 
+        {
+            x=_columns-1; 
+            _iPntSel.ry()--;
+        } 
+    }
+
+    _screenWindow->setSelectionStart( x , _iPntSel.y() , false );
+    _tripleSelBegin = QPoint( x, _iPntSel.y() );
+  }
+  else if (_tripleClickMode == SelectWholeLine) {
+    _screenWindow->setSelectionStart( 0 , _iPntSel.y() , false );
+    _tripleSelBegin = QPoint( 0, _iPntSel.y() );
+  }
+
+  while (_iPntSel.y()<_lines-1 && (_lineProperties[_iPntSel.y()] & LINE_WRAPPED) )
+    _iPntSel.ry()++;
+  
+  _screenWindow->setSelectionEnd( _columns - 1 , _iPntSel.y() );
+
+  setSelection(_screenWindow->selectedText(_preserveLineBreaks));
+
+  _iPntSel.ry() += _scrollBar->value();
+
+  emit tripleClicked( _screenWindow->selectedText( _preserveLineBreaks ) ); 
+}
+
+
+bool SessionView::focusNextPrevChild( bool next )
+{
+  if (next)
+    return false; // This disables changing the active part in konqueror
+                  // when pressing Tab
+  return QWidget::focusNextPrevChild( next );
+}
+
+
+int SessionView::charClass(quint16 ch) const
+{
+    QChar qch=QChar(ch);
+    if ( qch.isSpace() ) return ' ';
+
+    if ( qch.isLetterOrNumber() || _wordCharacters.contains(qch, Qt::CaseInsensitive ) )
+    return 'a';
+
+    // Everything else is weird
+    return 1;
+}
+
+void SessionView::setWordCharacters(const QString& wc)
+{
+	_wordCharacters = wc;
+}
+
+void SessionView::setUsesMouse(bool on)
+{
+  _mouseMarks = on;
+  setCursor( _mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor );
+}
+bool SessionView::usesMouse() const
+{
+    return _mouseMarks;
+}
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                               Clipboard                                   */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+#undef KeyPress
+
+void SessionView::emitSelection(bool useXselection,bool appendReturn)
+{
+  if ( !_screenWindow ) 
+      return;
+
+  // Paste Clipboard by simulating keypress events
+  QString text = QApplication::clipboard()->text(useXselection ? QClipboard::Selection :
+                                                                 QClipboard::Clipboard);
+  if(appendReturn)
+    text.append("\r");
+  if ( ! text.isEmpty() )
+  {
+    text.replace("\n", "\r");
+    QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text);
+    emit keyPressedSignal(&e); // expose as a big fat keypress event
+    
+    _screenWindow->clearSelection();
+  }
+}
+
+void SessionView::setSelection(const QString& t)
+{
+  QApplication::clipboard()->setText(t, QClipboard::Selection);
+}
+
+void SessionView::copyClipboard()
+{
+  if ( !_screenWindow )
+      return;
+
+  QString text = _screenWindow->selectedText(_preserveLineBreaks);
+  QApplication::clipboard()->setText(text);
+}
+
+void SessionView::pasteClipboard()
+{
+  emitSelection(false,false);
+}
+
+void SessionView::pasteSelection()
+{
+  emitSelection(true,false);
+}
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                                Keyboard                                   */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+void SessionView::setFlowControlWarningEnabled( bool enable )
+{
+	_flowControlWarningEnabled = enable;
+	
+	// if the dialog is currently visible and the flow control warning has 
+	// been disabled then hide the dialog
+	if (!enable)
+		outputSuspended(false);
+}
+
+void SessionView::keyPressEvent( QKeyEvent* event )
+{
+//qDebug("%s %d keyPressEvent and key is %d", __FILE__, __LINE__, event->key());
+
+    bool emitKeyPressSignal = true;
+
+    // XonXoff flow control
+    if (event->modifiers() & Qt::ControlModifier && _flowControlWarningEnabled)
+	{
+		if ( event->key() == Qt::Key_S ) {
+		//qDebug("%s %d keyPressEvent, output suspended", __FILE__, __LINE__);
+				emit flowControlKeyPressed(true /*output suspended*/);
+		}
+		else if ( event->key() == Qt::Key_Q ) {
+		//qDebug("%s %d keyPressEvent, output enabled", __FILE__, __LINE__);
+				emit flowControlKeyPressed(false /*output enabled*/);
+		}
+	}
+
+    // Keyboard-based navigation
+    if ( event->modifiers() == Qt::ShiftModifier )
+    {
+        bool update = true;
+
+        if ( event->key() == Qt::Key_PageUp )
+        {
+	    //qDebug("%s %d pageup", __FILE__, __LINE__);
+            _screenWindow->scrollBy( ScreenWindow::ScrollPages , -1 );
+        }
+        else if ( event->key() == Qt::Key_PageDown )
+        {
+	    //qDebug("%s %d pagedown", __FILE__, __LINE__);
+            _screenWindow->scrollBy( ScreenWindow::ScrollPages , 1 );
+        }
+        else if ( event->key() == Qt::Key_Up )
+        {
+	    //qDebug("%s %d keyup", __FILE__, __LINE__);	
+            _screenWindow->scrollBy( ScreenWindow::ScrollLines , -1 );
+        }
+        else if ( event->key() == Qt::Key_Down )
+        {
+	    //qDebug("%s %d keydown", __FILE__, __LINE__);	
+            _screenWindow->scrollBy( ScreenWindow::ScrollLines , 1 );
+        }
+        else {
+            update = false;
+	}
+
+        if ( update )
+        {
+	    //qDebug("%s %d updating", __FILE__, __LINE__);	
+            _screenWindow->setTrackOutput( _screenWindow->atEndOfOutput() );
+            
+            updateLineProperties();
+            updateImage();
+
+            // do not send key press to terminal
+            emitKeyPressSignal = false;
+        }
+    }
+    
+    _screenWindow->setTrackOutput( true );
+    
+    _actSel=0; // Key stroke implies a screen update, so TerminalDisplay won't
+              // know where the current selection is.
+
+    if (_hasBlinkingCursor) 
+    {
+      _blinkCursorTimer->start(BLINK_DELAY);
+      if (_cursorBlinking)
+        blinkCursorEvent();
+      else
+        _cursorBlinking = false;
+    }
+
+    if ( emitKeyPressSignal && !_readonly )
+        emit keyPressedSignal(event);
+
+    if (_readonly) {
+	event->ignore();
+    }
+    else {
+        event->accept();
+    }
+}
+
+void SessionView::inputMethodEvent( QInputMethodEvent* event )
+{
+    QKeyEvent keyEvent(QEvent::KeyPress,0,Qt::NoModifier,event->commitString());
+    emit keyPressedSignal(&keyEvent);
+
+    _inputMethodData.preeditString = event->preeditString();
+    update(preeditRect() | _inputMethodData.previousPreeditRect);
+    
+    event->accept();
+}
+QVariant SessionView::inputMethodQuery( Qt::InputMethodQuery query ) const
+{
+    const QPoint cursorPos = _screenWindow ? _screenWindow->cursorPosition() : QPoint(0,0);
+    switch ( query ) 
+    {
+        case Qt::ImMicroFocus:
+                return imageToWidget(QRect(cursorPos.x(),cursorPos.y(),1,1));
+            break;
+        case Qt::ImFont:
+                return font();
+            break;
+        case Qt::ImCursorPosition:
+                // return the cursor position within the current line
+                return cursorPos.x();
+            break;
+        case Qt::ImSurroundingText:
+            {
+                // return the text from the current line
+                QString lineText;
+                QTextStream stream(&lineText);
+                PlainTextDecoder decoder;
+                decoder.begin(&stream);
+                decoder.decodeLine(&_image[loc(0,cursorPos.y())],_usedColumns,_lineProperties[cursorPos.y()]);
+                decoder.end();
+                return lineText;
+            }
+            break;
+        case Qt::ImCurrentSelection:
+                return QString();
+            break;
+	    default:
+	        break;
+    }
+
+    return QVariant();
+}
+
+bool SessionView::event( QEvent *e )
+{
+  if ( e->type() == QEvent::ShortcutOverride )
+  {
+    QKeyEvent* keyEvent = static_cast<QKeyEvent *>( e );
+
+    // a check to see if keyEvent->text() is empty is used
+    // to avoid intercepting the press of the modifier key on its own.
+    //
+    // this is important as it allows a press and release of the Alt key
+    // on its own to focus the menu bar, making it possible to
+    // work with the menu without using the mouse
+    if ( (keyEvent->modifiers() == Qt::AltModifier) && 
+         !keyEvent->text().isEmpty() )
+    {
+    	keyEvent->accept();
+      	return true;
+    }
+
+    // Override any of the following shortcuts because
+    // they are needed by the terminal
+    int keyCode = keyEvent->key() | keyEvent->modifiers();
+    switch ( keyCode )
+    {
+      // list is taken from the QLineEdit::event() code
+      case Qt::Key_Tab:
+      case Qt::Key_Delete:
+      case Qt::Key_Home:
+      case Qt::Key_End:
+      case Qt::Key_Backspace:
+      case Qt::Key_Left:
+      case Qt::Key_Right:
+        keyEvent->accept();
+        return true;
+    }
+  }
+  return QWidget::event( e );
+}
+
+void SessionView::setBellMode(int mode)
+{
+  _bellMode=mode;
+}
+
+void SessionView::enableBell()
+{
+    _allowBell = true;
+}
+
+void SessionView::bell(const QString&)
+{
+  if (_bellMode==NoBell) return;
+
+  //limit the rate at which bells can occur 
+  //...mainly for sound effects where rapid bells in sequence 
+  //produce a horrible noise
+  if ( _allowBell )
+  {
+    _allowBell = false;
+    QTimer::singleShot(500,this,SLOT(enableBell()));
+ 
+    if (_bellMode==SystemBeepBell) 
+    {
+//        KNotification::beep();
+    } 
+    else if (_bellMode==NotifyBell) 
+    {
+//        KNotification::event("BellVisible", message,QPixmap(),this);
+    } 
+    else if (_bellMode==VisualBell) 
+    {
+        swapColorTable();
+        QTimer::singleShot(200,this,SLOT(swapColorTable()));
+    }
+  }
+}
+
+void SessionView::swapColorTable()
+{
+  ColorEntry color = _colorTable[1];
+  _colorTable[1]=_colorTable[0];
+  _colorTable[0]= color;
+  _colorsInverted = !_colorsInverted;
+  update();
+}
+
+void SessionView::clearImage()
+{
+  // We initialize _image[_imageSize] too. See makeImage()
+  for (int i = 0; i <= _imageSize; i++)
+  {
+    _image[i].character = ' ';
+    _image[i].foregroundColor = CharacterColor(COLOR_SPACE_DEFAULT,
+                                               DEFAULT_FORE_COLOR);
+    _image[i].backgroundColor = CharacterColor(COLOR_SPACE_DEFAULT,
+                                               DEFAULT_BACK_COLOR);
+    _image[i].rendition = DEFAULT_RENDITION;
+  }
+}
+
+void SessionView::calcGeometry()
+{
+  _scrollBar->resize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent),
+                    contentsRect().height());
+  switch(_scrollbarLocation)
+  {
+    case NoScrollBar :
+     _leftMargin = DEFAULT_LEFT_MARGIN;
+     _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN;
+     break;
+    case ScrollBarLeft :
+     _leftMargin = DEFAULT_LEFT_MARGIN + _scrollBar->width();
+     _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width();
+     _scrollBar->move(contentsRect().topLeft());
+     break;
+    case ScrollBarRight:
+     _leftMargin = DEFAULT_LEFT_MARGIN;
+     _contentWidth = contentsRect().width()  - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width();
+     _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width()-1,0));
+     break;
+  }
+
+  _topMargin = DEFAULT_TOP_MARGIN;
+  _contentHeight = contentsRect().height() - 2 * DEFAULT_TOP_MARGIN + /* mysterious */ 1;
+
+  if (!_isFixedSize)
+  {
+     // ensure that display is always at least one column wide
+     _columns = qMax(1,_contentWidth / _fontWidth);
+     _usedColumns = qMin(_usedColumns,_columns);
+     
+     // ensure that display is always at least one line high
+     _lines = qMax(1,_contentHeight / _fontHeight);
+     _usedLines = qMin(_usedLines,_lines);
+  }
+}
+
+void SessionView::makeImage()
+{
+//qDebug("%s %d makeImage", __FILE__, __LINE__);
+  calcGeometry();
+
+  // confirm that array will be of non-zero size, since the painting code 
+  // assumes a non-zero array length
+  Q_ASSERT( _lines > 0 && _columns > 0 );
+  Q_ASSERT( _usedLines <= _lines && _usedColumns <= _columns );
+
+  _imageSize=_lines*_columns;
+  
+  // We over-commit one character so that we can be more relaxed in dealing with
+  // certain boundary conditions: _image[_imageSize] is a valid but unused position
+  _image = new Character[_imageSize+1];
+
+  clearImage();
+}
+
+// calculate the needed size
+void SessionView::setSize(int columns, int lines)
+{
+  //FIXME - Not quite correct, a small amount of additional space
+  // will be used for margins, the scrollbar etc.
+  // we need to allow for this so that '_size' does allow
+  // enough room for the specified number of columns and lines to fit
+
+  QSize newSize = QSize( columns * _fontWidth  ,
+				 lines * _fontHeight   );
+
+  if ( newSize != size() )
+  {
+    _size = newSize;
+    updateGeometry();
+  }
+}
+
+void SessionView::setFixedSize(int cols, int lins)
+{
+  _isFixedSize = true;
+  
+  //ensure that display is at least one line by one column in size
+  _columns = qMax(1,cols);
+  _lines = qMax(1,lins);
+  _usedColumns = qMin(_usedColumns,_columns);
+  _usedLines = qMin(_usedLines,_lines);
+
+  if (_image)
+  {
+     delete[] _image;
+     makeImage();
+  }
+  setSize(cols, lins);
+  QWidget::setFixedSize(_size);
+}
+
+QSize SessionView::sizeHint() const
+{
+  return _size;
+}
+
+
+/* --------------------------------------------------------------------- */
+/*                                                                       */
+/* Drag & Drop                                                           */
+/*                                                                       */
+/* --------------------------------------------------------------------- */
+
+void SessionView::dragEnterEvent(QDragEnterEvent* event)
+{
+  if (event->mimeData()->hasFormat("text/plain"))
+      event->acceptProposedAction();
+}
+
+void SessionView::dropEvent(QDropEvent* event)
+{
+//  KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
+
+  QString dropText;
+/*  if (!urls.isEmpty()) 
+  {
+    for ( int i = 0 ; i < urls.count() ; i++ ) 
+    {
+        KUrl url = KIO::NetAccess::mostLocalUrl( urls[i] , 0 );
+        QString urlText;
+
+        if (url.isLocalFile())
+            urlText = url.path(); 
+        else
+            urlText = url.url();
+    
+        // in future it may be useful to be able to insert file names with drag-and-drop
+        // without quoting them (this only affects paths with spaces in) 
+        urlText = KShell::quoteArg(urlText);
+      
+        dropText += urlText;
+
+        if ( i != urls.count()-1 ) 
+            dropText += ' ';
+    }
+  }
+  else 
+  {
+    dropText = event->mimeData()->text();
+  }
+*/
+  if(event->mimeData()->hasFormat("text/plain")) 
+  {
+    emit sendStringToEmu(dropText.toLocal8Bit());
+  }
+}
+
+void SessionView::doDrag()
+{
+  dragInfo.state = diDragging;
+  dragInfo.dragObject = new QDrag(this);
+  QMimeData *mimeData = new QMimeData;
+  mimeData->setText(QApplication::clipboard()->text(QClipboard::Selection));
+  dragInfo.dragObject->setMimeData(mimeData);
+  dragInfo.dragObject->start(Qt::CopyAction);
+  // Don't delete the QTextDrag object.  Qt will delete it when it's done with it.
+}
+
+void SessionView::outputSuspended(bool suspended)
+{
+	//create the label when this function is first called
+	if (!_outputSuspendedLabel)
+	{
+            //This label includes a link to an English language website
+            //describing the 'flow control' (Xon/Xoff) feature found in almost 
+            //all terminal emulators.
+            //If there isn't a suitable article available in the target language the link
+            //can simply be removed.
+			_outputSuspendedLabel = new QLabel( ("<qt>Output has been "
+                                                "<a href=\"http://en.wikipedia.org/wiki/XON\">suspended</a>"
+                                                " by pressing Ctrl+S."
+											   "  Press <b>Ctrl+Q</b> to resume.</qt>"),
+											   this );
+
+            QPalette palette(_outputSuspendedLabel->palette());
+	    
+	    palette.setColor(QPalette::Normal, QPalette::WindowText, QColor(Qt::white));
+	    palette.setColor(QPalette::Normal, QPalette::Window, QColor(Qt::black));
+//            KColorScheme::adjustForeground(palette,KColorScheme::NeutralText);
+//		KColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground);
+    	    _outputSuspendedLabel->setPalette(palette);
+	    _outputSuspendedLabel->setAutoFillBackground(true);
+	    _outputSuspendedLabel->setBackgroundRole(QPalette::Base);
+	    _outputSuspendedLabel->setFont(QApplication::font());
+            _outputSuspendedLabel->setMargin(5);
+
+            //enable activation of "Xon/Xoff" link in label
+            _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse | 
+                                                          Qt::LinksAccessibleByKeyboard);
+            _outputSuspendedLabel->setOpenExternalLinks(true);
+            _outputSuspendedLabel->setVisible(false);
+
+            _gridLayout->addWidget(_outputSuspendedLabel);       
+            _gridLayout->addItem( new QSpacerItem(0,0,QSizePolicy::Expanding,
+                                                      QSizePolicy::Expanding),
+                                 1,0);
+
+    }
+
+	_outputSuspendedLabel->setVisible(suspended);
+}
+
+uint SessionView::lineSpacing() const
+{
+  return _lineSpacing;
+}
+
+void SessionView::setLineSpacing(uint i)
+{
+  _lineSpacing = i;
+  setVTFont(font()); // Trigger an update.
+}
new file mode 100644
--- /dev/null
+++ b/libqterminal/SessionView.h
@@ -0,0 +1,758 @@
+/*
+    Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
+    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301  USA.
+*/
+
+#ifndef TERMINALDISPLAY_H
+#define TERMINALDISPLAY_H
+
+// Qt
+#include <QtGui/QColor>
+#include <QtCore/QPointer>
+#include <QtGui/QWidget>
+
+// Konsole
+#include "Filter.h"
+#include "Character.h"
+
+class QDrag;
+class QDragEnterEvent;
+class QDropEvent;
+class QLabel;
+class QTimer;
+class QEvent;
+class QFrame;
+class QGridLayout;
+class QKeyEvent;
+class QScrollBar;
+class QShowEvent;
+class QHideEvent;
+class QWidget;
+
+extern unsigned short vt100_graphics[32];
+
+class ScreenWindow;
+
+/**
+ * A widget which displays output from a terminal emulation and sends input keypresses and mouse activity
+ * to the terminal.
+ *
+ * When the terminal emulation receives new output from the program running in the terminal, 
+ * it will update the display by calling updateImage().
+ *
+ * TODO More documentation
+ */
+class SessionView : public QWidget
+{
+   Q_OBJECT
+
+public:
+    /** Constructs a new terminal display widget with the specified parent. */
+    SessionView(QWidget *parent=0);
+    virtual ~SessionView();
+
+    /** Returns the terminal color palette used by the display. */
+    const ColorEntry* colorTable() const;
+    /** Sets the terminal color palette used by the display. */
+    void setColorTable(const ColorEntry table[]);
+    /**
+     * Sets the seed used to generate random colors for the display
+     * (in color schemes that support them).
+     */
+    void setRandomSeed(uint seed);
+    /**
+     * Returns the seed used to generate random colors for the display
+     * (in color schemes that support them).
+     */
+    uint randomSeed() const;
+
+    /** Sets the opacity of the terminal display. */
+    void setOpacity(qreal opacity);
+
+    /** 
+     * This enum describes the location where the scroll bar is positioned in the display widget.
+     */
+    enum ScrollBarPosition 
+    { 
+        /** Do not show the scroll bar. */
+        NoScrollBar=0, 
+        /** Show the scroll bar on the left side of the display. */
+        ScrollBarLeft=1, 
+        /** Show the scroll bar on the right side of the display. */
+        ScrollBarRight=2 
+    };
+    /** 
+     * Specifies whether the terminal display has a vertical scroll bar, and if so whether it
+     * is shown on the left or right side of the display.
+     */
+    void setScrollBarPosition(ScrollBarPosition position);
+
+    /** 
+     * Sets the current position and range of the display's scroll bar.
+     *
+     * @param cursor The position of the scroll bar's thumb.
+     * @param lines The maximum value of the scroll bar.
+     */
+    void setScroll(int cursor, int lines);
+
+    /** 
+     * Returns the display's filter chain.  When the image for the display is updated,
+     * the text is passed through each filter in the chain.  Each filter can define
+     * hotspots which correspond to certain strings (such as URLs or particular words).
+     * Depending on the type of the hotspots created by the filter ( returned by Filter::Hotspot::type() )
+     * the view will draw visual cues such as underlines on mouse-over for links or translucent
+     * rectangles for markers.
+     *
+     * To add a new filter to the view, call:
+     *      viewWidget->filterChain()->addFilter( filterObject );
+     */
+    FilterChain* filterChain() const;
+
+    /** 
+     * Updates the filters in the display's filter chain.  This will cause
+     * the hotspots to be updated to match the current image.
+     *
+     * WARNING:  This function can be expensive depending on the 
+     * image size and number of filters in the filterChain()
+     *
+     * TODO - This API does not really allow efficient usage.  Revise it so
+     * that the processing can be done in a better way.
+     *
+     * eg:
+     *      - Area of interest may be known ( eg. mouse cursor hovering
+     *      over an area )
+     */  
+    void processFilters();
+
+    /** 
+     * Returns a list of menu actions created by the filters for the content
+     * at the given @p position.
+     */
+    QList<QAction*> filterActions(const QPoint& position);
+
+    /** Returns true if the cursor is set to blink or false otherwise. */
+    bool blinkingCursor() { return _hasBlinkingCursor; }
+    /** Specifies whether or not the cursor blinks. */
+    void setBlinkingCursor(bool blink);
+
+    void setCtrlDrag(bool enable) { _ctrlDrag=enable; }
+    bool ctrlDrag() { return _ctrlDrag; }
+
+	/** 
+     *  This enum describes the methods for selecting text when
+ 	 *  the user triple-clicks within the display. 
+ 	 */
+	enum TripleClickMode
+	{
+		/** Select the whole line underneath the cursor. */
+		SelectWholeLine,
+		/** Select from the current cursor position to the end of the line. */
+		SelectForwardsFromCursor
+	};
+    /** Sets how the text is selected when the user triple clicks within the display. */	
+    void setTripleClickMode(TripleClickMode mode) { _tripleClickMode = mode; }
+	/** See setTripleClickSelectionMode() */
+    TripleClickMode tripleClickMode() { return _tripleClickMode; }
+
+    void setLineSpacing(uint);
+    uint lineSpacing() const;
+
+    void emitSelection(bool useXselection,bool appendReturn);
+
+    /**
+     * This enum describes the available shapes for the keyboard cursor.
+     * See setKeyboardCursorShape()
+     */
+    enum KeyboardCursorShape
+    {
+        /** A rectangular block which covers the entire area of the cursor character. */
+        BlockCursor,
+        /** 
+         * A single flat line which occupies the space at the bottom of the cursor
+         * character's area.
+         */
+        UnderlineCursor,
+        /** 
+         * An cursor shaped like the capital letter 'I', similar to the IBeam 
+         * cursor used in Qt/KDE text editors.
+         */
+        IBeamCursor
+    };
+    /** 
+     * Sets the shape of the keyboard cursor.  This is the cursor drawn   
+     * at the position in the terminal where keyboard input will appear.
+     *
+     * In addition the terminal display widget also has a cursor for 
+     * the mouse pointer, which can be set using the QWidget::setCursor()
+     * method.
+     *
+     * Defaults to BlockCursor
+     */
+    void setKeyboardCursorShape(KeyboardCursorShape shape);
+    /**
+     * Returns the shape of the keyboard cursor.  See setKeyboardCursorShape()
+     */
+    KeyboardCursorShape keyboardCursorShape() const;
+
+    /**
+     * Sets the color used to draw the keyboard cursor.  
+     *
+     * The keyboard cursor defaults to using the foreground color of the character
+     * underneath it.
+     *
+     * @param useForegroundColor If true, the cursor color will change to match
+     * the foreground color of the character underneath it as it is moved, in this
+     * case, the @p color parameter is ignored and the color of the character
+     * under the cursor is inverted to ensure that it is still readable.
+     * @param color The color to use to draw the cursor.  This is only taken into
+     * account if @p useForegroundColor is false.
+     */
+    void setKeyboardCursorColor(bool useForegroundColor , const QColor& color);
+
+    /** 
+     * Returns the color of the keyboard cursor, or an invalid color if the keyboard
+     * cursor color is set to change according to the foreground color of the character
+     * underneath it. 
+     */
+    QColor keyboardCursorColor() const;
+
+    /**
+     * Returns the number of lines of text which can be displayed in the widget.
+     *
+     * This will depend upon the height of the widget and the current font.
+     * See fontHeight()
+     */
+    int  lines()   { return _lines;   }
+    /**
+     * Returns the number of characters of text which can be displayed on
+     * each line in the widget.
+     *
+     * This will depend upon the width of the widget and the current font.
+     * See fontWidth()
+     */
+    int  columns() { return _columns; }
+
+    /**
+     * Returns the height of the characters in the font used to draw the text in the display.
+     */
+    int  fontHeight()   { return _fontHeight;   }
+    /**
+     * Returns the width of the characters in the display.  
+     * This assumes the use of a fixed-width font.
+     */
+    int  fontWidth()    { return _fontWidth; }
+
+    void setSize(int cols, int lins);
+    void setFixedSize(int cols, int lins);
+    
+    // reimplemented
+    QSize sizeHint() const;
+
+    /**
+     * Sets which characters, in addition to letters and numbers, 
+     * are regarded as being part of a word for the purposes
+     * of selecting words in the display by double clicking on them.
+     *
+     * The word boundaries occur at the first and last characters which
+     * are either a letter, number, or a character in @p wc
+     *
+     * @param wc An array of characters which are to be considered parts
+     * of a word ( in addition to letters and numbers ).
+     */
+    void setWordCharacters(const QString& wc);
+    /** 
+     * Returns the characters which are considered part of a word for the 
+     * purpose of selecting words in the display with the mouse.
+     *
+     * @see setWordCharacters()
+     */
+    QString wordCharacters() { return _wordCharacters; }
+
+    /** 
+     * Sets the type of effect used to alert the user when a 'bell' occurs in the 
+     * terminal session.
+     *
+     * The terminal session can trigger the bell effect by calling bell() with
+     * the alert message.
+     */
+    void setBellMode(int mode);
+    /** 
+     * Returns the type of effect used to alert the user when a 'bell' occurs in
+     * the terminal session.
+     * 
+     * See setBellMode()
+     */
+    int bellMode() { return _bellMode; }
+
+    /**
+     * This enum describes the different types of sounds and visual effects which
+     * can be used to alert the user when a 'bell' occurs in the terminal
+     * session.
+     */
+    enum BellMode
+    { 
+        /** A system beep. */
+        SystemBeepBell=0, 
+        /** 
+         * KDE notification.  This may play a sound, show a passive popup
+         * or perform some other action depending on the user's settings.
+         */
+        NotifyBell=1, 
+        /** A silent, visual bell (eg. inverting the display's colors briefly) */
+        VisualBell=2, 
+        /** No bell effects */
+        NoBell=3 
+    };
+
+    void setSelection(const QString &t);
+
+    /** 
+     * Reimplemented.  Has no effect.  Use setVTFont() to change the font
+     * used to draw characters in the display.
+     */
+    virtual void setFont(const QFont &);
+
+
+    /** Returns the font used to draw characters in the display */
+    QFont getVTFont() { return font(); }
+
+    /** 
+     * Sets the font used to draw the display.  Has no effect if @p font
+     * is larger than the size of the display itself.    
+     */
+    void setVTFont(const QFont& font);
+
+
+    /**
+     * Specified whether terminal widget should be at read-only mode
+     * Defaults to false.
+     */
+    void setReadOnly( bool readonly) { _readonly = readonly; }
+
+    /**
+     * Specified whether anti-aliasing of text in the terminal display
+     * is enabled or not.  Defaults to enabled.
+     */
+    static void setAntialias( bool antialias ) { _antialiasText = antialias; }
+    /** 
+     * Returns true if anti-aliasing of text in the terminal is enabled.
+     */
+    static bool antialias()                 { return _antialiasText;   }
+    
+    /**
+     * Sets whether or not the current height and width of the 
+     * terminal in lines and columns is displayed whilst the widget
+     * is being resized.
+     */
+    void setTerminalSizeHint(bool on) { _terminalSizeHint=on; }
+    /** 
+     * Returns whether or not the current height and width of
+     * the terminal in lines and columns is displayed whilst the widget
+     * is being resized.
+     */
+    bool terminalSizeHint() { return _terminalSizeHint; }
+    /** 
+     * Sets whether the terminal size display is shown briefly
+     * after the widget is first shown.
+     *
+     * See setTerminalSizeHint() , isTerminalSizeHint()
+     */
+    void setTerminalSizeStartup(bool on) { _terminalSizeStartup=on; }
+
+    void setBidiEnabled(bool set) { _bidiEnabled=set; }
+    bool isBidiEnabled() { return _bidiEnabled; }
+
+    /**
+     * Sets the terminal screen section which is displayed in this widget.
+     * When updateImage() is called, the display fetches the latest character image from the
+     * the associated terminal screen window.
+     *
+     * In terms of the model-view paradigm, the ScreenWindow is the model which is rendered
+     * by the TerminalDisplay.
+     */
+    void setScreenWindow( ScreenWindow* window );
+    /** Returns the terminal screen section which is displayed in this widget.  See setScreenWindow() */
+    ScreenWindow* screenWindow() const;
+
+    static bool HAVE_TRANSPARENCY;
+
+public slots:
+
+    /** 
+     * Causes the terminal display to fetch the latest character image from the associated
+     * terminal screen ( see setScreenWindow() ) and redraw the display.
+     */
+    void updateImage(); 
+    /**
+     * Causes the terminal display to fetch the latest line status flags from the 
+     * associated terminal screen ( see setScreenWindow() ).  
+     */ 
+    void updateLineProperties();
+
+    /** Copies the selected text to the clipboard. */
+    void copyClipboard();
+    /** 
+     * Pastes the content of the clipboard into the 
+     * display.
+     */
+    void pasteClipboard();
+    /**
+     * Pastes the content of the selection into the
+     * display.
+     */
+    void pasteSelection();
+
+	/** 
+ 	  * Changes whether the flow control warning box should be shown when the flow control
+ 	  * stop key (Ctrl+S) are pressed.
+ 	  */
+	void setFlowControlWarningEnabled(bool enabled);
+	
+    /** 
+	 * Causes the widget to display or hide a message informing the user that terminal
+	 * output has been suspended (by using the flow control key combination Ctrl+S)
+	 *
+	 * @param suspended True if terminal output has been suspended and the warning message should
+	 *				 	be shown or false to indicate that terminal output has been resumed and that
+	 *				 	the warning message should disappear.
+	 */ 
+	void outputSuspended(bool suspended);
+
+    /**
+     * Sets whether the program whoose output is being displayed in the view
+     * is interested in mouse events.
+     *
+     * If this is set to true, mouse signals will be emitted by the view when the user clicks, drags
+     * or otherwise moves the mouse inside the view.
+     * The user interaction needed to create selections will also change, and the user will be required
+     * to hold down the shift key to create a selection or perform other mouse activities inside the 
+     * view area - since the program running in the terminal is being allowed to handle normal mouse
+     * events itself.
+     *
+     * @param usesMouse Set to true if the program running in the terminal is interested in mouse events
+     * or false otherwise.
+     */
+    void setUsesMouse(bool usesMouse);
+  
+    /** See setUsesMouse() */
+    bool usesMouse() const;
+
+    /** 
+     * Shows a notification that a bell event has occurred in the terminal.
+     * TODO: More documentation here
+     */
+    void bell(const QString& message);
+
+signals:
+
+    /**
+     * Emitted when the user presses a key whilst the terminal widget has focus.
+     */
+    void keyPressedSignal(QKeyEvent *e);
+
+    /**
+     * Emitted when the user presses the suspend or resume flow control key combinations 
+     * 
+     * @param suspend true if the user pressed Ctrl+S (the suspend output key combination) or
+     * false if the user pressed Ctrl+Q (the resume output key combination)
+     */
+    void flowControlKeyPressed(bool suspend);
+    
+    /** 
+     * A mouse event occurred.
+     * @param button The mouse button (0 for left button, 1 for middle button, 2 for right button, 3 for release)
+     * @param column The character column where the event occurred
+     * @param line The character row where the event occurred
+     * @param eventType The type of event.  0 for a mouse press / release or 1 for mouse motion
+     */
+    void mouseSignal(int button, int column, int line, int eventType);
+    void changedFontMetricSignal(int height, int width);
+    void changedContentSizeSignal(int height, int width);
+
+    /** 
+     * Emitted when the user right clicks on the display, or right-clicks with the Shift
+     * key held down if usesMouse() is true.
+     *
+     * This can be used to display a context menu.
+     */
+    void configureRequest( SessionView*, int state, const QPoint& position );
+
+   void isBusySelecting(bool);
+   void sendStringToEmu(const char*);
+   
+   void tripleClicked( const QString& text );
+
+protected:
+    virtual bool event( QEvent * );
+
+    virtual void paintEvent( QPaintEvent * );
+
+    virtual void showEvent(QShowEvent*);
+    virtual void hideEvent(QHideEvent*);
+    virtual void resizeEvent(QResizeEvent*);
+
+    virtual void fontChange(const QFont &font);
+
+    virtual void keyPressEvent(QKeyEvent* event);
+    virtual void mouseDoubleClickEvent(QMouseEvent* ev);
+    virtual void mousePressEvent( QMouseEvent* );
+    virtual void mouseReleaseEvent( QMouseEvent* );
+    virtual void mouseMoveEvent( QMouseEvent* );
+    virtual void extendSelection( const QPoint& pos );
+    virtual void wheelEvent( QWheelEvent* );
+
+    virtual bool focusNextPrevChild( bool next );
+    
+    // drag and drop
+    virtual void dragEnterEvent(QDragEnterEvent* event);
+    virtual void dropEvent(QDropEvent* event);
+    void doDrag();
+    enum DragState { diNone, diPending, diDragging };
+
+    struct _dragInfo {
+      DragState       state;
+      QPoint          start;
+      QDrag           *dragObject;
+    } dragInfo;
+
+    virtual int charClass(quint16) const;
+
+    void clearImage();
+
+    void mouseTripleClickEvent(QMouseEvent* ev);
+
+    // reimplemented
+    virtual void inputMethodEvent ( QInputMethodEvent* event );
+    virtual QVariant inputMethodQuery( Qt::InputMethodQuery query ) const;
+
+protected slots:
+
+    void scrollBarPositionChanged(int value);
+    void blinkEvent();
+    void blinkCursorEvent();
+    
+    //Renables bell noises and visuals.  Used to disable further bells for a short period of time
+    //after emitting the first in a sequence of bell events.
+    void enableBell();
+
+private slots:
+
+    void swapColorTable();
+    void tripleClickTimeout();  // resets possibleTripleClick
+
+private:
+
+    // -- Drawing helpers --
+
+    // divides the part of the display specified by 'rect' into
+    // fragments according to their colors and styles and calls
+    // drawTextFragment() to draw the fragments 
+    void drawContents(QPainter &paint, const QRect &rect);
+    // draws a section of text, all the text in this section
+    // has a common color and style
+    void drawTextFragment(QPainter& painter, const QRect& rect, 
+                          const QString& text, const Character* style); 
+    // draws the background for a text fragment
+    // if useOpacitySetting is true then the color's alpha value will be set to
+    // the display's transparency (set with setOpacity()), otherwise the background
+    // will be drawn fully opaque
+    void drawBackground(QPainter& painter, const QRect& rect, const QColor& color,
+						bool useOpacitySetting);
+    // draws the cursor character
+    void drawCursor(QPainter& painter, const QRect& rect , const QColor& foregroundColor, 
+                                       const QColor& backgroundColor , bool& invertColors);
+    // draws the characters or line graphics in a text fragment
+    void drawCharacters(QPainter& painter, const QRect& rect,  const QString& text, 
+                                           const Character* style, bool invertCharacterColor);
+    // draws a string of line graphics
+	void drawLineCharString(QPainter& painter, int x, int y, 
+                            const QString& str, const Character* attributes);
+
+    // draws the preedit string for input methods
+    void drawInputMethodPreeditString(QPainter& painter , const QRect& rect);
+
+    // --
+
+    // maps an area in the character image to an area on the widget 
+    QRect imageToWidget(const QRect& imageArea) const;
+
+    // maps a point on the widget to the position ( ie. line and column ) 
+    // of the character at that point.
+    void getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const;
+
+    // the area where the preedit string for input methods will be draw
+    QRect preeditRect() const;
+
+    // shows a notification window in the middle of the widget indicating the terminal's
+    // current size in columns and lines
+    void showResizeNotification();
+
+    // scrolls the image by a number of lines.  
+    // 'lines' may be positive ( to scroll the image down ) 
+    // or negative ( to scroll the image up )
+    // 'region' is the part of the image to scroll - currently only
+    // the top, bottom and height of 'region' are taken into account,
+    // the left and right are ignored.
+    void scrollImage(int lines , const QRect& region);
+
+    void calcGeometry();
+    void propagateSize();
+    void updateImageSize();
+    void makeImage();
+    
+    void paintFilters(QPainter& painter);
+
+	// returns a region covering all of the areas of the widget which contain
+	// a hotspot
+	QRegion hotSpotRegion() const;
+
+	// returns the position of the cursor in columns and lines
+	QPoint cursorPosition() const;
+
+    // the window onto the terminal screen which this display
+    // is currently showing.  
+    QPointer<ScreenWindow> _screenWindow;
+
+    bool _allowBell;
+
+    QGridLayout* _gridLayout;
+
+    bool _fixedFont; // has fixed pitch
+    int  _fontHeight;     // height
+    int  _fontWidth;     // width
+    int  _fontAscent;     // ascend
+
+    int _leftMargin;    // offset
+    int _topMargin;    // offset
+
+    int _lines;      // the number of lines that can be displayed in the widget
+    int _columns;    // the number of columns that can be displayed in the widget
+    
+    int _usedLines;  // the number of lines that are actually being used, this will be less
+                    // than 'lines' if the character image provided with setImage() is smaller
+                    // than the maximum image size which can be displayed
+
+    int _usedColumns; // the number of columns that are actually being used, this will be less
+                     // than 'columns' if the character image provided with setImage() is smaller
+                     // than the maximum image size which can be displayed
+    
+    int _contentHeight;
+    int _contentWidth;
+    Character* _image; // [lines][columns]
+               // only the area [usedLines][usedColumns] in the image contains valid data
+
+    int _imageSize;
+    QVector<LineProperty> _lineProperties;
+
+    ColorEntry _colorTable[TABLE_COLORS];
+    uint _randomSeed;
+
+    bool _resizing;
+    bool _terminalSizeHint;
+    bool _terminalSizeStartup;
+    bool _bidiEnabled;
+    bool _mouseMarks;
+
+    QPoint  _iPntSel; // initial selection point
+    QPoint  _pntSel; // current selection point
+    QPoint  _tripleSelBegin; // help avoid flicker
+    int     _actSel; // selection state
+    bool    _wordSelectionMode;
+    bool    _lineSelectionMode;
+    bool    _preserveLineBreaks;
+    bool    _columnSelectionMode;
+
+    QClipboard*  _clipboard;
+    QScrollBar* _scrollBar;
+    ScrollBarPosition _scrollbarLocation;
+    QString     _wordCharacters;
+    int         _bellMode;
+
+    bool _blinking;   // hide text in paintEvent
+    bool _hasBlinker; // has characters to blink
+    bool _cursorBlinking;     // hide cursor in paintEvent
+    bool _hasBlinkingCursor;  // has blinking cursor enabled
+    bool _ctrlDrag;           // require Ctrl key for drag
+    TripleClickMode _tripleClickMode;
+    bool _isFixedSize; //Columns / lines are locked.
+    QTimer* _blinkTimer;  // active when hasBlinker
+    QTimer* _blinkCursorTimer;  // active when hasBlinkingCursor
+
+//    KMenu* _drop;
+    QString _dropText;
+    int _dndFileCount;
+
+    bool _possibleTripleClick;  // is set in mouseDoubleClickEvent and deleted
+                               // after QApplication::doubleClickInterval() delay
+
+
+    QLabel* _resizeWidget;
+    QTimer* _resizeTimer;
+
+	bool _flowControlWarningEnabled;
+
+    //widgets related to the warning message that appears when the user presses Ctrl+S to suspend
+    //terminal output - informing them what has happened and how to resume output
+    QLabel* _outputSuspendedLabel; 
+    	
+    uint _lineSpacing;
+
+    bool _colorsInverted; // true during visual bell
+
+    QSize _size;
+	
+    QRgb _blendColor;
+
+    // list of filters currently applied to the display.  used for links and
+    // search highlight
+    TerminalImageFilterChain* _filterChain;
+    QRect _mouseOverHotspotArea;
+
+    KeyboardCursorShape _cursorShape;
+
+    // custom cursor color.  if this is invalid then the foreground
+    // color of the character under the cursor is used
+    QColor _cursorColor;  
+
+
+    struct InputMethodData
+    {
+        QString preeditString;
+        QRect previousPreeditRect;
+    };
+    InputMethodData _inputMethodData;
+
+    static bool _antialiasText;   // do we antialias or not
+
+    //the delay in milliseconds between redrawing blinking text
+    static const int BLINK_DELAY = 500;
+	static const int DEFAULT_LEFT_MARGIN = 1;
+	static const int DEFAULT_TOP_MARGIN = 1;
+	
+    bool _readonly;
+
+public:
+    static void setTransparencyEnabled(bool enable)
+    {
+        HAVE_TRANSPARENCY = enable;
+    }
+};
+
+#endif // TERMINALDISPLAY_H
deleted file mode 100644
--- a/libqterminal/TerminalDisplay.cpp
+++ /dev/null
@@ -1,2743 +0,0 @@
-/*
-    This file is part of Konsole, a terminal emulator for KDE.
-    
-    Copyright (C) 2006-7 by Robert Knight <robertknight@gmail.com>
-    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
-    
-    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-    02110-1301  USA.
-*/
-
-// Own
-#include "TerminalDisplay.h"
-
-// Qt
-#include <QtGui/QApplication>
-#include <QtGui/QBoxLayout>
-#include <QtGui/QClipboard>
-#include <QtGui/QKeyEvent>
-#include <QtCore/QEvent>
-#include <QtCore/QTime>
-#include <QtCore/QFile>
-#include <QtGui/QGridLayout>
-#include <QtGui/QLabel>
-#include <QtGui/QLayout>
-#include <QtGui/QPainter>
-#include <QtGui/QPixmap>
-#include <QtGui/QScrollBar>
-#include <QtGui/QStyle>
-#include <QtCore>
-#include <QtGui>
-
-#include "Filter.h"
-#include "konsole_wcwidth.h"
-#include "ScreenWindow.h"
-#include "TerminalCharacterDecoder.h"
-
-#ifndef loc
-#define loc(X,Y) ((Y)*_columns+(X))
-#endif
-
-#define yMouseScroll 1
-
-#define REPCHAR   "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
-                  "abcdefgjijklmnopqrstuvwxyz" \
-                  "0123456789./+@"
-
-// scroll increment used when dragging selection at top/bottom of window.
-
-// static
-bool TerminalDisplay::_antialiasText = true;
-bool TerminalDisplay::HAVE_TRANSPARENCY = false;
-
-/* ------------------------------------------------------------------------- */
-/*                                                                           */
-/*                                Colors                                     */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb)
-
-   Code        0       1       2       3       4       5       6       7
-   ----------- ------- ------- ------- ------- ------- ------- ------- -------
-   ANSI  (bgr) Black   Red     Green   Yellow  Blue    Magenta Cyan    White
-   IBMPC (rgb) Black   Blue    Green   Cyan    Red     Magenta Yellow  White
-*/
-
-ScreenWindow* TerminalDisplay::screenWindow() const
-{
-    return _screenWindow;
-}
-void TerminalDisplay::setScreenWindow(ScreenWindow* window)
-{
-    // disconnect existing screen window if any
-    if ( _screenWindow )
-    {
-        disconnect( _screenWindow , 0 , this , 0 );
-    }
-
-    _screenWindow = window;
-
-    if ( window )
-    {
-//#warning "The order here is not specified - does it matter whether updateImage or updateLineProperties comes first?"
-        connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties()) );
-        connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage()) );
-	window->setWindowLines(_lines);
-    }
-}
-
-const ColorEntry* TerminalDisplay::colorTable() const
-{
-  return _colorTable;
-}
-
-void TerminalDisplay::setColorTable(const ColorEntry table[])
-{
-  for (int i = 0; i < TABLE_COLORS; i++)
-      _colorTable[i] = table[i];
-
-  QPalette p = palette();
-  p.setColor( backgroundRole(), _colorTable[DEFAULT_BACK_COLOR].color );
-  setPalette( p );
-
-  // Avoid propagating the palette change to the scroll bar 
-  _scrollBar->setPalette( QApplication::palette() );  
-
-  update();
-}
-
-/* ------------------------------------------------------------------------- */
-/*                                                                           */
-/*                                   Font                                    */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-/*
-   The VT100 has 32 special graphical characters. The usual vt100 extended
-   xterm fonts have these at 0x00..0x1f.
-
-   QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals
-   come in here as proper unicode characters.
-
-   We treat non-iso10646 fonts as VT100 extended and do the requiered mapping
-   from unicode to 0x00..0x1f. The remaining translation is then left to the
-   QCodec.
-*/
-
-static inline bool isLineChar(quint16 c) { return ((c & 0xFF80) == 0x2500);}
-static inline bool isLineCharString(const QString& string)
-{
-		return (string.length() > 0) && (isLineChar(string.at(0).unicode()));
-}
-						
-
-// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.
-
-unsigned short vt100_graphics[32] =
-{ // 0/8     1/9    2/10    3/11    4/12    5/13    6/14    7/15
-  0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0,
-  0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,
-  0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534,
-  0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7
-};
-
-void TerminalDisplay::fontChange(const QFont&)
-{
-  QFontMetrics fm(font());
-  _fontHeight = fm.height() + _lineSpacing;
-
-
-  // waba TerminalDisplay 1.123:
-  // "Base character width on widest ASCII character. This prevents too wide
-  //  characters in the presence of double wide (e.g. Japanese) characters."
-  // Get the width from representative normal width characters
-  _fontWidth = qRound((double)fm.width(REPCHAR)/(double)strlen(REPCHAR));
-
-  _fixedFont = true;
-
-  int fw = fm.width(REPCHAR[0]);
-  for(unsigned int i=1; i< strlen(REPCHAR); i++)
-  {
-    if (fw != fm.width(REPCHAR[i]))
-    {
-      _fixedFont = false;
-      break;
-    }
-  }
-
-  if (_fontWidth < 1)
-    _fontWidth=1;
-
-  _fontAscent = fm.ascent();
-
-  emit changedFontMetricSignal( _fontHeight, _fontWidth );
-  propagateSize();
-  update();
-}
-
-void TerminalDisplay::setVTFont(const QFont& f)
-{
-  QFont font = f;
-
-  QFontMetrics metrics(font);
-
-  if ( metrics.height() < height() && metrics.maxWidth() < width() )
-  {
-    // hint that text should be drawn without anti-aliasing.  
-    // depending on the user's font configuration, this may not be respected
-    if (!_antialiasText)
-        font.setStyleStrategy( QFont::NoAntialias );
- 
-    // experimental optimization.  Konsole assumes that the terminal is using a 
-    // mono-spaced font, in which case kerning information should have an effect.
-    // Disabling kerning saves some computation when rendering text. 
-    font.setKerning(false);
-
-    QWidget::setFont(font);
-    fontChange(font);
-  }
-}
-
-void TerminalDisplay::setFont(const QFont &)
-{
-  // ignore font change request if not coming from konsole itself
-}
-
-/* ------------------------------------------------------------------------- */
-/*                                                                           */
-/*                         Constructor / Destructor                          */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-TerminalDisplay::TerminalDisplay(QWidget *parent)
-:QWidget(parent)
-,_screenWindow(0)
-,_allowBell(true)
-,_gridLayout(0)
-,_fontHeight(1)
-,_fontWidth(1)
-,_fontAscent(1)
-,_lines(1)
-,_columns(1)
-,_usedLines(1)
-,_usedColumns(1)
-,_contentHeight(1)
-,_contentWidth(1)
-,_image(0)
-,_randomSeed(0)
-,_resizing(false)
-,_terminalSizeHint(false)
-,_terminalSizeStartup(true)
-,_bidiEnabled(false)
-,_actSel(0)
-,_wordSelectionMode(false)
-,_lineSelectionMode(false)
-,_preserveLineBreaks(false)
-,_columnSelectionMode(false)
-,_scrollbarLocation(NoScrollBar)
-,_wordCharacters(":@-./_~")
-,_bellMode(SystemBeepBell)
-,_blinking(false)
-,_cursorBlinking(false)
-,_hasBlinkingCursor(false)
-,_ctrlDrag(false)
-,_tripleClickMode(SelectWholeLine)
-,_isFixedSize(false)
-,_possibleTripleClick(false)
-,_resizeWidget(0)
-,_resizeTimer(0)
-,_flowControlWarningEnabled(false)
-,_outputSuspendedLabel(0)
-,_lineSpacing(0)
-,_colorsInverted(false)
-,_blendColor(qRgba(0,0,0,0xff))
-,_filterChain(new TerminalImageFilterChain())
-,_cursorShape(BlockCursor)
-,_readonly(false)
-{
-  // terminal applications are not designed with Right-To-Left in mind,
-  // so the layout is forced to Left-To-Right
-  setLayoutDirection(Qt::LeftToRight);
-
-  // The offsets are not yet calculated.
-  // Do not calculate these too often to be more smoothly when resizing
-  // konsole in opaque mode.
-  _topMargin = DEFAULT_TOP_MARGIN;
-  _leftMargin = DEFAULT_LEFT_MARGIN;
-
-  // create scroll bar for scrolling output up and down
-  // set the scroll bar's slider to occupy the whole area of the scroll bar initially
-  _scrollBar = new QScrollBar(this);
-  setScroll(0,0); 
-  _scrollBar->setCursor( Qt::ArrowCursor );
-  connect(_scrollBar, SIGNAL(valueChanged(int)), this, 
-  					  SLOT(scrollBarPositionChanged(int)));
-
-  // setup timers for blinking cursor and text
-  _blinkTimer   = new QTimer(this);
-  connect(_blinkTimer, SIGNAL(timeout()), this, SLOT(blinkEvent()));
-  _blinkCursorTimer   = new QTimer(this);
-  connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent()));
-
-//  QCursor::setAutoHideCursor( this, true );
-  
-  setUsesMouse(true);
-  setColorTable(base_color_table);
-  setMouseTracking(true);
-
-  // Enable drag and drop 
-  setAcceptDrops(true); // attempt
-  dragInfo.state = diNone;
-
-  setFocusPolicy( Qt::WheelFocus );
-
-  // enable input method support
-  setAttribute(Qt::WA_InputMethodEnabled, true);
-
-  // this is an important optimization, it tells Qt
-  // that TerminalDisplay will handle repainting its entire area.
-  setAttribute(Qt::WA_OpaquePaintEvent);
-
-  _gridLayout = new QGridLayout(this);
-  _gridLayout->setMargin(0);
-
-  setLayout( _gridLayout ); 
-
-  //set up a warning message when the user presses Ctrl+S to avoid confusion
-  connect( this,SIGNAL(flowControlKeyPressed(bool)),this,SLOT(outputSuspended(bool)) );
-}
-
-TerminalDisplay::~TerminalDisplay()
-{
-  qApp->removeEventFilter( this );
-  
-  delete[] _image;
-
-  delete _gridLayout;
-  delete _outputSuspendedLabel;
-  delete _filterChain;
-}
-
-/* ------------------------------------------------------------------------- */
-/*                                                                           */
-/*                             Display Operations                            */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-/**
- A table for emulating the simple (single width) unicode drawing chars.
- It represents the 250x - 257x glyphs. If it's zero, we can't use it.
- if it's not, it's encoded as follows: imagine a 5x5 grid where the points are numbered
- 0 to 24 left to top, top to bottom. Each point is represented by the corresponding bit.
-
- Then, the pixels basically have the following interpretation:
- _|||_
- -...-
- -...-
- -...-
- _|||_
-
-where _ = none
-      | = vertical line.
-      - = horizontal line.
- */
-
-
-enum LineEncode
-{
-    TopL  = (1<<1),
-    TopC  = (1<<2),
-    TopR  = (1<<3),
-
-    LeftT = (1<<5),
-    Int11 = (1<<6),
-    Int12 = (1<<7),
-    Int13 = (1<<8),
-    RightT = (1<<9),
-
-    LeftC = (1<<10),
-    Int21 = (1<<11),
-    Int22 = (1<<12),
-    Int23 = (1<<13),
-    RightC = (1<<14),
-
-    LeftB = (1<<15),
-    Int31 = (1<<16),
-    Int32 = (1<<17),
-    Int33 = (1<<18),
-    RightB = (1<<19),
-
-    BotL  = (1<<21),
-    BotC  = (1<<22),
-    BotR  = (1<<23)
-};
-
-#include "LineFont.h"
-
-static void drawLineChar(QPainter& paint, int x, int y, int w, int h, uchar code)
-{
-    //Calculate cell midpoints, end points.
-    int cx = x + w/2;
-    int cy = y + h/2;
-    int ex = x + w - 1;
-    int ey = y + h - 1;
-
-    quint32 toDraw = LineChars[code];
-
-    //Top _lines:
-    if (toDraw & TopL)
-        paint.drawLine(cx-1, y, cx-1, cy-2);
-    if (toDraw & TopC)
-        paint.drawLine(cx, y, cx, cy-2);
-    if (toDraw & TopR)
-        paint.drawLine(cx+1, y, cx+1, cy-2);
-
-    //Bot _lines:
-    if (toDraw & BotL)
-        paint.drawLine(cx-1, cy+2, cx-1, ey);
-    if (toDraw & BotC)
-        paint.drawLine(cx, cy+2, cx, ey);
-    if (toDraw & BotR)
-        paint.drawLine(cx+1, cy+2, cx+1, ey);
-
-    //Left _lines:
-    if (toDraw & LeftT)
-        paint.drawLine(x, cy-1, cx-2, cy-1);
-    if (toDraw & LeftC)
-        paint.drawLine(x, cy, cx-2, cy);
-    if (toDraw & LeftB)
-        paint.drawLine(x, cy+1, cx-2, cy+1);
-
-    //Right _lines:
-    if (toDraw & RightT)
-        paint.drawLine(cx+2, cy-1, ex, cy-1);
-    if (toDraw & RightC)
-        paint.drawLine(cx+2, cy, ex, cy);
-    if (toDraw & RightB)
-        paint.drawLine(cx+2, cy+1, ex, cy+1);
-
-    //Intersection points.
-    if (toDraw & Int11)
-        paint.drawPoint(cx-1, cy-1);
-    if (toDraw & Int12)
-        paint.drawPoint(cx, cy-1);
-    if (toDraw & Int13)
-        paint.drawPoint(cx+1, cy-1);
-
-    if (toDraw & Int21)
-        paint.drawPoint(cx-1, cy);
-    if (toDraw & Int22)
-        paint.drawPoint(cx, cy);
-    if (toDraw & Int23)
-        paint.drawPoint(cx+1, cy);
-
-    if (toDraw & Int31)
-        paint.drawPoint(cx-1, cy+1);
-    if (toDraw & Int32)
-        paint.drawPoint(cx, cy+1);
-    if (toDraw & Int33)
-        paint.drawPoint(cx+1, cy+1);
-
-}
-
-void TerminalDisplay::drawLineCharString(	QPainter& painter, int x, int y, const QString& str, 
-									const Character* attributes)
-{
-		const QPen& currentPen = painter.pen();
-		
-		if ( attributes->rendition & RE_BOLD )
-		{
-			QPen boldPen(currentPen);
-			boldPen.setWidth(3);
-			painter.setPen( boldPen );
-		}	
-		
-		for (int i=0 ; i < str.length(); i++)
-		{
-			uchar code = str[i].cell();
-        	if (LineChars[code])
-            	drawLineChar(painter, x + (_fontWidth*i), y, _fontWidth, _fontHeight, code);
-		}
-
-		painter.setPen( currentPen );
-}
-
-void TerminalDisplay::setKeyboardCursorShape(KeyboardCursorShape shape)
-{
-    _cursorShape = shape;
-}
-TerminalDisplay::KeyboardCursorShape TerminalDisplay::keyboardCursorShape() const
-{
-    return _cursorShape;
-}
-void TerminalDisplay::setKeyboardCursorColor(bool useForegroundColor, const QColor& color)
-{
-    if (useForegroundColor)
-        _cursorColor = QColor(); // an invalid color means that
-                                 // the foreground color of the
-                                 // current character should
-                                 // be used
-
-    else
-        _cursorColor = color;
-}
-QColor TerminalDisplay::keyboardCursorColor() const
-{
-    return _cursorColor;
-}
-
-void TerminalDisplay::setOpacity(qreal opacity)
-{
-    QColor color(_blendColor);
-    color.setAlphaF(opacity);
-
-    // enable automatic background filling to prevent the display
-    // flickering if there is no transparency
-    if ( color.alpha() == 255 ) 
-    {
-        setAutoFillBackground(true);
-    }
-    else
-    {
-        setAutoFillBackground(false);
-    }
-
-    _blendColor = color.rgba();
-}
-
-void TerminalDisplay::drawBackground(QPainter& painter, const QRect& rect, const QColor& backgroundColor, bool useOpacitySetting )
-{
-        // the area of the widget showing the contents of the terminal display is drawn
-        // using the background color from the color scheme set with setColorTable()
-        //
-        // the area of the widget behind the scroll-bar is drawn using the background
-        // brush from the scroll-bar's palette, to give the effect of the scroll-bar
-        // being outside of the terminal display and visual consistency with other KDE
-        // applications.  
-        //
-        QRect scrollBarArea = _scrollBar->isVisible() ? 
-                                    rect.intersected(_scrollBar->geometry()) :
-                                    QRect();
-        QRegion contentsRegion = QRegion(rect).subtracted(scrollBarArea);
-        QRect contentsRect = contentsRegion.boundingRect();
-
-        if ( HAVE_TRANSPARENCY && qAlpha(_blendColor) < 0xff && useOpacitySetting ) 
-        {
-            QColor color(backgroundColor);
-            color.setAlpha(qAlpha(_blendColor));
-
-            painter.save();
-            painter.setCompositionMode(QPainter::CompositionMode_Source);
-            painter.fillRect(contentsRect, color);
-            painter.restore();
-        } 
-        else {
-	    painter.fillRect(contentsRect, backgroundColor);
-	}
-
-        painter.fillRect(scrollBarArea,_scrollBar->palette().background());
-}
-
-void TerminalDisplay::drawCursor(QPainter& painter, 
-                                 const QRect& rect,
-                                 const QColor& foregroundColor,
-                                 const QColor& /*backgroundColor*/,
-                                 bool& invertCharacterColor)
-{
-    QRect cursorRect = rect;
-    cursorRect.setHeight(_fontHeight - _lineSpacing - 1);
-    
-    if (!_cursorBlinking)
-    {
-       if ( _cursorColor.isValid() )
-           painter.setPen(_cursorColor);
-       else {
-    	    painter.setPen(foregroundColor);
-	}
-
-       if ( _cursorShape == BlockCursor )
-       {
-            // draw the cursor outline, adjusting the area so that
-            // it is draw entirely inside 'rect'
-            int penWidth = qMax(1,painter.pen().width());
-
-            painter.drawRect(cursorRect.adjusted(penWidth/2,
-                                                 penWidth/2,
-                                                 - penWidth/2 - penWidth%2,
-                                                 - penWidth/2 - penWidth%2));
-            if ( hasFocus() )
-            {
-                painter.fillRect(cursorRect, _cursorColor.isValid() ? _cursorColor : foregroundColor);
-	    
-                if ( !_cursorColor.isValid() )
-                {
-                    // invert the colour used to draw the text to ensure that the character at
-                    // the cursor position is readable
-                    invertCharacterColor = true;
-                }
-            }
-       }
-       else if ( _cursorShape == UnderlineCursor )
-            painter.drawLine(cursorRect.left(),
-                             cursorRect.bottom(),
-                             cursorRect.right(),
-                             cursorRect.bottom());
-       else if ( _cursorShape == IBeamCursor )
-            painter.drawLine(cursorRect.left(),
-                             cursorRect.top(),
-                             cursorRect.left(),
-                             cursorRect.bottom());
-    
-    }
-}
-
-void TerminalDisplay::drawCharacters(QPainter& painter,
-                                     const QRect& rect,
-                                     const QString& text,
-                                     const Character* style,
-                                     bool invertCharacterColor)
-{
-    // don't draw text which is currently blinking
-    if ( _blinking && (style->rendition & RE_BLINK) )
-            return;
-   
-    // setup bold and underline
-    bool useBold = style->rendition & RE_BOLD || style->isBold(_colorTable) || font().bold();
-    bool useUnderline = style->rendition & RE_UNDERLINE || font().underline();
-
-    QFont font = painter.font();
-    if (    font.bold() != useBold 
-         || font.underline() != useUnderline )
-    {
-       font.setBold(useBold);
-       font.setUnderline(useUnderline);
-       painter.setFont(font);
-    }
-
-    const CharacterColor& textColor = ( invertCharacterColor ? style->backgroundColor : style->foregroundColor );
-    const QColor color = textColor.color(_colorTable);
-
-    QPen pen = painter.pen();
-    if ( pen.color() != color )
-    {
-        pen.setColor(color);
-        painter.setPen(color);
-    }
-    // draw text
-    if ( isLineCharString(text) ) {
-	  	drawLineCharString(painter,rect.x(),rect.y(),text,style);
-    }
-    else
-	{
-		// the drawText(rect,flags,string) overload is used here with null flags
-		// instead of drawText(rect,string) because the (rect,string) overload causes 
-		// the application's default layout direction to be used instead of 
-		// the widget-specific layout direction, which should always be
-		// Qt::LeftToRight for this widget
-        painter.drawText(rect,0,text);
-	}
-}
-
-void TerminalDisplay::drawTextFragment(QPainter& painter , 
-                                       const QRect& rect,
-                                       const QString& text, 
-                                       const Character* style)
-{
-    painter.save();
-
-    // setup painter 
-    const QColor foregroundColor = style->foregroundColor.color(_colorTable);
-    const QColor backgroundColor = style->backgroundColor.color(_colorTable);
-    
-    // draw background if different from the display's background color
-    if ( backgroundColor != palette().background().color() )
-        drawBackground(painter,rect,backgroundColor, false /* do not use transparency */);
-
-    // draw cursor shape if the current character is the cursor
-    // this may alter the foreground and background colors
-    bool invertCharacterColor = false;
-
-    if ( style->rendition & RE_CURSOR )
-        drawCursor(painter,rect,foregroundColor,backgroundColor,invertCharacterColor);
-    // draw text
-    drawCharacters(painter,rect,text,style,invertCharacterColor);
-
-    painter.restore();
-}
-
-void TerminalDisplay::setRandomSeed(uint randomSeed) { _randomSeed = randomSeed; }
-uint TerminalDisplay::randomSeed() const { return _randomSeed; }
-
-#if 0
-/*!
-    Set XIM Position
-*/
-void TerminalDisplay::setCursorPos(const int curx, const int cury)
-{
-    QPoint tL  = contentsRect().topLeft();
-    int    tLx = tL.x();
-    int    tLy = tL.y();
-
-    int xpos, ypos;
-    ypos = _topMargin + tLy + _fontHeight*(cury-1) + _fontAscent;
-    xpos = _leftMargin + tLx + _fontWidth*curx;
-    //setMicroFocusHint(xpos, ypos, 0, _fontHeight); //### ???
-    // fprintf(stderr, "x/y = %d/%d\txpos/ypos = %d/%d\n", curx, cury, xpos, ypos);
-    _cursorLine = cury;
-    _cursorCol = curx;
-}
-#endif
-
-// scrolls the image by 'lines', down if lines > 0 or up otherwise.
-//
-// the terminal emulation keeps track of the scrolling of the character 
-// image as it receives input, and when the view is updated, it calls scrollImage() 
-// with the final scroll amount.  this improves performance because scrolling the 
-// display is much cheaper than re-rendering all the text for the 
-// part of the image which has moved up or down.  
-// Instead only new lines have to be drawn
-//
-// note:  it is important that the area of the display which is 
-// scrolled aligns properly with the character grid - 
-// which has a top left point at (_leftMargin,_topMargin) , 
-// a cell width of _fontWidth and a cell height of _fontHeight).    
-void TerminalDisplay::scrollImage(int lines , const QRect& screenWindowRegion)
-{
-	// if the flow control warning is enabled this will interfere with the 
-	// scrolling optimisations and cause artifacts.  the simple solution here
-	// is to just disable the optimisation whilst it is visible
-	if ( _outputSuspendedLabel && _outputSuspendedLabel->isVisible() ) {
-		return;
-	}
-
-    // constrain the region to the display
-    // the bottom of the region is capped to the number of lines in the display's
-    // internal image - 2, so that the height of 'region' is strictly less
-    // than the height of the internal image.
-    QRect region = screenWindowRegion;
-    region.setBottom( qMin(region.bottom(),this->_lines-2) ); 
-
-    if (    lines == 0 
-         || _image == 0
-         || !region.isValid() 
-         || (region.top() + abs(lines)) >= region.bottom() 
-         || this->_lines <= region.height() ) return;
-
-    QRect scrollRect;
-
-    void* firstCharPos = &_image[ region.top() * this->_columns ];
-    void* lastCharPos = &_image[ (region.top() + abs(lines)) * this->_columns ];
-
-    int top = _topMargin + (region.top() * _fontHeight);
-    int linesToMove = region.height() - abs(lines);
-    int bytesToMove = linesToMove * 
-                      this->_columns *
-                      sizeof(Character);
-
-    Q_ASSERT( linesToMove > 0 );
-    Q_ASSERT( bytesToMove > 0 );
-
-    //scroll internal image
-    if ( lines > 0 )
-    {
-        // check that the memory areas that we are going to move are valid
-        Q_ASSERT( (char*)lastCharPos + bytesToMove < 
-                  (char*)(_image + (this->_lines * this->_columns)) );
-        
-        Q_ASSERT( (lines*this->_columns) < _imageSize ); 
-
-        //scroll internal image down
-        memmove( firstCharPos , lastCharPos , bytesToMove ); 
-      
-        //set region of display to scroll, making sure that
-        //the region aligns correctly to the character grid 
-        scrollRect = QRect( _leftMargin , top, 
-                            this->_usedColumns * _fontWidth , 
-                            linesToMove * _fontHeight );
-    }
-    else
-    {
-        // check that the memory areas that we are going to move are valid
-        Q_ASSERT( (char*)firstCharPos + bytesToMove < 
-                  (char*)(_image + (this->_lines * this->_columns)) );
-
-        //scroll internal image up
-        memmove( lastCharPos , firstCharPos , bytesToMove ); 
-     
-        //set region of the display to scroll, making sure that
-        //the region aligns correctly to the character grid
-        QPoint topPoint( _leftMargin , top + abs(lines)*_fontHeight );
-
-        scrollRect = QRect( topPoint ,
-                     QSize( this->_usedColumns*_fontWidth , 
-                            linesToMove * _fontHeight ));
-    }
-
-    //scroll the display vertically to match internal _image
-    scroll( 0 , _fontHeight * (-lines) , scrollRect );
-}
-
-QRegion TerminalDisplay::hotSpotRegion() const 
-{
-	QRegion region;
-	foreach( Filter::HotSpot* hotSpot , _filterChain->hotSpots() )
-	{
-		QRect rect;
-		rect.setLeft(hotSpot->startColumn());
-		rect.setTop(hotSpot->startLine());
-		rect.setRight(hotSpot->endColumn());
-		rect.setBottom(hotSpot->endLine());
-
-		region |= imageToWidget(rect); 
-	}
-	return region;
-}
-
-void TerminalDisplay::processFilters() 
-{
-	if (!_screenWindow)
-		return;
-
-	QRegion preUpdateHotSpots = hotSpotRegion();
-
-	// use _screenWindow->getImage() here rather than _image because
-	// other classes may call processFilters() when this display's
-	// ScreenWindow emits a scrolled() signal - which will happen before
-	// updateImage() is called on the display and therefore _image is 
-	// out of date at this point
-	_filterChain->setImage( _screenWindow->getImage(),
-							_screenWindow->windowLines(),
-							_screenWindow->windowColumns(),
-							_screenWindow->getLineProperties() );
-    _filterChain->process();
-
-	QRegion postUpdateHotSpots = hotSpotRegion();
-
-	update( preUpdateHotSpots | postUpdateHotSpots );
-}
-
-void TerminalDisplay::updateImage() 
-{
-  if ( !_screenWindow )
-      return;
-
-  // optimization - scroll the existing image where possible and 
-  // avoid expensive text drawing for parts of the image that 
-  // can simply be moved up or down
-  scrollImage( _screenWindow->scrollCount() ,
-               _screenWindow->scrollRegion() );
-  _screenWindow->resetScrollCount();
-
-  Character* const newimg = _screenWindow->getImage();
-  int lines = _screenWindow->windowLines();
-  int columns = _screenWindow->windowColumns();
-
-  setScroll( _screenWindow->currentLine() , _screenWindow->lineCount() );
-
-  if (!_image)
-     updateImageSize(); // Create _image
-
-  Q_ASSERT( this->_usedLines <= this->_lines );
-  Q_ASSERT( this->_usedColumns <= this->_columns );
-
-  int y,x,len;
-
-  QPoint tL  = contentsRect().topLeft();
-
-  int    tLx = tL.x();
-  int    tLy = tL.y();
-  _hasBlinker = false;
-
-  CharacterColor cf;       // undefined
-  CharacterColor _clipboard;       // undefined
-  int cr  = -1;   // undefined
-
-  const int linesToUpdate = qMin(this->_lines, qMax(0,lines  ));
-  const int columnsToUpdate = qMin(this->_columns,qMax(0,columns));
-
-  QChar *disstrU = new QChar[columnsToUpdate];
-  char *dirtyMask = new char[columnsToUpdate+2]; 
-  QRegion dirtyRegion;
-
-  // debugging variable, this records the number of lines that are found to
-  // be 'dirty' ( ie. have changed from the old _image to the new _image ) and
-  // which therefore need to be repainted
-  int dirtyLineCount = 0;
-
-  for (y = 0; y < linesToUpdate; y++)
-  {
-    const Character*       currentLine = &_image[y*this->_columns];
-    const Character* const newLine = &newimg[y*columns];
-
-    bool updateLine = false;
-    
-    // The dirty mask indicates which characters need repainting. We also
-    // mark surrounding neighbours dirty, in case the character exceeds
-    // its cell boundaries
-    memset(dirtyMask, 0, columnsToUpdate+2);
-   
-    for( x = 0 ; x < columnsToUpdate ; x++)
-    {
-        if ( newLine[x] != currentLine[x] ) 
-        {
-            dirtyMask[x] = true;
-        }
-    }
-
-    if (!_resizing) // not while _resizing, we're expecting a paintEvent
-    for (x = 0; x < columnsToUpdate; x++)
-    {
-      _hasBlinker |= (newLine[x].rendition & RE_BLINK);
-    
-      // Start drawing if this character or the next one differs.
-      // We also take the next one into account to handle the situation
-      // where characters exceed their cell width.
-      if (dirtyMask[x])
-      {
-        quint16 c = newLine[x+0].character;
-        if ( !c )
-            continue;
-        int p = 0;
-        disstrU[p++] = c; //fontMap(c);
-        bool lineDraw = isLineChar(c);
-        bool doubleWidth = (x+1 == columnsToUpdate) ? false : (newLine[x+1].character == 0);
-        cr = newLine[x].rendition;
-        _clipboard = newLine[x].backgroundColor;
-        if (newLine[x].foregroundColor != cf) cf = newLine[x].foregroundColor;
-        int lln = columnsToUpdate - x;
-        for (len = 1; len < lln; len++)
-        {
-            const Character& ch = newLine[x+len];
-
-            if (!ch.character)
-                continue; // Skip trailing part of multi-col chars.
-
-			bool nextIsDoubleWidth = (x+len+1 == columnsToUpdate) ? false : (newLine[x+len+1].character == 0);
-
-            if (  ch.foregroundColor != cf || 
-                  ch.backgroundColor != _clipboard || 
-                  ch.rendition != cr ||
-                  !dirtyMask[x+len] || 
-                  isLineChar(c) != lineDraw || 
-                  nextIsDoubleWidth != doubleWidth )
-            break;
-
-          disstrU[p++] = c; //fontMap(c);
-        }
-
-        QString unistr(disstrU, p);
-
-        bool saveFixedFont = _fixedFont;
-        if (lineDraw)
-           _fixedFont = false;
-        if (doubleWidth)
-           _fixedFont = false;
-
-		updateLine = true;
-
-		_fixedFont = saveFixedFont;
-        x += len - 1;
-      }
-      
-    }
-
-	//both the top and bottom halves of double height _lines must always be redrawn
-	//although both top and bottom halves contain the same characters, only 
-    //the top one is actually 
-	//drawn.
-    if (_lineProperties.count() > y)
-        updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT);
-
-    // if the characters on the line are different in the old and the new _image
-    // then this line must be repainted.    
-    if (updateLine)
-    {
-        dirtyLineCount++;
-
-        // add the area occupied by this line to the region which needs to be
-        // repainted
-        QRect dirtyRect = QRect( _leftMargin+tLx , 
-                                 _topMargin+tLy+_fontHeight*y , 
-                                 _fontWidth * columnsToUpdate , 
-                                 _fontHeight ); 	
-
-        dirtyRegion |= dirtyRect;
-    }
-
-    // replace the line of characters in the old _image with the 
-    // current line of the new _image 
-    memcpy((void*)currentLine,(const void*)newLine,columnsToUpdate*sizeof(Character));
-  }
-
-  // if the new _image is smaller than the previous _image, then ensure that the area
-  // outside the new _image is cleared 
-  if ( linesToUpdate < _usedLines )
-  {
-    dirtyRegion |= QRect(   _leftMargin+tLx , 
-                            _topMargin+tLy+_fontHeight*linesToUpdate , 
-                            _fontWidth * this->_columns , 
-                            _fontHeight * (_usedLines-linesToUpdate) );
-  }
-  _usedLines = linesToUpdate;
-  
-  if ( columnsToUpdate < _usedColumns )
-  {
-    dirtyRegion |= QRect(   _leftMargin+tLx+columnsToUpdate*_fontWidth , 
-                            _topMargin+tLy , 
-                            _fontWidth * (_usedColumns-columnsToUpdate) , 
-                            _fontHeight * this->_lines );
-  }
-  _usedColumns = columnsToUpdate;
-
-  dirtyRegion |= _inputMethodData.previousPreeditRect;
-
-  // update the parts of the display which have changed
-  update(dirtyRegion);
-
-  if ( _hasBlinker && !_blinkTimer->isActive()) _blinkTimer->start( BLINK_DELAY ); 
-  if (!_hasBlinker && _blinkTimer->isActive()) { _blinkTimer->stop(); _blinking = false; }
-  delete[] dirtyMask;
-  delete[] disstrU;
-
-}
-
-void TerminalDisplay::showResizeNotification()
-{
-  if (_terminalSizeHint && isVisible())
-  {
-     if (_terminalSizeStartup) {
-       		_terminalSizeStartup=false;
-       return;
-     }
-     if (!_resizeWidget)
-     {
-        _resizeWidget = new QLabel(("Size: XXX x XXX"), this);
-        _resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width(("Size: XXX x XXX")));
-        _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height());
-		_resizeWidget->setAlignment(Qt::AlignCenter);
-
-        _resizeWidget->setStyleSheet("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)");
-
-		_resizeTimer = new QTimer(this);
-		_resizeTimer->setSingleShot(true);
-        connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide()));
-
-     }
-     QString sizeStr;
-     sizeStr.sprintf("Size: %d x %d", _columns, _lines);
-     _resizeWidget->setText(sizeStr);
-     _resizeWidget->move((width()-_resizeWidget->width())/2,
-                         (height()-_resizeWidget->height())/2+20);
-     _resizeWidget->show();
-     _resizeTimer->start(1000);
-  }
-}
-
-void TerminalDisplay::setBlinkingCursor(bool blink)
-{
-  _hasBlinkingCursor=blink;
-  
-  if (blink && !_blinkCursorTimer->isActive()) 
-      _blinkCursorTimer->start(BLINK_DELAY);
-  
-  if (!blink && _blinkCursorTimer->isActive()) 
-  {
-    _blinkCursorTimer->stop();
-    if (_cursorBlinking)
-      blinkCursorEvent();
-    else
-      _cursorBlinking = false;
-  }
-}
-
-void TerminalDisplay::paintEvent( QPaintEvent* pe )
-{
-//qDebug("%s %d paintEvent", __FILE__, __LINE__);
-  QPainter paint(this);
-//qDebug("%s %d paintEvent %d %d", __FILE__, __LINE__, paint.window().top(), paint.window().right());
-
-  foreach (QRect rect, (pe->region() & contentsRect()).rects())
-  {
-    drawBackground(paint,rect,palette().background().color(),	true /* use opacity setting */);
-    drawContents(paint, rect);    
-  }
-//    drawBackground(paint,contentsRect(),palette().background().color(),	true /* use opacity setting */);
-//    drawContents(paint, contentsRect());    
-  drawInputMethodPreeditString(paint,preeditRect());
-  paintFilters(paint);
-
-  paint.end();
-}
-
-QPoint TerminalDisplay::cursorPosition() const
-{
-	if (_screenWindow)
-		return _screenWindow->cursorPosition();
-	else
-		return QPoint(0,0);
-}
-
-QRect TerminalDisplay::preeditRect() const
-{
-    const int preeditLength = string_width(_inputMethodData.preeditString);
-
-    if ( preeditLength == 0 )
-        return QRect();
-
-    return QRect(_leftMargin + _fontWidth*cursorPosition().x(),
-                 _topMargin + _fontHeight*cursorPosition().y(),
-                 _fontWidth*preeditLength,
-                 _fontHeight);
-}   
-
-void TerminalDisplay::drawInputMethodPreeditString(QPainter& painter , const QRect& rect)
-{
-    if ( _inputMethodData.preeditString.isEmpty() ) {
-        return;
-    }
-    const QPoint cursorPos = cursorPosition(); 
-
-    bool invertColors = false;
-    const QColor background = _colorTable[DEFAULT_BACK_COLOR].color;
-    const QColor foreground = _colorTable[DEFAULT_FORE_COLOR].color;
-    const Character* style = &_image[loc(cursorPos.x(),cursorPos.y())];
-
-    drawBackground(painter,rect,background,true);
-    drawCursor(painter,rect,foreground,background,invertColors);
-    drawCharacters(painter,rect,_inputMethodData.preeditString,style,invertColors);
-
-    _inputMethodData.previousPreeditRect = rect; 
-}
-
-FilterChain* TerminalDisplay::filterChain() const
-{
-    return _filterChain;
-}
-
-void TerminalDisplay::paintFilters(QPainter& painter)
-{
-//qDebug("%s %d paintFilters", __FILE__, __LINE__);
-
-    // get color of character under mouse and use it to draw
-    // lines for filters
-    QPoint cursorPos = mapFromGlobal(QCursor::pos());
-    int cursorLine;
-    int cursorColumn;
-    getCharacterPosition( cursorPos , cursorLine , cursorColumn );
-    Character cursorCharacter = _image[loc(cursorColumn,cursorLine)];
-
-    painter.setPen( QPen(cursorCharacter.foregroundColor.color(colorTable())) );
-
-    // iterate over hotspots identified by the display's currently active filters 
-    // and draw appropriate visuals to indicate the presence of the hotspot
-
-    QList<Filter::HotSpot*> spots = _filterChain->hotSpots();
-    QListIterator<Filter::HotSpot*> iter(spots);
-    while (iter.hasNext())
-    {
-        Filter::HotSpot* spot = iter.next();
-
-        for ( int line = spot->startLine() ; line <= spot->endLine() ; line++ )
-        {
-            int startColumn = 0;
-            int endColumn = _columns-1; // TODO use number of _columns which are actually 
-                                        // occupied on this line rather than the width of the 
-                                        // display in _columns
-
-            // ignore whitespace at the end of the lines
-            while ( QChar(_image[loc(endColumn,line)].character).isSpace() && endColumn > 0 )
-                endColumn--;
-              
-            // increment here because the column which we want to set 'endColumn' to
-            // is the first whitespace character at the end of the line
-            endColumn++;
-
-            if ( line == spot->startLine() )
-                startColumn = spot->startColumn();
-            if ( line == spot->endLine() )
-                endColumn = spot->endColumn();
-
-            // subtract one pixel from
-            // the right and bottom so that
-            // we do not overdraw adjacent
-            // hotspots
-            //
-            // subtracting one pixel from all sides also prevents an edge case where
-            // moving the mouse outside a link could still leave it underlined 
-            // because the check below for the position of the cursor
-            // finds it on the border of the target area
-            QRect r;
-            r.setCoords( startColumn*_fontWidth + 1, line*_fontHeight + 1,
-                             endColumn*_fontWidth - 1, (line+1)*_fontHeight - 1 ); 
-                                                                           
-            // Underline link hotspots 
-            if ( spot->type() == Filter::HotSpot::Link )
-            {
-                QFontMetrics metrics(font());
-        
-                // find the baseline (which is the invisible line that the characters in the font sit on,
-                // with some having tails dangling below)
-                int baseline = r.bottom() - metrics.descent();
-                // find the position of the underline below that
-                int underlinePos = baseline + metrics.underlinePos();
-
-                if ( r.contains( mapFromGlobal(QCursor::pos()) ) )
-                    painter.drawLine( r.left() , underlinePos , 
-                                      r.right() , underlinePos );
-            }
-            // Marker hotspots simply have a transparent rectanglular shape
-            // drawn on top of them
-            else if ( spot->type() == Filter::HotSpot::Marker )
-            {
-            //TODO - Do not use a hardcoded colour for this
-                painter.fillRect(r,QBrush(QColor(255,0,0,120)));
-            }
-        }
-    }
-}
-void TerminalDisplay::drawContents(QPainter &paint, const QRect &rect)
-{
-//qDebug("%s %d drawContents and rect x=%d y=%d w=%d h=%d", __FILE__, __LINE__, rect.x(), rect.y(),rect.width(),rect.height());
-
-  QPoint tL  = contentsRect().topLeft();
-//  int    tLx = tL.x();
-  int    tLy = tL.y();
-
-  int tLx = (_contentWidth - _usedColumns * _fontWidth)/2;
-//  int tLy = (_contentHeight - _usedLines * _fontHeight)/2; 
-//qDebug("%d %d %d %d", tLx, tLy, _contentWidth, _usedColumns * _fontWidth);  
-
-  int lux = qMin(_usedColumns-1, qMax(0,(rect.left()   - tLx - _leftMargin ) / _fontWidth));
-  int luy = qMin(_usedLines-1,  qMax(0, (rect.top()    - tLy - _topMargin  ) / _fontHeight));
-  int rlx = qMin(_usedColumns-1, qMax(0, (rect.right()  - tLx - _leftMargin ) / _fontWidth));
-  int rly = qMin(_usedLines-1,  qMax(0, (rect.bottom() - tLy - _topMargin  ) / _fontHeight));
-
-  const int bufferSize = _usedColumns;
-  QChar *disstrU = new QChar[bufferSize];
-  for (int y = luy; y <= rly; y++)
-  {
-    quint16 c = _image[loc(lux,y)].character;
-    int x = lux;
-    if(!c && x)
-      x--; // Search for start of multi-column character
-    for (; x <= rlx; x++)
-    {
-      int len = 1;
-      int p = 0;
-
-      // is this a single character or a sequence of characters ?
-      if ( _image[loc(x,y)].rendition & RE_EXTENDED_CHAR )
-      {
-        // sequence of characters
-        ushort extendedCharLength = 0;
-        ushort* chars = ExtendedCharTable::instance
-                            .lookupExtendedChar(_image[loc(x,y)].charSequence,extendedCharLength);
-        for ( int index = 0 ; index < extendedCharLength ; index++ ) 
-        {
-            Q_ASSERT( p < bufferSize );
-            disstrU[p++] = chars[index];
-        }
-      }
-      else
-      {
-        // single character
-        c = _image[loc(x,y)].character;
-        if (c)
-        {
-             Q_ASSERT( p < bufferSize );
-             disstrU[p++] = c; //fontMap(c);
-        }
-      }
-
-      bool lineDraw = isLineChar(c);
-      bool doubleWidth = (_image[ qMin(loc(x,y)+1,_imageSize) ].character == 0);
-      CharacterColor currentForeground = _image[loc(x,y)].foregroundColor;
-      CharacterColor currentBackground = _image[loc(x,y)].backgroundColor;
-      quint8 currentRendition = _image[loc(x,y)].rendition;
-	  
-      while (x+len <= rlx &&
-             _image[loc(x+len,y)].foregroundColor == currentForeground &&
-             _image[loc(x+len,y)].backgroundColor == currentBackground &&
-             _image[loc(x+len,y)].rendition == currentRendition &&
-             (_image[ qMin(loc(x+len,y)+1,_imageSize) ].character == 0) == doubleWidth &&
-             isLineChar( c = _image[loc(x+len,y)].character) == lineDraw) // Assignment!
-      {
-        if (c)
-          disstrU[p++] = c; //fontMap(c);
-        if (doubleWidth) // assert((_image[loc(x+len,y)+1].character == 0)), see above if condition
-          len++; // Skip trailing part of multi-column character
-        len++;
-      }
-      if ((x+len < _usedColumns) && (!_image[loc(x+len,y)].character))
-        len++; // Adjust for trailing part of multi-column character
-
-   	     bool save__fixedFont = _fixedFont;
-         if (lineDraw)
-            _fixedFont = false;
-         if (doubleWidth)
-            _fixedFont = false;
-         QString unistr(disstrU,p);
-		 
-		 if (y < _lineProperties.size())
-		 {
-			if (_lineProperties[y] & LINE_DOUBLEWIDTH) {
-				paint.scale(2,1);
-			}
-			
-			if (_lineProperties[y] & LINE_DOUBLEHEIGHT) {
-  		 		paint.scale(1,2);
-			}
-		 }
-
-		 //calculate the area in which the text will be drawn
-		 QRect textArea = QRect( _leftMargin+tLx+_fontWidth*x , 
-					_topMargin+tLy+_fontHeight*y , 
-					_fontWidth*len, 
-					_fontHeight);
-		
-		 //move the calculated area to take account of scaling applied to the painter.
-		 //the position of the area from the origin (0,0) is scaled 
-         //by the opposite of whatever
-		 //transformation has been applied to the painter.  this ensures that 
-		 //painting does actually start from textArea.topLeft() 
-         //(instead of textArea.topLeft() * painter-scale)	
-		 QMatrix inverted = paint.matrix().inverted();
-//		 textArea.moveTopLeft( inverted.map(textArea.topLeft()) );
-		 textArea.moveCenter( inverted.map(textArea.center()) );
-
-		 
-		 //paint text fragment
-         drawTextFragment(	paint,
-                		    textArea,
-                		    unistr, 
-					    	&_image[loc(x,y)] ); //, 
-						    //0, 
-						    //!_isPrinting );
-         
-		 _fixedFont = save__fixedFont;
-     
-		 //reset back to single-width, single-height _lines 
-		 paint.resetMatrix();
-
-		 if (y < _lineProperties.size()-1)
-		 {
-			//double-height _lines are represented by two adjacent _lines 
-            //containing the same characters
-			//both _lines will have the LINE_DOUBLEHEIGHT attribute.  
-            //If the current line has the LINE_DOUBLEHEIGHT attribute, 
-            //we can therefore skip the next line
-			if (_lineProperties[y] & LINE_DOUBLEHEIGHT)
-				y++;
-		 }
-		 
-	    x += len - 1;
-    }
-  }
-  delete [] disstrU;
-}
-
-void TerminalDisplay::blinkEvent()
-{
-  _blinking = !_blinking;
-
-  //TODO:  Optimise to only repaint the areas of the widget 
-  // where there is blinking text
-  // rather than repainting the whole widget.
-  update();
-}
-
-QRect TerminalDisplay::imageToWidget(const QRect& imageArea) const
-{
-//qDebug("%s %d imageToWidget", __FILE__, __LINE__);
-    QRect result;
-    result.setLeft( _leftMargin + _fontWidth * imageArea.left() );
-    result.setTop( _topMargin + _fontHeight * imageArea.top() );
-    result.setWidth( _fontWidth * imageArea.width() );
-    result.setHeight( _fontHeight * imageArea.height() );
-
-    return result;
-}
-
-void TerminalDisplay::blinkCursorEvent()
-{
-  _cursorBlinking = !_cursorBlinking;
-
-  QRect cursorRect = imageToWidget( QRect(cursorPosition(),QSize(1,1)) ); 
-
-  update(cursorRect);
-}
-
-/* ------------------------------------------------------------------------- */
-/*                                                                           */
-/*                                  Resizing                                 */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-void TerminalDisplay::resizeEvent(QResizeEvent*)
-{
-  updateImageSize();
-}
-
-void TerminalDisplay::propagateSize()
-{
-  if (_isFixedSize)
-  {
-     setSize(_columns, _lines);
-     QWidget::setFixedSize(sizeHint());
-     parentWidget()->adjustSize();
-     parentWidget()->setFixedSize(parentWidget()->sizeHint());
-     return;
-  }
-  if (_image)
-     updateImageSize();
-}
-
-void TerminalDisplay::updateImageSize()
-{
-//qDebug("%s %d updateImageSize", __FILE__, __LINE__);
-  Character* oldimg = _image;
-  int oldlin = _lines;
-  int oldcol = _columns;
-
-  makeImage();
-
-  
-  // copy the old image to reduce flicker
-  int lines = qMin(oldlin,_lines);
-  int columns = qMin(oldcol,_columns);
-
-//qDebug("%s %d updateImageSize", __FILE__, __LINE__);
-  if (oldimg)
-  {
-    for (int line = 0; line < lines; line++) 
-    {
-      memcpy((void*)&_image[_columns*line],
-             (void*)&oldimg[oldcol*line],columns*sizeof(Character));
-    }
-    delete[] oldimg;
-  }
-
-//qDebug("%s %d updateImageSize", __FILE__, __LINE__);
-  if (_screenWindow)
-  	_screenWindow->setWindowLines(_lines);
-
-  _resizing = (oldlin!=_lines) || (oldcol!=_columns);
-
-  if ( _resizing )
-  {
-//qDebug("%s %d updateImageSize", __FILE__, __LINE__);
-  	showResizeNotification();
-    emit changedContentSizeSignal(_contentHeight, _contentWidth); // expose resizeEvent
-  }
-//qDebug("%s %d updateImageSize", __FILE__, __LINE__);
-  
-  _resizing = false;
-}
-
-//showEvent and hideEvent are reimplemented here so that it appears to other classes that the 
-//display has been resized when the display is hidden or shown.
-//
-//this allows  
-//TODO: Perhaps it would be better to have separate signals for show and hide instead of using
-//the same signal as the one for a content size change 
-void TerminalDisplay::showEvent(QShowEvent*)
-{
-    emit changedContentSizeSignal(_contentHeight,_contentWidth);
-}
-void TerminalDisplay::hideEvent(QHideEvent*)
-{
-    emit changedContentSizeSignal(_contentHeight,_contentWidth);
-}
-
-/* ------------------------------------------------------------------------- */
-/*                                                                           */
-/*                                Scrollbar                                  */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-void TerminalDisplay::scrollBarPositionChanged(int)
-{
-  if ( !_screenWindow ) 
-      return;
-
-  _screenWindow->scrollTo( _scrollBar->value() );
-
-  // if the thumb has been moved to the bottom of the _scrollBar then set
-  // the display to automatically track new output, 
-  // that is, scroll down automatically
-  // to how new _lines as they are added
-  const bool atEndOfOutput = (_scrollBar->value() == _scrollBar->maximum());
-  _screenWindow->setTrackOutput( atEndOfOutput );
-
-  updateImage();
-}
-
-void TerminalDisplay::setScroll(int cursor, int slines)
-{
-//qDebug("%s %d setScroll", __FILE__, __LINE__);
-  // update _scrollBar if the range or value has changed,
-  // otherwise return
-  //
-  // setting the range or value of a _scrollBar will always trigger
-  // a repaint, so it should be avoided if it is not necessary
-  if ( _scrollBar->minimum() == 0                 &&
-       _scrollBar->maximum() == (slines - _lines) &&
-       _scrollBar->value()   == cursor )
-  {
-        return;
-  }
-
-  disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int)));
-  _scrollBar->setRange(0,slines - _lines);
-  _scrollBar->setSingleStep(1);
-  _scrollBar->setPageStep(_lines);
-  _scrollBar->setValue(cursor);
-  connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int)));
-}
-
-void TerminalDisplay::setScrollBarPosition(ScrollBarPosition position)
-{
-  if (_scrollbarLocation == position) {
-//      return; 
-  }
- 
-  if ( position == NoScrollBar )
-     _scrollBar->hide();
-  else 
-     _scrollBar->show(); 
-
-  _topMargin = _leftMargin = 1;
-  _scrollbarLocation = position;
-  
-  propagateSize();
-  update();
-}
-
-void TerminalDisplay::mousePressEvent(QMouseEvent* ev)
-{
-  if ( _possibleTripleClick && (ev->button()==Qt::LeftButton) ) {
-    mouseTripleClickEvent(ev);
-    return;
-  }
-
-  if ( !contentsRect().contains(ev->pos()) ) return;
-  
-  if ( !_screenWindow ) return;
-
-  int charLine;
-  int charColumn;
-  getCharacterPosition(ev->pos(),charLine,charColumn);
-  QPoint pos = QPoint(charColumn,charLine);
-
-  if ( ev->button() == Qt::LeftButton)
-  {
-    _lineSelectionMode = false;
-    _wordSelectionMode = false;
-
-    emit isBusySelecting(true); // Keep it steady...
-    // Drag only when the Control key is hold
-    bool selected = false;
-    
-    // The receiver of the testIsSelected() signal will adjust
-    // 'selected' accordingly.
-    //emit testIsSelected(pos.x(), pos.y(), selected);
-    
-    selected =  _screenWindow->isSelected(pos.x(),pos.y());
-
-    if ((!_ctrlDrag || ev->modifiers() & Qt::ControlModifier) && selected ) {
-      // The user clicked inside selected text
-      dragInfo.state = diPending;
-      dragInfo.start = ev->pos();
-    }
-    else {
-      // No reason to ever start a drag event
-      dragInfo.state = diNone;
-
-      _preserveLineBreaks = !( ( ev->modifiers() & Qt::ControlModifier ) && !(ev->modifiers() & Qt::AltModifier) );
-      _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier);
-
-      if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier))
-      {
-         _screenWindow->clearSelection();
-
-        //emit clearSelectionSignal();
-        pos.ry() += _scrollBar->value();
-        _iPntSel = _pntSel = pos;
-        _actSel = 1; // left mouse button pressed but nothing selected yet.
-        
-      }
-      else
-      {
-        emit mouseSignal( 0, charColumn + 1, charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0);
-      }
-    }
-  }
-  else if ( ev->button() == Qt::MidButton )
-  {
-    if ( _mouseMarks || (!_mouseMarks && (ev->modifiers() & Qt::ShiftModifier)) )
-      emitSelection(true,ev->modifiers() & Qt::ControlModifier);
-    else
-      emit mouseSignal( 1, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0);
-  }
-  else if ( ev->button() == Qt::RightButton )
-  {
-    if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) 
-    {
-        emit configureRequest( this, 
-                               ev->modifiers() & (Qt::ShiftModifier|Qt::ControlModifier), 
-                               ev->pos()
-                             );
-    }
-    else
-      emit mouseSignal( 2, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0);
-  }
-}
-
-QList<QAction*> TerminalDisplay::filterActions(const QPoint& position)
-{
-  int charLine, charColumn;
-  getCharacterPosition(position,charLine,charColumn);
-
-  Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn);
-
-  return spot ? spot->actions() : QList<QAction*>();
-}
-
-void TerminalDisplay::mouseMoveEvent(QMouseEvent* ev)
-{
-  int charLine = 0;
-  int charColumn = 0;
-
-  getCharacterPosition(ev->pos(),charLine,charColumn); 
-
-  // handle filters
-  // change link hot-spot appearance on mouse-over
-  Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn);
-  if ( spot && spot->type() == Filter::HotSpot::Link)
-  {
-    QRect previousHotspotArea = _mouseOverHotspotArea;
-    _mouseOverHotspotArea.setCoords( qMin(spot->startColumn() , spot->endColumn()) * _fontWidth,
-                                     spot->startLine() * _fontHeight,
-                                     qMax(spot->startColumn() , spot->endColumn()) * _fontHeight,
-                                     (spot->endLine()+1) * _fontHeight );
-
-    // display tooltips when mousing over links
-    // TODO: Extend this to work with filter types other than links
-    const QString& tooltip = spot->tooltip();
-    if ( !tooltip.isEmpty() )
-    {
-        QToolTip::showText( mapToGlobal(ev->pos()) , tooltip , this , _mouseOverHotspotArea );
-    }
-
-    update( _mouseOverHotspotArea | previousHotspotArea );
-  }
-  else if ( _mouseOverHotspotArea.isValid() )
-  {
-        update( _mouseOverHotspotArea );
-        // set hotspot area to an invalid rectangle
-        _mouseOverHotspotArea = QRect();
-  }
-  
-  // for auto-hiding the cursor, we need mouseTracking
-  if (ev->buttons() == Qt::NoButton ) return;
-
-  // if the terminal is interested in mouse movements 
-  // then emit a mouse movement signal, unless the shift
-  // key is being held down, which overrides this.
-  if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
-  {
-	int button = 3;
-	if (ev->buttons() & Qt::LeftButton)
-		button = 0;
-	if (ev->buttons() & Qt::MidButton)
-		button = 1;
-	if (ev->buttons() & Qt::RightButton)
-		button = 2;
-
-        
-        emit mouseSignal( button, 
-                        charColumn + 1,
-                        charLine + 1 +_scrollBar->value() -_scrollBar->maximum(),
-			 1 );
-      
-	return;
-  }
-      
-  if (dragInfo.state == diPending) 
-  {
-    // we had a mouse down, but haven't confirmed a drag yet
-    // if the mouse has moved sufficiently, we will confirm
-
-   int distance = 10; //KGlobalSettings::dndEventDelay();
-   if ( ev->x() > dragInfo.start.x() + distance || ev->x() < dragInfo.start.x() - distance ||
-        ev->y() > dragInfo.start.y() + distance || ev->y() < dragInfo.start.y() - distance) 
-   {
-      // we've left the drag square, we can start a real drag operation now
-      emit isBusySelecting(false); // Ok.. we can breath again.
-      
-       _screenWindow->clearSelection();
-      doDrag();
-    }
-    return;
-  } 
-  else if (dragInfo.state == diDragging) 
-  {
-    // this isn't technically needed because mouseMoveEvent is suppressed during
-    // Qt drag operations, replaced by dragMoveEvent
-    return;
-  }
-
-  if (_actSel == 0) return;
-
- // don't extend selection while pasting
-  if (ev->buttons() & Qt::MidButton) return;
-
-  extendSelection( ev->pos() );
-}
-
-#if 0
-void TerminalDisplay::setSelectionEnd()
-{
-  extendSelection( _configureRequestPoint );
-}
-#endif
-
-void TerminalDisplay::extendSelection(const QPoint& position) {
-  QPoint pos = position;
-
-  if (!_screenWindow) {
-      return;
-  }
-
-  QPoint tL  = contentsRect().topLeft();
-  int    tLx = tL.x();
-  int    tLy = tL.y();
-  int    scroll = _scrollBar->value();
-
-  // we're in the process of moving the mouse with the left button pressed
-  // the mouse cursor will kept caught within the bounds of the text in
-  // this widget.
-
-  // Adjust position within text area bounds. See FIXME above.
-  QPoint oldpos = pos;
-  if (pos.x() < tLx + _leftMargin) {
-      pos.setX(tLx + _leftMargin);
-  }
-  if (pos.x() > tLx + _leftMargin + _usedColumns * _fontWidth - 1) {
-      pos.setX(tLx + _leftMargin + _usedColumns * _fontWidth);
-  }
-  if (pos.y() < tLy + _topMargin) {
-      pos.setY(tLy + _topMargin);
-  }
-  if (pos.y() > tLy + _topMargin + _usedLines * _fontHeight - 1) {
-      pos.setY(tLy + _topMargin + _usedLines * _fontHeight - 1);
-  }
-
-  if (pos.y() == tLy + _topMargin + _usedLines * _fontHeight - 1) {
-    _scrollBar->setValue(_scrollBar->value() + yMouseScroll); // scrollforward
-  }
-  if (pos.y() == tLy + _topMargin) {
-    _scrollBar->setValue(_scrollBar->value() - yMouseScroll); // scrollback
-  }
-
-  int charColumn = 0;
-  int charLine = 0;
-  getCharacterPosition(pos, charLine, charColumn);
-
-  QPoint here = QPoint(charColumn, charLine);
-  QPoint ohere(here);
-  QPoint _iPntSelCorr = _iPntSel;
-  _iPntSelCorr.ry() -= _scrollBar->value();
-  QPoint _pntSelCorr = _pntSel;
-  _pntSelCorr.ry() -= _scrollBar->value();
-  bool swapping = false;
-
-  if (_wordSelectionMode) {
-    // Extend to word boundaries
-    int i = 0;
-    int selClass = 0;
-
-    bool left_not_right = (here.y() < _iPntSelCorr.y() ||
-						   (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));
-    bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||
-							   (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));
-    swapping = left_not_right != old_left_not_right;
-
-    // Find left (left_not_right ? from here : from start)
-    QPoint left = left_not_right ? here : _iPntSelCorr;
-    i = loc(left.x(), left.y());
-    if (i >= 0 && i <= _imageSize) {
-      selClass = charClass(_image[i].character);
-      while (((left.x() > 0) || (left.y() > 0 && (_lineProperties[left.y() - 1] & LINE_WRAPPED))) 
-					  && charClass(_image[i - 1].character) == selClass) {
-		i--;
-		if (left.x() > 0) {
-		  left.rx()--;
-		} else {
-		  left.rx() = _usedColumns - 1;
-		  left.ry()--;
-		}
-	  }
-    }
-
-    // Find left (left_not_right ? from start : from here)
-    QPoint right = left_not_right ? _iPntSelCorr : here;
-    i = loc(right.x(), right.y());
-    if (i >= 0 && i <= _imageSize) {
-      selClass = charClass(_image[i].character);
-      while (((right.x() < _usedColumns - 1) || (right.y() < _usedLines - 1 && (_lineProperties[right.y()] & LINE_WRAPPED))) 
-					  && charClass(_image[i + 1].character) == selClass) {
-		i++;
-		if (right.x() < _usedColumns - 1) {
-		  right.rx()++;
-		} else {
-		  right.rx() = 0;
-		  right.ry()++;
-		}
-	  }
-    }
-
-    // Pick which is start (ohere) and which is extension (here)
-    if (left_not_right) {
-      here = left;
-	  ohere = right;
-    } else {
-      here = right;
-	  ohere = left;
-    }
-    ohere.rx()++;
-  }
-
-  if (_lineSelectionMode) {
-    // Extend to complete line
-    bool above_not_below = (here.y() < _iPntSelCorr.y());
-
-    QPoint above = above_not_below ? here : _iPntSelCorr;
-    QPoint below = above_not_below ? _iPntSelCorr : here;
-
-    while (above.y() > 0 && (_lineProperties[above.y() - 1] & LINE_WRAPPED)) {
-      above.ry()--;
-	}
-    while (below.y() < _usedLines - 1 && (_lineProperties[below.y()] & LINE_WRAPPED)) {
-      below.ry()++;
-	}
-
-    above.setX(0);
-    below.setX(_usedColumns - 1);
-
-    // Pick which is start (ohere) and which is extension (here)
-    if (above_not_below) {
-      here = above;
-	  ohere = below;
-    } else {
-      here = below;
-	  ohere = above;
-    }
-
-    QPoint newSelBegin = QPoint(ohere.x(), ohere.y());
-    swapping = !(_tripleSelBegin == newSelBegin);
-    _tripleSelBegin = newSelBegin;
-
-    ohere.rx()++;
-  }
-
-  int offset = 0;
-  if (!_wordSelectionMode && !_lineSelectionMode) {
-    int i = 0;
-    int selClass = 0;
-
-    bool left_not_right = (here.y() < _iPntSelCorr.y() ||
-						   (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));
-    bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||
-							   (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));
-    swapping = left_not_right != old_left_not_right;
-
-    // Find left (left_not_right ? from here : from start)
-    QPoint left = left_not_right ? here : _iPntSelCorr;
-
-    // Find left (left_not_right ? from start : from here)
-    QPoint right = left_not_right ? _iPntSelCorr : here;
-    if (right.x() > 0 && !_columnSelectionMode) {
-      i = loc(right.x(), right.y());
-      if (i >= 0 && i <= _imageSize) {
-        selClass = charClass(_image[i - 1].character);
-        if (selClass == ' ') {
-          while (right.x() < _usedColumns - 1 && charClass(_image[i + 1].character) == selClass && (right.y() < _usedLines - 1) && 
-						  !(_lineProperties[right.y()] & LINE_WRAPPED)) {
-			i++;
-			right.rx()++;
-		  }
-          if (right.x() < _usedColumns - 1) {
-            right = left_not_right ? _iPntSelCorr : here;
-          } else {
-            right.rx()++;  // will be balanced later because of offset=-1;
-		  }
-        }
-      }
-    }
-
-    // Pick which is start (ohere) and which is extension (here)
-    if (left_not_right) {
-      here = left;
-	  ohere = right;
-	  offset = 0;
-    } else {
-      here = right;
-	  ohere = left;
-	  offset = -1;
-    }
-  }
-
-  if ((here == _pntSelCorr) && (scroll == _scrollBar->value())) {
-	return; // not moved
-  }
-
-  if (here == ohere) {
-	return; // It's not left, it's not right.
-  }
-
-  if (_actSel < 2 || swapping) {
-    if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) {
-        _screenWindow->setSelectionStart(ohere.x(), ohere.y(), true);
-    } else {
-        _screenWindow->setSelectionStart(ohere.x() - 1 - offset , ohere.y(), false);
-    }
-
-  }
-
-  _actSel = 2; // within selection
-  _pntSel = here;
-  _pntSel.ry() += _scrollBar->value();
-
-  if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) {
-     _screenWindow->setSelectionEnd(here.x(), here.y());
-  } else {
-     _screenWindow->setSelectionEnd(here.x() + offset, here.y());
-  }
-}
-
-void TerminalDisplay::mouseReleaseEvent(QMouseEvent* ev)
-{
-    if ( !_screenWindow )
-        return;
-
-    int charLine;
-    int charColumn;
-    getCharacterPosition(ev->pos(),charLine,charColumn);
-
-  if ( ev->button() == Qt::LeftButton)
-  {
-    emit isBusySelecting(false); 
-    if(dragInfo.state == diPending)
-    {
-      // We had a drag event pending but never confirmed.  Kill selection
-       _screenWindow->clearSelection();
-      //emit clearSelectionSignal();
-    }
-    else
-    {
-      if ( _actSel > 1 )
-      {
-          setSelection(  _screenWindow->selectedText(_preserveLineBreaks)  );
-      }
-
-      _actSel = 0;
-
-      //FIXME: emits a release event even if the mouse is
-      //       outside the range. The procedure used in `mouseMoveEvent'
-      //       applies here, too.
-
-      if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
-        emit mouseSignal( 3, // release
-                        charColumn + 1,
-                        charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0);
-    }
-    dragInfo.state = diNone;
-  }
-  
-  
-  if ( !_mouseMarks && 
-       ((ev->button() == Qt::RightButton && !(ev->modifiers() & Qt::ShiftModifier))
-                        || ev->button() == Qt::MidButton) ) 
-  {
-    emit mouseSignal( 3, 
-                      charColumn + 1, 
-                      charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 
-                      0);
-  }
-}
-
-void TerminalDisplay::getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const
-{
-
-    column = (widgetPoint.x() + _fontWidth/2 -contentsRect().left()-_leftMargin) / _fontWidth;
-    line = (widgetPoint.y()-contentsRect().top()-_topMargin) / _fontHeight;
-
-    if ( line < 0 )
-        line = 0;
-    if ( column < 0 )
-        column = 0;
-
-    if ( line >= _usedLines )
-        line = _usedLines-1;
-
-    // the column value returned can be equal to _usedColumns, which
-    // is the position just after the last character displayed in a line.
-    //
-    // this is required so that the user can select characters in the right-most
-    // column (or left-most for right-to-left input)
-    if ( column > _usedColumns )
-        column = _usedColumns;
-}
-
-void TerminalDisplay::updateLineProperties()
-{
-    if ( !_screenWindow ) 
-        return;
-
-    _lineProperties = _screenWindow->getLineProperties();    
-}
-
-void TerminalDisplay::mouseDoubleClickEvent(QMouseEvent* ev)
-{
-  if ( ev->button() != Qt::LeftButton) return;
-  if ( !_screenWindow ) return;
-
-  int charLine = 0;
-  int charColumn = 0;
-
-  getCharacterPosition(ev->pos(),charLine,charColumn);
-
-  QPoint pos(charColumn,charLine);
-
-  // pass on double click as two clicks.
-  if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
-  {
-    // Send just _ONE_ click event, since the first click of the double click
-    // was already sent by the click handler
-    emit mouseSignal( 0, 
-                      pos.x()+1, 
-                      pos.y()+1 +_scrollBar->value() -_scrollBar->maximum(),
-                      0 ); // left button
-    return;
-  }
-
-  _screenWindow->clearSelection();
-  QPoint bgnSel = pos;
-  QPoint endSel = pos;
-  int i = loc(bgnSel.x(),bgnSel.y());
-  _iPntSel = bgnSel;
-  _iPntSel.ry() += _scrollBar->value();
-
-  _wordSelectionMode = true;
-
-  // find word boundaries...
-  int selClass = charClass(_image[i].character);
-  {
-     // find the start of the word
-     int x = bgnSel.x();
-     while ( ((x>0) || (bgnSel.y()>0 && (_lineProperties[bgnSel.y()-1] & LINE_WRAPPED) )) 
-					 && charClass(_image[i-1].character) == selClass )
-     {  
-       i--; 
-       if (x>0) 
-           x--; 
-       else 
-       {
-           x=_usedColumns-1; 
-           bgnSel.ry()--;
-       } 
-     }
-
-     bgnSel.setX(x);
-     _screenWindow->setSelectionStart( bgnSel.x() , bgnSel.y() , false );
-
-     // find the end of the word
-     i = loc( endSel.x(), endSel.y() );
-     x = endSel.x();
-     while( ((x<_usedColumns-1) || (endSel.y()<_usedLines-1 && (_lineProperties[endSel.y()] & LINE_WRAPPED) )) 
-					 && charClass(_image[i+1].character) == selClass )
-     { 
-         i++; 
-         if (x<_usedColumns-1) 
-             x++; 
-         else 
-         {  
-             x=0; 
-             endSel.ry()++; 
-         } 
-     }
-
-     endSel.setX(x);
-
-     // In word selection mode don't select @ (64) if at end of word.
-     if ( ( QChar( _image[i].character ) == '@' ) && ( ( endSel.x() - bgnSel.x() ) > 0 ) )
-       endSel.setX( x - 1 );
-
-
-     _actSel = 2; // within selection
-     
-     _screenWindow->setSelectionEnd( endSel.x() , endSel.y() );
-    
-     setSelection( _screenWindow->selectedText(_preserveLineBreaks) ); 
-   }
-
-  _possibleTripleClick=true;
-
-  QTimer::singleShot(QApplication::doubleClickInterval(),this,
-                     SLOT(tripleClickTimeout()));
-}
-
-void TerminalDisplay::wheelEvent( QWheelEvent* ev )
-{
-  if (ev->orientation() != Qt::Vertical)
-    return;
-
-  if ( _mouseMarks )
-    _scrollBar->event(ev);
-  else
-  {
-    int charLine;
-    int charColumn;
-    getCharacterPosition( ev->pos() , charLine , charColumn );
-    
-    emit mouseSignal( ev->delta() > 0 ? 4 : 5, 
-                      charColumn + 1, 
-                      charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 
-                      0);
-  }
-}
-
-void TerminalDisplay::tripleClickTimeout()
-{
-  _possibleTripleClick=false;
-}
-
-void TerminalDisplay::mouseTripleClickEvent(QMouseEvent* ev)
-{
-  if ( !_screenWindow ) return;
-
-  int charLine;
-  int charColumn;
-  getCharacterPosition(ev->pos(),charLine,charColumn);
-  _iPntSel = QPoint(charColumn,charLine);
-
-  _screenWindow->clearSelection();
-
-  _lineSelectionMode = true;
-  _wordSelectionMode = false;
-
-  _actSel = 2; // within selection
-  emit isBusySelecting(true); // Keep it steady...
-
-  while (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) )
-    _iPntSel.ry()--;
-  
-  if (_tripleClickMode == SelectForwardsFromCursor) {
-    // find word boundary start
-    int i = loc(_iPntSel.x(),_iPntSel.y());
-    int selClass = charClass(_image[i].character);
-    int x = _iPntSel.x();
-    
-    while ( ((x>0) || 
-             (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) )
-            ) 
-            && charClass(_image[i-1].character) == selClass )
-    {
-        i--; 
-        if (x>0) 
-            x--; 
-        else 
-        {
-            x=_columns-1; 
-            _iPntSel.ry()--;
-        } 
-    }
-
-    _screenWindow->setSelectionStart( x , _iPntSel.y() , false );
-    _tripleSelBegin = QPoint( x, _iPntSel.y() );
-  }
-  else if (_tripleClickMode == SelectWholeLine) {
-    _screenWindow->setSelectionStart( 0 , _iPntSel.y() , false );
-    _tripleSelBegin = QPoint( 0, _iPntSel.y() );
-  }
-
-  while (_iPntSel.y()<_lines-1 && (_lineProperties[_iPntSel.y()] & LINE_WRAPPED) )
-    _iPntSel.ry()++;
-  
-  _screenWindow->setSelectionEnd( _columns - 1 , _iPntSel.y() );
-
-  setSelection(_screenWindow->selectedText(_preserveLineBreaks));
-
-  _iPntSel.ry() += _scrollBar->value();
-
-  emit tripleClicked( _screenWindow->selectedText( _preserveLineBreaks ) ); 
-}
-
-
-bool TerminalDisplay::focusNextPrevChild( bool next )
-{
-  if (next)
-    return false; // This disables changing the active part in konqueror
-                  // when pressing Tab
-  return QWidget::focusNextPrevChild( next );
-}
-
-
-int TerminalDisplay::charClass(quint16 ch) const
-{
-    QChar qch=QChar(ch);
-    if ( qch.isSpace() ) return ' ';
-
-    if ( qch.isLetterOrNumber() || _wordCharacters.contains(qch, Qt::CaseInsensitive ) )
-    return 'a';
-
-    // Everything else is weird
-    return 1;
-}
-
-void TerminalDisplay::setWordCharacters(const QString& wc)
-{
-	_wordCharacters = wc;
-}
-
-void TerminalDisplay::setUsesMouse(bool on)
-{
-  _mouseMarks = on;
-  setCursor( _mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor );
-}
-bool TerminalDisplay::usesMouse() const
-{
-    return _mouseMarks;
-}
-
-/* ------------------------------------------------------------------------- */
-/*                                                                           */
-/*                               Clipboard                                   */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-#undef KeyPress
-
-void TerminalDisplay::emitSelection(bool useXselection,bool appendReturn)
-{
-  if ( !_screenWindow ) 
-      return;
-
-  // Paste Clipboard by simulating keypress events
-  QString text = QApplication::clipboard()->text(useXselection ? QClipboard::Selection :
-                                                                 QClipboard::Clipboard);
-  if(appendReturn)
-    text.append("\r");
-  if ( ! text.isEmpty() )
-  {
-    text.replace("\n", "\r");
-    QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text);
-    emit keyPressedSignal(&e); // expose as a big fat keypress event
-    
-    _screenWindow->clearSelection();
-  }
-}
-
-void TerminalDisplay::setSelection(const QString& t)
-{
-  QApplication::clipboard()->setText(t, QClipboard::Selection);
-}
-
-void TerminalDisplay::copyClipboard()
-{
-  if ( !_screenWindow )
-      return;
-
-  QString text = _screenWindow->selectedText(_preserveLineBreaks);
-  QApplication::clipboard()->setText(text);
-}
-
-void TerminalDisplay::pasteClipboard()
-{
-  emitSelection(false,false);
-}
-
-void TerminalDisplay::pasteSelection()
-{
-  emitSelection(true,false);
-}
-
-/* ------------------------------------------------------------------------- */
-/*                                                                           */
-/*                                Keyboard                                   */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-void TerminalDisplay::setFlowControlWarningEnabled( bool enable )
-{
-	_flowControlWarningEnabled = enable;
-	
-	// if the dialog is currently visible and the flow control warning has 
-	// been disabled then hide the dialog
-	if (!enable)
-		outputSuspended(false);
-}
-
-void TerminalDisplay::keyPressEvent( QKeyEvent* event )
-{
-//qDebug("%s %d keyPressEvent and key is %d", __FILE__, __LINE__, event->key());
-
-    bool emitKeyPressSignal = true;
-
-    // XonXoff flow control
-    if (event->modifiers() & Qt::ControlModifier && _flowControlWarningEnabled)
-	{
-		if ( event->key() == Qt::Key_S ) {
-		//qDebug("%s %d keyPressEvent, output suspended", __FILE__, __LINE__);
-				emit flowControlKeyPressed(true /*output suspended*/);
-		}
-		else if ( event->key() == Qt::Key_Q ) {
-		//qDebug("%s %d keyPressEvent, output enabled", __FILE__, __LINE__);
-				emit flowControlKeyPressed(false /*output enabled*/);
-		}
-	}
-
-    // Keyboard-based navigation
-    if ( event->modifiers() == Qt::ShiftModifier )
-    {
-        bool update = true;
-
-        if ( event->key() == Qt::Key_PageUp )
-        {
-	    //qDebug("%s %d pageup", __FILE__, __LINE__);
-            _screenWindow->scrollBy( ScreenWindow::ScrollPages , -1 );
-        }
-        else if ( event->key() == Qt::Key_PageDown )
-        {
-	    //qDebug("%s %d pagedown", __FILE__, __LINE__);
-            _screenWindow->scrollBy( ScreenWindow::ScrollPages , 1 );
-        }
-        else if ( event->key() == Qt::Key_Up )
-        {
-	    //qDebug("%s %d keyup", __FILE__, __LINE__);	
-            _screenWindow->scrollBy( ScreenWindow::ScrollLines , -1 );
-        }
-        else if ( event->key() == Qt::Key_Down )
-        {
-	    //qDebug("%s %d keydown", __FILE__, __LINE__);	
-            _screenWindow->scrollBy( ScreenWindow::ScrollLines , 1 );
-        }
-        else {
-            update = false;
-	}
-
-        if ( update )
-        {
-	    //qDebug("%s %d updating", __FILE__, __LINE__);	
-            _screenWindow->setTrackOutput( _screenWindow->atEndOfOutput() );
-            
-            updateLineProperties();
-            updateImage();
-
-            // do not send key press to terminal
-            emitKeyPressSignal = false;
-        }
-    }
-    
-    _screenWindow->setTrackOutput( true );
-    
-    _actSel=0; // Key stroke implies a screen update, so TerminalDisplay won't
-              // know where the current selection is.
-
-    if (_hasBlinkingCursor) 
-    {
-      _blinkCursorTimer->start(BLINK_DELAY);
-      if (_cursorBlinking)
-        blinkCursorEvent();
-      else
-        _cursorBlinking = false;
-    }
-
-    if ( emitKeyPressSignal && !_readonly )
-        emit keyPressedSignal(event);
-
-    if (_readonly) {
-	event->ignore();
-    }
-    else {
-        event->accept();
-    }
-}
-
-void TerminalDisplay::inputMethodEvent( QInputMethodEvent* event )
-{
-    QKeyEvent keyEvent(QEvent::KeyPress,0,Qt::NoModifier,event->commitString());
-    emit keyPressedSignal(&keyEvent);
-
-    _inputMethodData.preeditString = event->preeditString();
-    update(preeditRect() | _inputMethodData.previousPreeditRect);
-    
-    event->accept();
-}
-QVariant TerminalDisplay::inputMethodQuery( Qt::InputMethodQuery query ) const
-{
-    const QPoint cursorPos = _screenWindow ? _screenWindow->cursorPosition() : QPoint(0,0);
-    switch ( query ) 
-    {
-        case Qt::ImMicroFocus:
-                return imageToWidget(QRect(cursorPos.x(),cursorPos.y(),1,1));
-            break;
-        case Qt::ImFont:
-                return font();
-            break;
-        case Qt::ImCursorPosition:
-                // return the cursor position within the current line
-                return cursorPos.x();
-            break;
-        case Qt::ImSurroundingText:
-            {
-                // return the text from the current line
-                QString lineText;
-                QTextStream stream(&lineText);
-                PlainTextDecoder decoder;
-                decoder.begin(&stream);
-                decoder.decodeLine(&_image[loc(0,cursorPos.y())],_usedColumns,_lineProperties[cursorPos.y()]);
-                decoder.end();
-                return lineText;
-            }
-            break;
-        case Qt::ImCurrentSelection:
-                return QString();
-            break;
-	    default:
-	        break;
-    }
-
-    return QVariant();
-}
-
-bool TerminalDisplay::event( QEvent *e )
-{
-  if ( e->type() == QEvent::ShortcutOverride )
-  {
-    QKeyEvent* keyEvent = static_cast<QKeyEvent *>( e );
-
-    // a check to see if keyEvent->text() is empty is used
-    // to avoid intercepting the press of the modifier key on its own.
-    //
-    // this is important as it allows a press and release of the Alt key
-    // on its own to focus the menu bar, making it possible to
-    // work with the menu without using the mouse
-    if ( (keyEvent->modifiers() == Qt::AltModifier) && 
-         !keyEvent->text().isEmpty() )
-    {
-    	keyEvent->accept();
-      	return true;
-    }
-
-    // Override any of the following shortcuts because
-    // they are needed by the terminal
-    int keyCode = keyEvent->key() | keyEvent->modifiers();
-    switch ( keyCode )
-    {
-      // list is taken from the QLineEdit::event() code
-      case Qt::Key_Tab:
-      case Qt::Key_Delete:
-      case Qt::Key_Home:
-      case Qt::Key_End:
-      case Qt::Key_Backspace:
-      case Qt::Key_Left:
-      case Qt::Key_Right:
-        keyEvent->accept();
-        return true;
-    }
-  }
-  return QWidget::event( e );
-}
-
-void TerminalDisplay::setBellMode(int mode)
-{
-  _bellMode=mode;
-}
-
-void TerminalDisplay::enableBell()
-{
-    _allowBell = true;
-}
-
-void TerminalDisplay::bell(const QString&)
-{
-  if (_bellMode==NoBell) return;
-
-  //limit the rate at which bells can occur 
-  //...mainly for sound effects where rapid bells in sequence 
-  //produce a horrible noise
-  if ( _allowBell )
-  {
-    _allowBell = false;
-    QTimer::singleShot(500,this,SLOT(enableBell()));
- 
-    if (_bellMode==SystemBeepBell) 
-    {
-//        KNotification::beep();
-    } 
-    else if (_bellMode==NotifyBell) 
-    {
-//        KNotification::event("BellVisible", message,QPixmap(),this);
-    } 
-    else if (_bellMode==VisualBell) 
-    {
-        swapColorTable();
-        QTimer::singleShot(200,this,SLOT(swapColorTable()));
-    }
-  }
-}
-
-void TerminalDisplay::swapColorTable()
-{
-  ColorEntry color = _colorTable[1];
-  _colorTable[1]=_colorTable[0];
-  _colorTable[0]= color;
-  _colorsInverted = !_colorsInverted;
-  update();
-}
-
-void TerminalDisplay::clearImage()
-{
-  // We initialize _image[_imageSize] too. See makeImage()
-  for (int i = 0; i <= _imageSize; i++)
-  {
-    _image[i].character = ' ';
-    _image[i].foregroundColor = CharacterColor(COLOR_SPACE_DEFAULT,
-                                               DEFAULT_FORE_COLOR);
-    _image[i].backgroundColor = CharacterColor(COLOR_SPACE_DEFAULT,
-                                               DEFAULT_BACK_COLOR);
-    _image[i].rendition = DEFAULT_RENDITION;
-  }
-}
-
-void TerminalDisplay::calcGeometry()
-{
-  _scrollBar->resize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent),
-                    contentsRect().height());
-  switch(_scrollbarLocation)
-  {
-    case NoScrollBar :
-     _leftMargin = DEFAULT_LEFT_MARGIN;
-     _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN;
-     break;
-    case ScrollBarLeft :
-     _leftMargin = DEFAULT_LEFT_MARGIN + _scrollBar->width();
-     _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width();
-     _scrollBar->move(contentsRect().topLeft());
-     break;
-    case ScrollBarRight:
-     _leftMargin = DEFAULT_LEFT_MARGIN;
-     _contentWidth = contentsRect().width()  - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width();
-     _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width()-1,0));
-     break;
-  }
-
-  _topMargin = DEFAULT_TOP_MARGIN;
-  _contentHeight = contentsRect().height() - 2 * DEFAULT_TOP_MARGIN + /* mysterious */ 1;
-
-  if (!_isFixedSize)
-  {
-     // ensure that display is always at least one column wide
-     _columns = qMax(1,_contentWidth / _fontWidth);
-     _usedColumns = qMin(_usedColumns,_columns);
-     
-     // ensure that display is always at least one line high
-     _lines = qMax(1,_contentHeight / _fontHeight);
-     _usedLines = qMin(_usedLines,_lines);
-  }
-}
-
-void TerminalDisplay::makeImage()
-{
-//qDebug("%s %d makeImage", __FILE__, __LINE__);
-  calcGeometry();
-
-  // confirm that array will be of non-zero size, since the painting code 
-  // assumes a non-zero array length
-  Q_ASSERT( _lines > 0 && _columns > 0 );
-  Q_ASSERT( _usedLines <= _lines && _usedColumns <= _columns );
-
-  _imageSize=_lines*_columns;
-  
-  // We over-commit one character so that we can be more relaxed in dealing with
-  // certain boundary conditions: _image[_imageSize] is a valid but unused position
-  _image = new Character[_imageSize+1];
-
-  clearImage();
-}
-
-// calculate the needed size
-void TerminalDisplay::setSize(int columns, int lines)
-{
-  //FIXME - Not quite correct, a small amount of additional space
-  // will be used for margins, the scrollbar etc.
-  // we need to allow for this so that '_size' does allow
-  // enough room for the specified number of columns and lines to fit
-
-  QSize newSize = QSize( columns * _fontWidth  ,
-				 lines * _fontHeight   );
-
-  if ( newSize != size() )
-  {
-    _size = newSize;
-    updateGeometry();
-  }
-}
-
-void TerminalDisplay::setFixedSize(int cols, int lins)
-{
-  _isFixedSize = true;
-  
-  //ensure that display is at least one line by one column in size
-  _columns = qMax(1,cols);
-  _lines = qMax(1,lins);
-  _usedColumns = qMin(_usedColumns,_columns);
-  _usedLines = qMin(_usedLines,_lines);
-
-  if (_image)
-  {
-     delete[] _image;
-     makeImage();
-  }
-  setSize(cols, lins);
-  QWidget::setFixedSize(_size);
-}
-
-QSize TerminalDisplay::sizeHint() const
-{
-  return _size;
-}
-
-
-/* --------------------------------------------------------------------- */
-/*                                                                       */
-/* Drag & Drop                                                           */
-/*                                                                       */
-/* --------------------------------------------------------------------- */
-
-void TerminalDisplay::dragEnterEvent(QDragEnterEvent* event)
-{
-  if (event->mimeData()->hasFormat("text/plain"))
-      event->acceptProposedAction();
-}
-
-void TerminalDisplay::dropEvent(QDropEvent* event)
-{
-//  KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
-
-  QString dropText;
-/*  if (!urls.isEmpty()) 
-  {
-    for ( int i = 0 ; i < urls.count() ; i++ ) 
-    {
-        KUrl url = KIO::NetAccess::mostLocalUrl( urls[i] , 0 );
-        QString urlText;
-
-        if (url.isLocalFile())
-            urlText = url.path(); 
-        else
-            urlText = url.url();
-    
-        // in future it may be useful to be able to insert file names with drag-and-drop
-        // without quoting them (this only affects paths with spaces in) 
-        urlText = KShell::quoteArg(urlText);
-      
-        dropText += urlText;
-
-        if ( i != urls.count()-1 ) 
-            dropText += ' ';
-    }
-  }
-  else 
-  {
-    dropText = event->mimeData()->text();
-  }
-*/
-  if(event->mimeData()->hasFormat("text/plain")) 
-  {
-    emit sendStringToEmu(dropText.toLocal8Bit());
-  }
-}
-
-void TerminalDisplay::doDrag()
-{
-  dragInfo.state = diDragging;
-  dragInfo.dragObject = new QDrag(this);
-  QMimeData *mimeData = new QMimeData;
-  mimeData->setText(QApplication::clipboard()->text(QClipboard::Selection));
-  dragInfo.dragObject->setMimeData(mimeData);
-  dragInfo.dragObject->start(Qt::CopyAction);
-  // Don't delete the QTextDrag object.  Qt will delete it when it's done with it.
-}
-
-void TerminalDisplay::outputSuspended(bool suspended)
-{
-	//create the label when this function is first called
-	if (!_outputSuspendedLabel)
-	{
-            //This label includes a link to an English language website
-            //describing the 'flow control' (Xon/Xoff) feature found in almost 
-            //all terminal emulators.
-            //If there isn't a suitable article available in the target language the link
-            //can simply be removed.
-			_outputSuspendedLabel = new QLabel( ("<qt>Output has been "
-                                                "<a href=\"http://en.wikipedia.org/wiki/XON\">suspended</a>"
-                                                " by pressing Ctrl+S."
-											   "  Press <b>Ctrl+Q</b> to resume.</qt>"),
-											   this );
-
-            QPalette palette(_outputSuspendedLabel->palette());
-	    
-	    palette.setColor(QPalette::Normal, QPalette::WindowText, QColor(Qt::white));
-	    palette.setColor(QPalette::Normal, QPalette::Window, QColor(Qt::black));
-//            KColorScheme::adjustForeground(palette,KColorScheme::NeutralText);
-//		KColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground);
-    	    _outputSuspendedLabel->setPalette(palette);
-	    _outputSuspendedLabel->setAutoFillBackground(true);
-	    _outputSuspendedLabel->setBackgroundRole(QPalette::Base);
-	    _outputSuspendedLabel->setFont(QApplication::font());
-            _outputSuspendedLabel->setMargin(5);
-
-            //enable activation of "Xon/Xoff" link in label
-            _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse | 
-                                                          Qt::LinksAccessibleByKeyboard);
-            _outputSuspendedLabel->setOpenExternalLinks(true);
-            _outputSuspendedLabel->setVisible(false);
-
-            _gridLayout->addWidget(_outputSuspendedLabel);       
-            _gridLayout->addItem( new QSpacerItem(0,0,QSizePolicy::Expanding,
-                                                      QSizePolicy::Expanding),
-                                 1,0);
-
-    }
-
-	_outputSuspendedLabel->setVisible(suspended);
-}
-
-uint TerminalDisplay::lineSpacing() const
-{
-  return _lineSpacing;
-}
-
-void TerminalDisplay::setLineSpacing(uint i)
-{
-  _lineSpacing = i;
-  setVTFont(font()); // Trigger an update.
-}
deleted file mode 100644
--- a/libqterminal/TerminalDisplay.h
+++ /dev/null
@@ -1,758 +0,0 @@
-/*
-    Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
-    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
-
-    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-    02110-1301  USA.
-*/
-
-#ifndef TERMINALDISPLAY_H
-#define TERMINALDISPLAY_H
-
-// Qt
-#include <QtGui/QColor>
-#include <QtCore/QPointer>
-#include <QtGui/QWidget>
-
-// Konsole
-#include "Filter.h"
-#include "Character.h"
-
-class QDrag;
-class QDragEnterEvent;
-class QDropEvent;
-class QLabel;
-class QTimer;
-class QEvent;
-class QFrame;
-class QGridLayout;
-class QKeyEvent;
-class QScrollBar;
-class QShowEvent;
-class QHideEvent;
-class QWidget;
-
-extern unsigned short vt100_graphics[32];
-
-class ScreenWindow;
-
-/**
- * A widget which displays output from a terminal emulation and sends input keypresses and mouse activity
- * to the terminal.
- *
- * When the terminal emulation receives new output from the program running in the terminal, 
- * it will update the display by calling updateImage().
- *
- * TODO More documentation
- */
-class TerminalDisplay : public QWidget
-{
-   Q_OBJECT
-
-public:
-    /** Constructs a new terminal display widget with the specified parent. */
-    TerminalDisplay(QWidget *parent=0);
-    virtual ~TerminalDisplay();
-
-    /** Returns the terminal color palette used by the display. */
-    const ColorEntry* colorTable() const;
-    /** Sets the terminal color palette used by the display. */
-    void setColorTable(const ColorEntry table[]);
-    /**
-     * Sets the seed used to generate random colors for the display
-     * (in color schemes that support them).
-     */
-    void setRandomSeed(uint seed);
-    /**
-     * Returns the seed used to generate random colors for the display
-     * (in color schemes that support them).
-     */
-    uint randomSeed() const;
-
-    /** Sets the opacity of the terminal display. */
-    void setOpacity(qreal opacity);
-
-    /** 
-     * This enum describes the location where the scroll bar is positioned in the display widget.
-     */
-    enum ScrollBarPosition 
-    { 
-        /** Do not show the scroll bar. */
-        NoScrollBar=0, 
-        /** Show the scroll bar on the left side of the display. */
-        ScrollBarLeft=1, 
-        /** Show the scroll bar on the right side of the display. */
-        ScrollBarRight=2 
-    };
-    /** 
-     * Specifies whether the terminal display has a vertical scroll bar, and if so whether it
-     * is shown on the left or right side of the display.
-     */
-    void setScrollBarPosition(ScrollBarPosition position);
-
-    /** 
-     * Sets the current position and range of the display's scroll bar.
-     *
-     * @param cursor The position of the scroll bar's thumb.
-     * @param lines The maximum value of the scroll bar.
-     */
-    void setScroll(int cursor, int lines);
-
-    /** 
-     * Returns the display's filter chain.  When the image for the display is updated,
-     * the text is passed through each filter in the chain.  Each filter can define
-     * hotspots which correspond to certain strings (such as URLs or particular words).
-     * Depending on the type of the hotspots created by the filter ( returned by Filter::Hotspot::type() )
-     * the view will draw visual cues such as underlines on mouse-over for links or translucent
-     * rectangles for markers.
-     *
-     * To add a new filter to the view, call:
-     *      viewWidget->filterChain()->addFilter( filterObject );
-     */
-    FilterChain* filterChain() const;
-
-    /** 
-     * Updates the filters in the display's filter chain.  This will cause
-     * the hotspots to be updated to match the current image.
-     *
-     * WARNING:  This function can be expensive depending on the 
-     * image size and number of filters in the filterChain()
-     *
-     * TODO - This API does not really allow efficient usage.  Revise it so
-     * that the processing can be done in a better way.
-     *
-     * eg:
-     *      - Area of interest may be known ( eg. mouse cursor hovering
-     *      over an area )
-     */  
-    void processFilters();
-
-    /** 
-     * Returns a list of menu actions created by the filters for the content
-     * at the given @p position.
-     */
-    QList<QAction*> filterActions(const QPoint& position);
-
-    /** Returns true if the cursor is set to blink or false otherwise. */
-    bool blinkingCursor() { return _hasBlinkingCursor; }
-    /** Specifies whether or not the cursor blinks. */
-    void setBlinkingCursor(bool blink);
-
-    void setCtrlDrag(bool enable) { _ctrlDrag=enable; }
-    bool ctrlDrag() { return _ctrlDrag; }
-
-	/** 
-     *  This enum describes the methods for selecting text when
- 	 *  the user triple-clicks within the display. 
- 	 */
-	enum TripleClickMode
-	{
-		/** Select the whole line underneath the cursor. */
-		SelectWholeLine,
-		/** Select from the current cursor position to the end of the line. */
-		SelectForwardsFromCursor
-	};
-    /** Sets how the text is selected when the user triple clicks within the display. */	
-    void setTripleClickMode(TripleClickMode mode) { _tripleClickMode = mode; }
-	/** See setTripleClickSelectionMode() */
-    TripleClickMode tripleClickMode() { return _tripleClickMode; }
-
-    void setLineSpacing(uint);
-    uint lineSpacing() const;
-
-    void emitSelection(bool useXselection,bool appendReturn);
-
-    /**
-     * This enum describes the available shapes for the keyboard cursor.
-     * See setKeyboardCursorShape()
-     */
-    enum KeyboardCursorShape
-    {
-        /** A rectangular block which covers the entire area of the cursor character. */
-        BlockCursor,
-        /** 
-         * A single flat line which occupies the space at the bottom of the cursor
-         * character's area.
-         */
-        UnderlineCursor,
-        /** 
-         * An cursor shaped like the capital letter 'I', similar to the IBeam 
-         * cursor used in Qt/KDE text editors.
-         */
-        IBeamCursor
-    };
-    /** 
-     * Sets the shape of the keyboard cursor.  This is the cursor drawn   
-     * at the position in the terminal where keyboard input will appear.
-     *
-     * In addition the terminal display widget also has a cursor for 
-     * the mouse pointer, which can be set using the QWidget::setCursor()
-     * method.
-     *
-     * Defaults to BlockCursor
-     */
-    void setKeyboardCursorShape(KeyboardCursorShape shape);
-    /**
-     * Returns the shape of the keyboard cursor.  See setKeyboardCursorShape()
-     */
-    KeyboardCursorShape keyboardCursorShape() const;
-
-    /**
-     * Sets the color used to draw the keyboard cursor.  
-     *
-     * The keyboard cursor defaults to using the foreground color of the character
-     * underneath it.
-     *
-     * @param useForegroundColor If true, the cursor color will change to match
-     * the foreground color of the character underneath it as it is moved, in this
-     * case, the @p color parameter is ignored and the color of the character
-     * under the cursor is inverted to ensure that it is still readable.
-     * @param color The color to use to draw the cursor.  This is only taken into
-     * account if @p useForegroundColor is false.
-     */
-    void setKeyboardCursorColor(bool useForegroundColor , const QColor& color);
-
-    /** 
-     * Returns the color of the keyboard cursor, or an invalid color if the keyboard
-     * cursor color is set to change according to the foreground color of the character
-     * underneath it. 
-     */
-    QColor keyboardCursorColor() const;
-
-    /**
-     * Returns the number of lines of text which can be displayed in the widget.
-     *
-     * This will depend upon the height of the widget and the current font.
-     * See fontHeight()
-     */
-    int  lines()   { return _lines;   }
-    /**
-     * Returns the number of characters of text which can be displayed on
-     * each line in the widget.
-     *
-     * This will depend upon the width of the widget and the current font.
-     * See fontWidth()
-     */
-    int  columns() { return _columns; }
-
-    /**
-     * Returns the height of the characters in the font used to draw the text in the display.
-     */
-    int  fontHeight()   { return _fontHeight;   }
-    /**
-     * Returns the width of the characters in the display.  
-     * This assumes the use of a fixed-width font.
-     */
-    int  fontWidth()    { return _fontWidth; }
-
-    void setSize(int cols, int lins);
-    void setFixedSize(int cols, int lins);
-    
-    // reimplemented
-    QSize sizeHint() const;
-
-    /**
-     * Sets which characters, in addition to letters and numbers, 
-     * are regarded as being part of a word for the purposes
-     * of selecting words in the display by double clicking on them.
-     *
-     * The word boundaries occur at the first and last characters which
-     * are either a letter, number, or a character in @p wc
-     *
-     * @param wc An array of characters which are to be considered parts
-     * of a word ( in addition to letters and numbers ).
-     */
-    void setWordCharacters(const QString& wc);
-    /** 
-     * Returns the characters which are considered part of a word for the 
-     * purpose of selecting words in the display with the mouse.
-     *
-     * @see setWordCharacters()
-     */
-    QString wordCharacters() { return _wordCharacters; }
-
-    /** 
-     * Sets the type of effect used to alert the user when a 'bell' occurs in the 
-     * terminal session.
-     *
-     * The terminal session can trigger the bell effect by calling bell() with
-     * the alert message.
-     */
-    void setBellMode(int mode);
-    /** 
-     * Returns the type of effect used to alert the user when a 'bell' occurs in
-     * the terminal session.
-     * 
-     * See setBellMode()
-     */
-    int bellMode() { return _bellMode; }
-
-    /**
-     * This enum describes the different types of sounds and visual effects which
-     * can be used to alert the user when a 'bell' occurs in the terminal
-     * session.
-     */
-    enum BellMode
-    { 
-        /** A system beep. */
-        SystemBeepBell=0, 
-        /** 
-         * KDE notification.  This may play a sound, show a passive popup
-         * or perform some other action depending on the user's settings.
-         */
-        NotifyBell=1, 
-        /** A silent, visual bell (eg. inverting the display's colors briefly) */
-        VisualBell=2, 
-        /** No bell effects */
-        NoBell=3 
-    };
-
-    void setSelection(const QString &t);
-
-    /** 
-     * Reimplemented.  Has no effect.  Use setVTFont() to change the font
-     * used to draw characters in the display.
-     */
-    virtual void setFont(const QFont &);
-
-
-    /** Returns the font used to draw characters in the display */
-    QFont getVTFont() { return font(); }
-
-    /** 
-     * Sets the font used to draw the display.  Has no effect if @p font
-     * is larger than the size of the display itself.    
-     */
-    void setVTFont(const QFont& font);
-
-
-    /**
-     * Specified whether terminal widget should be at read-only mode
-     * Defaults to false.
-     */
-    void setReadOnly( bool readonly) { _readonly = readonly; }
-
-    /**
-     * Specified whether anti-aliasing of text in the terminal display
-     * is enabled or not.  Defaults to enabled.
-     */
-    static void setAntialias( bool antialias ) { _antialiasText = antialias; }
-    /** 
-     * Returns true if anti-aliasing of text in the terminal is enabled.
-     */
-    static bool antialias()                 { return _antialiasText;   }
-    
-    /**
-     * Sets whether or not the current height and width of the 
-     * terminal in lines and columns is displayed whilst the widget
-     * is being resized.
-     */
-    void setTerminalSizeHint(bool on) { _terminalSizeHint=on; }
-    /** 
-     * Returns whether or not the current height and width of
-     * the terminal in lines and columns is displayed whilst the widget
-     * is being resized.
-     */
-    bool terminalSizeHint() { return _terminalSizeHint; }
-    /** 
-     * Sets whether the terminal size display is shown briefly
-     * after the widget is first shown.
-     *
-     * See setTerminalSizeHint() , isTerminalSizeHint()
-     */
-    void setTerminalSizeStartup(bool on) { _terminalSizeStartup=on; }
-
-    void setBidiEnabled(bool set) { _bidiEnabled=set; }
-    bool isBidiEnabled() { return _bidiEnabled; }
-
-    /**
-     * Sets the terminal screen section which is displayed in this widget.
-     * When updateImage() is called, the display fetches the latest character image from the
-     * the associated terminal screen window.
-     *
-     * In terms of the model-view paradigm, the ScreenWindow is the model which is rendered
-     * by the TerminalDisplay.
-     */
-    void setScreenWindow( ScreenWindow* window );
-    /** Returns the terminal screen section which is displayed in this widget.  See setScreenWindow() */
-    ScreenWindow* screenWindow() const;
-
-    static bool HAVE_TRANSPARENCY;
-
-public slots:
-
-    /** 
-     * Causes the terminal display to fetch the latest character image from the associated
-     * terminal screen ( see setScreenWindow() ) and redraw the display.
-     */
-    void updateImage(); 
-    /**
-     * Causes the terminal display to fetch the latest line status flags from the 
-     * associated terminal screen ( see setScreenWindow() ).  
-     */ 
-    void updateLineProperties();
-
-    /** Copies the selected text to the clipboard. */
-    void copyClipboard();
-    /** 
-     * Pastes the content of the clipboard into the 
-     * display.
-     */
-    void pasteClipboard();
-    /**
-     * Pastes the content of the selection into the
-     * display.
-     */
-    void pasteSelection();
-
-	/** 
- 	  * Changes whether the flow control warning box should be shown when the flow control
- 	  * stop key (Ctrl+S) are pressed.
- 	  */
-	void setFlowControlWarningEnabled(bool enabled);
-	
-    /** 
-	 * Causes the widget to display or hide a message informing the user that terminal
-	 * output has been suspended (by using the flow control key combination Ctrl+S)
-	 *
-	 * @param suspended True if terminal output has been suspended and the warning message should
-	 *				 	be shown or false to indicate that terminal output has been resumed and that
-	 *				 	the warning message should disappear.
-	 */ 
-	void outputSuspended(bool suspended);
-
-    /**
-     * Sets whether the program whoose output is being displayed in the view
-     * is interested in mouse events.
-     *
-     * If this is set to true, mouse signals will be emitted by the view when the user clicks, drags
-     * or otherwise moves the mouse inside the view.
-     * The user interaction needed to create selections will also change, and the user will be required
-     * to hold down the shift key to create a selection or perform other mouse activities inside the 
-     * view area - since the program running in the terminal is being allowed to handle normal mouse
-     * events itself.
-     *
-     * @param usesMouse Set to true if the program running in the terminal is interested in mouse events
-     * or false otherwise.
-     */
-    void setUsesMouse(bool usesMouse);
-  
-    /** See setUsesMouse() */
-    bool usesMouse() const;
-
-    /** 
-     * Shows a notification that a bell event has occurred in the terminal.
-     * TODO: More documentation here
-     */
-    void bell(const QString& message);
-
-signals:
-
-    /**
-     * Emitted when the user presses a key whilst the terminal widget has focus.
-     */
-    void keyPressedSignal(QKeyEvent *e);
-
-    /**
-     * Emitted when the user presses the suspend or resume flow control key combinations 
-     * 
-     * @param suspend true if the user pressed Ctrl+S (the suspend output key combination) or
-     * false if the user pressed Ctrl+Q (the resume output key combination)
-     */
-    void flowControlKeyPressed(bool suspend);
-    
-    /** 
-     * A mouse event occurred.
-     * @param button The mouse button (0 for left button, 1 for middle button, 2 for right button, 3 for release)
-     * @param column The character column where the event occurred
-     * @param line The character row where the event occurred
-     * @param eventType The type of event.  0 for a mouse press / release or 1 for mouse motion
-     */
-    void mouseSignal(int button, int column, int line, int eventType);
-    void changedFontMetricSignal(int height, int width);
-    void changedContentSizeSignal(int height, int width);
-
-    /** 
-     * Emitted when the user right clicks on the display, or right-clicks with the Shift
-     * key held down if usesMouse() is true.
-     *
-     * This can be used to display a context menu.
-     */
-    void configureRequest( TerminalDisplay*, int state, const QPoint& position );
-
-   void isBusySelecting(bool);
-   void sendStringToEmu(const char*);
-   
-   void tripleClicked( const QString& text );
-
-protected:
-    virtual bool event( QEvent * );
-
-    virtual void paintEvent( QPaintEvent * );
-
-    virtual void showEvent(QShowEvent*);
-    virtual void hideEvent(QHideEvent*);
-    virtual void resizeEvent(QResizeEvent*);
-
-    virtual void fontChange(const QFont &font);
-
-    virtual void keyPressEvent(QKeyEvent* event);
-    virtual void mouseDoubleClickEvent(QMouseEvent* ev);
-    virtual void mousePressEvent( QMouseEvent* );
-    virtual void mouseReleaseEvent( QMouseEvent* );
-    virtual void mouseMoveEvent( QMouseEvent* );
-    virtual void extendSelection( const QPoint& pos );
-    virtual void wheelEvent( QWheelEvent* );
-
-    virtual bool focusNextPrevChild( bool next );
-    
-    // drag and drop
-    virtual void dragEnterEvent(QDragEnterEvent* event);
-    virtual void dropEvent(QDropEvent* event);
-    void doDrag();
-    enum DragState { diNone, diPending, diDragging };
-
-    struct _dragInfo {
-      DragState       state;
-      QPoint          start;
-      QDrag           *dragObject;
-    } dragInfo;
-
-    virtual int charClass(quint16) const;
-
-    void clearImage();
-
-    void mouseTripleClickEvent(QMouseEvent* ev);
-
-    // reimplemented
-    virtual void inputMethodEvent ( QInputMethodEvent* event );
-    virtual QVariant inputMethodQuery( Qt::InputMethodQuery query ) const;
-
-protected slots:
-
-    void scrollBarPositionChanged(int value);
-    void blinkEvent();
-    void blinkCursorEvent();
-    
-    //Renables bell noises and visuals.  Used to disable further bells for a short period of time
-    //after emitting the first in a sequence of bell events.
-    void enableBell();
-
-private slots:
-
-    void swapColorTable();
-    void tripleClickTimeout();  // resets possibleTripleClick
-
-private:
-
-    // -- Drawing helpers --
-
-    // divides the part of the display specified by 'rect' into
-    // fragments according to their colors and styles and calls
-    // drawTextFragment() to draw the fragments 
-    void drawContents(QPainter &paint, const QRect &rect);
-    // draws a section of text, all the text in this section
-    // has a common color and style
-    void drawTextFragment(QPainter& painter, const QRect& rect, 
-                          const QString& text, const Character* style); 
-    // draws the background for a text fragment
-    // if useOpacitySetting is true then the color's alpha value will be set to
-    // the display's transparency (set with setOpacity()), otherwise the background
-    // will be drawn fully opaque
-    void drawBackground(QPainter& painter, const QRect& rect, const QColor& color,
-						bool useOpacitySetting);
-    // draws the cursor character
-    void drawCursor(QPainter& painter, const QRect& rect , const QColor& foregroundColor, 
-                                       const QColor& backgroundColor , bool& invertColors);
-    // draws the characters or line graphics in a text fragment
-    void drawCharacters(QPainter& painter, const QRect& rect,  const QString& text, 
-                                           const Character* style, bool invertCharacterColor);
-    // draws a string of line graphics
-	void drawLineCharString(QPainter& painter, int x, int y, 
-                            const QString& str, const Character* attributes);
-
-    // draws the preedit string for input methods
-    void drawInputMethodPreeditString(QPainter& painter , const QRect& rect);
-
-    // --
-
-    // maps an area in the character image to an area on the widget 
-    QRect imageToWidget(const QRect& imageArea) const;
-
-    // maps a point on the widget to the position ( ie. line and column ) 
-    // of the character at that point.
-    void getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const;
-
-    // the area where the preedit string for input methods will be draw
-    QRect preeditRect() const;
-
-    // shows a notification window in the middle of the widget indicating the terminal's
-    // current size in columns and lines
-    void showResizeNotification();
-
-    // scrolls the image by a number of lines.  
-    // 'lines' may be positive ( to scroll the image down ) 
-    // or negative ( to scroll the image up )
-    // 'region' is the part of the image to scroll - currently only
-    // the top, bottom and height of 'region' are taken into account,
-    // the left and right are ignored.
-    void scrollImage(int lines , const QRect& region);
-
-    void calcGeometry();
-    void propagateSize();
-    void updateImageSize();
-    void makeImage();
-    
-    void paintFilters(QPainter& painter);
-
-	// returns a region covering all of the areas of the widget which contain
-	// a hotspot
-	QRegion hotSpotRegion() const;
-
-	// returns the position of the cursor in columns and lines
-	QPoint cursorPosition() const;
-
-    // the window onto the terminal screen which this display
-    // is currently showing.  
-    QPointer<ScreenWindow> _screenWindow;
-
-    bool _allowBell;
-
-    QGridLayout* _gridLayout;
-
-    bool _fixedFont; // has fixed pitch
-    int  _fontHeight;     // height
-    int  _fontWidth;     // width
-    int  _fontAscent;     // ascend
-
-    int _leftMargin;    // offset
-    int _topMargin;    // offset
-
-    int _lines;      // the number of lines that can be displayed in the widget
-    int _columns;    // the number of columns that can be displayed in the widget
-    
-    int _usedLines;  // the number of lines that are actually being used, this will be less
-                    // than 'lines' if the character image provided with setImage() is smaller
-                    // than the maximum image size which can be displayed
-
-    int _usedColumns; // the number of columns that are actually being used, this will be less
-                     // than 'columns' if the character image provided with setImage() is smaller
-                     // than the maximum image size which can be displayed
-    
-    int _contentHeight;
-    int _contentWidth;
-    Character* _image; // [lines][columns]
-               // only the area [usedLines][usedColumns] in the image contains valid data
-
-    int _imageSize;
-    QVector<LineProperty> _lineProperties;
-
-    ColorEntry _colorTable[TABLE_COLORS];
-    uint _randomSeed;
-
-    bool _resizing;
-    bool _terminalSizeHint;
-    bool _terminalSizeStartup;
-    bool _bidiEnabled;
-    bool _mouseMarks;
-
-    QPoint  _iPntSel; // initial selection point
-    QPoint  _pntSel; // current selection point
-    QPoint  _tripleSelBegin; // help avoid flicker
-    int     _actSel; // selection state
-    bool    _wordSelectionMode;
-    bool    _lineSelectionMode;
-    bool    _preserveLineBreaks;
-    bool    _columnSelectionMode;
-
-    QClipboard*  _clipboard;
-    QScrollBar* _scrollBar;
-    ScrollBarPosition _scrollbarLocation;
-    QString     _wordCharacters;
-    int         _bellMode;
-
-    bool _blinking;   // hide text in paintEvent
-    bool _hasBlinker; // has characters to blink
-    bool _cursorBlinking;     // hide cursor in paintEvent
-    bool _hasBlinkingCursor;  // has blinking cursor enabled
-    bool _ctrlDrag;           // require Ctrl key for drag
-    TripleClickMode _tripleClickMode;
-    bool _isFixedSize; //Columns / lines are locked.
-    QTimer* _blinkTimer;  // active when hasBlinker
-    QTimer* _blinkCursorTimer;  // active when hasBlinkingCursor
-
-//    KMenu* _drop;
-    QString _dropText;
-    int _dndFileCount;
-
-    bool _possibleTripleClick;  // is set in mouseDoubleClickEvent and deleted
-                               // after QApplication::doubleClickInterval() delay
-
-
-    QLabel* _resizeWidget;
-    QTimer* _resizeTimer;
-
-	bool _flowControlWarningEnabled;
-
-    //widgets related to the warning message that appears when the user presses Ctrl+S to suspend
-    //terminal output - informing them what has happened and how to resume output
-    QLabel* _outputSuspendedLabel; 
-    	
-    uint _lineSpacing;
-
-    bool _colorsInverted; // true during visual bell
-
-    QSize _size;
-	
-    QRgb _blendColor;
-
-    // list of filters currently applied to the display.  used for links and
-    // search highlight
-    TerminalImageFilterChain* _filterChain;
-    QRect _mouseOverHotspotArea;
-
-    KeyboardCursorShape _cursorShape;
-
-    // custom cursor color.  if this is invalid then the foreground
-    // color of the character under the cursor is used
-    QColor _cursorColor;  
-
-
-    struct InputMethodData
-    {
-        QString preeditString;
-        QRect previousPreeditRect;
-    };
-    InputMethodData _inputMethodData;
-
-    static bool _antialiasText;   // do we antialias or not
-
-    //the delay in milliseconds between redrawing blinking text
-    static const int BLINK_DELAY = 500;
-	static const int DEFAULT_LEFT_MARGIN = 1;
-	static const int DEFAULT_TOP_MARGIN = 1;
-	
-    bool _readonly;
-
-public:
-    static void setTransparencyEnabled(bool enable)
-    {
-        HAVE_TRANSPARENCY = enable;
-    }
-};
-
-#endif // TERMINALDISPLAY_H
--- a/libqterminal/libqterminal.pro
+++ b/libqterminal/libqterminal.pro
@@ -27,12 +27,12 @@
            QTerminal.h \
            Screen.h \
            ScreenWindow.h \
-           Session.h \
            ShellCommand.h \
            TerminalCharacterDecoder.h \
-           TerminalDisplay.h \
            Vt102Emulation.h \
-    PseudoTerminal.h
+    PseudoTerminal.h \
+    SessionModel.h \
+    SessionView.h
 SOURCES  = BlockArray.cpp \
            Emulation.cpp \
            Filter.cpp \
@@ -45,9 +45,9 @@
            QTerminal.cpp \
            Screen.cpp \
            ScreenWindow.cpp \
-           Session.cpp \
            ShellCommand.cpp \
            TerminalCharacterDecoder.cpp \
-           TerminalDisplay.cpp \
            Vt102Emulation.cpp \
-    PseudoTerminal.cpp
+    PseudoTerminal.cpp \
+    SessionModel.cpp \
+    SessionView.cpp