{Begin SubSec Windows} {Title Windows} {Text {index *PRIMARY* Windows} A window specifies a region of the screen, a display stream, functions that get called when the window undergoes certain actions, and various other items of information. The basic model is that a window is a passive collection of bits (on the screen). On top of this basic level, the system supports many different types of windows that are linked to the data structures displayed in them and provide selection and redisplaying routines. In addition, it is possible for the user to create new types of windows by providing selection and displaying functions for them. Windows are ordered in depth from user to background. Windows in front of others obscure the latter. Operating on a window generally brings it to the top. Windows are located at a certain position on the screen. Each window has a clipping region that confines all bits written to it to a region that allows a border around the window, and a title above it. Each window has a display stream associated with it (see {PageRef Fn DSPCREATE}), and either a window or its display stream can be passed interchangeably to all system functions. There are dependencies between the window and its display stream that the user should not disturb. For instance, the destination bitmap of the display stream of a window must always be the screen bitmap. The X offset, Y offset, and Clipping Region fields of the display stream should not be changed. Windows can be created by the user interactively, under program control, or may be created automatically by the system. Windows are in one of two states: "open" or "closed". In an "open" state, a window is visible on the screen (unless it is covered by other open windows or off the edge of the screen) and accessible to mouse operations. In a "closed" state, a window is not visible and not accessible to mouse operations. Any attempt to print or draw on a closed window will open it. {Begin SubSec Window Properties} {Title Window Properties} {Text {index *PRIMARY* Window properties} The behavior of a window is controlled by a set of "window properties." Some of these are used by the system. However, any arbitrary property name may be used by a user program to associate information with a window. For many applications the user will associate the structure being displayed with its window using a property. The following functions provide for reading and setting window properties: {FnDef {Name WINDOWPROP} {Args WINDOW PROP NEWVALUE} {Type nospread} {Text Returns the previous value of {arg WINDOW}'s {arg PROP} aspect. If {arg NEWVALUE} is given, (even if given as {lisp NIL}), it is stored as the new {arg PROP} aspect. Some aspects cannot be set by the user and will generate errors. Any {arg PROP} name that is not recognized is stored on a property list associated with the window. }} {FnDef {Name WINDOWADDPROP} {args WINDOW PROP ITEMTOADD FIRSTFLG} {Text {fn WINDOWADDPROP} adds a new item to a window property. If {arg ITEMTOADD} is {lisp EQ} to an element of the {arg PROP} property of the window {arg WINDOW}, nothing is added. If the current property is not a list, it is made a list before {arg ITEMTOADD} added. {fn WINDOWADDPROP} returns the previous property. If {arg FIRSTFLG} is non-{lisp NIL}, the new item goes on the front of the list; otherwise, it goes on the end of the list. If {arg FIRSTFLG} is non-{lisp NIL} and {arg ITEMTOADD} is already on the list, it is moved to the front. Many window properties ({lisp OPENFN}, {lisp CLOSEFN}, etc.) can be a list of functions. {fn WINDOWADDPROP} is useful for adding additional functions to a window property without affecting any existing functions. Note that if the order of items in a window property is important, the list can be modified using {fn WINDOWPROP}. }} {FnDef {Name WINDOWDELPROP} {args WINDOW PROP ITEMTODELETE} {Text {fn WINDOWDELPROP} deletes {arg ITEMTODELETE} from the window property {arg PROP} of {arg WINDOW} and returns the previous list if {arg ITEMTODELETE} was an element. If {arg ITEMTODELETE} was not a member of window property {arg PROP}, {lisp NIL} is returned. }} {note should have variable SYSWINDOWPROPS that is a list of all window properties used by the system} }{End SubSec Window Properties} {Begin SubSec Creating Windows} {Title Creating Windows} {Text {FnDef {Name CREATEW} {Args REGION TITLE BORDERSIZE NOOPENFLG} {Text Creates a new window. {arg REGION} indicates where and how large the window should be by specifying the exterior region of the window. The usable height and width of the resulting window will be smaller than the height and width of the region by twice the border size and further less the height of the title, if any. If {arg REGION} is {lisp NIL}, {fn GETREGION} is called to prompt the user for a region. If {arg TITLE} is non-{lisp NIL}, it is printed in the border at the top of the window. The {arg TITLE} is printed using the global display stream {var WindowTitleDisplayStream}.{index WindowTitleDisplayStream Var} Thus the height of the title will be {lisp (FONTPROP WindowTitleDisplayStream 'HEIGHT)}. If {arg BORDERSIZE} is a number, it is used as the border size. If {arg BORDERSIZE} is not a number, the window will have a border {var WBorder}{index WBorder Var} (initially 4) bits wide. If {arg NOOPENFLG} is non-{lisp NIL}, the window will not be opened, i.e. displayed on the screen. The initial X and Y positions of the window are set to the upper left corner by calling {fn MOVETOUPPERLEFT} ({PageRef Fn MOVETOUPPERLEFT}). }} {FnDef {Name DECODE.WINDOW.ARG} {Args WHERESPEC WIDTH HEIGHT TITLE BORDER NOOPENFLG} {Text This is a useful function for creating windows. {arg WHERESPEC} can be a {lisp WINDOW}, a {lisp REGION}, a {lisp POSITION} or {lisp NIL}. If {arg WHERESPEC} is a {lisp WINDOW}, it is returned. In all other cases, {fn CREATEW} is called with the arguments {arg TITLE} {arg BORDER} and {arg NOOPENFLG}. The {arg REGION} argument to {fn CREATEW} is determined from {arg WHERESPEC} as follows: If {arg WHERESPEC} is a {lisp REGION}, it is adjusted to be on the screen, then passed to {fn CREATEW}. If {arg WIDTH} and {arg HEIGHT} are numbers and {arg WHERESPEC} is a {lisp POSITION}, the region whose lower left corner is {arg WHERESPEC}, whose width is {arg WIDTH} and whose height is {arg HEIGHT} is adjusted to be on the screen, then passed to {fn CREATEW}. If {arg WIDTH} and {arg HEIGHT} are numbers and {arg WHERESPEC} is not a {lisp POSITION}, then {fn GETBOXREGION} is called to prompt the user for the position of a region that is {arg WIDTH} by {arg HEIGHT}. If {arg WIDTH} and {arg HEIGHT} are not numbers, {fn CREATEW} is given {lisp NIL} as a {lisp REGION} argument. If {arg WIDTH} and {arg HEIGHT} are used, they are used as interior dimensions for the window. }} {FnDef {Name WINDOWP} {Args X} {Text Returns {arg X} if {arg X} is a window, {lisp NIL} otherwise. }} }{End SubSec Creating Windows} {Begin SubSec Opening and Closing Windows} {Title Opening and Closing Windows} {Text {FnDef {Name OPENWP} {Args WINDOW} {Text Returns {arg WINDOW}, if {arg WINDOW} is an open window (has not been closed); {lisp NIL} otherwise. }} {FnDef {Name OPENWINDOWS} {Text Returns a list of all open windows. }} {FnDef {Name OPENW} {Args WINDOW} {Text If {arg WINDOW} is a closed window, {fn OPENW} calls the function or functions on the window property {lisp OPENFN} of {arg WINDOW}, if any. If one of the {lisp OPENFN}s is the atom {lisp DON'T}, the window will not be opened. Otherwise the window is placed on the occlusion stack of windows and its contents displayed on the screen. If {arg WINDOW} is an open window, it returns {lisp NIL}. }} {FnDef {Name CLOSEW} {Args WINDOW} {Text {fn CLOSEW} calls the function or functions on the window property {lisp CLOSEFN} of {arg WINDOW}, if any. If one of the {lisp CLOSEFN}s is the atom {lisp DON'T} or returns the atom {lisp DON'T} as a value, {fn CLOSEW} returns without doing anything further. Otherwise, {fn CLOSEW} removes {arg WINDOW} from the window stack and restores the bits it is obscuring. If {arg WINDOW} was closed, {arg WINDOW} is returned as the value. If it was not closed, (for example because its {lisp CLOSEFN} returned the atom {lisp DON'T}), {lisp NIL} is returned as the value. {arg WINDOW} can be restored in the same place with the same contents (reopened) by calling {fn OPENW} or by using it as the source of a display operation. }} {Def {Type (Window Property)} {Name OPENFN} {Text The {lisp OPENFN} window property can be a single function or a list of functions. If one of the {lisp OPENFN}s is the atom {lisp DON'T}, the window will not be opened. Otherwise, the {lisp OPENFN}s are called after a window has been opened by {fn OPENW}, with the window as a single argument. }} {Def {Type (Window Property)} {Name CLOSEFN} {Text The {lisp CLOSEFN} window property can be a single function or a list of functions that are called just before a window is closed by {fn CLOSEW}. The function(s) will be called with the window as a single argument. If any of the {lisp CLOSEFN}s are the atom {lisp DON'T}, or if the value returned by any of the {lisp CLOSEFN}s is the atom {lisp DON'T}, the window will not be closed. Note: If the {lisp CAR} of the {lisp CLOSEFN} list is a {lisp LAMBDA} word, it is treated as a single function. Note: A {lisp CLOSEFN} should not call {fn CLOSEW} on its argument. }} {note OPENFN and CLOSEFN seem gratuitously asymmetric: the VALUES of CLOSEFNs are scanned for the value DON'T, but you have to have the atom DON'T as an OPENFN (you can't compute it) The problem is that some OPENFNs might want to hack the open window. Hmmm...} }{End SubSec Opening and Closing Windows} {Begin SubSec Redisplaying Windows} {Title Redisplaying Windows} {Text {FnDef {Name REDISPLAYW} {Args WINDOW REGION ALWAYSFLG} {Text Redisplay the region {arg REGION} of the window {arg WINDOW}. If {arg REGION} is {lisp NIL}, the entire window is redisplayed. If {arg WINDOW} doesn't have a {lisp REPAINTFN} ({PageRef (Window Property) REPAINTFN}), the action depends on the value of {arg ALWAYSFLG}. If {arg ALWAYSFLG} is {lisp NIL}, {arg WINDOW} will not change and the message "Window has no REPAINTFN. Can't redisplay." will be printed in the prompt window.{index Window has no REPAINTFN. Can't redisplay. (printed in prompt window)} If {arg ALWAYSFLG} is non-{lisp NIL}, {fn REDISPLAYW} acts as if {lisp REPAINTFN} was {fn NILL}. }} {Def {Type (Window Property)} {Name REPAINTFN} {Text The {lisp REPAINTFN} window property can be a single function or a list of functions that are called to repaint parts of the window by {fn REDISPLAYW}. The {lisp REPAINTFN}s are called with two arguments: the window and the region in the coordinates of the window's display stream of the area that should be repainted. Before the {lisp REPAINTFN} is called, the clipping region of the window is set to clip all display operations to the area of interest so that the {lisp REPAINTFN} can display the entire window contents and the results will be appropriately clipped. Note: {fn CLEARW} ({PageRef Fn CLEARW}) should not be used in {lisp REPAINTFN}s because it resets the window's coordinate system. If a {lisp REPAINTFN} wants to clear its region first, it should use {fn DSPFILL} ({PageRef Fn DSPFILL}). }} }{End SubSec Redisplaying Windows} {Begin SubSec Reshaping Windows} {Title Reshaping Windows} {Text {FnDef {Name SHAPEW} {Args WINDOW NEWREGION} {Text Reshapes {arg WINDOW}. If the window property {lisp RESHAPEFN} is the atom {lisp DON'T} or a list that contains the atom {lisp DON'T}, a message is printed in the prompt window, {arg WINDOW} is not changed, and {lisp NIL} is returned. Otherwise, {lisp RESHAPEFN} window property can be a single function or a list of functions that are called when a window is reshaped, to reformat or redisplay the window contents (see below). If the {lisp RESHAPEFN} window property is {lisp NIL}, {fn RESHAPEBYREPAINTFN} is the default. If the region {arg NEWREGION} is {lisp NIL}, it prompts for a region with {fn GETREGION} ({PageRef Fn GETREGION}). When calling {fn GETREGION}, the function {fn MINIMUMWINDOWSIZE} is called to determine the minimum height and width of the window, the function {fn WINDOWREGION} is called to get the region passed as the {arg OLDREGION} argument, the window property {lisp NEWREGIONFN} is used as the {lisp NEWREGIONFN} argument and {arg WINDOW} as the {lisp NEWREGIONFNARG} argument. If the window property {lisp INITCORNERSFN} is non-{lisp NIL}, it is applied to the window, and the value is passed as the {arg INITCORNERS} argument to {fn GETREGION}, to determine the initial size of the "ghost region." These window properties allow the window to specify the regions used for interactive calls to {fn SHAPEW}. If the region {arg NEWREGION} is a {lisp REGION} and its {lisp WIDTH} or {lisp HEIGHT} less than the minimums returned by calling the function {fn MINIMUMWINDOWSIZE}, they will be increased to the minimums. If {arg WINDOW} has a window property {lisp DOSHAPEFN}, it is called, passing it {arg WINDOW} and {arg NEWREGION} (or the region returned by {fn GETREGION}). If {arg WINDOW} does not have a {lisp DOSHAPEFN} window property, the function {fn SHAPEW1} is called to reshape the window. {lisp DOSHAPEFN}s are provided to implement window groups and few users should ever write them. They are tricky to write and must call {lisp SHAPEW1} eventually. The {lisp RESHAPEFN} window property is a simpler hook into reshape operations. }} {FnDef {Name SHAPEW1} {Args WINDOW REGION} {Text Changes {arg WINDOW}'s size and position on the screen to be {arg REGION}. After clearing the region on the screen, it calls the window's {lisp RESHAPEFN}, if any, passing it three arguments: (1) {arg WINDOW}, (2) a bitmap that contains {arg WINDOW}'s previous screen image and (3) the region of {arg WINDOW}'s old image within the bitmap. }} {Def {Type (Window Property)} {Name RESHAPEFN} {Text The {lisp RESHAPEFN} window property can be a single function or a list of functions that are called when a window is reshaped by {fn SHAPEW}. If the {lisp RESHAPEFN} is {lisp DON'T} or a list containing {lisp DON'T}, the window will not be reshaped. Otherwise, the function(s) are called after the window has been reshaped, its coordinate system readjusted to the new position, the title and border displayed, and the interior filled with texture. The {lisp RESHAPEFN} should display any additional information needed to complete the window's image in the new position and shape. The {lisp RESHAPEFN} is called with four arguments: (1) the window in its reshaped form, (2) a bitmap with the image of the old window in its old shape, and (3) the region within the bitmap that contains the window's old image, and (4) the region of the screen previously occupied by this window. This function is provided so that users can reformat window contents or whatever. {fn RESHAPEBYREPAINTFN} (below) is the default and should be useful for many windows. {note DON'T handling is very inconsistent, between different xxxFNs.} }} {Def {Type (Window Property)} {Name NEWREGIONFN} {Text If {fn SHAPEW} calls {fn GETREGION} to prompt the user for a region, the value of the {lisp NEWREGIONFN} window property is passed as the {arg NEWREGIONFN} argument to {fn GETREGION} ({PageRef Fn GETREGION}). }} {Def {Type (Window Property)} {Name INITCORNERSFN} {Text If this window property is non-{lisp NIL}, it should be a function of one argument, a window, that returns a list specifying the initial corners of a "ghost region" of the form {lisp ({arg BASEX} {arg BASEY} {arg OPPX} {arg OPPY})}, where ({arg BASEX}, {arg BASEY}) describes the anchored corner of the box, and ({arg OPPX}, {arg OPPY}) describes the trackable corner. If {fn SHAPEW} calls {fn GETREGION} to prompt the user for a region, this function is applied to the window, and the list returned is passed as the {arg INITCORNERS} argument to {fn GETREGION} ({PageRef Fn GETREGION}), to specify the initial ghost region. }} {Def {Type (Window Property)} {Name DOSHAPEFN} {Text If this window property is non-{lisp NIL}, it is called by {fn SHAPEW} to reshape the window (instead of {fn SHAPEW1}). It is called with two arguments: the window and the new region. }} {FnDef {Name RESHAPEBYREPAINTFN} {Args WINDOW OLDIMAGE IMAGEREGION OLDSCREENREGION} {Text This the default window {lisp RESHAPEFN}. {arg WINDOW} is a window that has been reshaped from the screen region {arg OLDSCREENREGION} to its new region (available via {lisp (WINDOWPROP WINDOW 'REGION)}). {arg OLDIMAGE} is a bitmap that contains the image of the window from its previous location. {arg IMAGEREGION} is the region within {arg OLDIMAGE} that contains the old image. {fn RESHAPEBYREPAINTFN} {fn BITBLT}s the old region contents into the new region. If the new shape is larger in either or both dimensions, the newly exposed areas are redisplayed via calls {arg WINDOW}'s {lisp REPAINTFN} window property ({PageRef (Window Property) REPAINTFN}). {fn RESHAPEBYREPAINTFN} may call the {lisp REPAINTFN} up to four times during a single reshape. The choice of which areas of the window to remove or extend is done as follows. If {arg WINDOW}'s new region shares an edge with {arg OLDSCREENREGION}, that edge of the window image will remain fixed and any addition or reduction in that dimension will be performed on the opposite side. If {arg WINDOW} has an {lisp EXTENT} property and the newly exposed window area is outside of it, any extra will be added so as to show {lisp EXTENT} that was previously not visible. An exception to these rules is that the current X,Y position is kept visible, if it was visible before the reshape. }} }{End SubSec Reshaping Windows} {Begin SubSec Moving Windows} {Title Moving Windows} {Text {note Larry says: "ugh! Why not just (MOVEW POS)?" because MOVEPROC, for example, garbage collects too much if it creates a POS every move - rrb.} {FnDef {Name MOVEW} {Args WINDOW POSorX Y} {Text Moves {arg WINDOW} to the position specified by {arg POSorX} and {arg Y} according to the following rules: If {arg POSorX} is {lisp NIL}, {fn GETBOXPOSITION} ({PageRef Fn GETBOXPOSITION}) is called to read a position from the user. If {arg WINDOW} has a {lisp CALCULATEREGION} window property, it will be called with {arg WINDOW} as an argument and should return a region which will be used to prompt the user with. If {arg WINDOW} does not have a {lisp CALCULATEREGION} window property, the region of {arg WINDOW} is used to prompt with. If {arg POSorX} is a {lisp POSITION}, {arg POSorX} is used. If {arg POSorX} and {arg Y} are both {lisp NUMBERP}, a position is created using {arg POSorX} as the {lisp XCOORD} and {arg Y} as the {lisp YCOORD}. If {arg POSorX} is a {lisp REGION}, a position is created using its {lisp LEFT} as the {lisp XCOORD} and {lisp BOTTOM} as the {lisp YCOORD}. If {arg WINDOW} is not open and {arg POSorX} is non-{lisp NIL}, the window will be moved without being opened. Otherwise, it will be opened. If {arg WINDOW} has the atom {lisp DON'T} as a {lisp MOVEFN} window property, the window will not be moved. If {arg WINDOW} has any other non-{lisp NIL} value as a {lisp MOVEFN} property, it should be a function or list of functions that will be called before the window is moved with the {arg WINDOW} and the new positon as its arguments. If it returns the atom {lisp DON'T}, the window will not be moved. If it returns a position, the window will be moved to that position instead of the new one. If there are more than one {lisp MOVEFN}s, the last one to return a value is the one that determines where the window is moved to. If {arg WINDOW} is moved and {arg WINDOW} has an {lisp AFTERMOVEFN} window property, it should be a function or a list of functions that will be called after the window is moved with {arg WINDOW} as an argument. {fn MOVEW} returns the new position, or {lisp NIL} if the window could not be moved. Note: If {fn MOVEW} moves any part of the window from off-screen onto the screen, that part is redisplayed (by calling {fn REDISPLAYW}). }} {FnDef {Name RELMOVEW} {Args WINDOW POSITION} {Text Like {fn MOVEW} for moving windows but the {arg POSITION} is interpreted relative to the current position of {arg WINDOW}. Example: The following code moves {arg WINDOW} to the right one screen point. {lispcode (RELMOVEW {arg WINDOW} (create POSITION XCOORD _ 1 YCOORD _ 0))} }} {Def {Type (Window Property)} {Name CALCULATEREGION} {Text If {fn MOVEW} calls {fn GETBOXPOSITION} to prompt the user for a region, the {lisp CALCULATEREGION} window property is called (passing the window as an argument. The {lisp CALCULATEREGION} should returns a region to be used to prompt the user with. If {lisp CALCULATEREGION} is {lisp NIL}, the region of the window is used to prompt with. }} {Def {Type (Window Property)} {Name MOVEFN} {Text If the {lisp MOVEFN} is {lisp DON'T}, the window will not be moved by {fn MOVEW}. Otherwise, if the {lisp MOVEFN} is non-{lisp NIL}, it should be a function or a list of functions that will be called before a window is moved with two arguments: the window being moved and the new position of the lower left corner in screen coordinates. If the {lisp MOVEFN} returns {lisp DON'T}, the window will not be moved. If the {lisp MOVEFN} returns a {lisp POSITION}, the window will be moved to that position. Otherwise, the window will be moved to the specified new position. }} {Def {Type (Window Property)} {Name AFTERMOVEFN} {Text If non-{lisp NIL}, it should be a function or a list of functions that will be called after the window is moved (by {fn MOVEW}) with the window as an argument. }} }{End SubSec Moving Windows} {Begin SubSec Exposing and Burying Windows} {Title Exposing and Burying Windows} {Text {FnDef {Name TOTOPW} {Args WINDOW NOCALLTOTOPFNFLG} {Text Brings {arg WINDOW} to the top of the stack of overlapping windows, guaranteeing that it is entirely visible. If {arg WINDOW} is closed, it is opened. This is done automatically whenever a printing or drawing operation occurs to the window. If {arg NOCALLTOTOPFNFLG} is {lisp NIL}, the {lisp TOTOPFN} of {arg WINDOW} is called ({PageRef (Window Property) TOTOPFN}). If {arg NOCALLTOTOPFNFLG} is {lisp T}, it is not called, which allows a {lisp TOTOPFN} to call {fn TOTOPW} without causing an infinite loop. }} {FnDef {Name BURYW} {Args WINDOW} {Text Puts {arg WINDOW} on the bottom of the stack by moving all the windows that it covers in front of it. }} {Def {Type (Window Property)} {Name TOTOPFN} {Text If non-{lisp NIL}, whenever the window is brought to the top, the {lisp TOTOPFN} is called (with the window as a single argument). This function may be used to bring a collection of windows to the top together. If the {arg NOCALLTOPWFN} argument of {fn TOTOPW} is non-{lisp NIL}, the {lisp TOTOPFN} of the window is not called, which provides a way of avoiding infinite loops when using {fn TOTOPW} from within a {lisp TOTOPFN}. }} }{End SubSec Exposing and Burying Windows} {Begin SubSec Shrinking Windows Into Icons} {Title Shrinking Windows Into Icons} {Text {index *PRIMARY* Icons} {index *PRIMARY* Shrinking windows} Occasionally, a user will have a number of large windows on the screen, making it difficult to access those windows being used. To help with the problem of screen space management, the Interlisp-D window system allows the creation of {it Icons}. An icon is a small rectangle (containing text or a bitmap) which is a "shrunken-down" form of a particular window. Using the {lisp Shrink} and {lisp Expand} window menu commands ({PageRef (Window Menu Command) Shrink}), the user can shrink windows not currently being used into icons, and quickly restore the original windows at any time. This facility is controlled by the following functions and window properties: {FnDef {Name SHRINKW} {Args WINDOW TOWHAT ICONPOSITION EXPANDFN} {Text {fn SHRINKW} makes a small icon which represents {arg WINDOW} and removes {arg WINDOW} from the screen. Icons have a different window command menu that contains "{lisp EXPAND}" instead of "{lisp SHRINK}". The {lisp EXPAND} command calls {fn EXPANDW} which returns the shrunken window to its original size and place. The icon can also be moved by pressing the {lisp LEFT} button in it, or expanded by pressing the {lisp MIDDLE} button in it. The {lisp SHRINKFN} property of the window {arg WINDOW} affects the operation of {fn SHRINKW}. If the {lisp SHRINKFN} property of {arg WINDOW} is the atom {lisp DON'T}, {fn SHRINKW} returns. Otherwise, the {lisp SHRINKFN} property of the window is treated as a (list of) function(s) to apply to {arg WINDOW}; if any returns the atom {lisp DON'T}, {fn SHRINKW} returns. {arg TOWHAT}, if given, indicates the image the icon window will have. If {arg TOWHAT} is a string, atom or list, the icon's image will be that string (currently implemented as a title-only window with {arg TOWHAT} as the title.) If {arg TOWHAT} is a {lisp BITMAP}, the icon's image will be a copy of the bitmap. If {arg TOWHAT} is a {lisp WINDOW}, that window will be used as the icon. If {arg TOWHAT} is not given (as is the case when invoked from the {lisp SHRINK} window command), then the following apply in turn: (1) If the window has an {lisp ICONFN} property, it gets called with the two arguments {arg WINDOW} and {arg OLDICON}, where {arg WINDOW} is the window being shrunk and {arg OLDICON} is the previously created icon, if any. The {lisp ICONFN} should return one of the {arg TOWHAT} entities described above or return the {arg OLDICON} if it does not want to change it. (2) If the window has an {lisp ICON} property, it is used as the value of {arg TOWHAT}. (3) If the window has neither an {lisp ICONFN} or {lisp ICON} property, the icon will be {arg WINDOW}'s title or, if {arg WINDOW} doesn't have a title, the date and time of the icon creation. {arg ICONPOSITION} gives the position that the new icon will be on the screen. If it is {lisp NIL}, the icon will be in the corner of the window furthest from the center of the screen. In all but the default case, the icon is cached on the property {lisp ICONWINDOW} of {arg WINDOW} so repeating {fn SHRINKW} reuses the same icon (unless overridden by the {lisp ICONFN} described above). Thus to change the icon it is necessary to remove the {lisp ICONWINDOW} property or call {fn SHRINKW} explicitly giving a {arg TOWHAT} argument. }} {Fndef {name EXPANDW} {args ICONW} {text Restores the window for which {arg ICONW} is an icon, and removes the icon from the screen. If the {lisp EXPANDFN} window property of the main window is the atom {lisp DON'T}, the window won't be expanded. Otherwise, the window will be restored to its original size and location and the {lisp EXPANDFN} (or list of functions) will be applied to it. }} {Def {Type (Window Property)} {Name SHRINKFN} {Text The {lisp SHRINKFN} window property can be a single function or a list of functions that are called just before a window is shrunken by {fn SHRINKW}, with the window as a single argument. If any of the {lisp SHRINKFN}s are the atom {lisp DON'T}, or if the value returned by any of the {lisp SHRINKFN}s is the atom {lisp DON'T}, the window will not be shrunk. }} {Def {Type (Window Property)} {Name ICONFN} {Text If {fn SHRINKW} is called without begin given a {arg TOWHAT} argument (as is the case when invoked from the {lisp SHRINK} window command) and the window's {lisp ICONFN} property is non-{lisp NIL}, then it gets called with two arguments, the window being shrunk and the previously created icon, if any. The {lisp ICONFN} should return one of the {arg TOWHAT} entities described above or return the previously created icon if it does not want to change it. }} {Def {Type (Window Property)} {Name ICON} {Text If {fn SHRINKW} is called without being given a {arg TOWHAT} argument, the window's {lisp ICONFN} property is {lisp NIL}, and the {lisp ICON} property is non-{lisp NIL}, then it is used as the value of {arg TOWHAT}. }} {Def {Type (Window Property)} {Name ICONWINDOW} {Text Whenever an icon is created, it is cached on the property {lisp ICONWINDOW} of the window, so calling {fn SHRINKW} again will reuse the same icon (unless overridden by the {lisp ICONFN}. Thus, to change the icon it is necessary to remove the {lisp ICONWINDOW} property or call {fn SHRINKW} ({PageRef Fn SHRINKW}) explicitly giving a {arg TOWHAT} argument. }} {Def {Type (Window Property)} {Name EXPANDFN} {Text The {lisp EXPANDFN} window property can be a single function or a list of functions. If one of the {lisp EXPANDFN}s is the atom {lisp DON'T}, the window will not be expanded. Otherwise, the {lisp EXPANDFN}s are called after the window has been expanded by {fn EXPANDW}, with the window as a single argument. }} }{End SubSec Shrinking Windows Into Icons} {Begin SubSec Coordinate Systems, Extents, And Scrolling} {Title Coordinate Systems, Extents, And Scrolling} {Text {index *PRIMARY* Coordinate Systems} {index *PRIMARY* Extents} {index *PRIMARY* Scrolling} Note: The word "scrolling" has two distinct meanings when applied to Interlisp-D windows. This section documents the use of "scroll bars" on the left and bottom of a window to move an object displayed in the window. "Scrolling" also describes the feature where trying to print text off the bottom of a window will cause the contents to "scroll up." This second feature is controlled by the function {fn DSPSCROLL} ({PageRef Fn DSPSCROLL}. One way of thinking of a window is as a "view" onto an object (e.g. a graph, a file, a picture, etc.) The object has its own natural coordinate system in terms of which its subparts are laid out. When the window is created, the X Offset and Y Offset of the window's display stream are set to map the origin of the object's coordinate system into the lower left point of the window's interior region. At the same time, the Clipping Region of the display stream is set to correspond to the interior of the window. From then on, the display stream's coordinate system is translated and its clipping region adjusted whenever the window is moved, scrolled or reshaped. There are several distinct regions associated with a window viewing an object. First, there is a region in the window's coordinate system that contains the complete image of the object. This region (which can only be determined by application programs with knowledge of the "semantics" of the object) is stored as the {lisp EXTENT}{index EXTENT (Window Property)} property of the window (below). Second, the clipping region of the display stream (obtainable with the function {fn DSPCLIPPINGREGION}, {PageRef Fn DSPCLIPPINGREGION}) specifies the portion of the object that is actually visible in the window. This is set so that it corresponds to the interior of the window (not including the border or title). Finally, there is the region on the screen that specifies the total area that the window occupies, including the border and title. This region (in screen coordinates) is stored as the {lisp REGION}{index REGION (Window Property)} property of the window ({PageRef (Window Property) REGION}). The window system supports the idea of scrolling the contents of a window. Scrolling regions are on the left and the bottom edge of each window. The {lisp LEFT} key is used to indicate upward or leftward scrolling by the amount necessary to move the selected position to the top or the left edge. The {lisp RIGHT} key is used to indicate downward or rightward scrolling by the amount necessary to move the top or left edge to the selected position. The {lisp MIDDLE} key is used to indicate global placement of the object within the window (similar to "thumbing" a book). In the scroll region, the part of the object that is being viewed by the window is marked with a gray shade. If the whole scroll bar is thought of as the entire object, the shaded portion is the portion currently being viewed. This will only occur when the window "knows" how big the object is (see window property {index EXTENT (Window Property)}{lisp EXTENT}, {PageRef (Window Property) EXTENT}). When the button is released in a scroll region, the function {lisp SCROLLW} is called. {lisp SCROLLW} calls the scrolling function associated with the window to do the actual scrolling and provides a programmable entry to the scrolling operation. {FnDef {Name SCROLLW} {Args WINDOW DELTAX DELTAY CONTINUOUSFLG} {Text Calls the {lisp SCROLLFN} window property of the window {arg WINDOW} with arguments {arg WINDOW}, {arg DELTAX}, {arg DELTAY} and {arg CONTINUOUSFLG}. See {lisp SCROLLFN} window property, {PageRef (Window Property) SCROLLFN}. }} {FnDef {Name SCROLL.HANDLER} {Args WINDOW} {Text This is the function that tracks the mouse while it is in the scroll region. It is called when the cursor leaves a window in either the left or downward direction. If {arg WINDOW} does not have a scroll region for this direction (e.g. the window has moved or reshaped since it was last scrolled), a scroll region is created that is {var SCROLLBARWIDTH}{index SCROLLBARWIDTH Var} wide. It then waits for {var SCROLLWAITTIME}{index SCROLLWAITTIME Var} milliseconds and if the cursor is still inside the scroll region, it opens a window the size of the scroll region and changes the cursor to indicate the scrolling is taking place. When a button is pressed, the cursor shape is changed to indicate the type of scrolling (up, down, left, right or thumb). After the button is held for {var WAITBEFORESCROLLTIME}{index WAITBEFORESCROLLTIME Var} milliseconds, until the button is released {lisp SCROLLW} is called each {var WAITBETWEENSCROLLTIME}{index WAITBETWEENSCROLLTIME Var} milliseconds. These calls are made with the {arg CONTINUOUSFLG} argument set to {lisp T}. If the button is released before {var WAITBEFORESCROLLTIME} milliseconds, {lisp SCROLLW} is called with the {arg CONTINUOUSFLG} argument set to {lisp NIL}. The arguments passed to {lisp SCROLLW} depend on the mouse button. If the {lisp LEFT} button is used in the vertical scroll region, {arg DY} is distance from cursor position at the time the button was released to the top of the window and {arg DX} is 0. If the {lisp RIGHT} button is used, the inverse of this quantity is used for {arg DY} and 0 for {arg DX}. If the {lisp LEFT} button is used in the horizontal scroll region, {arg DX} is distance from cursor position to left of the window and {arg DY} is 0. If the {lisp RIGHT} button is used, the inverse of this quantity is used for {arg DX} and 0 for {arg DY}. If the {lisp MIDDLE} button is pressed, the distance argument to {fn SCROLLW} will be a {lisp FLOATP} between 0.0 and 1.0 that indicates the proportion of the distance the cursor was from the left or top edge to the right or bottom edge. Note: The scrolling regions will not come up if the window has a {lisp SCROLLFN}{index SCROLLFN (Window Property)} window property of {lisp NIL}, has a non-{lisp NIL} {lisp NOSCROLLBARS}{index NOSCROLLBARS (Window Property)} window property, or if its {lisp SCROLLEXTENTUSE} ({PageRef (Window Property) SCROLLEXTENTUSE}) property has certain values and its {lisp EXTENT} is fully visible. }} {FnDef {Name SCROLLBYREPAINTFN} {Args WINDOW DELTAX DELTAY CONTINUOUSFLG} {Text {fn SCROLLBYREPAINTFN} is the standard scrolling function which should be used as the {lisp SCROLLFN}{index SCROLLFN (Window Property)} property for most scrolling windows. This function, when used as a {lisp SCROLLFN}, {fn BITBLT}s the bits that will remain visible after the scroll to their new location, fills the newly exposed area with texture, adjusts the window's coordinates and then calls the window's {lisp REPAINTFN} on the newly exposed region. Thus this function will scroll any window that has a repaint function. If {arg WINDOW} has an {lisp EXTENT}{index EXTENT (Window Property)} property ({PageRef (Window Property) EXTENT}), {fn SCROLLBYREPAINTFN} will limit scrolling in the X and Y directions according to the value of the window property {lisp SCROLLEXTENTUSE}{index SCROLLEXTENTUSE (Window Property)} ({PageRef (Window Property) SCROLLEXTENTUSE}). If {arg DELTAX} or {arg DELTAY} is a {lisp FLOATP}, {fn SCROLLBYREPAINTFN} will position the window so that its top or left edge will be positioned at that proportion of its {lisp EXTENT}. If the window does not have an {lisp EXTENT}, {fn SCROLLBYREPAINTFN} will do nothing. If {arg CONTINUOUSFLG} is non-{lisp NIL}, this indicates that the scrolling button is being held down. In this case, {fn SCROLLBYREPAINTFN} will scroll the distance of one linefeed height (as returned by {fn DSPLINEFEED}, {PageRef Fn DSPLINEFEED}). }} Scrolling is controlled by the following window properties: {Def {Type (Window Property)} {Name EXTENT} {Text Used to limit scrolling operations. Accesses the extent region of the window. If non-{lisp NIL}, the {lisp EXTENT} is a region in the window's display stream that contains the complete image of the object being viewed by the window. User programs are responsible for updating the {lisp EXTENT}. The functions {fn UNIONREGIONS}, {fn EXTENDREGION}, etc. ({PageRef Fn UNIONREGIONS}) are useful for computing a new extent region. In some situations, it is useful to define an {lisp EXTENT} that only exists in one dimension. This may be done by specifying an {lisp EXTENT} region with a width or height of {lisp -1}. {lisp SCROLLFN} handling recognizes this situation as meaning that the negative {lisp EXTENT} dimension is unknown. {note will UNIONREGIONS, EXTENDREGION handle these types of regions correctly?} }} {Begin Note} Comment from Larry: using -1 for the special case in EXTENTs (signifying no extent in a particular dimension) is a crock. Why not use NIL or MAX.INTEGER? Date: 6 Oct. 1982 12:31 pm PDT (Wednesday) From: KAPLAN.PA Comment on (11): -1 for EXTENT. The point is to have a distinguished value that means that the extent of the region is defined in only one dimension. MAX.INTEGER is not a particularly distinctive value, and it confuses the clear semantic distinction between "unknown" and "known to be very large". NIL is OK as an external indicator, except that some other code (like -1) would have to be stored internally if we ever went to a datatype representation for regions. In sum: I wouldn't mind NIL instead of -1, though I don't have any strong feelings about it. I vote against the MAX.INTEGER proposal. {End Note} {Def {Type (Window Property)} {Name SCROLLFN} {Text If the {lisp SCROLLFN} property is {lisp NIL}, the window will not scroll. Otherwise, it should be a function of four arguments: (1) the window being scrolled, (2) the distance to scroll in the horizontal direction (positive to right, negative to left), (3) the distance to scroll in the vertical direction (positive up, negative down), and (4) a flag which is {lisp T} if the scrolling button is being held down. For more information, see {fn SCROLL.HANDLER} ({PageRef Fn SCROLL.HANDLER}). For most scrolling windows, the {lisp SCROLLFN} function should be {fn SCROLLBYREPAINTFN} ({PageRef Fn SCROLLBYREPAINTFN}). }} {Def {Type (Window Property)} {Name NOSCROLLBARS} {Text If the {lisp NOSCROLLBARS} property is non-{lisp NIL}, scroll bars will not be brought up for this window. This disables mouse-driven scrolling of a window. This window can still be scrolled using {fn SCROLLW} ({PageRef Fn SCROLLW}). }} {Def {Type (Window Property)} {Name SCROLLEXTENTUSE} {Text {fn SCROLLBYREPAINTFN} uses the {lisp SCROLLEXTENTUSE} window property to limit how far scrolling can go in the X and Y directions. The possible values for {lisp SCROLLEXTENTUSE} and their interpretations are: {Begin LabeledList Possible Values of SCROLLEXTENTUSE} {Label {lisp NIL}} {Text This will keep the extent region visible or near visible. It will not scroll the window so that the top of the extent is below the top of the window, the bottom of the extent is more than one point above the top of the window, the left of the extent is to the right of the window and the right of the extent is to the left of the window. The {lisp EXTENT} can be scrolled to just above the window to provide a way of "hiding" the contents of a window. In this mode the extent is either in the window or just of the top of the window. } {Label {lisp T}} {Text The extent is not used to control scrolling. The user can scroll the window to anywhere. Having the {LISP EXTENT} window property does all thumb scrolling to be supported so that the user can get back to the EXTENT by thumb scrolling. } {Label {lisp LIMIT}} {Text This will keep the extent region visible. The window is only allowed to view within the extent. } {Label {lisp +}} {Text This will keep the extent region visible or just off in the positive direction in either X or Y (i.e. the image will be either be visible or just off to the top and/or right.) } {Label {lisp -}} {Text This will keep the extent region visible or just off in the negative direction in either X or Y (i.e. the image will be either be visible or just off to the left and/or bottom). } {Label {lisp +-}} {Label {lisp -+}} {Text This will keep the extent region visible or just off in the window (i.e. the image will be either be visible or just off to the left, bottom, top or right). } {Label {lisp ({arg XBEHAVIOR} . {arg YBEHAVIOR})}} {Text If the {lisp SCROLLEXTENTUSE} is a list, the {fn CAR} is interpreted as the scrolling limit in the X behavior and the {fn CDR} as the scrolling limit in the Y behavior. {arg XBEHAVIOR} and {arg YBEHAVIOR} should each be one of the atoms {lisp (NIL T LIMIT + - +- -+)}. The interpretations of the atoms is the same as above except that {lisp NIL} is equivalent to {lisp LIMIT}. } {End LabeledList Possible Values of SCROLLEXTENTUSE} Note: The {lisp NIL} value of {lisp SCROLLEXTENTUSE} is equivalent to {lisp (LIMIT . +)}. Example: If the {lisp SCROLLEXTENTUSE} window property of a window (with an extent defined) is {lisp (LIMIT . T)}, the window will scroll uncontrolled in the Y dimension but be limited to the extent region in the X dimension. }} }{End SubSec Coordinate Systems, Extents, And Scrolling} {Begin SubSec Mouse Activity in Windows} {Title Mouse Activity in Windows} {Text The following window properties allow the user to control the response to mouse activity in a window. The value of these properties, if non-{lisp NIL}, should be a function that will be called (with the window as argument) when the specified event occurs. Note: these functions should be "self-contained", communicating with the outside world solely via their window argument, e.g., by setting window properties. In particular, these functions should not expect to access variables bound on the stack, as the stack context is formally undefined at the time these functions are called. Since the functions are invoked asynchronously, they perform any terminal input/output operations from their own window. {Def {Type (Window Property)} {Name WINDOWENTRYFN} {Text Whenever a button goes down in the window and the process associated with the window is not the tty process, the {lisp WINDOWENTRYFN} is called. The default is {lisp GIVE.TTY.PROCESS} ({PageRef Fn GIVE.TTY.PROCESS}) which gives the process associated with the window the tty and calls the {lisp BUTTONEVENTFN}. {lisp WINDOWENTRYFN} can be a list of functions and all will be called. }} {Def {Type (Window Property)} {Name CURSORINFN} {Text Whenever the mouse moves into the window, the {lisp CURSORINFN} is called. If {lisp CURSORINFN} is a list of functions, all will be called. }} {Def {Type (Window Property)} {Name CURSOROUTFN} {Text The {lisp CURSOROUTFN} is called when the cursor leaves the window. If {lisp CURSOROUTFN} is a list of functions, all will be called. }} {Def {Type (Window Property)} {Name CURSORMOVEDFN} {Text The {lisp CURSORMOVEDFN} is called whenever the cursor has moved and is inside the window. {lisp CURSORMOVEDFN} can be a list of functions and all will be called. This allows a window function to implement "active" regions within itself by having its {lisp CURSORMOVEDFN} determine if the cursor is in a region of interest, and if so, perform some action. }} {Def {Type (Window Property)} {Name BUTTONEVENTFN} {Text The {lisp BUTTONEVENTFN} is called whenever there is a change in the state (up or down) of the mouse buttons inside the window. Changes to the mouse state while the {lisp BUTTONEVENTFN} is running will not be interpreted as new button events, and the {lisp BUTTONEVENTFN} will not be re-invoked. }} {Def {Type (Window Property)} {Name RIGHTBUTTONFN} {Text The {lisp RIGHTBUTTONFN} is called in lieu of the standard window menu operation {lisp (DOWINDOWCOM)} when the {lisp RIGHT} key is depressed in a window. More specifically, the {lisp RIGHTBUTTONFN} is called instead of the {lisp BUTTONEVENTFN} when {lisp (MOUSESTATE (ONLY RIGHT))}. If the {lisp RIGHT} key is to be treated like any other key in a window, supply {lisp RIGHTBUTTONFN} and {lisp BUTTONEVENTFN} with the same function. When an application program defines its own {lisp RIGHTBUTTONFN}, there is a convention that the default {lisp RIGHTBUTTONFN}, {fn DOWINDOWCOM} ({PageRef Fn DOWINDOWCOM}), may be executed by depressing the {lisp RIGHT} key when the cursor is in the header or border of a window. User {lisp RIGHTBUTTONFN}s are encouraged to follow this convention, by calling {fn DOWINDOWCOM} if the cursor is not in the interior region of the window. }} {VarDef {Name BACKGROUNDBUTTONEVENTFN} } {VarDef {Name BACKGROUNDCURSORINFN} } {VarDef {Name BACKGROUNDCURSOROUTFN} } {VarDef {Name BACKGROUNDCURSORMOVEDFN} {Text These variables provide a way of taking action when there is cursor action and the cursor in in the background. They are interpreted like the corresponding window properties. If set to the name of a function, that function will be called, respectively, whenever the cursor is in the background and a button changes, when the cursor moves into the background from a window, when the cursor moved from the background into a window and when the cursor moves from one place in the background to another. }} }{End SubSec Mouse Activity in Windows} {Begin SubSec Terminal I/O and Page Holding} {Title Terminal I/O and Page Holding} {Text Each process has its own terminal i/o stream (accessed as the stream {lisp T}, {PageRef Term Terminal Streams}). The terminal i/o stream for the current process can be changed to point to a window by using the function {fn TTYDISPLAYSTREAM}, so that output and echoing of type-in is directed to a window. {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 Clipping Region. The line length of {fn TTYDISPLAYSTREAM} is computed (like any other display stream) from its Left Margin, Right Margin, and Font. If one of these fields is changed, its line length is recalculated. If one of the fields used to compute the number of lines (such as the Clipping Region 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. }} {index *PRIMARY* Page holding in windows} {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. 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. }} {Def {Type (Window Property)} {Name PAGEFULLFN} {Text If the {lisp PAGEFULLFN} window property is non-{lisp NIL}, it will be called with the window as a single argument when the window is full (i.e., when enough has been printed since the last {lisp TTY} interaction so that the next character printed will cause information to be scrolled off the top of the window.) If the {lisp PAGEFULLFN} window property is {lisp NIL}, the system function {fn PAGEFULLFN}{index PAGEFULLFN Fn} is called. {fn PAGEFULLFN} simply returns if there are characters in the type-in buffer for {arg WINDOW}, otherwise it inverts the window and waits for the user to type a character. {fn PAGEFULLFN} is user advisable. Note: The {lisp PAGEFULLFN} window property is only called on windows which are the {fn TTYDISPLAYSTREAM} of some process. }} }{End SubSec Terminal I/O and Page Holding} {Begin SubSec The TTY Process and the Caret} {Title The TTY Process and the Caret} {Text {index TTY process} At any time, one process is designated as the TTY process, which is used for accepting keyboard input. The TTY process can be changed to a given process by calling {lisp GIVE.TTY.PROCESS} ({PageRef Fn GIVE.TTY.PROCESS}), or by clicking the mouse in a window associated with the process. The latter mechanism is implemented with the following window property: {Def {Type (Window Property)} {Name PROCESS} {Text If the {lisp PROCESS} window property is non-{lisp NIL}, it should be a {lisp PROCESS} and will be made the TTY process by {lisp GIVE.TTY.PROCESS} ({PageRef Fn GIVE.TTY.PROCESS}), the default {lisp WINDOWENTRYFN} property ({PageRef (Window Property) WINDOWENTRYFN}). This implements the mechanism by which the keyboard is associated with different processes. }} {index *PRIMARY* Carets} The window system uses a flashing caret (88llÆ) to indicate the position of the next window typeout. There is only one caret visible at any one time. The caret in the current TTY process is always visible; if it is hidden by another window, its window is brought to the top. An exception to this rule is that the flashing caret's window is not brought to the top if the user is buttoning or has a shift key down. This prevents the destination window (which has the tty and caret flashing) from interfering with the window one is trying to select text to copy from. {FnDef {Name CARET} {Args NEWCARET} {Text Sets the shape that blinks at the location of the next output to the current process. {arg NEWCARET} should be one of the following: {Begin LabeledList NEWCARET arg} {Label a {lisp CURSOR} object} {Text If {arg NEWCARET} is a {lisp CURSOR} object (see {PageRef Fn CURSORCREATE}), it is used to give the new caret shape } {Label {lisp OFF}} {Text Turns the caret off } {Label {lisp NIL}} {Text The caret is not changed. {fn CARET} returns a {lisp CURSOR} representing the current caret } {Label {lisp T}} {Text Reset the caret to the value of {var DEFAULTCARET}.{index DEFAULTCARET Var} {var DEFAULTCARET} can be set to change the initial caret for new processes. } {End LabeledList NEWCARET arg} 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 OFFRATE} is {lisp NIL} then it is set to be the same as {arg ONRATE}. If {arg ONRATE} is {lisp T}, both the "on" and "off" times are set to the value of the variable {var DEFAULTCARETRATE}{index DEFAULTCARETRATE Var} (initially 333). The previous value of {fn CARETRATE} is returned. If the caret is off, {fn CARETRATE} return NIL. }} }{End SubSec The TTY Process and the Caret} {Begin SubSec Miscellaneous Window Functions} {Title Miscellaneous Window Functions} {Text {FnDef {Name CLEARW} {Args WINDOW} {Text Fills {arg WINDOW} with its background texture, changes its coordinate system so that the origin is the lower left corner of the window, sets its X position to the left margin and sets its Y position to the base line of the uppermost line of text, ie. the top of the window less the font ascent. }} {Fndef {name INVERTW} {args WINDOW SHADE} {text Fills the window {ARG WINDOW} with the texture {arg SHADE} in {lisp INVERT} mode. If {arg SHADE} is {lisp NIL}, {var BLACKSHADE} is used. {fn INVERTW} returns {arg WINDOW} so that it can be used inside {fn RESETFORM}. }} {Fndef {name FLASHWINDOW} {args WIN? N FLASHINTERVAL SHADE} {text Flashes the window {arg WIN?} by "inverting" it twice. {arg N} is the number of times to flash the window (default is 1). {arg FLASHINTERVAL} is the length of time in milliseconds to wait between flashes (default is 200). {arg SHADE} is the shade that will be used to invert the window (default is {var BLACKSHADE}). If {arg WIN?} is {lisp NIL}, the whole screen is flashed. In this case, the {arg SHADE} argument is ignored (can only invert the screen). }} {FnDef {Name WHICHW} {Args X Y} {Text Returns the window which contains the position in screen coordinates of {arg X} if {arg X} is a {lisp POSITION}, the position ({arg X},{arg Y}) if {arg X} and {arg Y} are numbers, or the position of the cursor if {arg X} is {lisp NIL}. Returns {lisp NIL} if the coordinates are not in any window. If they are in more than one window, it returns the uppermost. Example: {lisp (WHICHW)} returns the window that the cursor is in. }} {note Larry says: "Ugh! Bad function name. How about using 'GETWINDOW'? Bill seconds the motion.} {FnDef {Name DECODE/WINDOW/OR/DISPLAYSTREAM} {Args DSORW WINDOWVAR TITLE BORDER} {Text Returns a display stream as determined by the {arg DSORW} and {arg WINDOWVAR} arguments. If {arg DSORW} is a display stream, it is returned. If {arg DSORW} is a window, its display stream is returned. If {arg DSORW} is {lisp NIL}, the litatom {arg WINDOWVAR} is evaluated. If its value is a window, its display stream is returned. If its value is not a window, {arg WINDOWVAR} is set to a newly created window (prompting user for region) whose display stream is then returned. If {arg DSORW} is {lisp NEW}, the display stream of a newly created window is returned. If a window is involved in the decoding, it is opened and if {arg TITLE} or {arg BORDER} are given, the {lisp TITLE} or {lisp BORDER} property of the window are reset. The {arg DSORW}={lisp NIL} case is most useful for programs that want to display their output in a window, but want to reuse the same window each time they are called. The non-{lisp NIL} cases are good for decoding a display stream argument passed to a function. }} {FnDef {Name WIDTHIFWINDOW} {Args INTERIORWIDTH BORDER} {Text Returns the width of the window necessary to have {arg INTERIORWIDTH} points in its interior if the width of the border is {arg BORDER}. If {arg BORDER} is {lisp NIL}, the default border size {var WBorder}{index WBorder Var} is used. }} {FnDef {Name HEIGHTIFWINDOW} {Args INTERIORHEIGHT TITLEFLG BORDER} {Text Returns the height of the window necessary to have {arg INTERIORHEIGHT} points in its interior with a border of {arg BORDER} and, if {arg TITLEFLG} is non-{lisp NIL}, a title. If {arg BORDER} is {lisp NIL}, the default border size {var WBorder}{index WBorder Var} is used. }} {fn WIDTHIFWINDOW} and {fn HEIGHTIFWINDOW} are useful for calculating the width and height for a call to {fn GETBOXPOSITION} for the purpose of positioning a prospective window. {FnDef {Name MINIMUMWINDOWSIZE} {Args WINDOW} {Text Returns a dotted pair, the {lisp CAR} of which is the minimum width {arg WINDOW} needs and the {lisp CDR} or which is the minimum height {arg WINDOW} needs. The minimum size is determined by the value of the window property {lisp MINSIZE}{index MINSIZE (Window Property)} of {arg WINDOW}. If the value of the {lisp MINSIZE} window property is {lisp NIL}, the width is 26 and the height is the height {arg WINDOW} needs to have its title, border and one line of text visible. If {lisp MINSIZE} is a dotted pair, it is returned. If it is a litatom, it should be a function which is called with {lisp WINDOW} as its first argument, which should return a dotted pair. }} }{End SubSec Miscellaneous Window Functions} {Begin SubSec Miscellaneous Window Properties} {Title Miscellaneous Window Properties} {Text {Def {Type (Window Property)} {Name TITLE} {Text Accesses the title of the window. If a title is added to a window whose title is {lisp NIL} or the title is removed (set to {lisp NIL}) from a window with a title, the window's exterior (its region on the screen) is enlarged or reduced to accomodate the change without changing the window's interior. For example, {lisp (WINDOWPROP {arg WINDOW} 'TITLE "Results")} changes the title of {arg WINDOW} to be "Results". {lisp (WINDOWPROP {arg WINDOW} 'TITLE NIL)} removes the title of {arg WINDOW}. }} {Def {Type (Window Property)} {Name BORDER} {Text Accesses the width of the border of the window. The border will have at most 2 point of white (but never more than half) and the rest black. The default border is the value of the global variable {var WBorder}{index WBorder Var} (initially 4). }} {Def {Type (Window Property)} {Name WINDOWTITLESHADE} {Text Accesses the window title shade of the window. If non-{lisp NIL}, it should be a texture which is used as the "backgound texture" for the title bar on the top of the window. If it is {lisp NIL}, the value of the global variable {var WINDOWTITLESHADE}{index WINDOWTITLESHADE Var} (initially {var BLACKSHADE}) is used. Note that black is always used as the background of the title printed in the title bar, so that the letters can be read. The remaining space is painted with the "title shade". }} {Def {Type (Window Property)} {Name HARDCOPYFN} {Text If non-{lisp NIL}, it should be a function that is called by the window menu command {lisp Hardcopy} ({PageRef (Window Menu Command) Hardcopy}) to print the contents of a window. The {lisp HARDCOPYFN} property is called with two arguments, the window and an image stream to print to. If the window does not have a {lisp HARDCOPYFN}, the bitmap image of the window (including the border and title) are printed on the file or printer. }} {Def {Type (Window Property)} {Name DSP} {Text Value is the display stream of the window. All system functions will operate on either the window or its display stream. This window property cannot be changed using {fn WINDOWPROP}. }} {Def {Type (Window Property)} {Name HEIGHT}} {Def {Type (Window Property)} {Name WIDTH} {Text Value is the height and width of the interior of the window (the usable space not counting the border and title). These window properties cannot be changed using {fn WINDOWPROP}. }} {Def {Type (Window Property)} {Name REGION} {Text Value is a region (in screen coordinates) indicating where the window (counting the border and title) is located on the screen. This window property cannot be changed using {fn WINDOWPROP}. }} }{End SubSec Miscellaneous Window Properties} {Begin SubSec Example: A Scrollable Window} {Title Example: A Scrollable Window} {Text The following is a simple example showing how one might create a scrollable window. {lisp CREATE.PPWINDOW} creates a window that displays the pretty printed expression {lisp EXPR}. The window properties {lisp PPEXPR}, {lisp PPORIGX}, and {lisp PPORIGY} are used for saving this expression, and the initial window position. Using this information, {lisp REPAINT.PPWINDOW} simply reinitializes the window position, and prettyprints the expression again. Note that the whole expression is reformatted every time, even if only a small part actually lies within the window. If this window was going to be used to display very large structures, it would be desirable to implement a more sophisticated {lisp REPAINTFN} that only redisplays that part of the expression within the window. However, this scheme would be satisfactory if most of the items to be displayed are small. {lisp RESHAPE.PPWINDOW} resets the window (and stores the initial window position), calls {lisp REPAINT.PPWINDOW} to display the window's expression, and then sets the {lisp EXTENT}{index EXTENT (Window Property)} property of the window so that {fn SCROLLBYREPAINTFN} will be able to handle scrolling and "thumbing" correctly. {Begin LispCode} (DEFINEQ (CREATE.PPWINDOW [LAMBDA (EXPR) {it (* rrb " 4-OCT-82 12:06")} {it (* creates a window that displays} {it a pretty printed expression.)} (PROG (WINDOW) {it (* ask the user for a piece of the} {it screen and make it into a window.)} (SETQ WINDOW (CREATEW NIL "PP window")) {it (* put the expression on the} {it property list of the window so that} {it the repaint and reshape functions} {it can access it.)} (WINDOWPROP WINDOW (QUOTE PPEXPR) EXPR) {it (* set the repaint and reshape} {it functions.)} (WINDOWPROP WINDOW (QUOTE REPAINTFN) (FUNCTION REPAINT.PPWINDOW)) (WINDOWPROP WINDOW (QUOTE RESHAPEFN) (FUNCTION RESHAPE.PPWINDOW)) {it (* make the scroll function} {it SCROLLBYREPAINTFN, a system} {it function that uses the repaint} {it function to do scrolling.)} (WINDOWPROP WINDOW (QUOTE SCROLLFN) (FUNCTION SCROLLBYREPAINTFN)) {it (* call the reshape function to} {it initially print the expression and} {it calculate its extent.)} (RESHAPE.PPWINDOW WINDOW) (RETURN WINDOW]) (REPAINT.PPWINDOW [LAMBDA (WINDOW REGION) {it (* rrb " 4-OCT-82 11:52")} {it (* the repainting function for a window with a} {it pretty printed expression. This repainting} {it function ignores the region to be repainted} {it and repaints the entire window.)} {it (* set the window position to the} {it beginning of the pretty printing} {it of the expression.)} (MOVETO (WINDOWPROP WINDOW (QUOTE PPORIGX)) (WINDOWPROP WINDOW (QUOTE PPORIGY)) WINDOW) (PRINTDEF (WINDOWPROP WINDOW (QUOTE PPEXPR)) 0 NIL NIL NIL WINDOW]) (RESHAPE.PPWINDOW [LAMBDA (WINDOW) {it (* rrb " 4-OCT-82 12:01")} {it (* the reshape function for a} {it window with a pretty printed} {it expression.)} (PROG (BTM) {it (* set the position of the window so that the} {it first character appears in the upper left corner} {it and save the X and Y for the repaint function.)} (DSPRESET WINDOW) (WINDOWPROP WINDOW (QUOTE PPORIGX) (DSPXPOSITION NIL WINDOW)) (WINDOWPROP WINDOW (QUOTE PPORIGY) (DSPYPOSITION NIL WINDOW)) {it (* call the repaint function to} {it pretty print the expression in} {it the newly cleared window.)} (REPAINT.PPWINDOW WINDOW) {it (* save the region actually covered by the pretty} {it printed expression so that the scrolling routines} {it will know where to stop. The pretty printing of} {it the expression does a carriage return after the} {it last piece of the expression printed so that the} {it current position is the base line of the next line} {it of text. Hence the last visible piece of the} {it expression (BTM) is the ending position plus the} {it height of the font above the base line (its ASCENT).)} (WINDOWPROP WINDOW (QUOTE EXTENT) (create REGION LEFT _ 0 BOTTOM _ [SETQ BTM (IPLUS (DSPYPOSITION NIL WINDOW) (FONTPROP WINDOW (QUOTE ASCENT] WIDTH _(WINDOWPROP WINDOW (QUOTE WIDTH)) HEIGHT _(IDIFFERENCE (WINDOWPROP WINDOW (QUOTE HEIGHT)) BTM]) ) {End LispCode} }{End SubSec Example: A Scrollable Window} }{End SubSec Windows} ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) Åó BMOBJ.GETFN2<Øázº