22. The TV Display

The principal output device of the Lisp Machine is the TV display system. It is used in conjunction with the keyboard as an interactive terminal, and it can output printed text or graphics. This chapter describes the Lisp functions used to manipulate the TV.

22.1 The Hardware
The Lisp machine display system is a raster-scan, bit-map system. This means that the screen is divided up rectangularly into points. The video signal that enters the TV comes from a memory which has one bit for every point on the screen. This memory is directly accessible to the program, allowing extremely flexible graphics. The coordinate system normally used has the origin (0,0) at the top left corner of the screen. X increases to the right, and Y increases downward. There are currently two TV controllers in use. The 16-bit controller, which is going away, generates industry-standard composite video, allowing a screen size of 454. lines from top to bottom with 576. points on each line. The newer, 32-bit controller, provides various options. With the CPT monitor it generates a black-and-white display of 896. lines with 768. points on each line. Other monitors can also be supported. One thing to be aware of is that the same fonts cannot be used with both controllers, because the 16-bit controller has its bits reversed. It is possible to have a display in which there is more than one bit per visible point, allowing gray-scale or color. The set of all bits which contribute to a single point on the screen is called a pixel . (The point on the screen itself is also sometimes called a pixel.) Some of the software operates in terms of pixels. Pixels are implemented in an entirely different way in the two controllers. This document doesn't really discuss them yet. Because of all these options, the Lisp machine system includes screen objects . A screen object contains all the attributes of a particular TV controller and display monitor.
22.2 Screens

