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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
|
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<title>High level functional description of a Terminal Emulator, Term</title>
<LINK REL="Stylesheet" HREF="../../../../../prose.css" TYPE="text/css" TITLE="NetBeans OpenSource Style">
</head>
<body>
<h1>
High level functional description of an ANSI Terminal Emulator, Term
<hr>
</h1>
<p><b>Author:</b>
<p><i>
<a href="mailto:ivan.solimanipour@eng.sun.com">Ivan Soleimanipour</a>,
Sun Microsystems.
</i>
<hr>
<p><b>Abstract:</b>
A highly configurable ANSI terminal emulator.
<br><b>Version:</b>
4 of
Wed Oct 24 2001
<hr>
<p><b>Table of contents:</b>
<ul>
<li> <a href="#motivation">Motivation</a>
<li> <a href="#features">User visible and API Features (as implemented currently)</a>
<li> <a href="#covenant">Covenant</a>
<li> <a href="#rfe">RFE queue</a>
<li> <a href="#performance">Performance</a>
<li> <a href="#hypertext">Use as a hypertext widget</a>
<li> <a href="#design_issues">Design issues</a>
<li> <a href="#source_code">Source code and demos</a>
<ul>
<li> <a href="#demo_build">Build tool demo</a>
<li> <a href="#demo_telnet">Telnet demo</a>
</ul>
</ul>
<hr>
<a name="motivation">
<h2>
Motivation
</h2>
The original impetus for Term was the need for a terminal
emulator for use by adaptations of NetBeans for non-Java development.
These tools need a proper terminal emulator in at least three areas:
<ul>
<li>
A window for program io, for programs being run under the debugger.
These programs will be traditional unix programs and may utilize
various levels of terminal manipulation, programs like 'more',
'top', 'vi' and 'ksh'.
<li>
A window for the debugger (e.g. dbx) command io. The dbx command
interpreter is a ksh variant and as such allows input history editing
or execution of any unix program (like 'vi').
<li>
A window for running alternative text editors, 'vi' or 'vim' under.
More on this later.
</ul>
The NetBeans community had expressed interest in such a component as a
candidate for the NetBeans build and other output windows.
The package was
<a href=
"http://www.netbeans.org/servlets/ReadMsg?msgId=141308&listName=contrib">
contributed</a>
to the NB source base circa Aug 2001.
<p>
A terminal emulator can also be used as a within-nb shell or telnet window.
See the
<a href="#demo_telnet">source code for a telnet demo</a>.
<a name="features">
<h2>
User visible and API Features (as implemented currently)
</h2>
<ul>
<li>
The base Term class handles "dumb" operations, putting characters
on a screen and forwarding keystrokes.
<p><li>
ANSI operations for cursor control, line manipulation etc.
<li>
ANSI color and other character attribute escape processing.
<br>
Not All sequences are implemented yet.
<p>
As references I used
<a href="http://www.fh-jena.de/~gmueller/Kurs_halle/esc_vt100.html">
Robert Frees spec</a>
and
<a href="http://enterprise.aacc.cc.md.us/~rhs/ansi.html">
this
</a>
as well as the DtTerm(3) man page from Solaris.
<p>
<li>
The interpretation of characters is done by an abstract
<a name="interpreter">interpreter</a>.
A set of classes are provided for
<a href="interpreter.html">interpreter construction</a>
using state machines.
The current default interpreter is a simple ANSI interpreter, polluted
with some DtTerm extensions.
<p>
<li>
Selection service in character, word and line modes modelled on xterm with
configurable word boundary detection.
<br>
This should work particularly well under X-windows with JDK1.4 where they
have fixed X-windows selections.
<li>
Auto-scrolling for the selection when the mouse moves outside of the view.
<p>
<li>
History buffer and vertical scrolling.
The history can be traversed using a ...
<li>
<list>LogicalLineVistor</list>
<br>
Provides access to whole history buffer contents and facilitates
searches and contents dumps etc. Suitable information and mechanisms are
provided for mapping a logical line to screen coordinates to facilitate
highlighting and resumption of search for example.
<p>
<li>
Horizontal scrolling.
<p>
<li>
Pluggable "line discipline".
<p>
Unlike other termulators Term does not
do things like line buffering, echoing, CR/LF processing and so on.
Since it is predominantly intended for use under Unix and since
under Unix all this stuff is done by the kernel (accessed through
pty's) Term doesn't bother with any of this.
<p>
However, there is a mechanism analogous to SVR4 io streams, or
pushable network stack elements, that allows customization of
character processing on other systems. A generic simple
stream module, <list>LineDiscipline</list> is provided in this package.
<p>
Stream modules can be used for other purposes like recording of the io
to some history file or for testing purposes.
<p>
<li>
Mechanisms for dealing with resizing for interaction with ptys and
telnet protocols.
<p>
<li>
"editor and glyph support". The original Solaris Workshop used an
enhanced DtTerm (The CDE termulator widget) that provided for
improved interaction with vi and the rest of the IDE.
So does Term:
<ul>
<li>
Ability to render glyphs in a "glyph gutter".
<li>
Ability to convert mouse clicks to row/col coordinates and even
the underlying text. For use by "balloon evaluation" for example.
<li>
Colored per-line background stripes, independent of ANSI
color escapes and the selection feedback.
</ul>
<p>
<li>
Term interacts with the rest of the world using functions that send and
receive char arrays. A subclass, StreamTerm allows hooking up of
java.io Streams. Other subclasses could be derived which connect the
Term to telnet clients or pty streams (which naturally requires JNI
code and is therefore not part of this package).
<p>
<li>
Choice of click-to-type or follow-mouse focus.
<li>
Choice of XOR or Swing style selection feedback.
<p>
<li>
Handles Sun keyboard Cut, Copy, Paste keys. Since they _are_ available
as AWT key codes.
<p>
<li>
Methods for querying and setting cursor location.
<br>
This can be used, for example, to ensure that a horizontal line
starts on column 0.
<p>
<li>
Consuming key events.
<br>
Because of it's nature, Term, by default, consumes all of the keystrokes
it gets and passes them through to the output stream.
<p>
A set of <list>KeyStrokes</list> may be registered with Term though to
allow passing through of keystrokes of the clients choice.
</ul>
Note that there are two important differences between this widget and
traditional Java text widgets:
<ul>
<li>
Because of the focus on cursor addressability it only works with
fixed-width fonts. It will accept any font setting but will
mutate it into a monospaced one.
<br>
Although there is some discussion to relax this considering the dearth of
monospaced unicode fonts.
<p><li>
It doesn't view documents; it's an input stream viewer.
This leads to some
<a href="#interesting_design_issues">
interesting design issues
</a>
.
</ul>
<p>
The UI ... is just too simple to be worth a picture.
<br>
It's just a screen area where text appears and a Swing scrollbar
in whatever is the current L&F.
<p>
This proposal comes with
<a href="../package-summary.html">Javadoc API documentation</a>
and a
<a href="properties.html">properties table</a>
.
<a name="covenant">
<h2>
Covenant
</h2>
(A covenant is a part of a property deed that puts restrictions on the use
of the property on all future owners)
<p>
<ul>
<li>
No additional dependencies. I would like Term to be usable outside
of NetBeans and therefore it should not depend on packages like
openide and so on.
</ul>
<a name="rfe">
<h2>
RFE queue
</h2>
These are things that are planned but not implemented yet.
<ul>
<p><li>
Misc. terminal things like ...
<ul>
<li>
Control of cursor style.
<li>
Bell: audible/visible.
<li>
Margin warning.
</ul>
<p><li>
Resize tooltip so you can get your columns and rows just they way you want them.
<p><li>
Line re-breaking.
<br>
You average terminal emulator will keep line breaks (due to wrapping)
at the original column when the width of the emulator changes.
It should be possible to re-break them as the width changes.
<p><li>
Accessibility.
<br>
This used to be an "issue" mainly because I hadn't learned much about it.
Term will implement the Accessible interface. The class Accessible is
really just a front gate to a whole host of other stuff that needs to
be implemented.
</ul>
<a name="performance">
<h2>
Performance
</h2>
Term is made up of the two main subsystems:
<dl>
<dt>Buffer maintenance
<dd>
This is the process of processing input characters and adding
them to the buffer, advancing the position of the cursor,
adding new lines at the bottom and taking away lines at the top.
<p>
The information is stored in a Vector of Lines. Each Line has a
an array of 'char's for character storage and an Array of 'int's
for attribute storage. These two arrays grow together (which is
more efficient than having two separate Vectors or StringBuffers).
However the attribute array may be null if all the characters in the
line have no attributes.
<p>
In order to prevent needless copying, these buffers are directly
available to the paint functions.
<p>
<dt>Painting
<dd>
This is he process of drawing the view of the buffer unto a canvas.
On each refresh the _whole_ view is redrawn! Since Swing's
refresh manager already provides a double buffered image there is
no user visible flickering.
<p>
Lines w/o attributes are rendered using Graphics.drawChars() in
the double buffered image setup by default by Swing and AWT.
<p>
Lines with attributes are rendered a "run" at a time. A run is
a sequence of characters all of which have the same attributes.
<p>
There are also various adornments to be rendered, like the cursor,
slection highlight, glyphs and so on.
<dd>
</dl>
The following points may be made:
<ul>
<li>
Redrawing the whole screen at the slightest excuse seems like a
bad idea. But it's premature to do anyting about this yet since
Term interaction with JScrollPane has not yet been finalized.
<li>
Regardlass of the the use of runs, use of attributes will always have a
slightly higher overhead in both buffer memory use and painting time.
</ul>
When measuring or comparing performance attention should be paid to the
following:
<dl>
<a name="buffering">
<dt>Buffering
<dd>
A repaint request is posted on every call to Term.putChar() and
every call to Term.putChars(). Obviously things are going to go
through much faster if you buffer 1000 characters and send them
via putChars() instead of calling putChar() 1000 times. The
first implementation of LineDiscipline() actually made this mistake.
<a name="batching">
<dt>Batching of refreshes
<dd>
The Swing (AWT?) repaint manager has it's own batching
which will compensate a bit for a high frequency of repaint
requests.
<dd>
<dt>Jump scrolling
<dd>
If you 'cat' a large file into a termulator you can have you choice
of two extremes, seeing every line go by and waiting for it all
to go by or having the printing finish quickly and seeing
"jumps" in the output (while the history buffer retains everything).
<p>
These two alternatives are usually controlled by a property known as
"jump scrolling". Term doesn't have it but the effect can
be achieved by appropriately buffering the input and or internally
using paintImmediately().
</dl>
Having said all of this, in my experience with the current implementation,
painting completely dominates buffer maintenance, so when you're
comparing Term with something else make sure they have comparable
refreshes/bytes-of-input.
<a name="hypertext">
<h2>
Use as a hypertext widget
</h2>
Term has facilities that allow it to be used as a reasonable styled
language and hypertext widget.
<ul>
<li>
Styled text can be rendered using ANSI color and font escapes, or
method calls, like <l>Term.setCharacterAttribute()</l>.
One can even concieve of an
<a href="#interpreter">Intepreter</a>
that interprets HTML.
<p><li>
An "Active Region" can be delineated through extended character
escapes or method calls (<l>Term.getRegionManager().beginRegion()</l>).
Active regions may be nested and the region manager can map a given
cursor (or pointer) position to the regions. This is the minimal
functionlaity with which a client can associate user data and actions with
active regions and highlight a region when a pointer passes over it,
execute an action on a click, or pop up a menu.
<p><li>
History can be "anchored" so that the beginning of a "page" of hypertext
doesn't vanish even if it's length exceeds the history size.
In other words,
when anchored, the history is temporarily expanded to accomodate the page.
</ul>
<a name="design_issues">
<h2>
Design issues
</h2>
I've been working off of O'Reilly publishers "JAVA Swing" by Eckstein, Loy
and Wood.
Many of the issues here are in the context of that book.
<p>
The issues often have to do with my ignorance or lack of good guidelines on a
subject and are really a plea for suggestions, education and discussion.
<p>
<dl>
<dt>
<b>
Swing Model and UI Delegate
</b>
<dd>
In ch 28 it is said that a proper swing widget has to have a
Model and a UI Delegate. Term currently has neither.
<p>
<dl>
<dt>
Why not a UIDelegate?
<dd>
Term used to have no "artwork" that needed to be drawn depending on a
specific look and feel. But now it has at least the following
properties that could be construed as L&F specific:
<dl>
<p><dt>selectionXOR<dd>
You can control whether selections are done using Swing
style (background highlighting) or using the more
traditional XOR style.
One could couch this as a L&F controllable setting with the XOR
style going to the Motif L&F.
<p><dt>autoCopy<dd>
On unix selections usually go to the primary selection. On
windows they go into the clipboard and only if a Copy action
was requested.
<p><dt>clickToType<dd>
Windows users live in the ClickToType (focus) world.
Unix people (i expect) prefer the "follow mouse" style
of focus control.
</dl>
<p>
Also, term is a "composite" widget and it is unclear to me how
one implements UIDelegates for composites, or whether one is
even needed.
<p>
<a name="interesting_design_issues">
<dt>
Why not a Model?
</a>
<dd>
In any text rendering widget the model is typically a "document".
The equivalent of this in a termulator would be the history buffer,
or if no history, just the screen backing storage.
<p>
However, this is really an internal implementation and a terminal
really interacts with the external world through it's io lines,
so the model is conceptually a "connection".
<p>
But a connection doesn't fit in with things like model-changed
events and such ... the data stored in the screen
backing store is ephemeral, it soon winks out of the history buffer.
So, I"m not exactly sure what a model would be for a termulator.
<p>
One candidate is the concept of sessions (A concept used in the
KDE 'konsole') where a single widget can multiplex between
multiple connections and the corresponding history buffers.
While such a feature should definitely be on the rfe list,
again, I'm not sure whether the Swing concept of a Model is
appropriate here.
<br>
To that end the current implementation has a Document class used
internally, but there's still a bit to go.
</dl>
<p>
<dt>
<b>
Working with JScrollPane
</b>
<dd>
Term is a composite and carries it's own scrollbar.
<br>
It is not JScrollPane-friendly.
<br>
Here's why ...
<p>
Initially it seems obvious that it should, like every other good Swing
component, implement Scrollable, work properly under a JScrollPane and
not contain it's own scrollbar, but this is not neccessarily a good idea.
<p>
Usually the size of a component refers to it's visible size.
But when the component is placed under a JScrollPane, it's size starts
referring to it's "virtual" size over which the user scrolls.
While this makes complete sense for tables, lists, and text documents,
in the case of a terminal emulator we don't want this. We want size
to still govern the visible screen size!
<p>
It is perhaps possible to design a Term that works under JScrollPane such
that resizes communicate the viewport size via TermListener.sizeChanged()
and setRows() sets the viewports size (this I actually can't figure how
to do). But this requires that Term discover that it's under a
JScrollPane and things become progressively more complex from there on.
<p>
Another argument can be made from a utility standpoint.
<br>
Most termulator applications (xterm) and widgets (DtTerm) have a property
that governs whether and where they have a scrollbar. It would be much more
convenient to retain this as a runtime controllable property of
Term itself (read <i>user option</i>) instead of
having the <i>container</i> of Term manage that;
create a JScrollPane, put Term under it etc. in response to user
option toggling.
<p>
<dt>
<b>
Reuse of and differences from standard Swing text components
</b>
<dd>
Why write a text rendering widget from scratch? Following are some reasons.
Some of them probably stem more from my ignorance of Swing or the NIH
syndrome, but others I believe are fair justifications for a new component.
<ul>
<p>
<li>
Speed.
<br>
In my experience Swing text components just can't handle
the volumes of stuff coming into them that you typically get
in consoles.
<p>
I believe this is not so much because of the complex Document and Element
structures but due to the same reasons that could make Term slow, and
that is control over buffering and batching, or rather lack thereof.
Read the
<a href="#performance">section on performance</a> to see
what I mean.
<p>
<li>
The selection and the cursor are strongly tied together in Swing. With Term
the selection is independent of the cursor.
<p>
<li>
Swing provides a whole infrastructure for Actions, KeyMaps, undoing etc.
Which are neccessary for it's functioning as a document "editor". Term,
while internally maintaining a document and performing "edits" on it, is
not fundamentally an editor and can dispense with all of the above.
<p>
<li>
Swing uses offsets as opposed to cartesian coordinates. Since the
bulk of the operations of terminal emulators involves cartesian
cursor motion and such, in order to reuse a Swing text component a
fair amount of machinery has to be added to convert between the two.
<br>
Some ideas I've tossed out:
<p>
<dl>
<dt>Pad lines with spaces
<dd>... so every "line" is 80 characters wide, making it easier
to do arithmetic. But then selection will absorb those spaces
which have to be thrown out etc.
<dt>Track line boundaries
<dd>
Using Positions for evey line? Expensive.
Tracking edits and maintaining my own map? Exspensive.
<dt>Use "Line" Elements.
<dd>Expensive but more importantly means we forego using Elements
for more useful delineations.
</dl>
<p>
<li>
Swing Elements are very similar to Terms ActiveRegions.
They differ in the following respects though:
<ul>
<p>
<li>
Elements use Positions. While ActiveRegions use Coords.
Positions are "marks" and entail a fair amount of overhead,
while Coords are like offsets.
<p>
The offsets used by Term are actually valid as regions go out
of history. This because "absolute coordinates" are used where
each line put into Terms history gets a serial row number which
only grows. Term correctly handles the case where the 32-bit
absolute row number wraps. At a continuous rate of output of
4000 lines/sec the wrapping will happenin about 4 days.
<p>
<li>
Elements and AttributeSets are tightly bound, while with Term
Character attributes are set completely independently of Active
Regions.
<p>
<li>
Elements are strictly nested. That is, there is no gap between
the beginning of a branch Element and the beginning of it's first
child. ActiveRegions can be arranged more flexibly.
</ul>
<p>
<li>
CaretEvent gets fired everytime the cursor moves. Imagine what this does
to massive amounts of text being hurled at a terminal emulator, even
if no-one is listening.
<p>
<li>
Swings 'int offset' is "between" characters, while termulators work
with coordinates "on" characters. I"m not sure that Position's BIAS
would help here. (This is perhaps a red herring since you can adopt
the convention that a caret's position implies a cursor on the character
following it).
</ul>
<p>
<dt>
<b>
Key tables
</b>
<dd>
(NOTE: This is not the same as Swings KeyMaps).
<br>
Term currently doesn't have a key map table. Most other termulators do.
The thing is I haven't yet seen the need. Lot of the usual type
of processing that key maps do seems to be absorbed by Swing and
AWT, so my initial hope was to just piggy-back on that. Same
thing for byte to char conversions.
<p>
There have been a few glitches like AWT converting a CR to a LF
that are currently being worked around in ad-hoc manner.
</dl>
<a name="source_code">
<h2>
Source code and demos
</h2>
</a>
The source code for Term is in the NB CVS repository under
<pre>
core/libsrc/org/netbeans/lib/terminalemulator.
</pre>
Two demo's are available:
<br>
(<b>Actually they are not!</b> I'm not sure whether it is appropriate
to put them into the CVS repository).
<a name="demo_build">
<h3>
Build tool demo
</h3>
<img src="snapshot.gif" alt="Snapshot of DemoBuild">
<br>
This is to showcase the capabilities of ActiveTerm and how it can be
used to annotate output, say from a build script.
<p>
A fair amount of the code has to do with the gui setup, javac Process
setup and capture of it's output.
Once the output is received it is processed line-by-line. A crude pattern
is used to detect the first line of a javac error message and a new
ActiveRegion is begun, while the previous one is ended. These active regions
have their feedback attribute set which means that they will be highlighted
as the mouse moves over them. Anyone who has had to decipher a
wrapped compilation line and error line from 'make' would appreciate this.
<p>
The sourcefilename and line number are also extracted using simple patterns
and put in their own ActiveRegions as HTML-style links, which if clicked will
bring up the right line # in some editor, or rather fake it using a popup.
<p>
The beginning of each error message is also tagged with a simple
glyph in the glyph gutter.
<p>
Please keep in mind that this is strictly a Term feature demo.
I"m not advocating using glyphs to tag error messasges, or that textual
pattern recognition should be used for detecting distinct error
messages and their component, nor is capturing of Process output is as
trivial as it seems here (if the demo had instead used 'make' you'd
see some reordering of output because some comes from stdout and
some comes from stderr).
<a name="demo_telnet">
<h3>
Telnet demo
</h3>
For a telnet client it uses portions of
<a href="http://www.mud.de/se/jta/">
The Java(tm) Telnet Application/Applet
</a>
by Matthias L. Jugel and Marcus Meisner.
I haven't included that stuff here to save space but you only need
<pre>
de/mud/ternet/ScriptHandler.java
de/mud/ternet/TelnetProtocolHandler.java
de/mud/ternet/TelnetWrapper.java
</pre>
You'll have to tweak the settings in the Makefile and the 'telnet' wrapper
script.
</body>
</html>
|