-- ClipperImpl.mesa -- Last changed by Doug Wyatt, September 25, 1980 3:58 PM DIRECTORY Clipper, Area USING [Handle, Free], Patch USING [Handle, New, NewPipe, Free], Pipe USING [Handle, Procs, Object, Sink, Put, Ref, Free], Memory USING [NewZone]; ClipperImpl: PROGRAM IMPORTS Memory,Area,Patch,Pipe EXPORTS Clipper SHARES Clipper,Pipe = { OPEN Clipper; ClipperError: PUBLIC SIGNAL = CODE; zone: UNCOUNTED ZONE = Memory.NewZone["ClipperImpl"]; Data: PUBLIC TYPE = RECORD [ level: CARDINAL, -- current Push depth clevel: CARDINAL, -- level above which clipper is enabled/disabled state: State, -- current clipper state c: CDataRef ]; DataRef: TYPE = LONG POINTER TO Data; CData: PUBLIC TYPE = RECORD [ plist: NodeRef, -- list of patches ppipe: Pipe.Handle, -- pipe into patch chain tpipe: Pipe.Handle, -- top pipe handed out to clients ipipe,opipe: Pipe.Handle, -- current in,out pipes state: State, -- state after last clipping operation inuse: BOOLEAN, -- TRUE if a client is holding tpipe refs: CARDINAL ]; CDataRef: TYPE = LONG POINTER TO CData; Node: TYPE = RECORD [ next: NodeRef, patch: Patch.Handle ]; NodeRef: TYPE = LONG POINTER TO Node; cProcs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [ NewPipe: CNewPipe, Push: CPush, Pop: CPop, Test: CTest, NewRegion: CNewRegion, Copy: CCopy, Free: CFree ]]; iProcs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [ NewPipe: INewPipe, Push: IPush, Pop: IPop, Test: CTest, NewRegion: CNewRegion, Copy: CCopy, Free: CFree ]]; oProcs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [ NewPipe: ONewPipe, Push: IPush, Pop: IPop, Test: CTest, NewRegion: CNewRegion, Copy: CCopy, Free: CFree ]]; NewCData: PROC RETURNS[CDataRef] = { c: CDataRef = zone.NEW[CData _ [ plist: NIL, ppipe: NIL, tpipe: NIL, ipipe: NIL, opipe: NIL, state: [FALSE,FALSE], inuse: FALSE, refs: 1 ]]; RETURN[c]; }; FreePList: PROC[c: CDataRef] = { IF c.plist#NIL THEN { list: NodeRef_c.plist; c.plist_NIL; zone.FREE[@c.tpipe]; Pipe.Free[@c.ppipe]; UNTIL list=NIL DO p: NodeRef_list; list_p.next; Patch.Free[@p.patch]; zone.FREE[@p]; ENDLOOP; }; }; FreeCData: PROC[cPtr: LONG POINTER TO CDataRef] = { c: CDataRef_cPtr^; cPtr^_NIL; IF c.inuse THEN ERROR ClipperError; IF (c.refs_c.refs-1)=0 THEN { FreePList[c]; zone.FREE[@c]; }; }; NewClipper: PUBLIC PROC RETURNS[Handle] = { d: DataRef = zone.NEW[Data _ [ level: 1, clevel: 0, state: [FALSE,FALSE], c: NewCData[] ]]; RETURN[zone.NEW[Object _ [procs: oProcs, data: d]]]; }; ipipeProcs: LONG POINTER TO READONLY Pipe.Procs = zone.NEW[Pipe.Procs = [ Put: IPPut, Free: PFree]]; opipeProcs: LONG POINTER TO READONLY Pipe.Procs = zone.NEW[Pipe.Procs = [ Put: OPPut, Free: PFree]]; NewIPipe: PROC[c: CDataRef] RETURNS[Pipe.Handle] = INLINE { RETURN[zone.NEW[Pipe.Object _ [procs: ipipeProcs, data: LOOPHOLE[c]]]]; }; NewOPipe: PROC[c: CDataRef] RETURNS[Pipe.Handle] = INLINE { RETURN[zone.NEW[Pipe.Object _ [procs: opipeProcs, data: LOOPHOLE[c]]]]; }; IPPut: PROC[self: Pipe.Handle, area: Area.Handle] = { c: CDataRef=LOOPHOLE[self.data]; c.state.in_TRUE; Pipe.Put[c.ipipe,area]; }; OPPut: PROC[self: Pipe.Handle, area: Area.Handle] = { c: CDataRef=LOOPHOLE[self.data]; c.state.out_TRUE; Pipe.Put[c.opipe,area]; }; PFree: PROC[self: Pipe.Handle] = { zone.FREE[@self]; }; tpipeProcs: LONG POINTER TO READONLY Pipe.Procs = zone.NEW[Pipe.Procs = [ Put: TPPut, Free: TPFree]]; NewTPipe: PROC[c: CDataRef] RETURNS[Pipe.Handle] = INLINE { RETURN[zone.NEW[Pipe.Object _ [ procs: tpipeProcs, data: LOOPHOLE[c], refs: 0 ]]]; }; TPPut: PROC[self: Pipe.Handle, area: Area.Handle] = { c: CDataRef=LOOPHOLE[self.data]; -- could do some culling here Pipe.Put[c.ppipe,area]; }; TPFree: PROC[self: Pipe.Handle] = { c: CDataRef=LOOPHOLE[self.data]; Pipe.Free[@c.ipipe]; Pipe.Free[@c.opipe]; c.inuse_FALSE; }; MakePipe: PROC[c: CDataRef] = { ip: Pipe.Handle_NewIPipe[c]; op: Pipe.Handle_NewOPipe[c]; c.ppipe_Pipe.Ref[op]; FOR p: NodeRef_c.plist,p.next UNTIL p=NIL DO c.ppipe_Patch.NewPipe[p.patch,Pipe.Ref[ip],c.ppipe]; ENDLOOP; Pipe.Free[@ip]; Pipe.Free[@op]; c.tpipe_NewTPipe[c]; }; CNewPipe: PROC[self: Handle, ipipe,opipe: Pipe.Handle] RETURNS[Pipe.Handle] = { d: DataRef=self.data; c: CDataRef=d.c; IF c.inuse THEN ERROR ClipperError; c.ipipe_ipipe; c.opipe_opipe; c.state_[FALSE,FALSE]; c.inuse_TRUE; RETURN[Pipe.Ref[c.tpipe]]; }; INewPipe: PROC[self: Handle, ipipe,opipe: Pipe.Handle] RETURNS[Pipe.Handle] = { Pipe.Free[@opipe]; RETURN[ipipe] }; ONewPipe: PROC[self: Handle, ipipe,opipe: Pipe.Handle] RETURNS[Pipe.Handle] = { Pipe.Free[@ipipe]; RETURN[opipe] }; CPush: PROC[self: Handle, area: Area.Handle] = { d: DataRef=self.data; c: CDataRef=d.c; pipe: Pipe.Handle_CNewPipe[self,Pipe.Sink[],Pipe.Sink[]]; Pipe.Put[pipe,area]; Pipe.Free[@pipe]; d.state_c.state; d.level_d.level+1; IF d.state=[TRUE,TRUE] THEN d.clevel_d.level ELSE self.procs_(IF d.state.in THEN iProcs ELSE oProcs); }; CPop: PROC[self: Handle] = { d: DataRef=self.data; IF d.level>1 THEN d.level_d.clevel_d.level-1; }; IPush: PROC[self: Handle, area: Area.Handle] = { d: DataRef=self.data; Area.Free[@area]; d.level_d.level+1; }; IPop: PROC[self: Handle] = { d: DataRef=self.data; IF d.level>1 THEN { d.level_d.level-1; IF d.level=d.clevel THEN { d.state_[TRUE,TRUE]; self.procs_cProcs }; }; }; CTest: PROC[self: Handle] RETURNS[State] = { d: DataRef=self.data; RETURN[d.state] }; regionProcs: LONG POINTER TO READONLY Pipe.Procs = zone.NEW[Pipe.Procs = [ Put: RPut, Free: RFree]]; CNewRegion: PROC[self: Handle] RETURNS[Pipe.Handle] = { d: DataRef=self.data; self.procs_oProcs; FreeCData[@d.c]; d^_[level: 1, clevel: 0, state: [FALSE,FALSE], c: NewCData[]]; d.c.inuse_TRUE; RETURN[zone.NEW[Pipe.Object _ [procs: regionProcs, data: LOOPHOLE[self]]]]; }; RPut: PROC[self: Pipe.Handle, area: Area.Handle] = { clip: Handle=LOOPHOLE[self.data]; d: DataRef=clip.data; c: CDataRef=d.c; p: NodeRef=zone.NEW[Node _ [next: NIL, patch: Patch.New[area]]]; p.next_c.plist; c.plist_p; }; RFree: PROC[self: Pipe.Handle] = { clip: Handle=LOOPHOLE[self.data]; d: DataRef=clip.data; c: CDataRef=d.c; IF c.plist#NIL THEN { MakePipe[c]; d.state_[TRUE,TRUE]; d.clevel_d.level; clip.procs_cProcs; }; c.inuse_FALSE; zone.FREE[@self]; }; CCopy: PROC[self: Handle] RETURNS[Handle] = { d: DataRef=self.data; dd: DataRef=zone.NEW[Data_d^]; c: CDataRef=dd.c; c.refs_c.refs+1; RETURN[zone.NEW[Object _ [procs: self.procs, data: dd]]]; }; CFree: PROC[self: Handle] = { d: DataRef_self.data; FreeCData[@d.c]; zone.FREE[@d]; zone.FREE[@self]; }; }.(670)