mirror of
https://github.com/ksherlock/TwoTerm.git
synced 2024-12-22 22:29:51 +00:00
e1cf110542
git-svn-id: svn://qnap.local/TwoTerm/trunk@3139 5590a31f-7b70-45f8-8c82-aa3a8e5f4507
413 lines
11 KiB
Plaintext
413 lines
11 KiB
Plaintext
//
|
|
// GSOSConsole.m
|
|
// 2Term
|
|
//
|
|
// Created by Kelvin Sherlock on 7/9/2016.
|
|
//
|
|
//
|
|
|
|
#import "GSOSConsole.h"
|
|
|
|
#include "OutputChannel.h"
|
|
#include "Screen.h"
|
|
|
|
#include "algorithm.h"
|
|
|
|
%%{
|
|
machine console;
|
|
alphtype unsigned int;
|
|
|
|
action nop {}
|
|
|
|
arg1 = any ${ _scratch[0] = (fc - 32); };
|
|
arg2 = any ${ _scratch[1] = (fc - 32); };
|
|
arg3 = any ${ _scratch[2] = (fc - 32); };
|
|
arg4 = any ${ _scratch[3] = (fc - 32); };
|
|
|
|
main := (
|
|
0x00 $nop
|
|
| 0x01 ${
|
|
/* save current textport and reset text port to default. */
|
|
|
|
_tpStack.push_back(_textPort);
|
|
// todo -- consLF, consDLE?
|
|
_textPort = TextPort();
|
|
|
|
}
|
|
|
|
| 0x02 arg1 arg2 arg3 arg4 ${
|
|
/* set the current text port */
|
|
|
|
// left, top, right, bottom
|
|
|
|
_scratch[0] = clamp(_scratch[0], 0, 80-1);
|
|
_scratch[1] = clamp(_scratch[1], 0, 24-1);
|
|
|
|
_scratch[2] = clamp(_scratch[2], 0, 80-1)+1;
|
|
_scratch[3] = clamp(_scratch[3], 0, 24-1)+1;
|
|
|
|
|
|
iRect r(_scratch[0],
|
|
_scratch[1],
|
|
_scratch[2] - _scratch[0],
|
|
_scratch[3] - _scratch[1]
|
|
);
|
|
|
|
_textPort.frame = r;
|
|
|
|
screen->setCursor(&_textPort, 0, 0);
|
|
}
|
|
|
|
| 0x03 ${
|
|
/* clear from beginning of line */
|
|
// todo -- should also include the cursor.
|
|
screen->erase(&_textPort, Screen::EraseLineBeforeCursor);
|
|
}
|
|
|
|
| 0x04 ${
|
|
/* pop text port */
|
|
|
|
if (!_tpStack.empty()) {
|
|
_textPort = _tpStack.back();
|
|
_tpStack.pop_back();
|
|
} else {
|
|
_textPort = TextPort();
|
|
}
|
|
|
|
}
|
|
|
|
| 0x05 any ${
|
|
/* horizontal scroll */
|
|
int8_t n = fc;
|
|
// ....
|
|
}
|
|
|
|
| 0x06 any ${
|
|
/* set vertical position */
|
|
unsigned n = clamp(fc - 32, 0, 24-1);
|
|
screen->setY(&_textPort, n);
|
|
}
|
|
|
|
| 0x07 ${
|
|
NSBeep();
|
|
}
|
|
|
|
| 0x08 ${
|
|
/* back space */
|
|
screen->decrementX(&_textPort);
|
|
}
|
|
|
|
| 0x09 $nop
|
|
|
|
| 0x0a ${
|
|
/* line feed */
|
|
screen->lineFeed(&_textPort);
|
|
}
|
|
|
|
| 0x0b ${
|
|
/* clear to end of text port */
|
|
/* actually sets them to consFill */
|
|
screen->erase(&_textPort, Screen::EraseAfterCursor);
|
|
}
|
|
|
|
|
|
| 0x0c ${
|
|
/* clear text port and home */
|
|
screen->erase(&_textPort, Screen::EraseAll);
|
|
screen->setCursor(&_textPort, 0, 0);
|
|
}
|
|
|
|
| 0x0d ${
|
|
/* carriage return */
|
|
screen->setX(&_textPort, 0);
|
|
|
|
if (_consLF) {
|
|
screen->lineFeed(&_textPort);
|
|
}
|
|
|
|
}
|
|
|
|
| 0x0e ${
|
|
/* set normal display */
|
|
screen->clearFlagBit(Screen::FlagInverse);
|
|
}
|
|
|
|
| 0x0f ${
|
|
/* set inverse display */
|
|
screen->setFlagBit(Screen::FlagInverse);
|
|
}
|
|
|
|
| 0x10 any ${
|
|
/* DLE expansion */
|
|
if (_consDLE) {
|
|
unsigned count = (fc - 32) & 0xff;
|
|
while (count--) screen->putc(&_textPort, ' ');
|
|
}
|
|
else { fhold; }
|
|
}
|
|
|
|
| 0x11 ${ /* 40 column mode */ }
|
|
| 0x12 ${ /* 80 column mode */ }
|
|
|
|
| 0x13 ${
|
|
/* clear from beginning of text port */
|
|
screen->erase(&_textPort, Screen::EraseBeforeCursor);
|
|
// todo -- clears up to and including cursor location!
|
|
}
|
|
|
|
| 0x14 any ${
|
|
/* set horizontal position */
|
|
unsigned n = clamp(fc - 32, 0, 80 - 1);
|
|
screen->setX(&_textPort, n);
|
|
}
|
|
|
|
| 0x15 any ${
|
|
/* set cursor movement */
|
|
unsigned flags = fc;
|
|
_textPort.advanceCursor = flags & 0x01;
|
|
_consLF = flags & 0x02;
|
|
if (flags & 0x04) {
|
|
_textPort.leftMargin = TextPort::MarginWrap;
|
|
_textPort.rightMargin = TextPort::MarginWrap;
|
|
} else {
|
|
_textPort.leftMargin = TextPort::MarginTruncate;
|
|
_textPort.rightMargin = TextPort::MarginTruncate;
|
|
}
|
|
_textPort.scroll = flags & 0x08;
|
|
|
|
_consDLE = flags & 0x10;
|
|
}
|
|
|
|
| 0x16 ${ /* scroll down 1 line */ }
|
|
|
|
| 0x17 ${ /* scroll up one line */ }
|
|
|
|
| 0x18 ${
|
|
/* disable mouse text */
|
|
screen->clearFlagBit(Screen::FlagMouseText);
|
|
}
|
|
|
|
| 0x19 ${
|
|
/* home cursor */
|
|
screen->setCursor(&_textPort, 0, 0);
|
|
}
|
|
|
|
| 0x1a ${
|
|
/* clear line */
|
|
screen->erase(&_textPort, Screen::EraseLineAll);
|
|
screen->setX(&_textPort, 0);
|
|
}
|
|
|
|
| 0x1b ${
|
|
/* enable mouse text mapping */
|
|
screen->setFlagBit(Screen::FlagMouseText);
|
|
}
|
|
|
|
| 0x1c ${
|
|
/* move cursor right */
|
|
screen->incrementX(&_textPort);
|
|
}
|
|
|
|
| 0x1d ${
|
|
/* clear to end of line */
|
|
screen->erase(&_textPort, Screen::EraseLineAfterCursor);
|
|
}
|
|
|
|
| 0x1e arg1 arg2
|
|
${ /* goto x y */
|
|
iPoint dca;
|
|
dca.x = clamp(_scratch[0], 0, 80 - 1);
|
|
dca.y = clamp(_scratch[1], 0, 24 - 1);
|
|
screen->setCursor(&_textPort, dca);
|
|
}
|
|
|
|
| 0x1f ${
|
|
/* move cursor up */
|
|
screen->reverseLineFeed(&_textPort);
|
|
}
|
|
|
|
| 0x20 .. 0x7f ${
|
|
screen->putc(&_textPort, fc);
|
|
}
|
|
|
|
| 0x80 .. 0x9f ${
|
|
/* uppercase inverse/normal */
|
|
uint8_t flag = ~(screen->flag() & Screen::FlagInverse);
|
|
screen->putc(&_textPort, fc - 0x40, flag);
|
|
}
|
|
|
|
| 0xa0 .. 0xbf ${
|
|
/* special inverse/normal */
|
|
uint8_t flag = ~(screen->flag() & Screen::FlagInverse);
|
|
screen->putc(&_textPort, fc - 0x80, flag);
|
|
}
|
|
|
|
| 0xc0 .. 0xdf ${
|
|
/* uppercase normal / mouse text. */
|
|
uint8_t flag = ~(screen->flag() & Screen::FlagInverse);
|
|
if (flag) flag |= Screen::FlagMouseText;
|
|
screen->putc(&_textPort, fc - 0x80, flag);
|
|
}
|
|
|
|
| 0xe0 .. 0xff ${
|
|
/* special inverse/normal */
|
|
uint8_t flag = ~(screen->flag() & Screen::FlagInverse);
|
|
screen->putc(&_textPort, fc - 0x80, flag);
|
|
}
|
|
|
|
)* $err{ fgoto main; };
|
|
|
|
write data;
|
|
}%%
|
|
|
|
@implementation GSOSConsole
|
|
|
|
+(void)load
|
|
{
|
|
[EmulatorManager registerClass: self];
|
|
}
|
|
|
|
+(NSString *)name
|
|
{
|
|
return @"GS/OS Console";
|
|
}
|
|
|
|
-(NSString *)name
|
|
{
|
|
return @"GS/OS Console";
|
|
}
|
|
|
|
-(const char *)termName
|
|
{
|
|
return "gsos-console";
|
|
}
|
|
|
|
|
|
|
|
-(BOOL)resizable
|
|
{
|
|
return NO;
|
|
}
|
|
|
|
-(struct winsize)defaultSize
|
|
{
|
|
struct winsize ws = { 24, 80, 0, 0 };
|
|
|
|
return ws;
|
|
}
|
|
|
|
-(void)initTerm: (struct termios *)term
|
|
{
|
|
// Control-U is used by the up-arrow key.
|
|
term->c_cc[VKILL] = CTRL('X');
|
|
// \t is a NOP so expand to spaces.
|
|
term->c_oflag |= OXTABS;
|
|
}
|
|
|
|
-(id)init
|
|
{
|
|
if ((self = [super init]))
|
|
{
|
|
[self reset];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
-(void)reset
|
|
{
|
|
|
|
%%write init;
|
|
|
|
_textPort.frame = iRect(0, 0, 80, 24);
|
|
_textPort.cursor = iPoint(0,0);
|
|
|
|
_textPort.scroll = true;
|
|
_textPort.advanceCursor = true;
|
|
_textPort.leftMargin = TextPort::MarginWrap;
|
|
_textPort.rightMargin = TextPort::MarginWrap;
|
|
|
|
_cursorType = Screen::CursorTypeUnderscore;
|
|
_consLF = true;
|
|
_consDLE = true;
|
|
|
|
// set flags to plain text.
|
|
}
|
|
|
|
-(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;
|
|
|
|
%%write exec;
|
|
|
|
}
|
|
|
|
-(void)keyDown:(NSEvent *)event screen:(Screen *)screen output:(OutputChannel *)output
|
|
{
|
|
NSEventModifierFlags flags = [event modifierFlags];
|
|
NSString *chars = [event charactersIgnoringModifiers];
|
|
|
|
NSUInteger length = [chars length];
|
|
|
|
for (unsigned i = 0; i < length; ++i)
|
|
{
|
|
unichar uc = [chars characterAtIndex: i];
|
|
|
|
switch (uc)
|
|
{
|
|
case NSEnterCharacter:
|
|
output->write(CTRL('M'));
|
|
break;
|
|
|
|
// todo -- verify...
|
|
#if 0
|
|
case NSDeleteCharacter:
|
|
output->write(0x7f);
|
|
break;
|
|
#endif
|
|
|
|
// todo -- verify...
|
|
case NSBackspaceCharacter:
|
|
output->write(0x7f);
|
|
break;
|
|
|
|
case NSLeftArrowFunctionKey:
|
|
output->write(CTRL('H'));
|
|
break;
|
|
|
|
case NSRightArrowFunctionKey:
|
|
output->write(CTRL('U'));
|
|
break;
|
|
|
|
case NSUpArrowFunctionKey:
|
|
output->write(CTRL('K'));
|
|
break;
|
|
|
|
case NSDownArrowFunctionKey:
|
|
output->write(CTRL('J'));
|
|
break;
|
|
|
|
|
|
default:
|
|
if (uc <= 0x7f)
|
|
{
|
|
char c = uc;
|
|
if (flags & (NSShiftKeyMask | NSAlphaShiftKeyMask))
|
|
{
|
|
c = toupper(c);
|
|
}
|
|
if (flags & NSControlKeyMask)
|
|
c = CTRL(c);
|
|
|
|
output->write(c);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
@end
|