======================================================================== The CyberSpace Deck Manual Don Hopkins Grasshopper Group Last update don@brillig.umd.edu grass@toad.com 22 July 89 ======================================================================== Introduction The CyberSpace deck lets you graphically display and manipulate the many PostScript data strutures, programs, and processes living in the virtual memory space of NeWS. The Network extensible Window System (NeWS) is a multitasking object oriented PostScript programming environment. NeWS programs and data structures make up the window system kernel, the user interface toolkit, and even entire applications. The CyberSpace deck is one such application, written entirely in PostScript, the result of an experiment in using a graphical programming environment to construct a interactive visual user interface to itself. It displays views of structured data objects in overlapping windows that can be moved around on the screen, and manipulated with the mouse: you can copy and paste data structures from place to place, execute them, edit them, open their substructures up to any depth, adjust the scale to shrink and magnify parts of the display, and pop up menus of other useful commands. Deep or complex data structures can be more easily grasped by applying various views to them. There is a window onto a NeWS process, a PostScript interpreter with which you can interact (as with an "executive"). PostScript is a stack based language, so the window has a spike sticking up out of it, representing the process's operand stack. Objects on the process's stack are displayed in windows with their tabs pinned on the spike. (Figure xxx) You can feed PostScript expressions to the interpreter by typing them with the keyboard, or pointing and clicking at them with the mouse, and the stack display will be dynamically updated to show the results. Not only can you examine and manipulate the objects on the stack, but you can also manipulate the stack directly with the mouse. You can drag the objects up and down the spike to change their order on the stack, and drag them on and off the spike to push and pop them; you can take objects off the spike and set them aside to refer to later, and close them into icons so they don't take up as much screen space. NeWS processes running in the same window server can be debugged using the existing NeWS debug commands in harmony with the graphical stack and object display. The CyberSpace deck can be used as a "hands on" way to learn about programming in PostScript and NeWS. You can try out examples from cookbooks and manuals, and explore and enrich your understanding of the environment with the help of the interactive data structure display. ======================================================================== ======================================================================== Concepts This section describes some concepts that you should be familiar with when using the CyberSpace Deck. It describes the most important types of PostScript data structures, and tells you how they look displayed on the screen. It also gives references to sections of other manuals that explain the concepts in more detail (Delimited by ~tildes~.) Referenced Manuals ~Blue: Adobe PostScript Language Tutorial and Cookbook~ ~Red: Adobe PostScript Language Reference Manual~ ~Green: Adobe PostScript Language Design~ ~NeWS: NeWS 1.1 Manual~ Object ~Blue 2: Stack and Arithmetic~ ~Blue 2.1: The PostScript Stack~ ~Red 3.2: Interpreter~ ~Green 2.3: The Operand Stack; Objects in the PostScript Language~ An object is any NeWS data structure that you can push onto the stack or refer to in other objects. Each object has a type, some attributes, and a value. ~Red 3.4: Data Types and Objects~ (The word "object" is used here in a more general sense than in "object oriented programming." The more specific words "class" and "instance" are used instead.) ~NeWS 6: Classes~ When an object is displayed in a window, its type is displayed in the window tab. An object's type precedes its value when its displayed inside another object. Examples: "array [6]", "integer 100" (Figure xxx) Composite objects, such as arrays, strings, and dictionaries, which can be pushed on the stack or referenced by other objects, are represented internally as pointers to their bodies. So there can be multiple references to any composite object, and its body doesn't get moved around in memory whenever the references are moved or copied. ~Blue 8.1: PostScript Arrays~ ~Red 3.4: Data Types and Objects; Simple and Composite Objects~ A reference count is maintained in the body of each composite object. Once there are no longer any remaining references to an object, its body is automatically garbage collected and its storage is reclaimed. ~NeWS 11.8: Object Cleanup~ Executable/Literal ~Blue 4.2: Defining Procedures and Variables~ ~Red 3.4: Data Types and Objects; Attributes of Objects~ ~Green 2.3: The Operand Stack; Objects in the PostScript Language~ ~Green 2.7: Procedures~ Each object has an attribute that makes it either executable or literal. This affects how the PostScript interpreter deals with it (whether it's used as code or data). Each reference to an object has its own executable/literal bit, so you can have an executable and a literal reference to the same object at once. Executable objects are displayed in an italic font, and literal objects are displayed in a non-italic font. (Figure xxx) String ~Blue 5.0: Printing Text; Introduction~ ~Red 3.3: Syntax; Strings~ ~Red 3.4: Data Types and Objects; String~ ~Green 2.6: The Interpreter and the Scanner~ Strings are delimited by parenthesis: "string (foobar)" The parenthesis inside the string do not have to be quoted if they balance: "string (Copyright (C) 1989)" If a string is longer than 80 characters, then only the first 80 are displayed, followed by an elipse: "string (blablabla...bla)..." Name ~Blue 4: Procedures and Variables~ ~Red 3.3: Syntax; Names" ~Red 3.4: Data Types and Objects; Name~ ~Green 2.5: Operators and Name Lookup~ Names are used as keys in dictionaries, to refer to the values of variables and procedures. Executable names are displayed in italics, without a leading slash: "name foo" Literal names are displayed with a slash before them: "name /foo" Array ~Blue 7: Loops and Conditionals~ ~Blue 8: Arrays~ ~Red 3.3: Syntax; Arrays, Procedures~ ~Red 3.4: Data Types and Objects; Array~ ~Red 3.6: Execution: Execution of Specific Types~ ~Green 2.7: Procedures~ PostScript arrays are polymorphic: Each array element can be an object of any type. A PostScript procedure is just an executable array of other objects, to be interpreted one after the other. Executable arrays (i.e. procedures) are displayed in italics, with their length enclosed in braces: "array {37}" Literal arrays are displayed with their length enclosed in square brackets: "array [6]" When you open up an array, lines are drawn fanning out to the right, leading from the array to its elements, which are displayed as "index: type value", in a smaller point size. Dictionary ~Blue 4: Procedures and Variables~ ~Red 3.4: Data Types and Objects; Dictionary~ ~Green 2.4: The Dictionary Stack~ ~Green 2.5: Operators and Name Lookup~ Dictionaries associate keys with values. The key (an index into a dictionary) can be an object of any type (except null), but is usually a name. The value can be anything at all. Dictionaries are used to hold the values of variables, functions and arguments, as records, lookup tables, classes, instances, and other things -- they're very useful! The dictionary stack defines the context of a PostScript process. Whenever the value of a name is needed, it is looked up in the dictionaries on the dictionary stack, in top to bottom order. A dictionary is displayed by showing the number of keys it contains, a slash, and the maximum size of the dictionary, enclosed in angled brackets: "dict <31/200>" When you open up a dictionary, lines are drawn fanning out to the right, leading from the dictionary to its elements, which are displayed as "key : type value" in a smaller point size: "/FirstName : string (don)" Class ~NeWS 6: Classes~ NeWS uses an object oriented programming package, which uses dictionaries to represent classes and instances. When a class dictionary is displayed, its class name is displayed, instead of its actual type "dict": "MessageItem <10/200>" Instance ~NeWS 6: Classes~ When an instance dictionary is displayed, its type is displayed as a period followed by its class name: ".MessageItem <31/200>" Magic Dictionary ~NeWS 11: NeWS Type Extensions~ ~NeWS 11.2: NeWS Type Extensions; Objects as Dictionaries~ Magic dictionaries are certain types of NeWS objects, such as processes, canvases, and events, that appear to be dictionaries, but are really special data types. They have a fixed set of keys with special meanings (such as a process's /OperandStack, or a canvas's /TopChild), but otherwise, you can treat them just like regular dictionaries. Special things may happen when you read or change the values of the keys (for example, setting the /Mapped key of a canvas to false makes it immediately disappear from the screen). Selection ~Red 3.4: Data Types and Objects~ ~NeWS 5: The Extended Input System~ ~NeWS 5.4: The Extended Input System; Selection Overview and Data Structures~ A selection is a piece of data, such as text from a terminal window, that can be copied and pasted from window to window. Selections are used to move data between separate window system applications. There are several different ranks of selections that you can make, but the most frequently used one is called the "primary selection". The CyberSpace deck displays the current primary selection in the field at the top of the scrolling text window. (figure xxx) Selections also come in different types, and the following types are currently recognized: text A string of ASCII text, selected from something like a terminal emulator, text canvas, text editor. object A single PostScript object, of any type. pointer PostScript does not have an explicit notion of a "pointer", but if we consider the meaning, "a way to reference or replace an object in memory," the term "pointer" means a *pair* of PostScript objects: a container and an index, that specify the location of another PostScript object. The container (usually an array or dictionary) holds the object, and the index into the container (usually an integer or name) tells which element of the container the object is. The PostScript operators "get" and "put" take pointers as arguments. ~Red 6.3: get, put~ The advantage of selecting a pointer to an object, rather than the object itself, is that whoever uses the selection is able to tell where the object came from, and/or can replace the selection with a new value. interval A subsequence of an array or string, a contiguous subset of the original elements, sharing the same storage. ~Red 6.3: getinterval, putinterval~ Process ~Red 3.5: Stacks~ ~NeWS 2.1: NeWS Extensions Overview; The Lightweight Process Mechanism~ ~NeWS 11.6: NeWS Type Extensions; Processes as Dictionaries~ Canvas ~NeWS 1.3: Introduction; Canvases~ ~NeWS 2.2: NeWS Extensions Overview; Canvases and Shapes~ ~NeWS 11.3: NeWS Type Extensions; Canvases as Dictionaries~ Event ~NeWS 1.4: Introduction; User Interaction -- Input~ ~NeWS 3: Input~ ~NeWS 11.4: NeWS Type Extensions; Events as Dictionaries~ ======================================================================== ======================================================================== How to Get Started First, you have to be running NeWS. If you don't have a NeWS handy, you can skip to the next section. The CyberSpace deck currently runs under NeWS 1.1, and walks under X11/NeWS Beta 2. (One day it will fly!) Take a look at the file "README" which should be supplied with the CyberSpace deck. It should contain the latest instructions for loading all the files you need to run it. In a directory containing the files the CyberSpace Deck was distributed with, just type "cyber". Or put the .ps files into your NeWS directory (under the directory where you run NeWS), and "psh cyber.ps" to load them all automatically. Or load them in the following order: echo "(debug.ps) LoadFile pop" | psh psh textcan.ps psh piemenu.ps psh pullout.ps psh quickwin.ps psh overlay.ps psh pointer.ps psh distill.ps psh mics.ps psh cyber.ps ======================================================================== ======================================================================== Navigating in CyberSpace There are several ways of giving commands to the CyberSpace Deck. The number of "*"'s to the right of the title of a section tell how important something is if you are learning to use the CyberSpace deck. (The more splats, the more interesting.) Clicking with the Mouse ***** The most commonly used functions can be performed directly by clicking on things with the mouse buttons. What a mouse button does depends exactly on what was underneath the cursor when you clicked the button. For example, the exact word you are on when you bring up a menu is often what the menu will affect. (This differs from most applications where all that matters is what window you are in.) Selecting from Menus **** There are a lot of commands available via pop-up menus, that you can get by clicking the "Menu" button (usually the right button). The menu that pops up applies to whatever was underneath the cursor when you first pressed down on the menu button. Typing PostScript Expressions *** You can type into the scrolling text window (or anywhere else in the CyberSpace Deck window). What you type is interpreted as a PostScript expression, and you can interact with the PostScript interpreter "executive", as you normally can with an "psh" (or "tip" to a laser printer). Pressing Function Keys and Control Characters ** Certain function keys and control characters invoke functions immediately when you type them. There are several different regions on the screen to interact with... The Scrolling Text Window ***** The scrolling text window presents a view of a NeWS process. There is a spike sticking out of the top of the window which represents the process's stack. Text that the process prints to its standard output is put into the text window, and text that you type anywhere in the CyberSpace Deck window is fed into the standard input of the process. At the top of the text window is a banner displaying the current primary selection. Text that you select from a text window, terminal emulator, or other applications goes into the primary selection, along with the objects you select from the deck. Text Window Tab ** You can move the text window around by pressing the Point button (left) down over the tab sticking out of the edge, dragging it to where you want, and releasing. Clicking the Menu button in the text window tab pops up a pie menu of commands affecting the process and text window, as well as a few commands for internal debugging and introspection. Text Display **** You can type commands into the text window, to be interpreted by NeWS. You can edit the text as you type it in, using the Delete or Backspace key to erase characters, and Control-X or Control-U to erase the whole line. There are a lot of other functions bound to control characters and function keys, which you can get a list of by pressing Help, Alternate, or Meta-?. (Todo: define a function called "help" in the initial userdict.) (To type in a "Meta" character on a Sun keyboard, hold down the "Left" key.) One of the most useful keyboard commands is Meta-Esc (or L9), which displays all the keys on the dictionary stack that match the partially typed name in the text window. The scroll bar on the left edge of the text window can be used to scroll through the lines of text that have been typed out in the window. (You'll need to use it to look at the list of key bindings.) Clicking and dragging the Point and Adjust buttons (left and middle) over the characters in the text window selects the text as the primary selection. Clicking the Menu button (right) inside of the text window pops up a menu of commands that operate on the Primary selection. The Background Menu **** If you click the Menu button (right) on the white background of the CyberSpace Deck window, the background menu will pop up. This is a menu of functions that push interesting things onto the stack for you to look at and play with. Pallets... *** A pallet is a dictionary or array of useful functions, that you can open up and execute with the mouse (below). Selecting the name of a pallet from the "Pallets..." submenu pushes a pallet of related functions onto the stack. You can open up a pallet and make its click action click-exec, from the tab menu. (todo: make automatic) The "Debug" pallet is a handy interface to the NeWS debugger (debug.ps). Processes *** This pushes an array of arrays of NeWS processes onto the stack. Each subarray contains all the processes in one process group. (This only works in X11/NeWS.) Framebuffer *** This pushes the framebuffer, the root of the canvas hierarchy, onto the stack. You can open up a canvas editor on the framebuffer to see an array of its children (from the structure "type...canvas editor" submenu) and open up a scroller editor on the array (also from the structure "type...scroller editor" submenu). (todo: make automatic) Windows **** This pushes on the stack a dictionary of every LiteWindow that has an active event manager listening for /DoIt events. The keys of the dictionary are the event managers, and the values are the windows they are managing. Canvases **** This lets you click at a place on the screen, and pushes on the stack an array of the canvases underneath the cursor where you clicked. It draws an "X" shape at the cursor to prompt you to click somewhere. Object **** This pushes the class Object, the root of all other classes, onto the stack. You can open up an class editor on class Object (from the structure "type...class editor" submenu). (todo: make automatic) You can open up Object's arrays of SubClasses and ClassDicts, and open class editors on classes in them, too. You can enter the context of the class or instance (from the structure "type...enter" submenu), and open up scroller editors (from the "type...scroller editor" submenu) on the class editor's arrays of InstanceVars, ClassVars, and Methods, and open up name editors on the names contained therein. (todo: make it open up collections of actual pointers to the objects, so you don't need to enter the object's context, and you can open them up and edit them.) The Data Structure Views ***** Views of PostScript data structures are displayed in windows with tabs sticking out of them. The tabs display the type of data structure being viewed in the window. View Window Tab ***** Moving the View Window ***** You can press the Point button (left) down on a tab, and drag the window around on the screen. When you release the button, the window will stay where it is (usually). If you place it so the tab overlaps the pin sticking out of the top of the scrolling text window, it will be pushed onto the stack. You can move objects around on the stack by dragging them up and down the spike by the tabs. Iconifying the View Window ** If you press the middle button over a structure window tab, it will iconify the window, so it displays only the first level of the data structure, with a rounded line drawn around the inside border. This isn't particularly useful for windows that are only displaying one level of data structure in the first place, but it sure is handy for big deep ones. View Window Tab Menu ***** Pressing the menu button over the tab of a structure window pops up a menu of operations on that whole window. Layout * Recompute the layout of the structure. Updates the display if the structure has changed. Paint ** Redraw the structure. Zap ***** Destroy the view of the data structure. If the window is on the stack, then the object is popped. Zapping a view window does not destroy the displayed data structure itself, unless there are no other references to it, in which case it gets garbage collected automatically. Print * Write out a PostScript program to print out the structure display. This is presently broken, but at least it doesn't seem to crash. Tab... ** Submenu to move the tab to different places around the window. Ignore the names, just select the direction in which you want the tab moved. View... ***** Menu of functions that affect the view of the structure in the window. The attributes you set with this menu can be overridden locally in the individual pieces of structure, with the structure view menu. point size ***** Change the point size at which the top level piece of structure is displayed. Pull out further to get a bigger point size. The size you have selected is displayed in the menu center. shrink *** Change the factor by which the point size diminishes with depth. Pull out further to get a bigger shrink factor. (If it's more than one then it's a grow factor!) The factor you have selected is displayed in the menu center. open *** Open the structure to a certain depth. Pull out further to open it deeper. The depth to which the structure will be opened is displayed in the menu center. Be careful about opening big structures deeper than one or two levels at once, unless you have a lot of time to wait! click proc... * Sets the function to call when you click the Adjust (middle) button on a piece of structure in that window. These are described later, but the most useful one for pallets of functions is "click-exec". An object whose click action is click-exec will be executed when you click the Adjust button on it. Structure View ***** A mouse sensative structural view of PostScript data is displayed inside the view window. You can use the mouse to point at a piece of structure in the display, inspect and manipulate it. No matter how small something is displayed (even in unreadable 1-point text), it is still mouse sensative! (It won't shrink any smaller than a pixel, so you can always point to it.) Selecting Data Structures ***** Clicking once on an object with the Point button (left) will select the object. This actually selects a "pointer" to the object (see above), and you will see it as the current primary selection, displayed in the line labeled "Selected:" at the top of the scrolling text window. You can hold the Point button down and drag the cursor up and down to select other pieces of structure in the same container. The currently selected structure will be displayed in the banner at the top of the scrolling text window. If you hold the shift key down while making a data structure selection, the results you get will depend on the type of the container from which you're selecting. If it's a dictionary, you can select one of its keys. If it's an array, you can drag the cursor up and down to select an array subinterval. Executing Data Structures **** Double clicking the Point button on an object selects it, makes it executable, and executes it. This is useful for calling functions that are displayed on the screen, and for using strings of text, such as previously typed commands selected from a text window, as command buttons. Doing Other Stuff to Data Structures ***** Clicking the Adjust button (middle) on a structure calls the structure's click action, or the default click action of the structure window if the particular piece of substructure does not have its own. There are several different click actions, such as click-exec, click-push, and click-select, but click-transfer is the default. The Default Click Action ***** Here are the three ways to use "click-transfer": Open/Close Structure ***** Press and release the Adjust (middle) button over a composite object like a dictionary, an array, canvas, or process. The structure will open up one level deep (or close if it was already opened). Transfer to Background ***** Press the Adjust button over an object, and holding it down, drag the object out over the background. When you release the button, a new view window will appear on the background. It will contain a copy of the object you just dragged out. Transfer to Structure ***** If you drag an object over to another structure window (or to the same one, but over a different piece of substructure), and release the button, the object will be pasted into the structure underneath the cursor when you released the button. Now you are actually editing PostScript data structures! Be careful! You can severly hose your NeWS server if you start pasting things into system data structures or functions. Make a few of your own dictionaries and arrays to play around with! Structure Menu ***** If you click the Menu button (right) over a piece of structure, you will pop up a structure menu with lots of functions which operate on the object under the cursor at the time you pressed the Menu button. push ***** Push the object onto the stack. exec ***** Make the object executable, and execute it. paste ***** Paste the primary selection into the place of the object under the cursor. This actually edits PostScript data structures! See the above warning in the description of click-transfer! open... **** Submenu of functions to open up an object in different ways. Pull out further to open it deeper. The depth to which the structure will be opened is displayed in the menu center. change... *** Submenu of functions that perform type conversions on the object (or at least they try). view... **** Submenu of functions that affect the local view of the piece of structure. Similar to the view submenu on the structure window tab, except that these functions apply just to the piece of structure under the cursor and its children, not all pieces of structure in the window. etc... ** Submenu of random but useful functions that wouldn't fit anywhere else. The "Molecule" function pops up a pseudo-scientific visualizer view of the PostScript data structure under the cursor. type... ***** Pops up a type-specific submenu of functions that apply to the object under the cursor at the time you popped up the structure menu. Which menu you get depends on the type of the object. ======================================================================== ======================================================================== Type Specific Functions ======================================================================== Editors boolean canvas class definitions digit element filter scroller shift step user ======================================================================== Pallets Window Debug ======================================================================== Debugging break-cont break-copy&cont break-enter break-exit break-kill break-list clear enter-it exit fix-typo push-dictstack push-execstack push-process show-dictstack show-execstack ========================================================================