{Begin SubSec Interactive Bitmap Editing} {Title Interactive Bitmap Editing} {Text One important concept of the Interlisp-D display system is the idea of a bitmap, a rectangular array of bits. While working with the display system, it is extremely useful to be able to manipulate bitmaps, textures, and character bitmaps. The following functions provide an easy-to-use interactive editing facility for various types of bitmaps. {FnDef {Name EDITBM} {Args BITMAP} {Text If {arg BITMAP} is a bitmap, it is edited. If {arg BITMAP} is an atom whose value is a bitmap, its value is edited. If {arg BITMAP} is {lisp NIL}, {fn EDITBM} asks for dimensions and creates a bitmap. If {arg BITMAP} is a region, that portion of {lisp (SCREENBITMAP)} is used. If {arg BITMAP} is a window, it is brought to the top and its contents edited. }} {fn EDITBM} sets up the bitmap being edited in an editing window. The editing window has two major areas: a gridded edit area in the lower part of the window and a display area in the upper left part. In the edit area, the left button will add points, the middle button will erase points. The right button provides access to the normal window commands to reposition and reshape the window. The actual size bitmap is shown in the display area.{note picture!!} If the bitmap is too large to fit in the edit area, only a portion will be editable. This portion can be changed by scrolling both up and down in the left margin and left and right in the bottom margin. Pressing the middle button while in the display area will bring up a menu that allows global placement of the portion of the bitmap being edited. To allow more of the bitmap to be editing at once, the window can be reshaped to make it larger or the {lisp GridSize←} command described below can be used to reduce the size of a bit in the edit area. Pressing the middle button while not in either the edit area or the display area (i.e. while in the grey area in the upper right or in the title) will bring up a command menu. There are commands to stop editing, to restore the bitmap to its initial state and to clear the bitmap. Holding the middle button down over a command will result in an explanatory message being printed in the prompt window. The commands are described below: {Begin Labeledlist EDITBM menu commands} {Indent 20percent} {Name {lisp OK}} {Item Copies the changed image into the original bitmap, stops the bitmap editor and closes the edit windows. The changes the bitmap editor makes during the interaction occur on a copy of the original bitmap. Unless the bitmap editor is exited via OK, no changes are made in the original. } {Name {lisp Stop}} {Item Stops the bitmap editor without making any changes to the original bitmap. } {Name {lisp Clear}} {Item Sets all or part of the bitmap to 0. Another menu will appear giving a choice between clearing the entire bitmap or just the portion that is in the edit area. The second menu also acts as a confirmation, since not selecting one of the choices on this menu results in no action being taken. } {Name {lisp Reset}} {Item Sets all or part of the bitmap to the contents it had when {fn EDITBM} was called. As with the {lisp Clear} command, another menu gives a choice between resetting the entire bitmap or just the portion that is in the edit area. } {Name {lisp GridSize←}} {Item Allows specification of the size of the editing grid. Another menu will appear giving a choice of several sizes. If one is selected, the editing portion of the bitmap editor will be redrawn using the selected grid size, allowing more or less of the bitmap to be edited without scrolling. The original size is chosen hueristically and is typically about 8. It is particularly useful when editing large bitmaps to set the edit grid size smaller than the original. } {Name {lisp ShowAsTile}} {Item Tesselates the current bitmap in the upper part of the window. This is useful for determining how a bitmap will look if it were made the background (using the function {fn CHANGEBACKGROUND}). Note: The tiled display will not automatically change as the bitmap changes; to update it, use the {lisp ShowAsTile} command again. } {Name {lisp Paint}} {Item Puts the current bitmap into a window and call the window {lisp PAINT} command on it. The {lisp PAINT} command implements drawing with various brush sizes and shapes but only on an actual sized bitmap. The {lisp PAINT} mode is left by pressing the {lisp RIGHT} button and selecting the {lisp QUIT} command from the menu. At this point, you will be given a choice of whether or not the changes you made while in {lisp PAINT} mode should be made to the current bitmap. } {Name {lisp CURSOR←}} {Item Makes the lower left part of the bitmap become the cursor and will prompt you for the "hot spot". } {End Labeledlist EDITBM menu commands} The bitmap editing window can be reshaped to provide more or less room for editing. When this happens, the space allocated to the editing area will be changed to fit in the new region. Whenever the left or middle button is down and the cursor is not in the edit area, the section of the display of the bitmap that is currently in the edit area is complemented. Pressing the left button while not in the edit region will put the lower left 16 x 16 section of the bitmap into the cursor for as long as the left button is held down. {FnDef {Name EDITSHADE} {Args SHADE} {Text Opens a window that allows the user to edit textures. Textures can be either small (4 by 4) patterns or large (16 by 16). In the edit area, the left button adds bits to the shade and the middle button erases bits from the shade. The top part of the window is painted with the current texture whenever all mouse keys are released. Thus it is possible to directly compare two textures that differ by more than one pixel by holding a mouse key down until all changes are made. When the "quit" button is selected, the texture being editted is returned. If {arg SHADE} is a texture object, {fn EDITSHADE} starts with it. If {arg SHADE} is {lisp T}, it starts with a large white texture. Otherwise, it starts with {VAR WHITESHADE}. }} }{End SubSec Interactive Bitmap Editing} {Begin SubSec Display Break Package} {Title Display Break Package} {Text {index Display Break Package} {Tag DisplayBreak} {note put in bitmap image of a break window, such as from Beau's datamation paper --rrb} The display break package allows easier access to the information available during a break, by modifying the function {fn BREAK1} to use the window system. It is turned on in the standard system but can be turned off with the following function: {FnDef {Name WBREAK} {Args ONFLG} {Text If {arg ONFLG} is non-{lisp NIL}, installs the display break package. If {arg ONFLG} is {lisp NIL}, it uninstalls the display break package, which makes {fn BREAK1} behave as in Interlisp-10. {fn WBREAK} returns {lisp T} if the display break package was previously installed; {lisp NIL} otherwise. }} The display break package maintains a trace window and as many break windows as necessary. When a break occurs, a break window is brought up near the tty window of the process that broke and the terminal stream switched to it. The title of the break window is changed to give the name of the broken function, the reason for the break, and the depth of the break recursions. If a break occurs under a previous break, a new break window is created. If a break is caused by a storage full error, the display break package will not try to open a new break window, since this would cause the error to occur repeatedly. {index EVAL (display break command)} {index EVAL! (display break command)} {index EDIT (display break command)} {index revert (display break command)} {index ↑ (display break command)} {index OK (display break command)} {index BT (display break command)} {index BT! (display break command)} {index ?= (display break command)} While in a break window, the middle button brings up a menu of break commands ({lisp EVAL}, {lisp EVAL!}, {lisp EDIT}, {lisp revert}, {lisp ↑}, {lisp OK}, {lisp BT}, {lisp BT!}, and {lisp ?=}). The commands {lisp BT} and {lisp BT!} bring up a backtrace menu beside the break window showing the frames on the stack. {lisp BT} shows frames for which {fn REALFRAMEP} is {lisp T}; {lisp BT!} shows all frames. When one of the frames is selected from this menu, it is greyed and the function name and the variables bound in that frame (including local variables and {fn PROG} variables) are printed in the "backtrace frame" {index backtrace frame window}window. If the left button is used for the selection, only named variables are printed. If the middle button is used, all variables are printed (variables without names will appear as {lisp *var*{arg N}}). The "backtrace frame" window is an inspect window (see {PageRef Tag Inspector}). In this window, the left button can be used to select the name of the function, the names of the variables or the values of the variables. After selecting an item, the middle button brings up a command menu of commands that apply to the selected item. If the function name is selected, a choice of editing the function or seeing the compiled code with {fn INSPECTCODE} will be given. If the function is edited in this way, the editor is called in the broken process, so variables evaluated in the editor will be in the broken process. If a variable name is selected, the command {lisp SET} will be offered. Selecting {lisp SET} will {fn READ} a value and set the selected to the value read. (Note: The inspector will only allow the setting of named variables. Even with this restriction it is still possible to crash the system by setting variables inside system frames. It is recommended that you exercise caution in setting variables in other than your own code.) If the item selected is a value, the inspector will be called on the selected value. The internal break variable {var LASTPOS}{index LASTPOS Var} is set to the selected frame of the backtrace menu so that the normal break commands {lisp EDIT}, {lisp revert}, and {lisp ?=} work on the currently selected frame. The commands {lisp EVAL}, {lisp revert}, {lisp ↑}, {lisp OK}, and {lisp ?=} in the break menu cause the corresponding commands to be "typed in." This means that these break commands will not have the intended effect if characters have already been typed in. Note also that the typed-in break commands {lisp BT}, {lisp BTV}, etc. use the value of {var LASTPOS} to determine where to start listing the stack, so selecting a stack frame name in the backtrace menu will effect these commands. The operation of the display break package is controlled by the following variables: {VarDef {Name MaxBkMenuWidth}} {VarDef {Name MaxBkMenuHeight} {Text The variables {var MaxBkMenuWidth} (default 125) and {var MaxBkMenuHeight} (default 300) control the maximum size of the backtrace menu. If this menu is too small to contain all of the frames in the backtrace, it is made scrollable in both vertical and horizontal directions. }} {VarDef {Name AUTOBACKTRACEFLG} {Text The value of {var AUTOBACKTRACEFLG} controls when and what kind of backtrace menu is automatically brought up. If its value is {lisp NIL} (the default), no backtrace is brought up. If its value is {lisp T}, then on error breaks the {lisp BT} menu is brought up. If its value is {lisp BT!}, then on error breaks the {lisp BT!} menu is brought up. If its value is {lisp ALWAYS}, then the {lisp BT} menu is brought up on both error breaks and user breaks (calls to functions broken by {fn BREAK}). If its value is {lisp ALWAYS!}, then on both error breaks and user breaks the {lisp BT!} menu is brought up. }} {VarDef {Name BACKTRACEFONT} {Text The backtrace menu is printed in the font {var BACKTRACEFONT}, which is initially Gacha 8. }} {VarDef {Name CLOSEBREAKWINDOWFLG} {Text The system normally closes break windows after the break is exited. If {var CLOSEBREAKWINDOWFLG} is {lisp NIL}, break windows will not be closed on exit. Note: In this case, the user must close all break windows. }} {VarDef {Name BREAKREGIONSPEC} {Text Break windows are positioned near the tty window of the broken process, as determined by the variable {var BREAKREGIONSPEC}. The value of this variable is a region whose {lisp LEFT} and {lisp BOTTOM} are an offset from the {lisp LEFT} and {lisp BOTTOM} of the tty window. The {lisp WIDTH} and {lisp HEIGHT} of {var BREAKREGIONSPEC} determine the size of the break window. }} {VarDef {Name TRACEWINDOW} {Text The trace window, {var TRACEWINDOW}, is used for tracing functions. It is brought up when the first tracing occurs and stays up until the user closes it. {var TRACEWINDOW} can be set to a particular window to cause the tracing formation to print out there. }} {VarDef {Name TRACEREGION} {Text The trace window is first created in the region {lisp TRACEREGION}. }} }{End SubSec Display Break Package} {Begin SubSec The Inspector} {Title The Inspector} {Text {Tag Inspector} {index Inspector} The Inspector provides a display-oriented facility for looking at and changing arbitrary Interlisp-D data structures. The inspector can be used to inspect all user datatypes and many system datatypes (although some objects such as numbers have no inspectable structure). The inspector displays the field names and values of an arbitrary object in a window that allows setting of the properties and further inspection of the values. This latter feature makes it possible to "walk" around all of the data structures in the system at the touch of a button. In addition, the inspector is integrated with the break package to allow inspection of any object on the stack and with the display and teletype structural editors to allow the editors to be used to "inspect" list structures and the inspector to "edit" datatypes. The underlying mechanisms of the data inspector have been factored to allow their use as specialized editors in user applications. This functionality is described at the end of this section. Note: Currently, the inspector does {it not} have {lisp UNDO}ing. Also, variables whose values are changed will not be marked as such. {Begin SubSec Inspect Windows} {Title Inspect Windows} {Text An inspect window displays two columns of values. The lefthand column lists the property names of the structure being inspected. The righthand column contains the values of the properties named on the left. For variable length data such as lists and arrays, the "property names" are numbers from 1 to the length of the inspected item and the values are the corresponding elements. For arrays, the property names are the array element numbers and the values are the corresponding elements of the array. For large lists or arrays, or datatypes with many fields, the initial window may be too small to contain all of them. In these cases, the unseen elements can be scrolled into view (from the bottom) or the window can be reshaped to increase its size. In an inspect window, the {lisp LEFT} button is used to select things, the {lisp MIDDLE} button to invoke commands that apply to the selected item. Any property or value can be selected by pointing the cursor directly at the text representing it, and clicking the {lisp LEFT} button. There is one selected item per window and it is marked by having its surrounding box inverted. The commands offered by the {lisp MIDDLE} button depend on whether the selection is a property or a value. If the selected item is a value, the commands provide different ways of inspecting the selected structure. The exact commands that are given depend on the type of the value. If the value is a litatom, the commands are the types for which the atom has definitions as determined by {fn HASDEF}. Some typical commands are: {Begin Table inspecting a LITATOM} {COLUMN 20percent} {COLUMN} {First {lisp FNS}} {Next Edit the definition of the selected litatom.} {First {lisp VARS}} {Next Inspect the value.} {First {lisp PROPS}} {Next Inspect the property list.} {End Table inspecting a LITATOM} If the value is a list, there will be choice of how to inspect the list: {Begin Table inspecting a LISTP} {COLUMN 20percent} {COLUMN} {First {lisp Inspect}} {Next Opens an inspect window in which the properties are numbers and the values are the elements of the list.} {First {lisp TtyEdit}} {Next Calls the teletype structural editor on the list.} {First {lisp DisplayEdit}} {Next Calls the display editor on the list.} {First {lisp As a PLIST}} {Next (If the list is in P-list form) Inspects the list as a property list.} {First {lisp As an ALIST}} {Next (If the list is in {fn ASSOC} list form) Inspects the list as an association-list.} {First {lisp As a record}} {Next Brings up a submenu with all of the {lisp RECORD}s in the system and inspect the list with the one chosen.} {First {lisp As a "record type"}} {Next (If the {fn CAR} is the name of a {lisp TYPERECORD}) Inspects the list as the record of the type named in its {fn CAR}.} {End Table inspecting a LISTP} If the value is neither a litatom or a list, the only command is {lisp Inspect}, which opens an inspector window onto the selected value. If the selected item is a property, the user will be asked for a new value and the selected property will be set to the result of evaluating the read form. The evaluation of the read form and the replacement of the selected item property will appear as their own history events and are individually undoable. Properties of system datatypes cannot be set. (There are often consistency requirements which can be inadvertently violated in ways that crash the system. This may be true of some user datatypes as well, however the system doesn't know which ones. Users are advised to exercise caution.) }{End SubSec Inspect Windows} {Begin SubSec Calling the Inspector} {Title Calling the Inspector} {Text The inspector can be called directly, by using the function {fn INSPECT}: {FnDef {Name INSPECT} {Args OBJECT ASTYPE WHERE} {Text Creates an inspect window onto {arg OBJECT}. If {arg ASTYPE} is given, it will be taken as the record type of {arg OBJECT}. This allows records to be inspected with their property names. If {arg ASTYPE} is {lisp NIL}, the data type of {arg OBJECT} will be used to determine its property names in the inspect window. {arg WHERE} specifies the location of the inspect window. If {arg WHERE} is {lisp NIL}, the user will be prompted for a location. If {arg WHERE} is a window, it will be used as the inspect window. If {arg WHERE} is a region, the inspect window will be created in that region of the screen. If {arg WHERE} is a position, the inspect window will have its lower left corner at that position on the screen. {fn INSPECT} returns the inspect window onto {arg OBJECT}, or {lisp NIL} if no inspection took place. }} There are several ways to open an inspect window onto an object. In addition to calling {fn INSPECT} directly, the inspector can also be called by buttoning an {lisp Inspect} command inside an existing inspector window. Finally, if a non-list is edited with {fn EDITV}, the inspector is called. This also causes the inspector to be called by the {lisp Dedit} command from the display editor or the {lisp EV} command from the standard editor if the selected piece of structure is a non-list. {FnDef {Name INSPECTCODE} {Args FN} {Text Opens a window and displays the compiled code of the function {arg FN} using {fn PRINTCODE}.{index PRINTCODE Fn} The window is scrollable. {note where should this be???} }} }{End SubSec Calling the Inspector} {Begin SubSec Choices Before Inspection} {Title Choices Before Inspection} {Text For some datatypes there is more than one aspect that is of interest or more than one method of inspecting the object. In these cases, the inspector will bring up a menu of the possibilities and wait for the user to select one. For litatoms, the choice includes inspecting its value, its definition, its property list, its {lisp MACRO} or any other aspect returned from {fn TYPESOF}. If a litatom only property is its value, its value will be inspected. For {lisp BITMAP}s, the choice is between inspecting the bitmap's contents with the bitmap editor ({fn EDITBM}) or inspecting the bitmap's fields. For {lisp LISTP}s, the choice is how to inspect it and is between a one level inspector, the teletype editor ({fn EDITE}) or the display editor ({lisp DEDIT}). }{End SubSec Choices Before Inspection} {Begin SubSec Redisplaying an inspect window} {Title Redisplaying an Inspect Window} {Text An inspect window is {it not} automatically updated when the structure it is inspecting is changed. The inspect window can be updated by selecting the "{lisp ReFetch}" command from the menu brought up by pressing the {lisp MIDDLE} button in the title of the window. The "{lisp ReFetch}" command will cause the values of the properties to be re-fetched from the structure and redisplayed. }{End SubSec Redisplaying an inspect window} {Begin SubSec Inspect Window Commands} {Title Inspect Window Commands} {Text By pressing the {lisp MIDDLE} button in the title of the inspect window, a menu of commands that apply to the inspect window is brought up: {Def {Name ReFetch} {Type (Inspect Window Command)} {Text Refetches and redisplays all of the fields of the object being inspected in the inspect window. }} {Def {Name IT←datum} {Type (Inspect Window Command)} {Text Sets the variable {var IT} to object being inspected in the inspect window. }} {Def {Name IT←selection} {Type (Inspect Window Command)} {Text Sets the variable {var IT} to the property name or value currently selected in the inspect window. }} }{End SubSec Inspect Window Commands} {Begin SubSec Interaction With the Display Break Package} {Title Interaction With the Display Break Package} {Text The display break package knows about the inspector in the sense that the backtrace frame window is an inspect window onto the frame selected from the back trace menu during a break. Thus you can call the inspector on an object that is bound on the stack by selecting its frame in the back trace menu, selecting its value with the {lisp LEFT} button in the back trace frame window, and selecting the inspect command with the {lisp MIDDLE} button in the back trace frame window. The values of variables in frames can be set by selecting the variable name with the {lisp LEFT} button and then the "{lisp Set}" command with the {lisp MIDDLE} button. Note: The inspector will only allow the setting of named variables. Even with this restriction it is still possible to crash the system by setting variables inside system frames. Exercise caution in setting variables in other than your own code. }{End SubSec Interaction With the Display Break Package} {Begin SubSec Controlling the Amount Displayed During Inspection} {Title Controlling the Amount Displayed During Inspection} {Text The amount of information displayed during inspection can be controlled using the following variables: {VarDef {Name MAXINSPECTCDRLEVEL} {Text The inspector prints only the first {var MAXINSPECTCDRLEVEL} elements of a long list, and will make the tail containing the unprinted elements the last item. The last item can be inspected to see further elements. Initially 50. }} {VarDef {Name MAXINSPECTARRAYLEVEL} {Text The inspector prints only the first {var MAXINSPECTARRAYLEVEL} elements of an array. The remaining elements can be inspected by calling the function {lisp (INSPECT/ARRAY {arg ARRAY} {arg BEGINOFFSET})}{index INSPECT/ARRAY FN} which inspects the {arg BEGINOFFSET} through the {arg BEGINOFFSET} + {var MAXINSPECTARRAYLEVEL} elements of {arg ARRAY}. Initially 300. }} {VarDef {Name INSPECTPRINTLEVEL} {Text When printing the values, the inspector reset {lisp PRINTLEVEL} to {var INSPECTPRINTLEVEL}. Initially {lisp (2 . 5)}. }} {VarDef {Name INSPECTALLFIELDSFLG} {Text If {var INSPECTALLFIELDSFLG} is {lisp T}, the inspector will show computed fields ({lisp ACCESSFNS}) as well as regular fields for structures that have a record definition. Initially {lisp T}. }} }{End SubSec Controlling the Amount Displayed During Inspection} {Begin SubSec Inspect Macros} {Title Inspect Macros} {Text The Inspector can be extended to inspect new structures and datatypes by adding entries to the list {var INSPECTMACROS}.{index INSPECTMACROS Var} An entry should be of the form {lisp ({arg OBJECTTYPE} . {arg INSPECTINFO})}. {arg OBJECTTYPE} is used to determine the types of objects that are inspected with this macro. If {arg OBJECTTYPE} is a litatom, the {arg INSPECTINFO} will be used to inspect items whose type name is {arg OBJECTTYPE}. If {arg OBJECTTYPE} is a {lisp LIST} of the form {lisp (FUNCTION {arg DATUM-PREDICATE})}, {arg DATUM-PREDICATE} will be {lisp APPLY}ed to the item and if it returns non-{lisp NIL}, the {arg INSPECTINFO} will be used to inspect the item. {arg INSPECTINFO} can be one of two forms. If {arg INSPECTINFO} is a litatom, it should be a function that will be applied to three arguments (the item being inspected, {arg OBJECTTYPE}, and the value of {arg WHERE} passed to {fn INSPECT}) that should do the inspection. If {arg INSPECTINFO} is not a litatom, it should be a list of {lisp ({arg PROPERTIES} {arg FETCHFN} {arg STOREFN} {arg PROPCOMMANDFN} {arg VALUECOMMANDFN} {arg TITLECOMMANDFN} {arg TITLE} {arg SELECTIONFN} {ARG WHERE} {arg PROPPRINTFN})} where the elements of this list are the arguments for {fn INSPECTW.CREATE}, described below. From this list, the {arg WHERE} argument will be evaluated; the others will not. If {arg WHERE} is {lisp NIL}, the value of {arg WHERE} that was passed to {fn INSPECT} will be used. Examples: The entry {lisp ((FUNCTION MYATOMP) PROPNAMES GETPROP PUTPROP)} on {var INSPECTMACROS} would cause all objects satisfying the predicate {lisp MYATOMP} to have their properties inspected with {fn GETPROP} and {fn PUTPROP}. In this example, {lisp MYATOMP} should make sure the object is a litatom. The entry {lisp (MYDATATYPE . MYINSPECTFN)} on {var INSPECTMACROS} would cause all datatypes of type {lisp MYDATATYPE} to be passed to the function {lisp MYINSPECTFN}. }{End SubSec Inspect Macros} {Begin SubSec INSPECTWs} {Title INSPECTWs} {text The inspector is built on the abstraction of an {lisp INSPECTW}. An {lisp INSPECTW} is a window with certain window properties that display an object and respond to selections of the object's parts. It is characterized by an object and its list of properties. An {lisp INSPECTW} displays the object in two columns with the property names on the left and the values of those properties on the right. An {lisp INSPECTW} supports the protocol that the {lisp LEFT} mouse button can be used to select any property name or property value and the {lisp MIDDLE} button calls a user provided function on the selected value or property. For the Inspector application, this function puts up a menu of the alternative ways of inspecting values or of the ways of setting properties. {lisp INSPECTW}s are created with the following function: {FnDef {Name INSPECTW.CREATE} {Args DATUM PROPERTIES FETCHFN STOREFN PROPCOMMANDFN VALUECOMMANDFN TITLECOMMANDFN TITLE SELECTIONFN WHERE PROPPRINTFN} {text Creates an {lisp INSPECTW} that views the object {arg DATUM}. If {arg PROPERTIES} is a {lisp LISTP}, it is taken as the list of properties of {arg DATUM} to display. If {arg PROPERTIES} is an {lisp ATOM}, it is {lisp APPLY}ed to {arg DATUM} and the result is used as the list of properties to display. }} {arg FETCHFN} is a function of two arguments {lisp ({arg OBJECT} {arg PROPERTY})} that should return the value of the {arg PROPERTY} property of {arg OBJECT}. The result of this function will be printed (with {fn PRIN2}) in the {lisp INSPECTW} as the value. {arg STOREFN} is a function of three arguments {lisp ({arg OBJECT} {arg PROPERTY} {arg NEWVALUE})} that changes the {arg PROPERTY} property of {arg OBJECT} to {arg NEWVALUE}. It is used by the default {arg PROPCOMMANDFN} and {arg VALUECOMMANDFN} to change the value of a property and also by the function {fn INSPECTW.REPLACE} (described below). This can be {lisp NIL} if the user provides command functions which do not call {fn INSPECTW.REPLACE}. Each replace action will be a separate event on the history list. Users are encouraged to provide {pacom UNDO}able {arg STOREFN}s. {arg PROPCOMMANDFN} is a function of three arguments {lisp ({arg PROPERTY} {arg OBJECT} {arg INSPECTW}}) which gets called when the user presses the {lisp MIDDLE} button and the selected item in the {lisp INSPECTW} is a property name. {arg PROPERTY} will be the name of the selected property, {arg OBJECT} will be the datum being viewed, and {lisp INSPECTW} will be the window. If {arg PROPCOMMANDFN} is a string, it will get printed in the {var PROMPTWINDOW} when the {lisp MIDDLE} button is pressed. This provides a convenient way to notify the user about disabled commands on the properties. {fn DEFAULT.INSPECTW.PROPCOMMANDFN},{index DEFAULT.INSPECTW.PROPCOMMANDFN Fn} the default {arg PROPCOMMANDFN}, will present a menu with the single command {lisp Set} on it. If selected, the {lisp Set} command will read a value from the user and set the selected property to the result of {lisp EVAL}uating this read value. {arg VALUECOMMANDFN} is a function of four arguments {lisp ({arg VALUE} {arg PROPERTY} {arg OBJECT} {arg INSPECTW})} that gets called when the user presses the {lisp MIDDLE} button and the selected item in the {lisp INSPECTW} is a property value. {arg VALUE} will be the selected value (as returned by {arg FETCHFN}), {arg PROPERTY} will be the name of the property {arg VALUE} is the value of, {arg OBJECT} will be the datum being viewed, and {arg INSPECTW} will be the {lisp INSPECTW} window. {fn DEFAULT.INSPECTW.VALUECOMMANDFN},{index DEFAULT.INSPECTW.VALUECOMMANDFN Fn} the default {arg VALUECOMMANDFN}, will present a menu of possible ways of inspecting the value and create a new Inspect window if one of the menu items is selected. {arg TITLECOMMANDFN} is a function of two arguments {lisp ({arg INSPECTW} {arg OBJECT})} which gets called when the user presses the {lisp MIDDLE} button and the cursor is in the title or border of the inspect window {arg INSPECTW}. This command function is provided so that users can implement commands that apply to the entire object. The default {arg TITLECOMMANDFN} ({fn DEFAULT.INSPECTW.TITLECOMMANDFN}){index DEFAULT.INSPECTW.TITLECOMMANDFN Fn} presents a menu with the single command {lisp Redisplay} and, if it is selected, redisplays {arg INSPECTW} (using {fn INSPECTW.REDISPLAY}, described below). {arg TITLE} specifies the title of the window. If {arg TITLE} is {lisp NIL}, the title of the window will be the printed form of {arg DATUM} followed by the string " Inspector". If {arg TITLE} is the litatom {lisp DON'T}, the inspect window will not have a title. If {arg TITLE} is any other litatom, it will be applyed to the {arg DATUM} and the potential inspect window (if it is known). If this result is the litatom {lisp DON'T}, the inspect window will not have a title; otherwise the result will be used as a title. If {arg TITLE} is not a litatom, it will be used as the title. {arg SELECTIONFN} is a function of three arguments {lisp ({arg PROPERTY} {arg VALUEFLG} {arg INSPECTW})} which gets called when the user releases the left button and the cursor is on one of the items. The {arg SELECTIONFN} allows a program to take action on the user's selection of an item in the inspect window. At the time this function is called, the selected item has been "selected". The function {fn INSPECTW.SELECTITEM} (described below) can be used to turn off this selection. {arg PROPERTY} will be the name of the property of the selected item. {arg VALUEFLG} will be {lisp NIL} if the selected item is the property name; {lisp T} if the selected item is the property value. {arg WHERE} indicates where the inspect window should go. Its interpretation is described in {fn INSPECT} ({PageRef Fn INSPECT}). If non-{lisp NIL}, {arg PROPPRINTFN} is a function of two arguments {lisp ({arg PROPERTY} {arg DATUM})} which gets called to determine what to print in the property place for the property {arg PROPERTY}. If {arg PROPPRINTFN} returns {lisp NIL}, no property name will be printed and the value will be printed to the left of the other values. An inspect window uses the following window property names to hold information: {prop DATUM}, {prop FETCHFN}, {prop STOREFN}, {prop PROPCOMMANDFN}, {prop VALUECOMMANDFN}, {prop SELECTIONFN}, {prop PROPPRINTFN}, {prop INSPECTWTITLE}, {prop PROPERTIES}, {prop CURRENTITEM} and {prop SELECTABLEITEMS}. {index DATUM Prop} {index FETCHFN Prop} {index STOREFN Prop} {index PROPCOMMANDFN Prop} {index VALUECOMMANDFN Prop} {index SELECTIONFN Prop} {index PROPPRINTFN Prop} {index INSPECTWTITLE Prop} {index PROPERTIES Prop} {index CURRENTITEM Prop} {index SELECTABLEITEMS Prop} {FnDef {Name INSPECTW.REDISPLAY} {Args INSPECTW PROPERTY {anonarg}} {text Updates the display of the objects being inspected in {arg INSPECTW}. If {arg PROPERTY} is a property name or a list of property names, only those properties are updated. If {arg PROPERTY} is {lisp NIL}, all properties are redisplayed. This function is provided because inspect windows do not automatically update their display when the object they are showing changes. This function is called by the {lisp Redisplay} command in the title command menu of an {lisp INSPECTW}. }} {FnDef {Name INSPECTW.REPLACE} {Args INSPECTW PROPERTY NEWVALUE} {text Uses the {arg STOREFN} of the inspect window {arg INSPECTW} to change the property named {arg PROPERTY} to the value {arg NEWVALUE} and updates the display of {arg PROPERTY}'s value in the display. This provides a functional interface for user {arg PROPCOMMANDFN}s. }} {FnDef {Name INSPECTW.SELECTITEM} {Args INSPECTW PROPERTY VALUEFLG} {text Sets the selected item in an inspect window. The item is inverted on the display and put on the window property {prop CURRENTITEM} of {arg INSPECTW}. If {arg INSPECTW} has a {prop CURRENTITEM}, it is deselected. {arg PROPERTY} is the name of the property of the selected item. {arg VALUEFLG} is {lisp NIL} if the selected item is the property name; {lisp T} if the selected item is the property value. If {arg PROPERTY} is NIL, no item will be selected. (This provides a way of deselecting items.) }} }{End SubSec INSPECTWs} }{End SubSec The Inspector}