Emu Reference Manual

Introduction

One of the oldest and, perhaps, most used X utilities is the ubiquitous xterm program. An indispensible part of the X Window System, it is nonetheless showing its age. Due largely to creeping featurism and the somewhat strenuous process of being ported to a number of varied and idiosyncratic platforms, the xterm source has also reached a state where further extension and maintainance has become a non-trivial exercise.

In 1990, we faced the choice of either further extending xterm or starting over from scratch. After a long evaluation, we came to the conclusion that further attempts to modify xterm would benefit neither us or the X community at large.

Combining our altruistic impulses with a genuine need for a VT220 compliant xterm, we then set out to completely rewrite xterm from scratch. Using some of the lessons learned from the original xterm (design vs creeping mutation) and taking full advantage of having a nice toolkit to work with (something, to be fair, the original designers did not have), we managed to add many new features without significantly exceeding the size of the old xterm program. We were also able to use the toolkit's widget mechanism almost exclusively as a framework, a major win in and of itself.

A secondary, but by no means trivial, design goal was to release not so much "an xterm done right" but also a set of tools with which users could go well beyond what is initially offered here. Given that the needs of users are many and varied, we focused more on providing a logical and portable framework than on providing a single-purpose canned solution. Using this system, users can easily add custom terminal emulators, display canvases, menus and other 'decorations' using either an Athena or Motif look and feel as desired. Application writers will also now find it quite simple to use a slave xterm from a larger application; one simply creates a couple of widgets and takes advantage of the hooks provided for getting at the incoming and outgoing data streams. A number of programmers accustomed to fighting with the old xterm's slave mode should now find life much easier. Like the X group itself, we have attempted to provide mechanism, not policy, wherever possible.

The end result, after almost 2 man years of work, is something both simpler and more complicated than the original xterm. As we were stuck for a really clever name, we decided to call it emu, which is short for emu-lator. Whether or not the code makes one think of large, hairy, flightless birds is purely a subjective issue and we refuse to touch it.

Being the kind souls that we are, we present this code free of charge to the X user community for their collective enjoyment and/or amusement. Caveat Emptor.

Glossary of Terms

In this manual, a number of special terms will be used that should be understood before going any further. Some of them may not make much sense initially, but it will at least be clear what the various buzzwords and abbreviations mean (each abbreviation will also be expanded the first time it's used, so it's not necessary to memorize everything at this juncture).

