File indexing completed on 2025-01-19 04:23:30
0001 /* 0002 Copyright (C) 2007 by Robert Knight <robertknight@gmail.com> 0003 0004 This program is free software; you can redistribute it and/or modify 0005 it under the terms of the GNU General Public License as published by 0006 the Free Software Foundation; either version 2 of the License, or 0007 (at your option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 GNU General Public License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program; if not, write to the Free Software 0016 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0017 02110-1301 USA. 0018 */ 0019 0020 // Own 0021 #include "ScreenWindow.h" 0022 0023 // Qt 0024 #include <QtDebug> 0025 0026 // Konsole 0027 #include "Screen.h" 0028 0029 using namespace Konsole; 0030 0031 ScreenWindow::ScreenWindow(QObject* parent) 0032 : QObject(parent) 0033 , _windowBuffer(0) 0034 , _windowBufferSize(0) 0035 , _bufferNeedsUpdate(true) 0036 , _windowLines(1) 0037 , _currentLine(0) 0038 , _trackOutput(true) 0039 , _scrollCount(0) 0040 { 0041 } 0042 ScreenWindow::~ScreenWindow() 0043 { 0044 delete[] _windowBuffer; 0045 } 0046 void ScreenWindow::setScreen(Screen* screen) 0047 { 0048 Q_ASSERT( screen ); 0049 0050 _screen = screen; 0051 } 0052 0053 Screen* ScreenWindow::screen() const 0054 { 0055 return _screen; 0056 } 0057 0058 Character* ScreenWindow::getImage() 0059 { 0060 // reallocate internal buffer if the window size has changed 0061 int size = windowLines() * windowColumns(); 0062 if (_windowBuffer == 0 || _windowBufferSize != size) 0063 { 0064 delete[] _windowBuffer; 0065 _windowBufferSize = size; 0066 _windowBuffer = new Character[size]; 0067 _bufferNeedsUpdate = true; 0068 } 0069 0070 if (!_bufferNeedsUpdate) 0071 return _windowBuffer; 0072 0073 _screen->getImage(_windowBuffer,size, 0074 currentLine(),endWindowLine()); 0075 0076 // this window may look beyond the end of the screen, in which 0077 // case there will be an unused area which needs to be filled 0078 // with blank characters 0079 fillUnusedArea(); 0080 0081 _bufferNeedsUpdate = false; 0082 return _windowBuffer; 0083 } 0084 0085 void ScreenWindow::fillUnusedArea() 0086 { 0087 int screenEndLine = _screen->getHistLines() + _screen->getLines() - 1; 0088 int windowEndLine = currentLine() + windowLines() - 1; 0089 0090 int unusedLines = windowEndLine - screenEndLine; 0091 int charsToFill = unusedLines * windowColumns(); 0092 0093 Screen::fillWithDefaultChar(_windowBuffer + _windowBufferSize - charsToFill,charsToFill); 0094 } 0095 0096 // return the index of the line at the end of this window, or if this window 0097 // goes beyond the end of the screen, the index of the line at the end 0098 // of the screen. 0099 // 0100 // when passing a line number to a Screen method, the line number should 0101 // never be more than endWindowLine() 0102 // 0103 int ScreenWindow::endWindowLine() const 0104 { 0105 return qMin(currentLine() + windowLines() - 1, 0106 lineCount() - 1); 0107 } 0108 QVector<LineProperty> ScreenWindow::getLineProperties() 0109 { 0110 QVector<LineProperty> result = _screen->getLineProperties(currentLine(),endWindowLine()); 0111 0112 if (result.count() != windowLines()) 0113 result.resize(windowLines()); 0114 0115 return result; 0116 } 0117 0118 QString ScreenWindow::selectedText( bool preserveLineBreaks ) const 0119 { 0120 return _screen->selectedText( preserveLineBreaks ); 0121 } 0122 0123 void ScreenWindow::getSelectionStart( int& column , int& line ) 0124 { 0125 _screen->getSelectionStart(column,line); 0126 line -= currentLine(); 0127 } 0128 void ScreenWindow::getSelectionEnd( int& column , int& line ) 0129 { 0130 _screen->getSelectionEnd(column,line); 0131 line -= currentLine(); 0132 } 0133 void ScreenWindow::setSelectionStart( int column , int line , bool columnMode ) 0134 { 0135 _screen->setSelectionStart( column , qMin(line + currentLine(),endWindowLine()) , columnMode); 0136 0137 _bufferNeedsUpdate = true; 0138 Q_EMIT selectionChanged(); 0139 } 0140 0141 void ScreenWindow::setSelectionEnd( int column , int line ) 0142 { 0143 _screen->setSelectionEnd( column , qMin(line + currentLine(),endWindowLine()) ); 0144 0145 _bufferNeedsUpdate = true; 0146 Q_EMIT selectionChanged(); 0147 } 0148 0149 bool ScreenWindow::isSelected( int column , int line ) 0150 { 0151 return _screen->isSelected( column , qMin(line + currentLine(),endWindowLine()) ); 0152 } 0153 0154 void ScreenWindow::clearSelection() 0155 { 0156 _screen->clearSelection(); 0157 0158 Q_EMIT selectionChanged(); 0159 } 0160 0161 void ScreenWindow::setWindowLines(int lines) 0162 { 0163 Q_ASSERT(lines > 0); 0164 _windowLines = lines; 0165 } 0166 int ScreenWindow::windowLines() const 0167 { 0168 return _windowLines; 0169 } 0170 0171 int ScreenWindow::windowColumns() const 0172 { 0173 return _screen->getColumns(); 0174 } 0175 0176 int ScreenWindow::lineCount() const 0177 { 0178 return _screen->getHistLines() + _screen->getLines(); 0179 } 0180 0181 int ScreenWindow::columnCount() const 0182 { 0183 return _screen->getColumns(); 0184 } 0185 0186 QPoint ScreenWindow::cursorPosition() const 0187 { 0188 QPoint position; 0189 0190 position.setX( _screen->getCursorX() ); 0191 position.setY( _screen->getCursorY() ); 0192 0193 return position; 0194 } 0195 0196 int ScreenWindow::currentLine() const 0197 { 0198 return qBound(0,_currentLine,lineCount()-windowLines()); 0199 } 0200 0201 void ScreenWindow::scrollBy( RelativeScrollMode mode , int amount ) 0202 { 0203 if ( mode == ScrollLines ) 0204 { 0205 scrollTo( currentLine() + amount ); 0206 } 0207 else if ( mode == ScrollPages ) 0208 { 0209 scrollTo( currentLine() + amount * ( windowLines() / 2 ) ); 0210 } 0211 } 0212 0213 bool ScreenWindow::atEndOfOutput() const 0214 { 0215 return currentLine() == (lineCount()-windowLines()); 0216 } 0217 0218 void ScreenWindow::scrollTo( int line ) 0219 { 0220 int maxCurrentLineNumber = lineCount() - windowLines(); 0221 line = qBound(0,line,maxCurrentLineNumber); 0222 0223 const int delta = line - _currentLine; 0224 _currentLine = line; 0225 0226 // keep track of number of lines scrolled by, 0227 // this can be reset by calling resetScrollCount() 0228 _scrollCount += delta; 0229 0230 _bufferNeedsUpdate = true; 0231 0232 Q_EMIT scrolled(_currentLine); 0233 } 0234 0235 void ScreenWindow::setTrackOutput(bool trackOutput) 0236 { 0237 _trackOutput = trackOutput; 0238 } 0239 0240 bool ScreenWindow::trackOutput() const 0241 { 0242 return _trackOutput; 0243 } 0244 0245 int ScreenWindow::scrollCount() const 0246 { 0247 return _scrollCount; 0248 } 0249 0250 void ScreenWindow::resetScrollCount() 0251 { 0252 _scrollCount = 0; 0253 } 0254 0255 QRect ScreenWindow::scrollRegion() const 0256 { 0257 bool equalToScreenSize = windowLines() == _screen->getLines(); 0258 0259 if ( atEndOfOutput() && equalToScreenSize ) 0260 return _screen->lastScrolledRegion(); 0261 else 0262 return QRect(0,0,windowColumns(),windowLines()); 0263 } 0264 0265 void ScreenWindow::selectAll() 0266 { 0267 _screen->selectAll(); 0268 0269 _bufferNeedsUpdate = true; 0270 Q_EMIT selectionChanged(); 0271 } 0272 0273 void ScreenWindow::notifyOutputChanged() 0274 { 0275 // move window to the bottom of the screen and update scroll count 0276 // if this window is currently tracking the bottom of the screen 0277 if ( _trackOutput ) 0278 { 0279 _scrollCount -= _screen->scrolledLines(); 0280 _currentLine = qMax(0,_screen->getHistLines() - (windowLines()-_screen->getLines())); 0281 } 0282 else 0283 { 0284 // if the history is not unlimited then it may 0285 // have run out of space and dropped the oldest 0286 // lines of output - in this case the screen 0287 // window's current line number will need to 0288 // be adjusted - otherwise the output will scroll 0289 _currentLine = qMax(0,_currentLine - 0290 _screen->droppedLines()); 0291 0292 // ensure that the screen window's current position does 0293 // not go beyond the bottom of the screen 0294 _currentLine = qMin( _currentLine , _screen->getHistLines() ); 0295 } 0296 0297 _bufferNeedsUpdate = true; 0298 0299 Q_EMIT outputChanged(); 0300 } 0301 0302 //#include "ScreenWindow.moc"