{Begin SubSec Windows} {Title Windows} {Text {note do windows have per-window dribble files, term tables, carets? (not yet! -- BVM)} Windows provide a means by which different programs can share the display harmoniously. Interlisp-D provides both interactive and programmatic constructs for creating, moving, reshaping, overlapping, and destroying windows in such a way that a program can be embedded in a window in a relatively transparent fashion. This is implemented by having each window save the bits that it obscures. This allows existing Interlisp programs to be used without change, while providing a base for experimentation with more complex window semantics in new applications. Because the window system assumes that all programs follow certain conventions concerning control of the screen, ordinary user programs should not perform display operations directly on the screen. In particular, functions that can operate directly on bitmaps (such as {fn BITBLT} or {fn BITMAPBIT}) should not be given {lisp (SCREENBITMAP)}{index SCREENBITMAP FN} as the destination argument. All interactions with the screen should take place through windows. For specialized applications that require taking complete control of the display, the window system can be turned off (and back on again) with the following function: {FnDef {Name WINDOWWORLD} {Args FLAG} {Type nospread} {Text The window world is turned on if {arg FLAG} is {lisp T} and off if {arg FLAG} is {lisp NIL}. {fn WINDOWWORLD} returns the previous state of the window world ({lisp T} or {lisp NIL}). If {fn WINDOWWORLD} is given no arguments, it simply returns the current state without affecting the window world. }} {Begin SubSec What are Windows?} {Title What are Windows?} {Text A window specifies a region of the screen, a display stream, a location in an occlusion stack, 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 splashed at 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, 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 {lisp ({fn SCREENBITMAP})}.{index SCREENBITMAP FN} The XOffset, YOffset, and ClippingRegion attributes of the display stream should not be changed. At some future date, the notions of window and display stream will be merged. 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 on the occlusion stack and therefore visible on the screen (unless it is covered by other open windows) and accessible to mouse operations. In a "closed" state, a window is not on the occlusion stack and therefore not visible and not accessible to mouse operations. Any attempt to print or draw on a closed window will open it. When Interlisp-D starts up, there are three windows on the screen: a top level typescript window, a window containing the Interlisp-D logo, and a prompt window. The top level typescript window corresponds to the file {lisp T} in the {lisp EXEC} process where the read-eval-print loop is operating. The {term logo window} is bound to the variable {var LOGOW}{index LOGOW Var} until it is closed. The {term prompt window} is used for the printing of help or prompting messages. It is available to user programs through the following functions: {VarDef {Name PROMPTWINDOW} {Text Global variable containing the prompt window. }} {FnDef {Name PROMPTPRINT} {Args EXP} {Type NOSPREAD} {Text Prints {arg EXP} in the prompt window. }} {FnDef {Name CLRPROMPT} {Args} {Text Clears the prompt window. }} }{End SubSec What are Windows?} {Begin SubSec Interactive Window Operations} {Title Interactive Window Operations} {Text {Tag InteractiveWindowOps} {note there should be a simple version of this in the introduction chapter, with pointers to this for people who want more info} The Interlisp-D window system allows the user to interactively manipulate the windows on the screen, moving them around, changing their shape, etc. by selecting various operations from a menu. Programmatic versions of these operations are described on {PageRef Tag ProgrammaticWindowOps}. For most windows, depressing the {lisp RIGHT} mouse key when the cursor is inside a window during I/O wait will cause the window to come to the top and a menu of window operations to appear. If a command is selected from this menu (by releasing the right mouse key while the cursor is over a command), the selected operation will be applied to the window in which the menu was brought up. (It is possible for an applications program to redefine the action of the {lisp RIGHT} mouse key. In these cases, there is a convention that the default command menu may be brought up by depressing the {lisp RIGHT} key when the cursor is in the header or border of a window. See {PageRef (Window Property) RIGHTBUTTONFN}) The operations are: {Def {Type (Window Menu Command)} {Name CLEAR} {Text Clears the window and repositions it to the left margin of the first line of text (below the upper left corner of the window by the amount of the font ascent). }} {Def {Type (Window Menu Command)} {Name CLOSE} {Text Closes the window, i.e, removes it from the screen. (See {fn CLOSEW}, {PageRef Fn CLOSEW}.) }} {Def {Type (Window Menu Command)} {Name BURY} {Text Puts the window on the bottom of the occlusion stack, thereby exposing any windows that it was hiding. }} {Def {Type (Window Menu Command)} {Name MOVE} {Text Moves the window to a location specified by depressing and then releasing the {lisp LEFT} key. During this time a ghost frame will indicate where the window will reappear when the key is released. (See {fn GETBOXPOSITION}, {PageRef Fn GETBOXPOSITION}.) }} {Def {Type (Window Menu Command)} {Name SHAPE} {Text Allows the user to specify a new region for the existing window contents. If the {lisp LEFT} key is used to specify the new region, the reshaped window can be placed anywhere. If the {lisp MIDDLE} key is used, the cursor will start out tugging at the nearest corner of the existing window, which is useful for making small adjustments in a window that is already positioned correctly. This is done by calling the function {fn SHAPEW}. }} {Def {Type (Window Menu Command)} {Name REDISPLAY} {Text Redisplays the window. (See {fn REDISPLAYW}, {PageRef Fn REDISPLAYW}.) }} {Def {Type (Window Menu Command)} {Name PAINT} {Text Switches to a mode in which the cursor can be used like a paint brush to draw in a window. This is useful for making notes on a window. While the {lisp LEFT} key is down, bits are added. While the {lisp MIDDLE} key is down, they are erased. The {lisp RIGHT} button pops up a command menu that allows changing of the brush shape, size and shade, changing the mode of combining the brush with the existing bits, or stopping paint mode. Paint mode also contains a hardcopy command that makes a Press file of the bits in a window and sends it to the printer. There are limitations on the complexity and size of the bitmaps that some printers will print. If the printer does not print the entire window correctly, try a smaller window or one with fewer black bits in it. To get a hardcopy of an arbitrary part of the screen that crosses window boundaries, use the {lisp HARDCOPY} command in the background menu (below). }} {index *PRIMARY* SNAP (Window Menu Command)} {Def {Type (Window Menu Command)} {Name SNAP} {Text Prompts for a region on the screen and makes a new window whose bits are a snapshot of the bits currently in that region. Useful for saving some particularly choice image before the window image changes. }} 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} commands, the user can shrink windows not currently being used into icons, and quickly restore the original windows at any time. {Def {Type (Window Menu Command)} {Name SHRINK} {Text Removes the window from the screen and brings up its {term icon}. (See {fn SHRINKW}, {PageRef Fn SHRINKW}.) The window can be restored by selecting {lisp EXPAND} from the window command menu of the icon. }} If the {lisp RIGHT} button is pressed while the cursor is in an {term icon}, the window command menu will contain a slightly different set of commands. The {lisp REDISPLAY} and {lisp CLEAR} commands are removed, and the {lisp SHRINK} command is replaced with the {lisp EXPAND} command: {Def {Type (Window Menu Command)} {Name EXPAND} {Text Restores the window associated with this icon and removes the icon. (See {fn EXPANDW}, {PageRef Fn EXPANDW}.) }} If the {lisp RIGHT} button is pressed while the cursor is not in any window, a "background menu" appears with the following operations: {Def {Type (Window Menu Command)} {Name SAVEVM} {Text Calls the function {fn SAVEVM} ({PageRef Fn SAVEVM}), which writes out all of the dirty pages of the virtual memory. After a {fn SAVEVM}, and until the pagefault handler is next forced to write out a dirty page, your virtual memory image will be continuable (as of the {fn SAVEVM}) should you experience a system crash or other disaster. }} {Def {Type (Window Menu Command)} {Name SNAP} {Text The same as the {lisp SNAP} command described above. }} {Def {Type (Window Menu Command)} {Name HARDCOPY} {Text Prompts for a region on the screen, makes a press file and sends it to the printer. The printing is done with {fn HARDCOPYW} ({PageRef Fn HARDCOPYW}), so if {var FULLPRESSPRINTER} is non-{lisp NIL}, the image will be sent there, rather than to {lisp (PRINTINGHOST)}. {Begin Note} the following contradicts doc for HARDCOPYW. ??? If the region is bigger than what a Dover can normally print, and FULLPRESSPRINTER is non-NIL, the system will attempt to send a reduced image to FULLPRESSPRINTER. FULLPRESSPRINTER is initially NIL; the site-dependent INIT file should set it appropriately if you have a "full-press" printer available (running the "Press" server rather than "Spruce" server.) {End Note} }} Some built-in facilities and Lispusers packages add commands to the background menu, to provide an easy way of calling the different facilities. The user can determine what these new commands do by holding the {lisp RIGHT} button down for a few seconds over the item in question; an explanatory message will be printed in the prompt window. The following functions provide a functional interface to the interactive window operations so that user programs can call them directly. {FnDef {Name DOWINDOWCOM} {Args WINDOW} {Text If {arg WINDOW} is {lisp NIL}, it calls {fn DOBACKGROUNDCOM}. If {arg WINDOW} is a {lisp WINDOW} that doesn't have a {lisp DOWINDOWCOMFN}{index DOWINDOWCOMFN (Window Property)} window property, it brings up the window command menu. The initial items in these menus are described above. If the user selects one of the items from the provided menu, that item is {lisp APPLY}ed to {arg WINDOW}. If {arg WINDOW} is a {lisp WINDOW} that has a {lisp DOWINDOWCOMFN} window property, it {lisp APPLY}s that property to {lisp WINDOW}. Shrunken windows have a {lisp DOWINDOWCOMFN} property that presents a window command menu that contains "expand" instead of "shrink". If {arg WINDOW} is not a {lisp WINDOW} or {lisp NIL}, {fn DOWINDOWCOM} returns. }} {FnDef {Name DOBACKGROUNDCOM} {Text Brings up the background menu. The initial items in this menu are described above. If the user selects one of the items from the menu, that item is {lisp EVAL}ed. }} {Text The variables {var BACKGROUNDBUTTONEVENTFN}, {VAR BACKGROUNDCURSORINFN}, {VAR BACKGROUNDCURSOROUTFN} and {var BACKGROUNDCURSORMOVEDFN} provide a way of taking action when there is cursor action and the cursor in in the background. 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 Interactive Window Operations} {Begin SubSec Changing Entries on the Window Command Menus} {Title Changing Entries on the Window Command Menus} {Text {note the format of these command lists is totally inconsistant! Does DOWINDOWCOM actually redefine the WHENSELECTEDFN of the menu, so it will APPLY CADR of the list rather than EVAL?? --- mjs} The window command menus for unshrunken windows, shrunken windows, and the background are cached in the variables {var WindowMenu}, {var IconWindowMenu}, and {var BackgroundMenu}. To change the entries in these menus, the user should change the change the menu "command lists" in the variables {var WindowMenuCommands}, {var IconWindowMenuCommands}, and {var BackgroundMenuCommands}, and set the appropriate menu variable to a non-{lisp MENU}, so the menu will be recreated. This provides a way of adding commands to the menu, of changing its font or of restoring the menu if it gets clobbered. The "command lists" are in the format of the {lisp ITEMS} field of a menu (see {PageRef (Menu Field) ITEMS}), except as specified below. Note: command menus are recreated using the current value of {var MENUFONT}.{index MENUFONT Var} {VarDef {Name WindowMenu} } {VarDef {Name WindowMenuCommands} {Text The menu that is brought up in response to a right button in an unshrunken window is stored on the variable {var WindowMenu}. If {var WindowMenu} is set to a non-{lisp MENU}, the menu will be recreated from the list of commands {var WindowMenuCommands}. The {fn CADR} of each command added to {var WindowMenuCommands} should be a function name that will be {fn APPLY}ed to the window. }} {VarDef {Name IconWindowMenu} } {VarDef {Name IconWindowMenuCommands} {Text The menu that is brought up in response to a right button in a shrunken window is stored on the variable {var IconWindowMenu}. If it is {lisp NIL}, it is recreated from the list of commands {var IconWindowMenuCommands}. The {fn CADR} of each command added a function name that will be {fn APPLY}ed to the window. }} {VarDef {Name BackgroundMenu} } {VarDef {Name BackgroundMenuCommands} {Text The menu that is brought up in response to a right button in the background is stored on the variable {var BackgroundMenu}. If it is {lisp NIL}, it is recreated from the list of commands {var BackgroundMenuCommands}. The {fn CADR} of each command added to {var BackgroundMenuCommands} should be a form that will be {fn EVAL}ed. }} }{End SubSec Changing Entries on the Window Command Menus} {Begin SubSec Coordinate Systems} {Title Coordinate Systems} {Text 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 XOffset and YOffset 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 ClippingRegion 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 ({PageRef (Window Property) EXTENT}). Second, the clipping region of the window (obtainable with the function {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}). }{End SubSec Coordinate Systems} {Begin SubSec Scrolling} {Title Scrolling} {Text {Tag WindowScrolling} 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 scrolling regions will only be active if the window has a {lisp SCROLLFN}{index SCROLLFN (Window Property)} window property ({PageRef (Window Property) SCROLLFN}) and does NOT have a {lisp NOSCROLLBARS}{index NOSCROLLBARS (Window Property)} window property ({PageRef (Window Property) NOSCROLLBARS}). If a window has a {lisp SCROLLFN}, its {lisp NOSCROLLBARS} property is non-{lisp NIL}, and the cursor moves from inside that window into its scrolling region and remains there for {var SCROLLWAITTIME}{index SCROLLWAITTIME Var} milliseconds (initially 1000), a scroll bar appears. The value of the global variable {var SCROLLBARWIDTH}{index SCROLLBARWIDTH Var} (initially 24) determines the size of the scrolling region. 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}. }} The function that tracks the mouse while it is in the scroll region is {lisp SCROLL.HANDLER}. {FnDef {Name SCROLL.HANDLER} {Args WINDOW} {Text This 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. }} {fn SCROLLBYREPAINTFN} is the standard scrolling function which should be used as the {lisp SCROLLFN}{index SCROLLFN (Window Property)} property for most scrolling windows. {FnDef {Name SCROLLBYREPAINTFN} {Args WINDOW DELTAX DELTAY CONTINUOUSFLG} {Text 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 to keep the extent region visible or near visible. That is, 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} is scrolled to just above the window to provide a way of "hiding" the contents of a window. 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}). }} }{End SubSec Scrolling} {Begin SubSec Programmatic Window Operations} {Title Programmatic Window Operations} {Text {FnDef {Name CREATEW} {Args REGION TITLE BORDER 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 BORDER} is a number, it is used as the border size. If {arg BORDER} 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 programs that create windows from one of their arguments. {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 {lisp 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 not numbers, {fn CREATEW} is given {lisp NIL} as a {lisp REGION} argument. 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. }} {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 active windows. }} {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 {lisp LITATOM}, it should be a function which is called with {lisp WINDOW} as its first argument, which should return a dotted pair. }} Interlisp-D provides a set of operations which apply to any window. In addition to being available as functions, most of these are also available via the standard mouse interface. See {PageRef Tag InteractiveWindowOps} {Tag ProgrammaticWindowOps} {FnDef {Name TOTOPW} {Args WINDOW NOCALLTOPWFN} {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 NOCALLTOPWFN} is {lisp NIL}, the {lisp TOTOPFN} of {arg WINDOW} is called ({PageRef (Window Property) TOTOPFN}). If {arg NOCALLTOPWFN} is {lisp T}, it is not called, which allows a {lisp TOTOPFN} to call {fn TOTOPW} without causing an infinite loop. }} {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. 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 and the window property {lisp NEWREGIONFN} ({PageRef (Window Property) NEWREGIONFN}) is used as the {lisp NEWREGIONFN} argument and {arg WINDOW} as the {lisp NEWREGIONFNARG} argument. This allows the window to control the shapes and sizes for interactive calls. 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. Unless {arg WINDOW} has a {lisp DOSHAPEFN} window property, the function {fn SHAPEW1} is called to reshape the window. If {arg WINDOW} has a window property {lisp DOSHAPEFN} ({PageRef (Window Property) DOSHAPEFN}), it is called, passing it {arg WINDOW} and {arg NEWREGION}, or the region returned by {fn GETREGION}. {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. There is a simpler user hook into reshape operations, the {lisp RESHAPEFN} window property ({PageRef (Window Property) RESHAPEFN}). }} {FnDef {Name SHAPEW1} {Args WINDOW NEWREGION} {Text Changes {arg WINDOW}'s size and position on the screen to be {arg NEWREGION}. 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. }} {FnDef {Name CLOSEW} {Args WINDOW} {Text {fn CLOSEW} calls the function or functions on the window property {lisp CLOSEFN} of {arg WINDOW}, if any ({PageRef (Window Property) CLOSEFN}). 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. }} {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 ({PageRef (Window Property) OPENFN}). 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}. }} {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}{index CALCULATEREGION (Window Property)} 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} property ({PageRef (Window Property) MOVEFN}), 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 a window property of {lisp AFTERMOVEFN} ({PageRef (Window Property) AFTERMOVEFN}), 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. }} {FnDef {Name RELMOVEW} {Args WINDOW POSITION} {Text Like {fn MOVEW} for moving windows but {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))} }} {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 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. }} {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 ALWAYSFLG} is {lisp NIL}, and {arg WINDOW} doesn't have a {lisp REPAINTFN} ({PageRef (Window Property) REPAINTFN}), {arg WINDOW} will not change and the message "That window doesn't have a REPAINTFN" will be printed in the prompt window. {note what will it do if there is no REPAINTFN and ALWAYSFLG=T??} }} {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 expanded by pressing the {lisp MIDDLE} button in it. The {lisp SHRINKFN} property ({PageRef (Window Property) SHRINKFN}) 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 ({PageRef (Window Property) ICONFN}), it gets called with arguments {lisp ({arg WINDOW} {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 ({PageRef (Window Property) ICON}), 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} ({PageRef (Window Property) 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 ICON} {text Restores the window for which {arg ICON} is an icon, and removes the icon from the screen. If the {lisp EXPANDFN} ({PageRef (Window Property) 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. }} {Fndef {name INVERTW} {args WINDOW SHADE} {text Fills the window {ARG WINDOW} with a shade in INVERT mode. If SHADE is {lisp NIL}, {LISP BLACKSHADE} is used. {fn INVERTW} return {arg WINDOW} so that it can be used inside {fn RESETFORM}.} {Fndef {name FLASHWINDOW} {args WIN? N FLASHINTERVAL SHADE} {text Flashes a window by filling it with a shade. {ARG WIN?} is the window to flash. {arg N} is the number of times to flash the window and defaults to 1. {arg FLASHINTERVAL} is the lenght of time in milliseconds to wait between flashes and defaults to 200. {arg SHADE} is the shade that will be flashed and defaults to {lisp BLACKSHADE}. } }{End SubSec Programmatic Window Operations} {Begin SubSec Window Properties} {Title Window Properties} {Text The behavior of a window is controlled by a set of {term 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. (Note: If the order of items in the list is important, the list can be modified using {fn WINDOWPROP}.) {fn WINDOWADDPROP} is useful for adding {lisp OPENFN} or {lisp CLOSEFN} functions to a window without affecting its existing functions. }} {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} {Begin SubSec Mouse Function Window Properties} {Title Mouse Function Window Properties} {Text These 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 {lisp TTY} input 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 (stored under the {lisp PROCESS} property) 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. {lisp CURSORINFN} can be a list of functions and all will be called. }} {Def {Type (Window Property)} {Name CURSOROUTFN} {Text The {lisp CURSOROUTFN} is called when the cursor leaves the window. {lisp CURSOROUTFN} can be a list of functions and 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. Note: 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 programs are encouraged to follow this convention. }} }{End SubSec Mouse Function Window Properties} {Begin SubSec Event Window Properties} {Title Event Window Properties} {Text {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} ({PageRef Fn CLOSEW}). (Note: If the {lisp CAR} of the list is a {lisp LAMBDA} word, it is treated as a single function.) 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: A {lisp CLOSEFN} should not call {fn CLOSEW} on its argument. }} {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} ({PageRef Fn OPENW}), with the window as a single 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...} {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} ({PageRef 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}. }} {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} ({PageRef 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} ({PageRef 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 on {PageRef Fn SHRINKW} or return the previously created icon if it does not want to change it. }} {Def {Type (Window Property)} {Name ICON} {Text If {fn SHRINKW} ({PageRef 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} ({PageRef Fn EXPANDW}), with the window as a single argument. }} {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 {LISP SCROLLW}. }} {Def {Type (Window Property)} {Name NEWREGIONFN} {Text The {lisp NEWREGIONFN} is passed as the {arg NEWREGIONFN} argument to {fn GETREGION} ({PageRef Fn GETREGION}) when the window is reshaped. }} {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} ({PageRef 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 fourthree arguments: (1) the window in its reshaped form, (2) a bitmap with the image of thecontents of the old window in its old shape, and (3) the region within the bitmap described in (2) that contains the window's old contentsold image, and (4) the region of the screen previously occuppied by this window. This function is provided so that users can reformat window contents or whatever. {fn RESHAPEBYREPAINTFN} ({PageRef Fn RESHAPEBYREPAINTFN}) 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 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} ({PageRef 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}).) }} {Def {Type (Window Property)} {Name MOVEFN} {Text If the {lisp MOVEFN} is {lisp DON'T}, the window will not be moved by {fn MOVEW} ({PageRef 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}, {PageRef Fn MOVEW}) with the window as an argument. }} }{End SubSec Event Window Properties} {Begin SubSec Miscellaneous Properties} {Title Miscellaneous 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. The window title shade is used to fill in the title bar that is not covered with text. If it is {lisp NIL}, the value of the global variable {var WINDOWTITLESHADE}{index WINDOWTITLESHADE Var} (initially BLACKSHADE) is used. }} {Def {Type (Window Property)} {Name EXTENT} {Text Used to limit scrolling operations (see {PageRef Tag WindowScrolling}). 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 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. This implements the mechanism by which the keyboard is associated with different processes. }} {Def {Type (Window Property)} {Name PAGEFULLFN} {Text If the {lisp PAGEFULLFN} 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} is {lisp NIL}, the system function {fn PAGEFULLFN} ({PageRef Fn PAGEFULLFN}) is called. Note: {lisp PAGEFULLFN} is only called on windows which are the {fn TTYDISPLAYSTREAM} of some process (see {PageRef Fn TTYDISPLAYSTREAM}). }} The following properties are read-only (i.e. their property values cannot be changed using {fn WINDOWPROP}). {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. }} {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). }} {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. }} }{End SubSec Miscellaneous Properties} }{End SubSec Window Properties} {Begin SubSec Auxiliary Functions} {Title Auxiliary Functions} {Text {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} ({PageRef (Window Property) REPAINTFN}). 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. Note that this may result in as many as four calls to the {lisp REPAINTFN}. }} {FnDef {Name RESHAPEBYREPAINTFN} {Args WINDOW OLDIMAGE OLDREGION} {Text It {fn BITBLT}s the old region contents into the lower left corner of the new region. If the new shape is larger in either or both dimensions, the new areas exposed are to the top and right of the old image. When this happens, {lisp RESHAPEBYREPAINTFN} calls {arg WINDOW}'s {lisp REPAINTFN} ({PageRef (Window Property) REPAINTFN}) to display the newly exposed region's contents. Note that this may result in two calls to the {lisp REPAINTFN}. }} {FnDef {Name PAGEFULLFN} {Args WINDOW} {Text If the window property {lisp PAGEFULLFN} ({PageRef (Window Property) PAGEFULLFN}) is {lisp NIL}, when the window is full the system function {fn PAGEFULLFN} 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. }} }{End SubSec Auxiliary Functions} {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]) {End LispCode} {Begin LispCode} (REPAINT.PPWINDOW [LAMBDA (WINDOW REGION) {it (* rrb " 4-OCT-82 11:52")} {it (* the repainting function for a window with a pretty printed expression.} {it This repainting function ignores the region to be repainted and repaints} {it 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]) {End LispCode} {Begin LispCode} (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 first character appears in} {it the upper left corner 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 printed expression so} {it that the scrolling routines will know where to stop. The pretty printing} {it of the expression does a carriage return after the last piece of the} {it expression printed so that the current position is the base line of} {it the next line of text. Hence the last visible piece of the expression} {it (BTM) is the ending position plus the height of the font above the} {it base line e.g 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} 2VGACHA 7GACHA PAPERWORKS.STYLEFNXGACHA GACHA EDITMARK.STYLEFNGACHA GACHA EDITMARK.STYLEFNGACHA GACHA EDITMARK.STYLEFN@GACHA GACHA EDITMARK.STYLEFN&GACHA GACHA EDITMARK.STYLEFNGACHA 4GACHA EDITMARK.STYLEFN;GACHA GACHA EDITMARK.STYLEFN GACHA GACHA EDITMARK.STYLEFNGACHA GACHA EDITMARK.STYLEFNGACHA ˆGACHA EDITMARK.STYLEFNGACHA  GACHA EDITMARK.STYLEFNGACHA GACHA EDITMARK.STYLEFNGACHA GACHA EDITMARK.STYLEFN GACHA |GACHA EDITMARK.STYLEFNGACHA þGACHA EDITMARK.STYLEFNGACHA  GACHA EDITMARK.STYLEFNGACHA ðGACHA EDITMARK.STYLEFNGACHA ^GACHA EDITMARK.STYLEFNcGACHA GACHA EDITMARK.STYLEFN$GACHA GACHA EDITMARK.STYLEFNGACHA GACHA EDITMARK.STYLEFNGACHA GACHA EDITMARK.STYLEFN GACHA GACHA EDITMARK.STYLEFNGACHA GACHA EDITMARK.STYLEFNGACHA GACHA EDITMARK.STYLEFNGACHA EDITMARK.STYLEFNDELETEDGGACHA GACHA EDITMARK.STYLEFNGACHA EDITMARK.STYLEFNDELETEDGACHA GACHA EDITMARK.STYLEFNGACHA GACHA EDITMARK.STYLEFNDELETED!GACHA GACHA EDITMARK.STYLEFNGACHA GACHA EDITMARK.STYLEFN GACHA EDITMARK.STYLEFNDELETEDFGACHA EDITMARK.STYLEFNGACHA 3GACHA EDITMARK.STYLEFN÷GACHA GACHA EDITMARK.STYLEFNîGACHA GACHA EDITMARK.STYLEFNDELETEDÔGACHA  wIz¸