`auxTrans'
An AUXilliary TRANSlation. Used by the termCanvas widget to change the meanings of various keycodes (I.E. the keyboard mapping) on the fly. auxTrans Entries.
`canvas'
Generally refers to the termCanvas widget, though it can refer to any canvas widget being used for character or graphics I/O by the term widget. See section The Canvas Widget.
`comblock'
A data structure used by the ComBlock for data exchange, as well as a permanent 'scratch pad' for IOP programs to store data of general interest. See section The ComBlock Interface
`comblock communications protocol'
This mouthful refers to a specialized protocol used by the term widget and its canvas to pass requests and ancillary information back and forth. See section The ComBlock Interface.
`emu'
Refers both to the emu client program and the system as a whole. See section Using The Emu Client.
`emulation'
A collection of FLUTs, auxTrans entries, ROPs and input sequences that describe a complete terminal emulation.
`FLUT'
A Font LookUp Table. Used by the termCanvas widget to map ASCII characters to actual font glyphs. @xref{OP_CHANGE_FLUT}.
`IOP'
An Intermediate OPeration. Used by the canvas and term widgets as well as the menu package. IOP's are the workhorses of the emu package and, aggregated, form a small but functional programming language. See section The IOP Language.
`parser'
Escape sequence parsers come in two flavors, hard and soft. A hard parser is one compiled directly into the term widget for a specific terminal type. A soft parser is defined wholly in the resource database and can be modified without having to recompile anything.
`operation code'
A unique integer id identifying some canvas action to be performed. A request may or may not take parameters, which are then found in the comblock.
`sequence list'
A comma separated list of one or more requests. Sequence Lists are only encountered as parts of See section Input Sequences and ROPs.
`ROP'
A Reverse OPeration. This is basically the mirror image of an See section Input Sequences. Rather than describing characters going in, it describes an outgoing action to be performed (though this need not necessarily result in any characters being output). See section ROP Sequences.
`input sequence'
A request list followed by a bracket delimited string of tokens. Each token describes either a character to be expected as input or an IOP to be performed along the way. Refer to See section Input Sequences for more information, as this is somewhat complicated.
`input sequence list'
One or more input sequences that, as a unit, form part of an emulation.
`term'
Refers to the term widget which wraps around the canvas and any ancillary widgets.

Copyright Information

Copyright (C) 1990 PCS Computer Systeme, GmbH
Pfaelzer-Wald-Str 36, D-8000 Munich 90, West Germany.

Copyright (C) 1994 Jordan K. Hubbard and Michael W. Elbel

Everyone is permitted to copy, modify and distribute copies of this
license document, provided that the section "Copyright Information" is
included exactly as in the original.

                        All Rights Reserved

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

We would also like to request that any enhancements to this software, or
its documentation, be sent back to one of the authors for inclusion in
subsequent releases. While you are certainly not in any way legally
required to do so, such cooperation will result in a better emu for all
concerned and is thus kindly requested.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL PCS, THE AUTHORS, OR THEIR HOUSEPETS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Structure of the Emu System.

What has been referred to so far as The Emu System is really nothing more than two widgets and a sample client (see section Using The Emu Client). What makes it a system is more the way it all fits together and provides a framework for future expansion.

To better understand the system, it is probably a good idea at this point to break it down into its component parts and attempt to describe, briefly, what each part does. What follows should only be considered a brief overview since each topic is described in much more detail in its own section of this manual.

The first item of interest is the term widget, which basically manages all aspects of the operating system dependent interface: PTY allocation, process management, and terminal mode manipulation. To put it another way, the term widget can be thought of as analgous to the communications hardware of an actual terminal, minus the screen and keyboard.

The term widget also handles all parsing of special input sequences (more commonly referred to as 'escape sequences) from the process, turning them into operation codes (see section Input Sequences) that the canvas understands.

Finally, the term widget provides a number of features and hooks for applications that want to do fancier I/O control and/or additional widget management. While the term widget typically manages just one canvas child, it can also manage other children (even additional canvases) as necessary (see section The Term Widget). This is typically used to implement scrollbars and menubars.

The second (and complimentary) widget of interest is the canvas. The canvas is in charge of all 'screen' output, as well as the translation of keycode sequences into ascii characters and mouse controlled cut and paste operations. Using the analogy of a physical terminal again, the canvas widget would be the CRT and keyboard part.

The canvas compliments the term widget by supporting a set of generic operations, such as moving the cursor, inserting or deleting text, etc, which the term widget then 'requests' it to perform as its recognises various input sequences in its parser description. Likewise, the canvas relies on the term widget to communicate with the process when dispatching of I/O from the keyboard or cut buffer/selection mechanism is required.

As stated earlier, the term 'canvas' actually refers to any widget that can speak the ComBlock protocol with the term widget, not just the particular widget we supply. In theory, any number of canvas widgets can, and may, exist for doing various types of display I/O. At the time of this writing the one canvas, called the termCanvas (see section The Canvas Widget), exists for doing reasonably sophisticated text display (basic text + VT220 attributes). In time, there will probably be a number of additional canvases that support generic graphics operations, auxilliary input devices, etc. A client application will then have the option of creating any number of term/canvas pairs (or one term with multiple canvases) to suit a particular need.

The final part of the system is the emu sample client, which will typically be all the average user sees or cares about. Most of the client is rather simple. It first creates a shell widget to interact with the window manager, as is normal, and provides a number of command line options to get directly at various term and termCanvas resources. It then creates a term widget as its child and, in turn, a termCanvas widget and several optional control widgets under it. As previously stated, the term widget does not really care about any widgets other than its canvas, though it will readily manage them. This feature is used by the emu client to optionally create a scrollbar and menu bar. Since the term widget does not know or care about either of these, the management of their size and position is left to the emu client itself. This is handled through a callback provided by the term widget which is called whenever a Resize, GeometryRequest or Realize occurs. The emu client then adjusts things accordingly. The scrollbar callbacks are likewise handled by the client with the scrollbar motion being translated into canvas scroll requests.

While this approach may seem to put an undue burden on the client program, it has helped to keep the term and termCanvas widgets free of application specific code, and makes the decoupling of GUI elements and terminal emulation possible.

Also part of the emu client is the configurable menu package. Through the toolkit translation mechanism, any number of menus can be automatically attached to the term widget without it having to know or care. Unlike the menu code in the old xterm program, a menu's actions (as well as appearance) are completely user configurable. See section Menu Configuration.

Summary:

The general philosophy of the emu system was to provide two, very general purpose, communication and text manipulation widgets with ample room for future expansion. All 'decoratations' like scrollbars, menu bars and menus are implemented on the client side through hooks made available by the widgets for that purpose. This approach also allowed the emu client to provide either Athena or Motif widget look-and-feel at very little added cost.

Using The Emu Client

The emu client is used in much the same way as the old xterm program was, though there are a few new command line options. Since the emu system also relies much more heavily on resources than the old xterm, installation of the application defaults is almost mandatory before emu will work properly. Without its resources, the typical emu client does not even know how to emulate a terminal!

Virtually all aspects of the emu system are user configurable with almost nothing being assumed about specific terminal types, keyboards, output fonts or menus. Of course, should the standard VT220 Emulation included with emu be sufficient for your needs, you won't need to worry about any of this, but should you need it, the ability to customize just about everything is there.

Designing a New Emulation.

Writing a new (or modifying an existing) Emulation generally consists of 3 basic steps:

Menu Configuration

Emu's menus are very straight-forward, the menu module (as with the rest of emu) providing a simple mechanism without trying to determine usage policy. The module provides facilities for creating, managing, popping-up, and attaching policy (functionality) to menus. It does not dictate how many menus or menu items exist, what is in each menu, what functions it performs, or how it is popped up. This is all user configurable, and is specified via the resource manager. Menus are, therefore, fully extensible and configurable.

Menu Resources

The emu menus are configurable through the resource file. All Athena Form, MenuButton (both for menu bar), SimpleMenu, Sme, SmeBSB, and SmeLine, or Motif XmRowColumn, XmCascadeButton (both for menu bar), XmPopupMenu, XmPushButtonGadget, XmLabelGadget, and XmSeparatorGadget resources are available for customization. Please see the appropriate Intrinsics, Athena or Motif documentaion for further clarification of these resources.

In addition to these standard widget resources, the number of menus, the number of menu items, and the position of menu item separators are settable via resources. For each menu item it is also possible to specify what functionality (action) lies behind it.

Menus are configured via the screen translations by specifying a menu name to pop-up and a key/button sequence indicating how to activate it. For example, the default configuration could look like:

    *term.screen.Translations: #override\n\
        Ctrl ~Shift<Btn1Down>:          XpEmuPopupMenu(menu1) \n\
        Ctrl ~Shift<Btn2Down>:          XpEmuPopupMenu(menu2, 302) \n\
        Ctrl ~Shift<Btn3Down>:          XpEmuPopupMenu(menu3, 303) \n\
        Ctrl  Shift<Btn3Down>:          XpEmuPopupMenu(menu4) \n

These translations show that pressing 'Ctrl', but not 'Shift', Pops-Up A Menu Called 'Menu1'. The name 'menu1' actually becomes the name of the menu widget when it is created. It is necessary to have this name since it is used further for qualifying resources. The second and third menus are specified in a similar fashion but by pressing (mouse) button2 and button3, respectively. The fourth menu is also activated by pressing button3, but this time the 'Ctrl' And 'Shift' keys must be pressed.

'XpEmuPopupMenu' expects at least a menu name as a parameter. If other actions (ROPs) are desired on a per menu, not menu item, basis then additional parameters (ROP numbers) may be declared after the menu name. These actions are performed each time just before the menu is popped-up. The second and third menu declarations illustrates such a situation.

Menu Item Resources

The following resources control the behavior of individual menu items.

Number Of Menu Items

The menu package creates the number of user specified items. The default configuration for 'menu1' might look like:

    *menu1.numberItems:             8

This resource must be given.

Menu Item Labels

It is not necessary to specify menu item labels; the toolkit default is to use the menu item widget name, which is, e.g., 'item1'. The resource file, however, does specify item label defaults for the declared menus. The 'menu1' defaults could be:

    *menu1*item1.label:             Redraw
    *menu1*item2.label:             Reset all
    *menu1*item3.label:             Set TTY sane
    *menu1*item4.label:             Set TTY origin
    *menu1*item5.label:             Send INT signal
    *menu1*item6.label:             Send HUP signal
    *menu1*item7.label:             Send TERM signal
    *menu1*item8.label:             Send KILL signal

Menu Item Line Separators

In order that menu items within a menu may be functionally (or otherwise) grouped, line separators may be specified in the resource file. Items after which to put line separators are indicated as such:

    *menu1.itemLines:               item1 item4

Menu Item Actions

In most cases, it is necessary that for each menu item an action is specified. The action resource is, in effect, the function that is invoked when the menu item is selected. This resource may either be a number (ROP action) or a string (emulation action). For example, 'menu1"s items could have ROP action numbers as given below:

    *menu1*item1.action:            310
    *menu1*item2.action:            311
    *menu1*item3.action:            312
    *menu1*item4.action:            313
    *menu1*item5.action:            314
    *menu1*item6.action:            315
    *menu1*item8.action:            316
    *menu1*item9.action:            317
    *menu1*item10.action:           318
    *menu1*item11.action:           319

An example of emulation action specification is shown by the possible default 'menu4' action resources:

    *menu4*item1.action:            tty
    *menu4*item2.action:            emu

Code

Menus are created at that moment the user first clicks a particular button.

The menu package has three explicit contact points to the rest of the emu program. The first is for initialization, which simply registers the exportable actions (XpEmuPopupMenu) with the translation manager. This initialization routine (XpEmuInitializeMenus) is the only routine that must be called by the emu client program.

The second point of contact is for the dispatching of actions (XpEmuMenuDispatch) when menu items are clicked. This is done indirectly via the single menu item callback (DoInteract). The callback passes the respective menu item ROP action number or emulation action string, specified in the resource file, to the emu program. If no ROP number or emulation name exists for the selected menu item, the widget label, or lastly, the widget name are used. This indicates the selection is an emulation.

The third contact point is the complement of the second. It is for the emu program to tell the menu module to perform some action (XpEmuMenuAction). The actions the menu package can perform are limited to activating/deactivating (sensitizing) and marking/unmarking menu items.

The making of a menu consists of detecting the number of items and possible separator lines via the resource manager, and then creating the menu with the single menu callback. No local menu call data exists; all necessary menu information is stored in and derived from the resource manager or the toolkit. In this way, no local data structures are necessary, no local memory is allocated, and therefore, the number of menus and the number of menu items are dynamic and may be of any size. Also, by using a single callback with user specifiable ROP actions, functionality is attached at menu realization time by the resource manager.

The Term Widget

The term Widget is used to encapsulate three basic things in the general task of emulating a terminal:

Term Widget Resources

The following X-Toolkit resources are provided by the Term widget.

command
This is the shell command to invoke when first starting up the term widget. This is typically a shell, and defaults to `/bin/sh'.
commandArgs
Any arguments to pass to the shell command in command.
termType
The terminal type to initially configure the emulator for. Defaults to xterm.
canvas
How to register a canvas widget with the terminal emulator. Usually done at startup time.
iopRequestProc
A callback list of procedures to call when the IOP call C is invoked. See IOP Glossary for more details.
layoutProc
A layout procedure to call when a child requests a size or position change. This is typically used for effective management of things like canvass that want to toggle between 80 and 132 columns, for example.
processDeath
A callback list of procedures to call when the sub-process (or any subprocess) managed by the term widget ties.
readSize
The number of bytes to try to buffered read from a pty at once. Increasing this can result in better I/O performance but at a possible loss in interactive response. The default settings are probably best left alone.
inParser
A callback list of procedures to call when input comes in from the sub-process. By default, the parser(s) are at the end of this list, but you are free to add your own procedures to the beginning if you want early access to the data. Each callback in the list is passed a pointer to the input buffer and length, which they are free to adjust if they wish to "remove" input meant for them alone.
outParser
A callback list of procedures to call on outgoing data to the sub-process. This typically might be used for post-processing of data before it actually reaches the tty output routines, but is typically left NULL.
utmpInhibit
If the writing of utmp entries is supported, inhibit it. By default this is false.
loginShell
Set if you want the sub-process to be invoked as a login shell.
rops
A list of ROPs for general usage.

