{Begin SubSec Inspector} {Title Inspector} {Text {Tag Inspector} {index *PRIMARY* 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 designed 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 Calling the Inspector} {Title Calling the Inspector} {Text There are several ways to open an inspect window onto an object. In addition to calling {fn INSPECT} directly (below), 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 EDITDEF} ({PageRef Fn EDITDEF}), 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 teletype editor if the selected piece of structure is a non-list. {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. }} {FnDef {Name INSPECTCODE} {Args FN WHERE {anonarg} {anonarg} {anonarg} {anonarg}} {Text Opens a window and displays the compiled code of the function {arg FN} using {fn PRINTCODE}.{index PRINTCODE Fn} The window is scrollable. {arg WHERE} determines where the window should appear. It can be a position, a region, or a window. If {lisp NIL}, the user is prompted to specify the position of the window. Note: If the Tedit library package is loaded, {fn INSPECTCODE} uses it to create the code inspector window. Also, if {fn INSPECTCODE} is called to inspect the frame name in a break window ({PageRef Term Break Windows}), the location in the code that the frame's PC indicates it was executing at the time is highlighted. }} }{End SubSec Calling the Inspector} {Begin SubSec Multiple Ways of Inspecting} {Title Multiple Ways of Inspecting} {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. If the object is a litatom, the commands are the types for which the litatom has definitions as determined by {fn HASDEF}. Some typical commands are: {Begin LabeledList inspecting a LITATOM} {Label {lisp FNS}} {Text Edit the definition of the selected litatom.} {Label {lisp VARS}} {Text Inspect the value.} {Label {lisp PROPS}} {Text Inspect the property list.} {End LabeledList inspecting a LITATOM} If the object is a list, there will be choice of how to inspect the list: {Begin LabeledList inspecting a LISTP} {Label {lisp Inspect}} {Text Opens an inspect window in which the properties are numbers and the values are the elements of the list.} {Label {lisp TtyEdit}} {Text Calls the teletype list structure editor on the list ({PageRef Term teletype list structure editor}).} {Label {lisp DisplayEdit}} {Text Calls the DEdit display editor on the list ({PageRef Term DEdit}).} {Label {lisp As a PLIST}} {Text Inspects the list as a property list, if the list is in property list form: {lisp (({arg PROP{sub 1}} {arg VAL{sub 1}}) {ellipsis} ({arg PROP{sub N}} {Arg VAL{sub N}}))}.} {Label {lisp As an ALIST}} {Text Inspects the list as an association-list, if the list is in {fn ASSOC} list form: {lisp ({arg PROP{sub 1}} {arg VAL{sub 1}} {ellipsis} {arg PROP{sub N}} {Arg VAL{sub N}})}.} {Label {lisp As a record}} {Text Brings up a submenu with all of the {lisp RECORD}s in the system and inspect the list with the one chosen.} {Label {lisp As a "record type"}} {Text Inspects the list as the record of the type named in its {fn CAR}, if the {fn CAR} of the list is the name of a {lisp TYPERECORD} ({PageRef (Record Type) TYPERECORD}).} {End LabeledList inspecting a LISTP} If the object is a bitmap, the choice is between inspecting the bitmap's contents with the bitmap editor ({fn EDITBM}) or inspecting the bitmap's fields. Other datatypes may include multiple methods for inspecting objects of that type. }{End SubSec Multiple Ways of Inspecting} {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 options 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 options provide different ways of inspecting the selected structure. The exact commands that are given depend on the type of the value. If the selected item is a property name, the command {lisp SET} will appear. If selected, the user will be asked to type in an expression, 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.) It is possible to copy-select property names or values out of an inspect window. Litatoms, numbers and strings are copied as they are displayed. Unprintable objects (such as bitmaps, etc.) come out as an appropriate system expression, such that if is evaluated, the object is re-created. }{End SubSec Inspect Windows} {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 An inspect window is {it not} automatically updated when the structure it is inspecting is changed. The "{lisp ReFetch}" command will refetche and redisplay 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 Break Windows} {Title Interaction With Break Windows} {Text The break window facility ({PageRef Term Break windows}) 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 Break Windows} {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 resets {lisp PRINTLEVEL} ({PageRef Fn PRINTLEVEL}) to the value of {var INSPECTPRINTLEVEL}. Initially {lisp (2 . 5)}. }} {VarDef {Name INSPECTALLFIELDSFLG} {Text If {var INSPECTALLFIELDSFLG} is {lisp T}, the inspector will show computed fields ({lisp ACCESSFNS}, {PageRef (Record Type) 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 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 list, it is taken as the list of properties of {arg DATUM} to display. If {arg PROPERTIES} is a litatom, 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 {arg 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 commands {lisp ReFetch}, {lisp IT_datum}, and {lisp IT_selection} (see {PageRef (Inspect Window Command) ReFetch}). {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}). {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. {index DATUM (Window Property)} {index FETCHFN (Window Property)} {index STOREFN (Window Property)} {index PROPCOMMANDFN (Window Property)} {index VALUECOMMANDFN (Window Property)} {index SELECTIONFN (Window Property)} {index PROPPRINTFN (Window Property)} {index INSPECTWTITLE (Window Property)} {index PROPERTIES (Window Property)} {index CURRENTITEM (Window Property)} {index SELECTABLEITEMS (Window Property)} An inspect window uses the following window property names to hold information: {lisp DATUM}, {lisp FETCHFN}, {lisp STOREFN}, {lisp PROPCOMMANDFN}, {lisp VALUECOMMANDFN}, {lisp SELECTIONFN}, {lisp PROPPRINTFN}, {lisp INSPECTWTITLE}, {lisp PROPERTIES}, {lisp CURRENTITEM} and {lisp SELECTABLEITEMS}. {FnDef {Name INSPECTW.REDISPLAY} {Args INSPECTW PROPS {anonarg}} {text Updates the display of the objects being inspected in {arg INSPECTW}. If {arg PROPS} is a property name or a list of property names, only those properties are updated. If {arg PROPS} 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 ReFetch} command in the title command menu of an {lisp INSPECTW} ({PageRef (Inspect Window Command) ReFetch}). }} {FnDef {Name INSPECTW.REPLACE} {Args INSPECTW PROPERTY NEWVALUE} {text Calls 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 all items. }} }{End SubSec INSPECTWs} }{End SubSec Inspector} ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) VÒVÒzº