The ANSI-BBS Specification

This "specification" is designed to standardize the meaning of ANSI-BBS in the communications world. It is split into three parts. General definitions are contained in the core document, specifications for the handling of server to client communications and saved ANSI-BBS files are contained in this document, and client to server specicifications are contained in the Client Communications document.

This is not a comprehensive ANSI specification, but a compilation of current common practices.

ANSI-BBS terminal chariteristics:

Output area

Almost all ANSI-BBS terminals are 80 columns wide and usually default to 24 rows high. Is is widely considered acceptable to assume 80 columns, but not considered acceptable to assume 24 rows. Other common hights include 23, 25, 42, and 49 rows.

Font issues

Most english BBS software assumes that IBM CodePage 437 is in use at all times, and extensive use is made of the extended ASCII characters in the 128-255 range. In many cases, if the user asserts that he supports ANSI, that user is assumed to be using this codepage. This is flawed but exceedingly common. In many countries not in North America, the most common codepage will not be IBM CodePage 437, which will cause visual glitches in a significant number of BBS programs.

Also common is the usage of some of the so-called "low ASCII" characters which IBM systems will use when control characters (those from zero to 31) are displayed. Only five are generally interpreted as control characters. Using terminals intended for non-BBS use will often cause glitches and outright malfunctions when used with BBS software. Many of these terminals will not display anything for these characters. Another group will display different glyphs for these. Most will cause exceedingly bad effects when certain control characters are sent to the terminal. The worst control sequences, their effects, and work-arounds are as follows:

SO (0x0e): Shift Out
Effects: Terminals which properly support the Shift Out control character will cause the meanings of all following characters to be changed. This will result in "gibberish" being displayed after this character is sent to the terminal.
Work-around: After sending an SO character, send the "Shift In" character (0x0f) followed by a backspace, a space, then another backspace. The SI character "undoes" what the SO character does. The backspace space backspace sequence erases the SI character on terminals which display it as the "white sun with rays" character.
ENQ (0x05): Enquiry
Effects: Terminals which properly support the Enquiry will send an arbitrary identification string back to the sender. This will be interpreted as characters which were entered by the user. It is quite common to encounter a loop by which one or more of the reply characters trigger another ENQ to be sent.
Work-around: Send a CSI6n after the ENQ then discard all input until the response is recieved.

End of line behaviour (wrapping)

