{Begin SubSec Cursor and Mouse} {Title Cursor and Mouse} {Text {index *PRIMARY* Mouse} {index *PRIMARY* Cursor} A mouse is a small box connected to the computer keyboard by a long wire. On the top of the mouse are two or three buttons. On the bottom is a rolling ball or a set of photoreceptors, to detect when the mouse is moved. As the mouse is moved on a surface, a small image on the screen, called the cursor, moves to follow the movement of the mouse. By moving the mouse, the user can cause the cursor to point to any part of the display screen. The mouse and cursor are an important part of the Interlisp-D user interface. The Interlisp-D window system allows the user to create, move, and reshape windows, and to select items from displayed menus, all by moving the mouse and clicking the mouse buttons. This section describes the low-level functions used to control the mouse and cursor. {Begin SubSec Changing the Cursor Image} {Title Changing the Cursor Image} {Text Interlisp-D maintains the image of the cursor on the screen, moving it as the mouse is moved. The bitmap that becomes visible as the cursor can be accessed by the following function: {FnDef {Name CURSORBITMAP} {Text Returns the cursor bitmap. }} {VarDef {Name CURSORWIDTH}} {VarDef {Name CURSORHEIGHT} {Text Value is the width and height of the cursor bitmap, respectively. }} The cursor bitmap 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. However, for some applications it is necessary to save and restore the cursor, which can be most easily done using {lisp CURSOR} record objects.{index CURSOR (Record)} A {lisp CURSOR} record contains fields {lisp CURSORBITMAP} and {lisp CURSORHOTSPOT}. The value of the {lisp CURSORBITMAP} field is a bitmap that is {var CURSORWIDTH} bits wide by {var CURSORHEIGHT} high. The value of the {lisp CURSORHOTSPOT} field is the {index *PRIMARY* Hot spot of cursor}{index *PRIMARY* Hotspot}"hot spot" of the cursor, a position in the bitmap interpreted as the point that the cursor is pointing to. {lisp CURSOR} objects can be saved on a file using the file package command {filecom CURSORS},{index CURSORS FileCom} or the {filecom UGLYVARS} file package command. {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 *PRIMARY* 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. }} The following list describes the cursors used by the Interlisp-D system. Most of them are stored as the values of various variables. {Begin LabeledList Named cursors} {Label €ÀàðøüþðØ˜ } {Text In variable {var DEFAULTCURSOR}.{index DEFAULTCURSOR Var} This is the default cursor. } {Label ÿþÀ`=xðàÀ€€À `07Øgìÿþÿþ} {Text In variable {var WAITINGCURSOR}.{index *PRIMARY* WAITINGCURSOR Var} Represents an hourglass. Used during long computations. } {Label  ÿø€¹(¹(¹(¹(¹(¹(¹(€€€€€€ÿø} {Text In variable {var MOUSECONFIRMCURSOR}.{index MOUSECONFIRMCURSOR Var} Indicates that the system is waiting for the user to confirm an action by pressing the left mouse button, or aborting the action by pressing any other button. Used by the function {fn MOUSECONFIRM} ({PageRef Fn MOUSECONFIRM}). } {Label tœ‚ a’$b2\JHJHJHJH1ˆ} {Text In variable {var SYSOUTCURSOR}.{index SYSOUTCURSOR Var} Indicates that the system is saving the virtual memory in a sysout file. See {fn SYSOUT}, {PageRef Fn SYSOUT}. } {Label  d Š Ê .¬ª@Ê@ N R P Ö Ò \} {Text In variable {var SAVINGCURSOR}.{index SAVINGCURSOR Var} Indicates that {fn SAVEVM} has been called automatically to save the virtual memory state after the system is idle for long enough. See {var SAVEVMWAIT}, {PageRef Var SAVEVMWAIT}. } {Label Àp1a AÁ�ÿþ�ÁAa 1pÀ} {Text In variable {var CROSSHAIRS}.{index CROSSHAIRS Var} Used by {fn GETPOSITION} ({PageRef Fn GETPOSITION}) to indicate a position. } {Label  ÿðÿðÀ0À0À0À0À0À0À0À0ÿðÿð} {Text In variable {var BOXCURSOR}.{index BOXCURSOR Var} Used by {fn GETBOXPOSITION} ({PageRef Fn GETBOXPOSITION}) to indicate where to place the corner of a box. } {Label  9À)@9À€€€pà��������``} {Text In variable {var FORCEPS}.{index FORCEPS Var} Used by {fn GETREGION} ({PageRef Fn GETREGION}) when the user switches corners. } {Label €ÀàðøçüÃþ½ð$Ø$˜½ à ç} {Text In variable {var EXPANDINGBOX}.{index EXPANDINGBOX Var} Used by {fn GETREGION} ({PageRef Fn GETREGION}) when a box is first displayed. } {Label  ÿÀÀÀÀÀÀÀÀÀÀ@} {Text In variable {var UpperRightCursor}.{index UpperRightCursor Var} } {Label   ````````àÿà} {Text In variable {var LowerRightCursor}.{index LowerRightCursor Var} } {Label  ÿÀÿ€ÀÀÀÀÀÀÀÀ€} {Text In variable {var UpperLeftCursor}.{index UpperLeftCursor Var} } {Label  €ÀÀÀÀÀÀÀÀÿÀÿà} {Text In variable {var LowerLeftCursor}.{index LowerLeftCursor Var} } {Unindent The previous four cursors are used by {fn GETREGION} ({PageRef Fn GETREGION}) to indicate the four corners of a region. } {Label  øÿÿàÿøÿàÿø} {Text In variable {var VertThumbCursor}.{index VertThumbCursor Var} Used during scrolling to indicate thumbing in a vertical scroll bar. } {Label 88||þ8888þ||88} {Text In variable {var VertScrollCursor}.{index VertScrollCursor Var} } {Label  >>ÿ€ÿ€} {Text In variable {var ScrollUpCursor}.{index ScrollUpCursor Var} } {Label  ÿ€ÿ€>>} {Text In variable {var ScrollDownCursor}.{index ScrollDownCursor Var} } {Unindent The previous four cursors are used by {fn SCROLL.HANDLER} ({PageRef Fn SCROLL.HANDLER}) during vertical scrolling. } {Label   € € €* * * ª¨ª¨ª¨ª¨ª¨} {Text In variable {var HorizThumbCursor}.{index HorizThumbCursor Var} Used during scrolling to indicate thumbing in a horizontal scroll bar. } {Label   088x<ÿþÿþx<880 } {Text In variable {var HorizScrollCursor}.{index HorizScrollCursor Var} } {Label  €€€?€ÿÿÿÿ?€€€€} {Text In variable {var ScrollLeftCursor}.{index ScrollLeftCursor Var} } {Label  ÀðüÿÿÿÿüðÀ} {Text In variable {var ScrollRightCursor}.{index ScrollRightCursor Var} } {Unindent The previous four cursors are used by {fn SCROLL.HANDLER} ({PageRef Fn SCROLL.HANDLER}) during horizontal scrolling. } {Label àNŽHˆNŽHˆNîà“v•%ç%¥%•v,  à!q©!!!à,  �!�qP©P!0!0!, d\–Ò‡Ò…R…R”Rd\} {Label  à“'ä©“©”©—w, ðˆŠÒóŠŠò, x@„ € �…ðzBßbDR„JFB} {Text These cursors are used by the Teleraid low-level debugger. These cursors are not accessable as standard Interlisp-D cursors. } {End LabeledList Named cursors} }{End SubSec Changing the Cursor Image} {Begin SubSec Flashing Bars on the Cursor} {Title Flashing Bars on the Cursor} {Text {index *PRIMARY* Flashing bars on cursor} {index *PRIMARY* Bars on cursor} {index *PRIMARY* Inverted cursor} The low-level Interlisp-D system uses the cursor to display certain system status information, such as garbage collection or swapping. This is done because changing the cursor image is very quick, and does not require interacting with the window system. Interlisp inverts horizontal bars on the cursor when the system is swapping pages, or doing certain stack operations. Normally, these bars are only inverted for a very short time, so they look like they are flashing. These cursor changes are interpreted as follows: {Begin LabeledList Flashing bars on cursor} {Label Inverted cursor: ÿ?ÿÿÿÿÿÿÿ'ÿgÿóÿóÿùÿùÿüÿüÿ} {Text Whatever image is being displayed as the cursor, whenever Interlisp does a garbage collection, the whole cursor is inverted. } {Label Top bar: ÿÀàðøüüðØ˜ } {Text Swap read. On when Interlisp is swapping in a page from the virtual memory file into the real memory. It is also on when Interlisp allocates a new virtual memory page, even though that doesn't involve a disk read. If this is flashing a lot, the system is doing a lot of swapping. This is an indication that the virtual memory working set is fragmented (see {PageRef Term Working Set}). Performance may be improved by reloading a clean Interlisp system. } {Label Upper middle bar: €ÀàðøüÿðØ˜ } {Text Stack operations. If this is flashing a lot, it suggests that some process is neglecting to release stack pointers in a timely fashion (see {PageRef Term Releasing Stack Pointers}). } {Label Lowereler middle bar: €ÀàðøüüðØgÿ } {Text Stack operations. On when Interlisp is moving frames on the stack. If the system is slow, and this is flashing a lot, {fn HARDRESET} ({PageRef Fn HARDRESET}) sometimes helps. } {Label Bottom bar: €ÀàðøüüðØ˜ üÿ} {Text Swap write. On when Interlisp writes a dirty virtual memory page from the real memory back into the virtual memory file. } {End LabeledList Flashing bars on cursor} }{End SubSec Flashing Bars on the Cursor} {Begin SubSec Cursor Position} {Title Cursor Position} {Text The position at which the cursor bitmap is being displayed can be read or set using the following functions: {FnDef {Name CURSORPOSITION} {Args NEWPOSITION DISPLAYSTREAM OLDPOSITION} {Text Returns the location of the cursor in the coordinate system of {arg DISPLAYSTREAM} (or the current display stream, if {arg DISPLAYSTREAM} is {lisp NIL}). If {arg NEWPOSITION} is non-{lisp NIL}, it should be a position and the cursor will be positioned at {arg NEWPOSITION}. If {arg NEWPOSITION} is {lisp NIL}, the current position is simple returned. Note: The current position of the cursor is the position of the "hot spot" of the cursor, not the position of the cursor bitmap. If {arg OLDPOSITION} is a {lisp POSITION} object, this object will be changed to point to the location of the cursor and returned, rather of allocating a new {lisp POSITION}. This can improve performance if {fn CURSORPOSITION} is called repeatedly to track the cursor. Note: To get the location of the cursor in absolute screen coordinates, use the variables {var LASTMOUSEX} and {var LASTMOUSEY} ({PageRef Var LASTMOUSEX}). }} {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. }} }{End SubSec Cursor Position} {Begin SubSec Mouse Button Testing} {Title Mouse Button Testing} {Text {index *PRIMARY* Mouse Keys} {index *PRIMARY* Keys on mouse} {index *PRIMARY* Mouse buttons} {index *PRIMARY* Buttons on mouse} There are two or three keys on the mouse. These keys (also called buttons) are referred to by their location: {lisp LEFT}, {lisp MIDDLE}, or {lisp RIGHT}. The following macros are provided to test the state of the mouse buttons: {MacDef {Name MOUSESTATE} {Args BUTTONFORM} {Text Reads the state of the mouse buttons, 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 {var LASTMOUSEBUTTONS} (below) rather than getting the current state. This is useful for determining which keys caused {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. This 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. }} {Begin comment keyset de-documented} 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 comment keyset de-documented} }{End SubSec Mouse Button Testing} {Begin SubSec Low Level Mouse Functions} {Title Low Level Mouse Functions} {Text This section describes the functions and variables that provide low level access to the mouse and cursor. {FnDef {Name LASTMOUSEX} {Args DISPLAYSTREAM} {Text Returns the value of the cursor's X position in the coordinates of {arg DISPLAYSTREAM} (as of the last call to {fn GETMOUSESTATE}, below). }} {FnDef {Name LASTMOUSEY} {Args DISPLAYSTREAM} {Text Returns the value of the cursor's Y position in the coordinates of {arg DISPLAYSTREAM} (as of the last call to {fn GETMOUSESTATE}, below). }} {VarDef {Name LASTMOUSEX} {Text Value is the X position of the cursor in absolute screen coordinates (as of the last call to {fn GETMOUSESTATE}, below). }} {VarDef {Name LASTMOUSEY} {Text Value is the Y position of the cursor in absolute screen coordinates (as of the last call to {fn GETMOUSESTATE}, below). }} {VarDef {Name LASTMOUSEBUTTONS} {Text Value is an integer that has bits on corresponding to the mouse buttons that are down (as of the last call to {fn GETMOUSESTATE}, below). Bit {lisp 4Q} is the left mouse button, {lisp 2Q} is the right button, {lisp 1Q} is the middle button. {Begin comment keyset de-documented} (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.) {End comment keyset de-documented} }} {VarDef {Name LASTKEYBOARD} {Text Value is an integer encoding the state of certain keys on the keyboard (as of the last call to {fn GETMOUSESTATE}, below). Bit {lisp 200Q} = lock, {lisp 100Q} = left shift, {lisp 40Q} = ctrl, {lisp 10Q} = right shift, {lisp 4Q} = blank Bottom, {lisp 2Q} = blank Middle, {lisp 1Q} = blank Top. If the key is down, the corresponding bit is on. }} {FnDef {Name GETMOUSESTATE} {Text Reads the current state of the mouse and sets the variables {var LASTMOUSEX}, {var LASTMOUSEY}, and {var LASTMOUSEBUTTONS}. 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. }} {FnDef {Name DECODEBUTTONS} {Args BUTTONSTATE} {Text Returns a list of the mouse buttons that are down in the state {arg BUTTONSTATE}. If {arg BUTTONSTATE} is not a small integer, the value of {var LASTMOUSEBUTTONS} (above) is used. The button names that can be returned are: {lisp LEFT}, {lisp MIDDLE}, {lisp RIGHT} (the three mouse keys). {Begin comment keyset de-documented} {lisp LEFTKEY}, {lisp LEFTMIDDLEKEY}, {lisp MIDDLEKEY}, {lisp RIGHTMIDDLEKEY} and {lisp RIGHTKEY} (the five keyset keys). {End comment keyset de-documented} }} {Begin Comment Flushed} {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.}} {End Comment Flushed} }{End SubSec Low Level Mouse Functions} }{End SubSec Cursor and Mouse} ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) Ò* BMOBJ.GETFN2* BMOBJ.GETFN2i* BMOBJ.GETFN2�* BMOBJ.GETFN2;& BMOBJ.GETFN2»$ BMOBJ.GETFN2( BMOBJ.GETFN2•" BMOBJ.GETFN2²* BMOBJ.GETFN2”& BMOBJ.GETFN2�  BMOBJ.GETFN2R  BMOBJ.GETFN2Q  BMOBJ.GETFN2P  BMOBJ.GETFN2×$ BMOBJ.GETFN2–* BMOBJ.GETFN2S* BMOBJ.GETFN2P* BMOBJ.GETFN2Ó$ BMOBJ.GETFN2š BMOBJ.GETFN2T BMOBJ.GETFN2R BMOBJ.GETFN2×( BMOBJ.GETFN2 BMOBJ.GETFN2 BMOBJ.GETFN2 BMOBJ.GETFN2  BMOBJ.GETFN2 BMOBJ.GETFN2& BMOBJ.GETFN2ð* BMOBJ.GETFN2˜* BMOBJ.GETFN2î* BMOBJ.GETFN2ß* BMOBJ.GETFN2Ï* BMOBJ.GETFN2pG¯Ezº