mirror of
https://github.com/ksherlock/TwoTerm.git
synced 2025-08-09 15:24:56 +00:00
rewrite VT05 / VT50 / VT50H with ragel.
This commit is contained in:
@@ -15,11 +15,10 @@
|
|||||||
|
|
||||||
|
|
||||||
@interface VT05 : NSObject <Emulator> {
|
@interface VT05 : NSObject <Emulator> {
|
||||||
unsigned _state;
|
unsigned cs;
|
||||||
|
unsigned _scratch[2];
|
||||||
context _context;
|
context _context;
|
||||||
BOOL _upperCase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)tab: (Screen *)screen;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
236
Emulators/VT05.mm.ragel
Normal file
236
Emulators/VT05.mm.ragel
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
//
|
||||||
|
// VT05.mm.m
|
||||||
|
// TwoTerm
|
||||||
|
//
|
||||||
|
// Created by Kelvin Sherlock on 3/3/2018.
|
||||||
|
//
|
||||||
|
// Disabled because linefeed only scrolls when on the last line... not very useful!
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
* http://vt100.net/docs/vt05-rm/contents.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/ttydefaults.h>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
#import "VT05.h"
|
||||||
|
|
||||||
|
#include "OutputChannel.h"
|
||||||
|
#include "Screen.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VTBell = 07,
|
||||||
|
VTCursorLeft = 010,
|
||||||
|
VTTab = 011,
|
||||||
|
VTLineFeed = 012,
|
||||||
|
VTCursorDown = 013,
|
||||||
|
VTCarriageReturn = 015,
|
||||||
|
VTCAD = 016,
|
||||||
|
|
||||||
|
VTCursorRight = 030,
|
||||||
|
VTCursorUp = 032,
|
||||||
|
VTHome = 035,
|
||||||
|
VTEOL = 036,
|
||||||
|
VTEOS = 037
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
%%{
|
||||||
|
machine console;
|
||||||
|
alphtype unsigned int;
|
||||||
|
|
||||||
|
action nop {}
|
||||||
|
|
||||||
|
|
||||||
|
action tab {
|
||||||
|
if (cursor.x < 64) cursor.x = (cursor.x + 8) & ~7;
|
||||||
|
else if (cursor.x < window.maxX() -1) cursor.x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
action linefeed {
|
||||||
|
if (cursor.y == window.maxY() -1)
|
||||||
|
screen->scrollUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
action dca {
|
||||||
|
|
||||||
|
unsigned y = _scratch[0];
|
||||||
|
if (y < window.maxY()) cursor.y = y;
|
||||||
|
|
||||||
|
unsigned x = _scratch[1];
|
||||||
|
if (x < window.maxX()) cursor.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
action erase_eos {
|
||||||
|
|
||||||
|
iRect tmp;
|
||||||
|
|
||||||
|
tmp.origin = cursor;
|
||||||
|
tmp.size = iSize( window.maxX() - cursor.x, 1);
|
||||||
|
screen->eraseRect(tmp);
|
||||||
|
|
||||||
|
tmp.origin = iPoint(0, cursor.y+1);
|
||||||
|
tmp.size = iSize(window.maxX(), window.maxY() - cursor.y - 1);
|
||||||
|
screen->eraseRect(tmp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
action erase_eol {
|
||||||
|
|
||||||
|
iRect tmp;
|
||||||
|
|
||||||
|
tmp.origin = cursor;
|
||||||
|
tmp.size = iSize( window.maxX() - cursor.x, 1);
|
||||||
|
screen->eraseRect(tmp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
arg1 = 0x00* (any-0x00) ${ _scratch[0] = ((fc & 0x7f) - 32); };
|
||||||
|
arg2 = 0x00* (any-0x00) ${ _scratch[1] = ((fc & 0x7f) - 32); };
|
||||||
|
|
||||||
|
control_codes = (
|
||||||
|
0x07 ${ NSBeep(); }
|
||||||
|
| 0x08 ${ if (cursor.x) cursor.x--; }
|
||||||
|
| 0x09 $tab
|
||||||
|
| 0x0a $linefeed
|
||||||
|
| 0x0b ${ if (cursor.y < window.maxY() -1) cursor.y++; }
|
||||||
|
| 0x0d ${ cursor.x = 0; }
|
||||||
|
| 0x0e arg1 arg2 $dca
|
||||||
|
| 0x18 ${ if (cursor.x < window.maxX() -1) cursor.x++; }
|
||||||
|
| 0x1a ${ if (cursor.y) cursor.y--; }
|
||||||
|
| 0x1d ${ cursor = iPoint(0,0); }
|
||||||
|
| 0x1e $erase_eol
|
||||||
|
| 0x1f $erase_eos
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
main := (
|
||||||
|
control_codes
|
||||||
|
| 0x20 .. 0x7e ${
|
||||||
|
uint8_t c = fc;
|
||||||
|
if (c & 0x40) c &= ~0x20;
|
||||||
|
screen->putc(c, _context);
|
||||||
|
if (cursor.x < window.maxX() - 1) cursor.x++;
|
||||||
|
}
|
||||||
|
| any
|
||||||
|
|
||||||
|
)** $err{ fgoto main; };
|
||||||
|
|
||||||
|
write data;
|
||||||
|
}%%
|
||||||
|
|
||||||
|
|
||||||
|
@implementation VT05
|
||||||
|
|
||||||
|
+(void)load {
|
||||||
|
[EmulatorManager registerClass: self];
|
||||||
|
}
|
||||||
|
|
||||||
|
+(NSString *)name {
|
||||||
|
return @"VT05";
|
||||||
|
}
|
||||||
|
|
||||||
|
-(NSString *)name {
|
||||||
|
return @"VT05";
|
||||||
|
}
|
||||||
|
|
||||||
|
-(const char *)termName {
|
||||||
|
return "vt05";
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)reset: (BOOL)hard {
|
||||||
|
|
||||||
|
%% write init;
|
||||||
|
if (hard) {
|
||||||
|
_context.cursor = iPoint(0,0);
|
||||||
|
_context.window = iRect(0, 0, 72, 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL)resizable {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(struct winsize)defaultSize {
|
||||||
|
struct winsize ws = { 20, 72, 0, 0 };
|
||||||
|
return ws;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-(id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
[self reset: YES];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)processData: (uint8_t *)data length: (size_t)length screen:(Screen *)screen output:(OutputChannel *)output
|
||||||
|
{
|
||||||
|
std::transform(data, data + length, data, [](uint8_t c){ return c & 0x7f; });
|
||||||
|
|
||||||
|
const uint8_t *eof = nullptr;
|
||||||
|
const uint8_t *p = data;
|
||||||
|
const uint8_t *pe = data + length;
|
||||||
|
|
||||||
|
iPoint &cursor = _context.cursor;
|
||||||
|
const iRect &window = _context.window;
|
||||||
|
|
||||||
|
%%write exec;
|
||||||
|
|
||||||
|
if (cursor.x == window.maxX()) screen->setCursor(iPoint(window.maxX() - 1, cursor.y));
|
||||||
|
else screen->setCursor(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-(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];
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
|
switch (uc)
|
||||||
|
{
|
||||||
|
case NSLeftArrowFunctionKey:
|
||||||
|
output->write(VTCursorLeft);
|
||||||
|
break;
|
||||||
|
case NSRightArrowFunctionKey:
|
||||||
|
output->write(VTCursorRight);
|
||||||
|
break;
|
||||||
|
case NSUpArrowFunctionKey:
|
||||||
|
output->write(VTCursorUp);
|
||||||
|
break;
|
||||||
|
case NSDownArrowFunctionKey:
|
||||||
|
output->write(VTCursorDown);
|
||||||
|
break;
|
||||||
|
case NSHomeFunctionKey:
|
||||||
|
output->write(VTHome);
|
||||||
|
break;
|
||||||
|
case NSDeleteCharacter:
|
||||||
|
output->write(0x7f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (uc > 0x7f) break;
|
||||||
|
c = uc;
|
||||||
|
|
||||||
|
if (flags & NSControlKeyMask)
|
||||||
|
{
|
||||||
|
c = CTRL(c);
|
||||||
|
}
|
||||||
|
output->write(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
33
Emulators/VT50.h
Normal file
33
Emulators/VT50.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// VT50.h
|
||||||
|
// TwoTerm
|
||||||
|
//
|
||||||
|
// Created by Kelvin Sherlock on 3/2/2018.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import "Emulator.h"
|
||||||
|
|
||||||
|
#include "iGeometry.h"
|
||||||
|
#include "Screen.h"
|
||||||
|
|
||||||
|
@interface VT50x : NSObject <Emulator> {
|
||||||
|
|
||||||
|
|
||||||
|
unsigned cs;
|
||||||
|
int _scratch[2];
|
||||||
|
context _context;
|
||||||
|
unsigned _model;
|
||||||
|
BOOL _altKeyPad;
|
||||||
|
BOOL _graphics;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface VT50 : VT50x
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface VT50H : VT50x
|
||||||
|
@end
|
447
Emulators/VT50.mm.ragel
Normal file
447
Emulators/VT50.mm.ragel
Normal file
@@ -0,0 +1,447 @@
|
|||||||
|
//
|
||||||
|
// VT50.m
|
||||||
|
// TwoTerm
|
||||||
|
//
|
||||||
|
// Created by Kelvin Sherlock on 3/2/2018.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <sys/ttydefaults.h>
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <numeric>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#import "VT50.h"
|
||||||
|
#include "OutputChannel.h"
|
||||||
|
#include "Screen.h"
|
||||||
|
|
||||||
|
#define ESC "\x1b"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ModelVT50,
|
||||||
|
ModelVT50H,
|
||||||
|
ModelVT52,
|
||||||
|
ModelVT55
|
||||||
|
};
|
||||||
|
namespace {
|
||||||
|
void normalize(iRect &r){
|
||||||
|
r.origin.y <<= 1;
|
||||||
|
r.size.height <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalize(iPoint &p) {
|
||||||
|
p.y <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%%{
|
||||||
|
machine vt50;
|
||||||
|
alphtype unsigned int;
|
||||||
|
|
||||||
|
|
||||||
|
esc = 0x1b;
|
||||||
|
|
||||||
|
|
||||||
|
action vt50h { _model == ModelVT50H }
|
||||||
|
action vt50 { _model == ModelVT50 }
|
||||||
|
|
||||||
|
|
||||||
|
action tab {
|
||||||
|
if (cursor.x < 72) cursor.x = (cursor.x + 8) & ~7;
|
||||||
|
else if (cursor.x < window.maxX() -1) cursor.x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
action linefeed {
|
||||||
|
if (cursor.y < window.maxY() - 1) cursor.y++;
|
||||||
|
else {
|
||||||
|
screen->scrollUp();
|
||||||
|
screen->scrollUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
action rlinefeed {
|
||||||
|
// this is documented as being vt52++
|
||||||
|
// however the 2BSD termcap entry (dating to 1980)
|
||||||
|
// and every termcap since claims 50h supports it...
|
||||||
|
if (cursor.y) cursor.y--;
|
||||||
|
else {
|
||||||
|
screen->scrollDown();
|
||||||
|
screen->scrollDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action erase_eos {
|
||||||
|
|
||||||
|
iRect tmp;
|
||||||
|
|
||||||
|
tmp.origin = cursor;
|
||||||
|
tmp.size = iSize( window.maxX() - cursor.x, 1);
|
||||||
|
normalize(tmp);
|
||||||
|
screen->eraseRect(tmp);
|
||||||
|
|
||||||
|
tmp.origin = iPoint(0, cursor.y+1);
|
||||||
|
tmp.size = iSize(window.maxX(), window.maxY() - cursor.y - 1);
|
||||||
|
normalize(tmp);
|
||||||
|
screen->eraseRect(tmp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
action erase_eol {
|
||||||
|
|
||||||
|
iRect tmp;
|
||||||
|
|
||||||
|
tmp.origin = cursor;
|
||||||
|
tmp.size = iSize( window.maxX() - cursor.x, 1);
|
||||||
|
normalize(tmp);
|
||||||
|
screen->eraseRect(tmp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
action identify {
|
||||||
|
// NB -- these indicate no copier.
|
||||||
|
switch(_model) {
|
||||||
|
case ModelVT50:
|
||||||
|
output->write(ESC "/A");
|
||||||
|
break;
|
||||||
|
case ModelVT50H:
|
||||||
|
output->write(ESC "/H");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action dca {
|
||||||
|
|
||||||
|
unsigned y = _scratch[0];
|
||||||
|
if (y >= window.maxY()) y = window.maxY() -1;
|
||||||
|
cursor.y = y;
|
||||||
|
|
||||||
|
unsigned x = _scratch[1];
|
||||||
|
if (x >= window.maxX()) x = window.maxX() -1;
|
||||||
|
cursor.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
action forward {
|
||||||
|
if (cursor.x > window.maxX()-1) {
|
||||||
|
cursor.x = window.minX();
|
||||||
|
if (cursor.y >= window.maxY()-1) {
|
||||||
|
screen->scrollUp();
|
||||||
|
screen->scrollUp();
|
||||||
|
} else {
|
||||||
|
cursor.y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
arg1 = any ${ _scratch[0] = ((fc & 0x7f) - 32); };
|
||||||
|
arg2 = any ${ _scratch[1] = ((fc & 0x7f) - 32); };
|
||||||
|
|
||||||
|
|
||||||
|
control_codes = (
|
||||||
|
0x07 ${ NSBeep(); }
|
||||||
|
| 0x08 ${ if (cursor.x) cursor.x--; }
|
||||||
|
| 0x09 $tab
|
||||||
|
| 0x0a $linefeed
|
||||||
|
| 0x0d ${ cursor.x = 0; }
|
||||||
|
| 0x0e when vt50 arg1 arg2 $dca
|
||||||
|
);
|
||||||
|
|
||||||
|
escape_codes = (
|
||||||
|
control_codes
|
||||||
|
| esc
|
||||||
|
| 'A' ${ if (cursor.y) cursor.y--; }
|
||||||
|
| 'B' when vt50h ${ if (cursor.y < window.maxY() -1) cursor.y++; }
|
||||||
|
| 'C' ${ if (cursor.x < window.maxX() -1) cursor.x++; }
|
||||||
|
| 'D' when vt50h ${ if (cursor.x) cursor.x--; }
|
||||||
|
#| 'F' when vt52_or_better ${ _graphics = true; }
|
||||||
|
#| 'G' when vt52_or_better ${ _graphics = false; }
|
||||||
|
| 'H' ${ cursor = iPoint(0, 0); }
|
||||||
|
| 'I' when vt50h $rlinefeed
|
||||||
|
| 'J' $erase_eos
|
||||||
|
| 'K' $erase_eol
|
||||||
|
| 'Y' when vt50h arg1 arg2 $dca
|
||||||
|
| 'Z' $identify
|
||||||
|
#| '=' when vt52_or_better ${ _altKeyPad = true; }
|
||||||
|
#| '>' when vt52_or_better ${ _altKeyPad = false; }
|
||||||
|
| any
|
||||||
|
);
|
||||||
|
|
||||||
|
main := (
|
||||||
|
control_codes
|
||||||
|
| esc escape_codes
|
||||||
|
| 0x20 .. 0x7e $forward ${
|
||||||
|
uint8_t c = fc;
|
||||||
|
if (c & 0x40) c &= ~0x20;
|
||||||
|
screen->putc(c, iPoint(cursor.x, cursor.y << 1), 0);
|
||||||
|
cursor.x++;
|
||||||
|
}
|
||||||
|
| any
|
||||||
|
)** $err { fgoto main; };
|
||||||
|
|
||||||
|
write data;
|
||||||
|
}%%
|
||||||
|
|
||||||
|
@implementation VT50x
|
||||||
|
|
||||||
|
|
||||||
|
-(BOOL)resizable
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(struct winsize)defaultSize
|
||||||
|
{
|
||||||
|
struct winsize ws = { 0, 0, 0, 0};
|
||||||
|
|
||||||
|
// VT50x have 12 rows. They are double spaced.
|
||||||
|
|
||||||
|
ws.ws_row = 12;
|
||||||
|
ws.ws_col = 80;
|
||||||
|
|
||||||
|
return ws;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
-(struct winsize)displaySize
|
||||||
|
{
|
||||||
|
struct winsize ws = { 0, 0, 0, 0};
|
||||||
|
|
||||||
|
// VT50x have 12 rows. They are double spaced.
|
||||||
|
|
||||||
|
ws.ws_row = 24;
|
||||||
|
ws.ws_col = 80;
|
||||||
|
|
||||||
|
return ws;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+(NSString *)name {
|
||||||
|
return @"";
|
||||||
|
}
|
||||||
|
|
||||||
|
-(NSString *)name {
|
||||||
|
return @"";
|
||||||
|
}
|
||||||
|
|
||||||
|
-(const char *)termName {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-(void)reset: (BOOL)hard
|
||||||
|
{
|
||||||
|
%% write init;
|
||||||
|
|
||||||
|
_altKeyPad = false;
|
||||||
|
_graphics = false;
|
||||||
|
|
||||||
|
if (hard) {
|
||||||
|
_context.cursor = iPoint(0,0);
|
||||||
|
_context.window = iRect(0, 0, 80, 12);
|
||||||
|
}
|
||||||
|
_context.flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(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];
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
|
|
||||||
|
if (flags & NSNumericPadKeyMask)
|
||||||
|
{
|
||||||
|
if (_altKeyPad)
|
||||||
|
{
|
||||||
|
const char *str = NULL;
|
||||||
|
switch (uc)
|
||||||
|
{
|
||||||
|
case '0':
|
||||||
|
str = ESC "?p";
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
str = ESC "?q";
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
str = ESC "?r";
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
str = ESC "?s";
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
str = ESC "?t";
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
str = ESC "?u";
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
str = ESC "?v";
|
||||||
|
break;
|
||||||
|
case '7':
|
||||||
|
str = ESC "?w";
|
||||||
|
break;
|
||||||
|
case '8':
|
||||||
|
str = ESC "?x";
|
||||||
|
break;
|
||||||
|
case '9':
|
||||||
|
str = ESC "?y";
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
str = ESC "?n";
|
||||||
|
break;
|
||||||
|
case NSNewlineCharacter: //?
|
||||||
|
case NSEnterCharacter:
|
||||||
|
str = ESC "?M";
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (str)
|
||||||
|
{
|
||||||
|
output->write(str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch (uc)
|
||||||
|
{
|
||||||
|
case NSEnterCharacter:
|
||||||
|
output->write('\r');
|
||||||
|
break;
|
||||||
|
case NSDeleteCharacter:
|
||||||
|
output->write(0x7f);
|
||||||
|
break;
|
||||||
|
case NSUpArrowFunctionKey:
|
||||||
|
output->write(ESC "A");
|
||||||
|
break;
|
||||||
|
case NSDownArrowFunctionKey:
|
||||||
|
output->write(ESC "B");
|
||||||
|
break;
|
||||||
|
case NSRightArrowFunctionKey:
|
||||||
|
output->write(ESC "C");
|
||||||
|
break;
|
||||||
|
case NSLeftArrowFunctionKey:
|
||||||
|
output->write(ESC "D");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 3 function keys. (VT50H / VT52)
|
||||||
|
case NSF1FunctionKey:
|
||||||
|
output->write(ESC "P");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSF2FunctionKey:
|
||||||
|
output->write(ESC "Q");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSF3FunctionKey:
|
||||||
|
output->write(ESC "R");
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (uc > 0x7f) break;
|
||||||
|
c = uc;
|
||||||
|
|
||||||
|
if (flags & (NSShiftKeyMask | NSAlphaShiftKeyMask))
|
||||||
|
{
|
||||||
|
c = toupper(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & NSControlKeyMask)
|
||||||
|
{
|
||||||
|
c = CTRL(c);
|
||||||
|
}
|
||||||
|
output->write(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)processData: (uint8_t *)data length: (size_t)length screen:(Screen *)screen output:(OutputChannel *)output
|
||||||
|
{
|
||||||
|
std::transform(data, data + length, data, [](uint8_t c){ return c & 0x7f; });
|
||||||
|
|
||||||
|
const uint8_t *eof = nullptr;
|
||||||
|
const uint8_t *p = data;
|
||||||
|
const uint8_t *pe = std::copy_if(data, data + length, data, [](uint8_t c){
|
||||||
|
if (c == 0 || c == 0x7f) return false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
iPoint &cursor = _context.cursor;
|
||||||
|
const iRect &window = _context.window;
|
||||||
|
|
||||||
|
%%write exec;
|
||||||
|
|
||||||
|
auto cc = cursor;
|
||||||
|
cc.y <<= 1;
|
||||||
|
if (cc.x == 80) cc.x = 79;
|
||||||
|
screen->setCursor(cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation VT50
|
||||||
|
|
||||||
|
+(void)load {
|
||||||
|
[EmulatorManager registerClass: self];
|
||||||
|
}
|
||||||
|
|
||||||
|
+(NSString *)name {
|
||||||
|
return @"VT50";
|
||||||
|
}
|
||||||
|
-(NSString *)name {
|
||||||
|
return @"VT50";
|
||||||
|
}
|
||||||
|
|
||||||
|
-(const char *)termName {
|
||||||
|
return "vt50";
|
||||||
|
}
|
||||||
|
|
||||||
|
-(id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
_model = ModelVT50;
|
||||||
|
[self reset: YES];
|
||||||
|
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@implementation VT50H
|
||||||
|
|
||||||
|
+(void)load {
|
||||||
|
[EmulatorManager registerClass: self];
|
||||||
|
}
|
||||||
|
|
||||||
|
+(NSString *)name {
|
||||||
|
return @"VT50H";
|
||||||
|
}
|
||||||
|
-(NSString *)name {
|
||||||
|
return @"VT50H";
|
||||||
|
}
|
||||||
|
|
||||||
|
-(const char *)termName {
|
||||||
|
return "vt50h";
|
||||||
|
}
|
||||||
|
|
||||||
|
-(id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
_model = ModelVT50H;
|
||||||
|
[self reset: YES];
|
||||||
|
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
@@ -28,11 +28,14 @@
|
|||||||
@interface VT52 : VT5x
|
@interface VT52 : VT5x
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
/*
|
||||||
@interface VT50H : VT5x
|
@interface VT50H : VT5x
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@interface VT50 : VT5x
|
@interface VT50 : VT5x
|
||||||
@end
|
@end
|
||||||
|
*/
|
||||||
|
|
||||||
@interface VT55 : VT5x
|
@interface VT55 : VT5x
|
||||||
@end
|
@end
|
||||||
|
@@ -43,7 +43,7 @@ enum {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
@implementation VT50
|
@implementation VT50
|
||||||
|
|
||||||
+(void)load {
|
+(void)load {
|
||||||
@@ -119,6 +119,8 @@ enum {
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@implementation VT52
|
@implementation VT52
|
||||||
|
|
||||||
+(void)load {
|
+(void)load {
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
B67B3CE512B6FA040033AE07 /* a2-charset-40.png in Resources */ = {isa = PBXBuildFile; fileRef = B67B3CE312B6FA040033AE07 /* a2-charset-40.png */; };
|
B67B3CE512B6FA040033AE07 /* a2-charset-40.png in Resources */ = {isa = PBXBuildFile; fileRef = B67B3CE312B6FA040033AE07 /* a2-charset-40.png */; };
|
||||||
B67B3CE612B6FA040033AE07 /* a2-charset-80.png in Resources */ = {isa = PBXBuildFile; fileRef = B67B3CE412B6FA040033AE07 /* a2-charset-80.png */; };
|
B67B3CE612B6FA040033AE07 /* a2-charset-80.png in Resources */ = {isa = PBXBuildFile; fileRef = B67B3CE412B6FA040033AE07 /* a2-charset-80.png */; };
|
||||||
B6801BD912EB549300B22E9E /* vt100-charset.png in Resources */ = {isa = PBXBuildFile; fileRef = B6801BD812EB549300B22E9E /* vt100-charset.png */; };
|
B6801BD912EB549300B22E9E /* vt100-charset.png in Resources */ = {isa = PBXBuildFile; fileRef = B6801BD812EB549300B22E9E /* vt100-charset.png */; };
|
||||||
|
B683F7102049E7B000470B99 /* VT50.mm.ragel in Sources */ = {isa = PBXBuildFile; fileRef = B683F70F2049E7B000470B99 /* VT50.mm.ragel */; };
|
||||||
B68E632A12FF909D00EAFF5F /* ExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = B68E632912FF909C00EAFF5F /* ExampleView.m */; };
|
B68E632A12FF909D00EAFF5F /* ExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = B68E632912FF909C00EAFF5F /* ExampleView.m */; };
|
||||||
B69D0FBA202799B10073CCB7 /* TermConfig.xib in Resources */ = {isa = PBXBuildFile; fileRef = B69D0FB8202799B10073CCB7 /* TermConfig.xib */; };
|
B69D0FBA202799B10073CCB7 /* TermConfig.xib in Resources */ = {isa = PBXBuildFile; fileRef = B69D0FB8202799B10073CCB7 /* TermConfig.xib */; };
|
||||||
B69E32A920221C9E0086D7B1 /* ChildMonitor.mm in Sources */ = {isa = PBXBuildFile; fileRef = B69E32A820221C9E0086D7B1 /* ChildMonitor.mm */; };
|
B69E32A920221C9E0086D7B1 /* ChildMonitor.mm in Sources */ = {isa = PBXBuildFile; fileRef = B69E32A820221C9E0086D7B1 /* ChildMonitor.mm */; };
|
||||||
@@ -176,6 +177,9 @@
|
|||||||
B67B3CE312B6FA040033AE07 /* a2-charset-40.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "a2-charset-40.png"; sourceTree = "<group>"; };
|
B67B3CE312B6FA040033AE07 /* a2-charset-40.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "a2-charset-40.png"; sourceTree = "<group>"; };
|
||||||
B67B3CE412B6FA040033AE07 /* a2-charset-80.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "a2-charset-80.png"; sourceTree = "<group>"; };
|
B67B3CE412B6FA040033AE07 /* a2-charset-80.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "a2-charset-80.png"; sourceTree = "<group>"; };
|
||||||
B6801BD812EB549300B22E9E /* vt100-charset.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "vt100-charset.png"; sourceTree = "<group>"; };
|
B6801BD812EB549300B22E9E /* vt100-charset.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "vt100-charset.png"; sourceTree = "<group>"; };
|
||||||
|
B683F70E2049E7B000470B99 /* VT50.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VT50.h; sourceTree = "<group>"; };
|
||||||
|
B683F70F2049E7B000470B99 /* VT50.mm.ragel */ = {isa = PBXFileReference; lastKnownFileType = text; path = VT50.mm.ragel; sourceTree = "<group>"; };
|
||||||
|
B683F711204AE32900470B99 /* VT05.mm.ragel */ = {isa = PBXFileReference; lastKnownFileType = text; path = VT05.mm.ragel; sourceTree = "<group>"; };
|
||||||
B68E632812FF909C00EAFF5F /* ExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleView.h; sourceTree = "<group>"; };
|
B68E632812FF909C00EAFF5F /* ExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleView.h; sourceTree = "<group>"; };
|
||||||
B68E632912FF909C00EAFF5F /* ExampleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleView.m; sourceTree = "<group>"; };
|
B68E632912FF909C00EAFF5F /* ExampleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleView.m; sourceTree = "<group>"; };
|
||||||
B69D0FB9202799B10073CCB7 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/TermConfig.xib; sourceTree = "<group>"; };
|
B69D0FB9202799B10073CCB7 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/TermConfig.xib; sourceTree = "<group>"; };
|
||||||
@@ -367,10 +371,13 @@
|
|||||||
B612F45D12DD5DF1005D1B77 /* PTSE.mm.ragel */,
|
B612F45D12DD5DF1005D1B77 /* PTSE.mm.ragel */,
|
||||||
B612F45E12DD5DF1005D1B77 /* VT05.h */,
|
B612F45E12DD5DF1005D1B77 /* VT05.h */,
|
||||||
B612F45F12DD5DF1005D1B77 /* VT05.mm */,
|
B612F45F12DD5DF1005D1B77 /* VT05.mm */,
|
||||||
|
B683F711204AE32900470B99 /* VT05.mm.ragel */,
|
||||||
B612F46012DD5DF1005D1B77 /* VT100.h */,
|
B612F46012DD5DF1005D1B77 /* VT100.h */,
|
||||||
B612F46112DD5DF1005D1B77 /* VT100.mm */,
|
B612F46112DD5DF1005D1B77 /* VT100.mm */,
|
||||||
B612F46212DD5DF1005D1B77 /* VT52.h */,
|
B612F46212DD5DF1005D1B77 /* VT52.h */,
|
||||||
B612F46312DD5DF1005D1B77 /* VT52.mm */,
|
B612F46312DD5DF1005D1B77 /* VT52.mm */,
|
||||||
|
B683F70E2049E7B000470B99 /* VT50.h */,
|
||||||
|
B683F70F2049E7B000470B99 /* VT50.mm.ragel */,
|
||||||
);
|
);
|
||||||
path = Emulators;
|
path = Emulators;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -545,6 +552,7 @@
|
|||||||
B675F4AC1E56A7F2004B0D9C /* GSOSConsole.mm.ragel in Sources */,
|
B675F4AC1E56A7F2004B0D9C /* GSOSConsole.mm.ragel in Sources */,
|
||||||
B6D1CD071E577E7D00C4A6BC /* PTSE.mm.ragel in Sources */,
|
B6D1CD071E577E7D00C4A6BC /* PTSE.mm.ragel in Sources */,
|
||||||
B6C21CD62033580200671774 /* RolloverButton.m in Sources */,
|
B6C21CD62033580200671774 /* RolloverButton.m in Sources */,
|
||||||
|
B683F7102049E7B000470B99 /* VT50.mm.ragel in Sources */,
|
||||||
B69E32A920221C9E0086D7B1 /* ChildMonitor.mm in Sources */,
|
B69E32A920221C9E0086D7B1 /* ChildMonitor.mm in Sources */,
|
||||||
B6407805201CE93500D3F2D1 /* GNOConsole.mm.ragel in Sources */,
|
B6407805201CE93500D3F2D1 /* GNOConsole.mm.ragel in Sources */,
|
||||||
8D11072D0486CEB800E47090 /* main.m in Sources */,
|
8D11072D0486CEB800E47090 /* main.m in Sources */,
|
||||||
|
Reference in New Issue
Block a user