git-svn-id: svn://qnap.local/TwoTerm/trunk@1658 5590a31f-7b70-45f8-8c82-aa3a8e5f4507

This commit is contained in:
Kelvin Sherlock 2010-07-17 18:21:26 +00:00
parent e956569350
commit a9b1a2772f
11 changed files with 1127 additions and 686 deletions

File diff suppressed because it is too large Load Diff

View File

@ -287,7 +287,7 @@
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
<array>
<array>
<integer>5</integer>
<integer>4</integer>
<integer>1</integer>
<integer>0</integer>
</array>
@ -310,7 +310,7 @@
<real>324</real>
</array>
<key>RubberWindowFrame</key>
<string>679 165 1060 902 0 0 1920 1178 </string>
<string>31 145 1060 902 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXSmartGroupTreeModule</string>
@ -326,7 +326,7 @@
<key>PBXProjectModuleGUID</key>
<string>B676054211DADB9000D6B66C</string>
<key>PBXProjectModuleLabel</key>
<string>Screen.cpp</string>
<string>VT52.mm</string>
<key>PBXSplitModuleInNavigatorKey</key>
<dict>
<key>Split0</key>
@ -334,11 +334,11 @@
<key>PBXProjectModuleGUID</key>
<string>B676054311DADB9000D6B66C</string>
<key>PBXProjectModuleLabel</key>
<string>Screen.cpp</string>
<string>VT52.mm</string>
<key>_historyCapacity</key>
<integer>0</integer>
<key>bookmark</key>
<string>B6E6A81111EAB37500A24C0C</string>
<string>B6A0F72A11F22CEE00AC3547</string>
<key>history</key>
<array>
<string>B676058811DAE21100D6B66C</string>
@ -361,7 +361,6 @@
<string>B6697A5411E7E072002ED475</string>
<string>B6697A5511E7E072002ED475</string>
<string>B6697A5611E7E072002ED475</string>
<string>B6697A5711E7E072002ED475</string>
<string>B6697A5811E7E072002ED475</string>
<string>B6697A5911E7E072002ED475</string>
<string>B6697A5A11E7E072002ED475</string>
@ -371,8 +370,12 @@
<string>B641C82311EA1B1600B6359F</string>
<string>B641C88811EA8DCC00B6359F</string>
<string>B6E6A7BD11EAA92100A24C0C</string>
<string>B6E6A80511EAB12B00A24C0C</string>
<string>B6E6A80711EAB12B00A24C0C</string>
<string>B64925C411EE622D0065E73A</string>
<string>B609786811EEB3DC00623E03</string>
<string>B609786911EEB3DC00623E03</string>
<string>B6A0F71A11F22CD200AC3547</string>
<string>B6A0F72811F22CEE00AC3547</string>
<string>B6A0F72911F22CEE00AC3547</string>
</array>
</dict>
<key>SplitCount</key>
@ -386,18 +389,18 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{0, 0}, {714, 413}}</string>
<string>{{0, 0}, {714, 344}}</string>
<key>RubberWindowFrame</key>
<string>679 165 1060 902 0 0 1920 1178 </string>
<string>31 145 1060 902 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXNavigatorGroup</string>
<key>Proportion</key>
<string>413pt</string>
<string>344pt</string>
</dict>
<dict>
<key>Proportion</key>
<string>443pt</string>
<string>512pt</string>
<key>Tabs</key>
<array>
<dict>
@ -411,7 +414,9 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {714, 416}}</string>
<string>{{10, 27}, {714, 485}}</string>
<key>RubberWindowFrame</key>
<string>31 145 1060 902 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>XCDetailModule</string>
@ -428,8 +433,6 @@
<dict>
<key>Frame</key>
<string>{{10, 27}, {714, 416}}</string>
<key>RubberWindowFrame</key>
<string>679 165 1060 902 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXProjectFindModule</string>
@ -488,7 +491,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {714, 405}}</string>
<string>{{10, 27}, {714, 461}}</string>
</dict>
<key>Module</key>
<string>PBXBuildResultsModule</string>
@ -516,11 +519,11 @@
</array>
<key>TableOfContents</key>
<array>
<string>B6E6A7C111EAA92400A24C0C</string>
<string>B6A0F71C11F22CD200AC3547</string>
<string>1CA23ED40692098700951B8B</string>
<string>B6E6A7C211EAA92400A24C0C</string>
<string>B6A0F71D11F22CD200AC3547</string>
<string>B676054211DADB9000D6B66C</string>
<string>B6E6A7C311EAA92400A24C0C</string>
<string>B6A0F71E11F22CD200AC3547</string>
<string>1CA23EDF0692099D00951B8B</string>
<string>1CA23EE00692099D00951B8B</string>
<string>1CA23EE10692099D00951B8B</string>
@ -571,12 +574,12 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{0, 0}, {1060, 279}}</string>
<string>{{0, 0}, {1060, 265}}</string>
</dict>
<key>Module</key>
<string>PBXDebugCLIModule</string>
<key>Proportion</key>
<string>279pt</string>
<string>265pt</string>
</dict>
<dict>
<key>ContentConfiguration</key>
@ -595,8 +598,8 @@
<string>yes</string>
<key>sizes</key>
<array>
<string>{{0, 0}, {517, 281}}</string>
<string>{{517, 0}, {543, 281}}</string>
<string>{{0, 0}, {517, 289}}</string>
<string>{{517, 0}, {543, 289}}</string>
</array>
</dict>
<key>VerticalSplitView</key>
@ -611,8 +614,8 @@
<string>yes</string>
<key>sizes</key>
<array>
<string>{{0, 0}, {1060, 281}}</string>
<string>{{0, 281}, {1060, 296}}</string>
<string>{{0, 0}, {1060, 289}}</string>
<string>{{0, 289}, {1060, 302}}</string>
</array>
</dict>
</dict>
@ -632,7 +635,7 @@
<key>DebugSTDIOWindowFrame</key>
<string>{{200, 200}, {500, 300}}</string>
<key>Frame</key>
<string>{{0, 284}, {1060, 577}}</string>
<string>{{0, 270}, {1060, 591}}</string>
<key>PBXDebugSessionStackFrameViewKey</key>
<dict>
<key>DebugVariablesTableConfiguration</key>
@ -645,13 +648,13 @@
<real>313</real>
</array>
<key>Frame</key>
<string>{{517, 0}, {543, 281}}</string>
<string>{{517, 0}, {543, 289}}</string>
</dict>
</dict>
<key>Module</key>
<string>PBXDebugSessionModule</string>
<key>Proportion</key>
<string>577pt</string>
<string>591pt</string>
</dict>
</array>
<key>Name</key>
@ -669,14 +672,14 @@
</array>
<key>TableOfContents</key>
<array>
<string>B6E6A7C411EAA92400A24C0C</string>
<string>B6A0F71F11F22CD200AC3547</string>
<string>1CCC7628064C1048000F2A68</string>
<string>1CCC7629064C1048000F2A68</string>
<string>B6E6A7C511EAA92400A24C0C</string>
<string>B6E6A7C611EAA92400A24C0C</string>
<string>B6E6A7C711EAA92400A24C0C</string>
<string>B6E6A7C811EAA92400A24C0C</string>
<string>B676054211DADB9000D6B66C</string>
<string>B6A0F72011F22CD200AC3547</string>
<string>B6A0F72111F22CD200AC3547</string>
<string>B6A0F72211F22CD200AC3547</string>
<string>B6A0F72311F22CD200AC3547</string>
<string>B6A0F72411F22CD200AC3547</string>
</array>
<key>ToolbarConfigUserDefaultsMinorVersion</key>
<string>2</string>
@ -710,14 +713,13 @@
<integer>5</integer>
<key>WindowOrderList</key>
<array>
<string>B6E6A81211EAB37500A24C0C</string>
<string>B6E6A7CA11EAA92400A24C0C</string>
<string>B6E6A7CB11EAA92400A24C0C</string>
<string>B6A0F72511F22CD200AC3547</string>
<string>B6A0F72611F22CD200AC3547</string>
<string>B6A0F72711F22CD200AC3547</string>
<string>/Users/kelvin/Projects/2Term/2Term.xcodeproj</string>
<string>B6E6A7DD11EAAB0200A24C0C</string>
</array>
<key>WindowString</key>
<string>679 165 1060 902 0 0 1920 1178 </string>
<string>31 145 1060 902 0 0 1920 1178 </string>
<key>WindowToolsV3</key>
<array>
<dict>

