# HG changeset patch # User Jacob Dawid # Date 1313688010 -7200 # Node ID cc90c62ada215a091fefd7a139dedd6f2c4c5527 # Parent 8f7adc0d59c199c50d942fa787b880aadfb13672 Removed terminal, instead now using QPlainTextEdit, which looks much nicer and is not that error-prone... diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/octave-gui.pro --- a/gui/octave-gui.pro Thu Aug 18 15:07:43 2011 +0200 +++ b/gui/octave-gui.pro Thu Aug 18 19:20:10 2011 +0200 @@ -58,16 +58,9 @@ # Files associated with the project: SOURCES +=\ src/lexer/lexeroctavegui.cpp \ - src/terminal/TerminalCharacterDecoder.cpp \ src/terminal/KeyboardTranslator.cpp \ - src/terminal/Screen.cpp \ src/terminal/History.cpp \ src/terminal/konsole_wcwidth.cpp \ - src/terminal/ScreenWindow.cpp \ - src/terminal/Emulation.cpp \ - src/terminal/Vt102Emulation.cpp \ - src/terminal/TerminalDisplay.cpp \ - src/terminal/Filter.cpp \ src/terminal/Pty.cpp \ src/terminal/kpty.cpp \ src/terminal/kptyprocess.cpp \ @@ -75,7 +68,6 @@ src/terminal/kptydevice.cpp \ src/terminal/Session.cpp \ src/terminal/ShellCommand.cpp \ - src/terminal/QTerminalWidget.cpp \ src/MainWindow.cpp \ src/OctaveTerminal.cpp \ src/VariablesDockWidget.cpp \ @@ -96,20 +88,13 @@ HEADERS += \ src/lexer/lexeroctavegui.h \ - src/terminal/TerminalCharacterDecoder.h \ src/terminal/Character.h \ src/terminal/CharacterColor.h \ src/terminal/ColorTables.h \ src/terminal/KeyboardTranslator.h \ - src/terminal/Screen.h \ src/terminal/History.h \ src/terminal/konsole_wcwidth.h \ src/terminal/konsole_export.h \ - src/terminal/ScreenWindow.h \ - src/terminal/Emulation.h \ - src/terminal/Vt102Emulation.h \ - src/terminal/TerminalDisplay.h \ - src/terminal/Filter.h \ src/terminal/Pty.h \ src/terminal/kpty.h \ src/terminal/kpty_p.h \ @@ -120,7 +105,6 @@ src/terminal/kptydevice.h \ src/terminal/Session.h \ src/terminal/ShellCommand.h \ - src/terminal/QTerminalWidget.h \ src/MainWindow.h \ src/OctaveTerminal.h \ src/VariablesDockWidget.h \ diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/MainWindow.cpp --- a/gui/src/MainWindow.cpp Thu Aug 18 15:07:43 2011 +0200 +++ b/gui/src/MainWindow.cpp Thu Aug 18 19:20:10 2011 +0200 @@ -22,6 +22,7 @@ #include #include #include +#include #include "MainWindow.h" #include "FileEditorMdiSubWindow.h" #include "ImageViewerMdiSubWindow.h" diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/MainWindow.h --- a/gui/src/MainWindow.h Thu Aug 18 15:07:43 2011 +0200 +++ b/gui/src/MainWindow.h Thu Aug 18 19:20:10 2011 +0200 @@ -27,6 +27,7 @@ #include #include #include +#include #include "ResourceManager.h" #include "OctaveTerminal.h" #include "OctaveLink.h" diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/OctaveTerminal.cpp --- a/gui/src/OctaveTerminal.cpp Thu Aug 18 15:07:43 2011 +0200 +++ b/gui/src/OctaveTerminal.cpp Thu Aug 18 19:20:10 2011 +0200 @@ -26,7 +26,8 @@ #include "unistd.h" #include -OctaveTerminal::OctaveTerminal (QWidget * parent):QWidget (parent) +OctaveTerminal::OctaveTerminal (QWidget * parent) + : QPlainTextEdit (parent) { construct (); } @@ -38,19 +39,23 @@ void OctaveTerminal::construct () { - m_terminalWidget = new QTerminalWidget (0, this); - m_terminalWidget->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding); - setFocusProxy (m_terminalWidget); - - QVBoxLayout *layout = new QVBoxLayout (); - layout->addWidget (m_terminalWidget); - layout->setMargin (3); - setLayout (layout); + setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding); } void OctaveTerminal::openTerminal () { + m_session = new Session (); + m_session->setTitle (Session::NameRole, "QTerminalWidget"); + m_session->setProgram ("/bin/bash"); + m_session->setArguments (QStringList ()); + m_session->setAutoClose (true); + m_session->setCodec (QTextCodec::codecForName ("UTF-8")); + m_session->setFlowControlEnabled (true); + m_session->setDarkBackground (true); + + connect (m_session, SIGNAL(receivedData(QString)), this, SLOT(appendPlainText(QString))); + int fdm, fds; if (openpty (&fdm, &fds, 0, 0, 0) < 0) { @@ -60,5 +65,152 @@ dup2 (fds, 1); dup2 (fds, 2); - m_terminalWidget->openTeletype (fdm); + m_session->openTeletype (fdm); } + +void +OctaveTerminal::keyPressEvent (QKeyEvent * keyEvent) +{ + //QByteArray textToSend; + + //textToSend += QString::fromUtf8()); + m_session->sendText(keyEvent->text ()); + keyEvent->accept (); + + /* + bool emitKeyPressSignal = true; + + if (event->modifiers () == Qt::ControlModifier) + { + switch (event->key ()) + { + case Qt::Key_C: + copyClipboard (); + break; + case Qt::Key_V: + pasteClipboard (); + break; + }; + } + else if (event->modifiers () == Qt::ShiftModifier) + { + bool update = true; + + if (event->key () == Qt::Key_PageUp) + { + _screenWindow->scrollBy (ScreenWindow::ScrollPages, -1); + } + else if (event->key () == Qt::Key_PageDown) + { + _screenWindow->scrollBy (ScreenWindow::ScrollPages, 1); + } + else if (event->key () == Qt::Key_Up) + { + _screenWindow->scrollBy (ScreenWindow::ScrollLines, -1); + } + else if (event->key () == Qt::Key_Down) + { + _screenWindow->scrollBy (ScreenWindow::ScrollLines, 1); + } + else + update = false; + + } + + _actSel = 0; // Key stroke implies a screen update, so TerminalDisplay won't + // know where the current selection is. + + if (_hasBlinkingCursor) + { + _blinkCursorTimer->start (QApplication::cursorFlashTime () / 2); + if (_cursorBlinking) + blinkCursorEvent (); + else + _cursorBlinking = false; + } + + if (emitKeyPressSignal) + emit keyPressedSignal (event); + + event->accept (); + _scrollBar->setValue (_scrollBar->maximum ()); + Qt::KeyboardModifiers modifiers = keyEvent->modifiers (); + KeyboardTranslator::States states = KeyboardTranslator::NoState; + + // get current states + if (getMode (MODE_NewLine)) + states |= KeyboardTranslator::NewLineState; + if (getMode (MODE_Ansi)) + states |= KeyboardTranslator::AnsiState; + if (getMode (MODE_AppCuKeys)) + states |= KeyboardTranslator::CursorKeysState; + if (getMode (MODE_AppScreen)) + states |= KeyboardTranslator::AlternateScreenState; + if (getMode (MODE_AppKeyPad) && (modifiers & Qt::KeypadModifier)) + states |= KeyboardTranslator::ApplicationKeypadState; + + // check flow control state + if (modifiers & Qt::ControlModifier) + { + if (event->key () == Qt::Key_S) + emit flowControlKeyPressed (true); + else + if (event->key () == Qt::Key_Q) + emit flowControlKeyPressed (false); + } + + // lookup key binding + if (_keyTranslator) + { + KeyboardTranslator::Entry entry = + _keyTranslator->findEntry (event->key (), modifiers, states); + + // send result to terminal + QByteArray textToSend; + + // special handling for the Alt (aka. Meta) modifier. pressing + // Alt+[Character] results in Esc+[Character] being sent + // (unless there is an entry defined for this particular combination + // in the keyboard modifier) + bool wantsAltModifier = + entry.modifiers () & entry.modifierMask () & Qt::AltModifier; + bool wantsAnyModifier = + entry.state () & entry. + stateMask () & KeyboardTranslator::AnyModifierState; + + if (modifiers & Qt::AltModifier + && !(wantsAltModifier || wantsAnyModifier) + && !event->text ().isEmpty ()) + { + textToSend.prepend ("\033"); + } + + if (entry.command () != KeyboardTranslator::NoCommand) + { + if (entry.command () & KeyboardTranslator::EraseCommand) + textToSend += eraseChar (); + + // TODO command handling + } + else if (!entry.text ().isEmpty ()) + { + textToSend += _codec->fromUnicode (entry.text (true, modifiers)); + } + else + textToSend += _codec->fromUnicode (event->text ()); + + sendData (textToSend.constData (), textToSend.length ()); + } + else + { + // print an error message to the terminal if no key translator has been + // set + QString translatorError = QString ("No keyboard translator available. " + "The information needed to convert key presses " + "into characters to send to the terminal " + "is missing."); + reset (); + receiveData (translatorError.toAscii ().constData (), + translatorError.count ()); + }*/ +} diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/OctaveTerminal.h --- a/gui/src/OctaveTerminal.h Thu Aug 18 15:07:43 2011 +0200 +++ b/gui/src/OctaveTerminal.h Thu Aug 18 19:20:10 2011 +0200 @@ -18,20 +18,24 @@ #ifndef OCTAVETERMINAL_H #define OCTAVETERMINAL_H -#include -#include "QTerminalWidget.h" +#include +#include "Session.h" -class OctaveTerminal:public QWidget +class OctaveTerminal:public QPlainTextEdit { Q_OBJECT public: OctaveTerminal (QWidget * parent = 0); ~OctaveTerminal (); - void sendText (QString text) { m_terminalWidget->sendText(text); } + void sendText (QString text) { m_session->sendText (text); } void openTerminal (); + +protected: + void keyPressEvent (QKeyEvent *keyEvent); + private: void construct (); - QTerminalWidget *m_terminalWidget; + Session *m_session; }; #endif // OCTAVETERMINAL_H diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/CharacterColor.h --- a/gui/src/terminal/CharacterColor.h Thu Aug 18 15:07:43 2011 +0200 +++ b/gui/src/terminal/CharacterColor.h Thu Aug 18 19:20:10 2011 +0200 @@ -117,7 +117,7 @@ //a standard set of colors using black text on a white background. //defined in TerminalDisplay.cpp -extern const ColorEntry base_color_table[TABLE_COLORS]; +//extern const ColorEntry base_color_table[TABLE_COLORS]; /* CharacterColor is a union of the various color spaces. diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/Emulation.cpp --- a/gui/src/terminal/Emulation.cpp Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,436 +0,0 @@ -/* - Copyright 2007-2008 Robert Knight - Copyright 1997,1998 by Lars Doelle - Copyright 1996 by Matthias Ettrich - - 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 "Emulation.h" - -// System -#include -#include -#include -#include - -// Qt -#include -#include -#include -#include -#include -#include -#include - -#include - -// Konsole -#include "KeyboardTranslator.h" -#include "Screen.h" -#include "TerminalCharacterDecoder.h" -#include "ScreenWindow.h" - -Emulation::Emulation (): -_currentScreen (0), -_codec (0), _decoder (0), _keyTranslator (0), _usesMouse (false) -{ - // create screens with a default size - _screen[0] = new Screen (40, 80); - _screen[1] = new Screen (40, 80); - _currentScreen = _screen[0]; - - QObject::connect (&_bulkTimer1, SIGNAL (timeout ()), this, - SLOT (showBulk ())); - QObject::connect (&_bulkTimer2, SIGNAL (timeout ()), this, - SLOT (showBulk ())); - - // listen for mouse status changes - connect (this, SIGNAL (programUsesMouseChanged (bool)), - SLOT (usesMouseChanged (bool))); -} - -bool -Emulation::programUsesMouse () const -{ - return _usesMouse; -} - -void -Emulation::usesMouseChanged (bool usesMouse) -{ - _usesMouse = usesMouse; -} - -ScreenWindow * -Emulation::createWindow () -{ - ScreenWindow *window = new ScreenWindow (); - window->setScreen (_currentScreen); - _windows << window; - - connect (window, SIGNAL (selectionChanged ()), - this, SLOT (bufferedUpdate ())); - - connect (this, SIGNAL (outputChanged ()), - window, SLOT (notifyOutputChanged ())); - return window; -} - -Emulation::~Emulation () -{ - QListIterator < ScreenWindow * >windowIter (_windows); - - while (windowIter.hasNext ()) - { - delete windowIter.next (); - } - - delete _screen[0]; - delete _screen[1]; - delete _decoder; -} - -void -Emulation::setScreen (int n) -{ - Screen *old = _currentScreen; - _currentScreen = _screen[n & 1]; - if (_currentScreen != old) - { - // tell all windows onto this emulation to switch to the newly active screen - foreach (ScreenWindow * window, _windows) - window->setScreen (_currentScreen); - } -} - -void -Emulation::clearHistory () -{ - _screen[0]->setScroll (_screen[0]->getScroll (), false); -} - -void -Emulation::setHistory (const HistoryType & t) -{ - _screen[0]->setScroll (t); - - showBulk (); -} - -const HistoryType & -Emulation::history () const -{ - return _screen[0]->getScroll (); -} - -void -Emulation::setCodec (const QTextCodec * qtc) -{ - if (qtc) - _codec = qtc; - else - setCodec (LocaleCodec); - - delete _decoder; - _decoder = _codec->makeDecoder (); - - emit useUtf8Request (utf8 ()); -} - -void -Emulation::setCodec (EmulationCodec codec) -{ - if (codec == Utf8Codec) - setCodec (QTextCodec::codecForName ("utf8")); - else if (codec == LocaleCodec) - setCodec (QTextCodec::codecForLocale ()); -} - -void -Emulation::setKeyBindings (const QString & name) -{ - _keyTranslator = - KeyboardTranslatorManager::instance ()->findTranslator (name); - if (!_keyTranslator) - { - _keyTranslator = - KeyboardTranslatorManager::instance ()->defaultTranslator (); - } -} - -QString -Emulation::keyBindings () const -{ - return _keyTranslator->name (); -} - -void -Emulation::receiveChar (int c) -// process application unicode input to terminal -// this is a trivial scanner -{ - c &= 0xff; - switch (c) - { - case '\b': - _currentScreen->backspace (); - break; - case '\t': - _currentScreen->tab (); - break; - case '\n': - _currentScreen->newLine (); - break; - case '\r': - _currentScreen->toStartOfLine (); - break; - case 0x07: - emit stateSet (NOTIFYBELL); - break; - default: - _currentScreen->displayCharacter (c); - break; - }; -} - -void -Emulation::sendKeyEvent (QKeyEvent * ev) -{ - emit stateSet (NOTIFYNORMAL); - - if (!ev->text ().isEmpty ()) - { // A block of text - // Note that the text is proper unicode. - // We should do a conversion here - emit sendData (ev->text ().toUtf8 (), ev->text ().length ()); - } -} - -void -Emulation::sendString (const char *, int) -{ - // default implementation does nothing -} - -void -Emulation::sendMouseEvent (int /*buttons */ , int /*column */ , int /*row */ , - int /*eventType */ ) -{ - // default implementation does nothing -} - -/* - We are doing code conversion from locale to unicode first. -TODO: Character composition from the old code. See #96536 -*/ - -void -Emulation::receiveData (const char *text, int length) -{ - emit stateSet (NOTIFYACTIVITY); - - bufferedUpdate (); - - QString unicodeText = _decoder->toUnicode (text, length); - - //send characters to terminal emulator - for (int i = 0; i < unicodeText.length (); i++) - receiveChar (unicodeText[i].unicode ()); -} - -void -Emulation::writeToStream (TerminalCharacterDecoder * _decoder, - int startLine, int endLine) -{ - _currentScreen->writeLinesToStream (_decoder, startLine, endLine); -} - -int -Emulation::lineCount () const -{ - // sum number of lines currently on _screen plus number of lines in history - return _currentScreen->getLines () + _currentScreen->getHistLines (); -} - -#define BULK_TIMEOUT1 10 -#define BULK_TIMEOUT2 40 - -void -Emulation::showBulk () -{ - _bulkTimer1.stop (); - _bulkTimer2.stop (); - - emit outputChanged (); - - _currentScreen->resetScrolledLines (); - _currentScreen->resetDroppedLines (); -} - -void -Emulation::bufferedUpdate () -{ - _bulkTimer1.setSingleShot (true); - _bulkTimer1.start (BULK_TIMEOUT1); - if (!_bulkTimer2.isActive ()) - { - _bulkTimer2.setSingleShot (true); - _bulkTimer2.start (BULK_TIMEOUT2); - } -} - -char -Emulation::eraseChar () const -{ - return '\b'; -} - -void -Emulation::setImageSize (int lines, int columns) -{ - if ((lines < 1) || (columns < 1)) - return; - - QSize screenSize[2] = { QSize (_screen[0]->getColumns (), - _screen[0]->getLines ()), - QSize (_screen[1]->getColumns (), - _screen[1]->getLines ()) - }; - QSize newSize (columns, lines); - - if (newSize == screenSize[0] && newSize == screenSize[1]) - return; - - _screen[0]->resizeImage (lines, columns); - _screen[1]->resizeImage (lines, columns); - - emit imageSizeChanged (lines, columns); - - bufferedUpdate (); -} - -QSize -Emulation::imageSize () const -{ - return QSize (_currentScreen->getColumns (), _currentScreen->getLines ()); -} - -ushort -ExtendedCharTable::extendedCharHash (ushort * unicodePoints, ushort length) const -{ - ushort hash = 0; - for (ushort i = 0; i < length; i++) - { - hash = 31 * hash + unicodePoints[i]; - } - return hash; -} - -bool -ExtendedCharTable::extendedCharMatch (ushort hash, ushort * unicodePoints, - ushort length) const -{ - ushort *entry = extendedCharTable[hash]; - - // compare given length with stored sequence length ( given as the first ushort in the - // stored buffer ) - if (entry == 0 || entry[0] != length) - return false; - // if the lengths match, each character must be checked. the stored buffer starts at - // entry[1] - for (int i = 0; i < length; i++) - { - if (entry[i + 1] != unicodePoints[i]) - return false; - } - return true; -} - -ushort -ExtendedCharTable::createExtendedChar (ushort * unicodePoints, ushort length) -{ - // look for this sequence of points in the table - ushort hash = extendedCharHash (unicodePoints, length); - - // check existing entry for match - while (extendedCharTable.contains (hash)) - { - if (extendedCharMatch (hash, unicodePoints, length)) - { - // this sequence already has an entry in the table, - // return its hash - return hash; - } - else - { - // if hash is already used by another, different sequence of unicode character - // points then try next hash - hash++; - } - } - - - // add the new sequence to the table and - // return that index - ushort *buffer = new ushort[length + 1]; - buffer[0] = length; - for (int i = 0; i < length; i++) - buffer[i + 1] = unicodePoints[i]; - - extendedCharTable.insert (hash, buffer); - - return hash; -} - -ushort * -ExtendedCharTable::lookupExtendedChar (ushort hash, ushort & length) const -{ - // lookup index in table and if found, set the length - // argument and return a pointer to the character sequence - - ushort *buffer = extendedCharTable[hash]; - if (buffer) - { - length = buffer[0]; - return buffer + 1; - } - else - { - length = 0; - return 0; - } -} - -ExtendedCharTable::ExtendedCharTable () -{ -} - -ExtendedCharTable::~ExtendedCharTable () -{ - // free all allocated character buffers - QHashIterator < ushort, ushort * >iter (extendedCharTable); - while (iter.hasNext ()) - { - iter.next (); - delete[]iter.value (); - } -} - -// global instance -ExtendedCharTable - ExtendedCharTable::instance; diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/Emulation.h --- a/gui/src/terminal/Emulation.h Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,461 +0,0 @@ -/* - This file is part of Konsole, an X terminal. - - Copyright 2007-2008 by Robert Knight - Copyright 1997,1998 by Lars Doelle - - 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 EMULATION_H -#define EMULATION_H - -// System -#include - -// Qt -#include -#include -#include -#include - - -class KeyboardTranslator; -class HistoryType; -class Screen; -class ScreenWindow; -class TerminalCharacterDecoder; - -/** - * This enum describes the available states which - * the terminal emulation may be set to. - * - * These are the values used by Emulation::stateChanged() - */ -enum -{ - /** The emulation is currently receiving user input. */ - NOTIFYNORMAL = 0, - /** - * The terminal program has triggered a bell event - * to get the user's attention. - */ - NOTIFYBELL = 1, - /** - * The emulation is currently receiving data from its - * terminal input. - */ - NOTIFYACTIVITY = 2, - - // unused here? - NOTIFYSILENCE = 3 -}; - -/** - * Base class for terminal emulation back-ends. - * - * The back-end is responsible for decoding an incoming character stream and - * producing an output image of characters. - * - * When input from the terminal is received, the receiveData() slot should be called with - * the data which has arrived. The emulation will process the data and update the - * screen image accordingly. The codec used to decode the incoming character stream - * into the unicode characters used internally can be specified using setCodec() - * - * The size of the screen image can be specified by calling setImageSize() with the - * desired number of lines and columns. When new lines are added, old content - * is moved into a history store, which can be set by calling setHistory(). - * - * The screen image can be accessed by creating a ScreenWindow onto this emulation - * by calling createWindow(). Screen windows provide access to a section of the - * output. Each screen window covers the same number of lines and columns as the - * image size returned by imageSize(). The screen window can be moved up and down - * and provides transparent access to both the current on-screen image and the - * previous output. The screen windows emit an outputChanged signal - * when the section of the image they are looking at changes. - * Graphical views can then render the contents of a screen window, listening for notifications - * of output changes from the screen window which they are associated with and updating - * accordingly. - * - * The emulation also is also responsible for converting input from the connected views such - * as keypresses and mouse activity into a character string which can be sent - * to the terminal program. Key presses can be processed by calling the sendKeyEvent() slot, - * while mouse events can be processed using the sendMouseEvent() slot. When the character - * stream has been produced, the emulation will emit a sendData() signal with a pointer - * to the character buffer. This data should be fed to the standard input of the terminal - * process. The translation of key presses into an output character stream is performed - * using a lookup in a set of key bindings which map key sequences to output - * character sequences. The name of the key bindings set used can be specified using - * setKeyBindings() - * - * The emulation maintains certain state information which changes depending on the - * input received. The emulation can be reset back to its starting state by calling - * reset(). - * - * The emulation also maintains an activity state, which specifies whether - * terminal is currently active ( when data is received ), normal - * ( when the terminal is idle or receiving user input ) or trying - * to alert the user ( also known as a "Bell" event ). The stateSet() signal - * is emitted whenever the activity state is set. This can be used to determine - * how long the emulation has been active/idle for and also respond to - * a 'bell' event in different ways. - */ -class Emulation:public QObject -{ -Q_OBJECT public: - - /** Constructs a new terminal emulation */ - Emulation (); - ~Emulation (); - - /** - * Creates a new window onto the output from this emulation. The contents - * of the window are then rendered by views which are set to use this window using the - * TerminalDisplay::setScreenWindow() method. - */ - ScreenWindow *createWindow (); - - /** Returns the size of the screen image which the emulation produces */ - QSize imageSize () const; - - /** - * Returns the total number of lines, including those stored in the history. - */ - int lineCount () const; - - /** - * Sets the history store used by this emulation. When new lines - * are added to the output, older lines at the top of the screen are transferred to a history - * store. - * - * The number of lines which are kept and the storage location depend on the - * type of store. - */ - void setHistory (const HistoryType &); - /** Returns the history store used by this emulation. See setHistory() */ - const HistoryType & history () const; - /** Clears the history scroll. */ - void clearHistory (); - - /** - * Copies the output history from @p startLine to @p endLine - * into @p stream, using @p decoder to convert the terminal - * characters into text. - * - * @param decoder A decoder which converts lines of terminal characters with - * appearance attributes into output text. PlainTextDecoder is the most commonly - * used decoder. - * @param startLine Index of first line to copy - * @param endLine Index of last line to copy - */ - virtual void writeToStream (TerminalCharacterDecoder * decoder, - int startLine, int endLine); - - /** Returns the codec used to decode incoming characters. See setCodec() */ - const QTextCodec *codec () const - { - return _codec; - } - /** Sets the codec used to decode incoming characters. */ - void setCodec (const QTextCodec *); - - /** - * Convenience method. - * Returns true if the current codec used to decode incoming - * characters is UTF-8 - */ - bool utf8 () const - { - Q_ASSERT (_codec); - return _codec->mibEnum () == 106; - } - - - /** TODO Document me */ - virtual char eraseChar () const; - - /** - * Sets the key bindings used to key events - * ( received through sendKeyEvent() ) into character - * streams to send to the terminal. - */ - void setKeyBindings (const QString & name); - /** - * Returns the name of the emulation's current key bindings. - * See setKeyBindings() - */ - QString keyBindings () const; - - /** - * Copies the current image into the history and clears the screen. - */ - virtual void clearEntireScreen () = 0; - - /** Resets the state of the terminal. */ - virtual void reset () = 0; - - /** - * Returns true if the active terminal program wants - * mouse input events. - * - * The programUsesMouseChanged() signal is emitted when this - * changes. - */ - bool programUsesMouse () const; - - public slots: - /** Change the size of the emulation's image */ - virtual void setImageSize (int lines, int columns); - - /** - * Interprets a sequence of characters and sends the result to the terminal. - * This is equivalent to calling sendKeyEvent() for each character in @p text in succession. - */ - virtual void sendText (const QString & text) = 0; - - /** - * Interprets a key press event and emits the sendData() signal with - * the resulting character stream. - */ - virtual void sendKeyEvent (QKeyEvent *); - - /** - * Converts information about a mouse event into an xterm-compatible escape - * sequence and emits the character sequence via sendData() - */ - virtual void sendMouseEvent (int buttons, int column, int line, - int eventType); - - /** - * Sends a string of characters to the foreground terminal process. - * - * @param string The characters to send. - * @param length Length of @p string or if set to a negative value, @p string will - * be treated as a null-terminated string and its length will be determined automatically. - */ - virtual void sendString (const char *string, int length = -1) = 0; - - /** - * Processes an incoming stream of characters. receiveData() decodes the incoming - * character buffer using the current codec(), and then calls receiveChar() for - * each unicode character in the resulting buffer. - * - * receiveData() also starts a timer which causes the outputChanged() signal - * to be emitted when it expires. The timer allows multiple updates in quick - * succession to be buffered into a single outputChanged() signal emission. - * - * @param buffer A string of characters received from the terminal program. - * @param len The length of @p buffer - */ - void receiveData (const char *buffer, int len); - - signals: - /** - * Emitted when a buffer of data is ready to send to the - * standard input of the terminal. - * - * @param data The buffer of data ready to be sent - * @param len The length of @p data in bytes - */ - void sendData (const char *data, int len); - - /** - * Requests that sending of input to the emulation - * from the terminal process be suspended or resumed. - * - * @param suspend If true, requests that sending of - * input from the terminal process' stdout be - * suspended. Otherwise requests that sending of - * input be resumed. - */ - void lockPtyRequest (bool suspend); - - /** - * Requests that the pty used by the terminal process - * be set to UTF 8 mode. - * - * TODO: More documentation - */ - void useUtf8Request (bool); - - /** - * Emitted when the activity state of the emulation is set. - * - * @param state The new activity state, one of NOTIFYNORMAL, NOTIFYACTIVITY - * or NOTIFYBELL - */ - void stateSet (int state); - - /** - * Requests that the color of the text used - * to represent the tabs associated with this - * emulation be changed. This is a Konsole-specific - * extension from pre-KDE 4 times. - * - * TODO: Document how the parameter works. - */ - void changeTabTextColorRequest (int color); - - /** - * This is emitted when the program running in the shell indicates whether or - * not it is interested in mouse events. - * - * @param usesMouse This will be true if the program wants to be informed about - * mouse events or false otherwise. - */ - void programUsesMouseChanged (bool usesMouse); - - /** - * Emitted when the contents of the screen image change. - * The emulation buffers the updates from successive image changes, - * and only emits outputChanged() at sensible intervals when - * there is a lot of terminal activity. - * - * Normally there is no need for objects other than the screen windows - * created with createWindow() to listen for this signal. - * - * ScreenWindow objects created using createWindow() will emit their - * own outputChanged() signal in response to this signal. - */ - void outputChanged (); - - /** - * Emitted when the program running in the terminal wishes to update the - * session's title. This also allows terminal programs to customize other - * aspects of the terminal emulation display. - * - * This signal is emitted when the escape sequence "\033]ARG;VALUE\007" - * is received in the input string, where ARG is a number specifying what - * should change and VALUE is a string specifying the new value. - * - * TODO: The name of this method is not very accurate since this method - * is used to perform a whole range of tasks besides just setting - * the user-title of the session. - * - * @param title Specifies what to change. - *
    - *
  • 0 - Set window icon text and session title to @p newTitle
  • - *
  • 1 - Set window icon text to @p newTitle
  • - *
  • 2 - Set session title to @p newTitle
  • - *
  • 11 - Set the session's default background color to @p newTitle, - * where @p newTitle can be an HTML-style string ("#RRGGBB") or a named - * color (eg 'red', 'blue'). - * See http://doc.trolltech.com/4.2/qcolor.html#setNamedColor for more - * details. - *
  • - *
  • 31 - Supposedly treats @p newTitle as a URL and opens it (NOT IMPLEMENTED)
  • - *
  • 32 - Sets the icon associated with the session. @p newTitle is the name - * of the icon to use, which can be the name of any icon in the current KDE icon - * theme (eg: 'konsole', 'kate', 'folder_home')
  • - *
