{Begin SubSec Display Streams}
{Title Display Streams}
{Text

Streams are used as the basis for all I/O operations.  Files are implemented as streams that can support character printing and reading operations, and file pointer manipulation.  Display streams are a type of stream that also provides an interface for translation, clipping, and figure generation on bitmaps.  All of the operations that can applied to streams can be applied to display streams.  For example, a display stream can be passed as the argument to {fn PRINT}, to print something on the bitmap of a display stream.  In addition, special functions are provided to draw lines and curves and perform other graphical operations on display streams.  Calling these functions on a stream that is not a display stream will generate an error.

Windows are closely related to display streams and can be thought of as a type of display stream.  (In the near future, windows will be a type of display stream.)  All of the functions that operate on display streams also accept windows.    


Display streams can be created with the following function:

{FnDef {Name DSPCREATE} {Args DESTINATION}
{Text
Returns a display stream, with initial settings as indicated below.  If {arg DESTINATION} is specified, it is used as the destination bitmap, otherwise the screen bitmap is used.
}}


Each window has an associated display stream.  To get the window of a particular display stream, use:

{FnDef {Name WFROMDS} {Args DISPLAYSTREAM} 
{Text
Returns the window associated with {arg DISPLAYSTREAM}, creating a window if one does not exist.  Returns {lisp NIL} if the destination of {arg DISPLAYSTREAM} is not a screen bitmap that supports a window system.
}}


{Begin SubSec Manipulating Display Streams}
{Title Manipulating Display Streams}
{Text

The following functions manipulate the fields of a display stream (they may also be given a window, in which case the associated display stream is used).  These functions return the old value (the one being replaced).  A value of {lisp NIL} for the new value will return the current setting without changing it.  These functions do not change any of the bits in the display stream's destination bitmap; just the effect of future operations done through the display stream.


Warning:  The window system maintains the Destination, XOffset, YOffset, and ClippingRegion fields of each window's display stream, adjusting them during window operations.  Users should be very careful about changing these fields in a window's display stream (with {fn DSPDESTINATION}, {fn DSPXOFFSET}, {fn DSPYOFFSET}, or {fn DSPCLIPPINGREGION}).


{FnDef {Name DSPDESTINATION} {Args DESTINATION DISPLAYSTREAM} {Text
Destination:  The bitmap that the display stream modifies.  This can be either the screen bitmap, or an auxilliary bitmap in order to construct figures, possibly save them, and then display them in a single operation.  Initially the screen bitmap.
}}

{FnDef {Name DSPXOFFSET} {Args XOFFSET DISPLAYSTREAM}}
{FnDef {Name DSPYOFFSET} {Args YOFFSET DISPLAYSTREAM}
{Text
XOffset:  The X origin of the display stream's coordinate system in the destination bitmap's coordinate system.  Initially 0 (no X-coordinate translation).

YOffset:  The Y origin of the display stream's coordinate system in the destination bitmap's coordinate system.  Initially 0 (no Y-coordinate translation).

Display streams have their own coordinate system.  Having the coordinate system local to the display stream allows objects to be displayed at different places by translating the display stream's coordinate system relative to its destination bitmap.
}}

{FnDef {Name DSPCLIPPINGREGION} {Args REGION DISPLAYSTREAM}
{Text
ClippingRegion:  A region that limits the extent of characters printed and lines drawn (in the display stream's coordinate system).  Initially set so that no clipping occurs.
}}



{FnDef {Name DSPXPOSITION} {Args XPOSITION DISPLAYSTREAM}}
{FnDef {Name DSPYPOSITION} {Args YPOSITION DISPLAYSTREAM}
{Text
XPosition:  The current X position.  Initially 0.

YPosition:  The current Y position.  Initially 0.

{fn DSPXPOSITION} and {fn DSPYPOSITION} specify the "current position" of the display stream, the position (in the display stream's coordinate system) where the next printing operation will start from.  The functions which print characters or draw on a display stream update these values appropriately.
}}

{FnDef {Name DSPTEXTURE} {Args TEXTURE DISPLAYSTREAM}
{Text
Texture:  A texture that is the background pattern used for the display stream.  Initially the value of {var WHITESHADE}.
}}

{FnDef {Name DSPFONT} {Args FONT DISPLAYSTREAM}
{Text
Font:  A Font Descriptor that specifies the font used when printing characters to the display stream.  Initially Gacha 10.

Note:  {fn DSPFONT} determines its new font descriptor from {arg FONT} by the same coercion rules that {fn FONTPROP} and {fn FONTCOPY} use, with one additional possibility: If {arg FONT} is a list of the form
{lisp ({arg PROP{sub 1}} {arg VAL{sub 1}} {arg PROP{sub 2}} {arg VAL{sub 2}} {ellipsis})}
where {arg PROP{sub 1}} is acceptable as a font-property to {fn FONTCOPY}, then the new font is obtained by
{lisp ({fn FONTCOPY} ({fn DSPFONT}  NIL DISPLAYSTREAM)
{arg  PROP{sub 1}} {arg VAL{sub 1}} {arg  PROP{sub 2}} {arg VAL{sub
2}} {ellipsis})}.
}}

{FnDef {Name DSPLEFTMARGIN} {Args XPOSITION DISPLAYSTREAM}
{Text
LeftMargin:  An integer that is the X position after an end-of-line (in the display stream's coordinate system) - initially 0.
}}

{FnDef {Name DSPRIGHTMARGIN} {Args XPOSITION DISPLAYSTREAM}
{Text
RightMargin:  An integer that is the maximum X position that characters will be printed by {lisp PRIN1} - initially the value is the right edge of the window.
}}


The line length of a window or image stream (as returned by {fn LINELENGTH}, {PageRef Fn LINELENGTH}) is computed by dividing the distance between the left and right margins by the width of an uppercase "A" in the current font.  The line length is changed whenever the Font, LeftMargin, or RightMargin are changed or whenever the window is reshaped.


{FnDef {Name DSPSOURCETYPE} {Args SOURCETYPE DISPLAYSTREAM}
{Text
SourceType:  The {fn BITBLT} sourcetype used when printing characters to the display stream.  Must be either {lisp INPUT} or {lisp INVERT}.  Initially {lisp INPUT}.
}}


{FnDef {Name DSPOPERATION} {Args OPERATION DISPLAYSTREAM}
{Text
Operation:  The default {lisp BITBLT} operation ({lisp REPLACE}, {lisp PAINT}, {lisp INVERT}, or {lisp ERASE}) used when printing or drawing on the display stream.  Initially {lisp REPLACE}.
}}


{FnDef {Name DSPLINEFEED} {Args DELTAY DISPLAYSTREAM}
{Text
LineFeed:  An integer that specifies the Y increment for each linefeed, normally negative.  Initially minus the height of the initial font (Gacha 10).
}}


{FnDef {Name DSPSCROLL} {Args SWITCHSETTING DISPLAYSTREAM}
{Text
Scroll:  A flag that determines the scrolling behavior of the display stream; either {lisp ON} or {lisp OFF}.  If {lisp ON}, the bits in the display streams's destination are moved after any linefeed that moves the current position out of the destination bitmap. Any bits moved out of the current clipping region are lost.  Does not adjust the XOffset, YOffset, or ClippingRegion fields.  Initially {lisp OFF}.  (Note:  if {arg SWITCHSETTING} is {lisp NIL}, the Scroll field is {it not} changed, and the previous value is returned.)
}}


}{End SubSec Manipulating Display Streams}


{Begin SubSec Drawing on Windows and Display Streams}
{Title Drawing on Windows and Display Streams}
{Text


{FnDef {Name DSPFILL} {Args REGION TEXTURE OPERATION DISPLAYSTREAM}
{Text
Fills {arg REGION} of the destination bitmap (within the clipping region) with {arg TEXTURE} (a pattern of bits).  If {arg REGION} is {lisp NIL}, the whole destination (within the clipping region) is used.  If {arg TEXTURE} or {arg OPERATION} are {lisp NIL}, the values from {arg DISPLAYSTREAM} are used.
}}


{FnDef {Name FILLCIRCLE} {Args X Y RADIUS TEXTURE DISPLAYSTREAM}
{Text
Fills in a circular area of radius {arg RADIUS} about the point ({arg X},{arg Y}) in the destination bitmap of {arg DISPLAYSTREAM} with {arg TEXTURE}.  {arg DISPLAYSTREAM}'s position is left at ({arg X},{arg Y}).

{note can't specify OPERATION??}
}}



{FnDef {Name DSPRESET} {Args DISPLAYSTREAM}
{Text
Sets the X position of {arg DISPLAYSTREAM} to its left margin, sets its Y position to the top of the clipping region minus the font ascent, and fills its destination bitmap with its background Texture.
}}


{FnDef {Name MOVETO} {Args X Y DISPLAYSTREAM}
{Text
Changes the current position of {arg DISPLAYSTREAM} to the point {lisp ({arg X},{arg Y})}.
}}


{FnDef {Name RELMOVETO} {Args DX DY DISPLAYSTREAM}
{Text
Changes the current position to the point {lisp ({arg DX},{arg DY})}
coordinates away from current position of {arg DISPLAYSTREAM}.
}}


{FnDef {Name MOVETOUPPERLEFT} {Args IMAGESTREAM REGION}
{Text
Moves the current position to the beginning position of the top line of text.  If {arg REGION} is non-{lisp NIL}, it must be a {lisp REGION} and the X position is changed to the left edge of {arg REGION} and the Y position changed to the top of {arg REGION} less the font ascent of {arg IMAGESTREAM}.  If {arg REGION} is {lisp NIL}, the X position is changed to the left margin of {arg IMAGESTREAM} and the Y position is changed to the top of the clipping region of {arg IMAGESTREAM} less the font ascent of {arg IMAGESTREAM}.
}}


{FnDef {Name DSPBACKUP} {Args WIDTH DISPLAYSTREAM}
{Text
Backs up {arg DISPLAYSTREAM} over a character which is {arg WIDTH} screen points wide.  {fn DSPBACKUP} fills the backed over area with the display stream's background texture and decreases the X position by {arg WIDTH}.  If this would put the X position less than {arg DISPLAYSTREAM}'s left margin, its operation is stopped at the left margin.  It returns {lisp T} if any bits were written, {lisp NIL} otherwise.
}}


{FnDef {Name CENTERPRINTINREGION} {Args EXP REGION DISPLAYSTREAM} 
{Text
Prints {arg EXP} so that is it centered within {arg REGION} of the {arg DISPLAYSTREAM}.  If {arg REGION} is {lisp NIL}, {arg EXP} will be centered in the clipping region of {arg DISPLAYSTREAM}.
}}


}{End SubSec Drawing on Windows and Display Streams}



{Begin SubSec Drawing Lines and Curves}
{Title Drawing Lines and Curves}
{Text

Interlisp-D provides several functions for drawing lines and curves onto the destination bitmap of a display stream or window.  The curve drawing functions take their {fn BITBLT} operation from the display stream, while for straight lines the Operation may be specified as an argument to the drawing function, with the display stream's operation only being used by default.

The following functions produce straight lines of the specified width (in screen points; the default is 1) in the display stream's destination bitmap.  They do not allow "brush" patterns; however, they do support {lisp INVERT} mode inwhich redrawing a line will erase it.  These functions are intended for interactive applications where efficiency is important.  {fn DRAWCURVE} can be used to draw lines with brushes.


{FnDef {Name DRAWTO} {Args X Y WIDTH OPERATION DISPLAYSTREAM COLOR}
{Text
Draws a line from the current position to the point {lisp ({arg X},{arg Y})} onto the destination bitmap of {arg DISPLAYSTREAM}.  The position of {arg DISPLAYSTREAM} is set to {lisp ({arg X},{arg Y})}.

If the destination bitmap has multiple bits per pixel, {arg COLOR} is a color specification that determines the color used to draw the line (See {PageRef Tag ColorSpecifications}).  If {arg COLOR} is {lisp NIL}, this will be the {fn DSPCOLOR} of {arg DISPLAYSTREAM}.
}}



{FnDef {Name RELDRAWTO} {Args DX DY WIDTH OPERATION DISPLAYSTREAM COLOR}
{Text
Draws a line from the current position to the point {lisp ({arg DX},{arg DY})} coordinates away onto the destination bitmap of {arg DISPLAYSTREAM}.  The position of {arg DISPLAYSTREAM} is set to the end of the line.
If {arg DX} and {arg DY} are both 0, nothing is drawn.
}}


{FnDef {Name DRAWLINE} {Args X{sub 1} Y{sub 1} X{sub 2} Y{sub 2} WIDTH OPERATION DISPLAYSTREAM COLOR}
{Text
Draws a line from the point {lisp ({arg X{sub 1}},{arg Y{sub 1}})} to the point {lisp ({arg X{sub 2}},{arg Y{sub 2}})} onto the destination bitmap of {arg DISPLAYSTREAM}.  The position of {arg DISPLAYSTREAM} is set to {lisp ({arg X{sub 2}},{arg Y{sub 2}})}.
If {arg X{sub 1}} equals {arg X{sub 2}} and {arg Y{sub 1}} equals {arg Y{sub 2}}, a point is drawn at {lisp ({arg X{sub 1}},{arg Y{sub 1}})}.
}}


{FnDef {Name DRAWBETWEEN}
{Args POSITION{sub 1} POSITION{sub 2} WIDTH OPERATION DISPLAYSTREAM COLOR}
{Text
Draws a line from the point {arg POSITION{sub 1}} to the point {arg POSITION{sub 2}} onto the destination bitmap of {arg DISPLAYSTREAM}.  The position of {arg DISPLAYSTREAM} is set to {arg POSITION{sub 2}}.
}}



A curve is drawn by placing a {term brush} pattern centered at each point along the curve's trajectory.  A brush pattern is defined by its shape, size, and color.  The currently recognized shapes are {lisp ROUND}, {lisp SQUARE}, {lisp HORIZONTAL}, {lisp VERTICAL}, and {lisp DIAGONAL}.  A brush size is an integer specifying the width of the brush in screen points.  The color is a color specification (see {PageRef Tag ColorSpecifications}), which is only used if the curve is drawn on a multiple bits per pixel bitmap.

A brush is specified to the various drawing functions as a shape-width-color list (such as {lisp (SQUARE 2)} or {lisp (VERTICAL 4 RED)}).  A brush can also be specified as a positive integer, which is interpreted as a {lisp ROUND} brush of that width.  Finally, if a brush is specified as {lisp NIL}, a {lisp (ROUND 1)} brush is used as default.

If a brush is a litatom, it is assumed to be a function which is called at each point of the curve's trajectory with three arguments: the X-coordinate or the point, the Y-coordinate, and the display stream.

The appearance of a curve is also determined by its {term dashing} characteristics.  Dashing is specified by a list of positive integers.  If a curve is dashed, the brush is placed along the trajectory for the number of points indicated by the first element of the dashing list.  The brush is {it off}, not placed in the bitmap, for a number of points indicated by the second element.  The third element indicates how long it will be on again, and so forth.  The dashing sequence is repeated from the beginning when the list is exhausted.  A curve or line is not dashed if the dashing argument to the drawing function is {lisp NIL}.

The curve functions use the display stream's clipping region and operation.  If the operation is {lisp REPLACE}, the curve will be {lisp PAINT}ed in.  Because of the problem of overlapping brush points, the brushes larger than 1 used with {lisp INVERT} operation are {lisp ERASE}ed, rather than inverted.


{FnDef {Name DRAWCURVE} {Args KNOTS CLOSED BRUSH DASHING DISPLAYSTREAM}
{Text
Draws a spline curve.  {arg KNOTS} is a list of positions to which the spline will be fitted.  {arg CLOSED} is a flag which indicates whether or not the spline is to be closed. The other arguments are interpreted as described above.

{note should include a short description of spline curves}
}}


{FnDef {Name DRAWCIRCLE} {Args X Y RADIUS BRUSH DASHING DISPLAYSTREAM}
{Text
Draws a circle of radius {arg RADIUS} about the point {lisp ({arg X},{arg Y})} onto the destination bitmap of {arg DISPLAYSTREAM}.
{arg DISPLAYSTREAM}'s position is left at {lisp ({arg X},{arg Y})}.
(Dashing may not be implemented for this function yet.) The other arguments are interpreted as described above.
}}


{FnDef {Name DRAWELLIPSE} {Args X Y SEMIMINORRADIUS SEMIMAJORRADIUS ORIENTATION BRUSH DASHING DISPLAYSTREAM}
{Text
Draws an ellipse with a minor radius of {arg SEMIMINORRADIUS} and a major radius of {arg SEMIMAJORRADIUS} about the point {lisp ({arg X},{arg Y})} onto the destination bitmap of {arg DISPLAYSTREAM}.
{arg ORIENTATION} is the angle of the major axis in degrees, positive in the counterclockwise direction.
{arg DISPLAYSTREAM}'s position is left at {lisp ({arg X},{arg Y})}.
(Dashing may not be implemented for this function yet.) The other arguments are interpreted as described above.
}}




}{End SubSec Drawing Lines and Curves}



}{End SubSec Display Streams}




{Begin SubSec Typescript Facilities: The "T" File}
{Title Typescript Facilities: The "T" File}
{Text

Output to the file {lisp T} and echoing of type-in is directed to a distinguished
terminal display stream.  This is initialized to be a display stream at the top of the screen, but that initial setting can be modified by the function {fn TTYDISPLAYSTREAM}.


{FnDef {Name TTYDISPLAYSTREAM} {Args DISPLAYSTREAM}
{Text
Selects the display stream or window {arg DISPLAYSTREAM} to be the terminal output channel, and returns the previous terminal output display stream.  {fn TTYDISPLAYSTREAM} puts {arg DISPLAYSTREAM} into scrolling mode and calls {fn PAGEHEIGHT} with the number of lines that will fit into {arg DISPLAYSTREAM} given its current Font and ClippingRegion.{note why?  -- lmm}  The linelength of {fn TTYDISPLAYSTREAM} is computed (like any other display stream) from its LeftMargin, RightMargin, and Font.  If one of these fields is changed, its linelength is recalculated.  If one of the fields used to compute the number of lines (such as the ClippingRegion or Font) changes, {lisp PAGEHEIGHT} is not automatically recomputed.  {lisp (TTYDISPLAYSTREAM (TTYDISPLAYSTREAM))} will cause it to be recomputed.

If the window system is active, the line buffer is saved in the old {lisp TTY} window, and the line buffer is set to the one saved in the window of the new display stream, or to a newly created line buffer (if it does not have one).  Caution:  It is possible to move the {fn TTYDISPLAYSTREAM} to a nonvisible display stream or to a window whose current position is not in its clipping region.
}}



{FnDef {Name CARET} {Args NEWCARET}
{Text
Sets the shape that blinks at the location of the next output to the {lisp TTYDISPLAYSTREAM}.  {arg NEWCARET} is either (1) {lisp NIL} - no changes, returns a {lisp CURSOR}{note ptr to CURSORs?} representing the current caret, (2) {lisp OFF} - turns the caret off, (3) a {lisp CURSOR} which gives the new caret shape or (4) {lisp T} - reset the caret to the value of {VAR DEFAULTCARET}. {index globalvar DEFAULTCARET}  {VAR DEFAULTCARET} can be set to change the initial caret for new processes.  The hotspot of {arg NEWCARET} indicates which point in the new caret bitmap should be located at the current output position.  The previous caret is returned.
Note: the bitmap for the caret is not limited to the dimensions {var CURSORWIDTH} by {var CURSORHEIGHT}.
}}


{FnDef {Name CARETRATE} {Args ONRATE OFFRATE}
{Text
Sets the rate at which the caret for the current process will flash.  The caret will be visible for {ARG ONRATE} milliseconds, then not visible for {arg OFFRATE}  milliseconds.   If {arg ONRATE} is {lisp T}, the rate is set to {VAR DEFAULTCARETRATE}{INDEX Globalvar DEFAULTCARETRATE}. If {arg OFFRATE} is {lisp NIL} then it is set to be the same as {arg ONRATE}. The previous value of {FN CARETRATE} is returned.  If the caret is off, {fn CARETRATE} return NIL.}}


{FnDef {Name PAGEHEIGHT} {Args N}
{Text
If {arg N} is greater than 0, it is the number of lines of output that will be printed to {lisp TTYDISPLAYSTREAM} before the page is held.{index page holding}  A page is held before the {arg N}+1 line is printed to {lisp TTYDISPLAYSTREAM} without intervening input if there is no terminal input waiting to be read.  The output is held with the screen video reversed until a character is typed.  Output holding is disabled if {arg N} is 0.  {fn PAGEHEIGHT} returns the previous setting.
}}

{note put FULLPAGEFN here?}

}{End SubSec Typescript Facilities: The "T" File}


{Begin SubSec Cursor and Mouse}
{Title Cursor and Mouse}
{Text

The screen relative position at which the cursor bitmap is being displayed can be read or set using the functions:


{FnDef {Name CURSORPOSITION} {Args NEWPOSITION DISPLAYSTREAM OLDPOSITION}
{Text
This returns the location of the cursor in the coordinate system of {arg DISPLAYSTREAM} (the current display stream, if {arg DISPLAYSTREAM} is {lisp NIL}).  If {arg OLDPOSITION} is a {lisp POSITION}, it will be reused, and returned.  If {arg NEWPOSITION} is non-{lisp NIL}, it should be a position and the cursor will be positioned at {arg NEWPOSITION}.
}}


{FnDef {Name ADJUSTCURSORPOSITION} {Args DELTAX DELTAY}
{Text
Moves the cursor {arg DELTAX} points in the X direction and {arg DELTAY} points in the Y direction. {arg DELTAX} and {arg DELTAY} default to 0.
}}


The cursor can be changed like any other bitmap by {fn BITBLT}ing into it or pointing a display stream at it and printing or drawing curves.  For most applications, it is also necessary to locate the {it hotspot} - a point within the {lisp CURSORWIDTH} by {lisp CURSORHEIGHT} area which is used to determine a {it point} position for the cursor.  Also for some applications it is necessary to save and restore the cursor.  The Cursor record and the following functions provide these capabilities.  A Cursor record has fields {lisp CURSORBITMAP} and {lisp CURSORHOTSPOT}, the latter a {lisp POSITION} that gives the location of the hot spot inside the cursor.


{FnDef {Name CURSORCREATE} {Args BITMAP X Y}
{Text
Returns a cursor object which has {arg BITMAP} as its image and the location ({arg X},{arg Y}) as the hot spot.  If {arg X} is a {lisp POSITION}, it is used as the hot spot.  If {arg BITMAP} has dimensions different from {lisp CURSORWIDTH} by {lisp CURSORHEIGHT}, the lesser of the widths and the lesser of the heights are used to determine the bits that actually get copied into the lower left corner of the cursor.  If {arg X} is {lisp NIL}, 0 is used.  If {arg Y} is {lisp NIL}, {lisp CURSORHEIGHT}-1 is used.  The default cursor is an uparrow with its tip in the upper left corner and its hot spot at (0,{lisp CURSORHEIGHT}-1).
}}


{note the INVERTFLG arg to CURSOR and SETCURSOR should not be documented...  FLIPCURSOR is to be used for inverting the cursor}


{FnDef {Name CURSOR} {Args NEWCURSOR {anonarg}}
{Text
Returns a {lisp CURSOR} record instance that contains (a copy of) the current cursor specification.  If {arg NEWCURSOR} is a {lisp CURSOR} record instance, the cursor will be set to the values in {arg NEWCURSOR}.  If {arg NEWCURSOR} is {lisp T}, the cursor will be set to the default cursor {var DEFAULTCURSOR},{index DEFAULTCURSOR Var} an upward left pointing arrow.
}}


{FnDef {Name SETCURSOR} {Args NEWCURSOR {anonarg}}
{Text
If {arg NEWCURSOR} is a {lisp CURSOR} record instance, the cursor will be set to the values in {arg NEWCURSOR}.  This does not return the old cursor, and therefore, provides a way of changing the cursor without using storage.
}}


{FnDef {Name FLIPCURSOR} {Args}
{Text
Inverts the cursor.
}}


There are several cursors defined in Interlisp-D that may be of interest to users.  One of these is {var WAITINGCURSOR},{index WAITINGCURSOR Var} an hour glass shape used by the system to indicate that a long computation is in progress.

{note should we include a list of all available cursors?  figure?}

{lisp CURSOR}s can be saved on a file using the file package command {filecom CURSORS},{index CURSORS FileCom} or the {filecom UGLYVARS} file package command.


{Begin SubSec Mouse Button Testing}
{Title Mouse Button Testing}
{Text

There are various graphical input devices that can be read from Interlisp-D.  The devices used in this manner are: a device called a {term mouse}, which has three keys and steers the cursor, and seven uninterpreted keys on the keyboard.  (Some Xerox 1100 systems may also have a small, five-key keyset.)  The following macros are provided to test the state of these input devices.  (The three keys on the mouse (often called buttons) are referred to by their location: left, middle, or right.)


{MacDef {Name MOUSESTATE} {Args BUTTONFORM}
{Text
Reads the mouse state and returns {lisp T} if that state is described by {arg BUTTONFORM}.
{arg BUTTONFORM} can be one of the key indicators
{lisp LEFT},{index LEFT (key indicator)}
{lisp MIDDLE},{index MIDDLE (key indicator)}
or {lisp RIGHT};{index RIGHT (key indicator)}
the atom {lisp UP} (indicating all keys are up); the form {lisp (ONLY {arg KEY})}; or a form of {lisp AND}, {lisp OR}, or {lisp NOT} applied to any valid button form.  For example: {lisp (MOUSESTATE LEFT)} will be true if the left mouse button is down.  {lisp (MOUSESTATE (ONLY LEFT))} will be true if the left mouse button is the only one down.  {lisp (MOUSESTATE (OR (NOT LEFT) MIDDLE))} will be true if either the left mouse button is up or the middle mouse button is down.
}}


{MacDef {Name LASTMOUSESTATE} {Args BUTTONFORM}
{Text
Similar to {mac MOUSESTATE}, but tests the value of {lisp LASTMOUSEBUTTONS} rather than getting the current state.  This is useful for determining which keys caused a {mac MOUSESTATE} to be true.
}}


{MacDef {Name UNTILMOUSESTATE} {Args BUTTONFORM INTERVAL}
{Text
{arg BUTTONFORM} is as described in {mac MOUSESTATE}.  Waits until {arg BUTTONFORM} is true or until {arg INTERVAL} milliseconds have elapsed.  The value of {mac UNTILMOUSESTATE} is {lisp T} if {arg BUTTONFORM} was satisfied before it timed out, otherwise {lisp NIL}.  If {arg INTERVAL} is {lisp NIL}, it waits indefinitely.  It compiles into an open loop that calls the {lisp TTY} wait background function.  This form should not be used inside the {lisp TTY} wait background function.  {mac UNTILMOUSESTATE} does not use any storage during its wait loop.
}}


The macros {mac KEYSETSTATE}{index KEYSETSTATE Mac} and {mac LASTKEYSETSTATE}{index LASTKEYSETSTATE Mac} are identical to {mac MOUSESTATE} and {mac LASTMOUSESTATE} except that they also check the state of the five-finger keyset as well as the state of the mouse buttons.  That is they check the state of both the mouse and the keyset.  Thus, if the left mouse button was the only mouse button held down, {lisp (MOUSESTATE (ONLY LEFT))} would be {lisp T} even though a keyset key was down; whereas {lisp (KEYSETSTATE (ONLY LEFT))} would be {lisp NIL} if a keyset button were down. 

The names of the keyset keys are:
{lisp LEFTKEY},{index LEFTKEY (key indicator)}
{lisp LEFTMIDDLEKEY},{index LEFTMIDDLEKEY (key indicator)}
{lisp MIDDLEKEY},{index MIDDLEKEY (key indicator)}
{lisp RIGHTMIDDLEKEY}{index RIGHTMIDDLEKEY (key indicator)}
and {lisp RIGHTKEY}.{index RIGHTKEY (key indicator)}


}{End SubSec Mouse Button Testing}




{Begin SubSec Low Level Access to Mouse}
{Title Low Level Access to Mouse}
{Text

This section describes the low level access to the graphical input devices and can be skipped by most users.  Graphical input information is represented in the following global variables:

{note this info may change ... possibly, there will be a "total-keyboard-and-mouse-state" datatype that will encode all of this information, which will be stored in a variable within particular processes at given times.  This will allow a process to be woken up, have another process do something, and the first process will be able to get the kbd state as of the time it was woken up.}


{VarDef {Name LASTMOUSEX}
{Text
The X position of the cursor in absolute screen coordinates.  Also see the function {fn LASTMOUSEX} below.
}}


{VarDef {Name LASTMOUSEY}
{Text
The Y position of the cursor in absolute screen coordinates.  Also see the function {fn LASTMOUSEY} below.
}}


{VarDef {Name LASTMOUSEBUTTONS}
{Text
An 8-bit number that has bits on corresponding to the mouse buttons that are down: {lisp 4Q} is the left mouse button, {lisp 2Q} is the right button, {lisp 1Q} is the middle button.  (Bits {lisp 200Q}, {lisp 100Q}, {lisp 40Q}, {lisp 20Q}, and {lisp 10Q} give the state of the keyset keys, from left to right, if you have a keyset.)
}}


{VarDef {Name LASTKEYBOARD}
{Text
The state of certain keys on the keyboard ({lisp 200Q} = lock, {lisp 100Q} = left shift, {lisp 40Q} = ctrl, {lisp 10Q} = right shift, {lisp 4Q}  = blankBottom, {lisp 2Q} = blankMiddle, {lisp 1Q} = blankTop).  If the key is down, the corresponding bit is on.
}}


{VarDef {Name LASTMOUSETIME}
{Text
The time in milliseconds since the mouse was last read (since the last call to {lisp GETMOUSESTATE}.  {var LASTMOUSETIME} is a 16-bit positive integer so it rolls over every 65+ seconds.
}}


The following functions provide low level cursor access in display stream coordinates.


{FnDef {Name LASTMOUSEX} {Args DISPLAYSTREAM}
{Text
Returns the value of the cursor's X position in the coordinates of {arg DISPLAYSTREAM}.
}}


{FnDef {Name LASTMOUSEY} {Args DISPLAYSTREAM}
{Text
Returns the value of the cursor's Y position in the coordinates of {arg DISPLAYSTREAM}.
}}


{FnDef {Name DECODEBUTTONS} {Args BUTTONSTATE}
{Text
Returns a list of the buttons or keys that are down in the state {arg BUTTONSTATE}.  If {arg BUTTONSTATE} is not a {lisp SMALLP}, {var LASTMOUSEBUTTONS} is used (see {fn GETMOUSESTATE} below).  The button names that can be returned are: {lisp LEFT}, {lisp MIDDLE}, {lisp RIGHT} (the three mouse keys), {lisp LEFTKEY}, {lisp LEFTMIDDLEKEY}, {lisp MIDDLEKEY}, {lisp RIGHTMIDDLEKEY} and {lisp RIGHTKEY} (the five keyset keys).
}}



{FnDef {Name GETMOUSESTATE}
{Text
Reads the current state of the mouse and sets the variables {var LASTMOUSEX}, {var LASTMOUSEY}, {var LASTMOUSEBUTTONS}, {var LASTMOUSETIME}, and {var LASTKEYBOARD}.  In polling mode, the program must remember the previous state and look for changes, such as a key going up or down, or the cursor moving outside a region of interest.
}}




{Begin Comment}
rrb is not sure whether this stuff still works with processes, etc. -- nobody has used it recently.


In queuing use, state of the mouse is saved whenever there is a transition in one of the mouse keys.  In this mode, the key clicks are treated much like typed-in keyboard strokes; they are saved until the program next asks for them.  To coordinate the keyboard with the mouse clicks, the mouse interrupt handler puts a designated character in the keyboard input buffer.  The intention is that this
character be a read macro character that handles the mouse event.  All system mouse interaction, including the window system, is done in polling mode.  Mouse queuing is included to allow systems to be developed which permit "buttoning ahead."  However the user may experience undesired interactions between queuing mode and the rest of the system.  The following functions deal with mouse event queuing:


{FnDef {Name ENABLEMOUSE} {Args #EVENTS CHARCODE}
{Text
Turns mouse event queuing on and off.  If {arg #EVENTS} is non-{lisp NIL}, it is the number of mouse events to save (Interlisp-D limit is 49).  If more than {arg #EVENTS} events occur, further events are ignored and the screen is flashed.  If {arg CHARCODE} is non-{lisp NIL}, it is the character code that will be inserted into the keyboard stream when the mouse event occurs.  If {arg CHARCODE} is {lisp NIL}, nothing will be put into the keyboard buffer.  The mouse queue can be cleared by calling {fn CLEARMOUSEBUF} (see below).  If {arg CHARCODE} is given, {fn CLEARBUF} will clear the mouse queue as well as the input buffer.

The size of the queue and the character code may also be specified by giving a dotted pair of the form {lisp ({arg #EVENTS} . {arg CHARCODE})} as the {arg #EVENTS} argument.  {fn ENABLEMOUSE} returns a dotted pair containing the previous size and character code settings, thus permitting {fn ENABLEMOUSE} to be used inside {fn RESETFORM}.  If {arg #EVENTS} is {lisp NIL}, {fn ENABLEMOUSE} turns off mouse queuing.
}}


{FnDef {Name GETMOUSEEVENT} {Args FLG}
{Text
Examines the state of the mouse queue and may read the next event (setting the variables mentioned above).  If {arg FLG} is {lisp NIL}, {fn GETMOUSEEVENT} returns the time of the next event if there is one (returns {lisp NIL} if there are no events), but does not read it.  If {arg FLG} is not {lisp NIL}, the time is returned and the event will be read into the variables {var LASTMOUSEX}, {var LASTMOUSEY}, etc.
}}


{FnDef {Name CLEARMOUSEBUF} {Args FLG}
{Text
Clears the mouse queue.  If {arg FLG} is non-{lisp NIL}, the cleared events are stored in an internal buffer that can be recovered with {fn MOUSEBUF}.
}}


{FnDef {Name MOUSEBUF} {Args FLG}
{Text
If {arg FLG} is {lisp T}, this returns the internal buffer of mouse events that were saved at the last {lisp ({fn CLEARMOUSEBUF} T)} or {lisp ({fn CLEARBUF} T T)}.  If {arg FLG} is {lisp NIL}, the internal mouse event buffer is cleared.
}}


{FnDef {Name BKMOUSEBUF} {Args EVENTLST}
{Text
{arg EVENTLST} is a list of mouse events. {fn BKMOUSEBUF} sets the mouse queue to this list of events. In typical use, {arg EVENTLST} is a list obtained by a call to {fn MOUSEBUF}.  The form of each mouse event is a list of the form {lisp (MOUSEX MOUSEY MOUSEBUTTONS KEYBOARD MOUSETIME)}.
}}

{End Comment}




}{End SubSec Low Level Access to Mouse}


}{End SubSec Cursor and Mouse}