DIRECTORY CD USING [Rect, Design], CDBasics, CDDrawQueue; CDDrawQueueImpl: CEDAR MONITOR IMPORTS CDBasics EXPORTS CDDrawQueue SHARES CD = BEGIN DrawQueue: TYPE = REF DrawQueueRep; Request: TYPE = CDDrawQueue.Request; QueueList: TYPE = LIST OF DrawQueue; maxC: CARD16 = 50; DrawQueueRep: PUBLIC TYPE = RECORD [ fancyList: LIST OF Request _ NIL, fancyLast: LIST OF Request _ NIL, cnt, in, out: CARD16, commandAvail: CONDITION, desgn: CD.Design, deviceClip: CD.Rect, comm: ARRAY [0..maxC) OF Request, stopFlag: REF BOOL, -- must be monitored active: BOOL _ FALSE, deleted: BOOL _ FALSE, alldoneToBeReported: BOOL _ FALSE, inProgress: Request _ [NIL, CDBasics.universe] ]; queueEmpty: PUBLIC REF _ NEW[INT]; finishedForEver: PUBLIC REF _ NEW[INT]; Activate: INTERNAL PROC [dq: DrawQueue] = { IF NOT dq.active THEN { list: QueueList _ NARROW[dq.desgn.cdDrawQueuePriv]; list _ CONS[dq, list]; dq.desgn.cdDrawQueuePriv _ list; dq.active _ TRUE; }; }; DeActivate: INTERNAL PROC [dq: DrawQueue] = { IF dq.active THEN { list: QueueList _ NARROW[dq.desgn.cdDrawQueuePriv]; IF list=NIL THEN RETURN; -- list#NIL; otherwise nothing too delete! not dq.active; but don't be picky IF list.first=dq THEN dq.desgn.cdDrawQueuePriv _ list.rest ELSE FOR l: QueueList _ list, l.rest WHILE l.rest#NIL DO IF l.rest.first=dq THEN {l.rest _ l.rest.rest; EXIT} ENDLOOP; dq.active _ FALSE; }; }; Create: PUBLIC ENTRY PROC [design: CD.Design, stopFlag: REF BOOL, clip: CD.Rect_[1,1,0,0]] RETURNS [DrawQueue] = { ENABLE UNWIND => NULL; --catches eg on stopFlag=NIL dq: DrawQueue = NEW[DrawQueueRep]; IF stopFlag=NIL THEN stopFlag _ NEW[BOOL_FALSE]; dq.cnt _ dq.in _ dq.out _ 0; dq.deviceClip _ CDBasics.empty; dq.desgn _ design; dq.stopFlag _ stopFlag; -- assigns addresses dq.deleted _ dq.active _ dq.alldoneToBeReported _ dq.stopFlag^ _ FALSE; InternalChangeClipArea[dq, clip]; RETURN [dq] }; ChangeClipArea: PUBLIC ENTRY PROC [dq: DrawQueue, clip: CD.Rect] = { ENABLE UNWIND => NULL; InternalChangeClipArea[dq, clip]; }; InternalChangeClipArea: INTERNAL PROC [dq: DrawQueue, clip: CD.Rect] = { InternalFlushAll[dq]; dq.deviceClip _ clip; IF CDBasics.NonEmpty[clip] THEN Activate[dq] ELSE DeActivate[dq] }; Destroy: PUBLIC ENTRY PROC [dq: DrawQueue] = { ENABLE UNWIND => NULL; IF dq#NIL THEN { dq.deleted _ TRUE; InternalFlushAll[dq]; DeActivate[dq]; dq.desgn _ NIL; } }; QueueInsertDrawCommand: PUBLIC ENTRY PROC [dq: DrawQueue, req: Request] = { ENABLE UNWIND => NULL; IF dq#NIL AND dq.active THEN InternalInsertCommand[dq, req] }; InsertFancy: INTERNAL PROC [dq: DrawQueue, req: Request] = INLINE { IF dq.fancyList=NIL THEN dq.fancyList _ dq.fancyLast _ LIST[req] ELSE { dq.fancyLast.rest _ LIST[req]; dq.fancyLast _ dq.fancyLast.rest; }; NOTIFY dq.commandAvail; }; Stronger: PROC [a, b: REF] RETURNS [ATOM] = INLINE { RETURN [IF a=$redraw OR b=$redraw THEN $redraw ELSE $draw]; }; InternalInsertCommand: INTERNAL PROC [dq: DrawQueue, req: Request] = { dq.alldoneToBeReported _ TRUE; IF req.key#$redraw AND req.key#$draw THEN InsertFancy[dq, req] ELSE { j: CARD16; IF ~CDBasics.Intersect[req.rect, dq.deviceClip] THEN RETURN; req.rect _ CDBasics.Intersection[req.rect, dq.deviceClip]; IF dq.cnt>=maxC THEN { InternalFlushDraw[dq]; InsertFancy[dq, Request[$flushed, dq.deviceClip]]; req _ Request[$redraw, dq.deviceClip]; }; IF CDBasics.Inside[dq.inProgress.rect, req.rect] THEN { IF dq.inProgress.key=$redraw OR dq.inProgress.key=$draw THEN { dq.stopFlag^ _ TRUE; req.key _ Stronger[req.key, dq.inProgress.key]; }; }; j _ dq.out; THROUGH [0..dq.cnt) DO IF CDBasics.Intersect[req.rect, dq.comm[j].rect] THEN { IF CDBasics.Inside[req.rect, dq.comm[j].rect] THEN { dq.comm[j].key _ Stronger[dq.comm[j].key, req.key]; RETURN }; IF CDBasics.Inside[dq.comm[j].rect, req.rect] THEN { dq.comm[j].key _ Stronger[dq.comm[j].key, req.key]; dq.comm[j].rect _ req.rect; RETURN }; }; j _ (j+1) MOD maxC; ENDLOOP; dq.cnt _ dq.cnt+1; dq.comm[dq.in] _ req; dq.in _ (dq.in+1) MOD maxC; NOTIFY dq.commandAvail; }; }; InsertDrawCommand: PUBLIC ENTRY PROC [design: CD.Design, req: Request] = { ENABLE UNWIND => NULL; FOR lst: QueueList _ NARROW[design.cdDrawQueuePriv], lst.rest WHILE lst#NIL DO InternalInsertCommand[lst.first, req]; ENDLOOP }; lastFirst: BOOL _ TRUE; FetchCommand: PUBLIC ENTRY PROC [dq: DrawQueue] RETURNS [req: Request] = { ENABLE UNWIND => NULL; dq.stopFlag^ _ FALSE; WHILE dq.cnt<=0 AND dq.fancyList=NIL DO IF dq.deleted THEN InsertDisappear[dq] ELSE IF dq.alldoneToBeReported THEN { InsertFancy[dq, Request[queueEmpty, [1,1,0,0]]]; dq.alldoneToBeReported _ FALSE; } ELSE WAIT dq.commandAvail; dq.stopFlag^ _ FALSE; ENDLOOP; IF dq.fancyList#NIL THEN { dq.inProgress _ req _ dq.fancyList.first; dq.fancyList _ dq.fancyList.rest; RETURN }; dq.cnt _ dq.cnt-1; IF dq.cnt>2 THEN { dq.in _ (dq.in+maxC-1) MOD maxC; dq.inProgress _ req _ dq.comm[dq.in]; } ELSE { dq.inProgress _ req _ dq.comm[dq.out]; dq.out _ (dq.out+1) MOD maxC; }; }; Flush: PUBLIC ENTRY PROC [dq: DrawQueue] = { ENABLE UNWIND => NULL; IF dq#NIL THEN InternalFlushAll[dq] }; InternalFlushAll: INTERNAL PROC [dq: DrawQueue] = { dq.fancyList _ dq.fancyLast _ NIL; InternalFlushDraw[dq]; }; InternalFlushDraw: INTERNAL PROC [dq: DrawQueue] = { dq.cnt _ dq.in _ dq.out _ 0; dq.stopFlag^ _ TRUE; dq.alldoneToBeReported _ FALSE; dq.inProgress _ [NIL, CDBasics.universe]; NOTIFY dq.commandAvail; }; InsertDisappear: INTERNAL PROC [dq: DrawQueue] = { dq.fancyList _ dq.fancyLast _ LIST[Request[finishedForEver, [1,1,0,0]]]; }; END. hCDDrawQueueImpl.mesa (part of ChipNDale) Copyright c 1983, 1986, 1987 by Xerox Corporation. All rights reserved. Created by Christian Jacobi July 6, 1983 5:09 pm Last edited by: Christian April 17, 1987 3:44:03 pm PDT -- request to stop the execution of (only!) the current command --stopFlag^ tells any drawing process to stop volunterly and to fetch the next command. --stopFlag^ must not be modified any more outside this monitor!! --until DeleteCommandTable is called --Users may request a stop by calling Flush. --changes the clipping aera --changes the clipping aera --no more insertion calls on dq allowed!! --redraw process must disapear from itself, --when redraw process dispears and contains nomore --reference of dq, it is subject for garbage collection --The stopFlag is immediately set to TRUE and later --reset to FALSE when the redraw --process stopped the current command, if it then fetches another --command it gets the disapearforever command. --regular draw requests --table overflow check --should painting stop? --try matching --enqueue --waits till command is available or DrawQueue deleted --silly heuristic; --if 2 elements it looks more like movement to clear the old area first --but if there is a backlog we want to draw the newest things first -- the drawing may stop after some time only, -- and NOT immediately with procedure return Κ Γ˜codešœ,™,Kšœ Οmœ=™HKšœ3™3K™7—šΟk ˜ Kšžœžœ˜K˜ Kšœ ˜ —K˜šΟnœžœžœ˜Kšžœ ˜Kšžœ ˜Kšžœžœ˜ —šž˜K˜—Kšœ žœžœ˜#Kšœ žœ˜$Kšœ žœžœžœ ˜$K˜Kšœžœ˜šœžœžœžœ˜$Kšœ žœžœ žœ˜!Kšœ žœžœ žœ˜!Kšœžœ˜Kšœž œ˜Kšœžœ˜Kšœ žœ˜Kšœžœ žœ ˜!šœ žœžœΟc˜(Kš ?™?—Kšœžœžœ˜Kšœ žœžœ˜Kšœžœžœ˜"Kšœžœ˜.K˜K˜—Kš œ žœžœžœžœ˜"Kš œžœžœžœžœ˜'K˜šŸœžœžœ˜+šžœžœ žœ˜Kšœžœ˜3Kšœžœ ˜Kšœ ˜ Kšœ žœ˜Kšœ˜—Kšœ˜K˜—šŸ œžœžœ˜-šžœ žœ˜Kšœžœ˜3šžœžœžœžœ˜Kš L˜L—Kšžœžœ%˜:šž˜šžœžœžœž˜3Kšžœžœžœ˜4Kšž˜——Kšœ žœ˜Kšœ˜—Kšœ˜K˜—šŸœžœžœžœ žœžœžœžœžœ˜rKšœX™XKšœ@™@Kšœ$™$Kšœ,™,Kšžœžœžœ ˜3Kšœžœ˜"Kš žœ žœžœ žœžœžœ˜0K˜K˜K˜Kšœ ˜-KšœAžœ˜GKšœ!˜!Kšžœ˜ Kšœ˜K˜—š Ÿœžœžœžœžœ ˜DKšœ™Kšžœžœžœ˜Kšœ!˜!Kšœ˜K˜—šŸœžœžœžœ ˜HKšœ™Kšœ˜K˜Kšžœžœ žœ˜@Kšœ˜K˜—šŸœžœžœžœ˜.Kšœ)™)Kšœ+™+Kšœ2™2Kšœ8™8Kšœ3™3Kšœ!™!KšœB™BKšœ.™.Kšžœžœžœ˜šžœžœžœ˜Kšœ žœ˜Kšœ˜Kšœ˜Kšœ žœ˜K˜—Kšœ˜K˜—šŸœžœžœžœ"˜KKšžœžœžœ˜Kšžœžœžœ žœ˜;Kšœ˜K˜—šŸ œžœžœ!žœ˜CKšžœžœžœžœ˜@šžœ˜Kšœžœ˜Kšœ!˜!K˜—Kšžœ˜K˜—K˜š Ÿœžœžœžœžœžœ˜4Kš žœžœ žœ žœ žœ˜;K˜—K˜šŸœžœžœ"˜FKšœžœ˜Kšžœžœžœ˜>šžœ˜Kš ™Kšœžœ˜ Kšžœ.žœžœ˜Kšœžœ˜Kšœ/˜/K˜—K˜—Kš ™Kšœ ˜ šžœ ž˜šžœ/žœ˜7šžœ,žœ˜4Kšœ3˜3Kšž˜K˜—šžœ,žœ˜4Kšœ3˜3Kšœ˜Kšž˜Kšœ˜—K˜—Kšœ žœ˜Kšžœ˜—Kš  ™ K˜K˜Kšœžœ˜Kšžœ˜K˜—Kšœ˜K˜—š Ÿœžœžœžœ žœ˜JKšžœžœžœ˜š žœžœ#žœžœž˜NKšœ&˜&Kšž˜—Kšœ˜K˜—Kšœ žœžœ˜K˜š Ÿ œžœžœžœžœ˜JKšœ6™6Kšžœžœžœ˜Kšœžœ˜šžœ žœžœžœ˜(Kšžœ žœ˜&šžœžœžœ˜%Kšœ0˜0Kšœžœ˜Kšœ˜—Kšžœžœ˜Kšœžœ˜Kšžœ˜—šžœžœžœ˜Kšœ)˜)Kšœ!˜!Kšž˜K˜—K˜Kšœ™KšœG™GKšœC™Cšžœ žœ˜Kšœžœ˜ Kšœ%˜%K˜—šžœ˜Kšœ&˜&Kšœžœ˜K˜—Kšœ˜K˜—šŸœžœžœžœ˜,Kšœ-™-Kšœ,™,Kšžœžœžœ˜Kšžœžœžœ˜#Kšœ˜K˜—šŸœžœžœ˜3Kšœžœ˜"Kšœ˜Kšœ˜K˜—šŸœžœžœ˜4K˜Kšœžœ˜Kšœžœ˜Kšœžœ˜)Kšžœ˜Kšœ˜K˜—šŸœžœžœ˜2Kšœžœ&˜HKšœ˜—K˜Kšžœ˜K˜K˜K˜K˜K˜—…—„$―