View File

@ -17,6 +17,7 @@
B60EBDE311E90FC300C1974F /* ScanLineFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B60EBDE211E90FC300C1974F /* ScanLineFilter.m */; };
B60EBDE811E9143F00C1974F /* ScanLineFilter.cikernel in Sources */ = {isa = PBXBuildFile; fileRef = B60EBDE711E9143F00C1974F /* ScanLineFilter.cikernel */; };
B60EBE2B11E918D500C1974F /* ScanLineFilter.cikernel in Resources */ = {isa = PBXBuildFile; fileRef = B60EBDE711E9143F00C1974F /* ScanLineFilter.cikernel */; };
B64925DA11EE6C350065E73A /* VT100.mm in Sources */ = {isa = PBXBuildFile; fileRef = B64925D911EE6C350065E73A /* VT100.mm */; };
B669798511E6A786002ED475 /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B669798411E6A786002ED475 /* Lock.cpp */; };
B6697A0F11E6BF95002ED475 /* CurveView.m in Sources */ = {isa = PBXBuildFile; fileRef = B6697A0E11E6BF95002ED475 /* CurveView.m */; };
B6697A3D11E7CCA0002ED475 /* PTSE.mm in Sources */ = {isa = PBXBuildFile; fileRef = B6697A3C11E7CCA0002ED475 /* PTSE.mm */; };
@ -59,6 +60,8 @@
B60EBDE111E90FC300C1974F /* ScanLineFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScanLineFilter.h; sourceTree = "<group>"; };
B60EBDE211E90FC300C1974F /* ScanLineFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScanLineFilter.m; sourceTree = "<group>"; };
B60EBDE711E9143F00C1974F /* ScanLineFilter.cikernel */ = {isa = PBXFileReference; explicitFileType = sourcecode.glsl; fileEncoding = 4; path = ScanLineFilter.cikernel; sourceTree = "<group>"; };
B64925D811EE6C350065E73A /* VT100.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VT100.h; sourceTree = "<group>"; };
B64925D911EE6C350065E73A /* VT100.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = VT100.mm; sourceTree = "<group>"; };
B669798311E6A786002ED475 /* Lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lock.h; sourceTree = "<group>"; };
B669798411E6A786002ED475 /* Lock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lock.cpp; sourceTree = "<group>"; };
B6697A0D11E6BF95002ED475 /* CurveView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CurveView.h; sourceTree = "<group>"; };
@ -220,6 +223,8 @@
B6F444C711E41AC000C3A836 /* VT05.mm */,
B699A08F11E572A300F54CC8 /* VT52.h */,
B699A09011E572A300F54CC8 /* VT52.mm */,
B64925D811EE6C350065E73A /* VT100.h */,
B64925D911EE6C350065E73A /* VT100.mm */,
);
name = Emulators;
sourceTree = "<group>";
@ -297,6 +302,7 @@
B60EBDE311E90FC300C1974F /* ScanLineFilter.m in Sources */,
B60EBDE811E9143F00C1974F /* ScanLineFilter.cikernel in Sources */,
B602376211E94D9800C0B73E /* iGeometry.cpp in Sources */,
B64925DA11EE6C350065E73A /* VT100.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -6,6 +6,7 @@
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#include <sys/ttycom.h>
@class NSEvent;
@ -17,6 +18,8 @@ class OutputChannel;
#define OutputChannel void
#endif
#import "iGeometry.h"
@protocol Emulator
-(void)processCharacter: (uint8_t)c screen: (Screen *)screen output: (OutputChannel *)output;
@ -27,4 +30,8 @@ class OutputChannel;
-(const char *)termName;
-(BOOL)resizable;
-(struct winsize)defaultSize;
@end

View File

@ -87,6 +87,23 @@ void Screen::putc(uint8_t c, bool incrementX)
}
}
void Screen::tabTo(unsigned xPos)
{
CharInfo clear(' ', _flag);
CharInfoIterator iter;
xPos = std::min(xPos, _width - 1);
for (unsigned x = _cursor.x; x < xPos; ++x)
{
_screen[_cursor.y][x] = clear;
}
_cursor.x = xPos;
}
void Screen::setX(int x, bool clamp)
{
if (x < 0)
@ -181,13 +198,35 @@ void Screen::eraseScreen()
}
void Screen::eraseRect(iRect rect)
{
unsigned maxX = std::min(_width, (unsigned)rect.maxX());
unsigned maxY = std::min(_height, (unsigned)rect.maxY());
CharInfo clear;
for (unsigned y = rect.minY(); y < maxY; ++y)
{
for (unsigned x = rect.minX(); x < maxX; ++x)
{
_screen[y][x] = clear;
}
}
_updates.push_back(rect.origin);
_updates.push_back(iPoint(maxX - 1, maxY - 1));
}
void Screen::lineFeed()
{
// moves the screen up one row, inserting a blank line at the bottom.
if (_cursor.y == _height - 1)
{
/*
// move lines 1..end up 1 line.
for (ScreenIterator iter = _screen.begin() + 1; iter < _screen.end(); ++iter)
{
@ -205,6 +244,9 @@ void Screen::lineFeed()
_updates.push_back(iPoint(0, 0));
_updates.push_back(iPoint(_width - 1, _height - 1));
*/
removeLine(0);
}
else
{
@ -212,13 +254,14 @@ void Screen::lineFeed()
}
}
void Screen::reverseLineFeed()
{
// moves the cursor down one row, inserting a blank line at the top.
if (_cursor.y == 0)
{
/*
for (ReverseScreenIterator iter = _screen.rbegin() + 1; iter < _screen.rend(); ++iter)
{
iter[-1] = *iter;
@ -235,15 +278,74 @@ void Screen::reverseLineFeed()
_updates.push_back(iPoint(0, 0));
_updates.push_back(iPoint(_width - 1, _height - 1));
*/
addLine(0);
}
else
{
_cursor.y--;
}
}
void Screen::addLine(unsigned line)
{
if (line >= _height) return;
if (line == _height - 1)
{
_screen.back().clear();
_screen.back().resize(_width);
}
else
{
std::vector<CharInfo> newLine;
ScreenIterator iter;
_screen.pop_back();
iter = _screen.insert(_screen.begin() + line, newLine);
iter->resize(_width);
}
_updates.push_back(iPoint(0, line));
_updates.push_back(iPoint(_width - 1, _height - 1));
}
void Screen::removeLine(unsigned line)
{
if (line >= _height) return;
if (line == _height - 1)
{
_screen.back().clear();
}
else
{
std::vector<CharInfo> newLine;
_screen.erase(_screen.begin() + line);
_screen.push_back(newLine);
}
_screen.back().resize(_width);
_updates.push_back(iPoint(0, line));
_updates.push_back(iPoint(_width - 1, _height - 1));
}
void Screen::setSize(unsigned width, unsigned height)
{

View File

@ -37,6 +37,7 @@ public:
static const unsigned FlagBold = 0x04;
static const unsigned FlagUnderscore = 0x08;
static const unsigned FlagBlink = 0x10;
static const unsigned FlagSelected = 0x20;
Screen(unsigned height = 24, unsigned width = 80);
@ -70,15 +71,24 @@ public:
void putc(uint8_t c, bool incrementX = true);
void tabTo(unsigned x);
CharInfo getc(int x, int y) const;
void eraseLine();
void eraseScreen();
void eraseRect(iRect rect);
void lineFeed();
void reverseLineFeed();
void addLine(unsigned line);
void removeLine(unsigned line);
void beginUpdate();
iRect endUpdate();

12
VT05.mm
View File

@ -239,4 +239,16 @@ enum {
}
}
-(BOOL)resizable
{
return NO;
}
-(struct winsize)defaultSize
{
struct winsize ws = { 20, 72, 0, 0 };
return ws;
}
@end

