mirror of
https://github.com/ksherlock/TwoTerm.git
synced 2024-06-26 05:29:35 +00:00
git-svn-id: svn://qnap.local/TwoTerm/trunk@1658 5590a31f-7b70-45f8-8c82-aa3a8e5f4507
This commit is contained in:
parent
e956569350
commit
a9b1a2772f
File diff suppressed because it is too large
Load Diff
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
108
Screen.cpp
108
Screen.cpp
|
@ -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)
|
||||
{
|
||||
|
||||
|
|
10
Screen.h
10
Screen.h
|
@ -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
12
VT05.mm
|
@ -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
37
VT100.h
Normal 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
580
VT100.mm
Normal 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
59
VT52.mm
|
@ -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
|
||||
|
|
21
iGeometry.h
21
iGeometry.h
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user