Porting To New Architectures

The task of allocation ptys, getting and setting tty values and dealing with things like utmp entries are all encapsulated by a set of standardized routines for each OS type in the `term/sysdep' directory. The routines are also layered in such a way as to support the specification of new operating system definitions in terms of existing ones, and for this no documentation will suffice so well as simply looking at the existing examples. A fairly rich set exists for System V, BSD and Linux architectures, and in all likelyhood it should require little more that adapting an existing set of descriptions when porting to a new machine at this point.

By convention, the system dependent routines should be implemented in two files under the `term/sysdep' directory:

These two files are then selectively pulled in with #ifdefs in the files `term/process.c' and `term/tty.c', respectively. Look in these two files to see how existing systems are configured before doing anything else.

The following routines comprise the system encapsulation API as implented in proc_*.i and tty_*.i:

These should be implemented in proc_<new_os_type>.i:

void process_init(TermWidget w)
Should do whatever's necessary to fork() off a process, initialize the new process group, chown the slave end appropriately, etc etc. Look at one of the existing examples for more details.
int process_wait(int *failcode)
Does whatever's necessary to wait() for a process that's died (this routine is only called in the event of child death). The routine should return the process id of the recently deceased with the value it returned (unmodified) being also stored in "failcode".

And these should be implemented in tty_<new_os_type>.i:

`String tty_find_pty(TermWidget w)'
Search for a free pty on the system and open it, assigning the appropriate Term widget file descriptors to the newly opened master end. Return the name of the master end as a string. Look at the existing examples for a good place to start; they're already pretty general.
`void tty_set_size(TermWidget w, int rows, int cols, int width, int height)'
Do whatever SIGWINCH'y type things that are necessary to let term's subprocess know that the window size has changed. This routing is optional, though certain editors may misbehave without it.
`void tty_add_utmp(TermWidget w)'
Add a utmp and/or wtmp entry for the term widget's tty. This routine is optional, though certain unix programs may fail without it.
`void tty_remove_utmp(TermWidget w)'
Remove a utmp and/or wtmp entry for the term widget's tty. This routine is optional, though it most certainly should be implemented if tty_add_utmp() is. The next three routines pass a private data structure around (the contents of which are left to their discretion) which is treated as a "generic" pointer value by the rest of the system.
`Generic tty_get_values(TermWidget w)'
Returns the current tty values for term's PTY. If "w" is NULL, then returns current values for invoking tty (only done once). This routine is optional, though performance without it may be marginal on some systems, depending on defaults.
`Generic tty_get_sane(TermWidget w)'
Returns a "sane" set of values which will result in law and order being restored on a PTY when applied. This routine is optional, though performance without it may be marginal on some systems, depending on defaults.
`void tty_set_values(TermWidget w, Generic values)'
Sets tty values for term's PTY to be "values" (assumed to be the product of an earlier call to tty_get_values() or tty_get_sane()). This routine is optional, though performance without it may be marginal on some systems, depending on defaults.

Managing Child Widgets

NOTE: This section currently unimplemented due to lack of time. Please see the sample client code that deals with scrollbars for a pretty reasonable example of how to do some of this. The canvas creation code also deals with the term widgets' handling of children.

The IOP Language

The IOP is the low-level workhorse of the emu package, doing everything from on-the-fly coordinate transformation in Input Sequences to setting flags, sending signals or invoking processes from menus! It is used in the consruction of so-called soft parsers, and is described in the overview.

IOP Overview

IOP code looks something like the Forth language, on which it is in fact loosely based. Like Forth, IOPs have a stack on which they can store and manipulate data. Also provided are 128 typed registers for general storage of data and inter-widget communication (see section The ComBlock Interface).

While it may appear at first glance that IOP represents serious engineering over-kill, let us assure you that each and every feature of IOP was added only after identifying a clear need for it. The examples given below only scratch the surface of what a more advanced, real-life terminal might desire in the way of emulation and, if you look at the `tdesc/*' examples, you'll soon see that emulating terminals such as the vt220 requires a fairly sophisticated array of tools!

IOPs can be (and usually are) imbeded in ROP or Input sequences by using the special Meta characters % and/or {} characters.

For example, take the following IOP sequence:

			%ga%1%+%2%*%pa

While this may look like a line of tty noise to the uninitiated user, it's actually quite simple. The first IOP is %ga, which means `Get Register A And Push It On The Stack.' The next IOP, %1 simply pushes a literal integer `1' onto the stack. The %+ IOP pops off two stack items (in this case, the contents of register `a' and 1) and adds them together, pushing the result onto the stack. Now %2 is pushed and %* pops it, and the earlier result from %+, multiplying them together and pushing the result. Finally, %pa 'Pops the stack into register a' and we're done.

Another way of specifying IOP sequences is to use the `%{}' delimiters, which mean 'treat all characters in the following sequence as IOP characters. The above sequence could thus also be more easily expressed as:

			%{ga 1 + 2 * pa}

The whitespace between IOP characters is not generally required (thus you could also say: %{ga1+2*pa}), but serves to make the code more readable and is encouraged.

String, character and numeric constants be pushed on the stack as `pseudo IOPS' in the following manner:

nnn
Where nnn is one or more decimal digits.
'n'
Where n is a single character or character specifier (e.g. \nnn, ^n, etc).
'n..n'
Where n..n is one or more ascii characters. As with character constants, the standard `C style' character escapes are supported.

IOP Glossary.

The following IOP characters are supported by emu:

+
Adds the top two stack items, pushing the result.
-
Subtracks the top two stack items, pushing the result.
*
Pop the top two stack items and multiply them, pushing the result.
/
Divide the top two stack items, pushing the result.
&
Bitwise AND's the top two stack items, pushing the result.
^
Pop the top two stack items, bitwise-not them, pushing the result.
|
Pop the top two stack items, bitwise-or them, pushing the result.
~
Pop the top stack item and complement it, pushing the result.
p`a'
Pop the top of stack and store in register `a'.
g`a'
Get the contents of register `a' and push on the stack.
G
Indirect get from register - pops the top of stack and uses is as a register name, pushing the value of that register in its place.
P
Indirect pop to register - pops two items from the top of stack, using the top value as a register name and the other as the value to store into it.
C
Pops an integer from the stack and uses it as an operation code in a direct call to the canvas.
c`a'
Pushes argument `a' onto the stack as a character. In a ROP this acts differently in that it actually writes the character out to the tty (and in which case the value `a' is also optional, the top stack item being popped and output when not specified).
d`a'
If in an IOP, push the argument `a' as an int. If a ROP, pop the stack and output the value as an integer to the tty (ignoring `a').
s`a'
If in an IOP, push the argument `a' as a string. If a ROP, pop the stack and output the string value to the tty (ignoring `a').
ba
Pops a string from the stack and appends it to the input stream buffer.
bs
Pops a string from the stack and replaces the input stream with it, discarding any previous contents.
@
Given the following two stack items (rightmost on top): <value> <CB_CHAR_TYPE|CB_INT_TYPE|CB_STR_TYPE|CB_ANY_TYPE> Pop them and "cast" the <value> accordingly, pushing the cast value back onto the stack.
X
Drop the top stack item.
D
Duplicate the top stack item, pushing the duplicate.
S
Swap the top two stack items.
?
Denote the start of a conditional expression, e.g.: gv ? OP_WRAP_AROUND : OP_DONT_WRAP ; Would get the contents of register `v' and, if non-zero, push the opcode for WRAP_AROUND, else DONT_WRAP.
:
Denote the `else' clause of a conditional expression.
;
Denote the `endif' part of a conditional expression (terminate the conditional expression).
=
Pop the two stack items and push a 1 or 0 if they are or are not equal to eachother (works for strings as well as integers).
>
Pop the top two stack items and push a 1 or 0 depending on whether or not the top stack item is greater than the first. Works for both strings and integers.
<
Pop the top two stack items and push a 1 or 0 depending on whether or not the top stack item is less than the first. Works for both strings and integers.
A
Pops top two stack items and pushes the `logical AND' (e.g. they're both non-zero) of the two. Generally used in conditional expressions.
!
Pops the top stack item and pushes its `logical NOT'.
O
Pops the top two stack items and pushes its `logical OR' (e.g. one of the two is non-zero).
f
Pops top of stack as a generic pointer and free()s it (dangerous! Make sure you know what you're doing).
j`a'
Jumps to a label (see IOP L), where `a' is the single character label in question.
L`a'
Declare a single-character label `a', which can be jumped directly to (see IOP j).
R
Pop a ROP code from the stack and recursively call it.
I
Pop the top of stack and use as a signal number to send the process (e.g. kill).
l
Pop the top of the stack as a string and push the length of it.
t
Pop the top of the stack as a string and set the window manager `title' hint to it (XtNtitle).
i
Pop the top of the stack as a string and set the window manager `icon label' hint to it (XtNiconName).
$
`Tokenize' a string. This is a little difficult to describe, though easy to do (see examples in the existing parsers). First the the two top stack items and popped, using the topmost as a "seperator character" and the second as a string to index it with. What is pushed back are two stack items - the chunk of the string following the index (e.g. "what's left") and the chunk leading up to the index. In such a way it is possible to write loops that take a string apart using a known seperator character. When no further instances of the seperator can be found, the untouched string is pushed followed by an empty string ("").
Tg
Get the current tty settings and push them onto the stack as an opaque (ANY) type.
Ti
Get the initial tty settings and push them onto the stack as an opaque (ANY) type. The initial settings were the ones first gotten from the tty structure when emu started up.
Td
Get the sane tty settings and push them onto the stack as an opaque (ANY) type. The sane settings are the ones defined internally by whomever ported emu to your platform as the ones to be used when a return to "sanity" is required (e.g. settings that are known to be "good").
Ts
Pop the settings from the top of stack and set the current tty settings with them.
U
Pop the top of stack as a string and send it to the emu client using the "IOP request" callback list provided for that purpose. This is used for out-of-band communications. See XpNiopRequestProc in the term widget.

Input Sequences

The basic premise behind parsing escape sequences (or input sequences) in the term widget is that for any given terminal escape sequence you want to essentially perform one or more operations on the canvas, and that it should be fairly easy to express a complete emulation as the set of all actions to be performed when a any conceivable sequence comes in.

For example, let's say we want to write a very simple little terminal emulation for a terminal that only has escape sequences for moving the cursor up, down, left right and to any arbitrary position on the screen. Let's also assume that such a terminal can ring its bell and handles newlines and carriage returns correctly. So, what might the input sequences for such a terminal look like?

First, let's define our hypothetical terminal's escape sequence set (as would typically be found in its documentation) so we can know just what it is we're trying to emulate:

        <ESC>J          - move cursor down
        <ESC>K          - move cursor up
        <ESC>H          - move cursor left
        <ESC>L          - move cursor right
        <ESC>=xy        - where x and y are ascii characters depicting
                        - a 255x255 screen space.
        ^G              - ring the bell
        ^M              - move to beginning of line
        ^J              - move to next line

Ok, so that's our goal. Now we need to describe this set of sequences to emu in a way it will understand, and in terms of the basic operations supported by its canvas. Emu expects such information in the form of an X-Toolkit resource in the following format:

Emu.term.<term name>-ops:  SEQUENCE [.. SEQUENCE ]

Where a SEQUENCE consists of:

        OP-CODE[,OP-CODE,..] <input-sequence>

A complete emulation description is then essentially nothing more than a list of SEQUENCEs, each consiting of one or more OP-CODEs and an input description.

Whenever a given input-sequence in the emulation description is seen, each OP-CODE, or Operation Code, in the list is sent to the canvas following the parsing and execution of any IOP instructions imbeded in the input-sequence itself (see below).

The OP-CODES are generally specified using macros which represent the unique operation code numbers in the canvas, which if you look in `include/xt_ops.h' you can see the complete set of. Due to the way that xrdb works, it is possible to push the emulation descriptions through the C pre-processor first for substitution and thus gain this level of canvas opcode/description independance.

Sound confusing? It is, at first, so let's just cut to the chase and show you what the description would look like (taken in the same order) in the resource database and describe it in more detail afterwards:

*term.funkyTerm-ops: \
        OP_MOVE_REL_ROW         <\EJ%1%py>	        \
        OP_MOVE_REL_ROW         <\EK%-1%py>	        \
        OP_MOVE_REL_COLUMN	<\EH%-1%px>	        \
        OP_MOVE_REL_COLUMN	<\EL%1%px>	        \
        OP_MOVE_ABS		<\E=%c%px%c%py>         \
        OP_RING_BELL		<^G>			\
        OP_MOVE_ABS_COLUMN	<%0%px\r>               \
        OP_MOVE_REL_ROW         <%1%py\n>

To truly understand this you should also read the See section The IOP Language chapter, but we can (hopefully) describe this simple example in enough detail to make it obvious enough on its own here.

Starting with the first line for handling the `<ESC>J' sequence, we see the opcode OP_MOVE_REL_ROW, which means, not surprisingly, "move the cursor to a relative position in the current row". We also see the sequence \EJ (ESCAPE-J) followed by the IOP commands `%1', which pushes the literal 1 onto stack, and `%py', which pops the stack and stores it into register y.

Looking briefly into the See section Canvas Functions section for a moment, we see that OP_MOVE_REL_ROW takes its argument in register y and so this all makes some sense - we're asking the canvas to move the cursor down one relative column position. In general, the convention is that negative arguments move the cursor left or up (depending on the operation) and positive arguments move the cursor right or down. In this context, the second sequence for ESCAPE-K makes sense, as do the next two (though we notice that the OP_MOVE_REL_COLUMN functions take their arguments in register x instead of y, this is just convention).

The OP_MOVE_ABS_COLUMN is slightly more complex in that we see the unfamiliar IOP command `%c' invoked, but this is pretty simple as well - it just matches the next character in the input stream, which is then pushed unchanged as an integer value into register x (the second character going into y).

The final 3 calls are simple indeed - ring the bell on a ^G (Control-G), move the cursor to the beginning of the current line on ^M (carriage return) and move down one line on ^J (newline). Voila! We've just created a terminal emulation!

Needless to say, actual terminals, especially fairly intelligent ones, rarely make things this easy and you've considerably more reading ahead of you if you truly wish to create one from scratch! It is suggested that you start with See section The IOP Language and then See section Canvas Functions to gain a good understanding of the underlying mechanisms.

Then take a look at the vt220 emulation in the `tdesc/' directory for real and fairly complex examples. It is possible to have an amazing degree of `execution' take place in the input-sequence alone due to the ability to imbed IOP code in it, and only a real example will suffice in showing just how far you can go with it. It helps to print the See section IOP Glossary. out and stick it up next to your terminal as well!

ROP Sequences

ROPs, or Reverse OPerations, are simply special instances of IOP code that don't correspond to any actual Input Sequence. Rather, they're used by menus, the canvas at initialization time (the reserved ROP ROP_INIT_CANVAS is always called when emu first starts up and is used to put the canvas into a known state) and by emulations that wish to output data to the tty, such as for terminal ID or "report current position" sequences.

Because ROPs are more intended for output, rather that input operations, they can in fact cause certain primitives in the IOP language to behave somewhat differently. Such differences, when they occur, are noted in the relevant portions of the See section IOP Glossary..

Rather than give many examples of ROP usage here, it will be left to the user to examine some of the existing examples since, with the possible exception of ROP_INIT_CANVAS, most uses of ROP calls are only used in special-case situations where the user is already likely to know exactly what they're doing. Suffice to say that ROPs are designed to enable the user to create arbirary IOP "routines" that can be called at any time and are not tied to the tty input state machine that governs when See section Input Sequences are invoked.

The Canvas Widget

The TermCanvas widget (referred to hereafter as the canvas) is the portion of emu that provides the actual screen output and keyboard handling for emu.

The canvas manages a virtual screen (referred to hereafter as the screen) of a configurable size, plus an area where text which scrolls off the top of the screen is stored (the save area).

The canvas also supplies a text cursor (the cursor) of configurable size and blink rate.

Text can be exchanged with other clients via the Toolkit's Selection Mechanism.

Canvas Resources

The following X-Toolkit resources are provided by the canvas

lines
The height of the canvas in terminal lines. The default is 24.
columns
The width of the canvas in terminal lines. The default is 80.
font
The font to use for normal text. The default is XtDefaultFont (fixed).
boldFont
The font to use for bold text. If not set, it will be automatically derived from font.
dWideFont
(Only present if emu is compiled with double sized fonts enabled) The font to use for double width, single height, normal text. If not set, it will be automatically derived from font.
dWHighFont
(Only present if emu is compiled with double sized fonts enabled) The font to use for double width, double height, normal text. If not set, it will be automatically derived from font.
dWideBFont
(Only present if emu is compiled with double sized fonts enabled) The font to use for double width, single height, bold text. If not set, it will be automatically derived from font.
dWHighBFont
(Only present if emu is compiled with double sized fonts enabled) The font to use for double width, double height bold text. If not set, it will be automatically derived from font.
underlineWidth
The thickness of the understrike line. The default is 1 pixel.
foreground
The text color. The default is XtDefaultForeground (black).
background
The window's background color. The default is XtDefaultBackground (white).
cursorFg
The text cursor foreground color. The default is XtDefaultForeground.
cursorBg
The text cursor background color. The default is XtDefaultBackground.
cursorHeight
The text cursor height in pixels. The maximum is the height of the font. To make the cursor as high as the cursor, specify 0. The default is 0.
cursorWidth
The cursor width in pixels. The maximum is the width of the font. To make the cursor as wide as the cursor, specify 0. The default is 0.
cursorBlinking
A boolean flag to determine whether the cursor should blink. The default is True.
blinkInterval
To specify how fast the cursor blinks, in milliseconds. The default is 500 msec.
blinkWOFocus
A boolean flag to determine whether the cursor should continue blinking when the canvas looses the input focus. The default is False.
textBlinkInterval
To specify how fast the blinking text blinks, in milliseconds. The default is 500 msec.
wrapAround
A boolean flag to determine whether text should wrap around the end of the line. The default is True.
insertMode
A boolean flag to determine whether inserted Text should be inserted or overwrite the existing characters. The default is False.
bellVolume
The volume of the bell in %. The default is 100.
defTabWidth
The default tabulator width to be used. The default is 8.
termType
The terminal type under which the canvas looks up its resources. There is no default.
setSize
A function to call when the canvas gets resized. There is no default.
output
A function to call with output generated by the canvas (e.g. through keystrokes in the canvas). There is no default.
notifyFirstMap
A function to call when the canvas is mapped for the first time. There is no default.
pointerShape
The font glyph of the cursor font to use for the mouse cursor inside the canvas window. The default is xterm
saveLines
The size of the save area in lines. The default is 64 or lines, whichever is larger.
multiClickTime
The maximum time interval between two subsequent mouse clicks that should be treated as belonging to a multi click. The default is 300 msec.
jumpScrollLines
The maximum number of lines that should be scrolled at a time if jump scrolling is enabled. The default is 10.

Canvas Actions

The canvas supports the following toolkit actions:

focus-in()
Should be called when the widget gets the input focus. The cursor shape changes to solid and optionally starts blinking.
focus-out()
Should be called when the widget loses the input focus. The cursor shape changes to outline and optionally stops blinking.
key-input([<string>])
Called without an argument it translates the KeySym that caused the action to a Latin-1 string. If Mod1 is pressed with the Key, the highest Bit of each character of the resulting string gets set to allow traditional recognition of the Meta key. The resulting string is sent to the reverse parser. With an argument key-input uses the given string instead.
select-start()
Starts the selection at the position of the mouse cursor.
select-extend()
Extends the selection to the current mouse cursor position.
select-end()
Ends the selection and transforms the selection into a string for later retrieval.
insert-selection()
Retrieve the selection and send it to the reverse parser
call-parser(<opcode>, <buffer>, [<register>, <value>], ...)
Calls the reverse parser with the specified opcode and buffer (use "" if the buffer is not needed). If register/value pairs are provided it sets the registers accordingly.
call-canvas(<opcode>, <buffer>, [<register>, <value>], ...)
Executes the specified opcode in the canvas. The buffer and any supplied registers are set accordingly.

Canvas Communications Model

The canvas communicates with the outside world (that is to say, the term widget (See section The Term Widget)) using a mechanism called a comblock. The comblock provides a general purpose communications buffer of sorts, containing space not only for characters to be displayed (the buffer) but also a set of registers for placing the parameters for various higher level requests into. See the See section Canvas Functions section for more details on which request types, and the registers they use, are supported (see also See section The ComBlock Interface).

Any number of canvas instances can be created by an application, and it is theoretically possible for a term Widget to multiplex communications between multiple instances, all the necessary frame-work is in place for such things though the default emu client assumes only one canvas and always communicates with the first one created.

Character Attributes

The following character attributes are defined in `emu/include/xt_ops.h' and can be ored together in any combination to change the way characters are displayed.

ATT_NONE
normal text - using screen.font
ATT_BOLD
bold text - using screen.boldFont
ATT_UNDERL
underlined - the underline width can be set via screen.underlineWidth
ATT_BLINK
blinking - the blink rate can be set via textBlinkInterval
ATT_REVERSE
reverse text - the background and text colors are exchanged.

If the canvas is compiled with support for double sized fonts, the following line attributes are available and can be used to change the way whole lines are displayed. Only one of the attributes may be specified at a time.

LINE_D_NORMAL
normal text height and width
LINE_D_WIDE
double wide text - all character cells are twice as wide as normal - using screen.DWideFont or screen.DWideBFont.
LINE_D_UPPER
double wide, double high text, upper half - all character cells are twice as wide as normal - using screen.DWHighFont or screen.DWHighBFont. Characters will be drawn and clipped so that the upper half of a double wide, double high font is visible.
LINE_D_LOWER
double wide, double high text, lower half - all character cells are twice as wide as normal - using screen.DWHighFont or screen.DWHighBFont. Characters will be drawn and clipped so that the lower half of a double wide, double high font is visible.

Color Handling

To allow for text color attributes, the canvas supports one of 16 foreground and background colors for each character. The mapping between logical character colors and actual X colors is done via a color index table (CIT), the entries in which can be set through the canvas function @xref{OP_SET_CIT_CELL}. The selection of logical foreground and background colors on the canvas is done through the functions @xref{OP_CHANGE_FG_COLOR} and @xref{OP_CHANGE_BG_COLOR}.

Canvas Functions

The following functions are recognized by the canvas, the constants for which are defined in `emu/include/xt_ops.h'. Data is exchanged via the given comblock (see section The ComBlock Interface).

OP_INSERT buffer = String to insert

The text in the comblock's buffer is inserted at the current cursor position with the current attributes. If insert mode is on, characters to the right, including the cursor position are shifted to the right. If line-wrap mode is on, characters beyond the right border of the screen are wrapped to the next line.

OP_MOVE_ABS x = column, y = line

Move the cursor to the absolute row and column position given in register x and y. If the relative-positioning flag is set, the start line of the scroll-region is added to y and the cursor is restricted to the scroll region. With the flag off the cursor is able to leave the scroll region.

OP_MOVE_REL x = delta column, y = delta line

Move the cursor relative to the current position by the amount of rows and columns given in register x and y. The cursor is restricted to the scroll region.

OP_MOVE_ABS_COLUMN x = column

Move the cursor to the absolute column given in register x on the current line. OP_MOVE_ABS_ROW y = line

Move the cursor to the absolute row given in register y in the current column. Rules for positioning relative to the scroll region and leaving the region apply as in OP_MOVE_ABS.

OP_MOVE_REL_COLUMN x = delta column

Move the cursor relative to the current position in the current row. The delta is given in register x.

OP_MOVE_REL_ROW y = delta line

Move the cursor relative to the current position in the current column. The delta is given in register y. The cursor is restricted to the scroll region.

OP_MOVE_REL_ROW_SCROLLED y = delta line

Move the cursor relative to the current postion in the current column. The delta is given in register y. If the cursor would leave the scroll region, the text inside the region is scrolled accordingly.

OP_INSERT_MODE (no args)

Turn insert mode on.

OP_OVERWRITE_MODE (no args)

Turn overwrite mode on - insert mode off.

OP_DELETE_CHARS a = number of characters to delete

Delete characters in the current line starting at the cursor position. The number of characters to be deleted is specified in register a. Characters to the right of the deleted ones are shifted to the left.

OP_DELETE_TO_EOL (no args)

Delete characters in the current line from the cursor position up to the end of the line.

OP_DELETE_LINES a = number of lines to delete

Deletes the number of lines specified in register a, and scrolls the lines under the deleted area up. The cursor is set to the left border of the screen. The deleted area starts at the current line. This action is restricted to the scrolling region.

OP_DELETE_TO_EOSCR (no args)

Deletes all characters after the cursor till the end of the screen.

OP_ERASE_CHARS a = number of characters to erase

Erase characters in the current line starting at the cursor position. The number of characters to be erased is specified in register a.

OP_ERASE_LINE_LEFT (no args)

Erases characters from the beginning of the current line to and including the cursor position. OP_ERASE_LINES a = number of lines to erase

Erases the number of lines specified in register a.

OP_ERASE_FROM_TOSCR (no args)

Erases characters from the top of the screen up to and including the cursor position.

OP_CLEAR_SCREEN (no args)

Clears the whole screen.

OP_INSERT_LINES a = number of lines to insert

Inserts the number of lines specified in register a at the current line. Existing lines are scrolled down accordingly. The cursor is set to the left border of the screen. This operation is restricted to the scroll region.

OP_SET_SCROLL_REGION a = start line, b = end line

Sets the scoll region to start at the line specified in register a, and end at the line specified in register b.

OP_RING_BELL (no args)

Calls 'XBell' with the volume specified in the resource bellVolume (default is 100%).

OP_HOR_TAB (no args)

Move the cursor to the next right tab in the current line. If there is no tab to the right of the cursor, the cursor is set to the right border of the screen.

OP_SET_TAB_CUR_COL (no args)

Sets a tab stop at the current column.

OP_SET_TAB_COL x = column

Sets a tab stop at the column specified in register x.

OP_SET_TABS_EQ_WIDTH a = distance

Sets up tabs with a distance specified in register a.

OP_CLEAR_TAB_CUR_COL (no args)

Clears a tab stop at the current column.

OP_CLEAR_TAB_COL x = column

Clears a tab stop at the column specified in register x.

OP_CLEAR_ALL_TABS (no args)

Clears all tabs.

OP_SET_ATTRIBUTE a = attribute(s)

Sets the attributes given in register a (more than one can be ored together).

OP_CLEAR_ATTRIBUTE b = attribute(s)

Clears the attributes given in register b (more than one can be ored together).

OP_OVERRIDE_TRANSLATIONS a = name of the translation

Retrieves the resource <term-type>-auxTrans-<name> and overrides the current translations with the resource. <name> is given in register a.

OP_CHANGE_FLUT a = name of the resource, b = offset to use

Retrieves the resource <term-type>-flut-<name> and changes the flut according to the info found there. <name> is given in register a, register b specifies the integer offset in the flut to use.

OP_CANVAS_SIZE (return) x = columns, (return) y = lines

The canvas returns its size in registers x and y.

OP_CANVAS_CURSOR_POS (return) x = column, (return) y = line

The canvas returns the current cursor position in registers x and y.

OP_CANVAS_ATTRIBS (return) a = attributes

The canvas returns the current attribues in register a (all ored together).

OP_CANVAS_SCROLL_REGION return a = start line, b = end line

Return start and end line of the scroll region in registers a and b.

OP_CANVAS_WRAP_MODE return a = boolean flag

Report in register a whether line wrap mode is on.

OP_CANVAS_REVERSE_MODE return a = boolean flag

Report in register a whether the canvas screen is in reverse video.

OP_CANVAS_CURSOR_ON return a = boolean flag

Report in register a whether the cursor is visible.

OP_CANVAS_CURSOR_BLINKING return a = boolean flag

Report in register a whether the cursor is blinking.

OP_CANVAS_CURSOR_SIZE return x = width, y = height in pixels

Return the current cursor size in registers x and y.

OP_REDRAW_SCREEN no args

Clears and redraws the entire screen.

OP_CHANGE_FONTS a = normal font, b = bold font or empty string

Changes the current fonts to the names given in registers a (normal font), and b (bold font). The fonts only get installed when they are both of the same size. If the bold font is an empty string, the canvas tries to derive a bold font from the normal one. If double sized font support is compiled into the canvas, it automatically generates names for the double sized fonts as well.

If an empty string is passed for the normal font, the canvas uses the initial one (e.g. specified in the resource database).

OP_SCROLL_SCREEN_ABSOLUTE a = save line to scroll to

Viewing the save area and the actual screen as continuous lines with line 0 being the beginning of the actual screen, numbering the save area negative upwards, this function places line -a at the top of the screen (0 thus re- presenting the normal case with only the actual screen showing).

OP_SCROLL_SCREEN_RELATIVE a = number of lines to scroll

Scrolls save area and actual screen a lines down (negative a results in scrolling upwards).

OP_CURSOR_OFF (no args)

Switches cursor off.

OP_CURSOR_ON (no args)

Switches cursor on.

OP_SET_SCREEN_SIZE (no args)

Sets the screen size to the values given in registers x and y.

OP_WRAP_AROUND (no args)

Turns line wrap around on.

OP_DONT_WRAP (no args)

Turns line wrap around off.

OP_CURSOR_POS_REL_TO_SCR_REG (no args)

Makes cursor positioning relative to the scroll region.

OP_CURSOR_POS_ABSOLUTE (no args)

Makes cursor positioning absolute.

OP_REVERSE_VIDEO (no args)

Puts the canvas in reverse video.

OP_NORMAL_VIDEO (no args)

Puts the canvas in normal video.

OP_SAVE_FLUT (no args)

Saves the current flut. Only one flut can be saved at a time, subsequent calls will overwrite the previous saved flut.

OP_RESTORE_FLUT (no args)

Restores flut to the last saved value.

OP_SET_CURSOR_BLINK a = boolean flag

Depending on the value in register a, cursor blinking gets turned on or off.

OP_SET_CURSOR_SIZE x = width, y = height in pixels

Sets the cursor size to the values in registers x and y.

OP_CHANGE_FG_COLOR a = number of the color to use

Changes the foreground color in which text is being drawn to the one specified in register a.

OP_CHANGE_BG_COLOR b = number of the color to use

Changes the background color with which text is being drawn to the one specified in register b.

OP_SET_CIT_CELL a = cell number, b = fg color, c = bg color

Sets the fore- and background colors of the CIT cell specified in register a to the values specified in registers b and c.

OP_CANVAS_DISPLAY_CELLS return a = number of color cells

Returns the number of color cells that the screen on which the canvas is running supports. This can be used to determine whether a emulation should use color or not (B/W screen vs. color screen).

OP_SET_JUMP_SCROLL a = number of lines to jump scroll

Sets the maximum number of lines the canvas should scroll at a time to the value in register a.

OP_GET_JUMP_SCROLL return a = current setting of js lines

Returns the number of lines the canvas will maximally scroll at a time in register b.

OP_SET_LINE_ATTRIBUTES a = attribute

Sets the attributes of the current line to the one given in register a. Right now it is not allowed to set more than one attribute at a time.

The ComBlock Interface

The various parts of emu use the comblock interface to exchange information and as such it's important for at least the emu programmer (or widget user) to understand something of how it works.

A comblock is a structure containing some buffer storage and a set of registers in which operands for canvas actions are passed (see section Canvas Functions). Though the comblock should really be regarded as an opaque structure and only manipulated through its accessor functions and macros (see `include/common.h'), it helps for the purpose of this document to describe its internals:

typedef struct _comblock {
     int opcode;			/* operation code */
     unsigned char buffer[BUF_SZ];	/* data buffer */
     int nbytes;			/* data buffer length */
     Register regs[CB_NREGS];		/* register array */
} ComBlock, *ComBlockPtr;