This behaviour is a major weakness in the current ANSI-BBS world. Because there is no officially correct behaviour at the end of a line, many different methods have been implemented by different terminal programs. The end result is that you cannot rely on what happens after a character is placed at the end of a line. In general, people simply avoid using the last column. This isn't necessary however since you can work-around this by using an absolute character positioning after writing to the last column. It is encouraged that programs which create ANSI art handle writes to the last column in this manner. The best method to use is as follows:

  1. At the beginning of a line which contains a character in column 80, add a line feed (0x0a) followed by the ESC [ A sequence to move the cursor back to the previous line. This forces a scroll if the current line is the last one on the screen.
  2. Add an ESC [ s sequence to save the cursor position.
  3. After the character is written to column 80, add an ESC [ u sequence to restore the cursor position
  4. Add a carriage return (0x0d) then line feed (0x0a). The CR/LF combination is used to allow proper line ending detection on Microsoft operating systems.

Attributes

This document will often speak of attributes. An attribute is a complete combination of four different factors which effect visual presentation of a character. These factors are:

Control characters:

While control characters have well defined meanings intended for terminals, BBS tradition has used these to display IBMs "low ascii" glyphs. Because if this historical usage, we must therefore support this if we intend to be compatible with a larger number of door games. In the standards, these are referred to as the C0 control function set.

This is a list of control characters and either their effect or the glyph which they display

NUL (0x00):
No action. The NULL character is silently discarded. Traditionally, the NUL character has been used as a pad character by UNIX systems. Because of this historical usage, this must be retained. DoorWay mode also makes extensive use of the NULL character.
SOL (0x01):
This will display the "while smiling face" (☺) character which is unicode 9786 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
STX (0x02):
This will display the "black smiling face" (☻) character which is unicode 9787 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
ETX (0x03):
This will display the "black heart suit" (♥) character which is unicode 9829 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
EOT (0x04):
This will display the "black diamond suit" (♦) character which is unicode 9830 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
ENQ (0x05):
This will display the "black club suit" (♣) character which is unicode 9827 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
ACK (0x06):
This will display the "black spade suit" (♠) character which is unicode 9824 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
BEL (0x07):
Beep - Causes the terminal to make a beep sound. The duration and frequency of the beep is up to the implementor and a system "beep" should be used when possible. However, as a rough guide, 440Hz, 100ms duration has been used by some terminals.
BS (0x08):
Backspace. Moves cursor position to the previous column unless the current column is the first, in which case no operation is performed. This may or may not be implemented as a "destructive" backspace which will remove the character from that position too and possibly change the current background colour to the current one. Because of this ambuguity, it is strongly suggested that you always use the backspace space backspace sequence. The specification calls for a NON destructive backspace.
TAB (0x09): (Subject to discussion)
Moves to the next tab stop. This may or may not erase characters from the current location to the new one. The specification indicates that the characters should NOT be erased.
LF (0x0a):
Move cursor position to same column of the next row. If current row is the last row, scrolls the screen up and fills the new row with the current attribute.
VT (0x0b):
This will display the "male sign" (♂) character which is unicode 9794 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
FF (0x0c):
Clears screen and homes cursor. Same as CSI2J.
CR (0x0d):
Move cursor position to column 1 of the current line
SO (0x0e):
This will display the "beamed eighth notes" (♫) character which is unicode 9835 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character. Not supported by mTelnet
SI (0x0f):
This will display the "white sun with rays" (☼) character which is unicode 9788 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character. Not supported by mTelnet
DLE (0x10):
This will display the "black right-pointing pointer" (▶) character which is unicode 9654 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
DC1 (0x11):
This will display the "black left-pointing pointer" (◀) character which is unicode 9664 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
DC2 (0x12):
This will display the "up down arrow" (↕) character which is unicode 8597 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
DC3 (0x13):
This will display the "double exclamation mark" (‼) character which is unicode 8252 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
DC4 (0x14):
This will display the "pilcrow sign" (¶) character which is unicode 182 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
NAK (0x15):
This will display the "section sign" (§) character which is unicode 167 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
SYN (0x16):
This will display the "black rectangle" (▬) character which is unicode 9644 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
ETB (0x17):
This will display the "up down arrow with base" (↨) character which is unicode 8616 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
CAN (0x18):
This will display the "upwards arrow" (↑) character which is unicode 8593 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
EM (0x19):
This will display the "downwards arrow" (↓) character which is unicode 8595 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
SUB (0x1a):
This will display the "rightwards arrow" (→) character which is unicode 8594 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
ESC (0x1b): (Subject to discussion)
This chacter is reserved for use to introduce control codes and control characters.
FS (0x1c): (Subject to discussion)
This will display the "turned not sign" (⌙) character which is unicode 8985 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
DISCUSSION:
It has been suggested that the far more common "right angle" (∟) which is unicode 8735 be used here. Apparently, IBM now uses this character in their maps.
GS (0x1d):
This will display the "left right arrow" (↔) character which is unicode 8596 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
RS (0x1e):
This will display the "black up-pointing triangle" (▲) character which is unicode 9650 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.
US (0x1f):
This will display the "black down-pointing triangle" (▼) character which is unicode 9660 and occupies this slot on IBMs running codepage 437. This will be treated as a normal character.

Two-byte control functions

Two-byte control function format

Known as the "7-bit C1 control function set" for '@' to '_' and the "Independant control functions" for '`' to '~' in standards, these are two-byte combinations which do not take any parameters. The first byte is always an ESC (0x1b) character. The second byte is from the range '@' (0x40) to '~' (0x7e) inclusive.

Unhandled functions

If a legal function which the terminal does not support is encountered, that function should be silently ignored.

Illegal functions

An illegal function is defined as any ESC character followed by any character which is not in the range of '@' (0x40) to '~' (0x5f) inclusive.

When an illegal function is encountered, the terminal should attempt to make this known to the user in some manner. Commonly all or part of the sequence itself is displayed

Defined Control Functions (in alphabetical order by the second byte)

ESC[
Control sequence Introducer (CSI)
This indicates the start of a control sequence. See the section on control sequences below for more details.

Control Sequences:

Control Sequence Format

Control sequences make up the bulk of the ANSI-BBS spec. And contain four distinct parts which are, in order:

Control Sequence Introducer (CSI)
The two-character CSI consists of the ESC character (0x1b) followed by the '[' character (0x5b)
Parameter Bytes (PBs)
Parameter bytes consist of zero of more of the characters from '0' (0x30) to '?' (0x3f)
Intermediate Bytes (IBs)
Intermediate bytes consist of zero or more of the charaters from ' ' (0x20) to '/' (0x2f)
Final Byte (FB)
The final byte consists of one of the characters from '@' (0x40) to '~' (0x7e)

All control sequences begin with a CSI, are followed by a series of zero or more PBs which are followed by zero or more IBs and terminated with a FB. The IBs and the FB together make a string which defines the Control Function CF.

Parameter Byte Formats

If a parameter byte string consists of only characters from '0' to ';' inclusive ("0123456789:;") then it is interpreted as a list of semi-colon (';') separated numeric values. The meaning of a colon in a value must be defined by the control function. If it is not so defined, anything between a colon and the end of that sub-parameter is ignored (ie: up to the next semi-colon, IB, or FB).

If a parameter byte string begins with one of the chrarcters from '<' to '?' inclusive ("<=>?") then it is part of an extension which will be defined in another document.

If a parameter byte string begins with one of the characters from '0' to ';' inclusive ("01234567890:;") but contains one of the characters from '<' to '?' ("<=>?"), it is deemed to be an illegal sequence and should be handled accordingly.

Unhandled sequences

If a legal sequence which the terminal does not support is encountered, that sequence should be silently ignored. If one item in a parameter list is not handled, only that single unhandled parameter should be ignored. All other parameters from the list should be handled.

Illegal sequences

An illegal sequence is defined as:

  1. A sequence which begins with a CSI but has any IB character before any PB character.
  2. A sequence which begins with a CSI and contains a character which is not a legal PB, IB, or FB
  3. A sequence which begins with a CSI, is followed by a PB from the set of charaters from '0' to ';' inclusive, and contains a PB from the set of characters from '<' to '?' inclusive.

When an illegal sequence is encountered, the terminal should attempt to make this known to the user in some manner. Commonly all or part of the sequence itself is displayed

Defined Control Sequences (in alphabetical order by FB)

The following is a list of commonly defined control sequences for ANSI-BBS terminals. Parameters will be indicated by one of:

IBs and FBs will be shown Like this.
CSIp1@
Insert Character(s)
Defaults: p1 = 1
Moves text from the current position to the right edge p1 characters to the right, with rightmost charaters going off-screen and the resulting hole being filled with the current attribute.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
Not supported by mTelnet
CSIp1A
Cursor Up
Defaults: p1 = 1
Moves the cursor position up p1 lines from the current position. Attempting to move past the screen boundaries stops the cursor at the screen boundary.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
CSIp1B
Cursor Down
Defaults: p1 = 1
Moves the cursor position down p1 lines from the current position. Attempting to move past the screen boundaries stops the cursor at the screen boundary.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
CSIp1C
Cursor Right
Defaults: p1 = 1
Moves the cursor position right p1 columns from the current position. Attempting to move past the screen boundaries stops the cursor at the screen boundary.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
CSIp1D
Cursor Left
Defaults: p1 = 1
Moves the cursor position left p1 columns from the current position. Attempting to move past the screen boundaries stops the cursor at the screen boundary.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
CSIp1;p2H
CSIp1;p2f
Cusror Position
Defaults: p1 = 1 p2 = 1
Moves the cursor to the p2th column of the p1th line.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
CSIp1J (Subject to discussion)
Erase in Page
Defaults: p1 = 0
Erases from the current screen according to the value of p1
  1. Erase from the current position to the end of the screen.
  2. Erase from the current position to the start of the screen.
  3. Erase entire screen. As a violation of ECMA-048, also moves the cursor to position 1/1 as a number of BBS programs assume this behaviour.
Erased characters are set to the current attribute.
DISCUSSION:
Should ESC 2 J violate the spec?
Source: BANSI.TXT
CSIp1K
Erase in Line
Defaults: p1 = 0
Erases from the current line according to the value of p1
  1. Erase from the current position to the end of the line.
  2. Erase from the current position to the start of the line.
  3. Erase entire line.
Erased characters are set to the current attribute.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
mTelnet interprets any sequence ending in 'K' as though p1 is zero
CSIp1L
Insert Line(s)
Defaults: p1 = 1
Inserts p1 lines at the current line position. The current line and those after it are scrolled down and the new empty lines are filled with the current attribute.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
CSIp1M
Delete Line(s)
Defaults: p1 = 1
Deletes the current line and the p1 - 1 lines after it scrolling the first non-deleted line up to the current line and filling the newly empty lines at the end of the screen with the current attribute. Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
CSIp1P
Delete Character
Defaults: p1 = 1
Deletes the character at the current position by shifting all characters from the current column + p1 left to the current column. Opened blanks at the end of the line are filled with the current attribute.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
Not supported by mTelnet
CSIp1S
Scroll Up
Defaults: p1 = 1
Scrolls all text on the screen up p1 lines. New lines emptied at the bottom are filled with the current attribute.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
Not supported by mTelnet
CSIp1T
Scroll Down
Defaults: p1 = 1
Scrolls all text on the screen down p1 lines. New lines emptied at the top are filled with the current attribute.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
Not supported by mTelnet
CSIp1X
Erase Character
Defaults: p1 = 1
Erases p1 characters starting at the corrent position. Will not go past the end of the line.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
CSIp1Z
Cursor Backward Tabulation
Defaults: p1 = 1
Move the cursor to the p1th preceeding tab stop. Will not go past the start of the line.
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
Not supported by mTelnet
CSIpXm
Select Graphic Rendition
Defaults: pX = 0
Sets or clears one or more text attributes. Unlimited parameters are supported and are applied in received order. The following are supoprted:
Modifies
pXDescriptionBlinkBoldFGBG
0 Default attribute, white on black X X X X
1 Bright Intensity X
2 Dim Intensity X
5 Blink (slow) X
6 Blink (fast) X
7 Negative Image - Reverses FG and BG X X
8 Concealed characters. Sets the FG to the BG X
22 Normal intensity X
25 Steady (not blinking) X
30 Black foreground X
31 Red foreground X
32 Green foreground X
33 Yellow foreground X
34 Blue foreground X
35 Magenta foreground X
36 Cyan foreground X
37 White foreground X
40 Black background X
41 Red background X
42 Green background X
43 Yellow background X
44 Blue background X
45 Magenta background X
46 Cyan background X
47 White background X
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
CSIp1n
Device Status Report
Defaults: p1 = 0
A request for a status report. ANSI-BBS terminals should handle at least the following values for p1
  1. Request active cursor position
    terminal must reply with CSIp1;p2R where p1 is the current line number counting from one, and p2 is the current column.
NOTE: This sequences should not be present in saved ANSI-BBS files
Source: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
CSIs
Save Current Cursor Position
No parameters
Saves the current cursor position for later restoring with CSIu.
Source: DOS ANSI.SYS Documentation
CSIu
Restore Cursor Position
No parameters
Move the cursor to the last saved position. If no position has been saved, the cursor is not moved.
Source: DOS ANSI.SYS Documentation

Please feel free to Comment on this page.