- * @param newTitle Specifies the new title - */ - - void titleChanged (int title, const QString & newTitle); - - /** - * Emitted when the program running in the terminal changes the - * screen size. - */ - void imageSizeChanged (int lineCount, int columnCount); - - /** - * Emitted when the terminal program requests to change various properties - * of the terminal display. - * - * A profile change command occurs when a special escape sequence, followed - * by a string containing a series of name and value pairs is received. - * This string can be parsed using a ProfileCommandParser instance. - * - * @param text A string expected to contain a series of key and value pairs in - * the form: name=value;name2=value2 ... - */ - void profileChangeCommandReceived (const QString & text); - - /** - * Emitted when a flow control key combination ( Ctrl+S or Ctrl+Q ) is pressed. - * @param suspendKeyPressed True if Ctrl+S was pressed to suspend output or Ctrl+Q to - * resume output. - */ - void flowControlKeyPressed (bool suspendKeyPressed); - -protected: - virtual void setMode (int mode) = 0; - virtual void resetMode (int mode) = 0; - - /** - * Processes an incoming character. See receiveData() - * @p ch A unicode character code. - */ - virtual void receiveChar (int ch); - - /** - * Sets the active screen. The terminal has two screens, primary and alternate. - * The primary screen is used by default. When certain interactive programs such - * as Vim are run, they trigger a switch to the alternate screen. - * - * @param index 0 to switch to the primary screen, or 1 to switch to the alternate screen - */ - void setScreen (int index); - - enum EmulationCodec - { - LocaleCodec = 0, - Utf8Codec = 1 - }; - void setCodec (EmulationCodec codec); // codec number, 0 = locale, 1=utf8 - - - QList < ScreenWindow * >_windows; - - Screen *_currentScreen; // pointer to the screen which is currently active, - // this is one of the elements in the screen[] array - - Screen *_screen[2]; // 0 = primary screen ( used by most programs, including the shell - // scrollbars are enabled in this mode ) - // 1 = alternate ( used by vi , emacs etc. - // scrollbars are not enabled in this mode ) - - - //decodes an incoming C-style character stream into a unicode QString using - //the current text codec. (this allows for rendering of non-ASCII characters in text files etc.) - const QTextCodec *_codec; - QTextDecoder *_decoder; - const KeyboardTranslator *_keyTranslator; // the keyboard layout - - protected slots: - /** - * Schedules an update of attached views. - * Repeated calls to bufferedUpdate() in close succession will result in only a single update, - * much like the Qt buffered update of widgets. - */ - void bufferedUpdate (); - - private slots: - // triggered by timer, causes the emulation to send an updated screen image to each - // view - void showBulk (); - - void usesMouseChanged (bool usesMouse); - -private: - bool _usesMouse; - QTimer _bulkTimer1; - QTimer _bulkTimer2; - -}; - -#endif // ifndef EMULATION_H diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/Filter.cpp --- a/gui/src/terminal/Filter.cpp Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,618 +0,0 @@ -/* - Copyright 2007-2008 by Robert Knight - - 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 "Filter.h" - -// System -#include - -// Qt -#include -#include -#include -#include -#include -#include -#include - -// Konsole -#include "TerminalCharacterDecoder.h" -#include "konsole_wcwidth.h" -#include "konsole_export.h" - -FilterChain::~FilterChain () -{ - QMutableListIterator < Filter * >iter (*this); - - while (iter.hasNext ()) - { - Filter *filter = iter.next (); - iter.remove (); - delete filter; - } -} - -void -FilterChain::addFilter (Filter * filter) -{ - append (filter); -} - -void -FilterChain::removeFilter (Filter * filter) -{ - removeAll (filter); -} - -bool -FilterChain::containsFilter (Filter * filter) -{ - return contains (filter); -} - -void -FilterChain::reset () -{ - QListIterator < Filter * >iter (*this); - while (iter.hasNext ()) - iter.next ()->reset (); -} - -void -FilterChain::setBuffer (const QString * buffer, - const QList < int >*linePositions) -{ - QListIterator < Filter * >iter (*this); - while (iter.hasNext ()) - iter.next ()->setBuffer (buffer, linePositions); -} - -void -FilterChain::process () -{ - QListIterator < Filter * >iter (*this); - while (iter.hasNext ()) - iter.next ()->process (); -} - -void -FilterChain::clear () -{ - QList < Filter * >::clear (); -} - -Filter::HotSpot * FilterChain::hotSpotAt (int line, int column) const -{ - QListIterator < Filter * >iter (*this); - while (iter.hasNext ()) - { - Filter * - filter = iter.next (); - Filter::HotSpot * spot = filter->hotSpotAt (line, column); - if (spot != 0) - { - return spot; - } - } - - return 0; -} - -QList < Filter::HotSpot * >FilterChain::hotSpots () const -{ - QList < Filter::HotSpot * >list; - QListIterator < Filter * >iter (*this); - while (iter.hasNext ()) - { - Filter * - filter = iter.next (); - list << filter->hotSpots (); - } - return list; -} - -//QList FilterChain::hotSpotsAtLine(int line) const; - -TerminalImageFilterChain::TerminalImageFilterChain ():_buffer (0), -_linePositions (0) -{ -} - -TerminalImageFilterChain::~TerminalImageFilterChain () -{ - delete _buffer; - delete _linePositions; -} - -void -TerminalImageFilterChain::setImage (const Character * const image, int lines, - int columns, - const QVector < LineProperty > - &lineProperties) -{ - if (empty ()) - return; - - // reset all filters and hotspots - reset (); - - PlainTextDecoder decoder; - decoder.setTrailingWhitespace (false); - - // setup new shared buffers for the filters to process on - QString *newBuffer = new QString (); - QList < int >*newLinePositions = new QList < int >(); - setBuffer (newBuffer, newLinePositions); - - // free the old buffers - delete _buffer; - delete _linePositions; - - _buffer = newBuffer; - _linePositions = newLinePositions; - - QTextStream lineStream (_buffer); - decoder.begin (&lineStream); - - for (int i = 0; i < lines; i++) - { - _linePositions->append (_buffer->length ()); - decoder.decodeLine (image + i * columns, columns, LINE_DEFAULT); - - // pretend that each line ends with a newline character. - // this prevents a link that occurs at the end of one line - // being treated as part of a link that occurs at the start of the next line - // - // the downside is that links which are spread over more than one line are not - // highlighted. - // - // TODO - Use the "line wrapped" attribute associated with lines in a - // terminal image to avoid adding this imaginary character for wrapped - // lines - if (!(lineProperties.value (i, LINE_DEFAULT) & LINE_WRAPPED)) - lineStream << QChar ('\n'); - } - decoder.end (); -} - -Filter::Filter (): -_linePositions (0), _buffer (0) -{ -} - -Filter::~Filter () -{ - QListIterator < HotSpot * >iter (_hotspotList); - while (iter.hasNext ()) - { - delete iter.next (); - } -} - -void -Filter::reset () -{ - _hotspots.clear (); - _hotspotList.clear (); -} - -void -Filter::setBuffer (const QString * buffer, const QList < int >*linePositions) -{ - _buffer = buffer; - _linePositions = linePositions; -} - -void -Filter::getLineColumn (int position, int &startLine, int &startColumn) -{ - Q_ASSERT (_linePositions); - Q_ASSERT (_buffer); - - - for (int i = 0; i < _linePositions->count (); i++) - { - int nextLine = 0; - - if (i == _linePositions->count () - 1) - nextLine = _buffer->length () + 1; - else - nextLine = _linePositions->value (i + 1); - - if (_linePositions->value (i) <= position && position < nextLine) - { - startLine = i; - startColumn = - string_width (buffer ()-> - mid (_linePositions->value (i), - position - _linePositions->value (i))); - return; - } - } -} - - -/*void Filter::addLine(const QString& text) -{ - _linePositions << _buffer.length(); - _buffer.append(text); -}*/ - -const QString * -Filter::buffer () -{ - return _buffer; -} - -Filter::HotSpot::~HotSpot () -{ -} - -void -Filter::addHotSpot (HotSpot * spot) -{ - _hotspotList << spot; - - for (int line = spot->startLine (); line <= spot->endLine (); line++) - { - _hotspots.insert (line, spot); - } -} - -QList < Filter::HotSpot * >Filter::hotSpots () const -{ - return _hotspotList; -} - -QList < Filter::HotSpot * >Filter::hotSpotsAtLine (int line) const -{ - return _hotspots.values (line); -} - -Filter::HotSpot * Filter::hotSpotAt (int line, int column) const -{ - QListIterator < HotSpot * >spotIter (_hotspots.values (line)); - - while (spotIter.hasNext ()) - { - HotSpot * - spot = spotIter.next (); - - if (spot->startLine () == line && spot->startColumn () > column) - continue; - if (spot->endLine () == line && spot->endColumn () < column) - continue; - - return spot; - } - - return 0; -} - -Filter::HotSpot::HotSpot (int startLine, int startColumn, int endLine, int endColumn):_startLine (startLine), _startColumn (startColumn), _endLine (endLine), -_endColumn (endColumn), -_type (NotSpecified) -{ -} - -QString -Filter::HotSpot::tooltip () const -{ - return QString (); -} - -QList < QAction * >Filter::HotSpot::actions () -{ - return QList < QAction * >(); -} - -int -Filter::HotSpot::startLine () const -{ - return _startLine; -} - -int -Filter::HotSpot::endLine () const -{ - return _endLine; -} - -int -Filter::HotSpot::startColumn () const -{ - return _startColumn; -} - -int -Filter::HotSpot::endColumn () const -{ - return _endColumn; -} - -Filter::HotSpot::Type Filter::HotSpot::type () const -{ - return _type; -} - -void -Filter::HotSpot::setType (Type type) -{ - _type = type; -} - -RegExpFilter::RegExpFilter () -{ -} - -RegExpFilter::HotSpot::HotSpot (int startLine, int startColumn, int endLine, - int endColumn): -Filter::HotSpot (startLine, startColumn, endLine, endColumn) -{ - setType (Marker); -} - -void -RegExpFilter::HotSpot::activate (QObject *) -{ -} - -void -RegExpFilter::HotSpot::setCapturedTexts (const QStringList & texts) -{ - _capturedTexts = texts; -} - -QStringList -RegExpFilter::HotSpot::capturedTexts () const -{ - return _capturedTexts; -} - -void -RegExpFilter::setRegExp (const QRegExp & regExp) -{ - _searchText = regExp; -} - -QRegExp -RegExpFilter::regExp () const -{ - return _searchText; -} - -/*void RegExpFilter::reset(int) -{ - _buffer = QString(); -}*/ -void -RegExpFilter::process () -{ - int pos = 0; - const QString *text = buffer (); - - Q_ASSERT (text); - - // ignore any regular expressions which match an empty string. - // otherwise the while loop below will run indefinitely - static const QString emptyString (""); - if (_searchText.exactMatch (emptyString)) - return; - - while (pos >= 0) - { - pos = _searchText.indexIn (*text, pos); - - if (pos >= 0) - { - int startLine = 0; - int endLine = 0; - int startColumn = 0; - int endColumn = 0; - - getLineColumn (pos, startLine, startColumn); - getLineColumn (pos + _searchText.matchedLength (), endLine, - endColumn); - - RegExpFilter::HotSpot * spot = newHotSpot (startLine, startColumn, - endLine, endColumn); - spot->setCapturedTexts (_searchText.capturedTexts ()); - - addHotSpot (spot); - pos += _searchText.matchedLength (); - - // if matchedLength == 0, the program will get stuck in an infinite loop - if (_searchText.matchedLength () == 0) - pos = -1; - } - } -} - -RegExpFilter::HotSpot * RegExpFilter::newHotSpot (int startLine, - int startColumn, - int endLine, int endColumn) -{ - return new RegExpFilter::HotSpot (startLine, startColumn, - endLine, endColumn); -} - -RegExpFilter::HotSpot * UrlFilter::newHotSpot (int startLine, int startColumn, - int endLine, int endColumn) -{ - return new UrlFilter::HotSpot (startLine, startColumn, endLine, endColumn); -} - -UrlFilter::HotSpot::HotSpot (int startLine, int startColumn, int endLine, int endColumn):RegExpFilter::HotSpot (startLine, startColumn, endLine, endColumn), -_urlObject (new - FilterObject (this)) -{ - setType (Link); -} - -QString -UrlFilter::HotSpot::tooltip () const -{ - QString - url = capturedTexts ().first (); - - const UrlType - kind = urlType (); - - if (kind == StandardUrl) - return QString (); - else if (kind == Email) - return QString (); - else - return QString (); -} - -UrlFilter::HotSpot::UrlType UrlFilter::HotSpot::urlType () const -{ - QString - url = capturedTexts ().first (); - - if (FullUrlRegExp.exactMatch (url)) - return StandardUrl; - else if (EmailAddressRegExp.exactMatch (url)) - return Email; - else - return Unknown; -} - -void -UrlFilter::HotSpot::activate (QObject * object) -{ - QString - url = capturedTexts ().first (); - - const UrlType - kind = urlType (); - - const - QString & - actionName = object ? object->objectName () : QString (); - - if (actionName == "copy-action") - { - QApplication::clipboard ()->setText (url); - return; - } - - if (!object || actionName == "open-action") - { - if (kind == StandardUrl) - { - // if the URL path does not include the protocol ( eg. "www.kde.org" ) then - // prepend http:// ( eg. "www.kde.org" --> "http://www.kde.org" ) - if (!url.contains ("://")) - { - url.prepend ("http://"); - } - } - else if (kind == Email) - { - url.prepend ("mailto:"); - } - - //new KRun(url,QApplication::activeWindow()); - } -} - -// Note: Altering these regular expressions can have a major effect on the performance of the filters -// used for finding URLs in the text, especially if they are very general and could match very long -// pieces of text. -// Please be careful when altering them. - -//regexp matches: -// full url: -// protocolname:// or www. followed by anything other than whitespaces, <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, comma and dot -const QRegExp -UrlFilter:: - -FullUrlRegExp -("(www\\.(?!\\.)|[a-z][a-z0-9+.-]*://)[^\\s<>'\"]+[^!,\\.\\s<>'\"\\]]"); -// email address: -// [word chars, dots or dashes]@[word chars, dots or dashes].[word chars] -const QRegExp -UrlFilter::EmailAddressRegExp ("\\b(\\w|\\.|-)+@(\\w|\\.|-)+\\.\\w+\\b"); - -// matches full url or email address -const QRegExp -UrlFilter::CompleteUrlRegExp ('(' + FullUrlRegExp.pattern () + '|' + - EmailAddressRegExp.pattern () + ')'); - -UrlFilter::UrlFilter () -{ - setRegExp (CompleteUrlRegExp); -} - -UrlFilter::HotSpot::~HotSpot () -{ - delete - _urlObject; -} - -void -FilterObject::activated () -{ - _filter->activate (sender ()); -} - -QList < QAction * >UrlFilter::HotSpot::actions () -{ - QList < QAction * >list; - - const UrlType - kind = urlType (); - - QAction * - openAction = new QAction (_urlObject); - QAction * - copyAction = new QAction (_urlObject);; - - Q_ASSERT (kind == StandardUrl || kind == Email); - - if (kind == StandardUrl) - { - openAction->setText (tr ((char *) "Open Link")); - copyAction->setText (tr ((char *) "Copy Link Address")); - } - else if (kind == Email) - { - openAction->setText (tr ((char *) "Send Email To...")); - copyAction->setText (tr ((char *) "Copy Email Address")); - } - - // object names are set here so that the hotspot performs the - // correct action when activated() is called with the triggered - // action passed as a parameter. - openAction->setObjectName (QLatin1String ("open-action")); - copyAction->setObjectName (QLatin1String ("copy-action")); - - QObject::connect (openAction, SIGNAL (triggered ()), _urlObject, - SLOT (activated ())); - QObject::connect (copyAction, SIGNAL (triggered ()), _urlObject, - SLOT (activated ())); - - list << openAction; - list << copyAction; - - return list; -} diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/Filter.h --- a/gui/src/terminal/Filter.h Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,379 +0,0 @@ -/* - Copyright 2007-2008 by Robert Knight - - 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 FILTER_H -#define FILTER_H - -// Qt -#include -#include -#include -#include -#include -#include - -// Local -#include "Character.h" - - -/** - * A filter processes blocks of text looking for certain patterns (such as URLs or keywords from a list) - * and marks the areas which match the filter's patterns as 'hotspots'. - * - * Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ), - * and an action. When the user performs some activity such as a mouse-click in a hotspot area ( the exact - * action will depend on what is displaying the block of text which the filter is processing ), the hotspot's - * activate() method should be called. Depending on the type of hotspot this will trigger a suitable response. - * - * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser. - * Hotspots may have more than one action, in which case the list of actions can be obtained using the - * actions() method. - * - * Different subclasses of filter will return different types of hotspot. - * Subclasses must reimplement the process() method to examine a block of text and identify sections of interest. - * When processing the text they should create instances of Filter::HotSpot subclasses for sections of interest - * and add them to the filter's list of hotspots using addHotSpot() - */ -class Filter -{ -public: - /** - * Represents an area of text which matched the pattern a particular filter has been looking for. - * - * Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ), - * and an action. When the user performs some activity such as a mouse-click in a hotspot area ( the exact - * action will depend on what is displaying the block of text which the filter is processing ), the hotspot's - * activate() method should be called. Depending on the type of hotspot this will trigger a suitable response. - * - * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser. - * Hotspots may have more than one action, in which case the list of actions can be obtained using the - * actions() method. These actions may then be displayed in a popup menu or toolbar for example. - */ - class HotSpot - { - public: - /** - * Constructs a new hotspot which covers the area from (@p startLine,@p startColumn) to (@p endLine,@p endColumn) - * in a block of text. - */ - HotSpot (int startLine, int startColumn, int endLine, int endColumn); - virtual ~ HotSpot (); - - enum Type - { - // the type of the hotspot is not specified - NotSpecified, - // this hotspot represents a clickable link - Link, - // this hotspot represents a marker - Marker - }; - - /** Returns the line when the hotspot area starts */ - int startLine () const; - /** Returns the line where the hotspot area ends */ - int endLine () const; - /** Returns the column on startLine() where the hotspot area starts */ - int startColumn () const; - /** Returns the column on endLine() where the hotspot area ends */ - int endColumn () const; - /** - * Returns the type of the hotspot. This is usually used as a hint for views on how to represent - * the hotspot graphically. eg. Link hotspots are typically underlined when the user mouses over them - */ - Type type () const; - /** - * Causes the an action associated with a hotspot to be triggered. - * - * @param object The object which caused the hotspot to be triggered. This is - * typically null ( in which case the default action should be performed ) or - * one of the objects from the actions() list. In which case the associated - * action should be performed. - */ - virtual void activate (QObject * object = 0) = 0; - /** - * Returns a list of actions associated with the hotspot which can be used in a - * menu or toolbar - */ - virtual QList < QAction * >actions (); - - /** - * Returns the text of a tooltip to be shown when the mouse moves over the hotspot, or - * an empty string if there is no tooltip associated with this hotspot. - * - * The default implementation returns an empty string. - */ - virtual QString tooltip () const; - - protected: - /** Sets the type of a hotspot. This should only be set once */ - void setType (Type type); - - private: - int _startLine; - int _startColumn; - int _endLine; - int _endColumn; - Type _type; - - }; - - /** Constructs a new filter. */ - Filter (); - virtual ~ Filter (); - - /** Causes the filter to process the block of text currently in its internal buffer */ - virtual void process () = 0; - - /** - * Empties the filters internal buffer and resets the line count back to 0. - * All hotspots are deleted. - */ - void reset (); - - /** Adds a new line of text to the filter and increments the line count */ - //void addLine(const QString& string); - - /** Returns the hotspot which covers the given @p line and @p column, or 0 if no hotspot covers that area */ - HotSpot *hotSpotAt (int line, int column) const; - - /** Returns the list of hotspots identified by the filter */ - QList < HotSpot * >hotSpots ()const; - - /** Returns the list of hotspots identified by the filter which occur on a given line */ - QList < HotSpot * >hotSpotsAtLine (int line) const; - - /** - * TODO: Document me - */ - void setBuffer (const QString * buffer, const QList < int >*linePositions); - -protected: - /** Adds a new hotspot to the list */ - void addHotSpot (HotSpot *); - /** Returns the internal buffer */ - const QString *buffer (); - /** Converts a character position within buffer() to a line and column */ - void getLineColumn (int position, int &startLine, int &startColumn); - -private: - QMultiHash < int, HotSpot * >_hotspots; - QList < HotSpot * >_hotspotList; - - const QList < int >*_linePositions; - const QString *_buffer; -}; - -/** - * A filter which searches for sections of text matching a regular expression and creates a new RegExpFilter::HotSpot - * instance for them. - * - * Subclasses can reimplement newHotSpot() to return custom hotspot types when matches for the regular expression - * are found. - */ -class RegExpFilter:public Filter -{ -public: - /** - * Type of hotspot created by RegExpFilter. The capturedTexts() method can be used to find the text - * matched by the filter's regular expression. - */ - class HotSpot:public Filter::HotSpot - { - public: - HotSpot (int startLine, int startColumn, int endLine, int endColumn); - virtual void activate (QObject * object = 0); - - /** Sets the captured texts associated with this hotspot */ - void setCapturedTexts (const QStringList & texts); - /** Returns the texts found by the filter when matching the filter's regular expression */ - QStringList capturedTexts () const; - private: - QStringList _capturedTexts; - }; - - /** Constructs a new regular expression filter */ - RegExpFilter (); - - /** - * Sets the regular expression which the filter searches for in blocks of text. - * - * Regular expressions which match the empty string are treated as not matching - * anything. - */ - void setRegExp (const QRegExp & text); - /** Returns the regular expression which the filter searches for in blocks of text */ - QRegExp regExp () const; - - /** - * Reimplemented to search the filter's text buffer for text matching regExp() - * - * If regexp matches the empty string, then process() will return immediately - * without finding results. - */ - virtual void process (); - -protected: - /** - * Called when a match for the regular expression is encountered. Subclasses should reimplement this - * to return custom hotspot types - */ - virtual RegExpFilter::HotSpot * newHotSpot (int startLine, int startColumn, - int endLine, int endColumn); - -private: - QRegExp _searchText; -}; - -class FilterObject; - -/** A filter which matches URLs in blocks of text */ -class UrlFilter:public RegExpFilter -{ -public: - /** - * Hotspot type created by UrlFilter instances. The activate() method opens a web browser - * at the given URL when called. - */ - class HotSpot:public RegExpFilter::HotSpot - { - public: - HotSpot (int startLine, int startColumn, int endLine, int endColumn); - virtual ~ HotSpot (); - - virtual QList < QAction * >actions (); - - /** - * Open a web browser at the current URL. The url itself can be determined using - * the capturedTexts() method. - */ - virtual void activate (QObject * object = 0); - - virtual QString tooltip () const; - private: - enum UrlType - { - StandardUrl, - Email, - Unknown - }; - UrlType urlType () const; - - FilterObject *_urlObject; - }; - - UrlFilter (); - -protected: - virtual RegExpFilter::HotSpot * newHotSpot (int, int, int, int); - -private: - - static const QRegExp FullUrlRegExp; - static const QRegExp EmailAddressRegExp; - - // combined OR of FullUrlRegExp and EmailAddressRegExp - static const QRegExp CompleteUrlRegExp; -}; - -class FilterObject:public QObject -{ -Q_OBJECT public: - FilterObject (Filter::HotSpot * filter):_filter (filter) - { - } - private slots:void activated (); -private: - Filter::HotSpot * _filter; -}; - -/** - * A chain which allows a group of filters to be processed as one. - * The chain owns the filters added to it and deletes them when the chain itself is destroyed. - * - * Use addFilter() to add a new filter to the chain. - * When new text to be filtered arrives, use addLine() to add each additional - * line of text which needs to be processed and then after adding the last line, use - * process() to cause each filter in the chain to process the text. - * - * After processing a block of text, the reset() method can be used to set the filter chain's - * internal cursor back to the first line. - * - * The hotSpotAt() method will return the first hotspot which covers a given position. - * - * The hotSpots() and hotSpotsAtLine() method return all of the hotspots in the text and on - * a given line respectively. - */ -class FilterChain:protected QList < Filter * > -{ -public: - virtual ~ FilterChain (); - - /** Adds a new filter to the chain. The chain will delete this filter when it is destroyed */ - void addFilter (Filter * filter); - /** Removes a filter from the chain. The chain will no longer delete the filter when destroyed */ - void removeFilter (Filter * filter); - /** Returns true if the chain contains @p filter */ - bool containsFilter (Filter * filter); - /** Removes all filters from the chain */ - void clear (); - - /** Resets each filter in the chain */ - void reset (); - /** - * Processes each filter in the chain - */ - void process (); - - /** Sets the buffer for each filter in the chain to process. */ - void setBuffer (const QString * buffer, const QList < int >*linePositions); - - /** Returns the first hotspot which occurs at @p line, @p column or 0 if no hotspot was found */ - Filter::HotSpot * hotSpotAt (int line, int column) const; - /** Returns a list of all the hotspots in all the chain's filters */ - QList < Filter::HotSpot * >hotSpots () const; - /** Returns a list of all hotspots at the given line in all the chain's filters */ - QList < Filter::HotSpot > hotSpotsAtLine (int line) const; - -}; - -/** A filter chain which processes character images from terminal displays */ -class TerminalImageFilterChain:public FilterChain -{ -public: - TerminalImageFilterChain (); - virtual ~ TerminalImageFilterChain (); - - /** - * Set the current terminal image to @p image. - * - * @param image The terminal image - * @param lines The number of lines in the terminal image - * @param columns The number of columns in the terminal image - * @param lineProperties The line properties to set for image - */ - void setImage (const Character * const image, int lines, int columns, - const QVector < LineProperty > &lineProperties); - -private: - QString * _buffer; - QList < int >*_linePositions; -}; - -#endif //FILTER_H diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/QTerminalWidget.cpp --- a/gui/src/terminal/QTerminalWidget.cpp Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -/* Copyright (C) 2008 e_k (e_k@users.sourceforge.net) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "QTerminalWidget.h" -#include "Session.h" -#include "TerminalDisplay.h" - -struct TermWidgetImpl -{ - TermWidgetImpl (QWidget * parent = 0); - - TerminalDisplay *m_terminalDisplay; - Session *m_session; - Session *createSession (); - TerminalDisplay *createTerminalDisplay (QWidget * parent); -}; - -TermWidgetImpl::TermWidgetImpl (QWidget * parent) -{ - QPalette palette = QApplication::palette (); - m_session = createSession (); - m_terminalDisplay = createTerminalDisplay (parent); - m_terminalDisplay->setBackgroundColor (palette.color (QPalette::Base)); - m_terminalDisplay->setForegroundColor (palette.color (QPalette::Text)); -} - -Session * -TermWidgetImpl::createSession () -{ - Session *session = new Session (); - session->setTitle (Session::NameRole, "QTerminalWidget"); - session->setProgram ("/bin/bash"); - session->setArguments (QStringList ()); - session->setAutoClose (true); - session->setCodec (QTextCodec::codecForName ("UTF-8")); - session->setFlowControlEnabled (true); - session->setHistoryType (HistoryTypeBuffer (1000)); - session->setDarkBackground (true); - session->setKeyBindings (""); - return session; -} - -TerminalDisplay * -TermWidgetImpl::createTerminalDisplay (QWidget * parent) -{ - TerminalDisplay *display = new TerminalDisplay (parent); - display->setBellMode (TerminalDisplay::NotifyBell); - display->setTerminalSizeHint (true); - display->setTripleClickMode (TerminalDisplay::SelectWholeLine); - display->setTerminalSizeStartup (true); - return display; -} - -QTerminalWidget::QTerminalWidget (int startnow, QWidget * parent):QWidget - (parent) -{ - m_impl = new TermWidgetImpl (this); - - initialize (); - - if (startnow && m_impl->m_session) - { - m_impl->m_session->run (); - } - - setFocus (Qt::OtherFocusReason); - m_impl->m_terminalDisplay->resize (this->size ()); - setFocusProxy (m_impl->m_terminalDisplay); -} - -void -QTerminalWidget::initialize () -{ - m_impl->m_terminalDisplay->setSize (80, 40); - - QFont font = QApplication::font (); - font.setFamily ("Monospace"); - font.setPointSize (10); - font.setStyleHint (QFont::TypeWriter); - m_impl->m_terminalDisplay->setVTFont (font); - m_impl->m_terminalDisplay->setScrollBarPosition (TerminalDisplay::ScrollBarRight); - - m_impl->m_session->addView (m_impl->m_terminalDisplay); - - connect (m_impl->m_session, SIGNAL (finished ()), this, - SLOT (sessionFinished ())); -} - -QTerminalWidget::~QTerminalWidget () -{ - emit destroyed (); -} - -void -QTerminalWidget::openTeletype (int fd) -{ - m_impl->m_session->openTeletype (fd); -} - -void -QTerminalWidget::setTextCodec (QTextCodec * codec) -{ - if (!m_impl->m_session) - return; - m_impl->m_session->setCodec (codec); -} - -void -QTerminalWidget::setSize (int h, int v) -{ - if (!m_impl->m_terminalDisplay) - return; - m_impl->m_terminalDisplay->setSize (h, v); -} - -void -QTerminalWidget::setHistorySize (int lines) -{ - if (lines < 0) - m_impl->m_session->setHistoryType (HistoryTypeFile ()); - else - m_impl->m_session->setHistoryType (HistoryTypeBuffer (lines)); -} - -void -QTerminalWidget::sendText (const QString & text) -{ - m_impl->m_session->sendText (text); -} - -void -QTerminalWidget::resizeEvent (QResizeEvent *) -{ - m_impl->m_terminalDisplay->resize (this->size ()); - m_impl->m_terminalDisplay->update (); -} - -void -QTerminalWidget::sessionFinished () -{ - emit finished (); -} diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/QTerminalWidget.h --- a/gui/src/terminal/QTerminalWidget.h Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* Copyright (C) 2008 e_k (e_k@users.sourceforge.net) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef QTERMINALWIDGET_H -#define QTERMINALWIDGET_H - -#include - -struct TermWidgetImpl; -/** - * \class QTerminalWidget - * This class forms a widget class that can be inserted into other widgets. - */ -class QTerminalWidget:public QWidget -{ - Q_OBJECT -public: - QTerminalWidget (int startnow = 1, QWidget * parent = 0); - ~QTerminalWidget (); - - void openTeletype (int fd); - - /** Text codec, default is UTF-8. */ - void setTextCodec (QTextCodec * codec); - - /** Resize terminal widget. */ - void setSize (int h, int v); - - /** History size for scrolling, values below zero mean infinite. */ - void setHistorySize (int lines); - - /** Send some text to the terminal. */ - void sendText (const QString & text); - -signals: - /** Emitted, when the current program has finished. */ - void finished (); - -protected: - virtual void resizeEvent (QResizeEvent *); - -protected slots: - void sessionFinished (); - -private: - /** Performs initial operations on this widget. */ - void initialize (); - TermWidgetImpl *m_impl; -}; - -#endif // QTERMINALWIDGET_H diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/Screen.cpp --- a/gui/src/terminal/Screen.cpp Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1528 +0,0 @@ -/* - This file is part of Konsole, an X terminal. - - Copyright 2007-2008 by Robert Knight - Copyright 1997,1998 by Lars Doelle - - 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 "Screen.h" - -// Standard -#include -#include -#include -#include -#include -#include - -// Qt -#include -#include - - -// Konsole -#include "konsole_wcwidth.h" -#include "TerminalCharacterDecoder.h" - -//FIXME: this is emulation specific. Use false for xterm, true for ANSI. -//FIXME: see if we can get this from terminfo. -#define BS_CLEARS false - -//Macro to convert x,y position on screen to position within an image. -// -//Originally the image was stored as one large contiguous block of -//memory, so a position within the image could be represented as an -//offset from the beginning of the block. For efficiency reasons this -//is no longer the case. -//Many internal parts of this class still use this representation for parameters and so on, -//notably moveImage() and clearImage(). -//This macro converts from an X,Y position into an image offset. -#ifndef loc -#define loc(X,Y) ((Y)*columns+(X)) -#endif - - -Character - Screen::defaultChar = Character (' ', - CharacterColor (COLOR_SPACE_DEFAULT, - DEFAULT_FORE_COLOR), - CharacterColor (COLOR_SPACE_DEFAULT, - DEFAULT_BACK_COLOR), - DEFAULT_RENDITION); - -//#define REVERSE_WRAPPED_LINES // for wrapped line debug - -Screen::Screen (int l, int c): -lines (l), -columns (c), -screenLines (new ImageLine[lines + 1]), -_scrolledLines (0), -_droppedLines (0), -history (new HistoryScrollNone ()), -cuX (0), -cuY (0), -currentRendition (0), -_topMargin (0), -_bottomMargin (0), -selBegin (0), -selTopLeft (0), -selBottomRight (0), -blockSelectionMode (false), -effectiveForeground (CharacterColor ()), -effectiveBackground (CharacterColor ()), -effectiveRendition (0), -lastPos (-1) -{ - lineProperties.resize (lines + 1); - for (int i = 0; i < lines + 1; i++) - lineProperties[i] = LINE_DEFAULT; - - initTabStops (); - clearSelection (); - reset (); -} - -/*! Destructor -*/ - -Screen::~Screen () -{ - delete[]screenLines; - delete history; -} - -void -Screen::cursorUp (int n) - //=CUU -{ - if (n == 0) - n = 1; // Default - int stop = cuY < _topMargin ? 0 : _topMargin; - cuX = qMin (columns - 1, cuX); // nowrap! - cuY = qMax (stop, cuY - n); -} - -void -Screen::cursorDown (int n) - //=CUD -{ - if (n == 0) - n = 1; // Default - int stop = cuY > _bottomMargin ? lines - 1 : _bottomMargin; - cuX = qMin (columns - 1, cuX); // nowrap! - cuY = qMin (stop, cuY + n); -} - -void -Screen::cursorLeft (int n) - //=CUB -{ - if (n == 0) - n = 1; // Default - cuX = qMin (columns - 1, cuX); // nowrap! - cuX = qMax (0, cuX - n); -} - -void -Screen::cursorRight (int n) - //=CUF -{ - if (n == 0) - n = 1; // Default - cuX = qMin (columns - 1, cuX + n); -} - -void -Screen::setMargins (int top, int bot) - //=STBM -{ - if (top == 0) - top = 1; // Default - if (bot == 0) - bot = lines; // Default - top = top - 1; // Adjust to internal lineno - bot = bot - 1; // Adjust to internal lineno - if (!(0 <= top && top < bot && bot < lines)) - { //Debug()<<" setRegion("< 0) - cuY -= 1; -} - -void -Screen::nextLine () - //=NEL -{ - toStartOfLine (); - index (); -} - -void -Screen::eraseChars (int n) -{ - if (n == 0) - n = 1; // Default - int p = qMax (0, qMin (cuX + n - 1, columns - 1)); - clearImage (loc (cuX, cuY), loc (p, cuY), ' '); -} - -void -Screen::deleteChars (int n) -{ - Q_ASSERT (n >= 0); - - // always delete at least one char - if (n == 0) - n = 1; - - // if cursor is beyond the end of the line there is nothing to do - if (cuX >= screenLines[cuY].count ()) - return; - - if (cuX + n > screenLines[cuY].count ()) - n = screenLines[cuY].count () - cuX; - - Q_ASSERT (n >= 0); - Q_ASSERT (cuX + n <= screenLines[cuY].count ()); - - screenLines[cuY].remove (cuX, n); -} - -void -Screen::insertChars (int n) -{ - if (n == 0) - n = 1; // Default - - if (screenLines[cuY].size () < cuX) - screenLines[cuY].resize (cuX); - - screenLines[cuY].insert (cuX, n, ' '); - - if (screenLines[cuY].count () > columns) - screenLines[cuY].resize (columns); -} - -void -Screen::deleteLines (int n) -{ - if (n == 0) - n = 1; // Default - scrollUp (cuY, n); -} - -void -Screen::insertLines (int n) -{ - if (n == 0) - n = 1; // Default - scrollDown (cuY, n); -} - -void -Screen::setMode (int m) -{ - currentModes[m] = true; - switch (m) - { - case MODE_Origin: - cuX = 0; - cuY = _topMargin; - break; //FIXME: home - } -} - -void -Screen::resetMode (int m) -{ - currentModes[m] = false; - switch (m) - { - case MODE_Origin: - cuX = 0; - cuY = 0; - break; //FIXME: home - } -} - -void -Screen::saveMode (int m) -{ - savedModes[m] = currentModes[m]; -} - -void -Screen::restoreMode (int m) -{ - currentModes[m] = savedModes[m]; -} - -bool -Screen::getMode (int m) const -{ - return currentModes[m]; -} - -void -Screen::saveCursor () -{ - savedState.cursorColumn = cuX; - savedState.cursorLine = cuY; - savedState.rendition = currentRendition; - savedState.foreground = currentForeground; - savedState.background = currentBackground; -} - -void -Screen::restoreCursor () -{ - cuX = qMin (savedState.cursorColumn, columns - 1); - cuY = qMin (savedState.cursorLine, lines - 1); - currentRendition = savedState.rendition; - currentForeground = savedState.foreground; - currentBackground = savedState.background; - updateEffectiveRendition (); -} - -void -Screen::resizeImage (int new_lines, int new_columns) -{ - if ((new_lines == lines) && (new_columns == columns)) - return; - - if (cuY > new_lines - 1) - { // attempt to preserve focus and lines - _bottomMargin = lines - 1; //FIXME: margin lost - for (int i = 0; i < cuY - (new_lines - 1); i++) - { - addHistLine (); - scrollUp (0, 1); - } - } - - // create new screen lines and copy from old to new - - ImageLine *newScreenLines = new ImageLine[new_lines + 1]; - for (int i = 0; i < qMin (lines - 1, new_lines + 1); i++) - newScreenLines[i] = screenLines[i]; - for (int i = lines; (i > 0) && (i < new_lines + 1); i++) - newScreenLines[i].resize (new_columns); - - lineProperties.resize (new_lines + 1); - for (int i = lines; (i > 0) && (i < new_lines + 1); i++) - lineProperties[i] = LINE_DEFAULT; - - clearSelection (); - - delete[]screenLines; - screenLines = newScreenLines; - - lines = new_lines; - columns = new_columns; - cuX = qMin (cuX, columns - 1); - cuY = qMin (cuY, lines - 1); - - // FIXME: try to keep values, evtl. - _topMargin = 0; - _bottomMargin = lines - 1; - initTabStops (); - clearSelection (); -} - -void -Screen::setDefaultMargins () -{ - _topMargin = 0; - _bottomMargin = lines - 1; -} - - -/* - Clarifying rendition here and in the display. - - currently, the display's color table is - 0 1 2 .. 9 10 .. 17 - dft_fg, dft_bg, dim 0..7, intensive 0..7 - - currentForeground, currentBackground contain values 0..8; - - 0 = default color - - 1..8 = ansi specified color - - re_fg, re_bg contain values 0..17 - due to the TerminalDisplay's color table - - rendition attributes are - - attr widget screen - -------------- ------ ------ - RE_UNDERLINE XX XX affects foreground only - RE_BLINK XX XX affects foreground only - RE_BOLD XX XX affects foreground only - RE_REVERSE -- XX - RE_TRANSPARENT XX -- affects background only - RE_INTENSIVE XX -- affects foreground only - - Note that RE_BOLD is used in both widget - and screen rendition. Since xterm/vt102 - is to poor to distinguish between bold - (which is a font attribute) and intensive - (which is a color attribute), we translate - this and RE_BOLD in falls eventually appart - into RE_BOLD and RE_INTENSIVE. - */ - -void -Screen::reverseRendition (Character & p) const -{ - CharacterColor f = p.foregroundColor; - CharacterColor b = p.backgroundColor; - - p.foregroundColor = b; - p.backgroundColor = f; //p->r &= ~RE_TRANSPARENT; -} - -void -Screen::updateEffectiveRendition () -{ - effectiveRendition = currentRendition; - if (currentRendition & RE_REVERSE) - { - effectiveForeground = currentBackground; - effectiveBackground = currentForeground; - } - else - { - effectiveForeground = currentForeground; - effectiveBackground = currentBackground; - } - - if (currentRendition & RE_BOLD) - effectiveForeground.toggleIntensive (); -} - -void -Screen::copyFromHistory (Character * dest, int startLine, int count) const -{ - Q_ASSERT (startLine >= 0 && count > 0 - && startLine + count <= history->getLines ()); - - for (int line = startLine; line < startLine + count; line++) - { - const int length = qMin (columns, history->getLineLen (line)); - const int destLineOffset = (line - startLine) * columns; - - history->getCells (line, 0, length, dest + destLineOffset); - - for (int column = length; column < columns; column++) - dest[destLineOffset + column] = defaultChar; - - // invert selected text - if (selBegin != -1) - { - for (int column = 0; column < columns; column++) - { - if (isSelected (column, line)) - { - reverseRendition (dest[destLineOffset + column]); - } - } - } - } -} - -void -Screen::copyFromScreen (Character * dest, int startLine, int count) const -{ - Q_ASSERT (startLine >= 0 && count > 0 && startLine + count <= lines); - - for (int line = startLine; line < (startLine + count); line++) - { - int srcLineStartIndex = line * columns; - int destLineStartIndex = (line - startLine) * columns; - - for (int column = 0; column < columns; column++) - { - int srcIndex = srcLineStartIndex + column; - int destIndex = destLineStartIndex + column; - - dest[destIndex] = - screenLines[srcIndex / columns].value (srcIndex % columns, - defaultChar); - - // invert selected text - if (selBegin != -1 - && isSelected (column, line + history->getLines ())) - reverseRendition (dest[destIndex]); - } - - } -} - -void -Screen::getImage (Character * dest, int size, int startLine, int endLine) const -{ - Q_ASSERT (startLine >= 0); - Q_ASSERT (endLine >= startLine && endLine < history->getLines () + lines); - - const int mergedLines = endLine - startLine + 1; - - Q_ASSERT (size >= mergedLines * columns); - Q_UNUSED (size); - - const int linesInHistoryBuffer = - qBound (0, history->getLines () - startLine, mergedLines); - const int linesInScreenBuffer = mergedLines - linesInHistoryBuffer; - - // copy lines from history buffer - if (linesInHistoryBuffer > 0) - copyFromHistory (dest, startLine, linesInHistoryBuffer); - - // copy lines from screen buffer - if (linesInScreenBuffer > 0) - copyFromScreen (dest + linesInHistoryBuffer * columns, - startLine + linesInHistoryBuffer - history->getLines (), - linesInScreenBuffer); - - // invert display when in screen mode - if (getMode (MODE_Screen)) - { - for (int i = 0; i < mergedLines * columns; i++) - reverseRendition (dest[i]); // for reverse display - } - - // mark the character at the current cursor position - int cursorIndex = loc (cuX, cuY + linesInHistoryBuffer); - if (getMode (MODE_Cursor) && cursorIndex < columns * mergedLines) - dest[cursorIndex].rendition |= RE_CURSOR; -} - -QVector < LineProperty > Screen::getLineProperties (int startLine, - int endLine) const -{ - Q_ASSERT (startLine >= 0); - Q_ASSERT (endLine >= startLine && endLine < history->getLines () + lines); - - const int - mergedLines = endLine - startLine + 1; - const int - linesInHistory = - qBound (0, history->getLines () - startLine, mergedLines); - const int - linesInScreen = mergedLines - linesInHistory; - - QVector < LineProperty > result (mergedLines); - int - index = 0; - - // copy properties for lines in history - for (int line = startLine; line < startLine + linesInHistory; line++) - { - //TODO Support for line properties other than wrapped lines - if (history->isWrappedLine (line)) - { - result[index] = (LineProperty) (result[index] | LINE_WRAPPED); - } - index++; - } - - // copy properties for lines in screen buffer - const int - firstScreenLine = startLine + linesInHistory - history->getLines (); - for (int line = firstScreenLine; line < firstScreenLine + linesInScreen; - line++) - { - result[index] = lineProperties[line]; - index++; - } - - return result; -} - -void -Screen::reset (bool clearScreen) -{ - setMode (MODE_Wrap); - saveMode (MODE_Wrap); // wrap at end of margin - resetMode (MODE_Origin); - saveMode (MODE_Origin); // position refere to [1,1] - resetMode (MODE_Insert); - saveMode (MODE_Insert); // overstroke - setMode (MODE_Cursor); // cursor visible - resetMode (MODE_Screen); // screen not inverse - resetMode (MODE_NewLine); - - _topMargin = 0; - _bottomMargin = lines - 1; - - setDefaultRendition (); - saveCursor (); - - if (clearScreen) - clear (); -} - -void -Screen::clear () -{ - clearEntireScreen (); - home (); -} - -void -Screen::backspace () -{ - cuX = qMin (columns - 1, cuX); // nowrap! - cuX = qMax (0, cuX - 1); - - if (screenLines[cuY].size () < cuX + 1) - screenLines[cuY].resize (cuX + 1); - - if (BS_CLEARS) - screenLines[cuY][cuX].character = ' '; -} - -void -Screen::tab (int n) -{ - // note that TAB is a format effector (does not write ' '); - if (n == 0) - n = 1; - while ((n > 0) && (cuX < columns - 1)) - { - cursorRight (1); - while ((cuX < columns - 1) && !tabStops[cuX]) - cursorRight (1); - n--; - } -} - -void -Screen::backtab (int n) -{ - // note that TAB is a format effector (does not write ' '); - if (n == 0) - n = 1; - while ((n > 0) && (cuX > 0)) - { - cursorLeft (1); - while ((cuX > 0) && !tabStops[cuX]) - cursorLeft (1); - n--; - } -} - -void -Screen::clearTabStops () -{ - for (int i = 0; i < columns; i++) - tabStops[i] = false; -} - -void -Screen::changeTabStop (bool set) -{ - if (cuX >= columns) - return; - tabStops[cuX] = set; -} - -void -Screen::initTabStops () -{ - tabStops.resize (columns); - - // Arrg! The 1st tabstop has to be one longer than the other. - // i.e. the kids start counting from 0 instead of 1. - // Other programs might behave correctly. Be aware. - for (int i = 0; i < columns; i++) - tabStops[i] = (i % 8 == 0 && i != 0); -} - -void -Screen::newLine () -{ - if (getMode (MODE_NewLine)) - toStartOfLine (); - index (); -} - -void -Screen::checkSelection (int from, int to) -{ - if (selBegin == -1) - return; - int scr_TL = loc (0, history->getLines ()); - //Clear entire selection if it overlaps region [from, to] - if ((selBottomRight >= (from + scr_TL)) && (selTopLeft <= (to + scr_TL))) - clearSelection (); -} - -void -Screen::displayCharacter (unsigned short c) -{ - // Note that VT100 does wrapping BEFORE putting the character. - // This has impact on the assumption of valid cursor positions. - // We indicate the fact that a newline has to be triggered by - // putting the cursor one right to the last column of the screen. - - int w = konsole_wcwidth (c); - if (w <= 0) - return; - - if (cuX + w > columns) - { - if (getMode (MODE_Wrap)) - { - lineProperties[cuY] = - (LineProperty) (lineProperties[cuY] | LINE_WRAPPED); - nextLine (); - } - else - cuX = columns - w; - } - - // ensure current line vector has enough elements - int size = screenLines[cuY].size (); - if (size < cuX + w) - { - screenLines[cuY].resize (cuX + w); - } - - if (getMode (MODE_Insert)) - insertChars (w); - - lastPos = loc (cuX, cuY); - - // check if selection is still valid. - checkSelection (lastPos, lastPos); - - Character & currentChar = screenLines[cuY][cuX]; - - currentChar.character = c; - currentChar.foregroundColor = effectiveForeground; - currentChar.backgroundColor = effectiveBackground; - currentChar.rendition = effectiveRendition; - - int i = 0; - int newCursorX = cuX + w--; - while (w) - { - i++; - - if (screenLines[cuY].size () < cuX + i + 1) - screenLines[cuY].resize (cuX + i + 1); - - Character & ch = screenLines[cuY][cuX + i]; - ch.character = 0; - ch.foregroundColor = effectiveForeground; - ch.backgroundColor = effectiveBackground; - ch.rendition = effectiveRendition; - - w--; - } - cuX = newCursorX; -} - -void -Screen::compose (const QString & /*compose */ ) -{ - Q_ASSERT (0 /*Not implemented yet */ ); - - /* if (lastPos == -1) - return; - - QChar c(image[lastPos].character); - compose.prepend(c); - //compose.compose(); ### FIXME! - image[lastPos].character = compose[0].unicode(); */ -} - -int -Screen::scrolledLines () const -{ - return _scrolledLines; -} - -int -Screen::droppedLines () const -{ - return _droppedLines; -} - -void -Screen::resetDroppedLines () -{ - _droppedLines = 0; -} - -void -Screen::resetScrolledLines () -{ - _scrolledLines = 0; -} - -void -Screen::scrollUp (int n) -{ - if (n == 0) - n = 1; // Default - if (_topMargin == 0) - addHistLine (); // history.history - scrollUp (_topMargin, n); -} - -QRect -Screen::lastScrolledRegion () const -{ - return _lastScrolledRegion; -} - -void -Screen::scrollUp (int from, int n) -{ - if (n <= 0 || from + n > _bottomMargin) - return; - - _scrolledLines -= n; - _lastScrolledRegion = - QRect (0, _topMargin, columns - 1, (_bottomMargin - _topMargin)); - - //FIXME: make sure `topMargin', `bottomMargin', `from', `n' is in bounds. - moveImage (loc (0, from), loc (0, from + n), - loc (columns - 1, _bottomMargin)); - clearImage (loc (0, _bottomMargin - n + 1), - loc (columns - 1, _bottomMargin), ' '); -} - -void -Screen::scrollDown (int n) -{ - if (n == 0) - n = 1; // Default - scrollDown (_topMargin, n); -} - -void -Screen::scrollDown (int from, int n) -{ - _scrolledLines += n; - - //FIXME: make sure `topMargin', `bottomMargin', `from', `n' is in bounds. - if (n <= 0) - return; - if (from > _bottomMargin) - return; - if (from + n > _bottomMargin) - n = _bottomMargin - from; - moveImage (loc (0, from + n), loc (0, from), - loc (columns - 1, _bottomMargin - n)); - clearImage (loc (0, from), loc (columns - 1, from + n - 1), ' '); -} - -void -Screen::setCursorYX (int y, int x) -{ - setCursorY (y); - setCursorX (x); -} - -void -Screen::setCursorX (int x) -{ - if (x == 0) - x = 1; // Default - x -= 1; // Adjust - cuX = qMax (0, qMin (columns - 1, x)); -} - -void -Screen::setCursorY (int y) -{ - if (y == 0) - y = 1; // Default - y -= 1; // Adjust - cuY = - qMax (0, qMin (lines - 1, y + (getMode (MODE_Origin) ? _topMargin : 0))); -} - -void -Screen::home () -{ - cuX = 0; - cuY = 0; -} - -void -Screen::toStartOfLine () -{ - cuX = 0; -} - -int -Screen::getCursorX () const -{ - return cuX; -} - -int -Screen::getCursorY () const -{ - return cuY; -} - -void -Screen::clearImage (int loca, int loce, char c) -{ - int scr_TL = loc (0, history->getLines ()); - //FIXME: check positions - - //Clear entire selection if it overlaps region to be moved... - if ((selBottomRight > (loca + scr_TL)) && (selTopLeft < (loce + scr_TL))) - { - clearSelection (); - } - - int topLine = loca / columns; - int bottomLine = loce / columns; - - Character clearCh (c, currentForeground, currentBackground, - DEFAULT_RENDITION); - - //if the character being used to clear the area is the same as the - //default character, the affected lines can simply be shrunk. - bool isDefaultCh = (clearCh == Character ()); - - for (int y = topLine; y <= bottomLine; y++) - { - lineProperties[y] = 0; - - int endCol = (y == bottomLine) ? loce % columns : columns - 1; - int startCol = (y == topLine) ? loca % columns : 0; - - QVector < Character > &line = screenLines[y]; - - if (isDefaultCh && endCol == columns - 1) - { - line.resize (startCol); - } - else - { - if (line.size () < endCol + 1) - line.resize (endCol + 1); - - Character *data = line.data (); - for (int i = startCol; i <= endCol; i++) - data[i] = clearCh; - } - } -} - -void -Screen::moveImage (int dest, int sourceBegin, int sourceEnd) -{ - Q_ASSERT (sourceBegin <= sourceEnd); - - int lines = (sourceEnd - sourceBegin) / columns; - - //move screen image and line properties: - //the source and destination areas of the image may overlap, - //so it matters that we do the copy in the right order - - //forwards if dest < sourceBegin or backwards otherwise. - //(search the web for 'memmove implementation' for details) - if (dest < sourceBegin) - { - for (int i = 0; i <= lines; i++) - { - screenLines[(dest / columns) + i] = - screenLines[(sourceBegin / columns) + i]; - lineProperties[(dest / columns) + i] = - lineProperties[(sourceBegin / columns) + i]; - } - } - else - { - for (int i = lines; i >= 0; i--) - { - screenLines[(dest / columns) + i] = - screenLines[(sourceBegin / columns) + i]; - lineProperties[(dest / columns) + i] = - lineProperties[(sourceBegin / columns) + i]; - } - } - - if (lastPos != -1) - { - int diff = dest - sourceBegin; // Scroll by this amount - lastPos += diff; - if ((lastPos < 0) || (lastPos >= (lines * columns))) - lastPos = -1; - } - - // Adjust selection to follow scroll. - if (selBegin != -1) - { - bool beginIsTL = (selBegin == selTopLeft); - int diff = dest - sourceBegin; // Scroll by this amount - int scr_TL = loc (0, history->getLines ()); - int srca = sourceBegin + scr_TL; // Translate index from screen to global - int srce = sourceEnd + scr_TL; // Translate index from screen to global - int desta = srca + diff; - int deste = srce + diff; - - if ((selTopLeft >= srca) && (selTopLeft <= srce)) - selTopLeft += diff; - else if ((selTopLeft >= desta) && (selTopLeft <= deste)) - selBottomRight = -1; // Clear selection (see below) - - if ((selBottomRight >= srca) && (selBottomRight <= srce)) - selBottomRight += diff; - else if ((selBottomRight >= desta) && (selBottomRight <= deste)) - selBottomRight = -1; // Clear selection (see below) - - if (selBottomRight < 0) - { - clearSelection (); - } - else - { - if (selTopLeft < 0) - selTopLeft = 0; - } - - if (beginIsTL) - selBegin = selTopLeft; - else - selBegin = selBottomRight; - } -} - -void -Screen::clearToEndOfScreen () -{ - clearImage (loc (cuX, cuY), loc (columns - 1, lines - 1), ' '); -} - -void -Screen::clearToBeginOfScreen () -{ - clearImage (loc (0, 0), loc (cuX, cuY), ' '); -} - -void -Screen::clearEntireScreen () -{ - // Add entire screen to history - for (int i = 0; i < (lines - 1); i++) - { - addHistLine (); - scrollUp (0, 1); - } - - clearImage (loc (0, 0), loc (columns - 1, lines - 1), ' '); -} - -/*! fill screen with 'E' - This is to aid screen alignment - */ - -void -Screen::helpAlign () -{ - clearImage (loc (0, 0), loc (columns - 1, lines - 1), 'E'); -} - -void -Screen::clearToEndOfLine () -{ - clearImage (loc (cuX, cuY), loc (columns - 1, cuY), ' '); -} - -void -Screen::clearToBeginOfLine () -{ - clearImage (loc (0, cuY), loc (cuX, cuY), ' '); -} - -void -Screen::clearEntireLine () -{ - clearImage (loc (0, cuY), loc (columns - 1, cuY), ' '); -} - -void -Screen::setRendition (int re) -{ - currentRendition |= re; - updateEffectiveRendition (); -} - -void -Screen::resetRendition (int re) -{ - currentRendition &= ~re; - updateEffectiveRendition (); -} - -void -Screen::setDefaultRendition () -{ - setForeColor (COLOR_SPACE_DEFAULT, DEFAULT_FORE_COLOR); - setBackColor (COLOR_SPACE_DEFAULT, DEFAULT_BACK_COLOR); - currentRendition = DEFAULT_RENDITION; - updateEffectiveRendition (); -} - -void -Screen::setForeColor (int space, int color) -{ - currentForeground = CharacterColor (space, color); - - if (currentForeground.isValid ()) - updateEffectiveRendition (); - else - setForeColor (COLOR_SPACE_DEFAULT, DEFAULT_FORE_COLOR); -} - -void -Screen::setBackColor (int space, int color) -{ - currentBackground = CharacterColor (space, color); - - if (currentBackground.isValid ()) - updateEffectiveRendition (); - else - setBackColor (COLOR_SPACE_DEFAULT, DEFAULT_BACK_COLOR); -} - -void -Screen::clearSelection () -{ - selBottomRight = -1; - selTopLeft = -1; - selBegin = -1; -} - -void -Screen::getSelectionStart (int &column, int &line) const -{ - if (selTopLeft != -1) - { - column = selTopLeft % columns; - line = selTopLeft / columns; - } - else - { - column = cuX + getHistLines (); - line = cuY + getHistLines (); - } -} - -void -Screen::getSelectionEnd (int &column, int &line) const -{ - if (selBottomRight != -1) - { - column = selBottomRight % columns; - line = selBottomRight / columns; - } - else - { - column = cuX + getHistLines (); - line = cuY + getHistLines (); - } -} - -void -Screen::setSelectionStart (const int x, const int y, const bool mode) -{ - selBegin = loc (x, y); - /* FIXME, HACK to correct for x too far to the right... */ - if (x == columns) - selBegin--; - - selBottomRight = selBegin; - selTopLeft = selBegin; - blockSelectionMode = mode; -} - -void -Screen::setSelectionEnd (const int x, const int y) -{ - if (selBegin == -1) - return; - - int endPos = loc (x, y); - - if (endPos < selBegin) - { - selTopLeft = endPos; - selBottomRight = selBegin; - } - else - { - /* FIXME, HACK to correct for x too far to the right... */ - if (x == columns) - endPos--; - - selTopLeft = selBegin; - selBottomRight = endPos; - } - - // Normalize the selection in column mode - if (blockSelectionMode) - { - int topRow = selTopLeft / columns; - int topColumn = selTopLeft % columns; - int bottomRow = selBottomRight / columns; - int bottomColumn = selBottomRight % columns; - - selTopLeft = loc (qMin (topColumn, bottomColumn), topRow); - selBottomRight = loc (qMax (topColumn, bottomColumn), bottomRow); - } -} - -bool -Screen::isSelected (const int x, const int y) const -{ - bool columnInSelection = true; - if (blockSelectionMode) - { - columnInSelection = x >= (selTopLeft % columns) && - x <= (selBottomRight % columns); - } - - int pos = loc (x, y); - return pos >= selTopLeft && pos <= selBottomRight && columnInSelection; -} - -QString -Screen::selectedText (bool preserveLineBreaks) const -{ - QString result; - QTextStream stream (&result, QIODevice::ReadWrite); - - PlainTextDecoder decoder; - decoder.begin (&stream); - writeSelectionToStream (&decoder, preserveLineBreaks); - decoder.end (); - - return result; -} - -bool -Screen::isSelectionValid () const -{ - return selTopLeft >= 0 && selBottomRight >= 0; -} - -void -Screen::writeSelectionToStream (TerminalCharacterDecoder * decoder, - bool preserveLineBreaks) const -{ - if (!isSelectionValid ()) - return; - writeToStream (decoder, selTopLeft, selBottomRight, preserveLineBreaks); -} - -void -Screen::writeToStream (TerminalCharacterDecoder * decoder, - int startIndex, int endIndex, - bool preserveLineBreaks) const -{ - int top = startIndex / columns; - int left = startIndex % columns; - - int bottom = endIndex / columns; - int right = endIndex % columns; - - Q_ASSERT (top >= 0 && left >= 0 && bottom >= 0 && right >= 0); - - for (int y = top; y <= bottom; y++) - { - int start = 0; - if (y == top || blockSelectionMode) - start = left; - - int count = -1; - if (y == bottom || blockSelectionMode) - count = right - start + 1; - - const bool appendNewLine = (y != bottom); - int copied = copyLineToStream (y, - start, - count, - decoder, - appendNewLine, - preserveLineBreaks); - - // if the selection goes beyond the end of the last line then - // append a new line character. - // - // this makes it possible to 'select' a trailing new line character after - // the text on a line. - if (y == bottom && copied < count) - { - Character newLineChar ('\n'); - decoder->decodeLine (&newLineChar, 1, 0); - } - } -} - -int -Screen::copyLineToStream (int line, - int start, - int count, - TerminalCharacterDecoder * decoder, - bool appendNewLine, - bool preserveLineBreaks) const -{ - //buffer to hold characters for decoding - //the buffer is static to avoid initialising every - //element on each call to copyLineToStream - //(which is unnecessary since all elements will be overwritten anyway) - static const int MAX_CHARS = 1024; - static Character characterBuffer[MAX_CHARS]; - - assert (count < MAX_CHARS); - - LineProperty currentLineProperties = 0; - - //determine if the line is in the history buffer or the screen image - if (line < history->getLines ()) - { - const int lineLength = history->getLineLen (line); - - // ensure that start position is before end of line - start = qMin (start, qMax (0, lineLength - 1)); - - // retrieve line from history buffer. It is assumed - // that the history buffer does not store trailing white space - // at the end of the line, so it does not need to be trimmed here - if (count == -1) - { - count = lineLength - start; - } - else - { - count = qMin (start + count, lineLength) - start; - } - - // safety checks - assert (start >= 0); - assert (count >= 0); - assert ((start + count) <= history->getLineLen (line)); - - history->getCells (line, start, count, characterBuffer); - - if (history->isWrappedLine (line)) - currentLineProperties |= LINE_WRAPPED; - } - else - { - if (count == -1) - count = columns - start; - - assert (count >= 0); - - const int screenLine = line - history->getLines (); - - Character *data = screenLines[screenLine].data (); - int length = screenLines[screenLine].count (); - - //retrieve line from screen image - for (int i = start; i < qMin (start + count, length); i++) - { - characterBuffer[i - start] = data[i]; - } - - // count cannot be any greater than length - count = qBound (0, count, length - start); - - Q_ASSERT (screenLine < lineProperties.count ()); - currentLineProperties |= lineProperties[screenLine]; - } - - // add new line character at end - const bool omitLineBreak = (currentLineProperties & LINE_WRAPPED) || - !preserveLineBreaks; - - if (!omitLineBreak && appendNewLine && (count + 1 < MAX_CHARS)) - { - characterBuffer[count] = '\n'; - count++; - } - - //decode line and write to text stream - decoder->decodeLine ((Character *) characterBuffer, - count, currentLineProperties); - - return count; -} - -void -Screen::writeLinesToStream (TerminalCharacterDecoder * decoder, int fromLine, - int toLine) const -{ - writeToStream (decoder, loc (0, fromLine), loc (columns - 1, toLine)); -} - -void -Screen::addHistLine () -{ - // add line to history buffer - // we have to take care about scrolling, too... - - if (hasScroll ()) - { - int oldHistLines = history->getLines (); - - history->addCellsVector (screenLines[0]); - history->addLine (lineProperties[0] & LINE_WRAPPED); - - int newHistLines = history->getLines (); - - bool beginIsTL = (selBegin == selTopLeft); - - // If the history is full, increment the count - // of dropped lines - if (newHistLines == oldHistLines) - _droppedLines++; - - // Adjust selection for the new point of reference - if (newHistLines > oldHistLines) - { - if (selBegin != -1) - { - selTopLeft += columns; - selBottomRight += columns; - } - } - - if (selBegin != -1) - { - // Scroll selection in history up - int top_BR = loc (0, 1 + newHistLines); - - if (selTopLeft < top_BR) - selTopLeft -= columns; - - if (selBottomRight < top_BR) - selBottomRight -= columns; - - if (selBottomRight < 0) - clearSelection (); - else - { - if (selTopLeft < 0) - selTopLeft = 0; - } - - if (beginIsTL) - selBegin = selTopLeft; - else - selBegin = selBottomRight; - } - } - -} - -int -Screen::getHistLines () const -{ - return history->getLines (); -} - -void -Screen::setScroll (const HistoryType & t, bool copyPreviousScroll) -{ - clearSelection (); - - if (copyPreviousScroll) - history = t.scroll (history); - else - { - HistoryScroll *oldScroll = history; - history = t.scroll (0); - delete oldScroll; - } -} - -bool -Screen::hasScroll () const -{ - return history->hasScroll (); -} - -const HistoryType & -Screen::getScroll () const -{ - return history->getType (); -} - -void -Screen::setLineProperty (LineProperty property, bool enable) -{ - if (enable) - lineProperties[cuY] = (LineProperty) (lineProperties[cuY] | property); - else - lineProperties[cuY] = (LineProperty) (lineProperties[cuY] & ~property); -} - -void -Screen::fillWithDefaultChar (Character * dest, int count) -{ - for (int i = 0; i < count; i++) - dest[i] = defaultChar; -} diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/Screen.h --- a/gui/src/terminal/Screen.h Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,678 +0,0 @@ -/* - This file is part of Konsole, KDE's terminal. - - Copyright 2007-2008 by Robert Knight - Copyright 1997,1998 by Lars Doelle - - 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 SCREEN_H -#define SCREEN_H - -// Qt -#include -#include -#include - -// Konsole -#include "Character.h" -#include "History.h" - -#define MODE_Origin 0 -#define MODE_Wrap 1 -#define MODE_Insert 2 -#define MODE_Screen 3 -#define MODE_Cursor 4 -#define MODE_NewLine 5 -#define MODES_SCREEN 6 - -class TerminalCharacterDecoder; - -/** - \brief An image of characters with associated attributes. - - The terminal emulation ( Emulation ) receives a serial stream of - characters from the program currently running in the terminal. - From this stream it creates an image of characters which is ultimately - rendered by the display widget ( TerminalDisplay ). Some types of emulation - may have more than one screen image. - - getImage() is used to retrieve the currently visible image - which is then used by the display widget to draw the output from the - terminal. - - The number of lines of output history which are kept in addition to the current - screen image depends on the history scroll being used to store the output. - The scroll is specified using setScroll() - The output history can be retrieved using writeToStream() - - The screen image has a selection associated with it, specified using - setSelectionStart() and setSelectionEnd(). The selected text can be retrieved - using selectedText(). When getImage() is used to retrieve the visible image, - characters which are part of the selection have their colours inverted. -*/ -class Screen -{ -public: - /** Construct a new screen image of size @p lines by @p columns. */ - Screen (int lines, int columns); - ~Screen (); - - // VT100/2 Operations - // Cursor Movement - - /** - * Move the cursor up by @p n lines. The cursor will stop at the - * top margin. - */ - void cursorUp (int n); - /** - * Move the cursor down by @p n lines. The cursor will stop at the - * bottom margin. - */ - void cursorDown (int n); - /** - * Move the cursor to the left by @p n columns. - * The cursor will stop at the first column. - */ - void cursorLeft (int n); - /** - * Move the cursor to the right by @p n columns. - * The cursor will stop at the right-most column. - */ - void cursorRight (int n); - /** Position the cursor on line @p y. */ - void setCursorY (int y); - /** Position the cursor at column @p x. */ - void setCursorX (int x); - /** Position the cursor at line @p y, column @p x. */ - void setCursorYX (int y, int x); - /** - * Sets the margins for scrolling the screen. - * - * @param topLine The top line of the new scrolling margin. - * @param bottomLine The bottom line of the new scrolling margin. - */ - void setMargins (int topLine, int bottomLine); - /** Returns the top line of the scrolling region. */ - int topMargin () const; - /** Returns the bottom line of the scrolling region. */ - int bottomMargin () const; - - /** - * Resets the scrolling margins back to the top and bottom lines - * of the screen. - */ - void setDefaultMargins (); - - /** - * Moves the cursor down one line, if the MODE_NewLine mode - * flag is enabled then the cursor is returned to the leftmost - * column first. - * - * Equivalent to NextLine() if the MODE_NewLine flag is set - * or index() otherwise. - */ - void newLine (); - /** - * Moves the cursor down one line and positions it at the beginning - * of the line. Equivalent to calling Return() followed by index() - */ - void nextLine (); - - /** - * Move the cursor down one line. If the cursor is on the bottom - * line of the scrolling region (as returned by bottomMargin()) the - * scrolling region is scrolled up by one line instead. - */ - void index (); - /** - * Move the cursor up one line. If the cursor is on the top line - * of the scrolling region (as returned by topMargin()) the scrolling - * region is scrolled down by one line instead. - */ - void reverseIndex (); - - /** - * Scroll the scrolling region of the screen up by @p n lines. - * The scrolling region is initially the whole screen, but can be changed - * using setMargins() - */ - void scrollUp (int n); - /** - * Scroll the scrolling region of the screen down by @p n lines. - * The scrolling region is initially the whole screen, but can be changed - * using setMargins() - */ - void scrollDown (int n); - /** - * Moves the cursor to the beginning of the current line. - * Equivalent to setCursorX(0) - */ - void toStartOfLine (); - /** - * Moves the cursor one column to the left and erases the character - * at the new cursor position. - */ - void backspace (); - /** Moves the cursor @p n tab-stops to the right. */ - void tab (int n = 1); - /** Moves the cursor @p n tab-stops to the left. */ - void backtab (int n); - - // Editing - - /** - * Erase @p n characters beginning from the current cursor position. - * This is equivalent to over-writing @p n characters starting with the current - * cursor position with spaces. - * If @p n is 0 then one character is erased. - */ - void eraseChars (int n); - /** - * Delete @p n characters beginning from the current cursor position. - * If @p n is 0 then one character is deleted. - */ - void deleteChars (int n); - /** - * Insert @p n blank characters beginning from the current cursor position. - * The position of the cursor is not altered. - * If @p n is 0 then one character is inserted. - */ - void insertChars (int n); - /** - * Removes @p n lines beginning from the current cursor position. - * The position of the cursor is not altered. - * If @p n is 0 then one line is removed. - */ - void deleteLines (int n); - /** - * Inserts @p lines beginning from the current cursor position. - * The position of the cursor is not altered. - * If @p n is 0 then one line is inserted. - */ - void insertLines (int n); - /** Clears all the tab stops. */ - void clearTabStops (); - /** Sets or removes a tab stop at the cursor's current column. */ - void changeTabStop (bool set); - - /** Resets (clears) the specified screen @p mode. */ - void resetMode (int mode); - /** Sets (enables) the specified screen @p mode. */ - void setMode (int mode); - /** - * Saves the state of the specified screen @p mode. It can be restored - * using restoreMode() - */ - void saveMode (int mode); - /** Restores the state of a screen @p mode saved by calling saveMode() */ - void restoreMode (int mode); - /** Returns whether the specified screen @p mode is enabled or not .*/ - bool getMode (int mode) const; - - /** - * Saves the current position and appearance (text color and style) of the cursor. - * It can be restored by calling restoreCursor() - */ - void saveCursor (); - /** Restores the position and appearance of the cursor. See saveCursor() */ - void restoreCursor (); - - /** Clear the whole screen, moving the current screen contents into the history first. */ - void clearEntireScreen (); - /** - * Clear the area of the screen from the current cursor position to the end of - * the screen. - */ - void clearToEndOfScreen (); - /** - * Clear the area of the screen from the current cursor position to the start - * of the screen. - */ - void clearToBeginOfScreen (); - /** Clears the whole of the line on which the cursor is currently positioned. */ - void clearEntireLine (); - /** Clears from the current cursor position to the end of the line. */ - void clearToEndOfLine (); - /** Clears from the current cursor position to the beginning of the line. */ - void clearToBeginOfLine (); - - /** Fills the entire screen with the letter 'E' */ - void helpAlign (); - - /** - * Enables the given @p rendition flag. Rendition flags control the appearance - * of characters on the screen. - * - * @see Character::rendition - */ - void setRendition (int rendition); - /** - * Disables the given @p rendition flag. Rendition flags control the appearance - * of characters on the screen. - * - * @see Character::rendition - */ - void resetRendition (int rendition); - - /** - * Sets the cursor's foreground color. - * @param space The color space used by the @p color argument - * @param color The new foreground color. The meaning of this depends on - * the color @p space used. - * - * @see CharacterColor - */ - void setForeColor (int space, int color); - /** - * Sets the cursor's background color. - * @param space The color space used by the @p color argumnet. - * @param color The new background color. The meaning of this depends on - * the color @p space used. - * - * @see CharacterColor - */ - void setBackColor (int space, int color); - /** - * Resets the cursor's color back to the default and sets the - * character's rendition flags back to the default settings. - */ - void setDefaultRendition (); - - /** Returns the column which the cursor is positioned at. */ - int getCursorX () const; - /** Returns the line which the cursor is positioned on. */ - int getCursorY () const; - - /** Clear the entire screen and move the cursor to the home position. - * Equivalent to calling clearEntireScreen() followed by home(). - */ - void clear (); - /** - * Sets the position of the cursor to the 'home' position at the top-left - * corner of the screen (0,0) - */ - void home (); - /** - * Resets the state of the screen. This resets the various screen modes - * back to their default states. The cursor style and colors are reset - * (as if setDefaultRendition() had been called) - *setDefaultRendition - *
    - *
  • Line wrapping is enabled.
  • - *
  • Origin mode is disabled.
  • - *
  • Insert mode is disabled.
  • - *
  • Cursor mode is enabled. TODO Document me
  • - *
  • Screen mode is disabled. TODO Document me
  • - *
  • New line mode is disabled. TODO Document me
  • - *
