-- PrintTV.mesa
-- Russ Atkinson, September 1, 1982 8:00 pm

DIRECTORY
Rope USING [ROPE],
RTBasic USING [nullType, TV, Type],
WorldVM USING [Address, World];

PrintTV: CEDAR DEFINITIONS
= BEGIN OPEN Rope, RTBasic, WorldVM;

PutProc: TYPE = PROC [data: REF, c: CHAR];
PutClosure: TYPE = RECORD [proc: PutProc, data: REFNIL];
NullPutClosure: PutClosure = [NIL, NIL];
-- note: the only error that will always terminate printing is ABORTED

Print: PROC
[tv: TV, put: PutClosure, depth: INT ← 4, width: INT ← 32, verbose: BOOLFALSE];
-- print the TV
-- if verbose, then print extra information as available

PrintType: PROC
[type: Type, put: PutClosure, depth: INT ← 4, width: INT ← 32, verbose: BOOLFALSE];
-- print the type
-- if verbose, then print extra information as available

PrintArguments: PROC
[tv: TV, put: PutClosure,
depth: INT ← 4, width: INT ← 32, breakBetweenItems: BOOLFALSE];
-- print the arguments to the given local frame
-- the depth and width args apply to the individual printing
-- an error msg is printed if this is not a local frame
-- breakBetweenItems causes a line break between arguments

PrintResults: PROC
[tv: TV, put: PutClosure,
depth: INT ← 4, width: INT ← 32, breakBetweenItems: BOOLFALSE];
-- print the results for the given local frame
-- the depth and width args apply to the individual printing
-- an error msg is printed if this is not a local frame
-- breakBetweenItems causes a line break between arguments

PrintVariables: PROC
[tv: TV, put: PutClosure,
depth: INT ← 4, width: INT ← 32,
all, breakBetweenItems: BOOLTRUE];
-- print the results for the given local frame
-- the depth and width args apply to the individual printing
-- an error msg is printed if this is not a local frame
-- if all = TRUE, then all variables in the frame are printed
-- breakBetweenItems causes a line break between arguments

PrintRef: PROC
[ref: REF READONLY ANY, put: PutClosure,
depth: INT ← 4, width: INT ← 32];
-- print the given ref in the local world

PrintPointer: UNSAFE PROC
[world: World, addr: Address, type: Type,
put: PutClosure, depth: INT ← 4, width: INT ← 32];
-- print the given long pointer as a pointer in the given world to the given type

Intercept: PROC
[type: Type, proc: Interceptor ← NIL, data: REFNIL, canHandleRemote: BOOLFALSE];
-- intercepts printing for the given type
-- proc will be called when PrintTV.Print tries to print the given type
-- (proc = NIL removes the print proc for the type)
-- data will be supplied when proc is called (faking a closure)
-- type = 0 => ERROR InvalidInterceptor
-- IF canHandleRemote THEN interceptor will be called for remote TVs as well as local

Interceptor: TYPE = PROC
[tv: TV, data: REF, put: PutClosure, depth: NAT, width: NAT]
RETURNS [useOld: BOOLFALSE];
-- the type of user's print proc
-- tv: TV is the thing to print
-- data: REF is the user's data given to Intercept
-- put: ... is the output routine for characters
-- depth and width are passed through from PrintTV.Print

GetInterceptor: PROC
[type: Type, deReferenced: BOOLFALSE]
RETURNS [proc: Interceptor, data: REF, enabled: BOOL, canHandleRemote: BOOL];
-- proc # NIL => print proc provided
-- enabled => print proc is enabled
-- deReferenced => what you really mean is REF type.

SetEnabled: PROC [type: Type, deReferenced: BOOL, enabled: BOOLTRUE];
-- sets the enabled flag for the type
-- no effect if no interceptor for that type

NextInterceptor: PROC
[after: Type ← nullType]
RETURNS [type:Type, proc: Interceptor, data: REF, enabled: BOOL];
-- provides a stateless enumerator for print interceptors

InvalidInterceptor: ERROR;
-- error raised by Intercept if bad arguments are given

Mother: PROC [inner: PROC] RETURNS [ROPE]
-- mother catches signals by inner and returns a descriptive message
-- ABORTED is resignaled, NIL is returned if no errors occurred
-- this proc is similar to BBSafety.Mother

END.