Registers are defined as:

typedef struct _reg {
     int type;				/* data type */
     Generic data;			/* data ptr */
} Register;

`Register.type' tells what type of data (int, string, float, etc) is contained in the register.

`Register.data' is a pointer to the data, or the data itself if a it can be contained in the storage provided by a pointer cell (usually 32 bits).

`ComBlock.opcode' identifies a specific operation to be performed.

`ComBlock.buffer' is used to transmit large amounts of data, generally I/O between the term and canvas widgets.

`ComBlock.nbytes' tells how many bytes are in the `buffer'.

`ComBlock.regs' contains a set of general purpose registers.

Each register can hold several types of data:

  1. CB_INT_TYPE - An integer.
  2. CB_STR_TYPE - A string.
  3. CB_CHAR_TYPE - An ASCII character.
  4. CB_ANY_TYPE - Some generic data item (user defined).

The comblock is allocated in the term widget and uses it to transfer data between the parser, reverse parser and canvas sections. It is also used by the parser and reverse parser for private storage.

The current policy is to use registers `a' to `d' and `x' to `z' to pass arguments and return values. Registers with lower case letter or numberic names should only be used for private data of the parser, upper case letters should only be used by the reverse parser. These conventions help to keep things straight.

Finally, when using the comblock, the following accessor functions/macros should be used:

