Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
43cb3c9e4f | ||
|
6cb2b91ac0 | ||
|
8a5f5a9e61 | ||
|
b1340d2a56 | ||
|
5a971ac08c | ||
|
254dfd548e | ||
|
bd6d13e51b | ||
|
54335e2e3b | ||
|
98dc438fa5 | ||
|
ceb1349199 | ||
|
22266914ed | ||
|
542dddd335 | ||
|
6b28a1e170 | ||
|
fd50370e8d | ||
|
92d89dd630 | ||
|
6f409db93e | ||
|
30df8aef9e | ||
|
99f5d60be8 | ||
|
020b095542 | ||
|
bcf03e124b | ||
|
0bc20c6fa8 | ||
|
e7ebb7b573 | ||
|
b766854f80 | ||
|
5b8c8fec17 | ||
|
92e1805694 | ||
|
24248e768b | ||
|
01c89f4715 | ||
|
bf7e733e8b | ||
|
49b165a56d |
21
.github/workflows/xcodebuild.yml
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
name: xcodebuild
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: brew
|
||||
run: brew install ragel
|
||||
- name: xcodebuild
|
||||
run: xcodebuild -target TwoTerm | xcpretty
|
|
@ -63,8 +63,8 @@
|
|||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="83">
|
||||
<menu key="submenu" title="File" id="81">
|
||||
<menuItem title="Shell" id="83">
|
||||
<menu key="submenu" title="Shell" id="81">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="82">
|
||||
<connections>
|
||||
|
@ -112,6 +112,19 @@
|
|||
<action selector="revertDocumentToSaved:" target="-1" id="364"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="1Bf-fE-VAI"/>
|
||||
<menuItem title="Reset" keyEquivalent="r" id="h3z-Y4-dyj">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="resetTerminal:" target="-1" id="Afh-EL-aOa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hard Reset" keyEquivalent="r" id="CX0-e3-Dg4">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hardResetTerminal:" target="-1" id="bVS-nP-oag"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="74">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
|
@ -236,9 +236,24 @@
|
|||
</subviews>
|
||||
</view>
|
||||
</box>
|
||||
<button misplaced="YES" id="b5f-6s-ZI2">
|
||||
<rect key="frame" x="451" y="357" width="24" height="24"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="TabClose" imagePosition="only" alignment="center" alternateImage="TabClose_Pressed" inset="2" id="Fi8-z7-gn2">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="performClose:" target="Ezq-gE-d2Y" id="CcO-2x-8Vw"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<point key="canvasLocation" x="-521" y="413"/>
|
||||
</view>
|
||||
<userDefaultsController representsSharedInstance="YES" id="mq9-aV-tAe"/>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="TabClose" width="12" height="13"/>
|
||||
<image name="TabClose_Pressed" width="12" height="13"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -8,15 +8,24 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
enum {
|
||||
CGApple80,
|
||||
CGApple40,
|
||||
CGVT52,
|
||||
CGVT100
|
||||
};
|
||||
|
||||
@interface CharacterGenerator : NSObject
|
||||
{
|
||||
CGImageRef _image;
|
||||
NSMutableArray *_characters;
|
||||
NSImage *_image;
|
||||
NSImage *_characters[256];
|
||||
NSSize _size;
|
||||
}
|
||||
|
||||
+(CharacterGenerator *)generator;
|
||||
+(CharacterGenerator *)generatorForCharacterSet: (unsigned)characterSet;
|
||||
|
||||
|
||||
|
||||
@property (nonatomic, readonly) NSSize characterSize;
|
||||
|
||||
|
|
|
@ -10,10 +10,16 @@
|
|||
|
||||
#import "CharacterGenerator.h"
|
||||
|
||||
@interface CharacterGenerator ()
|
||||
-(void)loadImageNamed: (NSString *)imageName;
|
||||
-(id)initWithImageNamed: (NSString *)imageName;
|
||||
@end
|
||||
|
||||
@implementation CharacterGenerator
|
||||
|
||||
@synthesize characterSize = _size;
|
||||
|
||||
#if 0
|
||||
static CGImageRef PNGImage(NSString *path)
|
||||
{
|
||||
CGImageRef image = NULL;
|
||||
|
@ -31,89 +37,117 @@ static CGImageRef PNGImage(NSString *path)
|
|||
|
||||
return image;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+(CharacterGenerator *)generatorForCharacterSet: (unsigned)characterSet {
|
||||
|
||||
static CharacterGenerator *singletons[4] = {};
|
||||
static NSString *names[] = {
|
||||
@"a2-charset-80",
|
||||
@"a2-charset-40",
|
||||
@"vt52-charset",
|
||||
@"vt100-charset",
|
||||
};
|
||||
|
||||
constexpr unsigned MaxCharSet = sizeof(names) / sizeof(names[0]);
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
for (unsigned i = 0; i < MaxCharSet; ++i)
|
||||
singletons[i] = [[CharacterGenerator alloc] initWithImageNamed: names[i]];
|
||||
});
|
||||
if (characterSet >= MaxCharSet) return nil;
|
||||
return singletons[characterSet];
|
||||
}
|
||||
|
||||
|
||||
+(id)generator
|
||||
{
|
||||
return [[self new] autorelease];
|
||||
return [self generatorForCharacterSet: CGApple80];
|
||||
}
|
||||
|
||||
-(id)init
|
||||
{
|
||||
|
||||
-(id)initWithImageNamed: (NSString *)imageName {
|
||||
if ((self = [super init]))
|
||||
{
|
||||
NSBundle *mainBundle;
|
||||
NSString *imagePath;
|
||||
|
||||
CGImageRef mask;
|
||||
CGImageRef src;
|
||||
NSSize size;
|
||||
|
||||
|
||||
mainBundle = [NSBundle mainBundle];
|
||||
|
||||
imagePath = [mainBundle pathForResource: @"a2-charset-80" ofType: @"png"];
|
||||
//imagePath = [mainBundle pathForResource: @"vt100-charset" ofType: @"png"];
|
||||
//imagePath = [mainBundle pathForResource: @"vt52-charset" ofType: @"png"];
|
||||
|
||||
|
||||
|
||||
_characters = [[NSMutableArray alloc] initWithCapacity: 256];
|
||||
_size = NSMakeSize(7, 16);
|
||||
|
||||
|
||||
src = PNGImage(imagePath);
|
||||
|
||||
size.width = CGImageGetWidth(src);
|
||||
size.height = CGImageGetHeight(src);
|
||||
|
||||
size.width /= 16;
|
||||
size.height /= 16;
|
||||
|
||||
_size = size;
|
||||
|
||||
if (src)
|
||||
{
|
||||
mask = CGImageMaskCreate(CGImageGetWidth(src),
|
||||
CGImageGetHeight(src),
|
||||
CGImageGetBitsPerComponent(src),
|
||||
CGImageGetBitsPerPixel(src),
|
||||
CGImageGetBytesPerRow(src),
|
||||
CGImageGetDataProvider(src),
|
||||
NULL, NO);
|
||||
|
||||
|
||||
for (unsigned i = 0; i < 16; ++i)
|
||||
{
|
||||
for (unsigned j = 0; j < 16; ++j)
|
||||
{
|
||||
CGImageRef cgimg = CGImageCreateWithImageInRect(mask, CGRectMake(j * _size.width, i * _size.height, _size.width, _size.height));
|
||||
NSImage *nsimg = [[NSImage alloc] initWithCGImage: cgimg size: _size];
|
||||
[_characters addObject: nsimg];
|
||||
|
||||
CGImageRelease(cgimg);
|
||||
[nsimg release];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CGImageRelease(src);
|
||||
CGImageRelease(mask);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
[self loadImageNamed: imageName];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This loads the image then split it up into 256 images.
|
||||
*
|
||||
* All representations are handled so it retins any @2x artwork.
|
||||
*
|
||||
*/
|
||||
-(void)loadImageNamed:(NSString *)imageName {
|
||||
|
||||
|
||||
_image = [[NSImage imageNamed: imageName] retain];
|
||||
|
||||
_size = [_image size];
|
||||
|
||||
_size.width /= 16;
|
||||
_size.height /= 16;
|
||||
|
||||
for (unsigned i = 0; i < sizeof(_characters) / sizeof(_characters[0]); ++i)
|
||||
_characters[i] = [[NSImage alloc] initWithSize: _size];
|
||||
|
||||
for (NSImageRep *rep in [_image representations]) {
|
||||
|
||||
CGImageRef mask;
|
||||
CGImageRef src;
|
||||
NSSize size;
|
||||
|
||||
/* src will auto release */
|
||||
src = [rep CGImageForProposedRect: NULL context: nil hints: nil];
|
||||
|
||||
|
||||
size.width = CGImageGetWidth(src) / 16;
|
||||
size.height = CGImageGetHeight(src) / 16;
|
||||
|
||||
mask = CGImageMaskCreate(CGImageGetWidth(src),
|
||||
CGImageGetHeight(src),
|
||||
CGImageGetBitsPerComponent(src),
|
||||
CGImageGetBitsPerPixel(src),
|
||||
CGImageGetBytesPerRow(src),
|
||||
CGImageGetDataProvider(src),
|
||||
NULL, NO);
|
||||
|
||||
|
||||
|
||||
for (unsigned i = 0; i < 16; ++i)
|
||||
{
|
||||
for (unsigned j = 0; j < 16; ++j)
|
||||
{
|
||||
CGImageRef cgimg = CGImageCreateWithImageInRect(mask, CGRectMake(j * size.width, i * size.height, size.width, size.height));
|
||||
|
||||
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithCGImage: cgimg];
|
||||
|
||||
NSImage *nsimg = _characters[i * 16 + j];
|
||||
[nsimg addRepresentation: rep];
|
||||
[rep release];
|
||||
CGImageRelease(cgimg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CGImageRelease(mask);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
if (_image) CGImageRelease(_image);
|
||||
[_characters release];
|
||||
[_image release];
|
||||
for (auto &o : _characters) [o release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
@ -121,14 +155,17 @@ static CGImageRef PNGImage(NSString *path)
|
|||
|
||||
-(NSImage *)imageForCharacter: (unsigned)character
|
||||
{
|
||||
if (character > [_characters count]) return nil;
|
||||
if (character >= sizeof(_characters) / sizeof(_characters[0])) return nil;
|
||||
|
||||
return (NSImage *)[_characters objectAtIndex: character];
|
||||
return _characters[character];
|
||||
}
|
||||
|
||||
-(void)drawCharacter: (unsigned)character atPoint: (NSPoint)point
|
||||
{
|
||||
NSImage *img = [self imageForCharacter: character];
|
||||
|
||||
if (character >= sizeof(_characters) / sizeof(_characters[0])) return;
|
||||
|
||||
NSImage *img = _characters[character];
|
||||
|
||||
if (!img) return;
|
||||
|
||||
|
|
24
Defaults.plist
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<array>
|
||||
<dict>
|
||||
<key>Name</key>
|
||||
<string>Green Black</string>
|
||||
<key>Foreground</key>
|
||||
<integer>65280</integer>
|
||||
<key>Background</key>
|
||||
<integer>0</integer>
|
||||
<key>Effects</key>
|
||||
<false/>
|
||||
<key>Bloom</key>
|
||||
<integer>0</integer>
|
||||
<key>Backlight</key>
|
||||
<integer>0</integer>
|
||||
<key>Scanlines</key>
|
||||
<integer>0</integer>
|
||||
<key>Vignette</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
</plist>
|
33
Emulators/Apple3.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Apple3.h
|
||||
// 2Term
|
||||
//
|
||||
// Created by Kelvin Sherlock on 12/24/2018.
|
||||
// Copyright 2018 __MyCompanyName__. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "Emulator.h"
|
||||
#include "iGeometry.h"
|
||||
#include "Screen.h"
|
||||
|
||||
|
||||
struct iii_context : public context {
|
||||
unsigned cursor_control = 0b1101;
|
||||
unsigned fg_color = 0;
|
||||
unsigned bg_color = 0;
|
||||
unsigned mode = 2;
|
||||
};
|
||||
|
||||
@interface Apple3 : NSObject <Emulator>
|
||||
{
|
||||
unsigned cs;
|
||||
iii_context _context;
|
||||
iii_context _saved_context;
|
||||
Screen::CursorType _cursorType;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@end
|
466
Emulators/Apple3.mm.ragel
Normal file
|
@ -0,0 +1,466 @@
|
|||
//
|
||||
// Apple3.mm
|
||||
// 2Term
|
||||
//
|
||||
// Created by Kelvin Sherlock on 12/24/2018.
|
||||
// Copyright 2010 __MyCompanyName__. All rights reserved.
|
||||
//
|
||||
|
||||
/*
|
||||
* See Apple III Standard Device Drivers Manual (ch 3, The Console Driver)
|
||||
* Also implemented via AppleWorks (which started life as III EZ Pieces)
|
||||
*
|
||||
* Apple III console can be 24 x 40 (BW), 24 x 40 (16 color), or 24 x 80 (BW).
|
||||
*
|
||||
*/
|
||||
|
||||
#import "Apple3.h"
|
||||
|
||||
#include <sys/ttydefaults.h>
|
||||
|
||||
#include "OutputChannel.h"
|
||||
#include "Screen.h"
|
||||
#include "algorithm.h"
|
||||
|
||||
#import "CharacterGenerator.h"
|
||||
|
||||
enum {
|
||||
kAdvance = 1 << 0,
|
||||
kLineFeed = 1 << 1,
|
||||
kWrap = 1 << 2,
|
||||
kScroll = 1 << 3,
|
||||
};
|
||||
|
||||
%%{
|
||||
machine console;
|
||||
alphtype unsigned int;
|
||||
|
||||
action nop {}
|
||||
|
||||
action advance {
|
||||
// advance cursor
|
||||
if (_context.cursor_control & kAdvance) {
|
||||
|
||||
|
||||
switch (_context.cursor_control & (kWrap | kScroll)) {
|
||||
default:
|
||||
if (cursor.x < window.maxX() - 1) ++cursor.x;
|
||||
break;
|
||||
case kWrap:
|
||||
if (cursor.x < window.maxX() - 1) ++cursor.x;
|
||||
else {
|
||||
cursor.x = window.minX();
|
||||
if (cursor.y < window.maxY() - 1) ++cursor.y;
|
||||
}
|
||||
break;
|
||||
case kWrap | kScroll:
|
||||
if (cursor.x < window.maxX() - 1) ++cursor.x;
|
||||
else {
|
||||
cursor.x = window.minX();
|
||||
if (cursor.y < window.maxY() - 1) ++cursor.y;
|
||||
else screen->scrollUp(window);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
action setx {
|
||||
/* horizontal position */
|
||||
int x = (unsigned)fc;
|
||||
x += window.minX();
|
||||
cursor.x = std::min(x, window.maxX() - 1);
|
||||
}
|
||||
|
||||
action sety {
|
||||
/* vertical position */
|
||||
int y = (unsigned)fc;
|
||||
y += window.minY();
|
||||
cursor.y = std::min(y, window.maxY() - 1);
|
||||
}
|
||||
|
||||
# arg1 = any ${ _scratch[0] = fc; };
|
||||
# arg2 = any ${ _scratch[1] = fc; };
|
||||
|
||||
|
||||
|
||||
|
||||
main := (
|
||||
0x00 $nop
|
||||
| 0x01 ${
|
||||
/* save viewport and reset */
|
||||
_saved_context = _context;
|
||||
window = iRect(0, 0, 80, 24);
|
||||
/* currently ignores mode */
|
||||
}
|
||||
| 0x02 ${
|
||||
/* set viewport top */
|
||||
iPoint tl = cursor;
|
||||
iPoint br = window.bottomRight();
|
||||
_context.window = iRect(tl, br);
|
||||
}
|
||||
| 0x03 ${
|
||||
/* set viewport bottom */
|
||||
iPoint tl = _context.window.topLeft();
|
||||
iPoint br = _context.cursor.offset(1,1);
|
||||
_context.window = iRect(tl, br);
|
||||
}
|
||||
| 0x04 ${
|
||||
/* restore viewport */
|
||||
_context = _saved_context;
|
||||
}
|
||||
|
||||
| 0x05 ${
|
||||
/* E - $05 - Turns cursor on (enables cursor display) */
|
||||
screen->setCursorType(Screen::CursorTypeUnderscore);
|
||||
}
|
||||
|
||||
| 0x06 ${
|
||||
/* F - $06 - Turns cursor off (disables cursor display) */
|
||||
screen->setCursorType(Screen::CursorTypeNone);
|
||||
}
|
||||
|
||||
| 0x07 ${
|
||||
/* Beep */
|
||||
NSBeep();
|
||||
}
|
||||
|
||||
| 0x08 ${
|
||||
/* Moves cursor left */
|
||||
|
||||
if (cursor.x > window.minX()) --cursor.x;
|
||||
else if (_context.cursor_control & kWrap) {
|
||||
cursor.x = window.maxX() - 1;
|
||||
|
||||
if (cursor.y > window.minY()) --cursor.y;
|
||||
else if (_context.cursor_control & kScroll) {
|
||||
screen->scrollDown(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
| 0x09 ${
|
||||
/* move cursor right */
|
||||
|
||||
if (cursor.x < window.maxX()-1) ++cursor.x;
|
||||
else if (_context.cursor_control & kWrap) {
|
||||
cursor.x = window.minX();
|
||||
|
||||
if (cursor.y < window.maxY()-1) ++cursor.y;
|
||||
else if (_context.cursor_control & kScroll) {
|
||||
screen->scrollUp(window);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
| 0x0a ${
|
||||
/* move cursor down */
|
||||
if (cursor.y < window.maxY() - 1) ++cursor.y;
|
||||
else if (_context.cursor_control & kScroll) {
|
||||
screen->scrollUp(window);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
| 0x0b ${
|
||||
/* move cursor up */
|
||||
if (cursor.y > window.minY()) --cursor.y;
|
||||
else if (_context.cursor_control & kScroll) {
|
||||
screen->scrollDown(window);
|
||||
}
|
||||
}
|
||||
|
||||
| 0x0c ${
|
||||
/* home */
|
||||
cursor = iPoint(window.topLeft());
|
||||
}
|
||||
|
||||
| 0x0d ${
|
||||
/* carriage return */
|
||||
/* also LF depending on cursor motion */
|
||||
cursor.x = window.minX();
|
||||
if (_context.cursor_control & kLineFeed) {
|
||||
|
||||
if (cursor.y < window.maxY() - 1) ++cursor.y;
|
||||
else if (_context.cursor_control & kScroll) {
|
||||
screen->scrollUp(window);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
| 0x0e ${
|
||||
/* turn screen off ... */
|
||||
}
|
||||
|
||||
| 0x0f ${
|
||||
/* turn screen on ... */
|
||||
}
|
||||
|
||||
| 0x10 any ${
|
||||
/* set text mode (40 vs 80, color vs bw) */
|
||||
_context.mode = fc & 0x03;
|
||||
}
|
||||
|
||||
| 0x11 ${
|
||||
/* normal text */
|
||||
_context.clearFlagBit(Screen::FlagInverse);
|
||||
}
|
||||
| 0x12 ${
|
||||
/* invert text */
|
||||
_context.setFlagBit(Screen::FlagInverse);
|
||||
}
|
||||
|
||||
| 0x13 any ${
|
||||
/* set foreground text color */
|
||||
_context.fg_color = fc & 0x0f;
|
||||
}
|
||||
|
||||
| 0x14 any ${
|
||||
/* set background text color */
|
||||
_context.bg_color = fc & 0x0f;
|
||||
}
|
||||
|
||||
| 0x15 any ${
|
||||
/* set cursor motion control */
|
||||
_context.cursor_control = fc & 0x0f;
|
||||
}
|
||||
|
||||
# sync
|
||||
| 0x16 $nop
|
||||
|
||||
| 0x17 any ${
|
||||
/* horizontal shift */
|
||||
int count = (int8_t)fc;
|
||||
/* if > 0, shift right */
|
||||
if (count > 0) screen->scrollRight(window, count);
|
||||
/* if < 0, shift left */
|
||||
if (count < 0) screen->scrollLeft(window, -count);
|
||||
}
|
||||
|
||||
# horizontal position
|
||||
| 0x18 any $setx
|
||||
# vertical position
|
||||
| 0x19 any $sety
|
||||
# horizontal + vertical position
|
||||
| 0x1a any $setx any $sety
|
||||
|
||||
# esc - reserved
|
||||
| 0x1b $nop
|
||||
|
||||
| 0x1c ${
|
||||
/* HOME + clear viewport */
|
||||
cursor = window.topLeft();
|
||||
screen->eraseRect(window);
|
||||
}
|
||||
|
||||
| 0x1d ${
|
||||
/* clear to end of viewport */
|
||||
iRect r(cursor, window.bottomRight());
|
||||
r.size.height = 1;
|
||||
screen->eraseRect(r);
|
||||
|
||||
r = iRect(window.minX(), cursor.y + 1, window.width(), window.maxY() - cursor.y - 1);
|
||||
screen->eraseRect(r);
|
||||
}
|
||||
|
||||
| 0x1e ${
|
||||
/* move to left edge of viewport, clear line */
|
||||
cursor.y = window.minY();
|
||||
iRect r(cursor, window.bottomRight());
|
||||
r.size.height = 1;
|
||||
screen->eraseRect(r);
|
||||
}
|
||||
|
||||
| 0x1f ${
|
||||
/* clear to end of line */
|
||||
iRect r(cursor, window.bottomRight());
|
||||
r.size.height = 1;
|
||||
screen->eraseRect(r);
|
||||
|
||||
}
|
||||
|
||||
| 0x20 .. 0x7f ${
|
||||
screen->putc(fc, _context);
|
||||
} $advance
|
||||
|
||||
| 0x80 .. 0x9f ${
|
||||
/* display control char? */
|
||||
}
|
||||
| 0xa0 .. 0xff ${
|
||||
screen->putc(fc & 0x7f, _context);
|
||||
} $advance
|
||||
|
||||
|
||||
)* $err{ fgoto main; };
|
||||
|
||||
write data;
|
||||
}%%
|
||||
|
||||
@implementation Apple3
|
||||
|
||||
+(void)load {
|
||||
[EmulatorManager registerClass: self];
|
||||
}
|
||||
|
||||
- (NSString *)name {
|
||||
return @"Apple III";
|
||||
}
|
||||
|
||||
|
||||
+ (NSString *)name {
|
||||
return @"Apple III";
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (const char *)termName {
|
||||
return "appleIII";
|
||||
}
|
||||
|
||||
|
||||
-(void)reset: (BOOL)hard
|
||||
{
|
||||
|
||||
%%write init;
|
||||
_context.flags = 0;
|
||||
_cursorType = Screen::CursorTypeUnderscore;
|
||||
|
||||
_context.fg_color = 15; /* white */
|
||||
_context.bg_color = 0; /* black */
|
||||
_context.cursor_control = kScroll | kWrap | kAdvance;
|
||||
|
||||
if (hard) {
|
||||
_context.window = iRect(0, 0, 80, 24);
|
||||
_context.cursor = iPoint(0,0);
|
||||
_context.mode = 2;
|
||||
|
||||
_saved_context = iii_context();
|
||||
}
|
||||
}
|
||||
|
||||
-(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');
|
||||
// tab is right arrow, so expand to spaces.
|
||||
term->c_oflag |= OXTABS;
|
||||
}
|
||||
|
||||
-(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
|
||||
{
|
||||
|
||||
const uint8_t *eof = nullptr;
|
||||
const uint8_t *p = data;
|
||||
const uint8_t *pe = data + length;
|
||||
|
||||
auto &cursor = _context.cursor;
|
||||
auto &window = _context.window;
|
||||
auto &cursor_control = _context.cursor_control;
|
||||
|
||||
%%write exec;
|
||||
|
||||
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];
|
||||
|
||||
switch (uc)
|
||||
{
|
||||
case NSEnterCharacter:
|
||||
output->write(CTRL('M'));
|
||||
break;
|
||||
/*
|
||||
case NSDeleteCharacter:
|
||||
output->write(0x7f);
|
||||
break;
|
||||
*/
|
||||
|
||||
|
||||
// the Apple II keyboard had a delete where the backspace key was.
|
||||
// it functions as a backspace key.
|
||||
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;
|
||||
|
||||
//NSLog(@"%@", event);
|
||||
|
||||
if (flags & NSAlphaShiftKeyMask)
|
||||
{
|
||||
c = flags & NSShiftKeyMask ? tolower(c) : toupper(c);
|
||||
}
|
||||
|
||||
if (flags & NSControlKeyMask)
|
||||
c = CTRL(c);
|
||||
|
||||
output->write(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
@ -12,12 +12,19 @@
|
|||
#include "iGeometry.h"
|
||||
#include "Screen.h"
|
||||
|
||||
@interface Apple80 : NSObject <Emulator> {
|
||||
@interface AppleX : NSObject <Emulator> {
|
||||
|
||||
unsigned cs;
|
||||
unsigned _columns;
|
||||
int _scratch[4];
|
||||
|
||||
context _context;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface Apple40 : AppleX
|
||||
@end
|
||||
|
||||
@interface Apple80 : AppleX
|
||||
@end
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "Screen.h"
|
||||
#include "algorithm.h"
|
||||
|
||||
#import "CharacterGenerator.h"
|
||||
|
||||
%%{
|
||||
machine console;
|
||||
|
@ -30,7 +31,7 @@
|
|||
|
||||
action advance {
|
||||
// advance cursor
|
||||
if (++cursor.x == 80) {
|
||||
if (++cursor.x == _columns) {
|
||||
cursor.x = 0;
|
||||
if (cursor.y >= 24-1) {
|
||||
screen->scrollUp();
|
||||
|
@ -74,7 +75,7 @@
|
|||
|
||||
if (cursor.x) cursor.x--;
|
||||
else {
|
||||
cursor.x = 80-1;
|
||||
cursor.x = _columns-1;
|
||||
// go up, possibly scrolling.
|
||||
if (cursor.y) cursor.y--;
|
||||
}
|
||||
|
@ -101,11 +102,11 @@
|
|||
|
||||
iRect tmp;
|
||||
tmp.origin = cursor;
|
||||
tmp.size = iSize(80 - cursor.x, 1);
|
||||
tmp.size = iSize(_columns - cursor.x, 1);
|
||||
|
||||
screen->eraseRect(tmp);
|
||||
|
||||
tmp = iRect(0, 0, 80, 24);
|
||||
tmp = iRect(0, 0, _columns, 24);
|
||||
tmp.origin.y = cursor.y+1;
|
||||
tmp.size.height -= cursor.y+1;
|
||||
screen->eraseRect(tmp);
|
||||
|
@ -172,7 +173,7 @@
|
|||
/* clear line */
|
||||
iRect tmp;
|
||||
tmp.origin = iPoint(0, cursor.y);
|
||||
tmp.size = iSize(80, 1);
|
||||
tmp.size = iSize(_columns, 1);
|
||||
screen->eraseRect(tmp);
|
||||
}
|
||||
|
||||
|
@ -187,7 +188,7 @@
|
|||
/* Moves cursor right one column; if at end of line, does Control-M */
|
||||
// n.b. - BASIC ^M also moves to next line.
|
||||
cursor.x++;
|
||||
if (cursor.x == 80) cursor.x = 0;
|
||||
if (cursor.x == _columns) cursor.x = 0;
|
||||
}
|
||||
|
||||
| 0x1d ${
|
||||
|
@ -195,7 +196,7 @@
|
|||
/* clear to end of line */
|
||||
iRect tmp;
|
||||
tmp.origin = cursor;
|
||||
tmp.size = iSize(80 - cursor.x, 1);
|
||||
tmp.size = iSize(_columns - cursor.x, 1);
|
||||
|
||||
screen->eraseRect(tmp);
|
||||
}
|
||||
|
@ -204,7 +205,7 @@
|
|||
// CTRL('^'):
|
||||
/* goto x y */
|
||||
// todo - verify behavior for illegal values.
|
||||
cursor.x = clamp(_scratch[0], 0, 80 - 1);
|
||||
cursor.x = clamp(_scratch[0], 0, (int)_columns - 1);
|
||||
cursor.y = clamp(_scratch[1], 0, 24 - 1);
|
||||
}
|
||||
|
||||
|
@ -248,37 +249,35 @@
|
|||
write data;
|
||||
}%%
|
||||
|
||||
@implementation Apple80
|
||||
@implementation AppleX
|
||||
|
||||
|
||||
+(void)load
|
||||
{
|
||||
[EmulatorManager registerClass: self];
|
||||
- (NSString *)name {
|
||||
return @"Apple X";
|
||||
}
|
||||
|
||||
+(NSString *)name
|
||||
{
|
||||
return @"Apple 80";
|
||||
|
||||
+ (NSString *)name {
|
||||
return @"Apple X";
|
||||
|
||||
}
|
||||
|
||||
-(NSString *)name
|
||||
{
|
||||
return @"Apple 80";
|
||||
}
|
||||
|
||||
-(const char *)termName
|
||||
{
|
||||
- (const char *)termName {
|
||||
return "appleIIe";
|
||||
}
|
||||
|
||||
|
||||
-(void)reset
|
||||
-(void)reset: (BOOL)hard
|
||||
{
|
||||
|
||||
%%write init;
|
||||
_context.window = iRect(0, 0, 80, 24);
|
||||
_context.cursor = iPoint(0,0);
|
||||
_context.flags = 0;
|
||||
|
||||
if (hard) {
|
||||
_context.window = iRect(0, 0, _columns, 24);
|
||||
_context.cursor = iPoint(0,0);
|
||||
}
|
||||
}
|
||||
|
||||
-(BOOL)resizable
|
||||
|
@ -288,7 +287,7 @@
|
|||
|
||||
-(struct winsize)defaultSize
|
||||
{
|
||||
struct winsize ws = { 24, 80, 0, 0 };
|
||||
struct winsize ws = { 24, (unsigned short)_columns, 0, 0 };
|
||||
|
||||
return ws;
|
||||
}
|
||||
|
@ -303,7 +302,7 @@
|
|||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
[self reset];
|
||||
[self reset: YES];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -393,4 +392,70 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation Apple40
|
||||
|
||||
+(void)load
|
||||
{
|
||||
[EmulatorManager registerClass: self];
|
||||
}
|
||||
|
||||
+(NSString *)name
|
||||
{
|
||||
return @"Apple 40";
|
||||
}
|
||||
|
||||
-(NSString *)name
|
||||
{
|
||||
return @"Apple 40";
|
||||
}
|
||||
|
||||
-(const char *)termName
|
||||
{
|
||||
return "appleIIe";
|
||||
}
|
||||
|
||||
-(void) reset: (BOOL)hard {
|
||||
_columns = 40;
|
||||
[super reset: hard];
|
||||
}
|
||||
|
||||
-(CharacterGenerator *)characterGenerator {
|
||||
return [CharacterGenerator generatorForCharacterSet: CGApple40];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation Apple80
|
||||
|
||||
+(void)load
|
||||
{
|
||||
[EmulatorManager registerClass: self];
|
||||
}
|
||||
|
||||
+(NSString *)name
|
||||
{
|
||||
return @"Apple 80";
|
||||
}
|
||||
|
||||
-(NSString *)name
|
||||
{
|
||||
return @"Apple 80";
|
||||
}
|
||||
|
||||
-(const char *)termName
|
||||
{
|
||||
return "appleIIe";
|
||||
}
|
||||
|
||||
-(void) reset: (BOOL)hard {
|
||||
_columns = 80;
|
||||
[super reset: hard];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ extern "C" unsigned EventCharacters(NSEvent *event, std::u32string &rv);
|
|||
|
||||
#import "iGeometry.h"
|
||||
|
||||
@class CharacterGenerator;
|
||||
|
||||
@interface EmulatorManager : NSObject
|
||||
|
||||
|
@ -49,7 +50,7 @@ extern "C" unsigned EventCharacters(NSEvent *event, std::u32string &rv);
|
|||
|
||||
-(void)keyDown: (NSEvent *)event screen: (Screen *)screen output: (OutputChannel *)output;
|
||||
|
||||
-(void)reset;
|
||||
-(void)reset: (BOOL)hard;
|
||||
|
||||
+(NSString *)name;
|
||||
-(NSString *)name;
|
||||
|
@ -63,5 +64,6 @@ extern "C" unsigned EventCharacters(NSEvent *event, std::u32string &rv);
|
|||
@optional
|
||||
|
||||
-(void)initTerm: (struct termios *)term;
|
||||
-(CharacterGenerator *)characterGenerator;
|
||||
|
||||
@end
|
||||
|
|
|
@ -129,7 +129,6 @@
|
|||
screen->scrollUp(window);
|
||||
} else cursor.y++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
arg1 = any ${ _scratch[0] = ((fc & 0x7f) - 32); };
|
||||
|
@ -411,19 +410,19 @@
|
|||
}
|
||||
|
||||
|
||||
-(void)reset
|
||||
-(void)reset: (BOOL)hard
|
||||
{
|
||||
|
||||
%%write init;
|
||||
|
||||
_context.flags = 0;
|
||||
_context.window = iRect(0, 0, 80, 24);
|
||||
_context.cursor = iPoint(0,0);
|
||||
|
||||
|
||||
_cursorType = Screen::CursorTypeUnderscore;
|
||||
|
||||
// set flags to plain text.
|
||||
if (hard) {
|
||||
_context.window = iRect(0, 0, 80, 24);
|
||||
_context.cursor = iPoint(0,0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-(BOOL)resizable
|
||||
|
@ -448,7 +447,7 @@
|
|||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
[self reset];
|
||||
[self reset: YES];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
|
|
@ -496,20 +496,23 @@ static void advance(Screen *screen, gsos_context &ctx) {
|
|||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
[self reset];
|
||||
[self reset: YES];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)reset
|
||||
-(void)reset: (BOOL)hard
|
||||
{
|
||||
|
||||
%%write init;
|
||||
|
||||
_context.window = iRect(0, 0, 80, 24);
|
||||
_context.cursor = iPoint(0,0);
|
||||
|
||||
|
||||
if (hard) {
|
||||
_context_stack.clear();
|
||||
|
||||
_context.window = iRect(0, 0, 80, 24);
|
||||
_context.cursor = iPoint(0,0);
|
||||
}
|
||||
|
||||
_context.consWrap = true;
|
||||
_context.consAdvance = true;
|
||||
|
|
|
@ -306,20 +306,15 @@
|
|||
return "proterm-special";
|
||||
}
|
||||
|
||||
-(void)reset: (Screen *)screen
|
||||
{
|
||||
[self reset];
|
||||
|
||||
if (screen) screen->eraseScreen();
|
||||
}
|
||||
|
||||
-(void)reset
|
||||
-(void)reset: (BOOL)hard
|
||||
{
|
||||
%%write init;
|
||||
|
||||
_context.cursor = iPoint(0,0);
|
||||
_context.window = iRect(0,0,80,24);
|
||||
_context.flags = 0;
|
||||
|
||||
if (hard) {
|
||||
_context.cursor = iPoint(0,0);
|
||||
_context.window = iRect(0,0,80,24);
|
||||
}
|
||||
}
|
||||
|
||||
-(BOOL)resizable
|
||||
|
@ -336,7 +331,7 @@
|
|||
|
||||
-(id)init
|
||||
{
|
||||
[self reset];
|
||||
[self reset: YES];
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
|
||||
|
||||
@interface VT05 : NSObject <Emulator> {
|
||||
unsigned _state;
|
||||
unsigned cs;
|
||||
unsigned _scratch[2];
|
||||
context _context;
|
||||
BOOL _upperCase;
|
||||
}
|
||||
|
||||
-(void)tab: (Screen *)screen;
|
||||
|
||||
@end
|
||||
|
|
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
|
|
@ -9,35 +9,54 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "Emulator.h"
|
||||
|
||||
#include "iGeometry.h"
|
||||
#include "Screen.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
|
||||
struct vt100_context : public context {
|
||||
|
||||
enum {
|
||||
G0, G1
|
||||
};
|
||||
enum {
|
||||
CharSet_A,
|
||||
CharSet_B,
|
||||
CharSet_0,
|
||||
CharSet_1,
|
||||
CharSet_2,
|
||||
};
|
||||
|
||||
unsigned G0_charset = CharSet_B;
|
||||
unsigned G1_charset = CharSet_B;
|
||||
unsigned charset = G0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@interface VT100 : NSObject <Emulator> {
|
||||
|
||||
unsigned _state;
|
||||
|
||||
BOOL _altKeyPad;
|
||||
unsigned cs;
|
||||
vt100_context _context;
|
||||
Screen::CursorType _cursorType;
|
||||
BOOL _private;
|
||||
|
||||
vt100_context _saved_context;
|
||||
|
||||
|
||||
|
||||
BOOL _keyMode;
|
||||
BOOL _vt52Mode;
|
||||
BOOL _graphics;
|
||||
|
||||
iPoint _dca;
|
||||
|
||||
|
||||
struct __vt100flags {
|
||||
unsigned int DECANM:1; // vt52 mode
|
||||
unsigned int DECANM:1; // ANSI/vt52 mode
|
||||
unsigned int DECARM:1; // auto repeat mode.
|
||||
unsigned int DECAWM:1; // autowrap mode
|
||||
unsigned int DECCKM:1; // cursor key mode.
|
||||
unsigned int DECKPAM:1; // alternate keypad.
|
||||
unsigned int DECKPNM:1; // not alternate keypad.
|
||||
//unsigned int DECKPNM:1; // not alternate keypad.
|
||||
unsigned int DECCOLM:1; // 80/132 mode.
|
||||
unsigned int DECSCLM:1; // scrolling
|
||||
unsigned int DECSCNM:1; // screen
|
||||
|
@ -46,17 +65,15 @@
|
|||
|
||||
unsigned int LNM:1; // line feed new line mode.
|
||||
|
||||
|
||||
unsigned int VT52GM:1; // vt52 graphics mode
|
||||
} _flags;
|
||||
|
||||
#ifdef __cplusplus
|
||||
std::vector<int> _parms;
|
||||
std::vector<unsigned> _args;
|
||||
std::bitset<80> _tabs;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
-(void)tab: (Screen *)screen;
|
||||
|
||||
|
||||
@end
|
||||
|
|
|
@ -89,8 +89,6 @@ enum {
|
|||
_flags.DECOM = 0;
|
||||
_flags.DECINLM = 0;
|
||||
_flags.LNM = 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
772
Emulators/VT100.mm.ragel
Normal file
|
@ -0,0 +1,772 @@
|
|||
//
|
||||
// VT100.mm.ragel
|
||||
// TwoTerm
|
||||
//
|
||||
// Created by Kelvin Sherlock on 4/6/2018.
|
||||
//
|
||||
|
||||
#include <sys/ttydefaults.h>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#import "VT100.h"
|
||||
#include "OutputChannel.h"
|
||||
#include "Screen.h"
|
||||
#include "algorithm.h"
|
||||
|
||||
#define ESC "\x1b"
|
||||
|
||||
|
||||
%%{
|
||||
machine vt100;
|
||||
alphtype unsigned int;
|
||||
|
||||
|
||||
esc = 0x1b;
|
||||
cancel = 0x30 | 0x32;
|
||||
|
||||
action clear_args {
|
||||
_args.clear();
|
||||
_args.push_back(0);
|
||||
}
|
||||
|
||||
action answerback {
|
||||
/* no answerback string */
|
||||
}
|
||||
|
||||
|
||||
# DECOM - locked to scrolling region
|
||||
# DECAWM - autowrap
|
||||
action forward {
|
||||
if (cursor.x > window_x.second) {
|
||||
cursor.x = window_x.first;
|
||||
if (_flags.DECAWM) {
|
||||
if (cursor_in_region()) {
|
||||
if (cursor.y == region_y.second)
|
||||
screen->scrollUp(window);
|
||||
else {
|
||||
if (cursor.y < window_y.second) cursor.y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# ROM test - scrolling only happens if at bottom of scrolling region.
|
||||
#
|
||||
action linefeed {
|
||||
|
||||
/*
|
||||
* ROM test - scrolling ONLY happens if at bottom line of scrolling region.
|
||||
*
|
||||
*/
|
||||
if (cursor.y == region_y.second) {
|
||||
screen->scrollUp(window);
|
||||
} else {
|
||||
cursor.y = std::min(cursor.y + 1u, window_y.second);
|
||||
}
|
||||
}
|
||||
|
||||
action reverse_linefeed {
|
||||
if (cursor.y == region_y.first) {
|
||||
screen->scrollDown(window);
|
||||
} else {
|
||||
cursor.y = std::min(cursor.y - 1u, window_y.first);
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# ROM TEST - up/down can't escape the scrolling region.
|
||||
#
|
||||
action cursor_up {
|
||||
/* cursor up */
|
||||
unsigned count = _flags.DECANM ? std::max(1u, _args.front()) : 1;
|
||||
|
||||
if (cursor_in_region()) {
|
||||
cursor.y = clamp(cursor.y - count, region_y.first, region_y.second);
|
||||
} else {
|
||||
cursor.y = clamp(cursor.y - count, window_y.first, window_y.second);
|
||||
}
|
||||
}
|
||||
action cursor_down {
|
||||
/* cursor down */
|
||||
unsigned count = _flags.DECANM ? std::max(1u, _args.front()) : 1;
|
||||
|
||||
if (cursor_in_region()) {
|
||||
cursor.y = clamp(cursor.y + count, region_y.first, region_y.second);
|
||||
} else {
|
||||
cursor.y = clamp(cursor.y + count, window_y.first, window_y.second);
|
||||
}
|
||||
}
|
||||
|
||||
action cursor_left {
|
||||
/* cursor left */
|
||||
unsigned count = _flags.DECANM ? std::max(1u, _args.front()) : 1;
|
||||
cursor.x = clamp(cursor.x - count, window_x.first, window_x.second);
|
||||
}
|
||||
|
||||
action cursor_right {
|
||||
/* cursor right */
|
||||
unsigned count = _flags.DECANM ? std::max(1u, _args.front()) : 1;
|
||||
cursor.x = clamp(cursor.x + count, window_x.first, window_x.second);
|
||||
}
|
||||
|
||||
action cup {
|
||||
/* Cursor Position aka DCA */
|
||||
/* todo - numbering of lines depends on DECOM */
|
||||
unsigned y = _args.size() > 0 ? _args[0] : 0;
|
||||
unsigned x = _args.size() > 1 ? _args[1] : 0;
|
||||
|
||||
if (x == 0) x = 1;
|
||||
if (y == 0) y = 1;
|
||||
|
||||
if (_flags.DECOM) {
|
||||
cursor.y = clamp(y - 1 + region_y.first, region_y.first, region_y.second);
|
||||
cursor.x = clamp(x - 1, window_x.first, window_x.second);
|
||||
} else {
|
||||
cursor.y = clamp(y - 1, window_y.first, window_y.second);
|
||||
cursor.x = clamp(x - 1, window_x.first, window_x.second);
|
||||
}
|
||||
|
||||
}
|
||||
action vt52_dca {
|
||||
/* todo - how are invalid values handled? */
|
||||
/* todo - DECOM supported? */
|
||||
if (_flags.DECOM) {
|
||||
cursor.y = clamp(_args[0] + region_y.first, region_y.first, region_y.second);
|
||||
cursor.x = clamp(_args[1], window_x.first, window_x.second);
|
||||
} else {
|
||||
cursor.y = clamp(_args[0], window_y.first, window_y.second);
|
||||
cursor.x = clamp(_args[1], window_x.first, window_x.second);
|
||||
}
|
||||
}
|
||||
|
||||
action stbm {
|
||||
/* Set Top and Bottom Margins */
|
||||
/* aka scrolling region */
|
||||
unsigned top = _args.size() > 0 ? _args[0] : 0;
|
||||
unsigned bottom = _args.size() > 1 ? _args[1] : 0;
|
||||
|
||||
|
||||
if (top == 0) top = 1;
|
||||
if (bottom == 0) bottom = 24;
|
||||
|
||||
if (top < bottom && bottom <= 24) {
|
||||
|
||||
--top;
|
||||
|
||||
window = iRect(0, top, 80, bottom - top);
|
||||
// also home the cursor ... depeds on DECOM.
|
||||
if (_flags.DECOM) cursor = window.origin;
|
||||
else cursor = iPoint(0, 0);
|
||||
|
||||
region_y.first = top;
|
||||
region_y.second = bottom - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
action reset_mode {
|
||||
for (auto m : _args) {
|
||||
switch (m) {
|
||||
case 1: if (_private) _flags.DECCKM = 0; break;
|
||||
case 2: if (_private) _flags.DECANM = 0; break;
|
||||
case 3: if (_private) _flags.DECCOLM = 0; break;
|
||||
case 4: if (_private) _flags.DECSCLM = 0; break;
|
||||
case 5: if (_private) _flags.DECSCNM = 0; break;
|
||||
case 6: if (_private) {
|
||||
_flags.DECOM = 0;
|
||||
/* also move to new origin */
|
||||
cursor = iPoint(0, 0);
|
||||
}
|
||||
break;
|
||||
case 7: if (_private) _flags.DECAWM = 0; break;
|
||||
case 8: if (_private) _flags.DECARM = 0; break;
|
||||
case 9: if (_private) _flags.DECINLM = 0; break;
|
||||
case 20: if (!_private) _flags.LNM = 0; break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
action set_mode {
|
||||
for (auto m : _args) {
|
||||
switch (m) {
|
||||
case 1: if (_private) _flags.DECCKM = 1; break;
|
||||
case 2: if (_private) _flags.DECANM = 1; break;
|
||||
case 3: if (_private) _flags.DECCOLM = 1; break;
|
||||
case 4: if (_private) _flags.DECSCLM = 1; break;
|
||||
case 5: if (_private) _flags.DECSCNM = 1; break;
|
||||
case 6: if (_private) {
|
||||
_flags.DECOM = 1;
|
||||
/* also move to new origin */
|
||||
cursor = window.origin;
|
||||
}
|
||||
case 7: if (_private) _flags.DECAWM = 1; break;
|
||||
case 8: if (_private) _flags.DECARM = 1; break;
|
||||
case 9: if (_private) _flags.DECINLM = 1; break;
|
||||
case 20: if (!_private) _flags.LNM = 1; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
action tbc {
|
||||
/* TBC – Tabulation Clear */
|
||||
for (auto arg : _args) {
|
||||
switch (arg) {
|
||||
case 0: if (cursor.x <= 79) _tabs[cursor.x] = 0; break;
|
||||
case 3: _tabs.reset(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
action dsr {
|
||||
/* Device Status Report */
|
||||
for (auto arg : _args) {
|
||||
switch(arg) {
|
||||
default: break;
|
||||
case 5: /* report status */
|
||||
output->write(ESC "[0n");
|
||||
break;
|
||||
case 6: { /* cursor position report */
|
||||
char buffer[16];
|
||||
iPoint pt = cursor;
|
||||
pt.x++;
|
||||
pt.y++;
|
||||
if (_flags.DECOM) pt.y -= region_y.first;
|
||||
snprintf(buffer, sizeof(buffer)-1, ESC "[%u;%uR", pt.y, pt.x);
|
||||
output->write(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
action erase_line {
|
||||
// mode 0 and 1 erase cursor.x
|
||||
iRect r(0, cursor.y, 80, 1);
|
||||
|
||||
for (auto arg : _args) {
|
||||
|
||||
switch (arg) {
|
||||
case 0: {
|
||||
// x ... eos
|
||||
r.origin.x = cursor.x;
|
||||
r.size.width = 80 - cursor.x;
|
||||
screen->eraseRect(r);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
// 0 ... x
|
||||
r.origin.x = 0;
|
||||
r.size.width = cursor.x + 1;
|
||||
screen->eraseRect(r);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// 0 .. eos
|
||||
r.origin.x = 0;
|
||||
r.size.width = 80;
|
||||
screen->eraseRect(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
action erase_screen {
|
||||
|
||||
iRect r(0, cursor.y, 80, 1);
|
||||
|
||||
for (auto arg : _args) {
|
||||
|
||||
switch (arg) {
|
||||
case 0: {
|
||||
// x .. eos
|
||||
r.origin.x = cursor.x;
|
||||
r.size.width = 80 - cursor.x;
|
||||
screen->eraseRect(r);
|
||||
|
||||
iRect tmp(0, cursor.y + 1, 80, 24 - cursor.y - 1);
|
||||
screen->eraseRect(tmp);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
// 0 ... x
|
||||
// 0 ... x
|
||||
r.origin.x = 0;
|
||||
r.size.width = cursor.x + 1;
|
||||
screen->eraseRect(r);
|
||||
|
||||
iRect tmp(0, 0, 80, cursor.y - 1);
|
||||
screen->eraseRect(tmp);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
iRect tmp(0, 0, 80, 24);
|
||||
screen->eraseRect(tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
action vt52_erase_line {
|
||||
iRect r(cursor.x, cursor.y, 80 - cursor.x, 1);
|
||||
screen->eraseRect(r);
|
||||
}
|
||||
|
||||
action vt52_erase_screen {
|
||||
iRect r(cursor.x, cursor.y, 80 - cursor.x, 1);
|
||||
screen->eraseRect(r);
|
||||
r = iRect(0, cursor.y + 1, 80, 24 - cursor.y - 1);
|
||||
screen->eraseRect(r);
|
||||
}
|
||||
|
||||
|
||||
action sgr {
|
||||
/* Select Graphical Rendition */
|
||||
|
||||
for (auto arg : _args) {
|
||||
switch(arg) {
|
||||
case 0: _context.flags = Screen::FlagNormal; break;
|
||||
case 1: _context.flags |= Screen::FlagBold; break;
|
||||
case 4: _context.flags |= Screen::FlagUnderscore; break;
|
||||
case 5: _context.flags |= Screen::FlagBlink; break;
|
||||
case 7: _context.flags |= Screen::FlagInverse; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
action sc {
|
||||
/* Save Cursor */
|
||||
_saved_context = _context;
|
||||
}
|
||||
# todo -- what if DECOM changes?
|
||||
action rc {
|
||||
_context.cursor = _saved_context.cursor;
|
||||
_context.charset = _saved_context.charset;
|
||||
_context.G0_charset = _saved_context.G0_charset;
|
||||
_context.G1_charset = _saved_context.G1_charset;
|
||||
|
||||
}
|
||||
|
||||
control_codes = (
|
||||
0x05 $answerback
|
||||
| 0x07 ${ NSBeep(); }
|
||||
| 0x08 ${ if (cursor.x) cursor.x--; }
|
||||
| 0x09 ${ cursor.x = tab(cursor.x); }
|
||||
| (0x0a | 0x0b | 0x0c) ${ if (_flags.LNM) cursor.x = 0; } $linefeed
|
||||
| 0x0d ${ cursor.x = 0; }
|
||||
| 0x0e ${ _context.charset = vt100_context::G1; }
|
||||
| 0x0f ${ _context.charset = vt100_context::G0; }
|
||||
| 0x11 ${ /* xon */ }
|
||||
| 0x13 ${ /* xoff */ }
|
||||
| cntrl - esc
|
||||
);
|
||||
|
||||
args = (
|
||||
';' ${ _args.push_back(0); }
|
||||
| [0-9] ${ _args.back() *= 10; _args.back() += fc - '0'; }
|
||||
)**
|
||||
# >to(clear_args)
|
||||
;
|
||||
|
||||
lbrace = (
|
||||
'A' $cursor_up
|
||||
| 'B' $cursor_down
|
||||
| 'C' $cursor_right
|
||||
| 'D' $cursor_left
|
||||
| ('H' | 'f') $cup
|
||||
| 'K' $erase_line
|
||||
| 'J' $erase_screen
|
||||
| 'm' $sgr
|
||||
| 'r' $stbm
|
||||
| 'g' $tbc
|
||||
| 'h' $set_mode
|
||||
| 'l' $reset_mode
|
||||
| 'n' $dsr
|
||||
| 'c' ${ if (_args.front() == 0) output->write(ESC "[?1;0c"); }
|
||||
| 'y' ${ /* tests */ }
|
||||
| 'q' ${ /* led lights */ }
|
||||
| 'x' # DECREQTPARM
|
||||
)
|
||||
;
|
||||
|
||||
lparen = [AB012] ${
|
||||
switch (fc) {
|
||||
case 'A': _context.G0_charset = vt100_context::CharSet_A; break;
|
||||
case 'B': _context.G0_charset = vt100_context::CharSet_B; break;
|
||||
case '0': _context.G0_charset = vt100_context::CharSet_0; break;
|
||||
case '1': _context.G0_charset = vt100_context::CharSet_1; break;
|
||||
case '2': _context.G0_charset = vt100_context::CharSet_2; break;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
rparen = [AB012] ${
|
||||
switch (fc) {
|
||||
case 'A': _context.G1_charset = vt100_context::CharSet_A; break;
|
||||
case 'B': _context.G1_charset = vt100_context::CharSet_B; break;
|
||||
case '0': _context.G1_charset = vt100_context::CharSet_0; break;
|
||||
case '1': _context.G1_charset = vt100_context::CharSet_1; break;
|
||||
case '2': _context.G1_charset = vt100_context::CharSet_2; break;
|
||||
}
|
||||
};
|
||||
|
||||
# #3 = DECDHL - Double-Height Line (top half)
|
||||
# #4 = DECDHL - Double-Height Line (bottom half)
|
||||
# #5 = DECSWL – Single-width Line
|
||||
# #6 = DECDWL – Double-Width Line
|
||||
|
||||
pound = (
|
||||
'3'
|
||||
| '4'
|
||||
| '5'
|
||||
| '6'
|
||||
| '7' # DECHCP - Hard Copy
|
||||
| '8' ${
|
||||
/* DECALN */
|
||||
screen->fillScreen(char_info('E', 0));
|
||||
}
|
||||
);
|
||||
|
||||
dca_arg = any ${ _args.push_back((fc & 0x7f) - 32); } ;
|
||||
|
||||
escape_vt52 := (
|
||||
'A' $cursor_up
|
||||
| 'B' $cursor_down
|
||||
| 'C' $cursor_right
|
||||
| 'D' $cursor_left
|
||||
| 'F' ${ _flags.VT52GM = 1; }
|
||||
| 'G' ${ _flags.VT52GM = 0; }
|
||||
| 'H' ${ cursor = window.origin; } # todo - DECOM?
|
||||
| 'I' $reverse_linefeed
|
||||
| 'J' $vt52_erase_screen
|
||||
| 'K' $vt52_erase_line
|
||||
| 'Y' ${ _args.clear(); } dca_arg dca_arg $vt52_dca
|
||||
| 'Z' ${ output->write(ESC "/Z"); }
|
||||
| '=' ${ _flags.DECKPAM = 1;}
|
||||
| '>' ${ _flags.DECKPAM = 0; }
|
||||
| '<' ${ _flags.DECANM = 1; }
|
||||
)
|
||||
@{ fgoto main; }
|
||||
$err{ fgoto main; }
|
||||
;
|
||||
|
||||
csi = '[' ${ _args.clear(); _args.push_back(0); _private = NO; };
|
||||
private_flag = ('?' ${ _private = YES; })?;
|
||||
|
||||
escape := (
|
||||
( control_codes | esc )**
|
||||
| cancel ${ /* cancel */ fgoto main; }
|
||||
| csi private_flag args lbrace
|
||||
| '(' lparen
|
||||
| ')' rparen
|
||||
| '#' pound
|
||||
| 'D' $linefeed
|
||||
| 'E' ${cursor.x = 0; } $linefeed
|
||||
| 'H' ${ if (cursor.x <= 79) _tabs[cursor.x] = 1; }
|
||||
| 'M' $reverse_linefeed
|
||||
| 'Z' ${ output->write(ESC "[?1;0c"); }
|
||||
| '7' $sc
|
||||
| '8' $rc
|
||||
| '=' ${ _flags.DECKPAM = 1;}
|
||||
| '>' ${ _flags.DECKPAM = 0; }
|
||||
# | 'N'
|
||||
# | 'O'
|
||||
| 'c' ${ [self reset: YES]; /* should also clear the screen */ }
|
||||
| '1' # DECG - graphic processor on (vt105?)
|
||||
| '2' # DECG - graphic processor off (vt105?)
|
||||
)
|
||||
@{ fnext main; }
|
||||
$err{ fgoto main; }
|
||||
;
|
||||
|
||||
main := (
|
||||
control_codes
|
||||
| esc ${
|
||||
if (_flags.DECANM) fgoto escape; else fgoto escape_vt52;
|
||||
|
||||
}
|
||||
| 0x20 .. 0x7f $forward ${
|
||||
screen->putc(fc, _context);
|
||||
cursor.x++;
|
||||
}
|
||||
)**
|
||||
$err{ fgoto main; }
|
||||
;
|
||||
|
||||
write data;
|
||||
}%%
|
||||
|
||||
|
||||
@implementation VT100
|
||||
|
||||
|
||||
+(void)load
|
||||
{
|
||||
[EmulatorManager registerClass: self];
|
||||
}
|
||||
|
||||
-(id)init
|
||||
{
|
||||
self = [super init];
|
||||
[self reset: YES];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
+(NSString *)name
|
||||
{
|
||||
return @"VT100";
|
||||
}
|
||||
|
||||
-(NSString *)name
|
||||
{
|
||||
return @"VT100";
|
||||
}
|
||||
|
||||
-(const char *)termName
|
||||
{
|
||||
return "vt100";
|
||||
}
|
||||
|
||||
-(BOOL)resizable
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(struct winsize)defaultSize
|
||||
{
|
||||
struct winsize ws = { 24, 80, 0, 0};
|
||||
|
||||
return ws;
|
||||
}
|
||||
|
||||
-(void)reset: (BOOL)hard
|
||||
{
|
||||
%% write init;
|
||||
|
||||
_args.clear();
|
||||
|
||||
_flags.DECANM = 1; // ansi/vt100 mode
|
||||
_flags.DECARM = 0;
|
||||
_flags.DECAWM = 1;
|
||||
_flags.DECCKM = 0;
|
||||
_flags.DECKPAM = 0;
|
||||
//_flags.DECKPNM = 1;
|
||||
_flags.DECCOLM = 0;
|
||||
|
||||
_flags.DECSCLM = 0;
|
||||
_flags.DECSCNM = 0;
|
||||
_flags.DECOM = 0;
|
||||
_flags.DECINLM = 0;
|
||||
_flags.LNM = 0;
|
||||
_flags.VT52GM = 0;
|
||||
|
||||
|
||||
if (hard) {
|
||||
_context.cursor = iPoint(0,0);
|
||||
_context.window = iRect(0, 0, 80, 24);
|
||||
|
||||
_tabs.reset();
|
||||
_tabs[8] = true;
|
||||
_tabs[16] = true;
|
||||
_tabs[24] = true;
|
||||
_tabs[32] = true;
|
||||
_tabs[40] = true;
|
||||
_tabs[48] = true;
|
||||
_tabs[56] = true;
|
||||
_tabs[64] = true;
|
||||
_tabs[72] = true;
|
||||
}
|
||||
_context.flags = 0;
|
||||
_context.charset = vt100_context::G0;
|
||||
_context.G0_charset = vt100_context::CharSet_B;
|
||||
_context.G1_charset = vt100_context::CharSet_B;
|
||||
}
|
||||
|
||||
-(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;
|
||||
});
|
||||
|
||||
if (p == pe) return;
|
||||
|
||||
iPoint &cursor = _context.cursor;
|
||||
iRect &window = _context.window;
|
||||
|
||||
|
||||
std::pair<unsigned, unsigned> window_x(0u, 80-1);
|
||||
std::pair<unsigned, unsigned> window_y(0u, 24-1);
|
||||
std::pair<unsigned, unsigned> region_y(window.minY(), window.maxY()-1);
|
||||
|
||||
auto cursor_in_region = [&](){
|
||||
return cursor.y >= region_y.first && cursor.y <= region_y.second;
|
||||
};
|
||||
|
||||
/* todo - vt100 rom sometimes tabs to 80, sometimes doesn't. */
|
||||
/* difference being: tab, x < x wraps to next line? */
|
||||
auto tab = [&](unsigned x) -> unsigned {
|
||||
if (x >= 79) return x;
|
||||
for (x = x + 1; x < 80; ++x) {
|
||||
if (_tabs[x]) return x;
|
||||
}
|
||||
return 79; //?
|
||||
};
|
||||
|
||||
%%write exec;
|
||||
|
||||
|
||||
if (cursor.x == 80) screen->setCursor(iPoint(79, cursor.y));
|
||||
else screen->setCursor(cursor);
|
||||
}
|
||||
|
||||
static const char *RemapKey(unichar uc, NSEventModifierFlags flags, struct __vt100flags vt100flags)
|
||||
{
|
||||
|
||||
auto DECKPAM = vt100flags.DECKPAM;
|
||||
/*
|
||||
DECKPAM – Keypad Application Mode (DEC Private)
|
||||
|
||||
The auxiliary keypad keys will transmit control sequences as defined in Tables 3-7 and 3-8.
|
||||
*/
|
||||
|
||||
auto DECCKM = vt100flags.DECCKM;
|
||||
/*
|
||||
DECCKM – Cursor Keys Mode (DEC Private)
|
||||
|
||||
This is a private parameter applicable to set mode (SM) and reset mode (RM) control sequences. This mode is only effective when the terminal is in keypad application mode (see DECKPAM) and the ANSI/VT52 mode (DECANM) is set (see DECANM). Under these conditions, if the cursor key mode is reset, the four cursor function keys will send ANSI cursor control commands. If cursor key mode is set, the four cursor function keys will send application functions.
|
||||
*/
|
||||
|
||||
|
||||
auto LNM = vt100flags.LNM;
|
||||
auto DECANM = vt100flags.DECANM;
|
||||
/*
|
||||
DECANM – ANSI/VT52 Mode (DEC Private)
|
||||
|
||||
This is a private parameter applicable to set mode (SM) and reset mode (RM) control sequences. The reset state causes only VT52 compatible escape sequences to be interpreted and executed. The set state causes only ANSI "compatible" escape and control sequences to be interpreted and executed.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/* Device-independent bits found in event modifier flags */
|
||||
typedef NS_OPTIONS(NSUInteger, NSEventModifierFlags) {
|
||||
NSEventModifierFlagCapsLock = 1 << 16, // Set if Caps Lock key is pressed.
|
||||
NSEventModifierFlagShift = 1 << 17, // Set if Shift key is pressed.
|
||||
NSEventModifierFlagControl = 1 << 18, // Set if Control key is pressed.
|
||||
NSEventModifierFlagOption = 1 << 19, // Set if Option or Alternate key is pressed.
|
||||
NSEventModifierFlagCommand = 1 << 20, // Set if Command key is pressed.
|
||||
NSEventModifierFlagNumericPad = 1 << 21, // Set if any key in the numeric keypad is pressed.
|
||||
NSEventModifierFlagHelp = 1 << 22, // Set if the Help key is pressed.
|
||||
NSEventModifierFlagFunction = 1 << 23, // Set if any function key is pressed.
|
||||
|
||||
// Used to retrieve only the device-independent modifier flags, allowing applications to mask off the device-dependent modifier flags, including event coalescing information.
|
||||
NSEventModifierFlagDeviceIndependentFlagsMask = 0xffff0000UL
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
NSEnterCharacter: keypad Enter Key
|
||||
NSNewlineCharacter: \n
|
||||
NSCarriageReturnCharacter: \r (main Enter/Return key)
|
||||
*/
|
||||
|
||||
//NSLog(@"%c %02x %08lx", isprint(uc) ? uc : '.', uc, (unsigned long)flags);
|
||||
|
||||
if (DECKPAM && (flags & NSNumericPadKeyMask)) {
|
||||
switch (uc) {
|
||||
case '0': return DECANM ? ESC "Op" : ESC "?p";
|
||||
case '1': return DECANM ? ESC "Oq" : ESC "?q";
|
||||
case '2': return DECANM ? ESC "Or" : ESC "?r";
|
||||
case '3': return DECANM ? ESC "Os" : ESC "?s";
|
||||
case '4': return DECANM ? ESC "Ot" : ESC "?t";
|
||||
case '5': return DECANM ? ESC "Ou" : ESC "?u";
|
||||
case '6': return DECANM ? ESC "Ov" : ESC "?v";
|
||||
case '7': return DECANM ? ESC "Ow" : ESC "?w";
|
||||
case '8': return DECANM ? ESC "Ox" : ESC "?x";
|
||||
case '9': return DECANM ? ESC "Oy" : ESC "?y";
|
||||
case ',': return DECANM ? ESC "Ol" : ESC "?l";
|
||||
case '-': return DECANM ? ESC "Om" : ESC "?m";
|
||||
case '.': return DECANM ? ESC "On" : ESC "?n";
|
||||
|
||||
|
||||
case NSEnterCharacter: return DECANM ? ESC "OM" : ESC "?M";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch(uc) {
|
||||
case NSUpArrowFunctionKey:
|
||||
if (DECANM) return DECKPAM ? ESC "OA" : ESC "[A";
|
||||
return ESC "A";
|
||||
|
||||
case NSDownArrowFunctionKey:
|
||||
if (DECANM) return DECKPAM ? ESC "OB" : ESC "[B";
|
||||
return ESC "B";
|
||||
|
||||
case NSRightArrowFunctionKey:
|
||||
if (DECANM) return DECKPAM ? ESC "OC" : ESC "[C";
|
||||
return ESC "C";
|
||||
|
||||
case NSLeftArrowFunctionKey:
|
||||
if (DECANM) return DECKPAM ? ESC "OD" : ESC "[D";
|
||||
return ESC "D";
|
||||
|
||||
case NSF1FunctionKey: return DECANM ? ESC "OP" : ESC "P";
|
||||
case NSF2FunctionKey: return DECANM ? ESC "OQ" : ESC "Q";
|
||||
case NSF3FunctionKey: return DECANM ? ESC "OR" : ESC "R";
|
||||
case NSF4FunctionKey: return DECANM ? ESC "OS" : ESC "S";
|
||||
|
||||
|
||||
/* return/enter key is CR */
|
||||
case NSEnterCharacter: case NSNewlineCharacter: case NSCarriageReturnCharacter:
|
||||
return LNM ? "\n\r" : "\r";
|
||||
|
||||
// NSDeleteCharacter IS 0x7f.
|
||||
//case NSDeleteCharacter: return "\x7f"; //
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
-(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];
|
||||
|
||||
const char *str = RemapKey(uc, flags, _flags);
|
||||
if (str) {
|
||||
output->write(str);
|
||||
} else if (uc <= 0x7f) {
|
||||
uint8_t c = uc;
|
||||
if (flags & NSControlKeyMask) c = CTRL(c);
|
||||
output->write(c);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
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
|
@ -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 vt50h arg1 arg2 $dca
|
||||
| cntrl - esc
|
||||
);
|
||||
|
||||
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
|
||||
@end
|
||||
|
||||
/*
|
||||
@interface VT50H : VT5x
|
||||
@end
|
||||
|
||||
|
||||
@interface VT50 : VT5x
|
||||
@end
|
||||
*/
|
||||
|
||||
@interface VT55 : VT5x
|
||||
@end
|
||||
|
|
|
@ -43,7 +43,7 @@ enum {
|
|||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
@implementation VT50
|
||||
|
||||
+(void)load {
|
||||
|
@ -72,7 +72,7 @@ enum {
|
|||
-(id)init {
|
||||
if ((self = [super init])) {
|
||||
_model = ModelVT50;
|
||||
[self reset];
|
||||
[self reset: YES];
|
||||
|
||||
}
|
||||
return self;
|
||||
|
@ -104,7 +104,7 @@ enum {
|
|||
-(id)init {
|
||||
if ((self = [super init])) {
|
||||
_model = ModelVT50H;
|
||||
[self reset];
|
||||
[self reset: YES];
|
||||
|
||||
}
|
||||
return self;
|
||||
|
@ -119,6 +119,8 @@ enum {
|
|||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
@implementation VT52
|
||||
|
||||
+(void)load {
|
||||
|
@ -141,7 +143,7 @@ enum {
|
|||
-(id)init {
|
||||
if ((self = [super init])) {
|
||||
_model = ModelVT52;
|
||||
[self reset];
|
||||
[self reset: YES];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -168,7 +170,7 @@ enum {
|
|||
-(id)init {
|
||||
if ((self = [super init])) {
|
||||
_model = ModelVT55;
|
||||
[self reset];
|
||||
[self reset: YES];
|
||||
|
||||
}
|
||||
return self;
|
||||
|
@ -319,15 +321,18 @@ enum {
|
|||
}
|
||||
}
|
||||
|
||||
-(void)reset
|
||||
-(void)reset: (BOOL)hard
|
||||
{
|
||||
cs = StateText;
|
||||
_escape = false;
|
||||
_altKeyPad = false;
|
||||
_graphics = false;
|
||||
_context.cursor = iPoint(0,0);
|
||||
_context.window = iRect(0, 0, 80, 24);
|
||||
if (_model <= ModelVT50H) _context.window = iRect(0, 0, 80, 12);
|
||||
|
||||
if (hard) {
|
||||
_context.cursor = iPoint(0,0);
|
||||
_context.window = iRect(0, 0, 80, 24);
|
||||
if (_model <= ModelVT50H) _context.window = iRect(0, 0, 80, 12);
|
||||
}
|
||||
_context.flags = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
|
@ -17,11 +15,11 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<string>1.0r6</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>4</string>
|
||||
<string>6</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.utilities</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
|
|
@ -57,6 +57,9 @@
|
|||
|
||||
-(void)setParameters: (NSDictionary *)parameters;
|
||||
|
||||
-(IBAction)resetTerminal: (id)sender;
|
||||
-(IBAction)hardResetTerminal: (id)sender;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -248,8 +248,14 @@
|
|||
[_emulatorView processData: (uint8_t *)buffer size: size];
|
||||
}
|
||||
|
||||
-(IBAction)resetTerminal: (id)sender {
|
||||
[_emulator reset: NO];
|
||||
}
|
||||
|
||||
|
||||
-(IBAction)hardResetTerminal: (id)sender {
|
||||
[_emulator reset: YES];
|
||||
[_emulatorView reset];
|
||||
}
|
||||
#pragma mark -
|
||||
#pragma mark NSWindowDelegate
|
||||
|
||||
|
@ -276,6 +282,13 @@
|
|||
[_colorView setWantsLayer: YES];
|
||||
[_colorView setContentFilters: [self effectsFilter]];
|
||||
|
||||
if ([_emulator respondsToSelector: @selector(characterGenerator)]) {
|
||||
id tmp = [_emulator characterGenerator];
|
||||
|
||||
[(EmulatorWindow *)window setTitleCharacterGenerator:tmp];
|
||||
|
||||
}
|
||||
|
||||
[self initPTY];
|
||||
}
|
||||
|
||||
|
@ -406,6 +419,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
- (IBAction)foregroundColor:(id)sender {
|
||||
[self updateForegroundColor];
|
||||
}
|
||||
|
@ -456,7 +470,6 @@
|
|||
[_emulatorView setBackgroundColor: color];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
|
||||
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
|
||||
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
|
||||
B609404C205ACD730077A69C /* VT05.mm.ragel in Sources */ = {isa = PBXBuildFile; fileRef = B683F711204AE32900470B99 /* VT05.mm.ragel */; };
|
||||
B60942042082BCA200141159 /* VT100.mm.ragel in Sources */ = {isa = PBXBuildFile; fileRef = B60942022077F24300141159 /* VT100.mm.ragel */; };
|
||||
B60EBD1211E8DEEF00C1974F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B60EBD1111E8DEEF00C1974F /* QuartzCore.framework */; };
|
||||
B60EBDE311E90FC300C1974F /* ScanLineFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B60EBDE211E90FC300C1974F /* ScanLineFilter.m */; };
|
||||
B60EBE2B11E918D500C1974F /* ScanLineFilter.cikernel in Resources */ = {isa = PBXBuildFile; fileRef = B60EBDE711E9143F00C1974F /* ScanLineFilter.cikernel */; };
|
||||
|
@ -43,11 +45,26 @@
|
|||
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 */; };
|
||||
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 */; };
|
||||
B68A37D221A9B9D9004CBDE4 /* a2-charset-80@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CD720349C8C00671774 /* a2-charset-80@2x.png */; };
|
||||
B68A37D321A9C15C004CBDE4 /* a2-charset-40@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CDA20349C8E00671774 /* a2-charset-40@2x.png */; };
|
||||
B68A37D421A9C161004CBDE4 /* vt52-charset@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CD920349C8D00671774 /* vt52-charset@2x.png */; };
|
||||
B68A37D521A9C164004CBDE4 /* vt100-charset@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CD820349C8D00671774 /* vt100-charset@2x.png */; };
|
||||
B68E632A12FF909D00EAFF5F /* ExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = B68E632912FF909C00EAFF5F /* ExampleView.m */; };
|
||||
B69D0FBA202799B10073CCB7 /* TermConfig.xib in Resources */ = {isa = PBXBuildFile; fileRef = B69D0FB8202799B10073CCB7 /* TermConfig.xib */; };
|
||||
B69E32A920221C9E0086D7B1 /* ChildMonitor.mm in Sources */ = {isa = PBXBuildFile; fileRef = B69E32A820221C9E0086D7B1 /* ChildMonitor.mm */; };
|
||||
B6ACA2AD1E614E38000E774B /* VT52.mm in Sources */ = {isa = PBXBuildFile; fileRef = B612F46312DD5DF1005D1B77 /* VT52.mm */; };
|
||||
B6ACA2AF1E635CEC000E774B /* vt52-charset.png in Resources */ = {isa = PBXBuildFile; fileRef = B6ACA2AE1E635CEC000E774B /* vt52-charset.png */; };
|
||||
B6C0909021D292E20067F7A4 /* Apple3.mm.ragel in Sources */ = {isa = PBXBuildFile; fileRef = B6C0908D21D1BBE70067F7A4 /* Apple3.mm.ragel */; };
|
||||
B6C21CCE2033382B00671774 /* TabClose_Busy.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CC82033382A00671774 /* TabClose_Busy.tiff */; };
|
||||
B6C21CCF2033382B00671774 /* TabClose_Busy_Pressed.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CC92033382A00671774 /* TabClose_Busy_Pressed.tiff */; };
|
||||
B6C21CD02033382B00671774 /* TabClose.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CCA2033382A00671774 /* TabClose.tiff */; };
|
||||
B6C21CD12033382B00671774 /* TabClose_Pressed.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CCB2033382B00671774 /* TabClose_Pressed.tiff */; };
|
||||
B6C21CD22033382B00671774 /* TabClose_Rollover.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CCC2033382B00671774 /* TabClose_Rollover.tiff */; };
|
||||
B6C21CD32033382B00671774 /* TabClose_Busy_Rollover.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CCD2033382B00671774 /* TabClose_Busy_Rollover.tiff */; };
|
||||
B6C21CD62033580200671774 /* RolloverButton.m in Sources */ = {isa = PBXBuildFile; fileRef = B6C21CD52033580200671774 /* RolloverButton.m */; };
|
||||
B6C21CE1203510CC00671774 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CE0203510CC00671774 /* Images.xcassets */; };
|
||||
B6C21CE52035262200671774 /* Defaults.plist in Resources */ = {isa = PBXBuildFile; fileRef = B6C21CE42035262200671774 /* Defaults.plist */; };
|
||||
B6C704EF15CCC64100CC0401 /* titlebar-center@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6C704EC15CCC64100CC0401 /* titlebar-center@2x.png */; };
|
||||
B6C704F015CCC64100CC0401 /* titlebar-left@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6C704ED15CCC64100CC0401 /* titlebar-left@2x.png */; };
|
||||
B6C704F115CCC64100CC0401 /* titlebar-right@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6C704EE15CCC64100CC0401 /* titlebar-right@2x.png */; };
|
||||
|
@ -61,6 +78,8 @@
|
|||
isa = PBXBuildRule;
|
||||
compilerSpec = "com.apple.build-tasks.copy-strings-file";
|
||||
fileType = sourcecode.glsl;
|
||||
inputFiles = (
|
||||
);
|
||||
isEditable = 1;
|
||||
outputFiles = (
|
||||
);
|
||||
|
@ -71,6 +90,8 @@
|
|||
compilerSpec = com.apple.compilers.proxy.script;
|
||||
filePatterns = "*.mm.ragel";
|
||||
fileType = pattern.proxy;
|
||||
inputFiles = (
|
||||
);
|
||||
isEditable = 1;
|
||||
outputFiles = (
|
||||
"$(DERIVED_SOURCES_DIR)/$(INPUT_FILE_BASE)",
|
||||
|
@ -92,10 +113,8 @@
|
|||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
|
||||
1DDD58150DA1D0A300B32029 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
256AC3D80F4B6AC300CF3369 /* TwoTermAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TwoTermAppDelegate.h; sourceTree = "<group>"; };
|
||||
256AC3D90F4B6AC300CF3369 /* TwoTermAppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TwoTermAppDelegate.mm; sourceTree = "<group>"; };
|
||||
256AC3F00F4B6AF500CF3369 /* TwoTerm_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TwoTerm_Prefix.pch; sourceTree = "<group>"; };
|
||||
|
@ -104,6 +123,7 @@
|
|||
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
|
||||
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
8D1107320486CEB800E47090 /* TwoTerm.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TwoTerm.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B60942022077F24300141159 /* VT100.mm.ragel */ = {isa = PBXFileReference; lastKnownFileType = text; path = VT100.mm.ragel; sourceTree = "<group>"; };
|
||||
B60B98712022BAF100E688E3 /* appleIIgs.ti */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = appleIIgs.ti; sourceTree = "<group>"; };
|
||||
B60B98732022BAF100E688E3 /* gno-console.ti */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "gno-console.ti"; sourceTree = "<group>"; };
|
||||
B60B98742022BAF100E688E3 /* gsos-console.ti */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "gsos-console.ti"; sourceTree = "<group>"; };
|
||||
|
@ -146,10 +166,8 @@
|
|||
B61D0D68125B8E06001C713B /* Defaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Defaults.m; sourceTree = "<group>"; };
|
||||
B61EF7C31481561E008C1891 /* titlebar-corner.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "titlebar-corner.png"; sourceTree = "<group>"; };
|
||||
B61EF7C41481561E008C1891 /* titlebar-middle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "titlebar-middle.png"; sourceTree = "<group>"; };
|
||||
B61EF7C814815AF8008C1891 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/NewTerminal.xib; sourceTree = "<group>"; };
|
||||
B61EF7CA14815E07008C1891 /* TitleBarView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TitleBarView.h; sourceTree = "<group>"; };
|
||||
B61EF7CB14815E07008C1891 /* TitleBarView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TitleBarView.m; sourceTree = "<group>"; };
|
||||
B61EF7CE148163E7008C1891 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/TitleBarView.xib; sourceTree = "<group>"; };
|
||||
B61EF7D41482FB6D008C1891 /* titlebar-center.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "titlebar-center.png"; sourceTree = "<group>"; };
|
||||
B61EF7D51482FB6D008C1891 /* titlebar-left.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "titlebar-left.png"; sourceTree = "<group>"; };
|
||||
B61EF7D61482FB6D008C1891 /* titlebar-right.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "titlebar-right.png"; sourceTree = "<group>"; };
|
||||
|
@ -159,20 +177,44 @@
|
|||
B66412381480A070003BC8D3 /* EmulatorWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EmulatorWindow.m; sourceTree = "<group>"; };
|
||||
B676063911DEAD3500D6B66C /* TermWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TermWindowController.h; sourceTree = "<group>"; };
|
||||
B676063A11DEAD3500D6B66C /* TermWindowController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TermWindowController.mm; sourceTree = "<group>"; };
|
||||
B676064D11DEBAE300D6B66C /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/TermWindow.xib; 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>"; };
|
||||
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>"; };
|
||||
B6887810235CD76A00407374 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
B6887811235CD76A00407374 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/TermWindow.xib; sourceTree = "<group>"; };
|
||||
B6887812235CD76A00407374 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/NewTerminal.xib; sourceTree = "<group>"; };
|
||||
B6887813235CD76B00407374 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/TermConfig.xib; sourceTree = "<group>"; };
|
||||
B6887814235CD76B00407374 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/TitleBarView.xib; sourceTree = "<group>"; };
|
||||
B6887815235CD77600407374 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
B68A37D621A9D45A004CBDE4 /* TwoTerm.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = TwoTerm.entitlements; path = TwoTerm/TwoTerm.entitlements; 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>"; };
|
||||
B69D0FB9202799B10073CCB7 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/TermConfig.xib; sourceTree = "<group>"; };
|
||||
B69E32A820221C9E0086D7B1 /* ChildMonitor.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ChildMonitor.mm; sourceTree = "<group>"; };
|
||||
B69E32AA20221CCA0086D7B1 /* ChildMonitor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChildMonitor.h; sourceTree = "<group>"; };
|
||||
B6ACA2AB1E5C8BEC000E774B /* GNOConsole.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GNOConsole.mm; sourceTree = "<group>"; };
|
||||
B6ACA2AE1E635CEC000E774B /* vt52-charset.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "vt52-charset.png"; sourceTree = "<group>"; };
|
||||
B6C0908D21D1BBE70067F7A4 /* Apple3.mm.ragel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Apple3.mm.ragel; sourceTree = "<group>"; };
|
||||
B6C0908F21D1D2070067F7A4 /* Apple3.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Apple3.h; sourceTree = "<group>"; };
|
||||
B6C173901D31D2B80024E360 /* GSOSConsole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GSOSConsole.h; sourceTree = "<group>"; };
|
||||
B6C173911D31D2B80024E360 /* GSOSConsole.mm.ragel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = GSOSConsole.mm.ragel; sourceTree = "<group>"; };
|
||||
B6C173941D35546A0024E360 /* algorithm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = algorithm.h; sourceTree = "<group>"; };
|
||||
B6C21CC82033382A00671774 /* TabClose_Busy.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TabClose_Busy.tiff; sourceTree = "<group>"; };
|
||||
B6C21CC92033382A00671774 /* TabClose_Busy_Pressed.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TabClose_Busy_Pressed.tiff; sourceTree = "<group>"; };
|
||||
B6C21CCA2033382A00671774 /* TabClose.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TabClose.tiff; sourceTree = "<group>"; };
|
||||
B6C21CCB2033382B00671774 /* TabClose_Pressed.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TabClose_Pressed.tiff; sourceTree = "<group>"; };
|
||||
B6C21CCC2033382B00671774 /* TabClose_Rollover.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TabClose_Rollover.tiff; sourceTree = "<group>"; };
|
||||
B6C21CCD2033382B00671774 /* TabClose_Busy_Rollover.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = TabClose_Busy_Rollover.tiff; sourceTree = "<group>"; };
|
||||
B6C21CD42033580200671774 /* RolloverButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RolloverButton.h; sourceTree = "<group>"; };
|
||||
B6C21CD52033580200671774 /* RolloverButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RolloverButton.m; sourceTree = "<group>"; };
|
||||
B6C21CD720349C8C00671774 /* a2-charset-80@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "a2-charset-80@2x.png"; sourceTree = "<group>"; };
|
||||
B6C21CD820349C8D00671774 /* vt100-charset@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "vt100-charset@2x.png"; sourceTree = "<group>"; };
|
||||
B6C21CD920349C8D00671774 /* vt52-charset@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "vt52-charset@2x.png"; sourceTree = "<group>"; };
|
||||
B6C21CDA20349C8E00671774 /* a2-charset-40@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "a2-charset-40@2x.png"; sourceTree = "<group>"; };
|
||||
B6C21CE0203510CC00671774 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = TwoTerm/Images.xcassets; sourceTree = "<group>"; };
|
||||
B6C21CE42035262200671774 /* Defaults.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Defaults.plist; sourceTree = "<group>"; };
|
||||
B6C704EC15CCC64100CC0401 /* titlebar-center@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "titlebar-center@2x.png"; sourceTree = "<group>"; };
|
||||
B6C704ED15CCC64100CC0401 /* titlebar-left@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "titlebar-left@2x.png"; sourceTree = "<group>"; };
|
||||
B6C704EE15CCC64100CC0401 /* titlebar-right@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "titlebar-right@2x.png"; sourceTree = "<group>"; };
|
||||
|
@ -245,6 +287,7 @@
|
|||
29B97314FDCFA39411CA2CEA /* 2Term */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B68A37D621A9D45A004CBDE4 /* TwoTerm.entitlements */,
|
||||
B612F46B12DD5E02005D1B77 /* Views */,
|
||||
B612F45512DD5DF1005D1B77 /* Emulators */,
|
||||
B612F44612DD5DAD005D1B77 /* cpp */,
|
||||
|
@ -271,10 +314,12 @@
|
|||
29B97317FDCFA39411CA2CEA /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B6C21CE0203510CC00671774 /* Images.xcassets */,
|
||||
B60B98702022BAF100E688E3 /* a2-terminfo */,
|
||||
B60EBDE711E9143F00C1974F /* ScanLineFilter.cikernel */,
|
||||
B66979CE11E6BCAE002ED475 /* images */,
|
||||
8D1107310486CEB800E47090 /* Info.plist */,
|
||||
B6C21CE42035262200671774 /* Defaults.plist */,
|
||||
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
|
||||
1DDD58140DA1D0A300B32029 /* MainMenu.xib */,
|
||||
B676065011DEBAE900D6B66C /* TermWindow.xib */,
|
||||
|
@ -308,10 +353,10 @@
|
|||
B612F44612DD5DAD005D1B77 /* cpp */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B612F44812DD5DAD005D1B77 /* iGeometry.h */,
|
||||
B612F44712DD5DAD005D1B77 /* iGeometry.cpp */,
|
||||
B6D5A0831E3996BD004FC1AC /* ring_buffer.h */,
|
||||
B6C173941D35546A0024E360 /* algorithm.h */,
|
||||
B612F44812DD5DAD005D1B77 /* iGeometry.h */,
|
||||
B612F44912DD5DAD005D1B77 /* Lock.cpp */,
|
||||
B612F44A12DD5DAD005D1B77 /* Lock.h */,
|
||||
B612F44B12DD5DAD005D1B77 /* OutputChannel.cpp */,
|
||||
|
@ -329,7 +374,9 @@
|
|||
B612F45912DD5DF1005D1B77 /* EmulatorManager.mm */,
|
||||
B612F45612DD5DF1005D1B77 /* Apple80.h */,
|
||||
B612F45712DD5DF1005D1B77 /* Apple80.mm.ragel */,
|
||||
B6C0908D21D1BBE70067F7A4 /* Apple3.mm.ragel */,
|
||||
B612F45A12DD5DF1005D1B77 /* GNOConsole.h */,
|
||||
B6C0908F21D1D2070067F7A4 /* Apple3.h */,
|
||||
B612F45B12DD5DF1005D1B77 /* GNOConsole.mm.ragel */,
|
||||
B6ACA2AB1E5C8BEC000E774B /* GNOConsole.mm */,
|
||||
B6C173901D31D2B80024E360 /* GSOSConsole.h */,
|
||||
|
@ -338,10 +385,14 @@
|
|||
B612F45D12DD5DF1005D1B77 /* PTSE.mm.ragel */,
|
||||
B612F45E12DD5DF1005D1B77 /* VT05.h */,
|
||||
B612F45F12DD5DF1005D1B77 /* VT05.mm */,
|
||||
B683F711204AE32900470B99 /* VT05.mm.ragel */,
|
||||
B612F46012DD5DF1005D1B77 /* VT100.h */,
|
||||
B612F46112DD5DF1005D1B77 /* VT100.mm */,
|
||||
B612F46212DD5DF1005D1B77 /* VT52.h */,
|
||||
B612F46312DD5DF1005D1B77 /* VT52.mm */,
|
||||
B683F70E2049E7B000470B99 /* VT50.h */,
|
||||
B683F70F2049E7B000470B99 /* VT50.mm.ragel */,
|
||||
B60942022077F24300141159 /* VT100.mm.ragel */,
|
||||
);
|
||||
path = Emulators;
|
||||
sourceTree = "<group>";
|
||||
|
@ -365,6 +416,8 @@
|
|||
B6ECFF261D2EEA2B00871A81 /* TextLabel.m */,
|
||||
B638188014A179D60027D007 /* ColorView.h */,
|
||||
B638188114A179D60027D007 /* ColorView.m */,
|
||||
B6C21CD42033580200671774 /* RolloverButton.h */,
|
||||
B6C21CD52033580200671774 /* RolloverButton.m */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
|
@ -372,6 +425,12 @@
|
|||
B66979CE11E6BCAE002ED475 /* images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B6C21CC92033382A00671774 /* TabClose_Busy_Pressed.tiff */,
|
||||
B6C21CCD2033382B00671774 /* TabClose_Busy_Rollover.tiff */,
|
||||
B6C21CC82033382A00671774 /* TabClose_Busy.tiff */,
|
||||
B6C21CCB2033382B00671774 /* TabClose_Pressed.tiff */,
|
||||
B6C21CCC2033382B00671774 /* TabClose_Rollover.tiff */,
|
||||
B6C21CCA2033382A00671774 /* TabClose.tiff */,
|
||||
B61EF7D41482FB6D008C1891 /* titlebar-center.png */,
|
||||
B61EF7D51482FB6D008C1891 /* titlebar-left.png */,
|
||||
B61EF7D61482FB6D008C1891 /* titlebar-right.png */,
|
||||
|
@ -384,6 +443,10 @@
|
|||
B6ACA2AE1E635CEC000E774B /* vt52-charset.png */,
|
||||
B67B3CE312B6FA040033AE07 /* a2-charset-40.png */,
|
||||
B67B3CE412B6FA040033AE07 /* a2-charset-80.png */,
|
||||
B6C21CDA20349C8E00671774 /* a2-charset-40@2x.png */,
|
||||
B6C21CD720349C8C00671774 /* a2-charset-80@2x.png */,
|
||||
B6C21CD920349C8D00671774 /* vt52-charset@2x.png */,
|
||||
B6C21CD820349C8D00671774 /* vt100-charset@2x.png */,
|
||||
);
|
||||
path = images;
|
||||
sourceTree = "<group>";
|
||||
|
@ -419,15 +482,25 @@
|
|||
29B97313FDCFA39411CA2CEA /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0910;
|
||||
LastUpgradeCheck = 1110;
|
||||
TargetAttributes = {
|
||||
8D1107260486CEB800E47090 = {
|
||||
ProvisioningStyle = Automatic;
|
||||
SystemCapabilities = {
|
||||
com.apple.HardenedRuntime = {
|
||||
enabled = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "TwoTerm" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
en,
|
||||
English,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 29B97314FDCFA39411CA2CEA /* 2Term */;
|
||||
projectDirPath = "";
|
||||
|
@ -443,24 +516,36 @@
|
|||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B6C21CE52035262200671774 /* Defaults.plist in Resources */,
|
||||
B60EBE2B11E918D500C1974F /* ScanLineFilter.cikernel in Resources */,
|
||||
B6C21CD12033382B00671774 /* TabClose_Pressed.tiff in Resources */,
|
||||
B6C21CCF2033382B00671774 /* TabClose_Busy_Pressed.tiff in Resources */,
|
||||
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
|
||||
B69D0FBA202799B10073CCB7 /* TermConfig.xib in Resources */,
|
||||
B68A37D421A9C161004CBDE4 /* vt52-charset@2x.png in Resources */,
|
||||
1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */,
|
||||
B676065111DEBAE900D6B66C /* TermWindow.xib in Resources */,
|
||||
B67B3CE512B6FA040033AE07 /* a2-charset-40.png in Resources */,
|
||||
B6C21CD02033382B00671774 /* TabClose.tiff in Resources */,
|
||||
B67B3CE612B6FA040033AE07 /* a2-charset-80.png in Resources */,
|
||||
B6801BD912EB549300B22E9E /* vt100-charset.png in Resources */,
|
||||
B68A37D321A9C15C004CBDE4 /* a2-charset-40@2x.png in Resources */,
|
||||
B6C21CCE2033382B00671774 /* TabClose_Busy.tiff in Resources */,
|
||||
B6C21CD32033382B00671774 /* TabClose_Busy_Rollover.tiff in Resources */,
|
||||
B61EF7C51481561E008C1891 /* titlebar-corner.png in Resources */,
|
||||
B61EF7C61481561E008C1891 /* titlebar-middle.png in Resources */,
|
||||
B68A37D521A9C164004CBDE4 /* vt100-charset@2x.png in Resources */,
|
||||
B68A37D221A9B9D9004CBDE4 /* a2-charset-80@2x.png in Resources */,
|
||||
B61EF7C914815AF8008C1891 /* NewTerminal.xib in Resources */,
|
||||
B61EF7CF148163E7008C1891 /* TitleBarView.xib in Resources */,
|
||||
B61EF7D71482FB6D008C1891 /* titlebar-center.png in Resources */,
|
||||
B6C21CE1203510CC00671774 /* Images.xcassets in Resources */,
|
||||
B61EF7D81482FB6D008C1891 /* titlebar-left.png in Resources */,
|
||||
B61EF7D91482FB6D008C1891 /* titlebar-right.png in Resources */,
|
||||
B6C704EF15CCC64100CC0401 /* titlebar-center@2x.png in Resources */,
|
||||
B6C704F015CCC64100CC0401 /* titlebar-left@2x.png in Resources */,
|
||||
B6C704F115CCC64100CC0401 /* titlebar-right@2x.png in Resources */,
|
||||
B6C21CD22033382B00671774 /* TabClose_Rollover.tiff in Resources */,
|
||||
B6ACA2AF1E635CEC000E774B /* vt52-charset.png in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -489,10 +574,15 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B675F4A91E561D20004B0D9C /* Apple80.mm.ragel in Sources */,
|
||||
B6C0909021D292E20067F7A4 /* Apple3.mm.ragel in Sources */,
|
||||
B675F4AC1E56A7F2004B0D9C /* GSOSConsole.mm.ragel in Sources */,
|
||||
B6D1CD071E577E7D00C4A6BC /* PTSE.mm.ragel in Sources */,
|
||||
B69E32A920221C9E0086D7B1 /* ChildMonitor.mm in Sources */,
|
||||
B683F7102049E7B000470B99 /* VT50.mm.ragel in Sources */,
|
||||
B6407805201CE93500D3F2D1 /* GNOConsole.mm.ragel in Sources */,
|
||||
B609404C205ACD730077A69C /* VT05.mm.ragel in Sources */,
|
||||
B60942042082BCA200141159 /* VT100.mm.ragel in Sources */,
|
||||
B6C21CD62033580200671774 /* RolloverButton.m in Sources */,
|
||||
B69E32A920221C9E0086D7B1 /* ChildMonitor.mm in Sources */,
|
||||
8D11072D0486CEB800E47090 /* main.m in Sources */,
|
||||
256AC3DA0F4B6AC300CF3369 /* TwoTermAppDelegate.mm in Sources */,
|
||||
B676063B11DEAD3500D6B66C /* TermWindowController.mm in Sources */,
|
||||
|
@ -523,7 +613,7 @@
|
|||
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
089C165DFE840E0CC02AAC07 /* English */,
|
||||
B6887815235CD77600407374 /* en */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
|
@ -531,7 +621,7 @@
|
|||
1DDD58140DA1D0A300B32029 /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
1DDD58150DA1D0A300B32029 /* English */,
|
||||
B6887810235CD76A00407374 /* Base */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
sourceTree = "<group>";
|
||||
|
@ -539,7 +629,7 @@
|
|||
B61EF7C714815AF8008C1891 /* NewTerminal.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
B61EF7C814815AF8008C1891 /* English */,
|
||||
B6887812235CD76A00407374 /* Base */,
|
||||
);
|
||||
name = NewTerminal.xib;
|
||||
sourceTree = "<group>";
|
||||
|
@ -547,7 +637,7 @@
|
|||
B61EF7CD148163E7008C1891 /* TitleBarView.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
B61EF7CE148163E7008C1891 /* English */,
|
||||
B6887814235CD76B00407374 /* Base */,
|
||||
);
|
||||
name = TitleBarView.xib;
|
||||
sourceTree = "<group>";
|
||||
|
@ -555,7 +645,7 @@
|
|||
B676065011DEBAE900D6B66C /* TermWindow.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
B676064D11DEBAE300D6B66C /* English */,
|
||||
B6887811235CD76A00407374 /* Base */,
|
||||
);
|
||||
name = TermWindow.xib;
|
||||
sourceTree = "<group>";
|
||||
|
@ -563,7 +653,7 @@
|
|||
B69D0FB8202799B10073CCB7 /* TermConfig.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
B69D0FB9202799B10073CCB7 /* English */,
|
||||
B6887813235CD76B00407374 /* Base */,
|
||||
);
|
||||
name = TermConfig.xib;
|
||||
sourceTree = "<group>";
|
||||
|
@ -575,8 +665,14 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
|
@ -586,6 +682,7 @@
|
|||
INSTALL_PATH = "$(HOME)/Applications";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.ksherlock.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = TwoTerm;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
@ -593,8 +690,13 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = TwoTerm_Prefix.pch;
|
||||
|
@ -615,11 +717,13 @@
|
|||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
|
@ -654,11 +758,13 @@
|
|||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
|
|
66
TwoTerm/Images.xcassets/AppIcon.appiconset/Contents.json
Normal file
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "16x16",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "16x16",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "32x32",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon-32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "32x32",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon-32@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "128x128",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon-128.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "128x128",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon-128@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "256x256",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon-256.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "256x256",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon-256@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "512x512",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon-512.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "512x512",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon-512@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
TwoTerm/Images.xcassets/AppIcon.appiconset/icon-128.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
TwoTerm/Images.xcassets/AppIcon.appiconset/icon-128@2x.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
TwoTerm/Images.xcassets/AppIcon.appiconset/icon-256.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
TwoTerm/Images.xcassets/AppIcon.appiconset/icon-256@2x.png
Normal file
After Width: | Height: | Size: 125 KiB |
BIN
TwoTerm/Images.xcassets/AppIcon.appiconset/icon-32.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
TwoTerm/Images.xcassets/AppIcon.appiconset/icon-32@2x.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
TwoTerm/Images.xcassets/AppIcon.appiconset/icon-512.png
Normal file
After Width: | Height: | Size: 123 KiB |
BIN
TwoTerm/Images.xcassets/AppIcon.appiconset/icon-512@2x.png
Normal file
After Width: | Height: | Size: 405 KiB |
5
TwoTerm/TwoTerm.entitlements
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict/>
|
||||
</plist>
|
|
@ -111,6 +111,8 @@ private:
|
|||
-(void)processData: (uint8_t *)data size: (size_t)size;
|
||||
-(void)childFinished: (int)status;
|
||||
-(void)childBegan;
|
||||
|
||||
-(void)reset;
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -143,19 +143,39 @@
|
|||
_screen.setFD(fd);
|
||||
}
|
||||
|
||||
-(void)setCharacterGenerator: (CharacterGenerator *)generator {
|
||||
if (generator != _charGen) {
|
||||
[_charGen release];
|
||||
_charGen = [generator retain];
|
||||
NSSize size = [_charGen characterSize];
|
||||
_charWidth = size.width;
|
||||
_charHeight = size.height;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
-(void)setEmulator:(NSObject<Emulator> *)emulator {
|
||||
if (_emulator == emulator) return;
|
||||
[_emulator release];
|
||||
_emulator = [emulator retain];
|
||||
if ([emulator respondsToSelector: @selector(characterGenerator)]) {
|
||||
id cg = [emulator characterGenerator];
|
||||
if (cg) [self setCharacterGenerator: cg];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
NSSize size;
|
||||
|
||||
_charWidth = 7;
|
||||
_charHeight = 16;
|
||||
|
||||
_paddingLeft = 8;
|
||||
_paddingTop = 8;
|
||||
_paddingBottom = 8;
|
||||
_fd = 1;
|
||||
_fd = -1;
|
||||
|
||||
//_foregroundColor = [[NSColor greenColor] retain];
|
||||
//_backgroundColor = [[NSColor blackColor] retain];
|
||||
|
@ -168,7 +188,7 @@
|
|||
_screen.setFD(_fd);
|
||||
_screen.setView(self);
|
||||
|
||||
_charGen = [[CharacterGenerator generator] retain];
|
||||
[self setCharacterGenerator: [CharacterGenerator generatorForCharacterSet: CGApple80]];
|
||||
|
||||
_cursorType = Screen::CursorTypeUnderscore;
|
||||
|
||||
|
@ -179,10 +199,6 @@
|
|||
_cursors[Screen::CursorTypeCrossHatch] = [[_charGen imageForCharacter: 0x7f] retain];
|
||||
|
||||
|
||||
size = [_charGen characterSize];
|
||||
_charWidth = size.width;
|
||||
_charHeight = size.height;
|
||||
|
||||
// enable drag+drop for files/urls.
|
||||
|
||||
|
||||
|
@ -233,6 +249,10 @@
|
|||
[self becomeFirstResponder];
|
||||
}
|
||||
|
||||
-(BOOL)canBecomeKeyView {
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(BOOL)acceptsFirstResponder
|
||||
{
|
||||
return YES;
|
||||
|
@ -323,9 +343,9 @@
|
|||
{
|
||||
|
||||
// mouse text actually requires mouse text and inverse to be on.
|
||||
if (flag & Screen::FlagMouseText)
|
||||
if ((flag & Screen::FlagMouseText) && c >= '@' && c <= '_')
|
||||
{
|
||||
if (c >= '@' && c <= '_') c |= 0x80;
|
||||
c |= 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -868,7 +888,12 @@
|
|||
}
|
||||
|
||||
|
||||
|
||||
-(void)reset {
|
||||
_screen.eraseScreen();
|
||||
_screen.setCursor(iPoint(0,0));
|
||||
_cursorOn = YES;
|
||||
[self setNeedsDisplay: YES];
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#import <AppKit/AppKit.h>
|
||||
@class TextLabel;
|
||||
@class CharacterGenerator;
|
||||
|
||||
@interface EmulatorWindow : NSWindow
|
||||
{
|
||||
|
@ -16,5 +17,5 @@
|
|||
@property (assign) IBOutlet TextLabel *textLabel;
|
||||
|
||||
-(void)setTitleTextColor: (NSColor *)color;
|
||||
|
||||
-(void)setTitleCharacterGenerator: (CharacterGenerator *)characterGenerator;
|
||||
@end
|
||||
|
|
|
@ -85,6 +85,11 @@
|
|||
[super setBackgroundColor: color];
|
||||
}
|
||||
|
||||
-(void)setTitleCharacterGenerator: (CharacterGenerator *)characterGenerator {
|
||||
[_textLabel setCharacterGenerator: characterGenerator];
|
||||
}
|
||||
|
||||
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
|
||||
|
|
16
Views/RolloverButton.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// RolloverButton.h
|
||||
// TwoTerm
|
||||
//
|
||||
// Created by Kelvin Sherlock on 2/13/2018.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface RolloverButton : NSButton {
|
||||
NSImage *_image;
|
||||
NSImage *_rolloverImage;
|
||||
NSTrackingArea *_trackingArea;
|
||||
BOOL _rollOver;
|
||||
}
|
||||
@end
|
98
Views/RolloverButton.m
Normal file
|
@ -0,0 +1,98 @@
|
|||
//
|
||||
// RolloverButton.m
|
||||
// TwoTerm
|
||||
//
|
||||
// Created by Kelvin Sherlock on 2/13/2018.
|
||||
//
|
||||
|
||||
#import "RolloverButton.h"
|
||||
|
||||
@implementation RolloverButton
|
||||
|
||||
#if 0
|
||||
- (void)createTrackingArea
|
||||
{
|
||||
NSTrackingAreaOptions focusTrackingAreaOptions = 0;
|
||||
focusTrackingAreaOptions |= NSTrackingActiveInActiveApp;
|
||||
focusTrackingAreaOptions |= NSTrackingMouseEnteredAndExited;
|
||||
//focusTrackingAreaOptions |= NSTrackingAssumeInside;
|
||||
focusTrackingAreaOptions |= NSTrackingInVisibleRect;
|
||||
|
||||
NSTrackingArea *focusTrackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
|
||||
options:focusTrackingAreaOptions
|
||||
owner:self userInfo:nil];
|
||||
[self addTrackingArea:focusTrackingArea];
|
||||
[focusTrackingArea release];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
- (void) updateTrackingAreas {
|
||||
[super updateTrackingAreas];
|
||||
if (_trackingArea) {
|
||||
[self removeTrackingArea: _trackingArea];
|
||||
[_trackingArea release];
|
||||
}
|
||||
|
||||
NSTrackingAreaOptions options = 0;
|
||||
options |= NSTrackingActiveInActiveApp;
|
||||
options |= NSTrackingMouseEnteredAndExited;
|
||||
//options |= NSTrackingAssumeInside;
|
||||
options |= NSTrackingInVisibleRect;
|
||||
|
||||
_trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
|
||||
options:options
|
||||
owner:self
|
||||
userInfo:nil];
|
||||
[self addTrackingArea: _trackingArea];
|
||||
}
|
||||
|
||||
|
||||
-(void)setImage:(NSImage *)image {
|
||||
if (_image != image) {
|
||||
[_image release];
|
||||
_image = [image retain];
|
||||
}
|
||||
if (!_rollOver) [super setImage: image];
|
||||
}
|
||||
|
||||
-(void)setRolloverImage: (NSImage *)image {
|
||||
|
||||
if (_rolloverImage != image) {
|
||||
[_rolloverImage release];
|
||||
_rolloverImage = [image retain];
|
||||
}
|
||||
if (_rollOver) [super setImage: image];
|
||||
}
|
||||
|
||||
-(void)awakeFromNib {
|
||||
[super awakeFromNib];
|
||||
//[self createTrackingArea];
|
||||
|
||||
[self setImage: [NSImage imageNamed: @"TabClose"]];
|
||||
[self setRolloverImage: [NSImage imageNamed: @"TabClose_Rollover"]];
|
||||
[[self cell] setHighlightsBy: NSContentsCellMask];
|
||||
}
|
||||
|
||||
-(void)dealloc {
|
||||
[_image release];
|
||||
[_rolloverImage release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(void)mouseExited:(NSEvent *)event {
|
||||
|
||||
[[self cell] setImage: _image];
|
||||
_rollOver = NO;
|
||||
[super mouseExited: event];
|
||||
}
|
||||
|
||||
-(void) mouseEntered:(NSEvent *)event {
|
||||
|
||||
[[self cell] setImage: _rolloverImage];
|
||||
_rollOver = YES;
|
||||
|
||||
[super mouseEntered: event];
|
||||
}
|
||||
|
||||
@end
|
|
@ -8,12 +8,15 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class CharacterGenerator;
|
||||
|
||||
@interface TextLabel : NSView
|
||||
{
|
||||
NSString *_text;
|
||||
NSColor *_color;
|
||||
CharacterGenerator *_generator;
|
||||
}
|
||||
@property (nonatomic, retain) NSString *text;
|
||||
@property (nonatomic, retain) NSColor *color;
|
||||
|
||||
@property (nonatomic, retain) CharacterGenerator *characterGenerator;
|
||||
@end
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
@synthesize text = _text;
|
||||
@synthesize color = _color;
|
||||
@synthesize characterGenerator = _characterGenerator;
|
||||
|
||||
-(void) setText:(NSString *)text {
|
||||
if (_text == text) return;
|
||||
|
@ -29,6 +30,14 @@
|
|||
[self setNeedsDisplay: YES];
|
||||
}
|
||||
|
||||
-(void) setCharacterGenerator:(CharacterGenerator *)characterGenerator {
|
||||
if (_characterGenerator == characterGenerator) return;
|
||||
[_characterGenerator release];
|
||||
_characterGenerator = [characterGenerator retain];
|
||||
[self setNeedsDisplay: YES];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
-(BOOL)isFlipped {
|
||||
return YES;
|
||||
|
@ -42,6 +51,7 @@
|
|||
|
||||
[_text release];
|
||||
[_color release];
|
||||
[_characterGenerator release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -55,9 +65,7 @@
|
|||
if (!length) return;
|
||||
if (!_color) return;
|
||||
|
||||
CharacterGenerator *gen = [CharacterGenerator generator];
|
||||
|
||||
NSSize sz = [gen characterSize];
|
||||
NSSize sz = [_characterGenerator characterSize];
|
||||
|
||||
NSRect frame = [self frame];
|
||||
|
||||
|
@ -75,7 +83,7 @@
|
|||
for (unsigned i = 0; i < length; ++i) {
|
||||
unichar c = [_text characterAtIndex: i];
|
||||
|
||||
[gen drawCharacter: c atPoint: point];
|
||||
[_characterGenerator drawCharacter: c atPoint: point];
|
||||
point.x += sz.width;
|
||||
if (point.x > NSWidth(frame)) break;
|
||||
}
|
||||
|
@ -89,6 +97,7 @@
|
|||
|
||||
if (!_text) _text = [@"Testing!" retain];
|
||||
if (!_color) _color = [[NSColor greenColor] retain];
|
||||
if (!_characterGenerator) _characterGenerator = [[CharacterGenerator generatorForCharacterSet: CGApple80] retain];
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit b91763ed705d32ec0fc7cbdca84f9d597696b050
|
||||
Subproject commit c7b95dda17a1239b303d01eeca8c8f9fba3d2131
|
BIN
images/TabClose.tiff
Normal file
100
images/TabCloseButton.pdf
Normal file
BIN
images/TabCloseButton_Busy.tiff
Normal file
BIN
images/TabClose_Busy.tiff
Normal file
BIN
images/TabClose_Busy_Pressed.tiff
Normal file
BIN
images/TabClose_Busy_Rollover.tiff
Normal file
BIN
images/TabClose_Pressed.tiff
Normal file
BIN
images/TabClose_Rollover.tiff
Normal file
BIN
images/TabNewButton.tiff
Normal file
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.8 KiB |
BIN
images/a2-charset-40@2x.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
images/a2-charset-80@2x.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
images/vt100-charset@2x.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
images/vt52-charset@2x.png
Normal file
After Width: | Height: | Size: 2.9 KiB |