<*PRAGMA LL*>The
VBTRep
interface defines the representation of VBTs
, and provides
operations that are useful for implementing low-level or esoteric
split classes.
INTERFACETo save space in aVBTRep ; IMPORT Batch, Cursor, PropertyV, Rect, Region, ScreenType, ScrnPaintOp, ScrnCursor, ScrnPixmap, ScrnFont, VBT, VBTClass, Word, PaintPrivate, Axis, Palette, PaintOp, Font, Pixmap; CONST EmptyCage = VBT.EmptyCage; TYPE MiscRef = REF MiscRec; MiscRec = RECORD cage := EmptyCage; badRgn := Region.Empty; rpseqno: Word.T; oldDomain := Rect.Empty; link: MiscRef := NIL END;
VBT
, the cage
, badRgn
, rpseqno
, and
oldDomain
fields are only stored if at least one of them has an
``unusual'' value. This is achieved by including a MiscRef
in the
VBT
object. If the MiscRef
is NIL
, then the badRgn
and oldDomain
are empty, the rpseqno
is irrelevant, and the cage is determined
from the cagetype
field as follows: if the cagetype
is
VBT.CageType.Rectangle
, then the cage rectangle is assumed to be
Rect.Empty
; otherwise the rectangle is irrelevant.
The rpseqno
field is the {\it repainting sequence number}. It is
incremented whenever the badRgn
is expanded and recorded before
activating a repaint
method. Thus when the repaint method returns,
the current value can be compared with the recorded value to
determine whether the current badRgn
is the one that the repaint
method responded to, or whether a new bad region arrived while the
client was responding to the old one.
TYPE Prop = {EscapePending, Reshaping, RepaintPending, OnQ, Covered, Combiner, ShortCircuit, CageCovered, Marked, ExcessBegins, HasNewShape, BlockNewShape, EscapeCovered}; Props = SET OF Prop; CONST AllProps = Props{FIRST(Prop)..LAST(Prop)}; NoProps = Props{};Here is the meaning of the properties:
EscapePending
: Set when a thread of control is forked to deliver a
cage escape to gone. Set to FALSE
when any position is delivered.
Reshaping
: set when the VBT
has a non-empty old domain.
RepaintPending
: Set when a thread of control exists that will deliver
the bad region.
OnQ
: Set when the VBT
is on the Metermaid
's to-be-serviced queue.
Covered
: Ordinarily painting into an empty batch will put the
VBT
on the Metermaid
's queue and set onQ
. If the covered
bit is set, this will not happen. For example, PutPosition
sets
covered
before passing the position to child, and clears it and
forces the batch before it returns. Only set during event delivery,
so any action that could be deferred until after event delivery can
check covered
and clean up on method exit.
Combiner
: Set to indicate that this VBT
is a good place to pile up
small paint batches, even if it is not covered. Trestle sets this bit
in one VBT
near the root of a client address space to avoid shipping
many small batches across RPC
.
ShortCircuit
: Set on a VBT
when painting on the VBT can be
implemented by clipping to the VBT
's domain and painting on its
parent.
Marked
: set by VBT.Mark
.
CageCovered
: VBTClass.PutPosition
sets this bit on a VBT
before
calling its position method; after calling the position method,
the procedure relays the child's cage to the parent and clears
the bit. VBTClass.SetCage
notices the bit and omits relaying the
cage to the parent.
ExcessBegins
: Set when excessBegins > 0
.
HasNewShape
is set when VBT.NewShape
is called, and cleared by
a call to VBTClass.HasNewShape
or VBTClass.GetShape
.
If BlockNewShape
is set, VBT.NewShape
calls will not be relayed
to the parent of the VBT
.
REVEAL VBT.Prefix = VBTClass.Prefix BRANDED OBJECT <* LL >= {SELF} *> cursor := Cursor.DontCare; cageType: (*BITS 16 FOR*) VBTClass.VBTCageType := VBTClass.VBTCageType.Gone; props: (*BITS 16 FOR*) Props := NoProps; batch: Batch.T := NIL; remaining: INTEGER := 0; propset: PropertyV.Set := NIL; miscRef: MiscRef := NIL; OVERRIDES getcursor := GetcursorDefault; axisOrder := AxisOrderDefault; END;The
batch
field contains the batch of uncompleted painting commands
for the VBT
, and remaining
contains the number of free addressable
units remaining in the batch
. In particular, if remaining # 0
, the
batch
field is not NIL
. The miscRef
field is always NIL
if the parent is NIL
.
REVEAL VBT.ScreenType <: STPub; TYPE STPub = ScreenType.Public OBJECT ops: REF ARRAY OF ScrnPaintOp.T; cursors: REF ARRAY OF ScrnCursor.T; pixmaps: REF ARRAY OF ScrnPixmap.T; fonts: REF ARRAY OF ScrnFont.T METHODS opApply(cl: Palette.OpClosure; op: PaintOp.T): ScrnPaintOp.T; cursorApply(cl: Palette.CursorClosure; cs: Cursor.T): ScrnCursor.T; pixmapApply(cl: Palette.PixmapClosure; pm: Pixmap.T): ScrnPixmap.T; fontApply(cl: Palette.FontClosure; ft: Font.T): ScrnFont.T END;The tables
st.ops
, st.fonts
, st.cursors
, and st.pixmaps
are
collectively called the screentype's {\it palette}. They are used
to translate between screen-independent resources and
screen-dependent resources. For example, recall that Pixmap.Gray
is a record containing the integer field Pixmap.Gray.pm
. The
screen-dependent equivalent of Pixmap.Gray
on the screentype st
is simply st.pixmaps[Pixmap.Gray.pm]
. When creating the palette,
the above apply methods are called for all resources; if cl is NIL, the
resource is built-in. The default values for these return the result of
invoking the closure or the built-in method; your procedure must not
return NIL when invoked on a built-in.
TYPE OffscreenType = VBT.ScreenType OBJECT st: VBT.ScreenType END;An
OffscreenType
s
, is a screen type that is derived from the screen
type s.st
. An OffscreenType will be replaced by its associated
screentype in calls to Trestle.InstallOffscreen
. The st
field
is read-only after creation.
PROCEDURE CheckMisc(v: VBT.T); <* LL >= {v} *>
Setv.misc := NIL
ifv
'sbadRgn
andoldDomain
are empty and its cage type is notRect
.
PROCEDURE CreateMisc(v: VBT.T); <* LL >= {v} *>
Ifv.misc = NIL
, then create amisc
forv
with emptybadRgn
andoldDomain
, and with appropriate cage. Otherwise, do nothing.
PROCEDURE DestroyMisc(v: VBT.T); <* LL >= {v, v.parent} *>
Setv
's misc toNIL
, clearingReshaping
fromv.props
.
PROCEDURE NewBatch(v: VBT.T; len: INTEGER := -1); <* LL.sup = v *>
Forcev
's batch if it is non-nil and allocate a new batch for it of size at leastlen
, or of sizeVBTTuning.BatchSize
iflen=-1
.
PROCEDURE ForceBatch(v: VBT.T); <* LL.sup = v *>
Force v
's batch if it is non-nil, and leave it nil.
PROCEDURE CancelBatch(v: VBT.T); <* LL.sup = v *>
Freev
's batch and set it toNIL
.
PROCEDURE Enqueue(v: VBT.T); <* LL.sup = v *>
Placev
on the list ofVBTs
scheduled to be serviced by the MeterMaid.
PROCEDURE GetcursorDefault(v: VBT.Prefix): ScrnCursor.T;
Return the result of resolvingcursor(v)
usingv
's screentype.
PROCEDURE AxisOrderDefault(v: VBT.Prefix): Axis.T;
Return Axis.T.Hor
.
PROCEDURE ExpandBadRect(w: VBT.T; READONLY clp: Rect.T; ba: Batch.T); <* LL.sup = w *>
Expandw
's bad region forba
.
In
ExpandBadRect
, the rectangle clp
is the original clipping
rectangle for ba
, before intersection with w.domain
. The
expansion is caused by (a) using out-of-domain bits as source (b)
painting into the old domain (c) scrolling an existing bad rectangle.
PROCEDURE ExtendBatch(v: VBT.T; VAR ba: Batch.T);
Extendv
's batch to include the painting operations inba
, and freeba
. It is assumed thatv
has a non-empty batch which has room for the extension.
PROCEDURE MaxRepeat(v: VBT.T): CARDINAL; <* LL.sup = v *>
Return the number of RepeatRec's that can fit in v
's current batch.
PROCEDURE PaintRepeat(v: VBT.T; READONLY clip: ARRAY OF Rect.T); <* LL.sup = v *>
Add aRepeatRec
tov
's batch for each rectangle inclip
.
PaintRepeat
is a checked run-time error if there isn't enough space
in v
's batch. Calling PaintRepeat
does not call
Enqueue(v)
.
PROCEDURE PaintSingle(v: VBT.T; READONLY clip: Rect.T; com: PaintPrivate.CommandPtr); <* LL.sup = v *>
Add the paint operation referenced bycom
tov
's batch, but use the clipping rectangleclip
instead of the one incom
.
PaintSingle
forces v
's batch if necessary and allocates a new
one. It does not call Enqueue(v)
. The command com
must not be a
scroll command.
PROCEDURE Scroll(v: VBT.T; READONLY clip: Rect.T; com: PaintPrivate.ScrollPtr); <* LL.sup = v *>
LikePaintSingle
, butcom
must be a scroll command.
PROCEDURE Mark(v: VBT.T); <* LL >= {v} *>
Identical to VBT.Mark
except for the locking level.
PROCEDURE Redisplay(); <* LL.sup = VBT.mu *>
Redisplay and unmark all marked windows whose screentype is non-NIL
.
That is,
Redisplay
is equivalent to this loop:
LOOP WITH m = an array containing all marked windows DO IF NUMBER(m) = 0 THEN EXIT END; Sort m in order of non-decreasing depth; FOR i := 0 TO LAST(m) DO IF IsMarked(m[i]) AND m[i].st # NIL THEN Unmark(m[i]); m[i].redisplay() END END END ENDThe depth of a window is the number of parent pointers that must be followed to reach
NIL
. Sorting by depth guarantees that
ancestors will be redisplayed before their descendants. The reason
is that redisplaying an ancestor window often reshapes its
descendants, and if a descendant is going to be reshaped it would
be wasteful to redisplay it in its old position.
Ordinarily when a window is marked, a thread is forked that will
call Redisplay
. This is wasteful if Redisplay
will be called
soon anyway. Therefore, if you know that Redisplay
will be called
soon, you can call CoverRedisplay
, which increments a ``coverage
counter''. If the coverage counter is non-zero, marking a VBT
does not fork a thread. Of course by calling CoverRedisplay
you
acquire the obligation to ensure that Redisplay
will be called
soon. Calling UncoverRedisplay
decrements the counter and calls
Redisplay
if the result is zero.
PROCEDURE CoverRedisplay(); <* LL.sup = VBT.mu *>
Increment the redisplay coverage counter.
PROCEDURE UncoverRedisplay(); <* LL.sup = VBT.mu *>
Decrement the redisplay coverage counter and call Redisplay
if
the result is zero.
END VBTRep.