Commit e7f1b790 authored by Robert Knight's avatar Robert Knight
Browse files

Allow the scrolling optimisation to work on regions of the display instead of...

Allow the scrolling optimisation to work on regions of the display instead of the whole screen.  This makes it work with split/screen vi/Screen etc.  Doesn't work with applications that use vertical splits.

svn path=/trunk/KDE/kdebase/apps/konsole/; revision=668839
parent 39cce65b
......@@ -857,11 +857,17 @@ void Screen::scrollUp(int n)
\sa setRegion \sa scrollDown
*/
QRect Screen::lastScrolledRegion() const
{
return _lastScrolledRegion;
}
void Screen::scrollUp(int from, int n)
{
if (n <= 0 || from + n > bmargin) return;
_scrolledLines -= n;
_lastScrolledRegion = QRect(0,tmargin,columns-1,(bmargin-tmargin));
//qDebug() << "Screen::scrollUp( from: " << from << " , n: " << n << ")";
......@@ -1402,7 +1408,8 @@ void Screen::copyLineToStream(int line , int start, int count,
QTextStream* stream, TerminalCharacterDecoder* decoder)
{
//buffer to hold characters for decoding
//the buffer is static to avoid initialising every element on each call to copyLineToStream
//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];
......
......@@ -24,6 +24,7 @@
#define SCREEN_H
// Qt
#include <QtCore/QRect>
#include <QtCore/QTextStream>
#include <QtCore/QVarLengthArray>
......@@ -330,6 +331,15 @@ public: // these are all `Screen' operations
* 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()
......@@ -388,6 +398,7 @@ private: // helper
ImageLine* screenLines; // [lines]
int _scrolledLines;
QRect _lastScrolledRegion;
QVarLengthArray<LineProperty,64> lineProperties;
......
......@@ -196,6 +196,11 @@ void ScreenWindow::resetScrollCount()
_scrollCount = 0;
}
QRect ScreenWindow::scrollRegion() const
{
return _screen->lastScrolledRegion();
}
void ScreenWindow::notifyOutputChanged()
{
// move window to the bottom of the screen and update scroll count
......
......@@ -23,6 +23,7 @@
// Qt
#include <QtCore/QObject>
#include <QtCore/QPoint>
#include <QtCore/QRect>
// Konsole
#include "TECommon.h"
......@@ -87,9 +88,15 @@ public:
QVector<LineProperty> getLineProperties();
/**
* Returns the number of lines which the window has been scrolled by since the last
* call to resetScrollCount().
* This allows views to optimise scrolling operations.
* 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;
......@@ -98,6 +105,15 @@ public:
*/
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.
......
......@@ -429,7 +429,7 @@ void SessionController::setupActions()
action->setShortcut( QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_Minus) );
connect( action , SIGNAL(triggered()) , this , SLOT(decreaseTextSize()) );
// History
// Scrollback
_searchToggleAction = new KAction(i18n("Search Output..."),this);
_searchToggleAction->setShortcut( QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_F) );
_searchToggleAction->setIcon( KIcon("edit-find") );
......@@ -469,6 +469,11 @@ void SessionController::setupActions()
action->setShortcut( QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_X) );
connect( action , SIGNAL(triggered()) , this , SLOT(clearHistoryAndReset()) );
// Menu
action = collection->addAction("show-menubar");
action->setText( i18n("Show Menubar") );
connect( action , SIGNAL(toggled(bool)) , this , SIGNAL(showMenuBarToggle(bool)) );
// Profile Options
action = collection->addAction("edit-current-profile");
action->setText( i18n("Edit Current Profile...") );
......
/*
This file is part of Konsole, an X terminal.
Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
This program is free software; you can redistribute it and/or modify
......@@ -44,18 +46,21 @@ typedef unsigned short UINT16;
/*!
*/
struct ColorEntry
class ColorEntry
{
public:
ColorEntry(QColor c, bool tr, bool b) : color(c), transparent(tr), bold(b) {}
ColorEntry() : transparent(false), bold(false) {} // default constructors
void operator=(const ColorEntry& rhs) {
void operator=(const ColorEntry& rhs)
{
color = rhs.color;
transparent = rhs.transparent;
bold = rhs.bold;
}
QColor color;
bool transparent; // if used on bg
bool bold; // if used on fg
bool transparent; // applies if color is used in background
bool bold; // applies if color is used in foreground
};
......@@ -184,53 +189,67 @@ static const int LINE_DOUBLEHEIGHT = (1 << 2);
class CharacterColor
{
friend class Character;
public:
CharacterColor() : t(0), u(0), v(0), w(0) {}
CharacterColor(UINT8 ty, int co) : t(ty), u(0), v(0), w(0)
CharacterColor()
: _colorSpace(COLOR_SPACE_UNDEFINED),
_u(0),
_v(0),
_w(0)
{}
CharacterColor(UINT8 colorSpace, int co)
: _colorSpace(colorSpace),
_u(0),
_v(0),
_w(0)
{
if (COLOR_SPACE_DEFAULT == t) {
u = co & 1;
} else if (COLOR_SPACE_SYSTEM == t) {
u = co & 7;
v = (co >> 3) & 1;
} else if (COLOR_SPACE_256 == t) {
u = co & 255;
} else if (COLOR_SPACE_RGB == t) {
u = co >> 16;
v = co >> 8;
w = co;
}
#if 0
// Doesn't work with gcc 3.3.4
switch (t)
switch (colorSpace)
{
case COLOR_SPACE_UNDEFINED: break;
case COLOR_SPACE_DEFAULT: u = co& 1; break;
case COLOR_SPACE_SYSTEM: u = co& 7; v = (co>>3)&1; break;
case COLOR_SPACE_256: u = co&255; break;
case COLOR_SPACE_RGB: u = co>>16; v = co>>8; w = co; break;
default : t = 0; break;
case COLOR_SPACE_DEFAULT:
_u = co & 1;
break;
case COLOR_SPACE_SYSTEM:
_u = co & 7;
_v = (co >> 3) & 1;
break;
case COLOR_SPACE_256:
_u = co & 255;
break;
case COLOR_SPACE_RGB:
_u = co >> 16;
_v = co >> 8;
_w = co;
break;
}
#endif
}
UINT8 t; // color space indicator
UINT8 u; // various bytes representing the data in the respective ...
UINT8 v; // ... color space. C++ does not do unions, so we cannot ...
UINT8 w; // ... express ourselfs here, properly.
void toggleIntensive(); // Hack or helper?
QColor color(const ColorEntry* base) const;
friend bool operator == (const CharacterColor& a, const CharacterColor& b);
friend bool operator != (const CharacterColor& a, const CharacterColor& b);
private:
UINT8 _colorSpace;
// bytes storing the character color
UINT8 _u;
UINT8 _v;
UINT8 _w;
};
inline bool operator == (const CharacterColor& a, const CharacterColor& b)
{
return *reinterpret_cast<const quint32*>(&a.t) == *reinterpret_cast<const quint32*>(&b.t);
return *reinterpret_cast<const quint32*>(&a._colorSpace) ==
*reinterpret_cast<const quint32*>(&b._colorSpace);
}
inline bool operator != (const CharacterColor& a, const CharacterColor& b)
{
return *reinterpret_cast<const quint32*>(&a.t) != *reinterpret_cast<const quint32*>(&b.t);
return *reinterpret_cast<const quint32*>(&a._colorSpace) !=
*reinterpret_cast<const quint32*>(&b._colorSpace);
}
inline const QColor color256(UINT8 u, const ColorEntry* base)
......@@ -250,21 +269,24 @@ inline const QColor color256(UINT8 u, const ColorEntry* base)
inline QColor CharacterColor::color(const ColorEntry* base) const
{
switch (t)
switch (_colorSpace)
{
case COLOR_SPACE_DEFAULT: return base[u+0+(v?BASE_COLORS:0)].color;
case COLOR_SPACE_SYSTEM: return base[u+2+(v?BASE_COLORS:0)].color;
case COLOR_SPACE_256: return color256(u,base);
case COLOR_SPACE_RGB: return QColor(u,v,w);
default : return QColor(255,0,0); // diagnostic catch all
case COLOR_SPACE_DEFAULT: return base[_u+0+(_v?BASE_COLORS:0)].color;
case COLOR_SPACE_SYSTEM: return base[_u+2+(_v?BASE_COLORS:0)].color;
case COLOR_SPACE_256: return color256(_u,base);
case COLOR_SPACE_RGB: return QColor(_u,_v,_w);
}
Q_ASSERT(false); // invalid color space;
return QColor();
}
inline void CharacterColor::toggleIntensive()
{
if (t == COLOR_SPACE_SYSTEM || t == COLOR_SPACE_DEFAULT)
if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT)
{
v = !v;
_v = !_v;
}
}
......@@ -320,18 +342,18 @@ inline bool operator != (const Character& a, const Character& b)
inline bool Character::isTransparent(const ColorEntry* base) const
{
return ((backgroundColor.t == COLOR_SPACE_DEFAULT) &&
base[backgroundColor.u+0+(backgroundColor.v?BASE_COLORS:0)].transparent)
|| ((backgroundColor.t == COLOR_SPACE_SYSTEM) &&
base[backgroundColor.u+2+(backgroundColor.v?BASE_COLORS:0)].transparent);
return ((backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) &&
base[backgroundColor._u+0+(backgroundColor._v?BASE_COLORS:0)].transparent)
|| ((backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) &&
base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].transparent);
}
inline bool Character::isBold(const ColorEntry* base) const
{
return (backgroundColor.t == COLOR_SPACE_DEFAULT) &&
base[backgroundColor.u+0+(backgroundColor.v?BASE_COLORS:0)].bold
|| (backgroundColor.t == COLOR_SPACE_SYSTEM) &&
base[backgroundColor.u+2+(backgroundColor.v?BASE_COLORS:0)].bold;
return (backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) &&
base[backgroundColor._u+0+(backgroundColor._v?BASE_COLORS:0)].bold
|| (backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) &&
base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].bold;
}
extern unsigned short vt100_graphics[32];
......
......@@ -693,64 +693,73 @@ void TerminalDisplay::setCursorPos(const int curx, const int cury)
_cursorCol = curx;
}
// scrolls the _image by '_lines', down if _lines > 0 or up otherwise.
// 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()
// 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
// display is much cheaper than re-rendering all the text for the
// part of the image which has moved up or down.
// Instead only new lines have to be drawn
//
// note: it is important that the area of the display which is scrolled aligns properly with
// the character grid - which has a top left point at (_bX,_bY) ,
// note: it is important that the area of the display which is
// scrolled aligns properly with the character grid -
// which has a top left point at (_bX,_bY) ,
// a cell width of _fontWidth and a cell height of _fontHeight).
void TerminalDisplay::scrollImage(int _lines)
void TerminalDisplay::scrollImage(int lines , const QRect& region)
{
if ( _lines == 0 || _image == 0 || abs(_lines) >= this->_usedLines ) return;
if ( lines == 0 || _image == 0 || abs(lines) >= region.height() ) return;
QRect scrollRect;
//qDebug() << "Scrolled region: top =" << region.top()
// << ", bottom =" << region.bottom()
// << ", height =" << region.height() << "lines. Image height ="
// << this->_usedLines << "lines"
// << ", scroll =" << lines << "lines";
void* firstCharPos = &_image[ region.top() * this->_usedColumns ];
void* lastCharPos = &_image[ (region.top() + abs(lines)) * this->_usedColumns ];
int top = _bY + (region.top() * _fontHeight);
int linesToMove = region.height() - abs(lines);
int bytesToMove = linesToMove *
this->_usedColumns *
sizeof(Character);
Q_ASSERT( linesToMove > 0 );
Q_ASSERT( bytesToMove > 0 );
//scroll internal _image
if ( _lines > 0 )
if ( lines > 0 )
{
assert( (_lines*this->_usedColumns) < _imageSize );
assert( (lines*this->_usedColumns) < _imageSize );
//scroll internal _image down
memmove( _image , &_image[_lines*this->_usedColumns] ,
( this->_usedLines - _lines ) *
this->_usedColumns *
sizeof(Character) );
memmove( firstCharPos , lastCharPos , bytesToMove );
//set region of display to scroll, making sure that
//the region aligns correctly to the character grid
scrollRect = QRect( _bX ,_bY,
scrollRect = QRect( _bX , top,
this->_usedColumns * _fontWidth ,
(this->_usedLines - _lines) * _fontHeight );
//qDebug() << "scrolled down " << _lines << " _lines";
linesToMove * _fontHeight );
}
else
{
//scroll internal _image up
memmove( &_image[ abs(_lines)*this->_usedColumns] , _image ,
(this->_usedLines - abs(_lines) ) *
this->_usedColumns *
sizeof(Character) );
memmove( lastCharPos , firstCharPos , bytesToMove );
//set region of the display to scroll, making sure that
//the region aligns correctly to the character grid
QPoint topPoint( _bX , _bY + abs(_lines)*_fontHeight );
QPoint topPoint( _bX , top + abs(lines)*_fontHeight );
scrollRect = QRect( topPoint ,
scrollRect = QRect( topPoint ,
QSize( this->_usedColumns*_fontWidth ,
(this->_usedLines - abs(_lines)) * _fontHeight ));
//qDebug() << "scrolled up " << _lines << " _lines";
linesToMove * _fontHeight ));
}
//scroll the display vertically to match internal _image
scroll( 0 , _fontHeight * (-_lines) , scrollRect );
scroll( 0 , _fontHeight * (-lines) , scrollRect );
}
void TerminalDisplay::processFilters()
......@@ -772,10 +781,11 @@ void TerminalDisplay::updateImage()
if ( !_screenWindow )
return;
// optimization - scroll the existing _image where possible and
// avoid expensive text drawing for parts of the _image that
// 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() );
scrollImage( _screenWindow->scrollCount() ,
_screenWindow->scrollRegion() );
_screenWindow->resetScrollCount();
Character* const newimg = _screenWindow->getImage();
......@@ -954,7 +964,7 @@ void TerminalDisplay::updateImage()
// free the image from the screen window
delete[] newimg;
// debugging - display a count of the number of _lines that will need
// debugging - display a count of the number of lines that will need
// to be repainted
//qDebug() << "dirty line count = " << dirtyLineCount;
......
......@@ -565,9 +565,13 @@ private:
// shows the popup menu associated with a hotspot
void showHotSpotMenu(Filter::HotSpot* spot , const QPoint& position);
// scrolls the image by a number of lines. 'lines' may be positive ( to scroll the image down )
// scrolls the image by a number of lines.
// 'lines' may be positive ( to scroll the image down )
// or negative ( to scroll the image up )
void scrollImage(int lines);
// '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();
......
......@@ -29,27 +29,6 @@ ViewProperties::ViewProperties(QObject* parent)
{
}
#if 0
void ViewProperties::setFlag(ViewFlag flag , bool set)
{
if ( set && !(_flags & flag) )
{
_flags |= flag;
emit flagsChanged(this);
}
else if ( !set && (_flags & flag) )
{
_flags &= ~flag;
emit flagsChanged(this);
}
}
ViewProperties::ViewFlag ViewProperties::flags() const
{
return (ViewFlag)_flags;
}
#endif
KUrl ViewProperties::url() const
{
return KUrl();
......
......@@ -65,46 +65,11 @@ public:
*/
int identifier() const;
#if 0
/**
* This enum describes the flags which provide information
* about the current state of the view.
*/
enum ViewFlag
{
/**
* Specifies that activity (often this means additional output)
* has occurred in the view.
*/
ActivityFlag = 1
};
/** Returns view's current flags. */
ViewFlag flags() const;
/**
* Sets or clears the specified view flag.
*
* @param flag The flag to set or clear.
* @param set True to set the flag or false to clear it.
*/
void setFlag(ViewFlag flag , bool set = true);
/**
* Convenience method. Unsets the specified flag.
* Equivalent to calling setFlag(@p flag,false);
*/
void clearFlag(ViewFlag flag) { setFlag(flag,false); }
#endif
signals:
/** Emitted when the icon for a view changes */
void iconChanged(ViewProperties* properties);
/** Emitted when the title for a view changes */
void titleChanged(ViewProperties* properties);
///** Emitted when the flags associated with a view change. */
//void flagsChanged(ViewProperties* properties);
/** Emitted when activity has occurred in this view. */
void activity(ViewProperties* item);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment