Refactor TS build and fix testing

This change is largely just moving files with minor tweaks to them to fix,
the rest of the commit is build process changes:

- The addons/ and test/ dirs have been moved to src/
- The build directory has been removed
- TypeScript builds are output in out/, this is where tests are run
- The demo now relies on the dist/ build which is performed as part of ./bin/build
- Addons are now shipped under the ./build directory
This commit is contained in:
Daniel Imms
2016-10-31 21:22:21 -07:00
parent a995b610cf
commit 56ecc77dfc
174 changed files with 50 additions and 37 deletions
+134
View File
@@ -0,0 +1,134 @@
/*
* Implements the attach method, that
* attaches the terminal to a WebSocket stream.
*
* The bidirectional argument indicates, whether the terminal should
* send data to the socket as well and is true, by default.
*/
(function (attach) {
if (typeof exports === 'object' && typeof module === 'object') {
/*
* CommonJS environment
*/
module.exports = attach(require('../../xterm'));
} else if (typeof define == 'function') {
/*
* Require.js is available
*/
define(['../../xterm'], attach);
} else {
/*
* Plain browser environment
*/
attach(window.Terminal);
}
})(function (Xterm) {
'use strict';
/**
* This module provides methods for attaching a terminal to a WebSocket
* stream.
*
* @module xterm/addons/attach/attach
*/
var exports = {};
/**
* Attaches the given terminal to the given socket.
*
* @param {Xterm} term - The terminal to be attached to the given socket.
* @param {WebSocket} socket - The socket to attach the current terminal.
* @param {boolean} bidirectional - Whether the terminal should send data
* to the socket as well.
* @param {boolean} buffered - Whether the rendering of incoming data
* should happen instantly or at a maximum
* frequency of 1 rendering per 10ms.
*/
exports.attach = function (term, socket, bidirectional, buffered) {
bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional;
term.socket = socket;
term._flushBuffer = function () {
term.write(term._attachSocketBuffer);
term._attachSocketBuffer = null;
clearTimeout(term._attachSocketBufferTimer);
term._attachSocketBufferTimer = null;
};
term._pushToBuffer = function (data) {
if (term._attachSocketBuffer) {
term._attachSocketBuffer += data;
} else {
term._attachSocketBuffer = data;
setTimeout(term._flushBuffer, 10);
}
};
term._getMessage = function (ev) {
if (buffered) {
term._pushToBuffer(ev.data);
} else {
term.write(ev.data);
}
};
term._sendData = function (data) {
socket.send(data);
};
socket.addEventListener('message', term._getMessage);
if (bidirectional) {
term.on('data', term._sendData);
}
socket.addEventListener('close', term.detach.bind(term, socket));
socket.addEventListener('error', term.detach.bind(term, socket));
};
/**
* Detaches the given terminal from the given socket
*
* @param {Xterm} term - The terminal to be detached from the given socket.
* @param {WebSocket} socket - The socket from which to detach the current
* terminal.
*/
exports.detach = function (term, socket) {
term.off('data', term._sendData);
socket = (typeof socket == 'undefined') ? term.socket : socket;
if (socket) {
socket.removeEventListener('message', term._getMessage);
}
delete term.socket;
};
/**
* Attaches the current terminal to the given socket
*
* @param {WebSocket} socket - The socket to attach the current terminal.
* @param {boolean} bidirectional - Whether the terminal should send data
* to the socket as well.
* @param {boolean} buffered - Whether the rendering of incoming data
* should happen instantly or at a maximum
* frequency of 1 rendering per 10ms.
*/
Xterm.prototype.attach = function (socket, bidirectional, buffered) {
return exports.attach(this, socket, bidirectional, buffered);
};
/**
* Detaches the current terminal from the given socket.
*
* @param {WebSocket} socket - The socket from which to detach the current
* terminal.
*/
Xterm.prototype.detach = function (socket) {
return exports.detach(this, socket);
};
return exports;
});
+93
View File
@@ -0,0 +1,93 @@
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="../../src/xterm.css" />
<link rel="stylesheet" href="../../demo/style.css" />
<script src="../../src/xterm.js"></script>
<script src="attach.js"></script>
<style>
body {
color: #111;
}
h1, h2 {
color: #444;
border-bottom: 1px solid #ddd;
text-align: left;
}
form {
margin-bottom: 32px;
}
input, button {
line-height: 22px;
font-size: 16px;
display: inline-block;
border-radius: 2px;
border: 1px solid #ccc;
}
input {
height: 22px;
padding-left: 4px;
padding-right: 4px;
}
button {
height: 28px;
background-color: #ccc;
cursor: pointer;
color: #333;
}
.container {
max-width: 900px;
margin: 0 auto;
}
</style>
</head>
<body>
<div class="container">
<h1>
xterm.js: socket attach
</h1>
<p>
Attach the terminal to a WebSocket terminal stream with ease. Perfect for attaching to your
Docker containers.
</p>
<h2>
Socket information
</h2>
<form id="socket-form">
<input id="socket-url"
type="text"
placeholder="Enter socket url (e.g. ws://mysock)"
autofocus />
<button>
Attach
</button>
</form>
<div id="terminal-container"></div>
</div>
<script>
var term = new Terminal(),
container = document.getElementById('terminal-container'),
socketUrl = document.getElementById('socket-url'),
socketForm = document.getElementById('socket-form');
socketForm.addEventListener('submit', function (ev) {
ev.preventDefault();
var url = socketUrl.value,
sock = new WebSocket(url);
sock.addEventListener('open', function () {
term.attach(sock);
});
});
term.open(container);
</script>
</body>
</html>
+5
View File
@@ -0,0 +1,5 @@
{
"name": "xterm.attach",
"main": "attach.js",
"private": true
}
+86
View File
@@ -0,0 +1,86 @@
/*
* Fit terminal columns and rows to the dimensions of its
* DOM element.
*
* Approach:
* - Rows: Truncate the division of the terminal parent element height
* by the terminal row height
*
* - Columns: Truncate the division of the terminal parent element width by
* the terminal character width (apply display: inline at the
* terminal row and truncate its width with the current number
* of columns)
*/
(function (fit) {
if (typeof exports === 'object' && typeof module === 'object') {
/*
* CommonJS environment
*/
module.exports = fit(require('../../xterm'));
} else if (typeof define == 'function') {
/*
* Require.js is available
*/
define(['../../xterm'], fit);
} else {
/*
* Plain browser environment
*/
fit(window.Terminal);
}
})(function (Xterm) {
/**
* This module provides methods for fitting a terminal's size to a parent container.
*
* @module xterm/addons/fit/fit
*/
var exports = {};
exports.proposeGeometry = function (term) {
var parentElementStyle = window.getComputedStyle(term.element.parentElement),
parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')),
parentElementWidth = parseInt(parentElementStyle.getPropertyValue('width')),
elementStyle = window.getComputedStyle(term.element),
elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')),
elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')),
availableHeight = parentElementHeight - elementPaddingVer,
availableWidth = parentElementWidth - elementPaddingHor,
container = term.rowContainer,
subjectRow = term.rowContainer.firstElementChild,
contentBuffer = subjectRow.innerHTML,
characterHeight,
rows,
characterWidth,
cols,
geometry;
subjectRow.style.display = 'inline';
subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace
characterWidth = subjectRow.getBoundingClientRect().width;
subjectRow.style.display = ''; // Revert style before calculating height, since they differ.
characterHeight = parseInt(subjectRow.offsetHeight);
subjectRow.innerHTML = contentBuffer;
rows = parseInt(availableHeight / characterHeight);
cols = parseInt(availableWidth / characterWidth) - 1;
geometry = {cols: cols, rows: rows};
return geometry;
};
exports.fit = function (term) {
var geometry = exports.proposeGeometry(term);
term.resize(geometry.cols, geometry.rows);
};
Xterm.prototype.proposeGeometry = function () {
return exports.proposeGeometry(this);
};
Xterm.prototype.fit = function () {
return exports.fit(this);
};
return exports;
});
+5
View File
@@ -0,0 +1,5 @@
{
"name": "xterm.fit",
"main": "fit.js",
"private": true
}
+10
View File
@@ -0,0 +1,10 @@
.xterm.fullscreen {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: auto;
height: auto;
z-index: 255;
}
+52
View File
@@ -0,0 +1,52 @@
/*
* Fullscreen addon for xterm.js
*
* Implements the toggleFullscreen function.
*
* If the `fullscreen` argument has been supplied, then
* if it is true, the fullscreen mode gets turned on,
* if it is false or null, the fullscreen mode gets turned off.
*
* If the `fullscreen` argument has not been supplied, the
* fullscreen mode is being toggled.
*/
(function (fullscreen) {
if (typeof exports === 'object' && typeof module === 'object') {
/*
* CommonJS environment
*/
module.exports = fullscreen(require('../../xterm'));
} else if (typeof define == 'function') {
/*
* Require.js is available
*/
define(['../../xterm'], fullscreen);
} else {
/*
* Plain browser environment
*/
fullscreen(window.Terminal);
}
})(function (Xterm) {
var exports = {};
exports.toggleFullScreen = function (term, fullscreen) {
var fn;
if (typeof fullscreen == 'undefined') {
fn = (term.element.classList.contains('fullscreen')) ? 'remove' : 'add';
} else if (!fullscreen) {
fn = 'remove';
} else {
fn = 'add';
}
term.element.classList[fn]('fullscreen');
};
Xterm.prototype.toggleFullscreen = function (fullscreen) {
exports.toggleFullScreen(this, fullscreen);
};
return exports;
});
+5
View File
@@ -0,0 +1,5 @@
{
"name": "xterm.fullscreen",
"main": "fullscreen.js",
"private": true
}
+36
View File
@@ -0,0 +1,36 @@
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="../../src/xterm.css" />
<link rel="stylesheet" href="../../demo/style.css" />
<script src="../../src/xterm.js"></script>
<script src="linkify.js"></script>
<style>
body {
color: #111;
}
#terminal-container {
max-width: 900px;
margin: 0 auto;
}
#terminal-container a {
color: #fff;
}
</style>
</head>
<body>
<div id="terminal-container"></div>
<script>
var term = new Terminal(),
container = document.getElementById('terminal-container');
term.open(container);
term.writeln('Hello, welcome to xterm.js');
term.writeln('');
term.writeln('Check it out at github.com/sourcelair/xterm.js');
term.linkify();
</script>
</body>
</html>
+207
View File
@@ -0,0 +1,207 @@
(function (linkify) {
if (typeof exports === 'object' && typeof module === 'object') {
/*
* CommonJS environment
*/
module.exports = linkify(require('../../xterm'));
} else if (typeof define == 'function') {
/*
* Require.js is available
*/
define(['../../xterm'], linkify);
} else {
/*
* Plain browser environment
*/
linkify(window.Terminal);
}
})(function (Xterm) {
'use strict';
/**
* This module provides methods for convertings valid URL substrings
* into HTML anchor elements (links), inside a terminal view.
*
* @module xterm/addons/linkify/linkify
*/
var exports = {},
protocolClause = '(https?:\\/\\/)',
domainCharacterSet = '[\\da-z\\.-]+',
negatedDomainCharacterSet = '[^\\da-z\\.-]+',
domainBodyClause = '(' + domainCharacterSet + ')',
tldClause = '([a-z\\.]{2,6})',
ipClause = '((\\d{1,3}\\.){3}\\d{1,3})',
portClause = '(:\\d{1,5})',
hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + ')' + portClause + '?',
pathClause = '(\\/[\\/\\w\\.-]*)*',
negatedPathCharacterSet = '[^\\/\\w\\.-]+',
bodyClause = hostClause + pathClause,
start = '(?:^|' + negatedDomainCharacterSet + ')(',
end = ')($|' + negatedPathCharacterSet + ')',
lenientUrlClause = start + protocolClause + '?' + bodyClause + end,
strictUrlClause = start + protocolClause + bodyClause + end,
lenientUrlRegex = new RegExp(lenientUrlClause),
strictUrlRegex = new RegExp(strictUrlClause);
/**
* Converts all valid URLs found in the given terminal line into
* hyperlinks. The terminal line can be either the HTML element itself
* or the index of the termina line in the children of the terminal
* rows container.
*
* @param {Xterm} terminal - The terminal that owns the given line.
* @param {number|HTMLDivElement} line - The terminal line that should get
* "linkified".
* @param {boolean} lenient - The regex type that will be used to identify links. If lenient is
* false, the regex requires a protocol clause. Defaults to true.
* @param {string} target - Sets target="" attribute with value provided to links.
* Default doesn't set target attribute
* @emits linkify
* @emits linkify:line
*/
exports.linkifyTerminalLine = function (terminal, line, lenient, target) {
if (typeof line == 'number') {
line = terminal.rowContainer.children[line];
} else if (! (line instanceof HTMLDivElement)) {
var message = 'The "line" argument should be either a number';
message += ' or an HTMLDivElement';
throw new TypeError(message);
}
if (typeof target === 'undefined') {
target = '';
} else {
target = 'target="' + target + '"';
}
var buffer = document.createElement('span'),
nodes = line.childNodes;
for (var j=0; j<nodes.length; j++) {
var node = nodes[j],
match;
/**
* Since we cannot access the TextNode's HTML representation
* from the instance itself, we assign its data as textContent
* to a dummy buffer span, in order to retrieve the TextNode's
* HTML representation from the buffer's innerHTML.
*/
buffer.textContent = node.data;
var nodeHTML = buffer.innerHTML;
/**
* Apply function only on TextNodes
*/
if (node.nodeType != node.TEXT_NODE) {
continue;
}
var url = exports.findLinkMatch(node.data, lenient);
if (!url) {
continue;
}
var startsWithProtocol = new RegExp('^' + protocolClause),
urlHasProtocol = url.match(startsWithProtocol),
href = (urlHasProtocol) ? url : 'http://' + url,
link = '<a href="' + href + '" ' + target + '>' + url + '</a>',
newHTML = nodeHTML.replace(url, link);
line.innerHTML = line.innerHTML.replace(nodeHTML, newHTML);
}
/**
* This event gets emitted when conversion of all URL susbtrings
* to HTML anchor elements (links) has finished, for a specific
* line of the current Xterm instance.
*
* @event linkify:line
*/
terminal.emit('linkify:line', line);
};
/**
* Finds a link within a block of text.
*
* @param {string} text - The text to search .
* @param {boolean} lenient - Whether to use the lenient search.
* @return {string} A URL.
*/
exports.findLinkMatch = function (text, lenient) {
var match = text.match(lenient ? lenientUrlRegex : strictUrlRegex);
if (!match || match.length === 0) {
return null;
}
return match[1];
}
/**
* Converts all valid URLs found in the terminal view into hyperlinks.
*
* @param {Xterm} terminal - The terminal that should get "linkified".
* @param {boolean} lenient - The regex type that will be used to identify links. If lenient is
* false, the regex requires a protocol clause. Defaults to true.
* @param {string} target - Sets target="" attribute with value provided to links.
* Default doesn't set target attribute
* @emits linkify
* @emits linkify:line
*/
exports.linkify = function (terminal, lenient, target) {
var rows = terminal.rowContainer.children;
lenient = (typeof lenient == "boolean") ? lenient : true;
for (var i=0; i<rows.length; i++) {
var line = rows[i];
exports.linkifyTerminalLine(terminal, line, lenient, target);
}
/**
* This event gets emitted when conversion of all URL substrings to
* HTML anchor elements (links) has finished for the current Xterm
* instance's view.
*
* @event linkify
*/
terminal.emit('linkify');
};
/**
* Extend Xterm prototype.
*/
/**
* Converts all valid URLs found in the current terminal linte into
* hyperlinks.
*
* @memberof Xterm
* @param {number|HTMLDivElement} line - The terminal line that should get
* "linkified".
* @param {boolean} lenient - The regex type that will be used to identify links. If lenient is
* false, the regex requires a protocol clause. Defaults to true.
* @param {string} target - Sets target="" attribute with value provided to links.
* Default doesn't set target attribute
*/
Xterm.prototype.linkifyTerminalLine = function (line, lenient, target) {
return exports.linkifyTerminalLine(this, line, lenient, target);
};
/**
* Converts all valid URLs found in the current terminal into hyperlinks.
*
* @memberof Xterm
* @param {boolean} lenient - The regex type that will be used to identify links. If lenient is
* false, the regex requires a protocol clause. Defaults to true.
* @param {string} target - Sets target="" attribute with value provided to links.
* Default doesn't set target attribute
*/
Xterm.prototype.linkify = function (lenient, target) {
return exports.linkify(this, lenient, target);
};
return exports;
});
+5
View File
@@ -0,0 +1,5 @@
{
"name": "xterm.linkify",
"main": "linkify.js",
"private": true
}
+5
View File
@@ -0,0 +1,5 @@
{
"name": "xterm.terminado",
"main": "terminado.js",
"private": true
}
+142
View File
@@ -0,0 +1,142 @@
/*
* Implements the attach method that
* attaches the terminal to a Terminado WebSocket stream.
*
* The bidirectional argument indicates, whether the terminal should
* send data to the socket as well and is true, by default.
*/
(function (attach) {
if (typeof exports === 'object' && typeof module === 'object') {
/*
* CommonJS environment
*/
module.exports = attach(require('../../xterm'));
} else if (typeof define == 'function') {
/*
* Require.js is available
*/
define(['../../xterm'], attach);
} else {
/*
* Plain browser environment
*/
attach(window.Terminal);
}
})(function (Xterm) {
'use strict';
/**
* This module provides methods for attaching a terminal to a WebSocket
* stream.
*
* @module xterm/addons/attach/attach
*/
var exports = {};
/**
* Attaches the given terminal to the given socket.
*
* @param {Xterm} term - The terminal to be attached to the given socket.
* @param {WebSocket} socket - The socket to attach the current terminal.
* @param {boolean} bidirectional - Whether the terminal should send data
* to the socket as well.
* @param {boolean} buffered - Whether the rendering of incoming data
* should happen instantly or at a maximum
* frequency of 1 rendering per 10ms.
*/
exports.terminadoAttach = function (term, socket, bidirectional, buffered) {
bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional;
term.socket = socket;
term._flushBuffer = function () {
term.write(term._attachSocketBuffer);
term._attachSocketBuffer = null;
clearTimeout(term._attachSocketBufferTimer);
term._attachSocketBufferTimer = null;
};
term._pushToBuffer = function (data) {
if (term._attachSocketBuffer) {
term._attachSocketBuffer += data;
} else {
term._attachSocketBuffer = data;
setTimeout(term._flushBuffer, 10);
}
};
term._getMessage = function (ev) {
var data = JSON.parse(ev.data)
if( data[0] == "stdout" ) {
if (buffered) {
term._pushToBuffer(data[1]);
} else {
term.write(data[1]);
}
}
};
term._sendData = function (data) {
socket.send(JSON.stringify(['stdin', data]));
};
term._setSize = function (size) {
socket.send(JSON.stringify(['set_size', size.rows, size.cols]));
};
socket.addEventListener('message', term._getMessage);
if (bidirectional) {
term.on('data', term._sendData);
}
term.on('resize', term._setSize);
socket.addEventListener('close', term.terminadoDetach.bind(term, socket));
socket.addEventListener('error', term.terminadoDetach.bind(term, socket));
};
/**
* Detaches the given terminal from the given socket
*
* @param {Xterm} term - The terminal to be detached from the given socket.
* @param {WebSocket} socket - The socket from which to detach the current
* terminal.
*/
exports.terminadoDetach = function (term, socket) {
term.off('data', term._sendData);
socket = (typeof socket == 'undefined') ? term.socket : socket;
if (socket) {
socket.removeEventListener('message', term._getMessage);
}
delete term.socket;
};
/**
* Attaches the current terminal to the given socket
*
* @param {WebSocket} socket - The socket to attach the current terminal.
* @param {boolean} bidirectional - Whether the terminal should send data
* to the socket as well.
* @param {boolean} buffered - Whether the rendering of incoming data
* should happen instantly or at a maximum
* frequency of 1 rendering per 10ms.
*/
Xterm.prototype.terminadoAttach = function (socket, bidirectional, buffered) {
return exports.terminadoAttach(this, socket, bidirectional, buffered);
};
/**
* Detaches the current terminal from the given socket.
*
* @param {WebSocket} socket - The socket from which to detach the current
* terminal.
*/
Xterm.prototype.terminadoDetach = function (socket) {
return exports.terminadoDetach(this, socket);
};
return exports;
});
+48
View File
@@ -0,0 +1,48 @@
var assert = require('chai').assert;
var Terminal = require('../../xterm');
var linkify = require('../../addons/linkify/linkify');
describe('linkify addon', function () {
var xterm;
describe('API', function () {
it('should define Terminal.prototype.linkify', function () {
assert.isDefined(Terminal.prototype.linkify);
});
it('should define Terminal.prototype.linkifyTerminalLine', function () {
assert.isDefined(Terminal.prototype.linkifyTerminalLine);
});
});
describe('findUrlMatchOnLine', function () {
describe('strict regex', function () {
it('should match when the entire text is a match', function () {
assert.equal(linkify.findLinkMatch('http://github.com', false), 'http://github.com');
assert.equal(linkify.findLinkMatch('http://127.0.0.1', false), 'http://127.0.0.1');
});
it('should match simple domains', function () {
assert.equal(linkify.findLinkMatch('foo http://github.com bar', false), 'http://github.com');
assert.equal(linkify.findLinkMatch('foo http://www.github.com bar', false), 'http://www.github.com');
assert.equal(linkify.findLinkMatch('foo https://github.com bar', false), 'https://github.com');
assert.equal(linkify.findLinkMatch('foo https://www.github.com bar', false), 'https://www.github.com');
});
it('should match web addresses with alpha paths', function () {
assert.equal(linkify.findLinkMatch('foo http://github.com/a/b/c bar', false), 'http://github.com/a/b/c');
assert.equal(linkify.findLinkMatch('foo http://www.github.com/a/b/c bar', false), 'http://www.github.com/a/b/c');
});
it('should not include whitespace surrounding a match', function () {
assert.equal(linkify.findLinkMatch(' http://github.com', false), 'http://github.com');
assert.equal(linkify.findLinkMatch('http://github.com ', false), 'http://github.com');
assert.equal(linkify.findLinkMatch(' http://github.com ', false), 'http://github.com');
});
it('should match IP addresses', function () {
assert.equal(linkify.findLinkMatch('foo http://127.0.0.1 bar', false), 'http://127.0.0.1');
assert.equal(linkify.findLinkMatch('foo https://127.0.0.1 bar', false), 'https://127.0.0.1');
});
it('should match ports on both domains and IP addresses', function () {
assert.equal(linkify.findLinkMatch('foo http://127.0.0.1:8080 bar', false), 'http://127.0.0.1:8080');
assert.equal(linkify.findLinkMatch('foo http://www.github.com:8080 bar', false), 'http://www.github.com:8080');
});
});
});
});
+10
View File
@@ -0,0 +1,10 @@
var assert = require('chai').assert;
var Terminal = require('../../xterm');
describe('xterm.js addons', function() {
it('should load addons with Terminal.loadAddon', function () {
Terminal.loadAddon('attach');
// Test that addon was loaded successfully
assert.equal(typeof Terminal.prototype.attach, 'function');
});
});
+18
View File
@@ -0,0 +1,18 @@
var assert = require('chai').assert;
var Terminal = require('../xterm');
var Clipboard = require('../handlers/Clipboard');
describe('evaluateCopiedTextProcessing', function () {
it('should strip trailing whitespaces and replace nbsps with spaces', function () {
var nonBreakingSpace = String.fromCharCode(160),
copiedText = 'echo' + nonBreakingSpace + 'hello' + nonBreakingSpace,
processedText = Clipboard.prepareTextForClipboard(copiedText);
// No trailing spaces
assert.equal(processedText.match(/\s+$/), null);
// No non-breaking space
assert.equal(processedText.indexOf(nonBreakingSpace), -1);
});
});
+263
View File
@@ -0,0 +1,263 @@
var assert = require('chai').assert;
var Terminal = require('../xterm');
describe('CompositionHelper', function () {
var terminal;
var compositionHelper;
var compositionView;
var textarea;
var handledText;
beforeEach(function () {
compositionView = {
classList: {
add: function () {},
remove: function () {},
},
getBoundingClientRect: function () {
return { width: 0 };
},
style: {
left: 0,
top: 0
},
textContent: ''
};
textarea = {
value: '',
style: {
left: 0,
top: 0
}
};
terminal = {
element: {
querySelector: function () {
return { offsetLeft: 0, offsetTop: 0 };
}
},
handler: function (text) {
handledText += text;
}
};
handledText = '';
compositionHelper = new Terminal.CompositionHelper(textarea, compositionView, terminal);
});
describe('Public API', function () {
it('should define CompositionHelper.prototype.compositionstart', function () {
assert.isDefined(Terminal.CompositionHelper.prototype.compositionstart);
});
it('should define CompositionHelper.prototype.compositionupdate', function () {
assert.isDefined(Terminal.CompositionHelper.prototype.compositionupdate);
});
it('should define CompositionHelper.prototype.compositionend', function () {
assert.isDefined(Terminal.CompositionHelper.prototype.compositionend);
});
it('should define CompositionHelper.prototype.finalizeComposition', function () {
assert.isDefined(Terminal.CompositionHelper.prototype.finalizeComposition);
});
it('should define CompositionHelper.prototype.handleAnyTextareaChanges', function () {
assert.isDefined(Terminal.CompositionHelper.prototype.handleAnyTextareaChanges);
});
it('should define CompositionHelper.prototype.updateCompositionElements', function () {
assert.isDefined(Terminal.CompositionHelper.prototype.updateCompositionElements);
});
it('should define CompositionHelper.isComposing', function () {
assert.isDefined(compositionHelper.isComposing);
});
it('should define CompositionHelper.isSendingComposition', function () {
assert.isDefined(compositionHelper.isSendingComposition);
});
});
describe('Input', function () {
it('Should insert simple characters', function (done) {
// First character 'ㅇ'
compositionHelper.compositionstart();
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = 'ㅇ';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionend();
setTimeout(function() { // wait for any textarea updates
assert.equal(handledText, 'ㅇ');
// Second character 'ㅇ'
compositionHelper.compositionstart();
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = 'ㅇㅇ';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionend();
setTimeout(function() { // wait for any textarea updates
assert.equal(handledText, 'ㅇㅇ');
done();
}, 0);
}, 0);
}, 0);
}, 0);
});
it('Should insert complex characters', function (done) {
// First character '앙'
compositionHelper.compositionstart();
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = 'ㅇ';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionupdate({ data: '아' });
textarea.value = '아';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionupdate({ data: '앙' });
textarea.value = '앙';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionend();
setTimeout(function() { // wait for any textarea updates
assert.equal(handledText, '앙');
// Second character '앙'
compositionHelper.compositionstart();
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = '앙ㅇ';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionupdate({ data: '아' });
textarea.value = '앙아';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionupdate({ data: '앙' });
textarea.value = '앙앙';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionend();
setTimeout(function() { // wait for any textarea updates
assert.equal(handledText, '앙앙');
done();
}, 0);
}, 0);
}, 0);
}, 0);
}, 0);
}, 0);
}, 0);
}, 0);
});
it('Should insert complex characters that change with following character', function (done) {
// First character '아'
compositionHelper.compositionstart();
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = 'ㅇ';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionupdate({ data: '아' });
textarea.value = '아';
setTimeout(function() { // wait for any textarea updates
// Start second character '아' in first character
compositionHelper.compositionupdate({ data: '앙' });
textarea.value = '앙';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionend();
compositionHelper.compositionstart();
compositionHelper.compositionupdate({ data: '아' });
textarea.value = '아아'
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionend();
setTimeout(function() { // wait for any textarea updates
assert.equal(handledText, '아아');
done();
}, 0);
}, 0);
}, 0);
}, 0);
}, 0);
});
it('Should insert multi-characters compositions', function (done) {
// First character 'だ'
compositionHelper.compositionstart();
compositionHelper.compositionupdate({ data: 'd' });
textarea.value = 'd';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionupdate({ data: 'だ' });
textarea.value = 'だ';
setTimeout(function() { // wait for any textarea updates
// Second character 'あ'
compositionHelper.compositionupdate({ data: 'だあ' });
textarea.value = 'だあ';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionend();
setTimeout(function() { // wait for any textarea updates
assert.equal(handledText, 'だあ');
done();
}, 0);
}, 0);
}, 0);
}, 0);
});
it('Should insert multi-character compositions that are converted to other characters with the same length', function (done) {
// First character 'だ'
compositionHelper.compositionstart();
compositionHelper.compositionupdate({ data: 'd' });
textarea.value = 'd';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionupdate({ data: 'だ' });
textarea.value = 'だ';
setTimeout(function() { // wait for any textarea updates
// Second character 'ー'
compositionHelper.compositionupdate({ data: 'だー' });
textarea.value = 'だー';
setTimeout(function() { // wait for any textarea updates
// Convert to katakana 'ダー'
compositionHelper.compositionupdate({ data: 'ダー' });
textarea.value = 'ダー';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionend();
setTimeout(function() { // wait for any textarea updates
assert.equal(handledText, 'ダー');
done();
}, 0);
}, 0);
}, 0);
}, 0);
}, 0);
})
it('Should insert multi-character compositions that are converted to other characters with different lengths', function (done) {
// First character 'い'
compositionHelper.compositionstart();
compositionHelper.compositionupdate({ data: 'い' });
textarea.value = 'い';
setTimeout(function() { // wait for any textarea updates
// Second character 'ま'
compositionHelper.compositionupdate({ data: 'いm' });
textarea.value = 'いm';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionupdate({ data: 'いま' });
textarea.value = 'いま';
setTimeout(function() { // wait for any textarea updates
// Convert to kanji '今'
compositionHelper.compositionupdate({ data: '今' });
textarea.value = '今';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionend();
setTimeout(function() { // wait for any textarea updates
assert.equal(handledText, '今');
done();
}, 0);
}, 0);
}, 0);
}, 0);
}, 0);
});
it('Should insert non-composition characters input immediately after composition characters', function (done) {
// First character 'ㅇ'
compositionHelper.compositionstart();
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = 'ㅇ';
setTimeout(function() { // wait for any textarea updates
compositionHelper.compositionend();
// Second character '1' (a non-composition character)
textarea.value = 'ㅇ1';
setTimeout(function() { // wait for any textarea updates
assert.equal(handledText, 'ㅇ1');
done();
}, 0);
}, 0);
});
});
});
+109
View File
@@ -0,0 +1,109 @@
var glob = require('glob');
var fs = require('fs');
var pty = require('pty.js');
var sleep = require('sleep');
var Terminal = require('../xterm');
var CONSOLE_LOG = console.log;
// expect files need terminal at 80x25!
var COLS = 80;
var ROWS = 25;
/** some helpers for pty interaction */
// we need a pty in between to get the termios decorations
// for the basic test cases a raw pty device is enough
var primitive_pty = pty.native.open(COLS, ROWS);
// fake sychronous pty write - read
// we just pipe the data from slave to master as a child program would do
// pty.js opens pipe fds with O_NONBLOCK
// just wait 10ms instead of setting fds to blocking mode
function pty_write_read(s) {
fs.writeSync(primitive_pty.slave, s);
sleep.usleep(10000);
var b = Buffer(64000);
var bytes = fs.readSync(primitive_pty.master, b, 0, 64000);
return b.toString('utf8', 0, bytes);
}
// make sure raw pty is at x=0 and has no pending data
function pty_reset() {
pty_write_read('\r\n');
}
/* debug helpers */
// generate colorful noisy output to compare xterm and emulator cell states
function formatError(in_, out_, expected) {
function addLineNumber(start, color) {
var counter = start || 0;
return function(s) {
counter += 1;
return '\x1b[33m' + (' ' + counter).slice(-2) + color + s;
}
}
var line80 = '12345678901234567890123456789012345678901234567890123456789012345678901234567890';
var s = '';
s += '\n\x1b[34m' + JSON.stringify(in_);
s += '\n\x1b[33m ' + line80 + '\n';
s += out_.split('\n').map(addLineNumber(0, '\x1b[31m')).join('\n');
s += '\n\x1b[33m ' + line80 + '\n';
s += expected.split('\n').map(addLineNumber(0, '\x1b[32m')).join('\n');
return s;
}
// simple debug output of terminal cells
function terminalToString(term) {
var result = '';
var line_s = '';
for (var line=0; line<term.rows; ++line) {
line_s = '';
for (var cell=0; cell<term.cols; ++cell) {
line_s += term.lines[line][cell][1];
}
// rtrim empty cells as xterm does
line_s = line_s.replace(/\s+$/, '');
result += line_s;
result += '\n';
}
return result;
}
/** tests */
describe('xterm output comparison', function() {
var xterm;
beforeEach(function () {
xterm = new Terminal(COLS, ROWS);
xterm.refresh = function() {};
});
// omit stack trace for escape sequence files
Error.stackTraceLimit = 0;
var files = glob.sync('**/escape_sequence_files/*.in');
// only successful tests for now
var successful = [0, 2, 6, 12, 13, 18, 20, 22, 27, 28];
console.log(files);
for (var a in successful) {
var i = successful[a];
(function(filename){
it(filename.split('/').slice(-1)[0], function () {
pty_reset();
var in_file = fs.readFileSync(filename, 'utf8');
var from_pty = pty_write_read(in_file);
// uncomment this to get log from terminal
console.log = function(){};
xterm.write(from_pty);
var from_emulator = terminalToString(xterm);
console.log = CONSOLE_LOG;
var expected = fs.readFileSync(filename.split('.')[0] + '.text', 'utf8');
if (from_emulator != expected) {
// uncomment to get noisy output
//throw new Error(formatError(in_file, from_emulator, expected));
throw new Error('mismatch');
}
});
})(files[i]);
}
});
+21
View File
@@ -0,0 +1,21 @@
All tests are made for 80x25 terminal. Make sure to run tests with 80x25.
Create .text files from xterm (expected output)
- open xterm
- resize xterm to 80x25
- run `python run_tests.py`
- copy & paste whole window output into editor
- add 26th empty line (due to line handling in toString) - not a bug, a feature ;)
- advance to next test with ^D
Known problems
##############
t0031-HBP:
- no documentation at all about CSIj found - skipping
t0050-ICH:
- bug in xterm? (cant ICH last real char, always sticks to last col)
- text used from https://github.com/MarkLodato/vt100-parser/blob/master/test/t0050-ICH.text
@@ -0,0 +1,6 @@
!"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~
@@ -0,0 +1,25 @@
!"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~
@@ -0,0 +1,95 @@
!
"
#
$
%
&
'
(
)
*
+
,
-
.
/
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\
]
^
_
`
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
~
@@ -0,0 +1,25 @@
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
~
@@ -0,0 +1 @@
abcdefghijklmnopqrstuvwxyz0123456789
@@ -0,0 +1,25 @@
abcdefghijklmnopqrstuvwxyz0123456789
@@ -0,0 +1,83 @@
a
ab
abc
abcd
abcde
abcdef
abcdefg
abcdefgh
abcdefghi
abcdefghij
abcdefghijk
abcdefghijkl
abcdefghijklm
abcdefghijklmn
abcdefghijklmno
abcdefghijklmnop
abcdefghijklmnopq
abcdefghijklmnopqr
abcdefghijklmnopqrs
abcdefghijklmnopqrst
abcdefghijklmnopqrstu
abcdefghijklmnopqrstuv
abcdefghijklmnopqrstuvw
abcdefghijklmnopqrstuvwx
abcdefghijklmnopqrstuvwxy
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyzA
abcdefghijklmnopqrstuvwxyzAB
abcdefghijklmnopqrstuvwxyzABC
abcdefghijklmnopqrstuvwxyzABCD
abcdefghijklmnopqrstuvwxyzABCDE
abcdefghijklmnopqrstuvwxyzABCDEF
abcdefghijklmnopqrstuvwxyzABCDEFG
abcdefghijklmnopqrstuvwxyzABCDEFGH
abcdefghijklmnopqrstuvwxyzABCDEFGHI
abcdefghijklmnopqrstuvwxyzABCDEFGHIJ
abcdefghijklmnopqrstuvwxyzABCDEFGHIJK
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKL
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLM
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTU
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890a
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890ab
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abc
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcd
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcde
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdef
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijk
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijkl
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmn
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrs
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrst
@@ -0,0 +1,25 @@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890a
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890ab
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abc
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcd
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcde
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdef
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijk
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijkl
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmn
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
r
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
rs
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
rst
@@ -0,0 +1,26 @@
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@@ -0,0 +1,25 @@
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@@ -0,0 +1,83 @@
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
0
1
2
3
4
5
6
7
8
9
0
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
@@ -0,0 +1,25 @@
7
8
9
0
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
@@ -0,0 +1,7 @@
1 x
2 x
3 x
4 x
5 x
6 x
7 x
@@ -0,0 +1,25 @@
x
x2
x 3
x 4
x 5
x 6
x 7
@@ -0,0 +1,82 @@
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
b a
@@ -0,0 +1,25 @@
a b
a b
a b
a b
a b
a b
a b
a b
a b
a b
a b
a b
a b
a b
a b
a b
a b
a b
a b
a b
a
ab
@@ -0,0 +1 @@
aDbDcDdDeDfDgDhDiDjDkDlDmDnDoDpDqDrDsDtDuDvDwDxDyDzDADBDCDDDEDFDGDHDIDJDKDLDMDNDODPDQDRDSDTDUDVDWDXDYDZD0D1D2D3D4D5D6D7D8D9D0DaDbDcDdDeDfDgDhDiDjDkDlDmDnDoDpDqDrDsDt
@@ -0,0 +1,25 @@
7
8
9
0
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
@@ -0,0 +1,8 @@
0 space:
1 space:
2 space:
3 space:
70 space:
71 space:
72 space:
73 space:
@@ -0,0 +1,25 @@
0 space:
1 space:
2 space:
3 space:
70 space:
71 space:
72 space:
73 space:
@@ -0,0 +1,7 @@
abcdefghijklmnopqrstuvwxyz!
abc@
#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop$
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq%
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr^
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrs&
@@ -0,0 +1,25 @@
abcdefghijklmnopqrst!vwxyz
@bc
#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij$lmnop
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij%lmnopq
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
^
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
&s
@@ -0,0 +1 @@
aEabEabcEabcdEabcdeEabcdefEabcdefgEabcdefghEabcdefghiEabcdefghijEabcdefghijkEabcdefghijklEabcdefghijklmEabcdefghijklmnEabcdefghijklmnoEabcdefghijklmnopEabcdefghijklmnopqEabcdefghijklmnopqrEabcdefghijklmnopqrsEabcdefghijklmnopqrstEabcdefghijklmnopqrstuEabcdefghijklmnopqrstuvEabcdefghijklmnopqrstuvwEabcdefghijklmnopqrstuvwxEabcdefghijklmnopqrstuvwxyEabcdefghijklmnopqrstuvwxyzEabcdefghijklmnopqrstuvwxyzAEabcdefghijklmnopqrstuvwxyzABEabcdefghijklmnopqrstuvwxyzABCEabcdefghijklmnopqrstuvwxyzABCDEabcdefghijklmnopqrstuvwxyzABCDEEabcdefghijklmnopqrstuvwxyzABCDEFEabcdefghijklmnopqrstuvwxyzABCDEFGEabcdefghijklmnopqrstuvwxyzABCDEFGHEabcdefghijklmnopqrstuvwxyzABCDEFGHIEabcdefghijklmnopqrstuvwxyzABCDEFGHIJEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQREabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890aEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdeEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghiEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijkEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnoEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrsEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrst
@@ -0,0 +1,25 @@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890a
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890ab
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abc
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcd
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcde
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdef
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijk
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijkl
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmn
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
r
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
rs
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
rst
@@ -0,0 +1,10 @@
a
b
c
dMeMfMg
h
i
j....................................................................kMlMmMn
@@ -0,0 +1,25 @@
a g n
h f m
ie l
j....................................................................k
@@ -0,0 +1,47 @@
And the third.
This should be the last line.
This one should be lost.
This one's a goner, too. MMMMMMMMMMMMMMMMMMMMMMMMThis is second line. MThis should be the first line.
@@ -0,0 +1,25 @@
This should be the first line.
This is second line.
And the third.
This should be the last line.
This one should be lost.
@@ -0,0 +1 @@
a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t
@@ -0,0 +1,25 @@
7
8
9
0
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
@@ -0,0 +1 @@
a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t
@@ -0,0 +1,25 @@
8
9
0
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
@@ -0,0 +1,8 @@
abcdDefgh
abcdDefgh
abcd!Defgh
abcd!*Defgh
abcd[Defgh
abcd[!Defgh
abcd[2Defgh
abcd[*2;Defgh
@@ -0,0 +1,25 @@
abcdDefgh
abcdDefgh
abcdDefgh
abcdDefgh
abcdDefgh
abcdDefgh
abcdDefgh
abcdDefgh
@@ -0,0 +1,8 @@
abcdDefgh
abcdDefgh
abcd!Defgh
abcd!*Defgh
abcd[Defgh
abcd[!Defgh
abcd[2Defgh
abcd[*2;Defgh
@@ -0,0 +1,25 @@
abcdDefgh
abcdDefgh
abcdDefgh
abcdDefgh
abcdDefgh
abcdDefgh
abcdDefgh
abcdDefgh
@@ -0,0 +1,17 @@
HelloGoodbye
UpDown
x

-----------------------------------------------------------------------------x
------------------------------------------------------------------------------x
-------------------------------------------------------------------------------x
--------------------------------------------------------------------------------x
---------------------------------------------------------------------------------x
.............................................................................x
..............................................................................x
...............................................................................x
................................................................................x
.................................................................................x

The End.
@@ -0,0 +1,25 @@
The End.
@@ -0,0 +1,54 @@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
a
b
c
d
e
f
g
h
------------------------------------------------------------------------------1
-------------------------------------------------------------------------------2
--------------------------------------------------------------------------------3
---------------------------------------------------------------------------------4
..............................................................................5
...............................................................................6
................................................................................7
.................................................................................8
@@ -0,0 +1,25 @@
a
b
f
g
h 1
2
3
-4------------------------------------------------------------------------------
5
6
7
8...............................................................................
@@ -0,0 +1,14 @@
abcdefghijkl
abcdefghijkl
abcdefghijkl
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@
x
x
abcd
@@ -0,0 +1,25 @@
abcdefg hijkl
abcdefg hijkl
abcdefg hijkl
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno @
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
r @
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @
x
x
abcd
@@ -0,0 +1,8 @@
abcdefg!@
abcdefg!@
abcdefg!@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr@
x
@@ -0,0 +1,25 @@
abcdef!@
!@cdefg
abcde!@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmn@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@q
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
@
x
@@ -0,0 +1,25 @@
a
b
c
defg
h
i
j....................................................................klmn
0123
@@ -0,0 +1,25 @@
a g n
h f m
ie l
j....................................................................k
3
2
1
0
@@ -0,0 +1,50 @@
This is the first line.
This is the second line.
And the third.
This line should be deleted.
Penultimate line.
This should be the last line. I have gone up all the way...
@@ -0,0 +1,25 @@
I have gone up all the way...
This line should be deleted.
Penultimate line.
This should be the last line.
@@ -0,0 +1,24 @@
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x012345Bottom line. ABCDE 
@@ -0,0 +1,25 @@
b 1
c 2
d 3
e
f 4
g
h
i 5
j
k
l
m
n
o
p
q A
r B
s C
t D
u E
v
w
x
Bottom line.
@@ -0,0 +1 @@
abcdefg
@@ -0,0 +1,25 @@
b
e
d
g
f
@@ -0,0 +1,2 @@
abcdefghi
-------------------------------------------------------------------------abcdefghijlast line
@@ -0,0 +1,25 @@
def
ghi
-------------------------------------------------------------------------abcdefg
hij
last line
@@ -0,0 +1,6 @@
erasedreplacement
line fourline two
@@ -0,0 +1,25 @@
replacement
line two
line four
@@ -0,0 +1,14 @@
abcdefghijkl
abcdefghijkl
abcdefghijkl
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@
x
x
abcd
@@ -0,0 +1,25 @@
abcdefg hijkl
abcdefg hijkl
abcdefg hijkl
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno @
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
r @
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @
x
x
abcd
@@ -0,0 +1,8 @@
abcdefg!@
abcdefg!@
abcdefg!@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr@
x
@@ -0,0 +1,25 @@
abcdefg!@
abcdefg!@
abcdefg!@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
r@
x
@@ -0,0 +1,25 @@
a
b
c
defg
h
i
j....................................................................klmn
0123
@@ -0,0 +1,25 @@
b
c
defg
h
i
j....................................................................klmn
0123
@@ -0,0 +1,50 @@
This is the first line.
This is the second line.
And the third.
This line should be deleted.
Penultimate line.
This should be the last line. I have gone up all the way...
@@ -0,0 +1,25 @@
I have gone up all the way...
@@ -0,0 +1,24 @@
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x012345Bottom line. ABCDE 
@@ -0,0 +1,25 @@
b 1
c 2
d 3
e
f 4
g
h
i 5
j
k
l
m
n
o
p
q A
r B
s C
t D
u E
v
w
x
Bottom line.
@@ -0,0 +1 @@
abcdefg
@@ -0,0 +1,25 @@
b
e
d
g
f
@@ -0,0 +1,7 @@
x
<
abcdefg
abcdefg!
@
.
?-
@@ -0,0 +1,25 @@
xxxxxx
<
abcdefg
abcd!fg
@@@@@@@@@
@@@@@@@@@@@@
.
....
?
?-
@@ -0,0 +1,23 @@
abcdefghijklmnopqrstuvwxyz[15@
abcdefghijklmnopqrstuvwxyz[80@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[17@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[18@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[19@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[20@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[21@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop[5@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq[5@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq[5@
ICH at end:[5@
abcdefghijklmnopqrstuvwxyz[15@!@#
abcdefghijklmnopqrstuvwxyz[80@!@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[17@!@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[18@!@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[19@!@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[20@!@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[21@!@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop[5@!@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq[5@!@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq[5@!@#
ICH at end:[5@!@#
@@ -0,0 +1,25 @@
abcdefghijklmnopqrstu
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567 89
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567 89
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567 8
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW XYZ01234567890abcdefghijkl
ICH at end:
abcdefghijklmnopqrstu!@# vwxyz
abcdefghijklmnopqrstu!@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567!@# 89
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567!@# 89
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567!@# 8
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567!@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567!@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop!
@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop!
@#
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW!@# XYZ01234567890abcdefghijkl
ICH at end:!@#
@@ -0,0 +1,23 @@
ab
cd
ef
gh
ij
kl
mn
opQRST
1
2
3
4
5------------------------------------------------------------------------------ab
6
7
8
9
10
11
12
13
14
15
@@ -0,0 +1,25 @@
ef
gh
ij
QR
kl
mn
op
1
2
3
b
4------------------------------------------------------------------------------a
5
6
7
8
9
10
11
12
@@ -0,0 +1,15 @@
a
b
c
d
e
f
g
hijklmnop
1
2
3
4 x
@@ -0,0 +1,25 @@
a
b
c
ijklmnop
g
h
1
x
4
@@ -0,0 +1,12 @@
abcdefghijklmnopqrstuvwxyz>
abcdefghijklmnopqrstuvwxyz>!
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>!
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>!
------------------------------------------------------------------------------?
-------------------------------------------------------------------------------?
-------------------------------------------------------------------------------?
---------------------------------------------------------------------------------?
..............................................................................
...............................................................................
...............................................................................
.................................................................................
@@ -0,0 +1,25 @@
abcdefghijklmnopqr>vwxyz
abcdefghijklmnopqr>!wxyz
>!mnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh
abcdefghijklmnopqrstuvwxyz0123456789ABC>!PQRSTUVWXYZ0123456789abcdefgh
------------------------------------------------------------------------------?
-------------------------------------------------------------------------------?
-------------------------------------------------------------------------------?
--------------------------------------------------------------------------------
-?
..............................................................................
...............................................................................
...............................................................................
................................................................................
.
@@ -0,0 +1,12 @@
abcdefghijklmnopqrstuvwxyz>
abcdefghijklmnopqrstuvwxyz>!
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>!
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>!
------------------------------------------------------------------------------?
-------------------------------------------------------------------------------?
-------------------------------------------------------------------------------?
---------------------------------------------------------------------------------?
..............................................................................
...............................................................................
...............................................................................
.................................................................................
@@ -0,0 +1,25 @@
abcdefghijklmnopqr> vwxyz
abcdefghijklmnopqr>! vwxyz
>! lmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh
abcdefghijklmnopqrstuvwxyz0123456789ABC>! OPQRSTUVWXYZ0123456789abcdefgh
------------------------------------------------------------------------------?
-------------------------------------------------------------------------------?
-------------------------------------------------------------------------------?
--------------------------------------------------------------------------------
-?
..............................................................................
...............................................................................
...............................................................................
................................................................................
.
@@ -0,0 +1,8 @@
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh><
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh><
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh><
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh><
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh><!
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh><!
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh><!
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh!

Some files were not shown because too many files have changed in this diff Show More