There is a type of Lisp object called a screen , which is the internal representation for a physical display with someone looking at it. Both microcode and Lisp functions look at screen objects. A screen is a structure which contains the following fields: 3 500
screen-nameAn arbitrary character string which appears in the printed representation of the screen-object.
screen-heightThe total height of the screen in bits (raster lines, pixels).
screen-widthThe total width of the screen in bits (pixels).
screen-x1, screen-x2, screen-y1, screen-y2
The coordinates of a rectangle which is the portion of the screen in which allocation of tvobs may occur. Usually this is the whole screen, but if there is a who-line it is excluded. There could be other reserved areas of the screen.
screen-plane-mask
0 if this screen is on a 32-bit controller. If it is on a 16-bit controller, one of the bits in this mask is on corresponding to the memory "plane" which contains this screen. (For instance, for plane 0 the value of this field would be 1.) Having more than one bit on in this mask is not really supported.
screen-bits-per-pixel
The number of bits in a pixel.
screen-property-list
This is a property list for special features of this screen. Access this via forms such as (get (locf (screen-property-list s)) ':video) The following property names are standard.
:videoThe kind of video this screen uses. One of :black-and-white , :gray , :color .
:controllerThe only controller that exists currently is :simple .
:monitorThe brand-name of the attached monitor, e.g. :cpt , :barco , etc.
:sidewaysIf the value of this property is non-nil , the monitor is standing on its left side. The TV routines know how to draw characters on such a screen, given a rotated font, so that the text comes out in the normal orientation.
screen-font-alist
An a-list that associates from font names to font objects. This is not really used yet.
screen-default-font
The font to be used by default on this screen.
screen-bufferThe address in virtual memory of the video buffer for this screen.
screen-locations-per-line
The number of locations (containing 16 or 32 bits depending on the controller) of the video buffer for a scan line.
screen-buffer-pixel-array
A two-dimensional array of positive integers, which are pixel values. The first subscript is the X coordinate and the second subscript is the Y coordinate.
screen-buffer-halfword-array
A one-dimensional array of 16-bit words of video buffer. This is provided to allow direct manipulation of the video buffer, bypassing the usual microcode primitives. Note that on a 16-bit controller, the bits in these words are reversed.
screen-control-address
The address, suitable for use with %xbus-read , of the hardware control registers for this screen.

tv-default-screen Variable
The value of tv-default-screen is the "normal" screen where text display happens. Various functions that take a screen as an optional argument default to this.
tv-define-screen name &rest options
Creates and returns a screen whose name is name (a string) and whose attributes are controlled by the options. These attributes has better correspond to an existing hardware screen. options is alternating keywords and arguments to those keywords. The following keywords are accepted:
:plane-maskThe value of the screen-plane-mask field. Defaults to 0, for screens on the 32-bit TV controller. (This is obsolete.)
:heightThe value of the screen-height field. Required argument.
:widthThe value of the screen-width field. Required argument.
:x1The value of the screen-x1 field. Defaults to 0.
:y1The value of the screen-y1 field. Defaults to 0.
:x2The value of the screen-x2 field. Defaults to the width.
:y2The value of the screen-y2 field. Defaults to the height, unless the :who-line-p option is specified, in which case one line of space is left at the bottom of the screen for the who-line.
:who-line-pt to leave space for a who-line, nil to make the entire screen available for TVOB allocation. Defaults to t .
:bufferA fixnum which is the address of the video buffer containing the bits for this screen. Required argument.
:control-address
A fixnum which goes into the screen-control-address field.
:locations-per-line
The value of the screen-locations-per-line field. Defaults from the width, the bits per pixel, and the controller type.
:bits-per-pixel
The value of the screen-bits-per-pixel field. Defaults to 1.
:propertiesThe value of the screen-attributes field. Defaults to nil .
:font-alistThe value of the screen-font-alist field. Defaults to nil .
:default-fontThe value of the screen-default-font field. Defaults according to the type of controller used.
22.3 Simple Bit Manipulation
Some arrays of numbers exist which allow access to the TV memory. These are regular Lisp arrays and all array operations work on them, but they are set up so that their data storage is actually in the TV memory. These arrays are normally found in fields of a screen object. screen-buffer-pixel-array is a two-dimensional array. Array element (x ,y ) corresponds to the point whose coordinates are x and y : if the array element is 0, the point is illuminated, and if the element is 1, the point is dark. (The opposite is true when the TV is in reverse-video mode; see below). The elements of this array are single bits in the usual case, but they can be small positive numbers in the case of gray-scale or color screens. In the case of a 16-bit TV, this array accesses whichever plane is currently selected. screen-buffer-halfword-array is a one-dimensional array of 16-bit elements, whose exact interpretation depends on the type of TV screen. Certain programs use this to access the TV buffer memory. It is possible to do anything to a TV screen, albeit slowly, using the above two arrays. However, for efficiency several microcode primitives are provided which perform certain common operations at much higher speed, typically close to the maximum speed of the memory. Most programs use these microcode primitives or the higher-level functions built on them rather than accessing the TV buffer memory directly. The remainder of this chapter describes these facilities.
22.4 Fonts

A font is a set of related characters. It is represented by an array (of type art-1b ) which contains the bit patterns used to actually draw the characters. The leader of that array contains other required information such as character widths, height, bookkeeping information, etc. There is a microcode entry for drawing characters, which understands the structure of fonts. It exists so as to make character drawing as fast as possible. User functions do not call the microcode entry directly, as it is rather kludgey, and handles only the easy cases. Instead the TV routines do all the necessary calls. A font usually contains 128 characters. The widths may be variable, but the height is always fixed (characters need not actually have ink all the way from the top to the bottom of the height, but the distance between lines is fixed for each font). There are special provisions for fixed-width fonts to save space and time. There is a thing called the baseline, which is a certain vertical position in each character. For example, the baseline touches the bottom of the legs of a capital A, and passes through the stem of a lower-case p. When several fonts are used together, all the baselines are made to line up. The way characters are drawn is a little strange (it is done this way for speed). There is a thing called a raster element , which is a row of 1-bits and 0-bits. A character is drawn by taking a column of raster elements, (making a rectangle) and OR'ing this into the bit-map memory. A raster element can be at most 16 bits wide for hardware reasons, so for large characters it may take several side-by-side columns to draw the character. The font is stored with several raster elements packed into each 32-bit word. The width of a raster element is chosen to give maximum packing, and depends on the font. The reason for the existence of raster elements is to decrease the number of memory cycles by processing several bits at a time. The structure of the array leader of a font is defined by defstruct macros. Here we list the element names and what they are for. This structure is not guaranteed not to be changed in the future, however the macros are automatically made available to user programs. 3
font-nameA symbol, in the fonts package, whose value is this font. This symbol also appears in the printed representation.
font-char-height
Height of the characters in this font (with a VSP of 0, this is how far the lines would be.)
font-char-width
Width of the characters if this is a fixed-width font, i.e. how far successive characters are drawn. Otherwise contains the width of "space".
font-raster-height
Number of raster lines of "ink" in a character (often the same as font-char-height ).
font-raster-width
Width of a raster element.
font-rasters-per-word
Number of elements packed per word (used when accessing the font.)
font-words-per-char
Number of words needed to hold one column of elements.
font-baselineNumber of raster lines down from the top of the character cell of the position to align.
font-char-width-table
nil for fixed width fonts. Otherwise, contains the 128-long array of character widths.
font-left-kern-table
nil for non-kerned fonts. Otherwise, contains the 128-long array of left-kerns. This is the amount (positive or negative) to back up the X position before drawing the character.
font-indexing-table
nil for narrow fonts which only take one column of raster elements to draw. Otherwise, contains a 129-long array which determines what columns of the font to draw for that character as follows: for character i , draw columns indexingtable (i ) through indexingtable (i +1)-1 inclusive. Note that 2 of the above 3 arrays only contain small positive numbers, so they are usually of type art-16b or art-8b to save space.
font-next-plane
nil usually. For multi-plane fonts, contains the font for the next higher plane. This field is obsolete and no longer supported.
font-blinker-width
Default width for blinkers.
font-blinker-height
Default height for blinkers.
The data part of a font array contains an integral number of words per character (per column in the case of wide characters that need an indexing table). Each word contains an integral number of raster elements, left adjusted and processed from left to right. All 32 bits of each element in this array are used. For easiest processing by Lisp programs, it should be of art-1b array type. The exact format of the data part of a font array depends on whether the font is intended to be used with a 16-bit TV controller or a 32-bit controller. In the 32-bit case, the bits are displayed from right to left. The maximum width of a raster element is 32. bits; use of the font-indexing-table is required if characters are wider than this. If there is more than one raster element per word, the elements are displayed from right to left. In the 16-bit case, the bits and raster elements are displayed from left to right, and the maximum width of a raster element is 16. bits.

22.5 TVOBs
[Here explain what TVOBs are, how they differ from pieces of paper, what you use them for, and point to JOBSYS chapter.] Until this is written, see this link.
22.6 Pieces of Paper

A piece of paper is something on which you draw characters. It is displayed on a certain rectangular portion of a screen. It remembers what fonts to use, where to display the next character, how to arrange margins and spacing, and what to do when certain special conditions arise. It optionally displays a blinking cursor (or several of them). All character-drawing in the Lisp Machine system is accomplished with pieces of paper. One thing to note is that pieces of paper do not remember the characters you draw on them, except by making dots on the TV screen. This means that if one piece of paper overlays another, or if the screen is cleared, the contents of the first is lost. A higher-level facility (e.g. editor buffers) must be used if the characters are to be remembered. The abbreviation "pc ppr" is often used for "piece of paper". A piece of paper is represented as an ordinary array whose elements are named by the following accessor macros. These are automatically available to the user, but should not normally be used as they are not guaranteed to remain unchanged, and often contain internal values which are made into more palatable form by the interface functions. All screen coordinates in this structure are absolute screen coordinates; the user interface functions convert these into coordinates which are relative to the margins of the piece of paper. 3
pc-ppr-nameAn arbitrary string which appears in the printed representation.
pc-ppr-screenThe screen-object representing the screen on which this pc ppr displays.
pc-ppr-topThe raster line number of the topmost screen line in this pc ppr.
pc-ppr-top-margin
The raster line number of the topmost screen line used to draw characters. The difference between pc-ppr-top-margin and pc-ppr-top is the size of the top margin.
pc-ppr-bottomThe raster line number of the screen line just below this pc ppr.
pc-ppr-bottom-margin
The raster line number of the screen line just below the bottommost point on which a character can be drawn. The difference between pc-ppr-bottom and pc-ppr-bottom-margin is the size of the bottom margin.
pc-ppr-bottom-limit
The lowest raster line to which the cursor may be positioned. This is a suitable value to prevent excursion below the bottom margin.
pc-ppr-leftThe bit number of the leftmost bit in the pc ppr's screen area.
pc-ppr-left-margin
The bit number of the leftmost bit used to draw characters. The difference between pc-ppr-left-margin and pc-ppr-left is the left margin.
pc-ppr-rightThe bit number of the bit just to the right of the pc ppr's screen area.
pc-ppr-right-margin
The bit number of the bit just to the right of the portion of the pc ppr in which characters may be drawn. The difference between pc-ppr-right and pc-ppr-right-margin is the right margin.
pc-ppr-right-limit
The rightmost bit position to which the cursor may be positioned. This is set to a suitable value to prevent excursion past the right margin.
pc-ppr-current-x
The X position of the left edge of the next character to be drawn, i.e. the X coordinate of the cursor position.
pc-ppr-current-y
The Y position of the top edge of the next character to be drawn, i.e. the Y coordinate of the cursor position.
pc-ppr-flagsA fixnum containing various bit flags, as follows:
pc-ppr-sideways-p
0 normally. 1 if the pc ppr is on a sideways screen, so the X and Y coordinates should be interchanged before calling the microcode.
pc-ppr-exceptions
Non-zero if any special conditions which prevent typeout are active. The conditions are:
pc-ppr-end-line-flag
1 if pc-ppr-current-x is greater than pc-ppr-right-limit . The default response to this is to advance to the next line.
pc-ppr-end-page-flag
1 if pc-ppr-current-y is greater than pc-ppr-bottom-limit . The default response to this is to return to the top of the pc ppr.
pc-ppr-more-flag
1 if "more-processing" must happen before the next character can be output. The default response to this is to display "**MORE**" and await keyboard input.
pc-ppr-output-hold-flag
1 if some higher-level function has decided that output is not to be allowed on this pc ppr. For example, its region of the screen might be in use for something else. When this is seen a function specified when the pc ppr was created is called.
(exceptions)
(flags)
pc-ppr-more-vpos
Y passing here triggers "more processing" by setting pc-ppr-more-flag . Add 100000 to this field to delay until after screen wraparound. Store nil here to inhibit more processing.
pc-ppr-baseline
The number of raster lines from the top of the character cell (pc-ppr-current-y ) to the baseline.
pc-ppr-font-map
An array of fonts. Normally a font-change command specifies a code number, which is looked up in this array to find what font to actually use. Font 0 is the "principal" font. The array is usually 26. long.
pc-ppr-current-font
The font which is currently selected.
pc-ppr-baseline-adj
Y offset for current font to align baseline. This is the difference between the pc-ppr-baseline and the font's baseline.
pc-ppr-line-height
The number of raster lines per character line.
pc-ppr-char-width
A character width which is just used for old-style space/backspace/tab operations and for blinkers.
pc-ppr-char-aluf
ALU function for drawing characters. The default is the value of tv-alu-ior .
pc-ppr-erase-aluf
ALU function for erasing characters/lines/whole pc ppr. The default is the value of tv-alu-andca .
pc-ppr-blinker-list
(Possibly null) list of blinkers on this pc ppr.
pc-ppr-end-line-fcn
Function called when typeout is attempted with pc-ppr-end-line-flag set. The default is to wrap around to the next line.
pc-ppr-end-screen-fcn
Function called when typeout is attempted with pc-ppr-end-page-flag set. The default is to wrap around to the top margin.
pc-ppr-output-hold-fcn
Function called when typeout is attempted with pc-ppr-output-hold-flag set. The default is to wait for the flag to be cleared by some other process.
pc-ppr-more-fcn
Function called when typeout is attempted with pc-ppr-more-flag set. The default is to type **MORE** and await typein.
(pc ppr)

22.6.1 Simple Typeout
tv-tyo pc-ppr char
Draws a printing character, or executes a special format character. The character is drawn at the current cursor position, in the current font, and the cursor position is shifted to the right by the width of the character. The following format effectors are recognized:
200Null. Nothing happens.
210Backspace. The cursor is moved left the width of a space. At the beginning of a line it sticks.
211Tab. The cursor is moved right to the next multiple of 8 times the width of a space.
215Carriage return. The cursor is advanced to the beginning of the next line, and that line is erased. More-processing and screen wrap-around may be triggered.
240-247Font change. The low 3 bits are the font number.
Other non-printing characters are displayed as their name enclosed in a box. These displays are quite wide and currently don't bother to respect the right margin.
tv-beep pc-ppr char
This function is used to attract the user's attention. It flashes the screen and beeps the beeper. Doesn't really have that much to do with TVs.
tv-beep Variable
If the value of tv-beep is non-nil , the tv-beep function doesn't flash the screen, it only sounds a beep. The initial value is nil .
si:tv-move-bitpos pc-ppr delta-x delta-y
Move current X, current Y on piece of paper, keeping inside boundaries. This function is called from many others. It is the central place to keep track of edges, automatic wrap-around, **MORE** processing, etc. It will set the pc-ppr-exceptions flags as necessary.
si:tv-exception pc-ppr
This function is called by various TV functions when they encounter a pc-ppr-exceptions flag which they care about (for example, tv-crlf does not care about pc-ppr-end-line-flag ). The appropriate function (stored in the pc ppr) is called. It is up to that function to correct the condition and clear the exception flag.
If you want to supply your own exception-handling function for a piece of paper, you would be well-advised to read the corresponding system default function first. They need to do non-obvious things in some cases.
si:tv-end-line-default pc-ppr
This is the default end-of-line function, called if an attempt is made to display a character when the cursor is off the end of a line. It essentially just does a crlf.
si:tv-end-screen-default pc-ppr
This is the default end-of-screen function, called when an attempt is made to display a character when the cursor is off the bottom of the pc ppr. It wraps around to the top of the pc ppr. Note that more-processing is separate from and unrelated to end-of-screen processing.
si:tv-more-default pc-ppr
This is the default more processor. It types out **MORE**, waits for input, and decides where the next "more" should happen.
tv-note-input pc-ppr
The purpose of tv-note-input is to prevent "more"s from happening during normal interactive usage, since typeout is frequently pausing for user input anyway, and presumably the user is keeping up in his reading. This function is called by the keyboard handler when a process hangs waiting for input. tv-note-input arranges (on each active pc ppr) for a more not to happen until the current line is reached again; except, if this line is far from the bottom, we prefer to more at the bottom before wrapping around. This makes moreing usually happen at the bottom.
22.6.2 Cursor Motion
Note that the "cursor" is the x,y position where the top-left corner of the next character printed will be placed. (This is not strictly true because there is base-line adjustment and kerning.) The cursor doesn't necessarily have a corresponding blinker; this is under the control of the user program. Many of these functions are not used by real Lisp Machine code, but are present for completeness and to aid compatibility with ITS I/O. On the other hand, some are heavily used.
tv-home pc-ppr
Home up to the top-left corner. Usually you then want to do a tv-clear-eol .
tv-home-down pc-ppr
Home down the cursor to the bottom-left corner (the beginning of the last line in the pc ppr).
tv-crlf pc-ppr
Advance to the beginning of the next line, and erase its previous contents.
tv-space pc-ppr
Space forward.
tv-backspace pc-ppr
Space backward. Not too useful with variable-width fonts.
tv-tab pc-ppr
Tab. Spaces forward to the next multiple of 8 times the width of space.
tv-set-font pc-ppr font
This is the common internal routine for changing what font a piece of paper is to print with. It does some bookkeeping, such as adjusting the baseline. It is OK to set the font to one which is not in the font map, however this won't change the line-spacing, which is initially set up according to the tallest font in the font map.
tv-set-cursorpos pc-ppr x y
Sets the "cursor" position of the piece of paper in raster units (not character units). x and y are relative to the margins of the pc ppr.
tv-read-cursorpos pc-ppr
Returns two values, the X and Y coordinates of the cursor. These are relative to the margins of the pc ppr.
22.6.3 Erasing, etc.
tv-clear-char pc-ppr
Clear the current character position. In a variable-width font, the width of space is used, which isn't likely to be the right thing.
tv-clear-eol pc-ppr
Clear from current position to end of line.
tv-clear-eof pc-ppr
Clear from current position to end of piece of paper.
tv-clear-pc-ppr pc-ppr
Clear whole piece of paper.
tv-clear-pc-ppr-except-margins pc-ppr
Clear all of pc-ppr except the margins, which are unaffected. This is useful if the margins contain decorative graphics 'c What Fredkin calls "decorative computer art" such as outlines.
tv-clear-screen &optional screen
Clears the entire screen, and tells the who-line it has been clobbered. screen defaults to tv-default-screen .
tv-delete-char pc-ppr &optional (char-count 1)
Deletes the specified number of character positions immediately to the right of the cursor, on the current line. The remainder of the line slides to the left, and blank space slides in from the right margin.
tv-insert-char pc-ppr &optional (char-count 1)
Inserts the specified number of blank character positions immediately to the right of the cursor, on the current line. The remainder of the line slides to the right, and anything that goes off the right margin is lost.
tv-delete-line pc-ppr &optional (line-count 1)
Deletes the specified number of lines immediately at and below the cursor. The remaining lines of the piece of paper slide up, and blank spaces slides in from the bottom margin.
tv-insert-line pc-ppr &optional (line-count 1)
Inserts the specified number of blank lines at the cursor. The remaining lines of the piece of paper slide down, and anything that goes off the bottom margin is lost.
tv-black-on-white &optional screen
Makes the hardware present the screen as black characters on a white background. (Presently, the screen argument can also be a plane-mask.)
tv-white-on-black &optional screen
Makes the hardware present the screen as white characters on a black background. (Presently, the screen argument can also be a plane-mask.)
tv-complement-bow-mode &optional screen
Makes the hardware present the screen in the reverse of its current mode. (Presently, the screen argument can also be a plane-mask.)
tv-white-on-black-state &optional screen
Returns :white if the screen is currently presented as white-on-black, or :black if it is currently presented as black-on-white. The screen argument can also be a plane-mask. If more than one bit is on in the plane-mask, and not all the planes are in the same state, :both is returned.
22.6.4 String Typeout
tv-string-out pc-ppr string &optional (start 0) end
Print a string onto a piece of paper. Optional starting and ending indices may be supplied; if unsupplied, the whole string is printed. This is basically just iterated tv-tyo , except in the case of simple fonts it runs much faster by removing a lot of overhead from the inner loop.
tv-line-out pc-ppr string &optional (start 0) end
This variant of tv-string-out is used by the editor's display routines to output one line. The argument is a string of either 8-bit or 16-bit characters (usually this is an EINE "line", but the leader is not touched except for the fill pointer.) The high 8 bits (%%ch-font ) of each character are the index into the font map for the font in which that character is to be displayed. 8-bit chars use font 0. There are optional starting and ending indices; if these are omitted the whole string is specified. If during printing the cursor runs off the end of the line, typeout stops and the index of the next character to be output is returned. At this point, the pc-ppr-end-line-flag is 1 and the cursor is off the end of the line. If the whole string is successfully output, nil is returned, and the pc ppr is pointing somewhere in the middle of the line.
tv-string-length pc-ppr string &optional (start 0) end stop-x
Compute the display-length of a string, which is the sum of the widths of the printing characters in it. Newline characters are ignored. Tab characters act as if the string starts at the left margin. pc-ppr is used mainly for its font map. start and end allow you to process a substring. stop-x , if non-nil , is a tv-length at which to stop. The index in the string of the character after the one which exceeded the stop-x is returned as the second value. The first returned value is the x -position reached, i.e. the tv-length of the string. The second returned value is the next index in the string, which is end if stop-x was not supplied. Contrast tv-compute-motion , which does a two-dimensional computation taking line-length into account.
tv-compute-motion pc-ppr x y string &optional (start 0) end (cr-at-end-p nil)
.defunc (stop-x 0) stop-y Compute the motion that would be caused by outputting a string. This is used by the editor to aid in planning its display, to compute indentations with variable width fonts, to position the cursor on the current character, etc. Note that this does not use the "case shift" flavor of font hacking. Instead, it uses the 16-bit-character flavor that the editor uses. This means that if you give it an ordinary 8-bit string it will be assumed to be all in font 0. The arguments are: the piece of paper, the X and Y position to start at (nil s here use the current position of the pc ppr), the string, and optionally the starting and ending indices, a flag saying to fake a crlf at the end of the string, and two additional arguments which are the X and Y to stop at; if not given these default to the end of the screen. Returns 3 values: final-X, final-Y, and an indication of how far down the string it got. This is nil if the whole string (including the fake carriage return, if any) was processed without reaching the stopping point, or the index of the next character to be processed when the stopping point was reached, or t if the stopping point was reached after the fake carriage return.
tv-char-width pc-ppr char
Returns the width of the character, if displayed in the font current in the pc-ppr. The width of backspace is negative, the width of tab depends on the pc ppr's cursor position, and the width of carriage return is zero.
22.6.5 More Processing
More processing is a flow control mechanism for output to the user. Lisp machine more processing is similar to more processing in ITS. The problem that more processing solves is that displayed output tends to appear faster than the user can read it. The solution is to stop just before output which has not been read yet is wiped out, and display "**MORE**". The user then reads the whole screen and hits space to allow the machine to continue output. More processing normally occurs one line above where the cursor was when the machine last waited for user input; however, it tries to do an extra **MORE** at the bottom of the pc ppr, so as to get into a phase where the **MORE** always appears at the bottom, which is more aesthetic.
22.6.6 ALU Functions
Some TV operations take an argument called an ALU Function , which specifies how data being stored into the TV memory is to be combined with data already present. The ALU function is OR'ed directly into a microinstruction, so specifying a value other than one of those listed below may produce unexpected disasters. The following special variables have numeric values which are useful ALU functions.
tv-alu-ior Variable
Inclusive-OR. Storing a 1 turns on the corresponding bit, otherwise the bit in TV memory is left unchanged.
tv-alu-xor Variable
Exclusive-OR. Storing a 1 complements the corresponding bit, otherwise the bit in TV memory is left unchanged.
tv-alu-andca Variable
AND-with-complement. Storing a 1 turns off the corresponding bit, otherwise the bit in TV memory is left unchanged.
tv-alu-seta Variable
Bits are simply stored, replacing the previous contents. With most functions, this is not useful since it clobbers unrelated bits in the same word as the bits being operated on. However, it is useful for bitblt.
22.6.7 Blinkers
A blinker is an attention-getting mark on the screen. Often, but not always, it will blink. The most common type is a character-sized rectangle which blinks twice a second, but several other types exist, and it is easy for the user to define new ones. Often a piece of paper will have an associated blinker which shows where the next character will be drawn. A blinker can be on top of a character, and the character will still be visible. This done by XORing the blinker into the TV memory. Synchronization between pieces of paper and blinkers is provided so that when characters are being drawn on the screen, blinkers are turned off to prevent the picture from being messed up. (This is called "opening" a piece of paper, and should be invisible to the user.) A blinker is an array, described as follows: 3
tv-blinker-x-pos
X position of the left edge of the blinker. nil if the blinker should follow the tv-blinker-pc-ppr 's current X and Y.
tv-blinker-y-pos
Y position of the top edge of the blinker.
tv-blinker-pc-ppr
Pc ppr the blinker is associated with. nil for a roving blinker , which can go anywhere.
tv-blinker-screen
The screen on which the blinker is displayed.
tv-blinker-visibility
nil invisible, t visible, blink blinking.
tv-blinker-half-period
Time interval in 60ths of a second between changes of the blinker.
tv-blinker-phase
nil means not visible, anything else means visible in some form. A complementing blinker has only two phases, nil and t , but provision is made for blinkers which go through an elaborate sequence of states.
tv-blinker-time-until-blink
Time interval in 60ths of a second until the next change. The scheduler decrements this 60 times a second if the tv-blinker-visibility is blink . If it reaches zero, the blinker is blinked. If this field is nil , the blinker is not to be looked at by the scheduler.
tv-blinker-function
The function to call to blink the blinker. The next two fields are for its use. The arguments to the function are the blinker, an operation code, the tv-blinker-x-pos , and the tv-blinker-y-pos . The operation codes are nil to make the blinker invisible, t to make it visible, and blink to blink it. When this function is called, interrupts have been disallowed and the proper screen has been selected. For additional conventions, read the function tv-blink .
tv-blinker-width
Width in bits of area to complement if tv-rectangular-blinker . For other blinker types, miscellaneous data.
tv-blinker-height
Height in raster lines of area to complement if tv-rectangular-blinker . For other blinker types, miscellaneous data.
tv-blinker-sideways-p
t => interchange X and Y before calling microcode.
tv-set-blinker-cursorpos blinker x y
Set the cursor position of a blinker. If blinker is a roving blinker, x and y are absolute coordinates. Otherwise, they are relative to the margins of blinker 's piece of paper. If this blinker was following the pc ppr's cursor, it won't any more.
tv-read-blinker-cursorpos blinker
Read the cursor position of a blinker, returning two values, X and Y. If the blinker is not roving, these are relative to the margins of its piece of paper.
tv-set-blinker-visibility blinker type
Carefully alters the visibility of a blinker. type may be nil (off), t (on), or blink .
tv-set-blinker-function blinker function &optional arg1 arg2
Carefully alters the function which implements a blinker. arg1 and arg2 , if supplied, change tv-blinker-height and tv-blinker-width , which are really just general arguments to the function.
tv-set-blinker-size blinker width height
Carefully changes the size of a blinker, consulting the function which implements it if that function has a tv-set-blinker-size-function property.
22.7 Graphics
tv-draw-line x1 y1 x2 y2 alu screen
Draws a straight line between the points (x1 ,y1 ) and (x2 ,y2 ), merging the line into the existing contents of the screen with the specified alu function. This is a fast micro-coded function.
bitblt alu width height from-array from-x from-y to-array to-x to-y
This function moves a portion of one two-dimensional numeric array into a portion of another, merging them under the control of a specified alu function. It has several applications, including shifting portions of the TV screen around (use the screen-buffer-pixel-array ), saving and restoring portions of the TV screen, writing half-tone and stipple patterns into the TV screen, and general array-moving. bitblt operates on a rectangular region of to-array which starts at the coordinates (to-x ,to-y ) and has extent (abs width) in the X direction and (abs height) in the Y direction. An error occurs if this region does not fit within the bounds of to-array . Note that the coordinates and the height and width are in terms of array elements, not bits, although the actual operation is done bitwise. from-array needn't be as big as the specified region; conceptually, bitblt replicates from-array a sufficiently-large number of times in both X and Y , then picks out a rectangular region containing the same number of bits as the destination region, starting at the coordinates (from-x ,from-y ). bitblt combines these two regions under control of alu . The "A" operand is the from-array , thus an alu function of tv-alu-seta copies the from-array , ignoring the previous contents of the selected region of the to-array . The specified X and Y coordinates are always the upper-left corner (minimum coordinate values) of the selected region. bitblt normally works in a left-to-right and top-to-bottom order, that is with increasing coordinate values. When using overlapping from and to arrays, for instance when shifting a portion of the TV screen slightly, it may be necessary to work in one of the other three possible orders. This is done using the sign of the width and height arguments. If width is negative, decreasing X coordinates are used, and if height is negative, decreasing Y coordinates are used. For the sake of efficiency, bitblt requires that the from-array and to-array have word-aligned rows. This means that the first dimension of these arrays must be a multiple of 32. divided by the number of bits per array-element. All TV screen arrays are forced by hardware to satisfy this criterion anyway.
22.8 The Who Line
The who line is a line at the bottom of the screen which contains information on what the program is currently doing. The who line has its own pc ppr and is updated whenever the software goes into an I/O wait. In addition, there are two short line segments (called run lights ) at the bottom of the screen which are controlled by the microcode and by the scheduler. The one on the right lights up when the machine is running (not waiting and not paging), and the one on the left lights up when the disk is running (paging).
tv-who-line-update &optional state
This function updates all fields of the who-line which have changed. It is called from various functions which change the "state of the machine" as perceived by the user. The optional argument, state , is a string to be displayed in the state field. If state is not specified, the value of tv-who-line-run-state is used, which is usually "RUN" .
tv-who-line-list Variable
The value of tv-who-line-list is a list of who-line fields. Each field is a list; the first four elements of the list constitute a structure containing the following components: 3
tv-who-line-item-function
A function to call, given the field as its argument. The function is supposed to update the field of the who-line if it has changed. The list elements of the field after the first four are for the use of this function.
tv-who-line-item-state
If nil , the who-line has been clobbered (e.g. by clearing of the screen) and the field must be updated. Otherwise, this is used by the function in an unspecified way to remember its previous state.
tv-who-line-item-left
The bit position of the left edge of the portion of the who-line containing this field.
tv-who-line-item-right
The bit position (+1) of the right edge of the portion of the who-line containing this field.
The initial tv-who-line-list is set up to display the time, the name of the person logged-on to the machine, the current package, the "state" of a certain selected process, and name and position of the current input file.
tv-who-line-prepare-field field
This is called by tv-who-line-item-function s in preparation for redisplay of a who-line field. The portion of the screen on which the field displays is erased and the tv-who-line-pc-ppr 's cursor is set to the beginning of the field.
tv-who-line-string field
This is a useful function to put into a who-line field. It displays the string which is the value of the symbol which is the fifth element of the field, if it is not eq to the string previously displayed.
tv-who-line-pc-ppr Variable
The value of tv-who-line-pc-ppr is a piece of paper which is used to display the characters in the who-line.
tv-who-line-stream Variable
The value of tv-who-line-stream is a stream whose output displays on the tv-who-line-pc-ppr .
tv-who-line-process Variable
The value of tv-who-line-process is the process whose state is to be displayed in the who-line. process-wait calls tv-who-line-update if this is the current process. tv-who-line-process is normally the main process of the job which owns the keyboard.
tv-who-line-run-state Variable
Normally the string "RUN". This is what appears in the wholine when the machine isn't waiting for anything.
tv-who-line-run-light-loc Variable
Unibus address of the TV memory location used for the run-light.
tv-who-line-state Variable
This is a special variable which exists inside of tv-who-line-update .
22.9 Microcode Routines
tv-select-screen screen
This microcode primitive selects a screen for use by the tv-draw-char and tv-erase functions. It sets up microcode variables and hardware registers. Note that this state is not preserved through process switching, so this primitive should only be called with inhibit-scheduling-flag bound to t , which is normally desired for other reasons anyway. tv-select-screen should also be used before referencing the TV arrays, such as the screen-buffer-pixel-array , if a 16-bit TV controller is being used.
tv-draw-char font-array char-code x-bit-pos y-bit-pos alu-func
The x-bit-pos and y-bit-pos are of the top left corner of the character. (0,0) is the top left corner of the screen. tv-draw-char extracts the raster elements for one character (or one column of a wide character) and displays them at the indicated address in the currently-selected plane, using the indicated ALU function to combine them with the bits already there. Note that this function does not know anything about pieces of paper; no pc ppr handling is in microcode.
tv-erase width height x-bit-pos y-bit-pos alu-func
This function is in microcode. width and height are in bits, and should be fixnums. A rectangle of the indicated size, of all 1s, is created and merged into the rectangle of TV memory in the currently-selected plane whose top left corner is at (x-bit-pos ,y-bit-pos ), using the specified alu-func . Usually the ANDCA function is used for erasing, but XOR is used for the blinking cursor etc. Note that width and height must be greater than zero.
tv-draw-line x0 y0 x1 y1 alu-func screen
This function is in microcode. A straight line is drawn from the point (x0,y0 ) to the point (x1,y1 ). These points had better not lie outside the screen. The bits that form the line are merged into the screen with the specified alu function. tv-select-screen is applied to screen before the line is drawn.
22.10 Opening a Piece of Paper
Before a piece of paper can be manipulated, any blinkers which may intercept it must be turned off (i.e. their tv-blinker-phase must be nil ). The operation of assuring this is called opening the piece of paper. Similarly, before a blinker's location, size, shape, visibility, or other attributes can be changed, it must be opened, that is made to have no visible effect on the screen. Once a blinker has been opened, we must make sure that the clock function, which implements the blinking, does not come in and turn the blinker back on. This is done in the simplest possible fashion, by binding the inhibit-scheduling-flag non-nil , which causes the microcode not to switch to another process. [In the present system processes are never interrupted, not even by the clock, and this variable is ignored.] This also prevents any other process from coming in and messing up the piece of paper by trying to type on it at the same time. Once we are done with a blinker or piece of paper, and don't need to have it opened any more, we want the blinkers to reappear. It looks best if a blinker reappears right away, rather than at the next time it would have blinked. However, for efficiency we don't want to disappear and reappear the blinker every time a TV operation is performed. Rather, if a program is doing several TV operations right in a row, the first one will turn off the blinkers, the succeeding ones will notice that the blinkers are already off, and then soon after the sequence is completed the blinker will come back on. This is implemented by having the next clock interrupt after we get out of the TV code turn the blinker on.
tv-prepare-pc-ppr Macro
The form (tv-prepare-pc-ppr (pc-ppr) form1 form2 ...) opens the piece of paper which is the value of the variable pc-ppr and evaluates the forms with it open. This macro contains all the knowledge of how to open a pc ppr, including disabling interrupts, finding and opening the blinkers, and selecting the proper screen.
tv-open-blinker blinker
The specified blinker is temporarily turned off; the next clock interrupt when inhibit-scheduling-flag is nil will turn it back on.
tv-open-screen blinker
Opens all the visible blinkers, preparatory to arbitrary munging of the screen, for instance picture drawing.
tv-rectangular-blinker blinker type x y
A tv-blinker-function function for rectangular blinkers (the default). Ignores type , just complements.
tv-hollow-rectangular-blinker blinker type x y
Function for hollow rectangles.
tv-character-blinker blinker type x y
Function for blinkers defined by a character. Arg1 ("height") is the font, and arg2 ("width") is the character in the font. The character is XORed in and out as the blinker blinks.
22.11 Creating Pieces of Paper and Blinkers
tv-define-pc-ppr name font-map &rest options
This function creates a returns a piece of paper. Keyword arguments allow the user to specify some of the many attributes of the piece of paper and leave the remainder to default. name is just a string which is remembered in the pc-ppr and appears in its printed representation. font-map may be either a list or an array of fonts; or it may be nil , which causes the font map to be taken from the screen's default. The remaining arguments are alternating keywords (which should be quoted) and values for those keywords. For example,
(setq foo (tv-define-pc-ppr "foo" (list fonts:tvfont)
			    ':top 300
			    ':bottom 400))
Valid option keywords are:
:screenThe screen on which the piece of paper is to display. The default is tv-default-screen .
:topRaster line number of highest line in the pc ppr. Defaults to screen-y1 of the specified screen, the top.
:bottomRaster line number + 1 of lowest line in the pc ppr. Defaults to screen-y2 of the specified screen, just above the who line (if there is one) at the bottom of the screen.
:leftRaster point number of left edge of pc ppr. Defaults to screen-x1 of the specified screen, the left edge.
:rightRaster point number + 1 of right edge of the pc ppr. Defaults to screen-x2 of the specified screen, the right edge.
:blinker-pt if this pc ppr should have a blinker on its cursor, nil if the cursor should be invisible. Default is t .
:activate-pt if this pc ppr should be initially active. Active means that its blinkers can blink. The default is t .
:reverse-video-p
t if this pc ppr should be in the inverse of the normal black-on-white mode. This works by changing pc-ppr-char-aluf and pc-ppr-erase-aluf . Default is nil .
:more-pt if this pc ppr should have more processing. Default is t .
:vspNumber of raster lines between character lines. This is added to the maximum height of the fonts in the font map to get the height of a line in this pc ppr. The default is 2.
:left-marginAmount of unused space at the left edge of the pc ppr. The default is 0.
:top-marginAmount of unused space at the top. The default is 0.
:right-marginAmount of unused space at the right. The default is 0.
:bottom-marginAmount of unused space at the bottom. The default is 0.
:end-line-fcnA function which is invoked when typeout reaches the end of a line. The default is one which wraps around to the next line.
:end-screen-fcn
A function which is invoked when typeout reaches the bottom of the pc ppr. The default is one which wraps around to the top.
:output-hold-fcn
A function which is invoked when typeout encounters the output-hold flag. The default is one which waits for some other process to clear the flag.
:more-fcnA function which is invoked when more processing is necessary. The default is one which types **MORE** and waits for the user to hit a character, then ignores that character and continues typing.
:blink-fcnThe function to implement the blinker if :blinker-p is not turned off. The default is tv-rectangular-blinker .
:sideways-pt means the monitor is standing on its left side instead of its bottom; change things around appropriately. The default comes from the specified screen.
:integral-pt means that the piece of paper should be forced to be an integral number of lines high; it will be made slightly smaller than the specified size if necessary. The default is nil .
:font-mapSet the font-map. This is intended to replace the passing in of the font-map as the second argument.
tv-define-blinker pc-ppr &rest options
Define a blinker on a piece of paper. The options are similar in syntax to those in tv-define-pc-ppr . Valid options are:
:heightNumber of raster lines high. The default comes from the first font in the pc ppr's font map.
:widthNumber of raster points wide. The default comes from the first font in the pc ppr's font map.
:functionThe function to implement the blinker. The default is tv-rectangular-blinker .
:arg1Another name for :width . Use this with :function s which don't interpret their first "argument" as a width.
:arg2Another name for :height . Use this with :function s which don't interpret their second "argument" as a height.
:visibilityInitial visibility, t , nil , or blink . Default is blink .
:follow-pt if this blinker should follow that pc ppr's cursor. Default is nil .
:roving-pt if this blinker is not confined to a single piece of paper. In this case the pc ppr argument is ignored and should be nil . Default is nil .
:activate-pt if this blinker should be initially active. The default is nil .
:half-periodNumber of 60ths of a second between changes in the blinker. Default is 15.
:screenThe screen on which the blinker should appear. The default is to take it from the pc ppr, or from tv-default-screen in the case of a roving blinker.
:sideways-pt to make the blinker be rotated 90 degrees. Default is to take it from the pc ppr.
You may give nil as a pc-ppr, in which case you must specify :width and :height (or :arg1 and :arg2 ) since they will default to nil . You should give nil as pc-ppr if and only if you specify :roving-p , probably, since :roving-p means this blinker is not on a pc ppr.
tv-redefine-pc-ppr pc-ppr &rest &eval options
Redefine some of the parameters of a pc ppr. The allowed options are :top , :bottom , :left , :right , :top-margin , :bottom-margin , :left-margin , :right-margin , :vsp , :integral-p , :more-p , :screen , and :fonts . :fonts allows you to change the font map, which can change the line height. The size of the blinker will not be changed, but perhaps it should be.
tv-deactivate-pc-ppr pc-ppr
Cause a piece of paper's blinkers to stop blinking. It is illegal to type out on a pc ppr which is deactivated.
tv-activate-pc-ppr pc-ppr
Cause blinkers to blink again.
tv-deactivate-pc-ppr-but-show-blinkers pc-ppr
Cause all blinkers on this piece of paper to be stuck in the blunk (t ) state. I.e. mark place but don't flash. Deactivates so that they won't flash. Typing out on this piece of paper will cause blinkers to start blinking again.
tv-return-pc-ppr pc-ppr
return-array all of a piece of paper.
tv-make-stream pc-ppr
Returns a stream which accepts output and displays it on pc-ppr , and reads input from the keyboard, echoing it on pc-ppr .
22.12 The Keyboard
Keyboard input can be done either by reading from the standard-input stream, which is preferred, or by calling these keyboard routines directly. The characters read by the functions below are in the Lisp Machine character set, with extra bits to incicate the Control and Meta keys. Also, the characters may come from the forced-input mechanism (see LINK:(force-kbd-input-fun)), and may be from the mouse. The byte fields which make up the fixnums returned by these functions have names beginning with "%%kbdSAIL- ", and are explained on LINK:(%%kbd). The special characters Break, Call, and Escape are normally intercepted by the keyboard routines. Break causes the process which reads it to enter a break loop (see LINK:(break-fun)). Call returns control to the top-level job, or enters a break loop if control is already in the top-level job. Control and Meta modifiers cause additional effects. See LINK:(call-key) for details. Escape is a prefix for various commands, as in ITS. Commands consist of Escape, an optional numeric argument (in octal), and a letter, and do not echo. The commands that currently exist are:
<esc>CComplement TV black-on-white mode.
<esc>n C
Complement black-on-white mode of plane n .
<esc>n S
Select video-switch input n .
<esc>MComplement more-processing enable.
<esc>0MTurn off more-processing.
<esc>1MTurn on more-processing.
kbd-tyi &optional (whostate "TYI" )
This is the main routine for reading from the keyboard. The optional argument is what to display as the program state in the who line (usually just "TYI") while awaiting typein. The value returned is a number which consists of a Lisp machine character code, augmented with bits for the control and meta keys. The character is not echoed.
kbd-tyi-no-hang &optional (whostate "TYI" )
Returns nil if no character has been typed, or the character code as kbd-tyi would return it.
kbd-char-available &optional (whostate "TYI" )
Returns non-nil if there is a character waiting to be read; otherwise returns nil . It does not read the character out. This function can be used with process-wait .
kbd-super-image-p Variable
If the value of kbd-super-image-p is non-nil , checking for the special characters Break, Call, and Escape is disabled. Note that you cannot lambda-bind this variable, because it is looked at in different stacks.
kbd-simulated-clock-fcn-list Variable
List of functions to be called every 60th of a second (while the machine is waiting for typein.) This is used to implement blinkers. [This variable should be renamed and moved to the scheduler section.]
force-kbd-input job input
This is used to make a job think it has keyboard input that was not actually typed by the user. The menu system, for example, uses this. job is the job to receive the input. input is either a fixnum, representing a single character, or an array of characters (which may or may not be a string). force-kbd-input waits until previous forced input has been read, then gives the new forced input to the job.
22.13 Internal Special Variables
tv-blinker-list Variable
This is a list of all blinkers which are visible (blinking or solidly on). It is used by the tv-blinker-clock routine and by tv-open-screen .
tv-roving-blinker-list Variable
This is a list of peculiar blinkers which don't stay on any single piece of paper. Whenever any piece of paper is opened, in addition to that piece of paper's own blinkers, all of the roving blinkers will be temporarily turned off. Only the visible ones are on this list. This is primarily for the mouse's blinker.
tv-pc-ppr-list Variable
This is a list of all the pieces of paper. Currently for no particular reason.
tv-white-on-black-state Variable
[??]
tv-beep-duration Variable
Controls beeping.
tv-beep-wavelength Variable
Controls beeping.
tv-more-processing-global-enable Variable
This flag controls whether "**MORE**"'s can happen. Complemented by <esc>M. The initial value is t .
22.14 Font Utility Routines
[Are these the latest word? I suspect not.]
tv-get-font-pixel font char row col
Returns a number which is the pixel value of the specified point in the specified character in the specified font. This is 0 or 1 for normal fonts, or a gray-level value for multi-plane fonts. The value returned is zero if you address outside of the character raster.
tv-store-font-pixel pixel font char row col
This is similar to the above, but stores. It is an error to store outside of the character raster.
tv-make-sideways-font font
Returns a new font which is the same, except turned on its side in such a way that it works on pieces of paper created with the sideways-p t option.
tv-make-dbl-hor-font font
Returns a new font with alternating bits split into two planes in such a way that it will work with doubled horizontal resolution (producing squished characters if the original font had a normal aspect ratio.)
tv-make-gray-font font1 &optional (x-ratio 2) (y-ratio 2) (n-planes 2)
Returns a new font which is the original font with areas x-ratio wide and y-ratio high converted into single points with an appropriate gray level value. n-planes determines the number of gray levels available.
22.15 The Font Compiler

The Font Compiler is a lisp program which runs on the pdp10. It converts fonts represented as AST files into QFASL files which can be loaded into the Lisp machine. When a font is loaded, a symbol in the fonts package is setq 'ed to the representation of that font. To run the font compiler, incant

:lispm1;qcmp
(fasload (lmio)fcmp)
(crunit dsk lmfont)  ;Or whatever directory you keep fonts on
(fcmp-1 'input  'output  'fontname  screen-type )
input is the first-name of the AST file containing the font to be processed. output is the first-name of the QFASL file to be produced. fontname is the name of the symbol in the fonts package whose value will be the font. This symbol will also appear in the font-name field of the font and in the printed representation of the font. screen-type is t if the font is to be used with the 32-bit TV controller, or nil if the font is to be used with the 16-bit controller. [Here insert a catalog of fonts when things settle down a little more.]