2010-07-08 22:26:58 +00:00
|
|
|
/*
|
|
|
|
* Screen.cpp
|
|
|
|
* 2Term
|
|
|
|
*
|
|
|
|
* Created by Kelvin Sherlock on 7/7/2010.
|
|
|
|
* Copyright 2010 __MyCompanyName__. All rights reserved.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "Screen.h"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
iPoint TextPort::absoluteCursor() const
|
|
|
|
{
|
|
|
|
return iPoint(frame.origin.x + cursor.x, frame.origin.y + cursor.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
Screen::Screen(unsigned height, unsigned width)
|
|
|
|
{
|
2010-12-23 20:41:58 +00:00
|
|
|
|
|
|
|
_port.frame = iRect(0, 0, width, height);
|
2011-01-11 00:29:59 +00:00
|
|
|
_port.rightMargin = TextPort::MarginTruncate;
|
|
|
|
_port.rightMargin = TextPort::MarginTruncate;
|
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
_port.advanceCursor = true;
|
|
|
|
_port.scroll = true;
|
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
|
|
|
|
_flag = 0;
|
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
_screen.resize(height);
|
2010-07-08 22:26:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
for (ScreenIterator iter = _screen.begin(); iter != _screen.end(); ++iter)
|
|
|
|
{
|
2010-12-23 20:41:58 +00:00
|
|
|
iter->resize(width);
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-07-12 02:18:37 +00:00
|
|
|
Screen::~Screen()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
|
|
|
|
void Screen::beginUpdate()
|
|
|
|
{
|
2010-07-09 01:18:30 +00:00
|
|
|
_lock.lock();
|
2010-07-08 22:26:58 +00:00
|
|
|
_updates.clear();
|
2011-01-11 00:29:59 +00:00
|
|
|
_updateCursor = cursor();
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
iRect Screen::endUpdate()
|
|
|
|
{
|
|
|
|
int maxX = -1;
|
|
|
|
int maxY = -1;
|
2010-12-23 20:41:58 +00:00
|
|
|
int minX = width();
|
|
|
|
int minY = height();
|
2010-07-09 01:18:30 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
iPoint c = cursor();
|
2010-07-09 01:18:30 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (c != _updateCursor)
|
2010-07-12 02:18:37 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
_updates.push_back(c);
|
2010-07-12 02:18:37 +00:00
|
|
|
_updates.push_back(_updateCursor);
|
|
|
|
}
|
2010-07-08 22:26:58 +00:00
|
|
|
|
|
|
|
for (UpdateIterator iter = _updates.begin(); iter != _updates.end(); ++iter)
|
|
|
|
{
|
|
|
|
maxX = std::max(maxX, iter->x);
|
|
|
|
maxY = std::max(maxY, iter->y);
|
|
|
|
|
|
|
|
minX = std::min(minX, iter->x);
|
|
|
|
minY = std::min(minY, iter->y);
|
|
|
|
}
|
|
|
|
|
2010-07-09 01:18:30 +00:00
|
|
|
_lock.unlock();
|
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
return iRect(iPoint(minX, minY), iSize(maxX + 1 - minX, maxY + 1 - minY));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::setFlag(uint8_t flag)
|
|
|
|
{
|
|
|
|
_flag = flag;
|
|
|
|
}
|
|
|
|
|
2010-12-23 03:42:04 +00:00
|
|
|
void Screen::setFlagBit(uint8_t bit)
|
|
|
|
{
|
|
|
|
_flag |= bit;
|
|
|
|
}
|
|
|
|
void Screen::clearFlagBit(uint8_t bit)
|
|
|
|
{
|
|
|
|
_flag &= ~bit;
|
|
|
|
}
|
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Screen::putc(TextPort *textPort, uint8_t c)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
/*
|
|
|
|
* textport must be valid.
|
|
|
|
* cursor must be within textport.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
if (!textPort) textPort = &_port;
|
|
|
|
iPoint cursor = textPort->absoluteCursor();
|
|
|
|
|
|
|
|
// right margin is a special case.
|
|
|
|
if (textPort->cursor.x == textPort->frame.width() -1)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
if (textPort->rightMargin == TextPort::MarginTruncate) return;
|
|
|
|
if (textPort->rightMargin == TextPort::MarginOverwrite)
|
|
|
|
{
|
|
|
|
_updates.push_back(cursor);
|
|
|
|
_screen[cursor.y][cursor.x] = CharInfo(c, _flag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//if (textPort->rightMargin == TextPort::MarginWrap)
|
|
|
|
}
|
2010-07-08 22:26:58 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
_updates.push_back(cursor);
|
|
|
|
_screen[cursor.y][cursor.x] = CharInfo(c, _flag);
|
2010-07-08 22:26:58 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (textPort->advanceCursor)
|
|
|
|
{
|
|
|
|
incrementX(textPort);
|
|
|
|
}
|
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
void Screen::tabTo(TextPort *textPort, unsigned xPos)
|
2010-12-20 23:37:02 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
if (!textPort) textPort = &_port;
|
|
|
|
|
|
|
|
CharInfo clear(' ', _flag);
|
|
|
|
iPoint cursor = textPort->absoluteCursor();
|
2010-12-20 23:37:02 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
xPos = std::min((int)xPos, textPort->frame.width() - 1);
|
2010-12-20 23:37:02 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
_updates.push_back(cursor);
|
2010-12-20 23:37:02 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
for (unsigned x = textPort->cursor.x; x < xPos; ++x)
|
2010-12-20 23:37:02 +00:00
|
|
|
{
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
_screen[cursor.y][x + textPort->frame.minX()] = clear;
|
2010-12-20 23:37:02 +00:00
|
|
|
}
|
2011-01-11 00:29:59 +00:00
|
|
|
|
2011-01-20 02:34:41 +00:00
|
|
|
textPort->cursor.x = xPos;
|
2011-01-11 00:29:59 +00:00
|
|
|
if (textPort != &_port) _port.cursor = textPort->absoluteCursor();
|
|
|
|
|
|
|
|
_updates.push_back(_port.cursor);
|
|
|
|
|
2010-12-20 23:37:02 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
#pragma mark Cursor manipulation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sets cursor.x within the textport.
|
|
|
|
* if x is outside the textport and clampX is true, it will be clamped to 0/width-1
|
|
|
|
* if x is outside the textport and clampX is false, x will not be updated.
|
|
|
|
*
|
|
|
|
* returns the new cursor.x
|
|
|
|
*/
|
|
|
|
|
|
|
|
int Screen::setX(TextPort *textPort, int x)
|
2010-12-20 23:37:02 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
// honors clampX.
|
|
|
|
if (!textPort) textPort = &_port;
|
|
|
|
|
|
|
|
bool clamp = textPort->clampX;
|
2010-12-20 23:37:02 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (x < 0)
|
2010-12-20 23:37:02 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
if (clamp) textPort->cursor.x = 0;
|
2010-12-20 23:37:02 +00:00
|
|
|
}
|
2011-01-11 00:29:59 +00:00
|
|
|
else if (x >= textPort->frame.width())
|
|
|
|
{
|
|
|
|
if (clamp) textPort->cursor.x = textPort->frame.width() - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
textPort->cursor.x = x;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (textPort != &_port) _port.cursor = textPort->absoluteCursor();
|
2010-12-20 23:37:02 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
return textPort->cursor.x;
|
2010-12-20 23:37:02 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
/*
|
|
|
|
* sets cursor.y within the textport.
|
|
|
|
* if y is outside the textport and clampY is true, it will be clamped to 0/height-1
|
|
|
|
* if y is outside the textport and clampY is false, y will not be updated.
|
|
|
|
*
|
|
|
|
* returns the new cursor.y
|
|
|
|
*/
|
2010-07-17 18:21:26 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
int Screen::setY(TextPort *textPort, int y)
|
2010-07-17 18:21:26 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
// honors clampY.
|
2010-07-17 18:21:26 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (!textPort) textPort = &_port;
|
2010-07-17 18:21:26 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
bool clamp = textPort->clampY;
|
2010-07-17 18:21:26 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (y < 0)
|
|
|
|
{
|
|
|
|
if (clamp) textPort->cursor.y = 0;
|
|
|
|
}
|
|
|
|
else if (y >= textPort->frame.height())
|
2010-07-17 18:21:26 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
if (clamp) textPort->cursor.y = textPort->frame.height() - 1;
|
2010-07-17 18:21:26 +00:00
|
|
|
}
|
2011-01-11 00:29:59 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
textPort->cursor.y = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (textPort != &_port) _port.cursor = textPort->absoluteCursor();
|
|
|
|
|
|
|
|
return textPort->cursor.y;
|
2010-07-17 18:21:26 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
/*
|
|
|
|
* increments cursor.x within the textport.
|
|
|
|
* if rightMargin wraps, it will set x = 0 and incrementY (which may scroll)
|
|
|
|
* if rightMargin does not wrap, it will not be updated.
|
|
|
|
*
|
|
|
|
* returns the new cursor.x
|
|
|
|
*/
|
|
|
|
int Screen::incrementX(TextPort *textPort)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
// honors wrap, scroll.
|
|
|
|
if (!textPort) textPort = &_port;
|
|
|
|
|
|
|
|
|
|
|
|
if (textPort->cursor.x == textPort->frame.width() - 1)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
if (textPort->rightMargin == TextPort::MarginWrap)
|
|
|
|
{
|
|
|
|
textPort->cursor.x = 0;
|
|
|
|
incrementY(textPort);
|
|
|
|
}
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
2011-01-11 00:29:59 +00:00
|
|
|
else
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
textPort->cursor.x++;
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (textPort != &_port) _port.cursor = textPort->absoluteCursor();
|
|
|
|
|
|
|
|
return textPort->cursor.x;
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
/*
|
|
|
|
* decrements cursor.x within the textport.
|
|
|
|
* if leftMargin wraps, it will set x = width - 1 and decrementY (which may scroll)
|
|
|
|
* if leftMargin does not wrap, it will not be updated.
|
|
|
|
*
|
|
|
|
* returns the new cursor.x
|
|
|
|
*/
|
2010-07-08 22:26:58 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
int Screen::decrementX(TextPort *textPort)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
// honors wrap, scroll.
|
|
|
|
if (!textPort) textPort = &_port;
|
|
|
|
|
|
|
|
|
|
|
|
if (textPort->cursor.x == 0)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
if (textPort->leftMargin == TextPort::MarginWrap)
|
|
|
|
{
|
|
|
|
textPort->cursor.x = textPort->frame.width() - 1;
|
|
|
|
decrementY(textPort);
|
|
|
|
}
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
2011-01-11 00:29:59 +00:00
|
|
|
else
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
textPort->cursor.x--;
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (textPort != &_port) _port.cursor = textPort->absoluteCursor();
|
|
|
|
|
|
|
|
return textPort->cursor.x;
|
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
/*
|
|
|
|
* increment cursor.y
|
|
|
|
* this is similar to lineFeed, except that it honors the scroll flag
|
|
|
|
* at the bottom of the screen.
|
|
|
|
* returns the new cursor.y
|
|
|
|
*/
|
2010-07-08 22:26:58 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
int Screen::incrementY(TextPort *textPort)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
// similar to linefeed, but honors scroll.
|
|
|
|
if (!textPort) textPort = &_port;
|
|
|
|
|
|
|
|
if (textPort->scroll)
|
|
|
|
return lineFeed(textPort);
|
|
|
|
|
|
|
|
if (textPort->cursor.y < textPort->frame.height() - 1)
|
|
|
|
return lineFeed(textPort);
|
|
|
|
|
|
|
|
return textPort->cursor.y;
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* decrement cursor.y
|
|
|
|
* this is similar to revereseLineFeed, except that it honors the scroll flag
|
|
|
|
* at the top of the screen.
|
|
|
|
* returns the new cursor.y
|
|
|
|
*/
|
|
|
|
int Screen::decrementY(TextPort *textPort)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
// similar to reverseLineFeed, but will not scroll.
|
|
|
|
if (!textPort) textPort = &_port;
|
|
|
|
|
|
|
|
if (!textPort) textPort = &_port;
|
|
|
|
|
|
|
|
if (textPort->scroll)
|
|
|
|
return lineFeed(textPort);
|
|
|
|
|
|
|
|
|
|
|
|
if (textPort->cursor.y > 0)
|
|
|
|
return reverseLineFeed(textPort);
|
|
|
|
|
|
|
|
|
|
|
|
return textPort->cursor.y;
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
|
|
|
|
void Screen::setCursor(TextPort *textPort,iPoint point)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
setX(textPort, point.x);
|
|
|
|
setY(textPort, point.y);
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
void Screen::setCursor(TextPort *textPort, int x, int y)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
setX(textPort, x);
|
|
|
|
setY(textPort, y);
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark Erase
|
2010-07-21 01:30:31 +00:00
|
|
|
|
|
|
|
void Screen::erase(EraseRegion region)
|
|
|
|
{
|
|
|
|
|
|
|
|
CharInfoIterator ciIter;
|
|
|
|
ScreenIterator screenIter;
|
|
|
|
|
|
|
|
if (region == EraseAll)
|
|
|
|
{
|
|
|
|
ScreenIterator end = _screen.end();
|
|
|
|
for (screenIter = _screen.begin(); screenIter < end; ++screenIter)
|
|
|
|
{
|
|
|
|
std::fill(screenIter->begin(), screenIter->end(), CharInfo(0,0));
|
|
|
|
}
|
|
|
|
_updates.push_back(iPoint(0,0));
|
2010-12-23 20:41:58 +00:00
|
|
|
_updates.push_back(iPoint(width() - 1, height() - 1));
|
2010-07-21 01:30:31 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO -- be smart and check if cursor is at x = 0 (or x = _width - 1)
|
|
|
|
if (region == EraseBeforeCursor)
|
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
ScreenIterator end = _screen.begin() + y() - 1;
|
2010-07-21 01:30:31 +00:00
|
|
|
for (screenIter = _screen.begin(); screenIter < end; ++screenIter)
|
|
|
|
{
|
|
|
|
std::fill(screenIter->begin(), screenIter->end(), CharInfo(0,0));
|
|
|
|
}
|
|
|
|
_updates.push_back(iPoint(0,0));
|
2011-01-11 00:29:59 +00:00
|
|
|
_updates.push_back(iPoint(width() - 1, y()));
|
2010-07-21 01:30:31 +00:00
|
|
|
|
|
|
|
region = EraseLineBeforeCursor;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (region == EraseAfterCursor)
|
|
|
|
{
|
|
|
|
ScreenIterator end = _screen.end();
|
2011-01-11 00:29:59 +00:00
|
|
|
for (screenIter = _screen.begin() + y() + 1; screenIter < end; ++screenIter)
|
2010-07-21 01:30:31 +00:00
|
|
|
{
|
|
|
|
std::fill(screenIter->begin(), screenIter->end(), CharInfo(0,0));
|
|
|
|
}
|
2011-01-11 00:29:59 +00:00
|
|
|
_updates.push_back(iPoint(0, y() + 1));
|
2010-12-23 20:41:58 +00:00
|
|
|
_updates.push_back(iPoint(width() - 1, height() - 1));
|
2010-07-21 01:30:31 +00:00
|
|
|
|
|
|
|
region = EraseLineAfterCursor;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (region == EraseLineAll)
|
2011-01-11 00:29:59 +00:00
|
|
|
{
|
|
|
|
std::fill(_screen[y()].begin(), _screen[y()].end(), CharInfo(0,0));
|
2010-07-21 01:30:31 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
_updates.push_back(iPoint(0, y()));
|
|
|
|
_updates.push_back(iPoint(width() - 1, y()));
|
2010-07-21 01:30:31 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (region == EraseLineBeforeCursor)
|
|
|
|
{
|
2011-01-12 03:43:41 +00:00
|
|
|
std::fill(_screen[y()].begin(), _screen[y()].begin() + x(), CharInfo(0,0));
|
2010-07-21 01:30:31 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
_updates.push_back(iPoint(0, y()));
|
|
|
|
_updates.push_back(cursor());
|
2010-07-21 01:30:31 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (region == EraseLineAfterCursor)
|
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
std::fill(_screen[y()].begin() + x(), _screen[y()].end(), CharInfo(0,0));
|
2010-07-21 01:30:31 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
_updates.push_back(cursor());
|
|
|
|
_updates.push_back(iPoint(width() - 1, y()));
|
2010-07-21 01:30:31 +00:00
|
|
|
|
2011-01-12 03:43:41 +00:00
|
|
|
return;
|
2010-07-21 01:30:31 +00:00
|
|
|
}
|
2011-01-12 03:43:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Screen::erase(TextPort* textPort, EraseRegion region)
|
|
|
|
{
|
|
|
|
if (!textPort) textPort = &_port;
|
|
|
|
|
|
|
|
iRect frame = textPort->frame;
|
|
|
|
iPoint cursor = textPort->absoluteCursor();
|
|
|
|
|
|
|
|
|
|
|
|
if (region == EraseAll)
|
|
|
|
{
|
|
|
|
//erase the current screen
|
|
|
|
|
|
|
|
ScreenIterator begin = _screen.begin() + frame.minY();
|
|
|
|
ScreenIterator end = _screen.begin() + frame.maxY();
|
|
|
|
|
|
|
|
for (ScreenIterator iter = begin; iter != end; ++iter)
|
|
|
|
{
|
|
|
|
CharInfoIterator begin = iter->begin() + frame.minX();
|
|
|
|
CharInfoIterator end = iter->begin() + frame.maxX();
|
|
|
|
|
|
|
|
std::fill(begin, end, CharInfo(0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
_updates.push_back(frame.origin);
|
|
|
|
_updates.push_back(iPoint(frame.maxX() - 1, frame.maxY() - 1));
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (region == EraseLineAll)
|
|
|
|
{
|
|
|
|
|
|
|
|
// erase the current line.
|
|
|
|
|
|
|
|
ScreenIterator iter = _screen.begin() + cursor.y;
|
|
|
|
CharInfoIterator begin = iter->begin() + frame.minX();
|
|
|
|
CharInfoIterator end = iter->begin() + frame.maxX();
|
|
|
|
|
|
|
|
std::fill(begin, end, CharInfo(0, 0));
|
|
|
|
|
|
|
|
_updates.push_back(iPoint(frame.minX(), cursor.y));
|
|
|
|
_updates.push_back(iPoint(frame.maxX() - 1, cursor.y));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (region == EraseBeforeCursor)
|
|
|
|
{
|
|
|
|
// erase everything before the cursor
|
|
|
|
// part 1 -- erase all lines prior to the current line.
|
|
|
|
|
|
|
|
ScreenIterator begin = _screen.begin() + frame.minY();
|
|
|
|
ScreenIterator end = _screen.begin() + cursor.y;
|
|
|
|
|
|
|
|
for (ScreenIterator iter = begin; iter != end; ++iter)
|
|
|
|
{
|
|
|
|
CharInfoIterator begin = iter->begin() + frame.minX();
|
|
|
|
CharInfoIterator end = iter->begin() + frame.maxX();
|
|
|
|
|
|
|
|
std::fill(begin, end, CharInfo(0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
_updates.push_back(frame.origin);
|
|
|
|
_updates.push_back(iPoint(frame.maxX() - 1, cursor.y - 1));
|
|
|
|
|
|
|
|
// handle rest below.
|
|
|
|
region = EraseLineBeforeCursor;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (region == EraseAfterCursor)
|
|
|
|
{
|
|
|
|
// erase everything after the cursor
|
|
|
|
// part 1 -- erase all lines after the current line.
|
|
|
|
|
|
|
|
ScreenIterator begin = _screen.begin() + cursor.y + 1;
|
|
|
|
ScreenIterator end = _screen.begin() + frame.maxY();
|
|
|
|
|
|
|
|
if (begin < end)
|
|
|
|
{
|
|
|
|
|
|
|
|
for (ScreenIterator iter = begin; iter != end; ++iter)
|
|
|
|
{
|
|
|
|
CharInfoIterator begin = iter->begin() + frame.minX();
|
|
|
|
CharInfoIterator end = iter->begin() + frame.maxX();
|
|
|
|
|
|
|
|
std::fill(begin, end, CharInfo(0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
_updates.push_back(iPoint(cursor.x, cursor.y + 1));
|
|
|
|
_updates.push_back(iPoint(frame.maxX() - 1, frame.maxY() - 1));
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
region = EraseLineAfterCursor;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (region == EraseLineBeforeCursor)
|
|
|
|
{
|
|
|
|
// erase the current line, before the cursor.
|
|
|
|
|
|
|
|
ScreenIterator iter = _screen.begin() + cursor.y;
|
|
|
|
CharInfoIterator begin = iter->begin() + frame.minX();
|
|
|
|
CharInfoIterator end = iter->begin() + cursor.x;
|
|
|
|
|
|
|
|
std::fill(begin, end, CharInfo(0, 0));
|
|
|
|
|
|
|
|
_updates.push_back(iPoint(frame.minX(), cursor.y));
|
|
|
|
_updates.push_back(iPoint(cursor.x - 1, cursor.y));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (region == EraseLineAfterCursor)
|
|
|
|
{
|
|
|
|
// erase the current line, after the cursor.
|
|
|
|
|
|
|
|
ScreenIterator iter = _screen.begin() + cursor.y;
|
|
|
|
CharInfoIterator begin = iter->begin() + cursor.x;
|
|
|
|
CharInfoIterator end = iter->begin() + frame.maxX();
|
|
|
|
|
|
|
|
std::fill(begin, end, CharInfo(0, 0));
|
|
|
|
|
|
|
|
_updates.push_back(iPoint(cursor.x, cursor.y));
|
|
|
|
_updates.push_back(iPoint(frame.maxX() - 1, cursor.y));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-07-21 01:30:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
void Screen::eraseLine()
|
|
|
|
{
|
|
|
|
// erases everything to the right of, and including, the cursor
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
for (CharInfoIterator ciIter = _screen[y()].begin() + x(); ciIter < _screen[y()].end(); ++ciIter)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
|
|
|
*ciIter = CharInfo(0, _flag);
|
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
_updates.push_back(cursor());
|
|
|
|
_updates.push_back(iPoint(width() - 1, y()));
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
void Screen::eraseScreen()
|
|
|
|
{
|
|
|
|
// returns everything to the right of, and including, the cursor as well as all subsequent lines.
|
|
|
|
|
|
|
|
eraseLine();
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (y() == height() -1) return;
|
2010-07-08 22:26:58 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
for (ScreenIterator iter = _screen.begin() + y(); iter < _screen.end(); ++iter)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
|
|
|
for (CharInfoIterator ciIter = iter->begin(); ciIter < iter->end(); ++ciIter)
|
|
|
|
{
|
|
|
|
*ciIter = CharInfo(0, _flag);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
_updates.push_back(iPoint(0, y() + 1));
|
2010-12-23 20:41:58 +00:00
|
|
|
_updates.push_back(iPoint(width() - 1, height() - 1));
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-17 18:21:26 +00:00
|
|
|
void Screen::eraseRect(iRect rect)
|
|
|
|
{
|
|
|
|
|
2010-12-24 20:00:44 +00:00
|
|
|
unsigned maxX = std::min(width(), rect.maxX());
|
|
|
|
unsigned maxY = std::min(height(), rect.maxY());
|
2010-07-17 18:21:26 +00:00
|
|
|
|
|
|
|
CharInfo clear;
|
|
|
|
|
|
|
|
for (unsigned y = rect.minY(); y < maxY; ++y)
|
|
|
|
{
|
|
|
|
for (unsigned x = rect.minX(); x < maxX; ++x)
|
|
|
|
{
|
|
|
|
_screen[y][x] = clear;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_updates.push_back(rect.origin);
|
|
|
|
_updates.push_back(iPoint(maxX - 1, maxY - 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
void Screen::lineFeed()
|
|
|
|
{
|
|
|
|
// moves the screen up one row, inserting a blank line at the bottom.
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (y() == height() - 1)
|
2010-12-23 20:41:58 +00:00
|
|
|
{
|
|
|
|
deleteLine(0);
|
|
|
|
}
|
|
|
|
else
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
_port.cursor.y++;
|
2010-12-23 20:41:58 +00:00
|
|
|
}
|
|
|
|
}
|
2010-07-08 22:26:58 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
/*
|
|
|
|
* perform a line feed. This increments Y. If Y was at the bottom of the
|
|
|
|
* textPort, the textPort scrolls.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
int Screen::lineFeed(TextPort *textPort)
|
2010-12-23 20:41:58 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
if (!textPort)
|
|
|
|
{
|
|
|
|
lineFeed();
|
2011-01-11 00:29:59 +00:00
|
|
|
return y();
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
2010-12-23 20:41:58 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
|
|
|
|
if (textPort->cursor.y == textPort->frame.height() - 1)
|
|
|
|
{
|
|
|
|
deleteLine(textPort, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
textPort->cursor.y++;
|
|
|
|
if (textPort != &_port) _port.cursor = textPort->absoluteCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
return textPort->cursor.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* perform a reverse line feed. This increments Y. If Y was at the top of the
|
|
|
|
* textPort, the textPort scrolls.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
int Screen::reverseLineFeed(TextPort *textPort)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!textPort)
|
|
|
|
{
|
|
|
|
reverseLineFeed();
|
|
|
|
return y();
|
|
|
|
}
|
2010-12-23 20:41:58 +00:00
|
|
|
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (textPort->cursor.y == 0)
|
2010-12-23 20:41:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
insertLine(textPort, 0);
|
2010-12-23 20:41:58 +00:00
|
|
|
}
|
2011-01-11 00:29:59 +00:00
|
|
|
else
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
textPort->cursor.y--;
|
|
|
|
if (textPort != &_port) _port.cursor = textPort->absoluteCursor();
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
2010-12-23 20:41:58 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
return textPort->cursor.y;
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
|
2010-07-17 18:21:26 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
void Screen::reverseLineFeed()
|
|
|
|
{
|
|
|
|
// moves the cursor down one row, inserting a blank line at the top.
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (y() == 0)
|
2010-07-08 22:26:58 +00:00
|
|
|
{
|
2010-12-23 20:41:58 +00:00
|
|
|
insertLine(0);
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
_port.cursor.y--;
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|
2010-07-17 18:21:26 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
void Screen::insertLine(unsigned line)
|
2010-07-17 18:21:26 +00:00
|
|
|
{
|
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
if (line >= height()) return;
|
2010-07-17 18:21:26 +00:00
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
if (line == height() - 1)
|
2010-07-17 18:21:26 +00:00
|
|
|
{
|
|
|
|
_screen.back().clear();
|
2010-12-23 20:41:58 +00:00
|
|
|
_screen.back().resize(width());
|
2010-07-17 18:21:26 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::vector<CharInfo> newLine;
|
|
|
|
ScreenIterator iter;
|
|
|
|
|
|
|
|
_screen.pop_back();
|
|
|
|
iter = _screen.insert(_screen.begin() + line, newLine);
|
2010-12-23 20:41:58 +00:00
|
|
|
iter->resize(width());
|
2010-07-17 18:21:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_updates.push_back(iPoint(0, line));
|
2010-12-23 20:41:58 +00:00
|
|
|
_updates.push_back(iPoint(width() - 1, height() - 1));
|
2010-07-17 18:21:26 +00:00
|
|
|
}
|
|
|
|
|
2010-12-24 20:00:44 +00:00
|
|
|
// line is relative to the textView.
|
|
|
|
// textView has been constrained.
|
|
|
|
|
|
|
|
void Screen::insertLine(TextPort *textPort, unsigned line)
|
|
|
|
{
|
|
|
|
CharInfo ci;
|
|
|
|
|
|
|
|
|
|
|
|
if (!textPort) return insertLine(line);
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
iRect frame(textPort->frame);
|
2010-12-24 20:00:44 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
int minY = frame.minY();
|
|
|
|
int maxY = frame.maxY();
|
2010-12-24 20:00:44 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
int minX = frame.minX();
|
|
|
|
int maxX = frame.maxX();
|
2010-12-24 20:00:44 +00:00
|
|
|
|
|
|
|
if (line < 0) return;
|
|
|
|
if (line >= frame.height()) return;
|
|
|
|
|
|
|
|
// move all subsequent lines forward by 1.
|
2011-01-11 00:29:59 +00:00
|
|
|
for (int y = frame.height() - 2; y >= line; --y)
|
2010-12-24 20:00:44 +00:00
|
|
|
{
|
|
|
|
CharInfoIterator iter;
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
iter = _screen[minY + y].begin();
|
2010-12-24 20:00:44 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
std::copy(iter +minX, iter + maxX, _screen[minY + y + 1].begin() + minX);
|
2010-12-24 20:00:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// clear the line.
|
|
|
|
std::fill(_screen[minY + line].begin() + minX, _screen[minY + line].begin() + maxX, ci);
|
|
|
|
|
|
|
|
// set the update region.
|
|
|
|
|
|
|
|
_updates.push_back(iPoint(minX, minY + line));
|
|
|
|
_updates.push_back(iPoint(maxX - 1, maxY - 1));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
void Screen::deleteLine(unsigned line)
|
2010-07-17 18:21:26 +00:00
|
|
|
{
|
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
if (line >= height()) return;
|
2010-07-17 18:21:26 +00:00
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
if (line == height() - 1)
|
2010-07-17 18:21:26 +00:00
|
|
|
{
|
|
|
|
_screen.back().clear();
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::vector<CharInfo> newLine;
|
|
|
|
|
|
|
|
_screen.erase(_screen.begin() + line);
|
|
|
|
|
|
|
|
_screen.push_back(newLine);
|
|
|
|
}
|
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
_screen.back().resize(width());
|
2010-07-17 18:21:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
_updates.push_back(iPoint(0, line));
|
2010-12-23 20:41:58 +00:00
|
|
|
_updates.push_back(iPoint(width() - 1, height() - 1));
|
2010-07-12 02:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-24 20:00:44 +00:00
|
|
|
void Screen::deleteLine(TextPort *textPort, unsigned line)
|
|
|
|
{
|
|
|
|
CharInfo ci;
|
|
|
|
|
|
|
|
if (!textPort) return deleteLine(line);
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
iRect frame(textPort->frame);
|
2010-12-24 20:00:44 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
int minY = frame.minY();
|
|
|
|
int maxY = frame.maxY();
|
2010-12-24 20:00:44 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
int minX = frame.minX();
|
|
|
|
int maxX = frame.maxX();
|
2010-12-24 20:00:44 +00:00
|
|
|
|
|
|
|
if (line < 0) return;
|
|
|
|
if (line >= frame.height()) return;
|
|
|
|
|
|
|
|
// move all subsequent lines back by 1.
|
2011-01-20 02:34:41 +00:00
|
|
|
for (int y = line; y < frame.height() - 1; ++y)
|
2010-12-24 20:00:44 +00:00
|
|
|
{
|
|
|
|
CharInfoIterator iter;
|
|
|
|
CharInfoIterator end;
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
iter = _screen[minY + y + 1].begin();
|
2010-12-24 20:00:44 +00:00
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
std::copy(iter + minX, iter + maxX, _screen[minY + y].begin() + minX);
|
2010-12-24 20:00:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// clear the last line.
|
|
|
|
std::fill(_screen[maxY - 1].begin() + minX, _screen[maxY - 1].begin() + maxX, ci);
|
|
|
|
|
|
|
|
// set the update region.
|
|
|
|
|
|
|
|
_updates.push_back(iPoint(minX, minY + line));
|
|
|
|
_updates.push_back(iPoint(maxX - 1, maxY - 1));
|
|
|
|
|
|
|
|
}
|
2010-07-17 18:21:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
void Screen::setSize(unsigned w, unsigned h)
|
2010-07-12 02:18:37 +00:00
|
|
|
{
|
2011-01-11 00:29:59 +00:00
|
|
|
// TODO -- have separate minimum size for textport?
|
2010-07-12 02:18:37 +00:00
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
if ((height() == h) && (width() == w)) return;
|
2010-07-12 02:18:37 +00:00
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
if (height() < h)
|
2010-07-12 02:18:37 +00:00
|
|
|
{
|
2010-12-23 20:41:58 +00:00
|
|
|
_screen.resize(h);
|
2010-07-12 02:18:37 +00:00
|
|
|
}
|
2010-12-23 20:41:58 +00:00
|
|
|
else if (height() > h)
|
2010-07-12 02:18:37 +00:00
|
|
|
{
|
2010-12-23 20:41:58 +00:00
|
|
|
unsigned count = height() - h;
|
2011-01-16 23:04:31 +00:00
|
|
|
int y = _port.cursor.y;
|
|
|
|
int maxY = height() - 1;
|
|
|
|
|
|
|
|
// 1. erase from the bottom, up to the cursor (if blank)
|
|
|
|
// 2. erase lines from the top.
|
|
|
|
|
|
|
|
while (count && maxY > y)
|
|
|
|
{
|
|
|
|
// todo -- check if blank...
|
|
|
|
_screen.pop_back();
|
|
|
|
--count;
|
|
|
|
--maxY;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-12 02:18:37 +00:00
|
|
|
// erase lines from the top.
|
2011-01-16 23:04:31 +00:00
|
|
|
if (count)
|
|
|
|
_screen.erase(_screen.begin(), _screen.begin() + count);
|
2010-07-12 02:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//if (_width != _width || _height != height)
|
|
|
|
{
|
|
|
|
ScreenIterator iter;
|
|
|
|
for (iter = _screen.begin(); iter != _screen.end(); ++iter)
|
|
|
|
{
|
2010-12-23 20:41:58 +00:00
|
|
|
iter->resize(w);
|
2010-07-12 02:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-12-23 20:41:58 +00:00
|
|
|
_port.frame.size = iSize(w, h);
|
2010-07-12 02:18:37 +00:00
|
|
|
|
|
|
|
|
2011-01-11 00:29:59 +00:00
|
|
|
if (_port.cursor.y >= h) _port.cursor.y = h - 1;
|
|
|
|
if (_port.cursor.x >= w) _port.cursor.x = w - 1;
|
2010-07-12 02:18:37 +00:00
|
|
|
|
|
|
|
//fprintf(stderr, "setSize(%u, %u)\n", width, height);
|
|
|
|
|
2010-07-08 22:26:58 +00:00
|
|
|
}
|