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-name | This 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-x1 | The first (leftmost) column of the TVOB's area of the screen.
|
tvob-y1 | The 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-x2 | The first (leftmost) column to the right of the TVOB's area of the screen.
|
tvob-y2 | The 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-handler | A function, described below.
|
tvob-info | This field may contain anything at all; it is meant to be used by the
tvob-handler function.
|
tvob-job | The job associated with this TVOB, or nil if there is no associated
job.
|
tvob-priority | Either 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-screen | The screen on which this TVOB is displayed. See this link.
|
tvob-status | This field is provided for the convenience of tvob-handler functions.
It contains one of the following symbols:
:selected | The TVOB is the selected TVOB. Only one TVOB will have this tvob-status .
|
:exposed | The 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.
|
nil | The 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-plist | A 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.
:expose | The TVOB is being made exposed. This command is only sent
when the TVOB is active and not exposed.
|
:deexpose | The TVOB is no longer exposed. This command is only sent when
the TVOB is active and exposed.
|
:select | The TVOB is now selected. This command is only sent when the TVOB
is exposed and not selected.
|
:deselect | The TVOB is no longer selected. This command is only sent when the TVOB
is selected.
|
:clobber | This 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.
|
:update | This 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-edges | The 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-name | The 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-tvobs | A list of all TVOBs associated with this job.
|
job-processes | A 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-handler | The value of the :handler option.
|
tvob-info | The value of the :info option.
|
tvob-job | The 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-priority | The value of the :priority option.
|
tvob-x1 | x1 .
|
tvob-y1 | y1 .
|
tvob-x2 | x2 .
|
tvob-y2 | y2 .
|
tvob-screen | The value of the :screen option, which should be a screen. It defaults
to the value of tv-default-screen .
|
tvob-status | The 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:
:handler | The tvob-handler function.
|
:info | The value to go in the tvob-info field.
|
:job | The 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-handler | The 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.
|
:name | The print-name of the TVOB.
|
:priority | t to make this TVOB more tenacious of its place on the screen.
|
:screen | The 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.]