37
VT100.h Normal file
View File

@ -0,0 +1,37 @@
//
// VT100.h
// 2Term
//
// Created by Kelvin Sherlock on 7/14/2010.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "Emulator.h"
#include "iGeometry.h"
#ifdef __cplusplus
#include <vector>
#endif
@interface VT100 : NSObject <Emulator> {
unsigned _state;
BOOL _keyMode;
BOOL _vt52Mode;
BOOL _graphics;
iPoint _dca;
#ifdef __cplusplus
std::vector<int> _parms;
#endif
}
@end

580
VT100.mm Normal file
View File

@ -0,0 +1,580 @@
//
// VT100.mm
// 2Term
//
// Created by Kelvin Sherlock on 7/14/2010.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "VT100.h"
#include "Screen.h"
#include "OutputChannel.h"
#include <sys/ttydefaults.h>
@implementation VT100
#define ESC "\x1b"
enum {
StateText,
StateEsc,
StateDCAY,
StateDCAX,
StateBracket,
StatePound
};
-(NSString *)name
{
return @"VT100";
}
-(const char *)termName
{
return "vt100";
}
-(BOOL)resizable
{
return YES;
}
-(struct winsize)defaultSize
{
struct winsize ws = { 24, 80, 0, 0};
return ws;
}
-(void)reset
{
_state = StateText;
_vt52Mode = NO;
}
-(void)vt52ProcessCharacter:(uint8_t)c screen:(Screen *)screen output:(OutputChannel *)output
{
if (_state == StateEsc)
{
switch (c)
{
case 0x00:
case 0x7f:
break;
case 'A':
// cursor up
screen->decrementY();
_state = StateText;
break;
case 'B':
// cursor down
screen->incrementY();
_state = StateText;
break;
case 'C':
// cursor right
screen->incrementX();
_state = StateText;
break;
case 'D':
screen->decrementX();
_state = StateText;
break;
case 'F':
// graphics character set on
_state = StateText;
break;
case 'G':
// graphics character set off.
_state = StateText;
break;
case 'H':
// home
screen->setCursor(0, 0);
_state = StateText;
break;
case 'I':
// inverse line feed.
screen->reverseLineFeed();
_state = StateText;
break;
case 'J':
// erase to end of screen
screen->eraseScreen();
_state = StateText;
break;
case 'K':
//erase to end of line.
screen->eraseLine();
_state = StateText;
break;
case 'Y':
// dca
_state = StateDCAY;
break;
case 'Z':
//identify
output->write(ESC "/Z");
_state = StateText;
break;
case '=':
// alt key pad
_keyMode = YES;
_state = StateText;
break;
case '>':
_keyMode = NO;
_state = StateText;
break;
case '1':
// graphics on
_state = StateText;
break;
case '2':
// graphics off
_state = StateText;
break;
case '<':
// ansi mode
_vt52Mode = NO;
_state = StateText;
break;
default:
NSLog(@"[%s %s]: unrecognized escape character: `%c' (%02x)", object_getClassName(self), sel_getName(_cmd), c, (int)c);
_state = StateText;
}
}
else if (_state == StateDCAY)
{
if (c == 0x00) return;
_dca.y = c - 0x20;
_state = StateDCAX;
}
else if (_state = StateDCAX)
{
if (c == 0x00) return;
_dca.x = c - 0x20;
/*
* If the line # does not specify a line that exists on the screen, the VT50H
* will move the cursor to the bottom line of the screen. However, the VT52 will
* not move the cursor vertically if the vertical parameter is out of bounds.
*/
/*
* If the column number is greater than 157 and, therefore, does not specify a column
* that exists on the screen, the cursor is moved to the rightmost column on a line on all models.
*/
screen->setCursor(_dca, true, false);
_state = StateText;
}
}
-(void)processCharacter:(uint8_t)c screen:(Screen *)screen output:(OutputChannel *)output
{
if (_vt52Mode && _state != StateText)
{
[self vt52ProcessCharacter: c screen: screen output: output];
return;
}
if (_state == StateBracket)
{
// '[' [0-9]* CODE
// '[' [0-9]+ (';' [0-9]+)* CODE
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
_parms.back() = _parms.back() * 10 + (c - '0');
break;
case ';':
_parms.push_back(0);
break;
case 'A':
// cursor up. default 1.
{
int count = std::max(_parms[0], 1);
screen->setY(screen->y() - count);
_state = StateText;
break;
}
case 'B':
// cursor down. default 1.
{
int count = std::max(_parms[0], 1);
screen->setY(screen->y() + count);
_state = StateText;
break;
}
case 'C':
// cursor forward. default 1.
{
int count = std::max(_parms[0], 1);
screen->setX(screen->x() + count);
_state = StateText;
break;
}
case 'D':
// cursor back. default 1.
{
int count = std::max(_parms[0], 1);
screen->setX(screen->x() - count);
_state = StateText;
break;
}
case 'H':
case 'f':
// set cursor position.
// line numbering depends on DECOM.
//
if (_parms.size() == 2)
{
// 0 = line
// 1 = column
screen->setCursor(std::max(_parms[1], 1) - 1, std::max(_parms[1],1) - 1);
}
else screen->setCursor(0, 0);
_state = StateText;
break;
}
if (_state == StateText) _parms.clear();
return;
}
if (_state == StateEsc)
{
switch(c)
{
case 0x00:
case 0x07f:
break;
case '[':
_state = StateBracket;
_parms.clear();
_parms.push_back(0);
break;
case '#':
_state = StatePound;
break;
case 'D':
// Index
screen->lineFeed();
_state = StateText;
break;
case 'M':
// Reverse Index
screen->reverseLineFeed();
_state = StateText;
break;
case '7':
// save cursor + attributes
case '8':
//restore cursor + attributes.
_state = StateText;
break;
}
}
}
static void commonKey(unichar uc, unsigned flags, Screen * screen, OutputChannel *output)
{
switch (uc)
{
case NSDeleteCharacter:
output->write(0x7f);
break;
default:
if (uc <= 0x7f)
{
char c = uc;
if (flags & NSControlKeyMask)
c = CTRL(c);
output->write(c);
}
}
}
static void keyModeKey(unichar uc, unsigned flags, Screen * screen, OutputChannel *output)
{
if (flags & NSNumericPadKeyMask)
{
const char *str = NULL;
switch(uc)
{
case '0':
str = ESC "Op";
break;
case '1':
str = ESC "Oq";
break;
case '2':
str = ESC "Or";
break;
case '3':
str = ESC "Os";
break;
case '4':
str = ESC "Ot";
break;
case '5':
str = ESC "Ou";
break;
case '6':
str = ESC "Ov";
break;
case '7':
str = ESC "Ow";
break;
case '8':
str = ESC "Ox";
break;
case '9':
str = ESC "Oy";
break;
case ',':
str = ESC "Ol";
break;
case '-':
str = ESC "Om";
break;
case '.':
str = ESC "On";
break;
case NSNewlineCharacter: //?
case NSEnterCharacter:
str = ESC "?M";
break;
}
if (str)
{
output->write(str);
return;
}
}
switch(uc)
{
case NSUpArrowFunctionKey:
output->write(ESC "OA");
break;
case NSDownArrowFunctionKey:
output->write(ESC "OB");
break;
case NSRightArrowFunctionKey:
output->write(ESC "OC");
break;
case NSLeftArrowFunctionKey:
output->write(ESC "OD");
break;
// these are located at numlock/*-
case NSF1FunctionKey:
output->write(ESC "OP");
break;
case NSF2FunctionKey:
output->write(ESC "OQ");
break;
case NSF3FunctionKey:
output->write(ESC "OR");
break;
case NSF4FunctionKey:
output->write(ESC "OS");
break;
default:
commonKey(uc, flags, screen, output);
break;
}
}
static void vt52ModeKey(unichar uc, unsigned flags, Screen * screen, OutputChannel *output)
{
if (flags & NSNumericPadKeyMask)
{
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 "?l";
break;
case '-':
str = ESC "?m";
break;
case '.':
str = ESC "?n";
break;
case NSNewlineCharacter: //?
case NSEnterCharacter:
str = ESC "?M";
break;
}
if (str)
{
output->write(str);
return;
}
}
switch(uc)
{
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;
case NSF1FunctionKey:
output->write(ESC "P");
break;
case NSF2FunctionKey:
output->write(ESC "Q");
break;
case NSF3FunctionKey:
output->write(ESC "R");
break;
case NSF4FunctionKey:
output->write(ESC "S");
break;
default:
commonKey(uc, flags, screen, output);
break;
}
}
-(void)keyDown:(NSEvent *)event screen:(Screen *)screen output:(OutputChannel *)output
{
unsigned flags = [event modifierFlags];
NSString *chars = [event charactersIgnoringModifiers];
unsigned length = [chars length];
for (unsigned i = 0; i < length; ++i)
{
unichar uc = [chars characterAtIndex: i];
if (_vt52Mode)
vt52ModeKey(uc, flags, screen, output);
else if (_keyMode)
keyModeKey(uc, flags, screen, output);
else
commonKey(uc, flags, screen, output);
}
}
@end

