ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Historical Overview ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Wynn Wagner III, the author of Opus-CBCS, developed a method of storing video control codes in a file sent to the Opus caller which was meant as a replacement of ANSI escape codes. Its main advantages were: ù The codes are smaller than ANSI, thus needing less disk storage space. ù The codes are in the binary form easily interpreted by the computer (ANSI sequences use ASCII). ù The same file can be sent to callers who do or do not have the ability of interpreting ANSI codes - in the former case the codes are first translated to ANSI, in the latter they are ignored. Because of lack of an appropriate name, Wynn temporarily named the codes oANSI with the understanding that a better name was needed. When George Stanislav started working on a TinyTerm communi- cations program, he had the idea that if Opus-CBCS could send the "oANSI" codes directly over the phone lines, it would speed up the communications considerably. A typical ANSI sequence contains 4 times as many bytes as the codes developed by Wynn Wagner. That phone call to Wynn resulted in two things: ù TinyTerm can interpret the "oANSI" codes and translate them to ANSI, then send them to stdout where they are converted to colors by ANSI.SYS. ù Opus-CBCS, starting with gamma version 1.10.iii, will send the codes without converting them to ANSI sequences. (It will still send ANSI codes to users without the proper terminal software.) He took over the coding of the part of Opus handling the video codes. He realized the codes were offering us much more power than just translating them to ANSI escape sequences. George proposed to call the codes AVATAR, the Advanced Video Attribute Terminal Assembler and Recreator. Wynn readily accepted the new name. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ The Two Levels of Avatar ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Avatar is more than a video attribute controller. It is a pro- tocol which, if need be, can totally eliminate the interference of line noise. However, this document is not concerned with the advanced topics of Avatar (which no BBS ware is using as of this writing). A full Avatar session with all its advanced features starts by exchanging the AVINIT packets. The caller sends a packet which de- scribes the video capabilities of his/her system. It also contains the caller's name, password and some other optional information. It also tells the BBS if the user is calling in person or just emulating a BBS session with an Avatar terminal program. The called system (the BBS) replies to the AVINIT packet with a packet that informs the user of his current status, i.e. you can stay until 16:30 PST, or you are denied access, or I am processing mail now but you can call back at 10:43 PST, etc. Until such AVINIT packets are exchanged, only the Avatar commands that were part of the original oANSI codes can be sent from the BBS to to the caller. The caller's term program should send no Avatar commands, with the exception of function key codes, before the AVINIT packets are exchanged. This assures that a BBS program which does not support full Avatar can still take advantage of the faster transfer of video codes using Avatar as opposed to ANSI escape sequences. It also permits the caller whose term program does not support full Avatar but can interpret the basic codes to take advantage of the term program's abilities. The two levels of Avatar then are: a full session and a basic session. This document is concerned with the BASIC Avatar session only. The full session will be defined in the future. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Basic Avatar Commands ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Before the AVINIT packets are exchanged, the BBS can send the basic Avatar commands if so permitted by the user's choice, typically recorded in the user datafile (ie. USER.BBS). Because Avatar is window oriented, in a basic session the full screen is considered the default window. Further, the default color of the window is assumed to be 3 (cyan text on a black background). All bytes are taken at their face value without escaping. However, save for one exception described below, no basic Avatar code will have the high bit set. Therefore, the term program should reset the high bit of all bytes except as described below. The basic commands are: <^L> - clear the current window and set current attribute to default. In the basic session this means: Clear the screen and set its attribute to 3. <^Y> - Read two bytes from the modem. Send the first one to the screen as many times as the binary value of the second one. This is the exception where the two bytes may have their high bit set. Do not reset it here! <^V> <^A> - Set the color attribute to . The default attribute remains unchanged. However, all text will be displayed in until the next ^V^A, ^V^B, or ^L. <^V> <^B> - Turn the high bit of current attribute on. In other words, turn blink on. <^V> <^C> - Move the cursor one line up. Do nothing, if you already are at the top line of the current window. <^V> <^D> - Move the cursor one line down. Do nothing if you already are at the bottom line of the current window. <^V> <^E> - Move the cursor one column to the left. Do nothing if you already are at the leftmost column of the current window. <^V> <^F> - Move the cursor one column to the right. Do nothing if you already are at the rightmost column of the current window. <^V> <^G> - Clear the rest of the line in the current window using the current attribute (not to be confused with the default attribute). <^V> <^H> - Move the cursor to the position within the current window. Comments: Current attribute and default attribute are not necessarily the same. Whenever the window is cleared by the <^L> command, the current attribute is made equal to the default attribute. There is also another command to make the current attribute equal to the default attribute. However, this command is not a part of the basic Avatar command set and therefore cannot be used before the AVINIT packets are exchanged. Whatever characters are sent to the screen, they should be displayed using the CURRENT attribute. There is an exception to this, but only after the AVINIT packets have been exchanged. The attribute byte is an eight-bit value. As basic Avatar can only transfer 7-bit commands, the high bit of the attribute byte can be set only by the <^V> <^B> command. The byte of the <^V> <^A> command should be AND-ed with 7F (hexadecimal). The colors set by the attribute byte are the same as are the colors of the text mode of an IBM color graphics adapter. That means the bits of the attribute byte have the following meaning: bit: 7 6 5 4 3 2 1 0 - - - - - - - - ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ÀÄÄÄÂÄÄÄÙ ÀÄÄÄÄÄÂÄÄÄÄÄÙ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ text color ³ ³ ³ ³ background color ³ blink If the blink bit is set, the text is blinking, else it is not blinking. The bits of background color can have values 0 - 7, the bits of the text color can have values 0 - 15. The value indicates the following colors: 0 black 1 blue 2 green 3 cyan 4 red 5 magenta 6 brown 7 gray (i.e. non-itense white) 8 dark gray 9 light blue 10 light green 11 light cyan 12 light red 13 light magenta 14 yellow 15 white (intense) Colors 8 - 15 are the same as 0 - 7 but with high intensity. Please note that these values are different from the numbers used by ANSI escape codes, if you are familiar with TheDraw or BASIC, these are the same numbers used by the two programs. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ The Function Key Codes ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ An Avatar capable BBS can accept function keys from the remote caller. This feature is optional (for the term program) but highly recommended. On an IBM (compatible) computer this means that if a caller hits a function key (ie., left arrow, page up, F7, insert, alt-H, etc.), the term program should send two bytes to the Avatar capable BBS: A binary zero followed by the keyboard scancode. Please note that con- trol keys (^A, ^B, etc.) are not function keys but have an ASCII value which is the only byte that should be transfered. There are two keys on the IBM keyboard that do have an ASCII value but also offer a separate scan code. These are the gray-plus and the gray-minus. If one of these keys is hit, treat it as a function key - send the binary zero followed by the scan code. This way if the BBS treats them differently from a regular plus and minus keys, the caller can take advantage of the keys. On the other hand, BBS writers who do not want to assign the gray keys a special value, should watch for their codes and treat them as a regular plus and minus. Systems that use a different keyboard layout (and scan codes) than IBM can emulate IBM by declaring which keys are considered the arrows, f-keys, etc. If you have the arrow keys, for example, but their scan codes are different, still send the binary zero and the scan code that an IBM keyboard would assign to that particular key. This should be transparent to the user. There is an obvious problem here. All terminal programs I have seen use function keys internally. A switch is needed so the user can decide whether a function key is meant for the internal use of the term program or it should be transfered to the BBS. Most but not all IBM clones have a scroll lock key, some even have an LED indicator on it. The IBM programs could use that as a switch to know what the user means by hitting a function key. Since some compatibles do not have a scroll lock key (ie. Tandy 1000), the Avatar capable BBS should never expect the combination to be transfered. That way the term program can use to switch between the local and remote use of function keys if the scroll lock key is not available. ÄÄÄÄÄÄÄÄÄÄ Conclusion ÄÄÄÄÄÄÄÄÄÄ This should about summarize the basic Avatar commands. Portions of this documentation was written by George Stanislav before leaving summer vacation realizing that it would be nice to give software developers of both BBS software and Communication programs something before releasing the specs of the full Avatar implementation. Here is also some sample C code. It assumes you have some low communications functions of your own. For the screen output it uses Turbo C library, but you can use anything you want. #include int def_attr = 3; int cur_attr = 3; int lastline = 25; int lastrow = 80; /* WARNING: This code has not been tested. */ /* It is just meant as an example. */ void pascal avatar() { int c,i,j; switch (mgetchar()) /* Read a char from the modem */ { case 12 : textattr(cur_attr = def_attr); /* ^L */ clrscr(); break; case 25 : c = mgetchar(); /* ^Y */ j = mgetchar(); for (i = 0; i < j; i++) cprintf("%c",c); /* print in color */ break; case 22 : switch(mgetchar()) /* ^V */ { case 1 : cur_attr = mgetchar() & 0x7f; textattr(cur_attr); break; case 2 : cur_attr ³= 0x80; textattr(cur_attr); break; case 3 : if ((i = wherey()) > 1) gotoxy(wherex(),i - 1); break; case 4 : if ((i = wherey()) < lastline) gotoxy(wherex(), i + 1); break; case 5 : if ((i = wherex()) > 1) gotoxy(i - 1,wherey()); break; case 6 : if ((i = wherex()) < lastrow) gotoxy(i + 1,wherey()); break; case 7 : cleol(); break; case 8 : i = mgetchar(); gotoxy(mgetchar(),i); } } } ÄÄÄÄÄÄÄÄÄÄÄ Definitions ÄÄÄÄÄÄÄÄÄÄÄ Avatar, level 0 - The Avatar protocol as presented at Fidocon '88 and described in AVATAR0.C, dated 23 August 1989, plus extensions defined in this document. AVT/0 - An abbreviation for Avatar, level 0, suggested by Joaquim Homrighausen. Current attribute - Video attribute defined by the last ^V^A, ^V^L, ^V^M or ^L AVT/0 command whichever happened last. In AVT/0, ^L sets the value of current attribute to 3, ^V^L, ^V^M and ^V^A to an explicit value. In addition, ^V^B turns blink on. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Extending AVT/0 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ It had become clear some of the Avatar commands originally reserved for AVT/1 would be very useful in AVT/0. George Stanislav was hesitant to add them for one simple reason: Any addition on level 0 would break all existing Avatar emulating software. At the time these modifications were made, there were only three known programs that had implemented Avatar emulation. Those programs were Stanislav's own Tiny Term, Joaquim Homrighasen's Frontdoor, and Jason Galanter's Jterm. Stanislav was assured by Joaquim and Jason that they would put the new commands in their programs, thus nothing would be broken. With that assurance in mind, he felt confident no chaos would result from adding these new commands. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ New Commands (brief definitions) ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ <^V><^I> - Turn insert mode ON. It stays on until any other AVT/0 command except <^Y> and <^V><^Y> is encountered after which it is turned off; <^V><^J> - scroll area up; <^V><^K> - scroll area down; <^V><^L> - clear area, set attribute; <^V><^M> - initialize area, set attribute; <^V><^N> - delete character, scroll rest of line left; <^V><^Y>[...] - repeat pattern. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Detailed Description ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Insert mode: Insert mode controls the way characters are printed on the screen. Insert mode is always assumed OFF unless explicitly set ON by the ^V^I command after which it stays on until another AVT/0 command except for ^Y or ^V^Y is encountered. Then it reverses back to off. Whenever insert mode is OFF, characters are printed on the screen like this: 1. Print character at current cursor position using current attribute, overwriting whatever was previously displayed at current cursor position; 2. Move cursor to next position, usually one character to the right. At end of the line, move the cursor to next line (possibly scrolling the display or current window if in AVT/1). Whenever insert mode is ON, characters are printed on the screen as follows: 1. Starting at current cursor position and going all the way to the second last character on current line, scroll the text one character to the right; 2. Discard the character previously at the end of the line, do NO move it at the beginning of the next line; 3. Print character at current cursor position using current attribute; 4. Move cursor to next position, precisely as in par. 2 of insert mode off. If ^Y or ^V^Y are encountered, the string of characters they com- press is first expanded, then treated as an ordinary stream of char- acters printed according to the above rules. Any other AVT/0 command turns insert mode back off. Please note that in either case the cursor is moved to its next position in an identical manner. The mere fact the cursor is moved to next line, or even scrolls the screen a line up, does NOT turn insert mode off. Only an AVT/0 except as mentioned above can change insert mode on or off. If control characters are a part of the text stream, they are interpreted indentically in insert mode on and off as follows: Carriage return - move cursor at the beginning of the same line; Line feed - move cursor one line down (scroll screen or window [in AVT/1] if necessary), do not change cursor column; Back space - move cursor one position to the left. Do NOT overwrite the character at that position. Do nothing if already at the leftmost position; Tab - move cursor to next tab position without over- writing anything. Tab positions are mult- iples of 8. Do nothing if already at the rightmost position. A space is treated as a character, not as a control character. Scrolling an area (^V^J and ^V^K): The area defined by its upper, left, lower and right coordinates is scrolled up <^V^J) or down (^V^K) by lines filling the gap with blank spaces using current attribute. If the value of is zero or exceeds the actual number of lines within the scrolled area, the area is filled with blanks using current attribute. These two commands do NOT change the position of the cursor, nor do they define the scrolled area as the default window. The coordinates are relative to the upper left corner of the screen (or current window in AVT/1). The coordinates of upper left corner are 1,1. If a coordinate contains 0, it is to be changed to 1. Initializing an area (^V^M): This command contains several steps: 1. Set current attribute to ; 2. Starting at current cursor position (inclusively), ending at current cursor position plus number of and , print at all position inside the defined area. Do not move the cursor. If the number of columns or lines exceeds whatever is available to the right and below current cursor position, truncate the dimensions to fit within the limits of the screen (or current window in AVT/1). Clearing an area (^V^L): This is a shortcut version of the ^V^M command. The character to be used to initialize the area of the screen is assumed to be a blank space. In other words, it sets current attribute and clears an area of the screen start- ing at current cursor position (which remains unchanged). Please note that the usual 7-bit restriction applies to ^V^L. That means that the attribute byte should be anded with 7f hex before applying. If blinking is desired, ^V^B should be used next. On the other hand, requiring to ignore the high bit in ^V^M would make it impossible to fill the area of the screen with a blinking pattern. Therefore, if bit 7 of attr is set in ^V^M, current attribute is set to AND 7f hex and blink is turned on before filling the area with a character. Deleting a character (^V^N): Starting at the column one character to the right of current cursor position all the way to end of the line, scroll the text one character position to the left. This effectively deletes the character at current cursor position. Print a blank space using current attribute at the rightmost end of the line to fill the gap. Do not change current cursor position. If the cursor is at the end of the line, simply overwrite the last character with a blank space using current attribute. Repeat pattern: This is an extension of the ^Y command which allows a group of characters to form a repetititious pattern. determines the number of characters in the pattern, the number of times the pattern is to be printed out. The pattern may contain AVT/0 codes. For example, <^V><^Y><#3>ABC<#4> expands to "ABCABCABCABC". ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Scrolling Philosophy ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ An important philosophical question has not been answered yet: When scrolling the contents of an area (in the scrolling commands ^V^J and ^V^J, in insert mode ON and in deleting characters ^V^N) should only the text be scrolled and the attribute of the scrolled areas remain where they are or should the attributes move as well. A case can be made for either approach. Obviously, the gaps created by scrolling are filled with current attribute, therefore, it seems more logical to scroll the attributes along with the text (else there would be no need to fill the gaps). Thus we follow a consistent principle of video attributes belonging to a character (be it a blank, a digit, or a true character), not to a location. Whenever a character is scrolled to a different location, it takes its attribute along.