ragel version of gno console emulator.

git-svn-id: svn://qnap.local/TwoTerm/branches/fix-gno-scrolling-region@3159 5590a31f-7b70-45f8-8c82-aa3a8e5f4507
This commit is contained in:
Kelvin Sherlock 2017-02-05 19:23:27 +00:00
parent 02ea54d3fe
commit 228b4da5cc
2 changed files with 235 additions and 250 deletions

View File

@ -15,17 +15,11 @@
@interface GNOConsole : NSObject <Emulator>
{
unsigned _state;
unsigned cs;
TextPort _textPort;
iPoint _dca;
int _vp[4];
Screen::CursorType _cursorType;
int _scratch[4];
}

View File

@ -116,20 +116,234 @@
*/
%%{
machine console;
alphtype unsigned int;
action nop {}
arg1 = any ${ _scratch[0] = ((fc & 0x7f) - 32); };
arg2 = any ${ _scratch[1] = ((fc & 0x7f) - 32); };
arg3 = any ${ _scratch[2] = ((fc & 0x7f) - 32); };
arg4 = any ${ _scratch[3] = ((fc & 0x7f) - 32); };
main := (
0x00 $nop
| 0x01 ${
// CTRL(A)
// set cursor to flashing block.
_cursorType = Screen::CursorTypeBlock;
screen->setCursorType(_cursorType);
}
| 0x02 ${
// CTRL('B')
// set cursor to flashing underscore.
_cursorType = Screen::CursorTypeUnderscore;
screen->setCursorType((Screen::CursorType)_cursorType);
}
| 0x03 '[' arg1 arg2 arg3 arg4 ${
// CTRL('C'):
_scratch[0] = std::max(0, _scratch[0]);
_scratch[2] = std::max(0, _scratch[2]);
_scratch[1] = std::min(80, _scratch[1]);
_scratch[3] = std::min(24, _scratch[3]);
if (_scratch[1] <= _scratch[0]) _scratch[1] = 80;
if (_scratch[3] <= _scratch[2]) _scratch[3] = 24;
_textPort.frame = iRect(_scratch[0], _scratch[2], _scratch[1] - _scratch[0], _scratch[3] - _scratch[2]);
// move the cursor to the top left
// gnome clamps the horizontal, doesn't adjust the vertical.
screen->setCursor(&_textPort, iPoint(0,0));
}
| 0x04 $nop
| 0x05 ${
// CTRL('E'):
// cursor on
screen->setCursorType(_cursorType);
}
| 0x06 ${
//CTRL('F'):
//cursor off
screen->setCursorType(Screen::CursorTypeNone);
}
| 0x07 ${
//CTRL('G'):
NSBeep();
}
| 0x08 ${
// CTRL('H'):
screen->decrementX(&_textPort);
//screen->decrementX(true);
}
| 0x09 ${
// CTRL('I'):
// tab
screen->tabTo(&_textPort, (_textPort.cursor.x + 8) & ~0x07);
//screen->tabTo((screen->x() + 8) & ~0x07);
}
| 0x0a ${
// CTRL('J'):
// down 1 line.
screen->lineFeed(&_textPort);
}
| 0x0b ${
// CTRL('K'):
// clear to end of screen
screen->erase(&_textPort, Screen::EraseAfterCursor);
}
| 0x0c ${
// CTRL('L'):
// clear screen, go home.
screen->erase(&_textPort, Screen::EraseAll);
screen->setCursor(&_textPort, 0, 0);
}
| 0x0d ${
// CTRL('M'):
// move to left edge.
screen->setX(&_textPort, 0);
}
| 0x0e ${
// CTRL('N'):
// normal text.
screen->clearFlagBit(Screen::FlagInverse);
}
| 0x0f ${
// CTRL('O'):
// inverse text.
screen->setFlagBit(Screen::FlagInverse);
}
| 0x10 $nop
| 0x11 ${
// CTRL('Q'):
// insert line.
// TODO -- verify textPort
screen->insertLine(&_textPort, _textPort.cursor.y);
}
| 0x12 ${
// CTRL('R'):
// delete line
// TODO -- verify textPort
screen->deleteLine(&_textPort, _textPort.cursor.y);
}
| 0x13 $nop
| 0x14 $nop
| 0x15 ${
// CTRL('U'):
// right arrow.
screen->incrementX(&_textPort);
}
| 0x16 ${
// CTRL('V'):
// scroll down 1 line.
screen->insertLine(&_textPort, 0);
}
| 0x17 ${
// CTRL('W'):
// scroll up 1 line.
screen->deleteLine(&_textPort, 0);
}
| 0x18 ${
// CTRL('X'):
//mouse text off
screen->clearFlagBit(Screen::FlagMouseText);
}
| 0x19 ${
// CTRL('Y'):
// cursor home
screen->setCursor(&_textPort, 0, 0);
}
| 0x1a ${
// CTRL('Z'):
// clear entire line
screen->erase(&_textPort, Screen::EraseLineAll);
}
| 0x1b ${
// CTRL('['):
// mouse text on
// inverse must also be on.
screen->setFlagBit(Screen::FlagMouseText);
}
| 0x1c ${
// CTRL('\\'):
// move cursor 1 character to the right
screen->incrementX(&_textPort);
}
| 0x1d ${
// CTRL(']'):
// clear to end of line.
screen->erase(&_textPort, Screen::EraseLineAfterCursor);
}
| 0x1e arg1 arg2 ${
// CTRL('^'):
// goto x y
// goto xy does not respect the text window.
if (_scratch[0] >= 80) _scratch[0] = 0;
if (_scratch[1] >= 24) _scratch[1] = 0;
iPoint dca(_scratch[0], _scratch[1]);
screen->setCursor(&_textPort, dca);
}
| 0x1f ${
// CTRL('_'):
// move up 1 line
screen->decrementY(&_textPort);
}
| 0x20 .. 0x7f ${
screen->putc(&_textPort, fc);
}
| 0x80 .. 0xff $nop
)* $err{ fgoto main; };
write data;
}%%
@implementation GNOConsole
enum {
StateText,
StateDCAX,
StateDCAY,
StateSetPort1,
StateSetPort2,
StateSetPort3,
StateSetPort4,
StateSetPort5
};
+(void)load
{
@ -154,7 +368,8 @@ enum {
-(void)reset
{
_state = StateText;
%%write init;
_textPort.frame = iRect(0, 0, 80, 24);
_textPort.cursor = iPoint(0,0);
@ -197,239 +412,15 @@ enum {
return self;
}
-(void)processCharacter:(uint8_t)c screen:(Screen *)screen output:(OutputChannel *)output
-(void)processData:(const uint8_t *)data length: (size_t)length screen:(Screen *)screen output:(OutputChannel *)output
{
const uint8_t *eof = nullptr;
const uint8_t *p = data;
const uint8_t *pe = data + length;
if (_state == StateText)
{
switch (c)
{
case CTRL('A'):
// set cursor to flashing block.
_cursorType = Screen::CursorTypeBlock;
screen->setCursorType(_cursorType);
break;
case CTRL('B'):
_cursorType = Screen::CursorTypeUnderscore;
screen->setCursorType((Screen::CursorType)_cursorType);
// set cursor to flashing underscore.
break;
case CTRL('C'):
// begin set text window sequence
_state = StateSetPort1;
break;
case CTRL('E'):
// cursor on
screen->setCursorType(_cursorType);
break;
case CTRL('F'):
//cursor off
screen->setCursorType(Screen::CursorTypeNone);
break;
case CTRL('G'):
NSBeep();
break;
case CTRL('H'):
screen->decrementX(&_textPort);
//screen->decrementX(true);
break;
case CTRL('I'):
// tab
screen->tabTo(&_textPort, (_textPort.cursor.x + 8) & ~0x07);
//screen->tabTo((screen->x() + 8) & ~0x07);
break;
case CTRL('J'):
// down 1 line.
screen->lineFeed(&_textPort);
break;
case CTRL('K'):
// clear to end of screen
screen->erase(&_textPort, Screen::EraseAfterCursor);
break;
case CTRL('L'):
// clear screen, go home.
screen->erase(&_textPort, Screen::EraseAll);
screen->setCursor(&_textPort, 0, 0);
break;
case CTRL('M'):
// move to left edge.
screen->setX(&_textPort, 0);
break;
case CTRL('N'):
// normal text.
screen->clearFlagBit(Screen::FlagInverse);
break;
case CTRL('O'):
// inverse text.
screen->setFlagBit(Screen::FlagInverse);
break;
case CTRL('Q'):
// insert line.
// TODO -- verify textPort
screen->insertLine(&_textPort, _textPort.cursor.y);
break;
case CTRL('R'):
// delete line
// TODO -- verify textPort
screen->deleteLine(&_textPort, _textPort.cursor.y);
break;
case CTRL('U'):
// right arrow.
screen->incrementX(&_textPort);
break;
case CTRL('V'):
// scroll down 1 line.
screen->insertLine(&_textPort, 0);
break;
case CTRL('W'):
// scroll up 1 line.
screen->deleteLine(&_textPort, 0);
break;
case CTRL('X'):
//mouse text off
screen->clearFlagBit(Screen::FlagMouseText);
break;
case CTRL('Y'):
// cursor home
screen->setCursor(&_textPort, 0, 0);
break;
case CTRL('Z'):
// clear entire line
screen->erase(&_textPort, Screen::EraseLineAll);
break;
case CTRL('['):
// mouse text on
// inverse must also be on.
screen->setFlagBit(Screen::FlagMouseText);
break;
case CTRL('\\'):
// move cursor 1 character to the right
screen->incrementX(&_textPort);
break;
case CTRL(']'):
// clear to end of line.
screen->erase(&_textPort, Screen::EraseLineAfterCursor);
break;
case CTRL('^'):
// goto x y
_state = StateDCAX;
break;
case CTRL('_'):
// move up 1 line
screen->decrementY(&_textPort);
break;
default:
if (c >= 0x20 && c < 0x7f)
{
screen->putc(&_textPort, c);
}
break;
}
return;
}
switch (_state)
{
case StateDCAX:
_dca.x = (c & 0x7f) - 32;
_state = StateDCAY;
break;
%%write exec;
case StateDCAY:
_dca.y = (c & 0x7f) - 32;
// goto xy does not respect the text window.
if (_dca.x >= 80) _dca.x = 0;
if (_dca.y >= 24) _dca.y = 0;
screen->setCursor(&_textPort, _dca);
//screen->setCursor(_dca);
_state = StateText;
break;
case StateSetPort1:
// [
if (c == '[')
_state++;
else
_state = StateText;
break;
case StateSetPort2:
// left
_vp[0] = (c & 0x7f) - 32;
_state++;
break;
case StateSetPort3:
// right
_vp[1] = (c & 0x7f) - 32 + 1;
_state++;
break;
case StateSetPort4:
// top
_vp[2] = (c & 0x7f) - 32;
_state++;
break;
case StateSetPort5:
// bottom
// and validation.
_vp[3] = (c & 0x7f) - 32 + 1;
_vp[0] = std::max(0, _vp[0]);
_vp[2] = std::max(0, _vp[2]);
_vp[1] = std::min(80, _vp[1]);
_vp[3] = std::min(24, _vp[3]);
if (_vp[1] <= _vp[0]) _vp[1] = 80;
if (_vp[3] <= _vp[2]) _vp[3] = 24;
_textPort.frame = iRect(_vp[0], _vp[2], _vp[1] - _vp[0], _vp[3] - _vp[2]);
// move the cursor to the top left
// gnome clamps the horizontal, doesn't adjust the vertical.
screen->setCursor(&_textPort, iPoint(0,0));
_state = StateText;
}
}