59
VT52.mm
View File

@ -20,6 +20,11 @@ enum {
StateDCAX
};
/*
* TODO -- the VT50x are 12 rows but double spaced.
*
*
*/
// VT52 is 24 x 80 upper/lowercase.
// 50/50H is 12 * 80, uppercase only. H has a keypad.
@ -74,8 +79,7 @@ enum {
unsigned flags = [event modifierFlags];
NSString *chars = [event charactersIgnoringModifiers];
unsigned length = [chars length];
for (unsigned i = 0; i < length; ++i)
{
unichar uc = [chars characterAtIndex: i];
@ -158,6 +162,20 @@ enum {
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;
@ -488,4 +506,41 @@ enum {
}
-(BOOL)resizable
{
switch (_model)
{
case ModelVT52:
case ModelVT55:
return YES;
default:
return NO;
}
}
-(struct winsize)defaultSize
{
struct winsize ws = { 0, 0, 0, 0};
// TODO -- although VT50x have 12 rows, they are double spaced.
switch (_model)
{
case ModelVT52:
case ModelVT55:
ws.ws_row = 24;
ws.ws_col = 80;
break;
default:
ws.ws_row = 12;
ws.ws_col = 80;
break;
}
return ws;
}
@end

View File

@ -76,6 +76,27 @@ typedef struct iRect {
bool contains(const iRect aRect) const;
bool intersects(const iRect aRect) const;
int height() const
{ return size.height; }
int width() const
{ return size.width; }
int minX() const
{ return origin.x; }
int minY() const
{ return origin.y; }
int maxX() const
{ return minX() + width(); }
int maxY() const
{ return minY() + height(); }
#endif
} iRect;