reg_size
This macro should be used when allocating space for registers or when you otherwise need to know the `size' of a register.
reg_type(reg)
This macro should be used to access the type field of a register. The reg argument is a character denoting the register name.
reg_data(reg)
This macro should be used to access the data field of a register. The reg argument is a character denoting the register name.
cb_size
This macro should be used when allocating space for ComBlocks or when you otherwise need to know the `size' of a ComBlock.
cb_opcode(cb)
This macro should be used for accessing the ComBlock operation code (also known as a `requested action'). The cb argument is the ComBlock structure to be examined.
cb_buffer(cb)
This macro should be used for accessing the buffer area of the ComBlock. The cb argument is the ComBlock structure to be examined.
cb_nbytes(cb)
This macro should be used for accessing the buffer length field of the ComBlock. The cb argument is the ComBlock structure to be examined.
cb_regs(cb)
This macro should be used for accessing the register array area of the ComBlock (as one chunk). The cb argument is the ComBlock structure to be examined.
cb_reg(cb, reg)
This macro should be used for accessing an individual register in the ComBlock (though see the following 2 calls first). The cb argument is the ComBlock structure to be examined and the reg argument is the register name.
cb_reg_type(cb, reg)
This macro should be used for accessing the type field of an individual register in the ComBlock. This is a short-hand combination of cb_reg and reg_type. The cb argument is the ComBlock structure to be examined and the reg argument is the register name.
cb_reg_data(cb, reg)
This macro should be used for accessing the data field of an individual register in the ComBlock. This is a short-hand combination of cb_reg and reg_type. The cb argument is the ComBlock structure to be examined and the reg argument is the register name.

Index

a

  • ATT_BLINK
  • ATT_BOLD
  • ATT_NONE
  • ATT_REVERSE
  • ATT_UNDERL
  • auxilliary translation
  • b

  • background
  • bellVolume
  • blinkInterval
  • blinkWOFocus
  • boldFont
  • c

  • call-canvas
  • call-parser
  • canvas
  • Canvas Communications Model
  • CB_ANY_TYPE
  • CB_CHAR_TYPE
  • CB_INT_TYPE
  • CB_STR_TYPE
  • child widgets
  • client
  • columns
  • comblock
  • ComBlock Buffer
  • ComBlock Buffer Length
  • comblock communications protocol
  • Comblock Interface
  • ComBlock Operation Code
  • ComBlock Register
  • ComBlock Register Data
  • ComBlock Register Type
  • ComBlock Registers
  • ComBlock Size
  • command arguments
  • cursorBg
  • cursorBlinking
  • cursorFg
  • cursorHeight
  • cursorWidth
  • d

  • defTabWidth
  • dWHighBFont
  • dWHighFont
  • dWideBFont
  • dWideFont
  • e

  • emu
  • emu, client
  • emu, system
  • emulation
  • emulations, writing
  • f

  • FLUT
  • focus-in
  • focus-out
  • font
  • foreground
  • i

  • input parser
  • input sequence
  • input sequence list
  • input sequences
  • insert-selection
  • insertMode
  • introduction
  • IOP
  • IOP !
  • IOP $
  • IOP &
  • IOP *
  • IOP +
  • IOP -
  • IOP /
  • IOP :
  • IOP ;
  • IOP <
  • IOP =
  • IOP >
  • IOP ?
  • IOP @
  • IOP ^
  • IOP A
  • IOP ba
  • IOP bs
  • IOP C
  • IOP c
  • IOP D
  • IOP d
  • IOP f
  • IOP G
  • IOP g
  • IOP Glossary
  • IOP I
  • IOP i
  • IOP j
  • IOP L
  • IOP l
  • IOP Language
  • IOP O
  • IOP Overview
  • IOP P
  • IOP p
  • IOP R
  • IOP request procedure
  • IOP S
  • IOP s
  • IOP t
  • IOP Td
  • IOP Tg
  • IOP Ti
  • IOP Ts
  • IOP U
  • IOP X
  • IOP |
  • IOP ~
  • j

  • jumpScrollLines
  • k

  • key-input
  • l

  • layout procedure
  • LINE_D_LOWER
  • LINE_D_NORMAL
  • LINE_D_UPPER
  • LINE_D_WIDE
  • lines
  • login shell
  • m

  • managing children
  • menu configuration
  • menu configuration parameters
  • menu item actions
  • menu item configuration parameters
  • menu item line separators
  • menu names
  • menu ROPs
  • menu translations
  • menus
  • multiClickTime
  • n

  • new architectures
  • notifyFirstMap
  • o

  • opcode
  • operation code
  • output
  • output parser
  • p

  • parser
  • pointerShape
  • process death handler
  • process_init
  • process_wait
  • r

  • read size
  • Register Data
  • Register Size
  • Register Type
  • resources
  • reverse operations
  • ROP
  • rops
  • s

  • saveLines
  • select-end
  • select-extend
  • select-start
  • sequence list
  • setSize
  • shell command
  • structure
  • t

  • term
  • term widget
  • term widget resources
  • termCanvas widget
  • terminal type
  • terms
  • termType
  • termWidget
  • textBlinkInterval
  • The ComBlock
  • tty_add_utmp
  • tty_find_pty
  • tty_get_sane
  • tty_get_values
  • tty_remove_utmp
  • tty_set_size
  • tty_set_values
  • u

  • underlineWidth
  • utmp
  • utmp inhibit
  • w

  • wrapAround
  • c

  • cb_buffer
  • cb_nbytes
  • cb_opcode
  • cb_reg
  • cb_reg_data
  • cb_reg_type
  • cb_regs
  • cb_size
  • r

  • reg_data
  • reg_size
  • reg_type
  • References

    [1] McCormack, Joel. Asente, Paul and Swick, Ralph R. X Toolkit Intrinsics - C Language Interface Massachusetts Institute of Technology, 1985, 1986, 1987, 1988

    [2] Swick, Ralph R. and Weissman, Terry. X Toolkit Athena Widgets - C Language Interface Massachusetts Institute of Technology, 1985, 1986, 1987, 1988