- * - * If @p clearScreen is true then the screen contents are erased entirely, - * otherwise they are unaltered. - */ - void reset (bool clearScreen = true); - - /** - * Displays a new character at the current cursor position. - * - * If the cursor is currently positioned at the right-edge of the screen and - * line wrapping is enabled then the character is added at the start of a new - * line below the current one. - * - * If the MODE_Insert screen mode is currently enabled then the character - * is inserted at the current cursor position, otherwise it will replace the - * character already at the current cursor position. - */ - void displayCharacter (unsigned short c); - - // Do composition with last shown character FIXME: Not implemented yet for KDE 4 - void compose (const QString & compose); - - /** - * Resizes the image to a new fixed size of @p new_lines by @p new_columns. - * In the case that @p new_columns is smaller than the current number of columns, - * existing lines are not truncated. This prevents characters from being lost - * if the terminal display is resized smaller and then larger again. - * - * The top and bottom margins are reset to the top and bottom of the new - * screen size. Tab stops are also reset and the current selection is - * cleared. - */ - void resizeImage (int new_lines, int new_columns); - - /** - * Returns the current screen image. - * The result is an array of Characters of size [getLines()][getColumns()] which - * must be freed by the caller after use. - * - * @param dest Buffer to copy the characters into - * @param size Size of @p dest in Characters - * @param startLine Index of first line to copy - * @param endLine Index of last line to copy - */ - void getImage (Character * dest, int size, int startLine, - int endLine) const; - - /** - * Returns the additional attributes associated with lines in the image. - * The most important attribute is LINE_WRAPPED which specifies that the - * line is wrapped, - * other attributes control the size of characters in the line. - */ - QVector < LineProperty > getLineProperties (int startLine, - int endLine) const; - - - /** Return the number of lines. */ - int getLines () const - { - return lines; - } - /** Return the number of columns. */ - int getColumns () const - { - return columns; - } - /** Return the number of lines in the history buffer. */ - int getHistLines () const; - /** - * Sets the type of storage used to keep lines in the history. - * If @p copyPreviousScroll is true then the contents of the previous - * history buffer are copied into the new scroll. - */ - void setScroll (const HistoryType &, bool copyPreviousScroll = true); - /** Returns the type of storage used to keep lines in the history. */ - const HistoryType & getScroll () const; - /** - * Returns true if this screen keeps lines that are scrolled off the screen - * in a history buffer. - */ - bool hasScroll () const; - - /** - * Sets the start of the selection. - * - * @param column The column index of the first character in the selection. - * @param line The line index of the first character in the selection. - * @param blockSelectionMode True if the selection is in column mode. - */ - void setSelectionStart (const int column, const int line, - const bool blockSelectionMode); - - /** - * Sets the end of the current selection. - * - * @param column The column index of the last character in the selection. - * @param line The line index of the last character in the selection. - */ - void setSelectionEnd (const int column, const int line); - - /** - * Retrieves the start of the selection or the cursor position if there - * is no selection. - */ - void getSelectionStart (int &column, int &line) const; - - /** - * Retrieves the end of the selection or the cursor position if there - * is no selection. - */ - void getSelectionEnd (int &column, int &line) const; - - /** Clears the current selection */ - void clearSelection (); - - /** - * Returns true if the character at (@p column, @p line) is part of the - * current selection. - */ - bool isSelected (const int column, const int line) const; - - /** - * Convenience method. Returns the currently selected text. - * @param preserveLineBreaks Specifies whether new line characters should - * be inserted into the returned text at the end of each terminal line. - */ - QString selectedText (bool preserveLineBreaks) const; - - /** - * Copies part of the output to a stream. - * - * @param decoder A decoder which converts terminal characters into text - * @param fromLine The first line in the history to retrieve - * @param toLine The last line in the history to retrieve - */ - void writeLinesToStream (TerminalCharacterDecoder * decoder, int fromLine, - int toLine) const; - - /** - * Copies the selected characters, set using @see setSelBeginXY and @see setSelExtentXY - * into a stream. - * - * @param decoder A decoder which converts terminal characters into text. - * PlainTextDecoder is the most commonly used decoder which converts characters - * into plain text with no formatting. - * @param preserveLineBreaks Specifies whether new line characters should - * be inserted into the returned text at the end of each terminal line. - */ - void writeSelectionToStream (TerminalCharacterDecoder * decoder, bool - preserveLineBreaks = true) const; - - /** - * Checks if the text between from and to is inside the current - * selection. If this is the case, the selection is cleared. The - * from and to are coordinates in the current viewable window. - * The loc(x,y) macro can be used to generate these values from a - * column,line pair. - * - * @param from The start of the area to check. - * @param to The end of the area to check - */ - void checkSelection (int from, int to); - - /** - * Sets or clears an attribute of the current line. - * - * @param property The attribute to set or clear - * Possible properties are: - * LINE_WRAPPED: Specifies that the line is wrapped. - * LINE_DOUBLEWIDTH: Specifies that the characters in the current line - * should be double the normal width. - * LINE_DOUBLEHEIGHT:Specifies that the characters in the current line - * should be double the normal height. - * Double-height lines are formed of two lines containing the same characters, - * with both having the LINE_DOUBLEHEIGHT attribute. - * This allows other parts of the code to work on the - * assumption that all lines are the same height. - * - * @param enable true to apply the attribute to the current line or false to remove it - */ - void setLineProperty (LineProperty property, bool enable); - - /** - * Returns the number of lines that the image has been scrolled up or down by, - * since the last call to resetScrolledLines(). - * - * a positive return value indicates that the image has been scrolled up, - * a negative return value indicates that the image has been scrolled down. - */ - int scrolledLines () const; - - /** - * Returns the region of the image which was last scrolled. - * - * This is the area of the image from the top margin to the - * bottom margin when the last scroll occurred. - */ - QRect lastScrolledRegion () const; - - /** - * Resets the count of the number of lines that the image has been scrolled up or down by, - * see scrolledLines() - */ - void resetScrolledLines (); - - /** - * Returns the number of lines of output which have been - * dropped from the history since the last call - * to resetDroppedLines() - * - * If the history is not unlimited then it will drop - * the oldest lines of output if new lines are added when - * it is full. - */ - int droppedLines () const; - - /** - * Resets the count of the number of lines dropped from - * the history. - */ - void resetDroppedLines (); - - /** - * Fills the buffer @p dest with @p count instances of the default (ie. blank) - * Character style. - */ - static void fillWithDefaultChar (Character * dest, int count); - -private: - - //copies a line of text from the screen or history into a stream using a - //specified character decoder. Returns the number of lines actually copied, - //which may be less than 'count' if (start+count) is more than the number of characters on - //the line - // - //line - the line number to copy, from 0 (the earliest line in the history) up to - // history->getLines() + lines - 1 - //start - the first column on the line to copy - //count - the number of characters on the line to copy - //decoder - a decoder which converts terminal characters (an Character array) into text - //appendNewLine - if true a new line character (\n) is appended to the end of the line - int copyLineToStream (int line, - int start, - int count, - TerminalCharacterDecoder * decoder, - bool appendNewLine, bool preserveLineBreaks) const; - - //fills a section of the screen image with the character 'c' - //the parameters are specified as offsets from the start of the screen image. - //the loc(x,y) macro can be used to generate these values from a column,line pair. - void clearImage (int loca, int loce, char c); - - //move screen image between 'sourceBegin' and 'sourceEnd' to 'dest'. - //the parameters are specified as offsets from the start of the screen image. - //the loc(x,y) macro can be used to generate these values from a column,line pair. - // - //NOTE: moveImage() can only move whole lines - void moveImage (int dest, int sourceBegin, int sourceEnd); - // scroll up 'i' lines in current region, clearing the bottom 'i' lines - void scrollUp (int from, int i); - // scroll down 'i' lines in current region, clearing the top 'i' lines - void scrollDown (int from, int i); - - void addHistLine (); - - void initTabStops (); - - void updateEffectiveRendition (); - void reverseRendition (Character & p) const; - - bool isSelectionValid () const; - // copies text from 'startIndex' to 'endIndex' to a stream - // startIndex and endIndex are positions generated using the loc(x,y) macro - void writeToStream (TerminalCharacterDecoder * decoder, int startIndex, - int endIndex, bool preserveLineBreaks = true) const; - // copies 'count' lines from the screen buffer into 'dest', - // starting from 'startLine', where 0 is the first line in the screen buffer - void copyFromScreen (Character * dest, int startLine, int count) const; - // copies 'count' lines from the history buffer into 'dest', - // starting from 'startLine', where 0 is the first line in the history - void copyFromHistory (Character * dest, int startLine, int count) const; - - - // screen image ---------------- - int lines; - int columns; - - typedef QVector < Character > ImageLine; // [0..columns] - ImageLine *screenLines; // [lines] - - int _scrolledLines; - QRect _lastScrolledRegion; - - int _droppedLines; - - QVarLengthArray < LineProperty, 64 > lineProperties; - - // history buffer --------------- - HistoryScroll *history; - - // cursor location - int cuX; - int cuY; - - // cursor color and rendition info - CharacterColor currentForeground; - CharacterColor currentBackground; - quint8 currentRendition; - - // margins ---------------- - int _topMargin; - int _bottomMargin; - - // states ---------------- - int currentModes[MODES_SCREEN]; - int savedModes[MODES_SCREEN]; - - // ---------------------------- - - QBitArray tabStops; - - // selection ------------------- - int selBegin; // The first location selected. - int selTopLeft; // TopLeft Location. - int selBottomRight; // Bottom Right Location. - bool blockSelectionMode; // Column selection mode - - // effective colors and rendition ------------ - CharacterColor effectiveForeground; // These are derived from - CharacterColor effectiveBackground; // the cu_* variables above - quint8 effectiveRendition; // to speed up operation - - class SavedState - { - public: - SavedState ():cursorColumn (0), cursorLine (0), rendition (0) - { - } - - int cursorColumn; - int cursorLine; - quint8 rendition; - CharacterColor foreground; - CharacterColor background; - }; - SavedState savedState; - - // last position where we added a character - int lastPos; - - static Character defaultChar; -}; - -#endif // SCREEN_H diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/ScreenWindow.cpp --- a/gui/src/terminal/ScreenWindow.cpp Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,326 +0,0 @@ -/* - Copyright (C) 2007 by Robert Knight - - Rewritten for QT4 by e_k , 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 "ScreenWindow.h" - -// Qt -#include - -// Konsole -#include "Screen.h" - -ScreenWindow::ScreenWindow (QObject * parent):QObject (parent), _windowBuffer (0), _windowBufferSize (0), -_bufferNeedsUpdate (true), _windowLines (1), _currentLine (0), -_trackOutput (true), _scrollCount (0) -{ -} - -ScreenWindow::~ScreenWindow () -{ - delete[]_windowBuffer; -} - -void -ScreenWindow::setScreen (Screen * screen) -{ - Q_ASSERT (screen); - - _screen = screen; -} - -Screen * -ScreenWindow::screen () const -{ - return _screen; -} - -Character * -ScreenWindow::getImage () -{ - // reallocate internal buffer if the window size has changed - int size = windowLines () * windowColumns (); - if (_windowBuffer == 0 || _windowBufferSize != size) - { - delete[]_windowBuffer; - _windowBufferSize = size; - _windowBuffer = new Character[size]; - _bufferNeedsUpdate = true; - } - - if (!_bufferNeedsUpdate) - return _windowBuffer; - - _screen->getImage (_windowBuffer, size, currentLine (), endWindowLine ()); - - // this window may look beyond the end of the screen, in which - // case there will be an unused area which needs to be filled - // with blank characters - fillUnusedArea (); - - _bufferNeedsUpdate = false; - return _windowBuffer; -} - -void -ScreenWindow::fillUnusedArea () -{ - int screenEndLine = _screen->getHistLines () + _screen->getLines () - 1; - int windowEndLine = currentLine () + windowLines () - 1; - - int unusedLines = windowEndLine - screenEndLine; - int charsToFill = unusedLines * windowColumns (); - - Screen::fillWithDefaultChar (_windowBuffer + _windowBufferSize - - charsToFill, charsToFill); -} - -// return the index of the line at the end of this window, or if this window -// goes beyond the end of the screen, the index of the line at the end -// of the screen. -// -// when passing a line number to a Screen method, the line number should -// never be more than endWindowLine() -// -int -ScreenWindow::endWindowLine () const -{ - return qMin (currentLine () + windowLines () - 1, lineCount () - 1); -} - -QVector < LineProperty > ScreenWindow::getLineProperties () -{ - QVector < LineProperty > result = - _screen->getLineProperties (currentLine (), endWindowLine ()); - - if (result.count () != windowLines ()) - result.resize (windowLines ()); - - return result; -} - -QString -ScreenWindow::selectedText (bool preserveLineBreaks) const -{ - return _screen->selectedText (preserveLineBreaks); -} - -void -ScreenWindow::getSelectionStart (int &column, int &line) -{ - _screen->getSelectionStart (column, line); - line -= currentLine (); -} - -void -ScreenWindow::getSelectionEnd (int &column, int &line) -{ - _screen->getSelectionEnd (column, line); - line -= currentLine (); -} - -void -ScreenWindow::setSelectionStart (int column, int line, bool columnMode) -{ - _screen->setSelectionStart (column, - qMin (line + currentLine (), endWindowLine ()), - columnMode); - - _bufferNeedsUpdate = true; - emit selectionChanged (); -} - -void -ScreenWindow::setSelectionEnd (int column, int line) -{ - _screen->setSelectionEnd (column, - qMin (line + currentLine (), endWindowLine ())); - - _bufferNeedsUpdate = true; - emit selectionChanged (); -} - -bool -ScreenWindow::isSelected (int column, int line) -{ - return _screen->isSelected (column, - qMin (line + currentLine (), endWindowLine ())); -} - -void -ScreenWindow::clearSelection () -{ - _screen->clearSelection (); - - emit selectionChanged (); -} - -void -ScreenWindow::setWindowLines (int lines) -{ - Q_ASSERT (lines > 0); - _windowLines = lines; -} - -int -ScreenWindow::windowLines () const -{ - return _windowLines; -} - -int -ScreenWindow::windowColumns () const -{ - return _screen->getColumns (); -} - -int -ScreenWindow::lineCount () const -{ - return _screen->getHistLines () + _screen->getLines (); -} - -int -ScreenWindow::columnCount () const -{ - return _screen->getColumns (); -} - -QPoint -ScreenWindow::cursorPosition () const -{ - QPoint position; - - position.setX (_screen->getCursorX ()); - position.setY (_screen->getCursorY ()); - - return position; -} - -int -ScreenWindow::currentLine () const -{ - return qBound (0, _currentLine, lineCount () - windowLines ()); -} - -void -ScreenWindow::scrollBy (RelativeScrollMode mode, int amount) -{ - if (mode == ScrollLines) - { - scrollTo (currentLine () + amount); - } - else if (mode == ScrollPages) - { - scrollTo (currentLine () + amount * (windowLines () / 2)); - } -} - -bool -ScreenWindow::atEndOfOutput () const -{ - return currentLine () == (lineCount () - windowLines ()); -} - -void -ScreenWindow::scrollTo (int line) -{ - int maxCurrentLineNumber = lineCount () - windowLines (); - line = qBound (0, line, maxCurrentLineNumber); - - const int delta = line - _currentLine; - _currentLine = line; - - // keep track of number of lines scrolled by, - // this can be reset by calling resetScrollCount() - _scrollCount += delta; - - _bufferNeedsUpdate = true; - - emit scrolled (_currentLine); -} - -void -ScreenWindow::setTrackOutput (bool trackOutput) -{ - _trackOutput = trackOutput; -} - -bool -ScreenWindow::trackOutput () const -{ - return _trackOutput; -} - -int -ScreenWindow::scrollCount () const -{ - return _scrollCount; -} - -void -ScreenWindow::resetScrollCount () -{ - _scrollCount = 0; -} - -QRect -ScreenWindow::scrollRegion () const -{ - bool equalToScreenSize = windowLines () == _screen->getLines (); - - if (atEndOfOutput () && equalToScreenSize) - return _screen->lastScrolledRegion (); - else - return QRect (0, 0, windowColumns (), windowLines ()); -} - -void -ScreenWindow::notifyOutputChanged () -{ - // move window to the bottom of the screen and update scroll count - // if this window is currently tracking the bottom of the screen - if (_trackOutput) - { - _scrollCount -= _screen->scrolledLines (); - _currentLine = - qMax (0, - _screen->getHistLines () - (windowLines () - - _screen->getLines ())); - } - else - { - // if the history is not unlimited then it may - // have run out of space and dropped the oldest - // lines of output - in this case the screen - // window's current line number will need to - // be adjusted - otherwise the output will scroll - _currentLine = qMax (0, _currentLine - _screen->droppedLines ()); - - // ensure that the screen window's current position does - // not go beyond the bottom of the screen - _currentLine = qMin (_currentLine, _screen->getHistLines ()); - } - - _bufferNeedsUpdate = true; - - emit outputChanged (); -} diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/ScreenWindow.h --- a/gui/src/terminal/ScreenWindow.h Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,249 +0,0 @@ -/* - Copyright (C) 2007 by Robert Knight - - Rewritten for QT4 by e_k , 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 SCREENWINDOW_H -#define SCREENWINDOW_H - -// Qt -#include -#include -#include - -// Konsole -#include "Character.h" - -class Screen; - -/** - * Provides a window onto a section of a terminal screen. - * This window can then be rendered by a terminal display widget ( TerminalDisplay ). - * - * To use the screen window, create a new ScreenWindow() instance and associated it with - * a terminal screen using setScreen(). - * Use the scrollTo() method to scroll the window up and down on the screen. - * Call the getImage() method to retrieve the character image which is currently visible in the window. - * - * setTrackOutput() controls whether the window moves to the bottom of the associated screen when new - * lines are added to it. - * - * Whenever the output from the underlying screen is changed, the notifyOutputChanged() slot should - * be called. This in turn will update the window's position and emit the outputChanged() signal - * if necessary. - */ -class ScreenWindow:public QObject -{ -Q_OBJECT public: - /** - * Constructs a new screen window with the given parent. - * A screen must be specified by calling setScreen() before calling getImage() or getLineProperties(). - * - * You should not call this constructor directly, instead use the Emulation::createWindow() method - * to create a window on the emulation which you wish to view. This allows the emulation - * to notify the window when the associated screen has changed and synchronize selection updates - * between all views on a session. - */ - ScreenWindow (QObject * parent = 0); - virtual ~ ScreenWindow (); - - /** Sets the screen which this window looks onto */ - void setScreen (Screen * screen); - /** Returns the screen which this window looks onto */ - Screen *screen () const; - - /** - * Returns the image of characters which are currently visible through this window - * onto the screen. - * - * The buffer is managed by the ScreenWindow instance and does not need to be - * deleted by the caller. - */ - Character *getImage (); - - /** - * Returns the line attributes associated with the lines of characters which - * are currently visible through this window - */ - QVector < LineProperty > getLineProperties (); - - /** - * Returns the number of lines which the region of the window - * specified by scrollRegion() has been scrolled by since the last call - * to resetScrollCount(). scrollRegion() is in most cases the - * whole window, but will be a smaller area in, for example, applications - * which provide split-screen facilities. - * - * This is not guaranteed to be accurate, but allows views to optimise - * rendering by reducing the amount of costly text rendering that - * needs to be done when the output is scrolled. - */ - int scrollCount () const; - - /** - * Resets the count of scrolled lines returned by scrollCount() - */ - void resetScrollCount (); - - /** - * Returns the area of the window which was last scrolled, this is - * usually the whole window area. - * - * Like scrollCount(), this is not guaranteed to be accurate, - * but allows views to optimise rendering. - */ - QRect scrollRegion () const; - - /** - * Sets the start of the selection to the given @p line and @p column within - * the window. - */ - void setSelectionStart (int column, int line, bool columnMode); - /** - * Sets the end of the selection to the given @p line and @p column within - * the window. - */ - void setSelectionEnd (int column, int line); - /** - * Retrieves the start of the selection within the window. - */ - void getSelectionStart (int &column, int &line); - /** - * Retrieves the end of the selection within the window. - */ - void getSelectionEnd (int &column, int &line); - /** - * Returns true if the character at @p line , @p column is part of the selection. - */ - bool isSelected (int column, int line); - /** - * Clears the current selection - */ - void clearSelection (); - - /** Sets the number of lines in the window */ - void setWindowLines (int lines); - /** Returns the number of lines in the window */ - int windowLines () const; - /** Returns the number of columns in the window */ - int windowColumns () const; - - /** Returns the total number of lines in the screen */ - int lineCount () const; - /** Returns the total number of columns in the screen */ - int columnCount () const; - - /** Returns the index of the line which is currently at the top of this window */ - int currentLine () const; - - /** - * Returns the position of the cursor - * within the window. - */ - QPoint cursorPosition () const; - - /** - * Convenience method. Returns true if the window is currently at the bottom - * of the screen. - */ - bool atEndOfOutput () const; - - /** Scrolls the window so that @p line is at the top of the window */ - void scrollTo (int line); - - enum RelativeScrollMode - { - ScrollLines, - ScrollPages - }; - - /** - * Scrolls the window relative to its current position on the screen. - * - * @param mode Specifies whether @p amount refers to the number of lines or the number - * of pages to scroll. - * @param amount The number of lines or pages ( depending on @p mode ) to scroll by. If - * this number is positive, the view is scrolled down. If this number is negative, the view - * is scrolled up. - */ - void scrollBy (RelativeScrollMode mode, int amount); - - /** - * Specifies whether the window should automatically move to the bottom - * of the screen when new output is added. - * - * If this is set to true, the window will be moved to the bottom of the associated screen ( see - * screen() ) when the notifyOutputChanged() method is called. - */ - void setTrackOutput (bool trackOutput); - /** - * Returns whether the window automatically moves to the bottom of the screen as - * new output is added. See setTrackOutput() - */ - bool trackOutput () const; - - /** - * Returns the text which is currently selected. - * - * @param preserveLineBreaks See Screen::selectedText() - */ - QString selectedText (bool preserveLineBreaks) const; - - public slots: - /** - * Notifies the window that the contents of the associated terminal screen have changed. - * This moves the window to the bottom of the screen if trackOutput() is true and causes - * the outputChanged() signal to be emitted. - */ - void notifyOutputChanged (); - - signals: - /** - * Emitted when the contents of the associated terminal screen ( see screen() ) changes. - */ - void outputChanged (); - - /** - * Emitted when the screen window is scrolled to a different position. - * - * @param line The line which is now at the top of the window. - */ - void scrolled (int line); - - /** - * Emitted when the selection is changed. - */ - void selectionChanged (); - -private: - int endWindowLine () const; - void fillUnusedArea (); - - Screen *_screen; // see setScreen() , screen() - Character *_windowBuffer; - int _windowBufferSize; - bool _bufferNeedsUpdate; - - int _windowLines; - int _currentLine; // see scrollTo() , currentLine() - bool _trackOutput; // see setTrackOutput() , trackOutput() - int _scrollCount; // count of lines which the window has been scrolled by since - // the last call to resetScrollCount() -}; -#endif // SCREENWINDOW_H diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/Session.cpp --- a/gui/src/terminal/Session.cpp Thu Aug 18 15:07:43 2011 +0200 +++ b/gui/src/terminal/Session.cpp Thu Aug 18 19:20:10 2011 +0200 @@ -42,9 +42,7 @@ #include "kptydevice.h" #include "Pty.h" -#include "TerminalDisplay.h" #include "ShellCommand.h" -#include "Vt102Emulation.h" int Session::lastSessionId = 0; @@ -95,7 +93,7 @@ } Session::Session (QObject * parent): -QObject (parent), _shellProcess (0), _emulation (0), _monitorActivity (false), +QObject (parent), _shellProcess (0),/* _emulation (0),*/ _monitorActivity (false), _monitorSilence (false), _notifiedActivity (false), _autoClose (true), _wantedClose (false), _silenceSeconds (10), _flowControl (true), _fullScripting (false), _sessionId (0), @@ -111,8 +109,8 @@ //QDBusConnection::sessionBus().registerObject(QLatin1String("/Sessions/")+QString::number(_sessionId), this); //create emulation backend - _emulation = new Vt102Emulation (); - + //_emulation = new Vt102Emulation (); + /* connect (_emulation, SIGNAL (titleChanged (int, const QString &)), this, SLOT (setUserTitle (int, const QString &))); connect (_emulation, SIGNAL (stateSet (int)), @@ -124,7 +122,7 @@ SIGNAL (profileChangeCommandReceived (const QString &))); connect (_emulation, SIGNAL (flowControlKeyPressed (bool)), this, SLOT (updateFlowControlState (bool))); - +*/ //create new teletype for I/O with shell process openTeletype (-1); @@ -151,19 +149,19 @@ else _shellProcess = new Pty (fd); - _shellProcess->setUtf8Mode (_emulation->utf8 ()); + //_shellProcess->setUtf8Mode (_emulation->utf8 ()); //connect teletype to emulation backend 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 (useUtf8Request (bool)), _shellProcess, - SLOT (setUtf8Mode (bool))); + //connect (_emulation, SIGNAL (sendData (const char *, int)), _shellProcess, +// SLOT (sendData (const char *, int))); + //connect (_emulation, SIGNAL (useUtf8Request (bool)), _shellProcess, + // SLOT (setUtf8Mode (bool))); connect (_shellProcess, SIGNAL (finished (int, QProcess::ExitStatus)), this, SLOT (done (int))); - connect (_emulation, SIGNAL (imageSizeChanged (int, int)), this, - SLOT (updateWindowSize (int, int))); + //connect (_emulation, SIGNAL (imageSizeChanged (int, int)), this, + // SLOT (updateWindowSize (int, int))); } void @@ -187,7 +185,7 @@ void Session::setCodec (QTextCodec * codec) { - emulation ()->setCodec (codec); + //emulation ()->setCodec (codec); } bool @@ -205,7 +203,7 @@ QByteArray Session::codec () { - return _emulation->codec ()->name (); + return QByteArray(); //_emulation->codec ()->name (); } void @@ -227,11 +225,13 @@ _arguments = ShellCommand::expand (arguments); } +/* QList < TerminalDisplay * >Session::views () const { return _views; -} +}*/ +/* void Session::addView (TerminalDisplay * widget) { @@ -265,8 +265,9 @@ QObject::connect (widget, SIGNAL (destroyed (QObject *)), this, SLOT (viewDestroyed (QObject *))); -} +}*/ +/* void Session::viewDestroyed (QObject * view) { @@ -275,8 +276,9 @@ Q_ASSERT (_views.contains (display)); removeView (display); -} +}*/ +/* void Session::removeView (TerminalDisplay * widget) { @@ -304,7 +306,7 @@ close (); } } - +*/ QString Session::checkProgram (const QString & program) const { @@ -327,6 +329,7 @@ void Session::terminalWarning (const QString & message) { + /* static const QByteArray warningText = QByteArray ("@info:shell Alert the user with red color text"); QByteArray messageText = message.toLocal8Bit (); @@ -334,6 +337,7 @@ static const char redPenOn[] = "\033[1m\033[31m"; static const char redPenOff[] = "\033[0m"; + _emulation->receiveData (redPenOn, strlen (redPenOn)); _emulation->receiveData ("\n\r\n\r", 4); _emulation->receiveData (warningText.constData (), @@ -342,6 +346,7 @@ strlen (messageText.constData ())); _emulation->receiveData ("\n\r\n\r", 4); _emulation->receiveData (redPenOff, strlen (redPenOff)); +*/ } void @@ -402,7 +407,7 @@ _shellProcess->setWorkingDirectory (QDir::homePath ()); _shellProcess->setFlowControlEnabled (_flowControl); - _shellProcess->setErase (_emulation->eraseChar ()); + //_shellProcess->setErase (_emulation->eraseChar ()); // 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 @@ -528,11 +533,11 @@ //KNotification::event("Silence", i18n("Silence in session '%1'", _nameTitle)propagateSize, QPixmap(), // QApplication::activeWindow(), // KNotification::CloseWhenWidgetActivated); - emit stateChanged (NOTIFYSILENCE); + //emit stateChanged (NOTIFYSILENCE); } else { - emit stateChanged (NOTIFYNORMAL); + //emit stateChanged (NOTIFYNORMAL); } _notifiedActivity = false; @@ -541,6 +546,7 @@ void Session::updateFlowControlState (bool suspended) { + /* if (suspended) { if (flowControlEnabled ()) @@ -556,12 +562,12 @@ { foreach (TerminalDisplay * display, _views) display->outputSuspended (false); - } + }*/ } void Session::activityStateSet (int state) -{ +{/* if (state == NOTIFYBELL) { // empty @@ -592,6 +598,7 @@ state = NOTIFYNORMAL; emit stateChanged (state); + */ } void @@ -602,7 +609,7 @@ void Session::updateTerminalSize () -{ +{/* QListIterator < TerminalDisplay * >viewIter (_views); int minLines = -1; @@ -615,6 +622,7 @@ 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 (); @@ -636,7 +644,7 @@ if (minLines > 0 && minColumns > 0) { _emulation->setImageSize (minLines, minColumns); - } + }*/ } void @@ -714,13 +722,14 @@ void Session::sendText (const QString & text) const { - _emulation->sendText (text); + _shellProcess->sendData (text.toStdString().c_str(), text.length ()); + //_emulation->sendText (text); } void Session::sendMouseEvent (int buttons, int column, int line, int eventType) { - _emulation->sendMouseEvent (buttons, column, line, eventType); + //_emulation->sendMouseEvent (buttons, column, line, eventType); } Session::~Session () @@ -729,7 +738,7 @@ // delete _foregroundProcessInfo; //if (_sessionProcessInfo) // delete _sessionProcessInfo; - delete _emulation; + //delete _emulation; delete _shellProcess; //delete _zmodemProc; } @@ -774,18 +783,6 @@ emit finished (); } -Emulation * -Session::emulation () const -{ - return _emulation; -} - -QString -Session::keyBindings () const -{ - return _emulation->keyBindings (); -} - QStringList Session::environment () const { @@ -799,12 +796,6 @@ } void -Session::setKeyBindings (const QString & id) -{ - _emulation->setKeyBindings (id); -} - -void Session::setTitle (TitleRole role, const QString & newTitle) { if (title (role) != newTitle) @@ -857,24 +848,6 @@ 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 { @@ -909,16 +882,10 @@ void Session::onReceiveBlock (const char *buf, int len) { - _emulation->receiveData (buf, len); + //_emulation->receiveData (buf, len); emit receivedData (QString::fromLatin1 (buf, len)); } -QSize -Session::size () -{ - return _emulation->imageSize (); -} - void Session::setSize (const QSize & size) { @@ -1029,14 +996,14 @@ if (master) { - connect (session->emulation (), SIGNAL (sendData (const char *, int)), - this, SLOT (forwardData (const char *, int))); + //connect (session->emulation (), SIGNAL (sendData (const char *, int)), + // this, SLOT (forwardData (const char *, int))); } else { - disconnect (session->emulation (), - SIGNAL (sendData (const char *, int)), this, - SLOT (forwardData (const char *, int))); + //disconnect (session->emulation (), + // SIGNAL (sendData (const char *, int)), this, + // SLOT (forwardData (const char *, int))); } } @@ -1060,7 +1027,7 @@ Session *other = iter.next (); if (!_sessions[other]) { - other->emulation ()->sendString (data, size); + //other->emulation ()->sendString (data, size); } } _inForwardData = false; diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/Session.h --- a/gui/src/terminal/Session.h Thu Aug 18 15:07:43 2011 +0200 +++ b/gui/src/terminal/Session.h Thu Aug 18 19:20:10 2011 +0200 @@ -35,9 +35,8 @@ #include "History.h" class KProcess; -class Emulation; class Pty; -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. @@ -95,7 +94,7 @@ * Views can be removed using removeView(). The session is automatically * closed when the last view is removed. */ - void addView (TerminalDisplay * widget); + //void addView (TerminalDisplay * widget); /** * Removes a view from this session. When the last view is removed, * the session will be closed automatically. @@ -103,18 +102,18 @@ * @p widget will no longer display output from or send input * to the terminal */ - void removeView (TerminalDisplay * widget); + //void removeView (TerminalDisplay * widget); /** * Returns the views connected to this session */ - QList < TerminalDisplay * >views () const; + // QList < TerminalDisplay * >views () const; /** * Returns the terminal emulation instance being used to encode / decode * characters to / from the process. */ - Emulation *emulation () const; + //Emulation *emulation () const; /** Returns the arguments passed to the shell process when run() is called. */ QStringList arguments () const; @@ -141,36 +140,6 @@ */ 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 (); - - /** - * 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. @@ -444,7 +413,7 @@ void activityStateSet (int); //automatically detach views from sessions when view is destroyed - void viewDestroyed (QObject * view); + //void viewDestroyed (QObject * view); void updateFlowControlState (bool suspended); void updateWindowSize (int lines, int columns); @@ -463,9 +432,9 @@ QUuid _uniqueIdentifier; // SHELL_SESSION_ID Pty *_shellProcess; - Emulation *_emulation; + //Emulation *_emulation; - QList < TerminalDisplay * >_views; + //QList < TerminalDisplay * >_views; bool _monitorActivity; bool _monitorSilence; diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/TerminalCharacterDecoder.cpp --- a/gui/src/terminal/TerminalCharacterDecoder.cpp Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,267 +0,0 @@ -/* - This file is part of Konsole, an X terminal. - - Copyright 2006-2008 by Robert Knight - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser 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 Lesser 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 "TerminalCharacterDecoder.h" - -// Qt -#include - -// Konsole -#include "konsole_wcwidth.h" - -PlainTextDecoder::PlainTextDecoder ():_output (0), _includeTrailingWhitespace (true), -_recordLinePositions (false) -{ - -} - -void -PlainTextDecoder::setTrailingWhitespace (bool enable) -{ - _includeTrailingWhitespace = enable; -} - -bool -PlainTextDecoder::trailingWhitespace () const -{ - return _includeTrailingWhitespace; -} - -void -PlainTextDecoder::begin (QTextStream * output) -{ - _output = output; - if (!_linePositions.isEmpty ()) - _linePositions.clear (); -} - -void -PlainTextDecoder::end () -{ - _output = 0; -} - -void -PlainTextDecoder::setRecordLinePositions (bool record) -{ - _recordLinePositions = record; -} - -QList < int > -PlainTextDecoder::linePositions () const -{ - return _linePositions; -} - -void -PlainTextDecoder::decodeLine (const Character * const characters, int count, LineProperty /*properties */ - ) -{ - Q_ASSERT (_output); - - if (_recordLinePositions && _output->string ()) - { - int pos = _output->string ()->count (); - _linePositions << pos; - } - - //TODO should we ignore or respect the LINE_WRAPPED line property? - - //note: we build up a QString and send it to the text stream rather writing into the text - //stream a character at a time because it is more efficient. - //(since QTextStream always deals with QStrings internally anyway) - QString plainText; - plainText.reserve (count); - - int outputCount = count; - - // if inclusion of trailing whitespace is disabled then find the end of the - // line - if (!_includeTrailingWhitespace) - { - for (int i = count - 1; i >= 0; i--) - { - if (characters[i].character != ' ') - break; - else - outputCount--; - } - } - - for (int i = 0; i < outputCount;) - { - plainText.append (QChar (characters[i].character)); - i += qMax (1, konsole_wcwidth (characters[i].character)); - } - *_output << plainText; -} - -HTMLDecoder::HTMLDecoder (): -_output (0), _colorTable (base_color_table), _innerSpanOpen (false), -_lastRendition (DEFAULT_RENDITION) -{ - -} - -void -HTMLDecoder::begin (QTextStream * output) -{ - _output = output; - - QString text; - - //open monospace span - openSpan (text, "font-family:monospace"); - - *output << text; -} - -void -HTMLDecoder::end () -{ - Q_ASSERT (_output); - - QString text; - - closeSpan (text); - - *_output << text; - - _output = 0; - -} - -//TODO: Support for LineProperty (mainly double width , double height) -void -HTMLDecoder::decodeLine (const Character * const characters, int count, LineProperty /*properties */ - ) -{ - Q_ASSERT (_output); - - QString text; - - int spaceCount = 0; - - for (int i = 0; i < count; i++) - { - QChar ch (characters[i].character); - - //check if appearance of character is different from previous char - if (characters[i].rendition != _lastRendition || - characters[i].foregroundColor != _lastForeColor || - characters[i].backgroundColor != _lastBackColor) - { - if (_innerSpanOpen) - closeSpan (text); - - _lastRendition = characters[i].rendition; - _lastForeColor = characters[i].foregroundColor; - _lastBackColor = characters[i].backgroundColor; - - //build up style string - QString style; - - bool useBold; - ColorEntry::FontWeight weight = - characters[i].fontWeight (_colorTable); - if (weight == ColorEntry::UseCurrentFormat) - useBold = _lastRendition & RE_BOLD; - else - useBold = weight == ColorEntry::Bold; - - if (useBold) - style.append ("font-weight:bold;"); - - if (_lastRendition & RE_UNDERLINE) - style.append ("font-decoration:underline;"); - - //colours - a colour table must have been defined first - if (_colorTable) - { - style.append (QString ("color:%1;"). - arg (_lastForeColor.color (_colorTable).name ())); - - if (!characters[i].isTransparent (_colorTable)) - { - style.append (QString ("background-color:%1;"). - arg (_lastBackColor.color (_colorTable). - name ())); - } - } - - //open the span with the current style - openSpan (text, style); - _innerSpanOpen = true; - } - - //handle whitespace - if (ch.isSpace ()) - spaceCount++; - else - spaceCount = 0; - - - //output current character - if (spaceCount < 2) - { - //escape HTML tag characters and just display others as they are - if (ch == '<') - text.append ("<"); - else if (ch == '>') - text.append (">"); - else - text.append (ch); - } - else - { - text.append (" "); //HTML truncates multiple spaces, so use a space marker instead - } - - } - - //close any remaining open inner spans - if (_innerSpanOpen) - closeSpan (text); - - //start new line - text.append ("
"); - - *_output << text; -} - -void -HTMLDecoder::openSpan (QString & text, const QString & style) -{ - text.append (QString ("").arg (style)); -} - -void -HTMLDecoder::closeSpan (QString & text) -{ - text.append (""); -} - -void -HTMLDecoder::setColorTable (const ColorEntry * table) -{ - _colorTable = table; -} diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/TerminalCharacterDecoder.h --- a/gui/src/terminal/TerminalCharacterDecoder.h Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* - This file is part of Konsole, an X terminal. - - Copyright 2006-2008 by Robert Knight - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser 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 Lesser 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 TERMINAL_CHARACTER_DECODER_H -#define TERMINAL_CHARACTER_DECODER_H - -#include "Character.h" - -#include - -class QTextStream; - -/** - * Base class for terminal character decoders - * - * The decoder converts lines of terminal characters which consist of a unicode character, foreground - * and background colours and other appearance-related properties into text strings. - * - * Derived classes may produce either plain text with no other colour or appearance information, or - * they may produce text which incorporates these additional properties. - */ -class TerminalCharacterDecoder -{ -public: - virtual ~ TerminalCharacterDecoder () - { - } - - /** Begin decoding characters. The resulting text is appended to @p output. */ - virtual void begin (QTextStream * output) = 0; - /** End decoding. */ - virtual void end () = 0; - - /** - * Converts a line of terminal characters with associated properties into a text string - * and writes the string into an output QTextStream. - * - * @param characters An array of characters of length @p count. - * @param count The number of characters - * @param properties Additional properties which affect all characters in the line - */ - virtual void decodeLine (const Character * const characters, - int count, LineProperty properties) = 0; -}; - -/** - * A terminal character decoder which produces plain text, ignoring colours and other appearance-related - * properties of the original characters. - */ -class PlainTextDecoder:public TerminalCharacterDecoder -{ -public: - PlainTextDecoder (); - - /** - * Set whether trailing whitespace at the end of lines should be included - * in the output. - * Defaults to true. - */ - void setTrailingWhitespace (bool enable); - /** - * Returns whether trailing whitespace at the end of lines is included - * in the output. - */ - bool trailingWhitespace () const; - /** - * Returns of character positions in the output stream - * at which new lines where added. Returns an empty if setTrackLinePositions() is false or if - * the output device is not a string. - */ - QList < int >linePositions () const; - /** Enables recording of character positions at which new lines are added. See linePositions() */ - void setRecordLinePositions (bool record); - - virtual void begin (QTextStream * output); - virtual void end (); - - virtual void decodeLine (const Character * const characters, - int count, LineProperty properties); - - -private: - QTextStream * _output; - bool _includeTrailingWhitespace; - - bool _recordLinePositions; - QList < int >_linePositions; -}; - -/** - * A terminal character decoder which produces pretty HTML markup - */ -class HTMLDecoder:public TerminalCharacterDecoder -{ -public: - /** - * Constructs an HTML decoder using a default black-on-white color scheme. - */ - HTMLDecoder (); - - /** - * Sets the colour table which the decoder uses to produce the HTML colour codes in its - * output - */ - void setColorTable (const ColorEntry * table); - - virtual void decodeLine (const Character * const characters, - int count, LineProperty properties); - - virtual void begin (QTextStream * output); - virtual void end (); - -private: - void openSpan (QString & text, const QString & style); - void closeSpan (QString & text); - - QTextStream *_output; - const ColorEntry *_colorTable; - bool _innerSpanOpen; - quint8 _lastRendition; - CharacterColor _lastForeColor; - CharacterColor _lastBackColor; - -}; - -#endif diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/TerminalDisplay.cpp --- a/gui/src/terminal/TerminalDisplay.cpp Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3069 +0,0 @@ -/* - This file is part of Konsole, a terminal emulator for KDE. - - Copyright 2006-2008 by Robert Knight - Copyright 1997,1998 by Lars Doelle - - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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./+@" - -const ColorEntry base_color_table[TABLE_COLORS] = -// The following are almost IBM standard color codes, with some slight -// gamma correction for the dim colors to compensate for bright X screens. -// It contains the 8 ansiterm/xterm colors in 2 intensities. -{ - // Fixme: could add faint colors here, also. - // normal - ColorEntry (QColor (0x00, 0x00, 0x00), 0), ColorEntry (QColor (0xB2, 0xB2, 0xB2), 1), // Dfore, Dback - ColorEntry (QColor (0x00, 0x00, 0x00), 0), ColorEntry (QColor (0xB2, 0x18, 0x18), 0), // Black, Red - ColorEntry (QColor (0x18, 0xB2, 0x18), 0), ColorEntry (QColor (0xB2, 0x68, 0x18), 0), // Green, Yellow - ColorEntry (QColor (0x18, 0x18, 0xB2), 0), ColorEntry (QColor (0xB2, 0x18, 0xB2), 0), // Blue, Magenta - ColorEntry (QColor (0x18, 0xB2, 0xB2), 0), ColorEntry (QColor (0xB2, 0xB2, 0xB2), 0), // Cyan, White - // intensiv - ColorEntry (QColor (0x00, 0x00, 0x00), 0), - ColorEntry (QColor (0xFF, 0xFF, 0xFF), 1), - ColorEntry (QColor (0x68, 0x68, 0x68), 0), - ColorEntry (QColor (0xFF, 0x54, 0x54), 0), - ColorEntry (QColor (0x54, 0xFF, 0x54), 0), - ColorEntry (QColor (0xFF, 0xFF, 0x54), 0), - ColorEntry (QColor (0x54, 0x54, 0xFF), 0), - ColorEntry (QColor (0xFF, 0x54, 0xFF), 0), - ColorEntry (QColor (0x54, 0xFF, 0xFF), 0), - ColorEntry (QColor (0xFF, 0xFF, 0xFF), 0) -}; - -// scroll increment used when dragging selection at top/bottom of window. - -// static -bool - TerminalDisplay::_antialiasText = true; -bool - TerminalDisplay::HAVE_TRANSPARENCY = false; - -// we use this to force QPainter to display text in LTR mode -// more information can be found in: http://unicode.org/reports/tr9/ -const QChar -LTR_OVERRIDE_CHAR (0x202D); - -/* ------------------------------------------------------------------------- */ -/* */ -/* 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) - { - - // TODO: Determine if this is an issue. - //#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::setBackgroundColor (const QColor & color) -{ - _colorTable[DEFAULT_BACK_COLOR].color = color; - QPalette p = palette (); - p.setColor (backgroundRole (), color); - setPalette (p); - - // Avoid propagating the palette change to the scroll bar - _scrollBar->setPalette (QApplication::palette ()); - - update (); -} - -void -TerminalDisplay::setForegroundColor (const QColor & color) -{ - _colorTable[DEFAULT_FORE_COLOR].color = color; - - update (); -} - -void -TerminalDisplay::setColorTable (const ColorEntry table[]) -{ - for (int i = 0; i < TABLE_COLORS; i++) - _colorTable[i] = table[i]; - - setBackgroundColor (_colorTable[DEFAULT_BACK_COLOR].color); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* 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 (!QFontInfo (font).fixedPitch ()) - { - //kWarning() << "Using an unsupported variable-width font in the terminal. This may produce display errors."; - } - - 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), _boldIntense (true), -_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), -_hasBlinker (false), _cursorBlinking (false), _hasBlinkingCursor (false), -_allowBlinkingText (true), _ctrlDrag (true), -_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) -{ - // 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 ())); - - //KCursor::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->setContentsMargins (0, 0, 0, 0); - - setLayout (_gridLayout); - - new - AutoScrollHandler (this); -} - -TerminalDisplay::~TerminalDisplay () -{ - disconnect (_blinkTimer); - disconnect (_blinkCursorTimer); - 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) -}; - -void -TerminalDisplay::setKeyboardCursorShape (KeyboardCursorShape shape) -{ - _cursorShape = shape; -} - -TerminalDisplay::KeyboardCursorShape TerminalDisplay::keyboardCursorShape () const -{ - return _cursorShape; -} - -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 boldJ and underline - bool useBold; - ColorEntry::FontWeight weight = style->fontWeight (_colorTable); - if (weight == ColorEntry::UseCurrentFormat) - useBold = ((style->rendition & RE_BOLD) && _boldIntense) - || font ().bold (); - else - useBold = (weight == ColorEntry::Bold) ? true : false; - 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); - } - - // setup pen - 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); - } - - if (_bidiEnabled) - painter.drawText (rect, 0, text); - else - painter.drawText (rect, 0, LTR_OVERRIDE_CHAR + 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; - _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 -void -TerminalDisplay::scrollImage (int lines, const QRect & screenWindowRegion) -{ - // if the flow control warning is enabled this will interfere with the - // scrolling optimizations and cause artifacts. the simple solution here - // is to just disable the optimization 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)); - - // return if there is nothing to do - if (lines == 0 - || _image == 0 - || !region.isValid () - || (region.top () + abs (lines)) >= region.bottom () - || this->_lines <= region.height ()) - return; - - // hide terminal size label to prevent it being scrolled - if (_resizeWidget && _resizeWidget->isVisible ()) - _resizeWidget->hide (); - - // Note: With Qt 4.4 the left edge of the scrolled area must be at 0 - // to get the correct (newly exposed) part of the widget repainted. - // - // The right edge must be before the left edge of the scroll bar to - // avoid triggering a repaint of the entire widget, the distance is - // given by SCROLLBAR_CONTENT_GAP - // - // Set the QT_FLUSH_PAINT environment variable to '1' before starting the - // application to monitor repainting. - // - int scrollBarWidth = _scrollBar->isHidden ()? 0 : _scrollBar->width (); - const int SCROLLBAR_CONTENT_GAP = 1; - QRect scrollRect; - if (_scrollbarLocation == ScrollBarLeft) - { - scrollRect.setLeft (scrollBarWidth + SCROLLBAR_CONTENT_GAP); - scrollRect.setRight (width ()); - } - else - { - scrollRect.setLeft (0); - scrollRect.setRight (width () - scrollBarWidth - SCROLLBAR_CONTENT_GAP); - } - 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 - scrollRect.setTop (top); - } - 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 - scrollRect.setTop (top + abs (lines) * _fontHeight); - } - scrollRect.setHeight (linesToMove * _fontHeight); - - Q_ASSERT (scrollRect.isValid () && !scrollRect.isEmpty ()); - - //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 r; - if (hotSpot->startLine () == hotSpot->endLine ()) - { - r.setLeft (hotSpot->startColumn ()); - r.setTop (hotSpot->startLine ()); - r.setRight (hotSpot->endColumn ()); - r.setBottom (hotSpot->endLine ()); - region |= imageToWidget (r);; - } - else - { - r.setLeft (hotSpot->startColumn ()); - r.setTop (hotSpot->startLine ()); - r.setRight (_columns); - r.setBottom (hotSpot->startLine ()); - region |= imageToWidget (r);; - for (int line = hotSpot->startLine () + 1; line < hotSpot->endLine (); - line++) - { - r.setLeft (0); - r.setTop (line); - r.setRight (_columns); - r.setBottom (line); - region |= imageToWidget (r);; - } - r.setLeft (0); - r.setTop (hotSpot->endLine ()); - r.setRight (hotSpot->endColumn ()); - r.setBottom (hotSpot->endLine ()); - region |= imageToWidget (r);; - } - } - 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 (); - - if (!_image) - { - // Create _image. - // The emitted changedContentSizeSignal also leads to getImage being recreated, so do this first. - updateImageSize (); - } - - Character *const newimg = _screenWindow->getImage (); - int lines = _screenWindow->windowLines (); - int columns = _screenWindow->windowColumns (); - - setScroll (_screenWindow->currentLine (), _screenWindow->lineCount ()); - - 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 (TEXT_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 (QString ("Size: XXX x XXX"), this); - _resizeWidget->setMinimumWidth (_resizeWidget->fontMetrics (). - width (QString - ("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 = QString ("Size: %1 x %2").arg (_columns).arg (_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 (QApplication::cursorFlashTime () / 2); - - if (!blink && _blinkCursorTimer->isActive ()) - { - _blinkCursorTimer->stop (); - if (_cursorBlinking) - blinkCursorEvent (); - else - _cursorBlinking = false; - } -} - -void -TerminalDisplay::setBlinkingTextEnabled (bool blink) -{ - _allowBlinkingText = blink; - - if (blink && !_blinkTimer->isActive ()) - _blinkTimer->start (TEXT_BLINK_DELAY); - - if (!blink && _blinkTimer->isActive ()) - { - _blinkTimer->stop (); - _blinking = false; - } -} - -void -TerminalDisplay::focusOutEvent (QFocusEvent *) -{ - // trigger a repaint of the cursor so that it is both visible (in case - // it was hidden during blinking) - // and drawn in a focused out state - _cursorBlinking = false; - updateCursor (); - - _blinkCursorTimer->stop (); - if (_blinking) - blinkEvent (); - - _blinkTimer->stop (); -} - -void -TerminalDisplay::focusInEvent (QFocusEvent *) -{ - updateImage (); - if (_hasBlinkingCursor) - { - _blinkCursorTimer->start (); - } - updateCursor (); - - if (_hasBlinker) - _blinkTimer->start (); -} - -void -TerminalDisplay::paintEvent (QPaintEvent * pe) -{ - QPainter paint (this); - - foreach (const QRect & rect, (pe->region () & contentsRect ()).rects ()) - { - drawBackground (paint, rect, palette ().background ().color (), - true /* use opacity setting */ ); - drawContents (paint, rect); - } - drawInputMethodPreeditString (paint, preeditRect ()); - paintFilters (paint); -} - -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) -{ - // get color of character under mouse and use it to draw - // lines for filters - QPoint cursorPos = mapFromGlobal (QCursor::pos ()); - int cursorLine; - int cursorColumn; - int scrollBarWidth = - (_scrollbarLocation == ScrollBarLeft) ? _scrollBar->width () : 0; - - 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 (); - - QRegion region; - if (spot->type () == Filter::HotSpot::Link) - { - QRect r; - if (spot->startLine () == spot->endLine ()) - { - r.setCoords (spot->startColumn () * _fontWidth + 1 + - scrollBarWidth, - spot->startLine () * _fontHeight + 1, - (spot->endColumn () - 1) * _fontWidth - 1 + - scrollBarWidth, - (spot->endLine () + 1) * _fontHeight - 1); - region |= r; - } - else - { - r.setCoords (spot->startColumn () * _fontWidth + 1 + - scrollBarWidth, - spot->startLine () * _fontHeight + 1, - (_columns - 1) * _fontWidth - 1 + scrollBarWidth, - (spot->startLine () + 1) * _fontHeight - 1); - region |= r; - for (int line = spot->startLine () + 1; line < spot->endLine (); - line++) - { - r.setCoords (0 * _fontWidth + 1 + scrollBarWidth, - line * _fontHeight + 1, - (_columns - 1) * _fontWidth - 1 + - scrollBarWidth, (line + 1) * _fontHeight - 1); - region |= r; - } - r.setCoords (0 * _fontWidth + 1 + scrollBarWidth, - spot->endLine () * _fontHeight + 1, - (spot->endColumn () - 1) * _fontWidth - 1 + - scrollBarWidth, - (spot->endLine () + 1) * _fontHeight - 1); - region |= r; - } - } - - 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 + scrollBarWidth, - line * _fontHeight + 1, - endColumn * _fontWidth - 1 + scrollBarWidth, - (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 (region.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) -{ - QPoint tL = contentsRect ().topLeft (); - int tLx = tL.x (); - int tLy = tL.y (); - - 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; - QString unistr; - unistr.reserve (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; - - // reset our buffer to the maximal size - unistr.resize (bufferSize); - QChar *disstrU = unistr.data (); - - // 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; - unistr.resize (p); - - // Create a text scaling matrix for double width and double height lines. - QMatrix textScale; - - if (y < _lineProperties.size ()) - { - if (_lineProperties[y] & LINE_DOUBLEWIDTH) - textScale.scale (2, 1); - - if (_lineProperties[y] & LINE_DOUBLEHEIGHT) - textScale.scale (1, 2); - } - - //Apply text scaling matrix. - paint.setWorldMatrix (textScale, true); - - //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) - textArea.moveTopLeft (textScale.inverted (). - map (textArea.topLeft ())); - - //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.setWorldMatrix (textScale.inverted (), true); - - 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; - } - } -} - -void -TerminalDisplay::blinkEvent () -{ - if (!_allowBlinkingText) - return; - - _blinking = !_blinking; - - //TODO: Optimize 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 -{ - 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::updateCursor () -{ - QRect cursorRect = imageToWidget (QRect (cursorPosition (), QSize (1, 1))); - update (cursorRect); -} - -void -TerminalDisplay::blinkCursorEvent () -{ - _cursorBlinking = !_cursorBlinking; - updateCursor (); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* 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 () -{ - 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); - - if (oldimg) - { - for (int line = 0; line < lines; line++) - { - memcpy ((void *) &_image[_columns * line], - (void *) &oldimg[oldcol * line], - columns * sizeof (Character)); - } - delete[]oldimg; - } - - if (_screenWindow) - _screenWindow->setWindowLines (_lines); - - _resizing = (oldlin != _lines) || (oldcol != _columns); - - if (_resizing) - { - showResizeNotification (); - emit changedContentSizeSignal (_contentHeight, _contentWidth); // expose resizeEvent - } - - _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. -// -//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) -{ - // 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 (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; - int scrollBarWidth = - (_scrollbarLocation == ScrollBarLeft) ? _scrollBar->width () : 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) - { - QRegion previousHotspotArea = _mouseOverHotspotArea; - _mouseOverHotspotArea = QRegion (); - QRect r; - if (spot->startLine () == spot->endLine ()) - { - r.setCoords (spot->startColumn () * _fontWidth + scrollBarWidth, - spot->startLine () * _fontHeight, - spot->endColumn () * _fontWidth + scrollBarWidth, - (spot->endLine () + 1) * _fontHeight - 1); - _mouseOverHotspotArea |= r; - } - else - { - r.setCoords (spot->startColumn () * _fontWidth + scrollBarWidth, - spot->startLine () * _fontHeight, - _columns * _fontWidth - 1 + scrollBarWidth, - (spot->startLine () + 1) * _fontHeight); - _mouseOverHotspotArea |= r; - for (int line = spot->startLine () + 1; line < spot->endLine (); - line++) - { - r.setCoords (0 * _fontWidth + scrollBarWidth, - line * _fontHeight, - _columns * _fontWidth + scrollBarWidth, - (line + 1) * _fontHeight); - _mouseOverHotspotArea |= r; - } - r.setCoords (0 * _fontWidth + scrollBarWidth, - spot->endLine () * _fontHeight, - spot->endColumn () * _fontWidth + scrollBarWidth, - (spot->endLine () + 1) * _fontHeight); - _mouseOverHotspotArea |= r; - } - // 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.boundingRect ()); - } - - update (_mouseOverHotspotArea | previousHotspotArea); - } - else if (!_mouseOverHotspotArea.isEmpty ()) - { - update (_mouseOverHotspotArea); - // set hotspot area to an invalid rectangle - _mouseOverHotspotArea = QRegion (); - } - - // 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 ()); -} - -void -TerminalDisplay::extendSelection (const QPoint & position) -{ - QPoint pos = position; - - if (!_screenWindow) - return; - - //if ( !contentsRect().contains(ev->pos()) ) 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. - - int linesBeyondWidget = 0; - - QRect textBounds (tLx + _leftMargin, - tLy + _topMargin, - _usedColumns * _fontWidth - 1, - _usedLines * _fontHeight - 1); - - // Adjust position within text area bounds. - QPoint oldpos = pos; - - pos.setX (qBound (textBounds.left (), pos.x (), textBounds.right ())); - pos.setY (qBound (textBounds.top (), pos.y (), textBounds.bottom ())); - - if (oldpos.y () > textBounds.bottom ()) - { - linesBeyondWidget = (oldpos.y () - textBounds.bottom ()) / _fontHeight; - _scrollBar->setValue (_scrollBar->value () + linesBeyondWidget + 1); // scrollforward - } - if (oldpos.y () < textBounds.top ()) - { - linesBeyondWidget = (textBounds.top () - oldpos.y ()) / _fontHeight; - _scrollBar->setValue (_scrollBar->value () - linesBeyondWidget - 1); // history - } - - int charColumn = 0; - int charLine = 0; - getCharacterPosition (pos, charLine, charColumn); - - QPoint here = QPoint (charColumn, charLine); //QPoint((pos.x()-tLx-_leftMargin+(_fontWidth/2))/_fontWidth,(pos.y()-tLy-_topMargin)/_fontHeight); - QPoint ohere; - 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; - QChar selClass; - - 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; - QChar selClass; - - 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... - QChar 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 the terminal program is not interested mouse events - // then send the event to the scrollbar if the slider has room to move - // or otherwise send simulated up / down key presses to the terminal program - // for the benefit of programs such as 'less' - if (_mouseMarks) - { - bool canScroll = _scrollBar->maximum () > 0; - if (canScroll) - _scrollBar->event (ev); - else - { - // assume that each Up / Down key event will cause the terminal application - // to scroll by one line. - // - // to get a reasonable scrolling speed, scroll by one line for every 5 degrees - // of mouse wheel rotation. Mouse wheels typically move in steps of 15 degrees, - // giving a scroll of 3 lines - int key = ev->delta () > 0 ? Qt::Key_Up : Qt::Key_Down; - - // QWheelEvent::delta() gives rotation in eighths of a degree - int wheelDegrees = ev->delta () / 8; - int linesToScroll = abs (wheelDegrees) / 5; - - QKeyEvent keyScrollEvent (QEvent::KeyPress, key, Qt::NoModifier); - - for (int i = 0; i < linesToScroll; i++) - emit keyPressedSignal (&keyScrollEvent); - } - } - else - { - // terminal program wants notification of mouse activity - - 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 ()); - QChar 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 (); -} - - -bool -TerminalDisplay::focusNextPrevChild (bool next) -{ - if (next) - return false; // This disables changing the active part in konqueror - // when pressing Tab - return QWidget::focusNextPrevChild (next); -} - - -QChar -TerminalDisplay::charClass (QChar qch) const -{ - if (qch.isSpace ()) - return ' '; - - if (qch.isLetterOrNumber () - || _wordCharacters.contains (qch, Qt::CaseInsensitive)) - return 'a'; - - return qch; -} - -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); - if (!text.isEmpty ()) - 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) -{ - bool emitKeyPressSignal = true; - - if (event->modifiers () == Qt::ControlModifier) - { - switch (event->key ()) - { - case Qt::Key_C: - copyClipboard (); - break; - case Qt::Key_V: - pasteClipboard (); - break; - }; - } - else if (event->modifiers () == Qt::ShiftModifier) - { - bool update = true; - - if (event->key () == Qt::Key_PageUp) - { - _screenWindow->scrollBy (ScreenWindow::ScrollPages, -1); - } - else if (event->key () == Qt::Key_PageDown) - { - _screenWindow->scrollBy (ScreenWindow::ScrollPages, 1); - } - else if (event->key () == Qt::Key_Up) - { - _screenWindow->scrollBy (ScreenWindow::ScrollLines, -1); - } - else if (event->key () == Qt::Key_Down) - { - _screenWindow->scrollBy (ScreenWindow::ScrollLines, 1); - } - else - update = false; - - if (update) - { - _screenWindow->setTrackOutput (_screenWindow->atEndOfOutput ()); - - updateLineProperties (); - updateImage (); - - // do not send key press to terminal - emitKeyPressSignal = false; - } - } - - _actSel = 0; // Key stroke implies a screen update, so TerminalDisplay won't - // know where the current selection is. - - if (_hasBlinkingCursor) - { - _blinkCursorTimer->start (QApplication::cursorFlashTime () / 2); - if (_cursorBlinking) - blinkCursorEvent (); - else - _cursorBlinking = false; - } - - if (emitKeyPressSignal) - emit keyPressedSignal (event); - - event->accept (); - _scrollBar->setValue (_scrollBar->maximum ()); -} - -void -TerminalDisplay::inputMethodEvent (QInputMethodEvent * event) -{ - QKeyEvent keyEvent (QEvent::KeyPress, 0, - (Qt::KeyboardModifiers) 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::handleShortcutOverrideEvent (QKeyEvent * keyEvent) -{ - int modifiers = keyEvent->modifiers (); - - // When a possible shortcut combination is pressed, - // emit the overrideShortcutCheck() signal to allow the host - // to decide whether the terminal should override it or not. - if (modifiers != Qt::NoModifier) - { - int modifierCount = 0; - unsigned int currentModifier = Qt::ShiftModifier; - - while (currentModifier <= Qt::KeypadModifier) - { - if (modifiers & currentModifier) - modifierCount++; - currentModifier <<= 1; - } - if (modifierCount < 2) - { - bool override = false; - emit overrideShortcutCheck (keyEvent, override); - if (override) - { - keyEvent->accept (); - return true; - } - } - } - - // Override any of the following shortcuts because - // they are needed by the terminal - int keyCode = keyEvent->key () | 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 false; -} - -bool -TerminalDisplay::event (QEvent * event) -{ - bool eventHandled = false; - switch (event->type ()) - { - case QEvent::ShortcutOverride: - eventHandled = handleShortcutOverrideEvent ((QKeyEvent *) event); - break; - case QEvent::PaletteChange: - case QEvent::ApplicationPaletteChange: - _scrollBar->setPalette (QApplication::palette ()); - break; - default: - break; - } - return eventHandled ? true : QWidget::event (event); -} - -void -TerminalDisplay::setBellMode (int mode) -{ - _bellMode = mode; -} - -void -TerminalDisplay::enableBell () -{ - _allowBell = true; -} - -void -TerminalDisplay::bell (const QString & message) -{ - Q_UNUSED (message); - 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) - { - // TODO: This will need added back in at some point - //KNotification::beep(); - } - else if (_bellMode == NotifyBell) - { - // TODO: This will need added back in at some point - //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 (_scrollBar->sizeHint ().width (), - 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 () -{ - 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, this must be synced with calcGeometry() -void -TerminalDisplay::setSize (int columns, int lines) -{ - int scrollBarWidth = - _scrollBar->isHidden ()? 0 : _scrollBar->sizeHint ().width (); - int horizontalMargin = 2 * DEFAULT_LEFT_MARGIN; - int verticalMargin = 2 * DEFAULT_TOP_MARGIN; - - QSize newSize = - QSize (horizontalMargin + scrollBarWidth + (columns * _fontWidth), - verticalMargin + (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) -{ - QString dropText; - 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 (QString ("Output has been " - "suspended" - " by pressing Ctrl+S." - " Press Ctrl+Q to resume."), - this); - - QPalette palette (_outputSuspendedLabel->palette ()); - //KColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground); - _outputSuspendedLabel->setPalette (palette); - _outputSuspendedLabel->setAutoFillBackground (true); - _outputSuspendedLabel->setBackgroundRole (QPalette::Base); - _outputSuspendedLabel->setFont (QApplication::font ()); - _outputSuspendedLabel->setContentsMargins (5, 5, 5, 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. -} - -AutoScrollHandler::AutoScrollHandler (QWidget * parent):QObject (parent), -_timerId (0) -{ - //parent->installEventFilter(this); -} - -void -AutoScrollHandler::timerEvent (QTimerEvent * event) -{ - if (event->timerId () != _timerId) - return; - - QMouseEvent mouseEvent (QEvent::MouseMove, - widget ()->mapFromGlobal (QCursor::pos ()), - Qt::NoButton, Qt::LeftButton, Qt::NoModifier); - - QApplication::sendEvent (widget (), &mouseEvent); -} - -bool -AutoScrollHandler::eventFilter (QObject * watched, QEvent * event) -{ - Q_ASSERT (watched == parent ()); - Q_UNUSED (watched); - - QMouseEvent *mouseEvent = (QMouseEvent *) event; - switch (event->type ()) - { - case QEvent::MouseMove: - { - bool mouseInWidget = widget ()->rect ().contains (mouseEvent->pos ()); - - if (mouseInWidget) - { - if (_timerId) - killTimer (_timerId); - _timerId = 0; - } - else - { - if (!_timerId && (mouseEvent->buttons () & Qt::LeftButton)) - _timerId = startTimer (100); - } - break; - } - case QEvent::MouseButtonRelease: - if (_timerId && (mouseEvent->buttons () & ~Qt::LeftButton)) - { - killTimer (_timerId); - _timerId = 0; - } - break; - default: - break; - }; - - return false; -} diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/TerminalDisplay.h --- a/gui/src/terminal/TerminalDisplay.h Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,849 +0,0 @@ -/* - Copyright 2007-2008 by Robert Knight - Copyright 1997,1998 by Lars Doelle - - 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 -#include -#include - -// Konsole -#include "Filter.h" -#include "Character.h" - -class QDrag; -class QDragEnterEvent; -class QDropEvent; -class QLabel; -class QTimer; -class QEvent; -class QGridLayout; -class QKeyEvent; -class QScrollBar; -class QShowEvent; -class QHideEvent; -class QTimerEvent; -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; - - /** - * 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); - - /** Specifies whether or not text can blink. */ - void setBlinkingTextEnabled (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; - - /** - * 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 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; - } - - /** - * Specifies whether characters with intense colors should be rendered - * as bold. Defaults to true. - */ - void setBoldIntense (bool value) - { - _boldIntense = value; - } - /** - * Returns true if characters with intense colors are rendered in bold. - */ - bool getBoldIntense () - { - return _boldIntense; - } - - /** - * 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; - } - - /** - * Sets the status of the BiDi rendering inside the terminal display. - * Defaults to disabled. - */ - void setBidiEnabled (bool set) - { - _bidiEnabled = set; - } - /** - * Returns the status of the BiDi rendering in this widget. - */ - 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); - /** - * Returns true if the flow control warning box is enabled. - * See outputSuspended() and setFlowControlWarningEnabled() - */ - bool flowControlWarningEnabled () const - { - return _flowControlWarningEnabled; - } - - /** - * 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); - - /** - * Sets the background of the display to the specified color. - * @see setColorTable(), setForegroundColor() - */ - void setBackgroundColor (const QColor & color); - - /** - * Sets the text of the display to the specified color. - * @see setColorTable(), setBackgroundColor() - */ - void setForegroundColor (const QColor & color); - -signals: - - /** - * Emitted when the user presses a key whilst the terminal widget has focus. - */ - void keyPressedSignal (QKeyEvent * e); - - /** - * 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 (const QPoint & position); - - /** - * When a shortcut which is also a valid terminal key sequence is pressed while - * the terminal widget has focus, this signal is emitted to allow the host to decide - * whether the shortcut should be overridden. - * When the shortcut is overridden, the key sequence will be sent to the terminal emulation instead - * and the action associated with the shortcut will not be triggered. - * - * @p override is set to false by default and the shortcut will be triggered as normal. - */ - void overrideShortcutCheck (QKeyEvent * keyEvent, bool & override); - - void isBusySelecting (bool); - void sendStringToEmu (const char *); - -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 focusInEvent (QFocusEvent * event); - virtual void focusOutEvent (QFocusEvent * event); - 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; - - // classifies the 'ch' into one of three categories - // and returns a character to indicate which category it is in - // - // - A space (returns ' ') - // - Part of a word (returns 'a') - // - Other characters (returns the input character) - QChar charClass (QChar ch) 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 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; - - // redraws the cursor - void updateCursor (); - - bool handleShortcutOverrideEvent (QKeyEvent * event); - - // 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 - bool _boldIntense; // Whether intense colors should be rendered with bold font - - 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 _allowBlinkingText; // allow text to blink - 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 - - 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; - QRegion _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 TEXT_BLINK_DELAY = 500; - static const int DEFAULT_LEFT_MARGIN = 1; - static const int DEFAULT_TOP_MARGIN = 1; - -public: - static void setTransparencyEnabled (bool enable) - { - HAVE_TRANSPARENCY = enable; - } -}; - -class AutoScrollHandler:public QObject -{ -Q_OBJECT public: - AutoScrollHandler (QWidget * parent); -protected: - virtual void timerEvent (QTimerEvent * event); - virtual bool eventFilter (QObject * watched, QEvent * event); -private: - QWidget * widget () const - { - return static_cast < QWidget * >(parent ()); - } - int _timerId; -}; - - -#endif // TERMINALDISPLAY_H diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/Vt102Emulation.cpp --- a/gui/src/terminal/Vt102Emulation.cpp Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1790 +0,0 @@ -/* - This file is part of Konsole, an X terminal. - - Copyright 2007-2008 by Robert Knight - Copyright 1997,1998 by Lars Doelle - - 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 "Vt102Emulation.h" - - -// this allows konsole to be compiled without XKB and XTEST extensions -// even though it might be available on a particular system. -#if defined(AVOID_XKB) -#undef HAVE_XKB -#endif - -#if defined(HAVE_XKB) -void scrolllock_set_off (); -void scrolllock_set_on (); -#endif - -// Standard -#include -#include -#include - -// Qt -#include -#include -#include - -// Konsole -#include "KeyboardTranslator.h" -#include "Screen.h" - -Vt102Emulation::Vt102Emulation ():Emulation (), -_titleUpdateTimer (new QTimer (this)) -{ - _titleUpdateTimer->setSingleShot (true); - QObject::connect (_titleUpdateTimer, SIGNAL (timeout ()), this, - SLOT (updateTitle ())); - - initTokenizer (); - reset (); -} - -Vt102Emulation::~Vt102Emulation () -{ -} - -void -Vt102Emulation::clearEntireScreen () -{ - _currentScreen->clearEntireScreen (); - bufferedUpdate (); -} - -void -Vt102Emulation::reset () -{ - resetTokenizer (); - resetModes (); - resetCharset (0); - _screen[0]->reset (); - resetCharset (1); - _screen[1]->reset (); - setCodec (LocaleCodec); - - bufferedUpdate (); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Processing the incoming byte stream */ -/* */ -/* ------------------------------------------------------------------------- */ - -/* Incoming Bytes Event pipeline - - This section deals with decoding the incoming character stream. - Decoding means here, that the stream is first separated into `tokens' - which are then mapped to a `meaning' provided as operations by the - `Screen' class or by the emulation class itself. - - The pipeline proceeds as follows: - - - Tokenizing the ESC codes (onReceiveChar) - - VT100 code page translation of plain characters (applyCharset) - - Interpretation of ESC codes (processToken) - - The escape codes and their meaning are described in the - technical reference of this program. -*/ - -// Tokens ------------------------------------------------------------------ -- - -/* - Since the tokens are the central notion if this section, we've put them - in front. They provide the syntactical elements used to represent the - terminals operations as byte sequences. - - They are encodes here into a single machine word, so that we can later - switch over them easily. Depending on the token itself, additional - argument variables are filled with parameter values. - - The tokens are defined below: - - - CHR - Printable characters (32..255 but DEL (=127)) - - CTL - Control characters (0..31 but ESC (= 27), DEL) - - ESC - Escape codes of the form - - ESC_DE - Escape codes of the form C - - CSI_PN - Escape codes of the form '[' {Pn} ';' {Pn} C - - CSI_PS - Escape codes of the form '[' {Pn} ';' ... C - - CSI_PR - Escape codes of the form '[' '?' {Pn} ';' ... C - - CSI_PE - Escape codes of the form '[' '!' {Pn} ';' ... C - - VT52 - VT52 escape codes - - - - 'Y'{Pc}{Pc} - - XTE_HA - Xterm window/terminal attribute commands - of the form `]' {Pn} `;' {Text} - (Note that these are handled differently to the other formats) - - The last two forms allow list of arguments. Since the elements of - the lists are treated individually the same way, they are passed - as individual tokens to the interpretation. Further, because the - meaning of the parameters are names (althought represented as numbers), - they are includes within the token ('N'). - -*/ - -#define TY_CONSTRUCT(T,A,N) ( ((((int)N) & 0xffff) << 16) | ((((int)A) & 0xff) << 8) | (((int)T) & 0xff) ) - -#define TY_CHR( ) TY_CONSTRUCT(0,0,0) -#define TY_CTL(A ) TY_CONSTRUCT(1,A,0) -#define TY_ESC(A ) TY_CONSTRUCT(2,A,0) -#define TY_ESC_CS(A,B) TY_CONSTRUCT(3,A,B) -#define TY_ESC_DE(A ) TY_CONSTRUCT(4,A,0) -#define TY_CSI_PS(A,N) TY_CONSTRUCT(5,A,N) -#define TY_CSI_PN(A ) TY_CONSTRUCT(6,A,0) -#define TY_CSI_PR(A,N) TY_CONSTRUCT(7,A,N) - -#define TY_VT52(A) TY_CONSTRUCT(8,A,0) -#define TY_CSI_PG(A) TY_CONSTRUCT(9,A,0) -#define TY_CSI_PE(A) TY_CONSTRUCT(10,A,0) - -#define MAX_ARGUMENT 4096 - -// Tokenizer --------------------------------------------------------------- -- - -/* The tokenizer's state - - The state is represented by the buffer (tokenBuffer, tokenBufferPos), - and accompanied by decoded arguments kept in (argv,argc). - Note that they are kept internal in the tokenizer. -*/ - -void -Vt102Emulation::resetTokenizer () -{ - tokenBufferPos = 0; - argc = 0; - argv[0] = 0; - argv[1] = 0; -} - -void -Vt102Emulation::addDigit (int digit) -{ - if (argv[argc] < MAX_ARGUMENT) - argv[argc] = 10 * argv[argc] + digit; -} - -void -Vt102Emulation::addArgument () -{ - argc = qMin (argc + 1, MAXARGS - 1); - argv[argc] = 0; -} - -void -Vt102Emulation::addToCurrentToken (int cc) -{ - tokenBuffer[tokenBufferPos] = cc; - tokenBufferPos = qMin (tokenBufferPos + 1, MAX_TOKEN_LENGTH - 1); -} - -// Character Class flags used while decoding - -#define CTL 1 // Control character -#define CHR 2 // Printable character -#define CPN 4 // TODO: Document me -#define DIG 8 // Digit -#define SCS 16 // TODO: Document me -#define GRP 32 // TODO: Document me -#define CPS 64 // Character which indicates end of window resize - // escape sequence '\e[8;;t' - -void -Vt102Emulation::initTokenizer () -{ - int i; - quint8 *s; - for (i = 0; i < 256; ++i) - charClass[i] = 0; - for (i = 0; i < 32; ++i) - charClass[i] |= CTL; - for (i = 32; i < 256; ++i) - charClass[i] |= CHR; - for (s = (quint8 *) "@ABCDGHILMPSTXZcdfry"; *s; ++s) - charClass[*s] |= CPN; - // resize = \e[8;;t - for (s = (quint8 *) "t"; *s; ++s) - charClass[*s] |= CPS; - for (s = (quint8 *) "0123456789"; *s; ++s) - charClass[*s] |= DIG; - for (s = (quint8 *) "()+*%"; *s; ++s) - charClass[*s] |= SCS; - for (s = (quint8 *) "()+*#[]%"; *s; ++s) - charClass[*s] |= GRP; - - resetTokenizer (); -} - -/* Ok, here comes the nasty part of the decoder. - - Instead of keeping an explicit state, we deduce it from the - token scanned so far. It is then immediately combined with - the current character to form a scanning decision. - - This is done by the following defines. - - - P is the length of the token scanned so far. - - L (often P-1) is the position on which contents we base a decision. - - C is a character or a group of characters (taken from 'charClass'). - - - 'cc' is the current character - - 's' is a pointer to the start of the token buffer - - 'p' is the current position within the token buffer - - Note that they need to applied in proper order. -*/ - -#define lec(P,L,C) (p == (P) && s[(L)] == (C)) -#define lun( ) (p == 1 && cc >= 32 ) -#define les(P,L,C) (p == (P) && s[L] < 256 && (charClass[s[(L)]] & (C)) == (C)) -#define eec(C) (p >= 3 && cc == (C)) -#define ees(C) (p >= 3 && cc < 256 && (charClass[cc] & (C)) == (C)) -#define eps(C) (p >= 3 && s[2] != '?' && s[2] != '!' && s[2] != '>' && cc < 256 && (charClass[cc] & (C)) == (C)) -#define epp( ) (p >= 3 && s[2] == '?') -#define epe( ) (p >= 3 && s[2] == '!') -#define egt( ) (p >= 3 && s[2] == '>') -#define Xpe (tokenBufferPos >= 2 && tokenBuffer[1] == ']') -#define Xte (Xpe && cc == 7 ) -#define ces(C) (cc < 256 && (charClass[cc] & (C)) == (C) && !Xte) - -#define ESC 27 -#define CNTL(c) ((c)-'@') - -// process an incoming unicode character -void -Vt102Emulation::receiveChar (int cc) -{ - if (cc == 127) - return; //VT100: ignore. - - if (ces (CTL)) - { - // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100 - // This means, they do neither a resetTokenizer() nor a pushToToken(). Some of them, do - // of course. Guess this originates from a weakly layered handling of the X-on - // X-off protocol, which comes really below this level. - if (cc == CNTL ('X') || cc == CNTL ('Z') || cc == ESC) - resetTokenizer (); //VT100: CAN or SUB - if (cc != ESC) - { - processToken (TY_CTL (cc + '@'), 0, 0); - return; - } - } - // advance the state - addToCurrentToken (cc); - - int *s = tokenBuffer; - int p = tokenBufferPos; - - if (getMode (MODE_Ansi)) - { - if (lec (1, 0, ESC)) - { - return; - } - if (lec (1, 0, ESC + 128)) - { - s[0] = ESC; - receiveChar ('['); - return; - } - if (les (2, 1, GRP)) - { - return; - } - if (Xte) - { - processWindowAttributeChange (); - resetTokenizer (); - return; - } - if (Xpe) - { - return; - } - if (lec (3, 2, '?')) - { - return; - } - if (lec (3, 2, '>')) - { - return; - } - if (lec (3, 2, '!')) - { - return; - } - if (lun ()) - { - processToken (TY_CHR (), applyCharset (cc), 0); - resetTokenizer (); - return; - } - if (lec (2, 0, ESC)) - { - processToken (TY_ESC (s[1]), 0, 0); - resetTokenizer (); - return; - } - if (les (3, 1, SCS)) - { - processToken (TY_ESC_CS (s[1], s[2]), 0, 0); - resetTokenizer (); - return; - } - if (lec (3, 1, '#')) - { - processToken (TY_ESC_DE (s[2]), 0, 0); - resetTokenizer (); - return; - } - if (eps (CPN)) - { - processToken (TY_CSI_PN (cc), argv[0], argv[1]); - resetTokenizer (); - return; - } - - // resize = \e[8;;t - if (eps (CPS)) - { - processToken (TY_CSI_PS (cc, argv[0]), argv[1], argv[2]); - resetTokenizer (); - return; - } - - if (epe ()) - { - processToken (TY_CSI_PE (cc), 0, 0); - resetTokenizer (); - return; - } - if (ees (DIG)) - { - addDigit (cc - '0'); - return; - } - if (eec (';')) - { - addArgument (); - return; - } - for (int i = 0; i <= argc; i++) - { - if (epp ()) - processToken (TY_CSI_PR (cc, argv[i]), 0, 0); - else if (egt ()) - processToken (TY_CSI_PG (cc), 0, 0); // spec. case for ESC]>0c or ESC]>c - else if (cc == 'm' && argc - i >= 4 - && (argv[i] == 38 || argv[i] == 48) && argv[i + 1] == 2) - { - // ESC[ ... 48;2;;; ... m -or- ESC[ ... 38;2;;; ... m - i += 2; - processToken (TY_CSI_PS (cc, argv[i - 2]), COLOR_SPACE_RGB, - (argv[i] << 16) | (argv[i + 1] << 8) | argv[i + - 2]); - i += 2; - } - else if (cc == 'm' && argc - i >= 2 - && (argv[i] == 38 || argv[i] == 48) && argv[i + 1] == 5) - { - // ESC[ ... 48;5; ... m -or- ESC[ ... 38;5; ... m - i += 2; - processToken (TY_CSI_PS (cc, argv[i - 2]), COLOR_SPACE_256, - argv[i]); - } - else - processToken (TY_CSI_PS (cc, argv[i]), 0, 0); - } - resetTokenizer (); - } - else - { - // VT52 Mode - if (lec (1, 0, ESC)) - return; - if (les (1, 0, CHR)) - { - processToken (TY_CHR (), s[0], 0); - resetTokenizer (); - return; - } - if (lec (2, 1, 'Y')) - return; - if (lec (3, 1, 'Y')) - return; - if (p < 4) - { - processToken (TY_VT52 (s[1]), 0, 0); - resetTokenizer (); - return; - } - processToken (TY_VT52 (s[1]), s[2], s[3]); - resetTokenizer (); - return; - } -} - -void -Vt102Emulation::processWindowAttributeChange () -{ - // Describes the window or terminal session attribute to change - // See Session::UserTitleChange for possible values - int attributeToChange = 0; - int i; - for (i = 2; i < tokenBufferPos && - tokenBuffer[i] >= '0' && tokenBuffer[i] <= '9'; i++) - { - attributeToChange = 10 * attributeToChange + (tokenBuffer[i] - '0'); - } - - if (tokenBuffer[i] != ';') - { - reportDecodingError (); - return; - } - - QString newValue; - newValue.reserve (tokenBufferPos - i - 2); - for (int j = 0; j < tokenBufferPos - i - 2; j++) - newValue[j] = tokenBuffer[i + 1 + j]; - - _pendingTitleUpdates[attributeToChange] = newValue; - _titleUpdateTimer->start (20); -} - -void -Vt102Emulation::updateTitle () -{ - QListIterator < int >iter (_pendingTitleUpdates.keys ()); - while (iter.hasNext ()) - { - int arg = iter.next (); - emit titleChanged (arg, _pendingTitleUpdates[arg]); - } - _pendingTitleUpdates.clear (); -} - -// Interpreting Codes --------------------------------------------------------- - -/* - Now that the incoming character stream is properly tokenized, - meaning is assigned to them. These are either operations of - the current _screen, or of the emulation class itself. - - The token to be interpreteted comes in as a machine word - possibly accompanied by two parameters. - - Likewise, the operations assigned to, come with up to two - arguments. One could consider to make up a proper table - from the function below. - - The technical reference manual provides more information - about this mapping. -*/ - -void -Vt102Emulation::processToken (int token, int p, int q) -{ - switch (token) - { - - case TY_CHR (): - _currentScreen->displayCharacter (p); - break; //UTF16 - - // 127 DEL : ignored on input - - case TY_CTL ('@'): /* NUL: ignored */ - break; - case TY_CTL ('A'): /* SOH: ignored */ - break; - case TY_CTL ('B'): /* STX: ignored */ - break; - case TY_CTL ('C'): /* ETX: ignored */ - break; - case TY_CTL ('D'): /* EOT: ignored */ - break; - case TY_CTL ('E'): - reportAnswerBack (); - break; //VT100 - case TY_CTL ('F'): /* ACK: ignored */ - break; - case TY_CTL ('G'): - emit stateSet (NOTIFYBELL); - break; //VT100 - case TY_CTL ('H'): - _currentScreen->backspace (); - break; //VT100 - case TY_CTL ('I'): - _currentScreen->tab (); - break; //VT100 - case TY_CTL ('J'): - _currentScreen->newLine (); - break; //VT100 - case TY_CTL ('K'): - _currentScreen->newLine (); - break; //VT100 - case TY_CTL ('L'): - _currentScreen->newLine (); - break; //VT100 - case TY_CTL ('M'): - _currentScreen->toStartOfLine (); - break; //VT100 - - case TY_CTL ('N'): - useCharset (1); - break; //VT100 - case TY_CTL ('O'): - useCharset (0); - break; //VT100 - - case TY_CTL ('P'): /* DLE: ignored */ - break; - case TY_CTL ('Q'): /* DC1: XON continue */ - break; //VT100 - case TY_CTL ('R'): /* DC2: ignored */ - break; - case TY_CTL ('S'): /* DC3: XOFF halt */ - break; //VT100 - case TY_CTL ('T'): /* DC4: ignored */ - break; - case TY_CTL ('U'): /* NAK: ignored */ - break; - case TY_CTL ('V'): /* SYN: ignored */ - break; - case TY_CTL ('W'): /* ETB: ignored */ - break; - case TY_CTL ('X'): - _currentScreen->displayCharacter (0x2592); - break; //VT100 - case TY_CTL ('Y'): /* EM : ignored */ - break; - case TY_CTL ('Z'): - _currentScreen->displayCharacter (0x2592); - break; //VT100 - case TY_CTL ('['): /* ESC: cannot be seen here. */ - break; - case TY_CTL ('\\'): /* FS : ignored */ - break; - case TY_CTL (']'): /* GS : ignored */ - break; - case TY_CTL ('^'): /* RS : ignored */ - break; - case TY_CTL ('_'): /* US : ignored */ - break; - - case TY_ESC ('D'): - _currentScreen->index (); - break; //VT100 - case TY_ESC ('E'): - _currentScreen->nextLine (); - break; //VT100 - case TY_ESC ('H'): - _currentScreen->changeTabStop (true); - break; //VT100 - case TY_ESC ('M'): - _currentScreen->reverseIndex (); - break; //VT100 - case TY_ESC ('Z'): - reportTerminalType (); - break; - case TY_ESC ('c'): - reset (); - break; - - case TY_ESC ('n'): - useCharset (2); - break; - case TY_ESC ('o'): - useCharset (3); - break; - case TY_ESC ('7'): - saveCursor (); - break; - case TY_ESC ('8'): - restoreCursor (); - break; - - case TY_ESC ('='): - setMode (MODE_AppKeyPad); - break; - case TY_ESC ('>'): - resetMode (MODE_AppKeyPad); - break; - case TY_ESC ('<'): - setMode (MODE_Ansi); - break; //VT100 - - case TY_ESC_CS ('(', '0'): - setCharset (0, '0'); - break; //VT100 - case TY_ESC_CS ('(', 'A'): - setCharset (0, 'A'); - break; //VT100 - case TY_ESC_CS ('(', 'B'): - setCharset (0, 'B'); - break; //VT100 - - case TY_ESC_CS (')', '0'): - setCharset (1, '0'); - break; //VT100 - case TY_ESC_CS (')', 'A'): - setCharset (1, 'A'); - break; //VT100 - case TY_ESC_CS (')', 'B'): - setCharset (1, 'B'); - break; //VT100 - - case TY_ESC_CS ('*', '0'): - setCharset (2, '0'); - break; //VT100 - case TY_ESC_CS ('*', 'A'): - setCharset (2, 'A'); - break; //VT100 - case TY_ESC_CS ('*', 'B'): - setCharset (2, 'B'); - break; //VT100 - - case TY_ESC_CS ('+', '0'): - setCharset (3, '0'); - break; //VT100 - case TY_ESC_CS ('+', 'A'): - setCharset (3, 'A'); - break; //VT100 - case TY_ESC_CS ('+', 'B'): - setCharset (3, 'B'); - break; //VT100 - - case TY_ESC_CS ('%', 'G'): - setCodec (Utf8Codec); - break; //LINUX - case TY_ESC_CS ('%', '@'): - setCodec (LocaleCodec); - break; //LINUX - - case TY_ESC_DE ('3'): /* Double height line, top half */ - _currentScreen->setLineProperty (LINE_DOUBLEWIDTH, true); - _currentScreen->setLineProperty (LINE_DOUBLEHEIGHT, true); - break; - case TY_ESC_DE ('4'): /* Double height line, bottom half */ - _currentScreen->setLineProperty (LINE_DOUBLEWIDTH, true); - _currentScreen->setLineProperty (LINE_DOUBLEHEIGHT, true); - break; - case TY_ESC_DE ('5'): /* Single width, single height line */ - _currentScreen->setLineProperty (LINE_DOUBLEWIDTH, false); - _currentScreen->setLineProperty (LINE_DOUBLEHEIGHT, false); - break; - case TY_ESC_DE ('6'): /* Double width, single height line */ - _currentScreen->setLineProperty (LINE_DOUBLEWIDTH, true); - _currentScreen->setLineProperty (LINE_DOUBLEHEIGHT, false); - break; - case TY_ESC_DE ('8'): - _currentScreen->helpAlign (); - break; - -// resize = \e[8;;t - case TY_CSI_PS ('t', 8): - setImageSize (q /* columns */ , p /* lines */ ); - break; - -// change tab text color : \e[28;t color: 0-16,777,215 - case TY_CSI_PS ('t', 28): - emit changeTabTextColorRequest (p); - break; - - case TY_CSI_PS ('K', 0): - _currentScreen->clearToEndOfLine (); - break; - case TY_CSI_PS ('K', 1): - _currentScreen->clearToBeginOfLine (); - break; - case TY_CSI_PS ('K', 2): - _currentScreen->clearEntireLine (); - break; - case TY_CSI_PS ('J', 0): - _currentScreen->clearToEndOfScreen (); - break; - case TY_CSI_PS ('J', 1): - _currentScreen->clearToBeginOfScreen (); - break; - case TY_CSI_PS ('J', 2): - _currentScreen->clearEntireScreen (); - break; - case TY_CSI_PS ('J', 3): - clearHistory (); - break; - case TY_CSI_PS ('g', 0): - _currentScreen->changeTabStop (false); - break; //VT100 - case TY_CSI_PS ('g', 3): - _currentScreen->clearTabStops (); - break; //VT100 - case TY_CSI_PS ('h', 4): - _currentScreen->setMode (MODE_Insert); - break; - case TY_CSI_PS ('h', 20): - setMode (MODE_NewLine); - break; - case TY_CSI_PS ('i', 0): /* IGNORE: attached printer */ - break; //VT100 - case TY_CSI_PS ('l', 4): - _currentScreen->resetMode (MODE_Insert); - break; - case TY_CSI_PS ('l', 20): - resetMode (MODE_NewLine); - break; - case TY_CSI_PS ('s', 0): - saveCursor (); - break; - case TY_CSI_PS ('u', 0): - restoreCursor (); - break; - - case TY_CSI_PS ('m', 0): - _currentScreen->setDefaultRendition (); - break; - case TY_CSI_PS ('m', 1): - _currentScreen->setRendition (RE_BOLD); - break; //VT100 - case TY_CSI_PS ('m', 4): - _currentScreen->setRendition (RE_UNDERLINE); - break; //VT100 - case TY_CSI_PS ('m', 5): - _currentScreen->setRendition (RE_BLINK); - break; //VT100 - case TY_CSI_PS ('m', 7): - _currentScreen->setRendition (RE_REVERSE); - break; - case TY_CSI_PS ('m', 10): /* IGNORED: mapping related */ - break; //LINUX - case TY_CSI_PS ('m', 11): /* IGNORED: mapping related */ - break; //LINUX - case TY_CSI_PS ('m', 12): /* IGNORED: mapping related */ - break; //LINUX - case TY_CSI_PS ('m', 22): - _currentScreen->resetRendition (RE_BOLD); - break; - case TY_CSI_PS ('m', 24): - _currentScreen->resetRendition (RE_UNDERLINE); - break; - case TY_CSI_PS ('m', 25): - _currentScreen->resetRendition (RE_BLINK); - break; - case TY_CSI_PS ('m', 27): - _currentScreen->resetRendition (RE_REVERSE); - break; - - case TY_CSI_PS ('m', 30): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 0); - break; - case TY_CSI_PS ('m', 31): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 1); - break; - case TY_CSI_PS ('m', 32): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 2); - break; - case TY_CSI_PS ('m', 33): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 3); - break; - case TY_CSI_PS ('m', 34): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 4); - break; - case TY_CSI_PS ('m', 35): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 5); - break; - case TY_CSI_PS ('m', 36): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 6); - break; - case TY_CSI_PS ('m', 37): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 7); - break; - - case TY_CSI_PS ('m', 38): - _currentScreen->setForeColor (p, q); - break; - - case TY_CSI_PS ('m', 39): - _currentScreen->setForeColor (COLOR_SPACE_DEFAULT, 0); - break; - - case TY_CSI_PS ('m', 40): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 0); - break; - case TY_CSI_PS ('m', 41): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 1); - break; - case TY_CSI_PS ('m', 42): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 2); - break; - case TY_CSI_PS ('m', 43): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 3); - break; - case TY_CSI_PS ('m', 44): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 4); - break; - case TY_CSI_PS ('m', 45): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 5); - break; - case TY_CSI_PS ('m', 46): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 6); - break; - case TY_CSI_PS ('m', 47): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 7); - break; - - case TY_CSI_PS ('m', 48): - _currentScreen->setBackColor (p, q); - break; - - case TY_CSI_PS ('m', 49): - _currentScreen->setBackColor (COLOR_SPACE_DEFAULT, 1); - break; - - case TY_CSI_PS ('m', 90): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 8); - break; - case TY_CSI_PS ('m', 91): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 9); - break; - case TY_CSI_PS ('m', 92): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 10); - break; - case TY_CSI_PS ('m', 93): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 11); - break; - case TY_CSI_PS ('m', 94): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 12); - break; - case TY_CSI_PS ('m', 95): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 13); - break; - case TY_CSI_PS ('m', 96): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 14); - break; - case TY_CSI_PS ('m', 97): - _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 15); - break; - - case TY_CSI_PS ('m', 100): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 8); - break; - case TY_CSI_PS ('m', 101): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 9); - break; - case TY_CSI_PS ('m', 102): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 10); - break; - case TY_CSI_PS ('m', 103): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 11); - break; - case TY_CSI_PS ('m', 104): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 12); - break; - case TY_CSI_PS ('m', 105): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 13); - break; - case TY_CSI_PS ('m', 106): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 14); - break; - case TY_CSI_PS ('m', 107): - _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 15); - break; - - case TY_CSI_PS ('n', 5): - reportStatus (); - break; - case TY_CSI_PS ('n', 6): - reportCursorPosition (); - break; - case TY_CSI_PS ('q', 0): /* IGNORED: LEDs off */ - break; //VT100 - case TY_CSI_PS ('q', 1): /* IGNORED: LED1 on */ - break; //VT100 - case TY_CSI_PS ('q', 2): /* IGNORED: LED2 on */ - break; //VT100 - case TY_CSI_PS ('q', 3): /* IGNORED: LED3 on */ - break; //VT100 - case TY_CSI_PS ('q', 4): /* IGNORED: LED4 on */ - break; //VT100 - case TY_CSI_PS ('x', 0): - reportTerminalParms (2); - break; //VT100 - case TY_CSI_PS ('x', 1): - reportTerminalParms (3); - break; //VT100 - - case TY_CSI_PN ('@'): - _currentScreen->insertChars (p); - break; - case TY_CSI_PN ('A'): - _currentScreen->cursorUp (p); - break; //VT100 - case TY_CSI_PN ('B'): - _currentScreen->cursorDown (p); - break; //VT100 - case TY_CSI_PN ('C'): - _currentScreen->cursorRight (p); - break; //VT100 - case TY_CSI_PN ('D'): - _currentScreen->cursorLeft (p); - break; //VT100 - case TY_CSI_PN ('G'): - _currentScreen->setCursorX (p); - break; //LINUX - case TY_CSI_PN ('H'): - _currentScreen->setCursorYX (p, q); - break; //VT100 - case TY_CSI_PN ('I'): - _currentScreen->tab (p); - break; - case TY_CSI_PN ('L'): - _currentScreen->insertLines (p); - break; - case TY_CSI_PN ('M'): - _currentScreen->deleteLines (p); - break; - case TY_CSI_PN ('P'): - _currentScreen->deleteChars (p); - break; - case TY_CSI_PN ('S'): - _currentScreen->scrollUp (p); - break; - case TY_CSI_PN ('T'): - _currentScreen->scrollDown (p); - break; - case TY_CSI_PN ('X'): - _currentScreen->eraseChars (p); - break; - case TY_CSI_PN ('Z'): - _currentScreen->backtab (p); - break; - case TY_CSI_PN ('c'): - reportTerminalType (); - break; //VT100 - case TY_CSI_PN ('d'): - _currentScreen->setCursorY (p); - break; //LINUX - case TY_CSI_PN ('f'): - _currentScreen->setCursorYX (p, q); - break; //VT100 - case TY_CSI_PN ('r'): - setMargins (p, q); - break; //VT100 - case TY_CSI_PN ('y'): /* IGNORED: Confidence test */ - break; //VT100 - - case TY_CSI_PR ('h', 1): - setMode (MODE_AppCuKeys); - break; //VT100 - case TY_CSI_PR ('l', 1): - resetMode (MODE_AppCuKeys); - break; //VT100 - case TY_CSI_PR ('s', 1): - saveMode (MODE_AppCuKeys); - break; //FIXME - case TY_CSI_PR ('r', 1): - restoreMode (MODE_AppCuKeys); - break; //FIXME - - case TY_CSI_PR ('l', 2): - resetMode (MODE_Ansi); - break; //VT100 - - case TY_CSI_PR ('h', 3): - setMode (MODE_132Columns); - break; //VT100 - case TY_CSI_PR ('l', 3): - resetMode (MODE_132Columns); - break; //VT100 - - case TY_CSI_PR ('h', 4): /* IGNORED: soft scrolling */ - break; //VT100 - case TY_CSI_PR ('l', 4): /* IGNORED: soft scrolling */ - break; //VT100 - - case TY_CSI_PR ('h', 5): - _currentScreen->setMode (MODE_Screen); - break; //VT100 - case TY_CSI_PR ('l', 5): - _currentScreen->resetMode (MODE_Screen); - break; //VT100 - - case TY_CSI_PR ('h', 6): - _currentScreen->setMode (MODE_Origin); - break; //VT100 - case TY_CSI_PR ('l', 6): - _currentScreen->resetMode (MODE_Origin); - break; //VT100 - case TY_CSI_PR ('s', 6): - _currentScreen->saveMode (MODE_Origin); - break; //FIXME - case TY_CSI_PR ('r', 6): - _currentScreen->restoreMode (MODE_Origin); - break; //FIXME - - case TY_CSI_PR ('h', 7): - _currentScreen->setMode (MODE_Wrap); - break; //VT100 - case TY_CSI_PR ('l', 7): - _currentScreen->resetMode (MODE_Wrap); - break; //VT100 - case TY_CSI_PR ('s', 7): - _currentScreen->saveMode (MODE_Wrap); - break; //FIXME - case TY_CSI_PR ('r', 7): - _currentScreen->restoreMode (MODE_Wrap); - break; //FIXME - - case TY_CSI_PR ('h', 8): /* IGNORED: autorepeat on */ - break; //VT100 - case TY_CSI_PR ('l', 8): /* IGNORED: autorepeat off */ - break; //VT100 - case TY_CSI_PR ('s', 8): /* IGNORED: autorepeat on */ - break; //VT100 - case TY_CSI_PR ('r', 8): /* IGNORED: autorepeat off */ - break; //VT100 - - case TY_CSI_PR ('h', 9): /* IGNORED: interlace */ - break; //VT100 - case TY_CSI_PR ('l', 9): /* IGNORED: interlace */ - break; //VT100 - case TY_CSI_PR ('s', 9): /* IGNORED: interlace */ - break; //VT100 - case TY_CSI_PR ('r', 9): /* IGNORED: interlace */ - break; //VT100 - - case TY_CSI_PR ('h', 12): /* IGNORED: Cursor blink */ - break; //att610 - case TY_CSI_PR ('l', 12): /* IGNORED: Cursor blink */ - break; //att610 - case TY_CSI_PR ('s', 12): /* IGNORED: Cursor blink */ - break; //att610 - case TY_CSI_PR ('r', 12): /* IGNORED: Cursor blink */ - break; //att610 - - case TY_CSI_PR ('h', 25): - setMode (MODE_Cursor); - break; //VT100 - case TY_CSI_PR ('l', 25): - resetMode (MODE_Cursor); - break; //VT100 - case TY_CSI_PR ('s', 25): - saveMode (MODE_Cursor); - break; //VT100 - case TY_CSI_PR ('r', 25): - restoreMode (MODE_Cursor); - break; //VT100 - - case TY_CSI_PR ('h', 40): - setMode (MODE_Allow132Columns); - break; // XTERM - case TY_CSI_PR ('l', 40): - resetMode (MODE_Allow132Columns); - break; // XTERM - - case TY_CSI_PR ('h', 41): /* IGNORED: obsolete more(1) fix */ - break; //XTERM - case TY_CSI_PR ('l', 41): /* IGNORED: obsolete more(1) fix */ - break; //XTERM - case TY_CSI_PR ('s', 41): /* IGNORED: obsolete more(1) fix */ - break; //XTERM - case TY_CSI_PR ('r', 41): /* IGNORED: obsolete more(1) fix */ - break; //XTERM - - case TY_CSI_PR ('h', 47): - setMode (MODE_AppScreen); - break; //VT100 - case TY_CSI_PR ('l', 47): - resetMode (MODE_AppScreen); - break; //VT100 - case TY_CSI_PR ('s', 47): - saveMode (MODE_AppScreen); - break; //XTERM - case TY_CSI_PR ('r', 47): - restoreMode (MODE_AppScreen); - break; //XTERM - - case TY_CSI_PR ('h', 67): /* IGNORED: DECBKM */ - break; //XTERM - case TY_CSI_PR ('l', 67): /* IGNORED: DECBKM */ - break; //XTERM - case TY_CSI_PR ('s', 67): /* IGNORED: DECBKM */ - break; //XTERM - case TY_CSI_PR ('r', 67): /* IGNORED: DECBKM */ - break; //XTERM - - // XTerm defines the following modes: - // SET_VT200_MOUSE 1000 - // SET_VT200_HIGHLIGHT_MOUSE 1001 - // SET_BTN_EVENT_MOUSE 1002 - // SET_ANY_EVENT_MOUSE 1003 - // - - //Note about mouse modes: - //There are four mouse modes which xterm-compatible terminals can support - 1000,1001,1002,1003 - //Konsole currently supports mode 1000 (basic mouse press and release) and mode 1002 (dragging the mouse). - //TODO: Implementation of mouse modes 1001 (something called hilight tracking) and - //1003 (a slight variation on dragging the mouse) - // - - case TY_CSI_PR ('h', 1000): - setMode (MODE_Mouse1000); - break; //XTERM - case TY_CSI_PR ('l', 1000): - resetMode (MODE_Mouse1000); - break; //XTERM - case TY_CSI_PR ('s', 1000): - saveMode (MODE_Mouse1000); - break; //XTERM - case TY_CSI_PR ('r', 1000): - restoreMode (MODE_Mouse1000); - break; //XTERM - - case TY_CSI_PR ('h', 1001): /* IGNORED: hilite mouse tracking */ - break; //XTERM - case TY_CSI_PR ('l', 1001): - resetMode (MODE_Mouse1001); - break; //XTERM - case TY_CSI_PR ('s', 1001): /* IGNORED: hilite mouse tracking */ - break; //XTERM - case TY_CSI_PR ('r', 1001): /* IGNORED: hilite mouse tracking */ - break; //XTERM - - case TY_CSI_PR ('h', 1002): - setMode (MODE_Mouse1002); - break; //XTERM - case TY_CSI_PR ('l', 1002): - resetMode (MODE_Mouse1002); - break; //XTERM - case TY_CSI_PR ('s', 1002): - saveMode (MODE_Mouse1002); - break; //XTERM - case TY_CSI_PR ('r', 1002): - restoreMode (MODE_Mouse1002); - break; //XTERM - - case TY_CSI_PR ('h', 1003): - setMode (MODE_Mouse1003); - break; //XTERM - case TY_CSI_PR ('l', 1003): - resetMode (MODE_Mouse1003); - break; //XTERM - case TY_CSI_PR ('s', 1003): - saveMode (MODE_Mouse1003); - break; //XTERM - case TY_CSI_PR ('r', 1003): - restoreMode (MODE_Mouse1003); - break; //XTERM - - case TY_CSI_PR ('h', 1034): /* IGNORED: 8bitinput activation */ - break; //XTERM - - case TY_CSI_PR ('h', 1047): - setMode (MODE_AppScreen); - break; //XTERM - case TY_CSI_PR ('l', 1047): - _screen[1]->clearEntireScreen (); - resetMode (MODE_AppScreen); - break; //XTERM - case TY_CSI_PR ('s', 1047): - saveMode (MODE_AppScreen); - break; //XTERM - case TY_CSI_PR ('r', 1047): - restoreMode (MODE_AppScreen); - break; //XTERM - - //FIXME: Unitoken: save translations - case TY_CSI_PR ('h', 1048): - saveCursor (); - break; //XTERM - case TY_CSI_PR ('l', 1048): - restoreCursor (); - break; //XTERM - case TY_CSI_PR ('s', 1048): - saveCursor (); - break; //XTERM - case TY_CSI_PR ('r', 1048): - restoreCursor (); - break; //XTERM - - //FIXME: every once new sequences like this pop up in xterm. - // Here's a guess of what they could mean. - case TY_CSI_PR ('h', 1049): - saveCursor (); - _screen[1]->clearEntireScreen (); - setMode (MODE_AppScreen); - break; //XTERM - case TY_CSI_PR ('l', 1049): - resetMode (MODE_AppScreen); - restoreCursor (); - break; //XTERM - - //FIXME: weird DEC reset sequence - case TY_CSI_PE ('p'): /* IGNORED: reset ( ) */ - break; - - //FIXME: when changing between vt52 and ansi mode evtl do some resetting. - case TY_VT52 ('A'): - _currentScreen->cursorUp (1); - break; //VT52 - case TY_VT52 ('B'): - _currentScreen->cursorDown (1); - break; //VT52 - case TY_VT52 ('C'): - _currentScreen->cursorRight (1); - break; //VT52 - case TY_VT52 ('D'): - _currentScreen->cursorLeft (1); - break; //VT52 - - case TY_VT52 ('F'): - setAndUseCharset (0, '0'); - break; //VT52 - case TY_VT52 ('G'): - setAndUseCharset (0, 'B'); - break; //VT52 - - case TY_VT52 ('H'): - _currentScreen->setCursorYX (1, 1); - break; //VT52 - case TY_VT52 ('I'): - _currentScreen->reverseIndex (); - break; //VT52 - case TY_VT52 ('J'): - _currentScreen->clearToEndOfScreen (); - break; //VT52 - case TY_VT52 ('K'): - _currentScreen->clearToEndOfLine (); - break; //VT52 - case TY_VT52 ('Y'): - _currentScreen->setCursorYX (p - 31, q - 31); - break; //VT52 - case TY_VT52 ('Z'): - reportTerminalType (); - break; //VT52 - case TY_VT52 ('<'): - setMode (MODE_Ansi); - break; //VT52 - case TY_VT52 ('='): - setMode (MODE_AppKeyPad); - break; //VT52 - case TY_VT52 ('>'): - resetMode (MODE_AppKeyPad); - break; //VT52 - - case TY_CSI_PG ('c'): - reportSecondaryAttributes (); - break; //VT100 - - default: - reportDecodingError (); - break; - }; -} - -void -Vt102Emulation::clearScreenAndSetColumns (int columnCount) -{ - setImageSize (_currentScreen->getLines (), columnCount); - clearEntireScreen (); - setDefaultMargins (); - _currentScreen->setCursorYX (0, 0); -} - -void -Vt102Emulation::sendString (const char *s, int length) -{ - if (length >= 0) - emit sendData (s, length); - else - emit sendData (s, strlen (s)); -} - -void -Vt102Emulation::reportCursorPosition () -{ - char tmp[20]; - sprintf (tmp, "\033[%d;%dR", _currentScreen->getCursorY () + 1, - _currentScreen->getCursorX () + 1); - sendString (tmp); -} - -void -Vt102Emulation::reportTerminalType () -{ - // Primary device attribute response (Request was: ^[[0c or ^[[c (from TT321 Users Guide)) - // VT220: ^[[?63;1;2;3;6;7;8c (list deps on emul. capabilities) - // VT100: ^[[?1;2c - // VT101: ^[[?1;0c - // VT102: ^[[?6v - if (getMode (MODE_Ansi)) - sendString ("\033[?1;2c"); // I'm a VT100 - else - sendString ("\033/Z"); // I'm a VT52 -} - -void -Vt102Emulation::reportSecondaryAttributes () -{ - // Seconday device attribute response (Request was: ^[[>0c or ^[[>c) - if (getMode (MODE_Ansi)) - sendString ("\033[>0;115;0c"); // Why 115? ;) - else - sendString ("\033/Z"); // FIXME I don't think VT52 knows about it but kept for - // konsoles backward compatibility. -} - -void -Vt102Emulation::reportTerminalParms (int p) -// DECREPTPARM -{ - char tmp[100]; - sprintf (tmp, "\033[%d;1;1;112;112;1;0x", p); // not really true. - sendString (tmp); -} - -void -Vt102Emulation::reportStatus () -{ - sendString ("\033[0n"); //VT100. Device status report. 0 = Ready. -} - -void -Vt102Emulation::reportAnswerBack () -{ - // FIXME - Test this with VTTEST - // This is really obsolete VT100 stuff. - const char *ANSWER_BACK = ""; - sendString (ANSWER_BACK); -} - -/*! - `cx',`cy' are 1-based. - `eventType' indicates the button pressed (0-2) - or a general mouse release (3). - - eventType represents the kind of mouse action that occurred: - 0 = Mouse button press or release - 1 = Mouse drag -*/ - -void -Vt102Emulation::sendMouseEvent (int cb, int cx, int cy, int eventType) -{ - if (cx < 1 || cy < 1) - return; - - // normal buttons are passed as 0x20 + button, - // mouse wheel (buttons 4,5) as 0x5c + button - if (cb >= 4) - cb += 0x3c; - - //Mouse motion handling - if ((getMode (MODE_Mouse1002) || getMode (MODE_Mouse1003)) - && eventType == 1) - cb += 0x20; //add 32 to signify motion event - - char command[20]; - sprintf (command, "\033[M%c%c%c", cb + 0x20, cx + 0x20, cy + 0x20); - sendString (command); -} - -void -Vt102Emulation::sendText (const QString & text) -{ - if (!text.isEmpty ()) - { - QKeyEvent event (QEvent::KeyPress, - 0, (Qt::KeyboardModifiers) Qt::NoModifier, text); - - sendKeyEvent (&event); // expose as a big fat keypress event - } -} - -void -Vt102Emulation::sendKeyEvent (QKeyEvent * event) -{ - Qt::KeyboardModifiers modifiers = event->modifiers (); - KeyboardTranslator::States states = KeyboardTranslator::NoState; - - // get current states - if (getMode (MODE_NewLine)) - states |= KeyboardTranslator::NewLineState; - if (getMode (MODE_Ansi)) - states |= KeyboardTranslator::AnsiState; - if (getMode (MODE_AppCuKeys)) - states |= KeyboardTranslator::CursorKeysState; - if (getMode (MODE_AppScreen)) - states |= KeyboardTranslator::AlternateScreenState; - if (getMode (MODE_AppKeyPad) && (modifiers & Qt::KeypadModifier)) - states |= KeyboardTranslator::ApplicationKeypadState; - - // check flow control state - if (modifiers & Qt::ControlModifier) - { - if (event->key () == Qt::Key_S) - emit flowControlKeyPressed (true); - else - if (event->key () == Qt::Key_Q) - emit flowControlKeyPressed (false); - } - - // lookup key binding - if (_keyTranslator) - { - KeyboardTranslator::Entry entry = - _keyTranslator->findEntry (event->key (), modifiers, states); - - // send result to terminal - QByteArray textToSend; - - // special handling for the Alt (aka. Meta) modifier. pressing - // Alt+[Character] results in Esc+[Character] being sent - // (unless there is an entry defined for this particular combination - // in the keyboard modifier) - bool wantsAltModifier = - entry.modifiers () & entry.modifierMask () & Qt::AltModifier; - bool wantsAnyModifier = - entry.state () & entry. - stateMask () & KeyboardTranslator::AnyModifierState; - - if (modifiers & Qt::AltModifier - && !(wantsAltModifier || wantsAnyModifier) - && !event->text ().isEmpty ()) - { - textToSend.prepend ("\033"); - } - - if (entry.command () != KeyboardTranslator::NoCommand) - { - if (entry.command () & KeyboardTranslator::EraseCommand) - textToSend += eraseChar (); - - // TODO command handling - } - else if (!entry.text ().isEmpty ()) - { - textToSend += _codec->fromUnicode (entry.text (true, modifiers)); - } - else - textToSend += _codec->fromUnicode (event->text ()); - - sendData (textToSend.constData (), textToSend.length ()); - } - else - { - // print an error message to the terminal if no key translator has been - // set - QString translatorError = QString ("No keyboard translator available. " - "The information needed to convert key presses " - "into characters to send to the terminal " - "is missing."); - reset (); - receiveData (translatorError.toAscii ().constData (), - translatorError.count ()); - } -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* VT100 Charsets */ -/* */ -/* ------------------------------------------------------------------------- */ - -// Character Set Conversion ------------------------------------------------ -- - -/* - The processing contains a VT100 specific code translation layer. - It's still in use and mainly responsible for the line drawing graphics. - - These and some other glyphs are assigned to codes (0x5f-0xfe) - normally occupied by the latin letters. Since this codes also - appear within control sequences, the extra code conversion - does not permute with the tokenizer and is placed behind it - in the pipeline. It only applies to tokens, which represent - plain characters. - - This conversion it eventually continued in TerminalDisplay.C, since - it might involve VT100 enhanced fonts, which have these - particular glyphs allocated in (0x00-0x1f) in their code page. -*/ - -#define CHARSET _charset[_currentScreen==_screen[1]] - -// Apply current character map. - -unsigned short -Vt102Emulation::applyCharset (unsigned short c) -{ - if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) - return vt100_graphics[c - 0x5f]; - if (CHARSET.pound && c == '#') - return 0xa3; //This mode is obsolete - return c; -} - -/* - "Charset" related part of the emulation state. - This configures the VT100 charset filter. - - While most operation work on the current _screen, - the following two are different. -*/ - -void -Vt102Emulation::resetCharset (int scrno) -{ - _charset[scrno].cu_cs = 0; - strncpy (_charset[scrno].charset, "BBBB", 4); - _charset[scrno].sa_graphic = false; - _charset[scrno].sa_pound = false; - _charset[scrno].graphic = false; - _charset[scrno].pound = false; -} - -void -Vt102Emulation::setCharset (int n, int cs) // on both screens. -{ - _charset[0].charset[n & 3] = cs; - useCharset (_charset[0].cu_cs); - _charset[1].charset[n & 3] = cs; - useCharset (_charset[1].cu_cs); -} - -void -Vt102Emulation::setAndUseCharset (int n, int cs) -{ - CHARSET.charset[n & 3] = cs; - useCharset (n & 3); -} - -void -Vt102Emulation::useCharset (int n) -{ - CHARSET.cu_cs = n & 3; - CHARSET.graphic = (CHARSET.charset[n & 3] == '0'); - CHARSET.pound = (CHARSET.charset[n & 3] == 'A'); //This mode is obsolete -} - -void -Vt102Emulation::setDefaultMargins () -{ - _screen[0]->setDefaultMargins (); - _screen[1]->setDefaultMargins (); -} - -void -Vt102Emulation::setMargins (int t, int b) -{ - _screen[0]->setMargins (t, b); - _screen[1]->setMargins (t, b); -} - -void -Vt102Emulation::saveCursor () -{ - CHARSET.sa_graphic = CHARSET.graphic; - CHARSET.sa_pound = CHARSET.pound; //This mode is obsolete - // we are not clear about these - //sa_charset = charsets[cScreen->_charset]; - //sa_charset_num = cScreen->_charset; - _currentScreen->saveCursor (); -} - -void -Vt102Emulation::restoreCursor () -{ - CHARSET.graphic = CHARSET.sa_graphic; - CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete - _currentScreen->restoreCursor (); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Mode Operations */ -/* */ -/* ------------------------------------------------------------------------- */ - -/* - Some of the emulations state is either added to the state of the screens. - - This causes some scoping problems, since different emulations choose to - located the mode either to the current _screen or to both. - - For strange reasons, the extend of the rendition attributes ranges over - all screens and not over the actual _screen. - - We decided on the precise precise extend, somehow. -*/ - -// "Mode" related part of the state. These are all booleans. - -void -Vt102Emulation::resetModes () -{ - // MODE_Allow132Columns is not reset here - // to match Xterm's behaviour (see Xterm's VTReset() function) - - resetMode (MODE_132Columns); - saveMode (MODE_132Columns); - resetMode (MODE_Mouse1000); - saveMode (MODE_Mouse1000); - resetMode (MODE_Mouse1001); - saveMode (MODE_Mouse1001); - resetMode (MODE_Mouse1002); - saveMode (MODE_Mouse1002); - resetMode (MODE_Mouse1003); - saveMode (MODE_Mouse1003); - - resetMode (MODE_AppScreen); - saveMode (MODE_AppScreen); - resetMode (MODE_AppCuKeys); - saveMode (MODE_AppCuKeys); - resetMode (MODE_AppKeyPad); - saveMode (MODE_AppKeyPad); - resetMode (MODE_NewLine); - setMode (MODE_Ansi); -} - -void -Vt102Emulation::setMode (int m) -{ - _currentModes.mode[m] = true; - switch (m) - { - case MODE_132Columns: - if (getMode (MODE_Allow132Columns)) - clearScreenAndSetColumns (132); - else - _currentModes.mode[m] = false; - break; - case MODE_Mouse1000: - case MODE_Mouse1001: - case MODE_Mouse1002: - case MODE_Mouse1003: - emit programUsesMouseChanged (false); - break; - - case MODE_AppScreen: - _screen[1]->clearSelection (); - setScreen (1); - break; - } - if (m < MODES_SCREEN || m == MODE_NewLine) - { - _screen[0]->setMode (m); - _screen[1]->setMode (m); - } -} - -void -Vt102Emulation::resetMode (int m) -{ - _currentModes.mode[m] = false; - switch (m) - { - case MODE_132Columns: - if (getMode (MODE_Allow132Columns)) - clearScreenAndSetColumns (80); - break; - case MODE_Mouse1000: - case MODE_Mouse1001: - case MODE_Mouse1002: - case MODE_Mouse1003: - emit programUsesMouseChanged (true); - break; - - case MODE_AppScreen: - _screen[0]->clearSelection (); - setScreen (0); - break; - } - if (m < MODES_SCREEN || m == MODE_NewLine) - { - _screen[0]->resetMode (m); - _screen[1]->resetMode (m); - } -} - -void -Vt102Emulation::saveMode (int m) -{ - _savedModes.mode[m] = _currentModes.mode[m]; -} - -void -Vt102Emulation::restoreMode (int m) -{ - if (_savedModes.mode[m]) - setMode (m); - else - resetMode (m); -} - -bool -Vt102Emulation::getMode (int m) -{ - return _currentModes.mode[m]; -} - -char -Vt102Emulation::eraseChar () const -{ - KeyboardTranslator::Entry entry = - _keyTranslator->findEntry (Qt::Key_Backspace, 0, 0); - if (entry.text ().count () > 0) - return entry.text ()[0]; - else - return '\b'; -} - -// print contents of the scan buffer -static void -hexdump (int *s, int len) -{ - int i; - for (i = 0; i < len; i++) - { - if (s[i] == '\\') - printf ("\\\\"); - else if ((s[i]) > 32 && s[i] < 127) - printf ("%c", s[i]); - else - printf ("\\%04x(hex)", s[i]); - } -} - -void -Vt102Emulation::reportDecodingError () -{ - if (tokenBufferPos == 0 - || (tokenBufferPos == 1 && (tokenBuffer[0] & 0xff) >= 32)) - return; - printf ("Undecodable sequence: "); - hexdump (tokenBuffer, tokenBufferPos); - printf ("\n"); -} diff -r 8f7adc0d59c1 -r cc90c62ada21 gui/src/terminal/Vt102Emulation.h --- a/gui/src/terminal/Vt102Emulation.h Thu Aug 18 15:07:43 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,187 +0,0 @@ -/* - This file is part of Konsole, an X terminal. - - Copyright 2007-2008 by Robert Knight - Copyright 1997,1998 by Lars Doelle - - 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 VT102EMULATION_H -#define VT102EMULATION_H - -// Standard Library -#include - -// Qt -#include -#include -#include - -// Konsole -#include "Emulation.h" -#include "Screen.h" - -#define MODE_AppScreen (MODES_SCREEN+0) // Mode #1 -#define MODE_AppCuKeys (MODES_SCREEN+1) // Application cursor keys (DECCKM) -#define MODE_AppKeyPad (MODES_SCREEN+2) // -#define MODE_Mouse1000 (MODES_SCREEN+3) // Send mouse X,Y position on press and release -#define MODE_Mouse1001 (MODES_SCREEN+4) // Use Hilight mouse tracking -#define MODE_Mouse1002 (MODES_SCREEN+5) // Use cell motion mouse tracking -#define MODE_Mouse1003 (MODES_SCREEN+6) // Use all motion mouse tracking -#define MODE_Ansi (MODES_SCREEN+7) // Use US Ascii for character sets G0-G3 (DECANM) -#define MODE_132Columns (MODES_SCREEN+8) // 80 <-> 132 column mode switch (DECCOLM) -#define MODE_Allow132Columns (MODES_SCREEN+9) // Allow DECCOLM mode -#define MODE_total (MODES_SCREEN+10) - -struct CharCodes -{ - // coding info - char charset[4]; // - int cu_cs; // actual charset. - bool graphic; // Some VT100 tricks - bool pound; // Some VT100 tricks - bool sa_graphic; // saved graphic - bool sa_pound; // saved pound -}; - -/** - * Provides an xterm compatible terminal emulation based on the DEC VT102 terminal. - * A full description of this terminal can be found at - * - * In addition, various additional xterm escape sequences are supported to provide - * features such as mouse input handling. - * See http://rtfm.etla.org/xterm/ctlseq.html for a description of xterm's escape - * sequences. - * - */ -class Vt102Emulation:public Emulation -{ -Q_OBJECT public: - /** Constructs a new emulation */ - Vt102Emulation (); - ~Vt102Emulation (); - - // reimplemented from Emulation - virtual void clearEntireScreen (); - virtual void reset (); - virtual char eraseChar () const; - - public slots: - // reimplemented from Emulation - virtual void sendString (const char *, int length = -1); - virtual void sendText (const QString & text); - virtual void sendKeyEvent (QKeyEvent *); - virtual void sendMouseEvent (int buttons, int column, int line, - int eventType); - -protected: - // reimplemented from Emulation - virtual void setMode (int mode); - virtual void resetMode (int mode); - virtual void receiveChar (int cc); - - private slots: - //causes changeTitle() to be emitted for each (int,QString) pair in pendingTitleUpdates - //used to buffer multiple title updates - void updateTitle (); - -private: - unsigned short applyCharset (unsigned short c); - void setCharset (int n, int cs); - void useCharset (int n); - void setAndUseCharset (int n, int cs); - void saveCursor (); - void restoreCursor (); - void resetCharset (int scrno); - - void setMargins (int top, int bottom); - //set margins for all screens back to their defaults - void setDefaultMargins (); - - // returns true if 'mode' is set or false otherwise - bool getMode (int mode); - // saves the current boolean value of 'mode' - void saveMode (int mode); - // restores the boolean value of 'mode' - void restoreMode (int mode); - // resets all modes - // (except MODE_Allow132Columns) - void resetModes (); - - void resetTokenizer (); -#define MAX_TOKEN_LENGTH 80 - void addToCurrentToken (int cc); - int tokenBuffer[MAX_TOKEN_LENGTH]; //FIXME: overflow? - int tokenBufferPos; -#define MAXARGS 15 - void addDigit (int dig); - void addArgument (); - int argv[MAXARGS]; - int argc; - void initTokenizer (); - - // Set of flags for each of the ASCII characters which indicates - // what category they fall into (printable character, control, digit etc.) - // for the purposes of decoding terminal output - int charClass[256]; - - void reportDecodingError (); - - void processToken (int code, int p, int q); - void processWindowAttributeChange (); - - void reportTerminalType (); - void reportSecondaryAttributes (); - void reportStatus (); - void reportAnswerBack (); - void reportCursorPosition (); - void reportTerminalParms (int p); - - void onScrollLock (); - void scrollLock (const bool lock); - - // clears the screen and resizes it to the specified - // number of columns - void clearScreenAndSetColumns (int columnCount); - - CharCodes _charset[2]; - - class TerminalState - { - public: - // Initializes all modes to false - TerminalState () - { - memset (&mode, false, MODE_total * sizeof (bool)); - } - - bool mode[MODE_total]; - }; - - TerminalState _currentModes; - TerminalState _savedModes; - - //hash table and timer for buffering calls to the session instance - //to update the name of the session - //or window title. - //these calls occur when certain escape sequences are seen in the - //output from the terminal - QHash < int, QString > _pendingTitleUpdates; - QTimer *_titleUpdateTimer; -}; - -#endif // VT102EMULATION_H