30. TVOBs and Jobs
[The subject of this chapter is currently being redesigned. The contents of this chapter will be completely changed in the next edition of this manual.]
30.1 Introduction to the Concepts of This Chapter

TVOBs (TV OBjects) represent permission to use the TV screen. The TVOB mechanism is provided to allow the TV to be shared between all of the activities the user may be conducting, without those activities getting in each other's way.

A job is a collection of processes and TVOBs,ed together for the user's convenience. The processes can be started and stopped together, and the TVOBs can be put on or taken off the TV together.

30.2 Introduction to the Concepts of This Chapter
A TVOB (TV OBject) is a Lisp structure with the following components: 3
tvob-nameThis is the name of the TVOB, as a string. It is only used for the TVOB's printed representation, and can be anything reasonably mnemonic.
tvob-x1The first (leftmost) column of the TVOB's area of the screen.
tvob-y1The first (highest) line of the TVOB's area of the screen. The tvob-x1 and tvob-y1 are the co-ordinates of the upper-left-hand corner of the TVOB's rectangular area.
tvob-x2The first (leftmost) column to the right of the TVOB's area of the screen.
tvob-y2The first (highest) line below the TVOB's area of the screen. The tvob-x2 and tvob-y2 are the co-ordinates of the lower-right-hand corner of the TVOB's rectangular area, with 1 added to each. Thus the height of the tvob is the difference between its tvob-y2 and tvob-y1 , and the width is the difference between the tvob-x2 and tvob-x1 .
tvob-handlerA function, described below.
tvob-infoThis field may contain anything at all; it is meant to be used by the tvob-handler function.
tvob-jobThe job associated with this TVOB, or nil if there is no associated job.
tvob-priorityEither t or nil . If it is t , the functions which allocate area on the screen (tvob-create and tvob-create-expandable , see LINK:(tvob-create-fun)) will be reluctant to allocate over this TVOB's area of the screen.
tvob-screenThe screen on which this TVOB is displayed. See this link.
tvob-statusThis field is provided for the convenience of tvob-handler functions. It contains one of the following symbols:
:selectedThe TVOB is the selected TVOB. Only one TVOB will have this tvob-status .
:exposedThe TVOB is not selected, but is on exposed-tvobs . This means that this TVOB is not covered by any other TVOB; its screen area is fully exposed.
nilThe TVOB is not on exposed-tvobs .
tvob-clobbered-p
This field is provided for the convenience of tvob-handler functions. It is t if the TVOB has been sent a :clobber or :set-edges command more recently than an :update command; otherwise it is nil .
tvob-mouse-handler
A function to call when the mouse enters this TVOB's screen region. This allows the TVOB to take over control of the mouse. This field is nil if this TVOB does not do anything special with the mouse.
tvob-mouse-action
See mouse-default-handler (LINK:(mouse-default-handler-fun)).
tvob-plistA disembodied property list. Use, for example, (get (locf (tvob-plist tvob)) 'mumble) .
It is often useful to divide the TV screen up into several parts, and do different things in each part. Sometimes one program wants to split up the screen, as Eine does; sometimes the user wants to run several programs at once, and each program wants some space on the screen. At any time, there is a set of active TVOBs (TV objects) which are sharing the screen. Each TVOB has a rectangular piece of the screen on which it does its displaying; it is not allowed to go outside its area. It is possible for two active TVOB's regions of the screen to overlap. When this happens, only one of them is exposed (fully visible); the other is partially or fully buried. There is a subset of the active TVOBs called the exposed TVOBs; no two exposed TVOBs overlap. The TVOBs act as if they were a bunch of rectangular sheets of paper on a desktop; some are up at the top, and others are partially buried. Various programs can "pull" a non-exposed TVOB up to the top, making it exposed and making some other TVOB(s) non-exposed. Several functions of the job system, explained below, keep track of and change which TVOBs are active, and which are exposed. The job system also keeps track of one TVOB called the selected TVOB . Conceptually, the selected TVOB is the one in which the user is interested at the moment, and it is usually the one that is responding to the keyboard. For example, when Eine is being used, the TVOB of the window in which the user is editing is the selected TVOB. The selected TVOB is always exposed. A TVOB's being selected, exposed but not selected, or not exposed at all is called the TVOB's status . Usually a program will want certain actions to be taken when the status of a TVOB changes. When the TVOB associated with an Eine window becomes exposed, Eine generally wants to redisplay the window, and when the TVOB is selected, Eine starts blinking the window's blinkers and makes its buffer be the current buffer. In order to let a user program know that the status of a TVOB has changed, so that it can do these things, there is a function called the handler associated with every TVOB. When the status of the TVOB changes, its handler is applied to three arguments: the TVOB itself, a keyword symbol indicating what kind of change of status is occurring, and a list of other information whose meaning is dependant on the value of the second argument. The applications of this function can be thought of as a "command" being sent to the TVOB. For example, when a TVOB becomes selected, it is "sent a command" telling it so; that is, the handler is applied to the TVOB, the keyword :select , and nil . Here is a list of all of the keyword symbols (i.e. all of the kinds of commands) that are used. In addition to status changes, requests for the TVOB to update and relocate itself cause the handler to be invoked.
:exposeThe TVOB is being made exposed. This command is only sent when the TVOB is active and not exposed.
:deexposeThe TVOB is no longer exposed. This command is only sent when the TVOB is active and exposed.
:selectThe TVOB is now selected. This command is only sent when the TVOB is exposed and not selected.
:deselectThe TVOB is no longer selected. This command is only sent when the TVOB is selected.
:clobberThis command means that for some reason, the TVOB's area of the screen has been altered; future :update and :clean commands should not assume that the screen is as it was left. Most TVOBs will ignore this message, since the information is saved in the tvob-clobbered-p element of the TVOB (see below). This command is only sent when the TVOB is exposed.
:updateThis command is only sent when the TVOB is exposed. The TVOB should assure that its area of the screen contains whatever it is supposed to contain. Just what :update means depends on the program. Some programs can remember the contents of what is on the TVOB and can refresh it at will; others do not remember the contents, and cannot reconstruct them. The former kind, upon receiving the :update command, should update the TVOB. If the TVOB has not been clobbered, the handler can assume that whatever it last put there is still there, and it may be able to avoid redisplaying. The tvob-clobbered-p field of the TVOB is set to t by the job system after a :clobber or :set-edges command is sent, and to nil after an :update or :clean command is sent. The handler can determine whether or not its area of the screen has been clobbered by simply looking at the tvob-clobbered-p . The latter kind of TVOB cannot update, and should ignore the :update command entirely.
:clean:clean is like :update except that TVOBs of the kind that cannot refresh themselves should clear their areas instead of doing nothing. Like :update , this command is only sent when the TVOB is exposed. :clean is sent to all exposed TVOBs when the user requests that the screen be cleaned up; for instance when the FORM key is pressed in most programs.
:set-edgesThe TVOB should change its area of the screen. This command takes four arguments: the new left edge, top edge, bottom edge, and right edge, in raster units. The first two are inclusive, and the other two are exclusive. The elements of the TVOB structure that hold the screen area (tvob-x1 etc.) will be updated automatically; the handler need not change them itself. The handler should update any other associated information; for example, if the TVOB has an associated "piece of paper", it should call tv-redefine-pc-ppr (see LINK:(tv-redefine-pc-ppr-fun)).
The tvob-info component of the TVOB is provided to give the handler somewhere to put its internal state. It is usually some kind of structure, depending on what program created the TVOB. For example, it might be a piece of paper (see this link).
30.3 Introduction to the Concepts of This Chapter
A job is a Lisp structure with the following components: 3
job-nameThe name of the job, as a string. This is only used for the printed representation of the job or for display by programs, and may be anything reasonably mnemonic.
job-tvobsA list of all TVOBs associated with this job.
job-processesA list of all processes associated with this job.
job-enabled-tvobs
A list of this job's enabled tvobs. Each TVOB on this list is also on the job-tvobs list. The order of the enabled tvobs list is "highest" first; this list is sometimes passed to tvob-setup .
job-enabled-processes
A list of this job's enabled processes. This list is a subset of the job-processes list.
job-tvob-enabled-p
If this is non-nil , this job is tvob-enabled ; its enabled TVOBs are active.
job-process-enabled-p
If this is non-nil , this job is process-enabled ; its enabled processes are active.
job-who-line-process
Whenever this job becomes the kbd-job , the process in this component becomes the tv-who-line-process (The process whose process-whostate is displayed in the who-line) (see LINK:(tv-who-line-process-var)).
job-tvob-selector
nil , or a function which is called by tvob-setup (see LINK:(tvob-setup-fun)) when this job is current and a new selected-tvob is needed. The function takes no arguments and doesn't return anything in particular. It isn't required to do anything, but it normally should call tvob-select with an appropriate TVOB.
job-forced-input
If non-nil , a character or a string which is forced input for this job. This is a character or characters which are pretending to come from the keyboard but really originated from another process or the mouse. See the function force-kbd-input (LINK:(force-kbd-input-fun)).
job-forced-input-index
Index into job-forced-input when it is a string.
At any time, the user of the Lisp Machine may be conducting several different activities. For example, he may want to temporarily stop editing in order to send some mail; he might want to start up a file transfer, and while waiting for it to finish, continue editing. Each such activity, in general, will want some processes to do computation, and some pieces of the screen (TVOBs) on which to do output. When the user is not concerned with some activity, he may want its processes to stop, and/or its TVOBs to stop displaying. In order to make it easy to deactivate a set of processes and TVOBs, such a set may beed together as a job . Every job has a set of processes and TVOBs; these sets are represented by the lists in the job-processes and job-tvobs of the job. Of each set, there is a subset that is enabled ; these are the job-enabled-processes and job-enabled-tvobs of the job. A process's being enabled means that whenever the job is told that it may run, that process will be made active . The same is true for TVOBs. When the job is told that it may run its enabled processes, it is said to be process-enabled ; when it is told that it may display its enabled TVOBs, it is said to be tvob-enabled . A job can control which of its processes and TVOBs are enabled by means of the functions process-enable , process-disable , tvob-enable , and tvob-disable , which are described below. At any time there is one job which is said to "own the keyboard"; this job is the value of the variable kbd-job . When a function calls any of the keyboard input functions (such as kbd-tyi ), the function will wait until the current job is the kbd-job before returning. The reason for this is that while the TV can be split up into areas so that several programs can type on it at once, there is no similar way to split up the keyboard; if several jobs want keyboard input, one of them will get what the user types, and the rest will wait until they become the kbd-job . When Lisp is initialized, one job is created and given the keyboard. The job is given a single, active TVOB, the size of the screen, and a single, active process. It is both process-enabled and TVOB-enabled, so the process and TVOB are both active.
30.4 Introduction to the Concepts of This Chapter
It should be made easy for the user to control which jobs are process-enabled and which are TVOB-enabled. Unfortunately, the commands to allow easy control of these parameters have not yet been fully developed. This section describes what has been implemented so far, but this will probably change. The following two simple functions control whether a job is process-enabled or TVOB-enabled.
job-set-process-state job state
If state is non-nil , job is made process-enabled; otherwise, it is made process-disabled.
job-set-tvob-state job state
If state is non-nil , job is made TVOB-enabled; otherwise, it is made TVOB-disabled. Since this function can change the set of active TVOBs, the caller should follow with a call to tvob-setup (see LINK:(tvob-setup-fun)).
There is one job designated as the top-level job, from which other jobs are selected. This job is the value of the variable si:top-job . When Lisp is initialized, si:top-job is set to the initial job, and usually it is never set again. If this job wants to let some other job run, it uses the function job-select , which may be called directly by the user, or by a program's "command interface" function. (The functions ed , edval , and edprop serve this purpose for Eine, and the function supdup for the Supdup program.)
job-select job
job-select should be called from the top-level job to give the keyboard to job . The top-level job is made process-disabled and TVOB-disabled, and job is made process-enabled and TVOB-enabled, and is given the keyboard (made to be the kbd-job ).
When the keyboard belongs to some job other than the top-level job, 'setq call-key page the "CALL" key is interpreted specially to mean "Return the keyboard to the top-level job." If the user types a "CALL", the current kbd-job will be made process-disabled and TVOB-disabled, the top-level job will be made process-enabled and TVOB-enabled, and the top-level job will be given the keyboard. The Control and Meta keys can be used with CALL: Control prevents the current kbd-job from being made TVOB-disabled, and Meta stops it from being process-disabled.
30.5 Introduction to the Concepts of This Chapter
The following four functions are all used to create TVOBs; they differ primarily in the way the caller specifies the TVOB's area of the screen. To fully specify the area, use tvob-create-absolute . If you just want an area of a certain size, but don't care where the area is, use tvob-create . If you need at least a certain size but would accept a larger size if the space is available, use tvob-create-expandable . If you have a pc ppr (piece of paper) and want to make a TVOB for it, use tvob-create-for-pc-ppr .
tvob-create-absolute x1 y1 x2 y2 &rest options
tvob-create-absolute creates and returns a new TVOB. Its fields are set up as follows:
tvob-handlerThe value of the :handler option.
tvob-infoThe value of the :info option.
tvob-jobThe value of the :job option. If it is t , the current job is used instead; this is the default. Otherwise it should be nil (meaning that the TVOB is not associated with any job), or a job.
tvob-priorityThe value of the :priority option.
tvob-x1x1 .
tvob-y1y1 .
tvob-x2x2 .
tvob-y2y2 .
tvob-screenThe value of the :screen option, which should be a screen. It defaults to the value of tv-default-screen .
tvob-statusThe value of the :status option.
tvob-clobbered-p
nil .
tvob-mouse-handler
The value of the :mouse-handler option. If the value is t , use the default mouse handler.
The options to tvob-create-absolute are:
:handlerThe tvob-handler function.
:infoThe value to go in the tvob-info field.
:jobThe job with which the TVOB will be associated. t means the current job and nil means no job. The default is the current job.
:mouse-handlerThe tvob-mouse-handler function. nil means this TVOB doesn't do anything special with the mouse, and t means the mouse-default-handler should be used.
:nameThe print-name of the TVOB.
:priorityt to make this TVOB more tenacious of its place on the screen.
:screenThe screen on which the TVOB will appear. The default is tv-default-screen .
tvob-create x y &rest options
This allocates an area of the screen of width x and height y , and creates and returns a TVOB with that area. The options are the same as for tvob-create-absolute . The screen area of the TVOB will be within the rectangular boundaries described by the screen-x1 , screen-y1 , screen-x2 , and screen-y2 of the screen on which the TVOB is created. tvob-create tries to choose an area that will overlap the fewest interesting TVOBs. Specifically, it tries to stay out of the area used by the exposed TVOB of the highest priority, then that of the exposed TVOB of the second-highest priority, etc. The way priority works is that the exposed tvobs are divided into twos: those with tvob-priority of t , and those with tvob-priority of nil ; the former all have higher priority than the latter. Within these twos, the TVOBs are ordered by their ordering in the list active-tvobs . The priority is remembered by the ordering of the list exposed-tvobs , of which the first element is the TVOB of lowest priority, and the last is the TVOB of highest priority.
tvob-create-expandable min-x min-y &optional max-x max-y &rest options
This first finds a min-x by min-y area of the screen, the same way tvob-create does. Then it tries to make that area larger, up to max-x by max-y , without overlapping any other exposed TVOBs. Otherwise it is like tvob-create . max-x defaults to the size of the area in which automatic allocation takes place: the difference between the screen-x2 and screen-x1 of the screen. max-y defaults similarly.
tvob-create-for-pc-ppr pc-ppr &rest options
If you want to use a pc ppr, you need an associated TVOB in order to get permission for your pc ppr to use the screen. This function takes a pc ppr and creates a TVOB, whose area of the screen is that of the pc ppr. The tvob-info will be the pc ppr, the tvob-handler a function called si:pc-ppr-tvob-handler (which does the right thing for pieces of paper which don't remember what they are displaying and hence cannot :update ), and the screen used will be the pc-ppr-screen of the pc ppr. If you give the :handler option, though, it will override the si:pc-ppr-tvob-handler . The rest of the options are the same as in tvob-create-absolute .
tvob-kill tvob
This deactivates tvob if it is active, and dissociates it from its associated job (if any).
tvob-enable tvob
Enable tvob . If tvob has no associated job, or if its job is tvob-enabled, activate tvob . After making some calls to tvob-enable and tvob-disable , the caller should call tvob-setup (see LINK:(tvob-setup-fun)).
tvob-disable tvob
Disable tvob . If it was active, deactivate it. After making some calls to tvob-enable and tvob-disable , the caller should call tvob-setup (see LINK:(tvob-setup-fun)).
tvob-setup no-reselection &rest tvobs
This is the function in charge of keeping the state of the screen and the internal database consistent when tvobs are activated, deactivated, moved, etc. After a program makes some calls to tvob-enable and tvob-disable , it may have changed the set of active TVOBs, and it should call tvob-setup to make sure that the set of exposed TVOBs is recomputed, and that the right messages are sent to all TVOBs. (If tvob-enable etc. did that themselves, then unneccesary redisplay and computation would be unavoidable.) The job-set-tvob-state function can also change the set of active TVOBs, and it too should be followed by a call to tvob-setup . tvob-setup looks at its argument, tvobs , and at the list of active TVOBs and figures out which TVOBs should be exposed. First, tvob-setup examines the elements of tvobs , all of which should be active, and rearranges the order of active-tvobs . The TVOBs in tvobs are moved to the front of active-tvobs , and placed in the order they were given to tvob-setup . The first TVOB in tvobs is guaranteed to be first in active-tvobs . The remaining active TVOBs are moved to the end of active-tvobs . Their relative order is not changed. The job-enabled-tvobs lists of the TVOB's jobs are similarly reordered. Next, tvob-setup figures out the new subset of the active TVOBs that should be exposed, by walking down the active-tvobs list and taking every TVOB that doesn't overlap with some TVOB already on the new exposed-tvobs list. Since the new list starts out as nil , the first element of active-tvobs , which was the second argument to tvob-setup , will always be exposed. The exposed list is kept in reverse priority order, as explained under tvob-create (see LINK:(tvob-create-fun)). Having determined the new set of exposed tvobs, tvob-setup sends out :deselect , :deexpose , and :expose commands as needed. It only sends :deselect if the selected tvob would no longer be exposed; when it does this, it also sets selected-tvob to nil . At this point, exposed-tvobs is set to its new value. tvob-select then sends :clobber and :update commands to all of the new exposed TVOBs. Finally, if there is no selected-tvob , and no-reselection is nil , tvob-setup tries to choose a new selected-tvob by calling the job-tvob-selector function of the kbd-job (if there is a kbd-job and it has a job-tvob-selector ).
tvob-select tvob
This makes tvob be the selected-tvob . It makes sure that tvob 's job is TVOB-enabled, and that tvob is exposed. Then it deselects the current selected-tvob (if any) and selects tvob .
tvob-update tvob
If the variable tvob-complete-redisplay is non-nil , set it to nil and call tvob-complete-redisplay . Otherwise send an :update message to all exposed TVOBs.
tvob-complete-redisplay Variable
Used as a flag by tvob-update (see above): if non-nil , tvob-update should do a tvob-complete-redisplay .
tvob-complete-redisplay tvob
Clears the screen, outlines the screen area of partially-exposed enabled TVOBs, and sends :clobber and :update to all exposed TVOBs.
tvob-clean tvob
This "cleans up" the screen. It sends a :clean message to all exposed TVOBs, and clears portions of the screen not occupied by exposed TVOBs.
tvob-command command tvob &rest arguments
Sends command to tvob , with the given arguments . command should be one of the symbols mentioned above (:set-edges , :clobber , etc.). After sending the command, tvob-command updates the tvob 's tvob-status , tvob-clobbered-p , or the screen area (tvob-x1 et. al.) as appropriate. In order to preserve consistency, only the tvob-setup and tvob-select functions should send any of the commands :select , :deselect , :expose , and :deexpose ; you should never send these yourself.
tvob-under-point x y &optional screen
Returns the TVOB under the point (x ,y ) on screen , or nil if there is none. If there are several TVOBs at that point, the "top-most" one, i.e. the one which is actually visible, is returned. screen defaults to tv-default-screen .
30.6 Introduction to the Concepts of This Chapter
job-create name
Creates and returns a job, whose name is name . The job is created with no processes and no TVOBs, and its initial job-process-enabled-p and job-tvob-enabled-p are both nil . job-create also puts the job on job-list .
job-kill job
Deactivates and kills all of job 's processes and TVOBs, and removes job from the job-list .
job-list Variable
A list of all jobs. See job-create and job-kill .
job-reset-processes job
Disables all of job 's enabled processes, and unwinds those processes's stacks.
job-select job
This is meant to be called from the top-level job, which should have the keyboard at the time. It disables the kbd-job 's processes and TVOBs, enables those of job , and gives job the keyboard.
job-return job
This is meant to be called from jobs other than the top-level job. It disables the current job's processes and TVOBs, enables those of the top-level job, and gives the top-level job the keyboard. [The job calling it had better have the keyboard.]