<> <> <> <> DIRECTORY Basics USING [BITSHIFT, LongMult, bitsPerWord], CD, CDColors, CDVPrivate, CDVScale, RuntimeError, PrincOps, PrincOpsUtils, TerminalExtras, Terminal, ViewerClasses; CDVCursorImpl: CEDAR MONITOR IMPORTS Basics, CDVPrivate, RuntimeError, PrincOpsUtils, TerminalExtras, Terminal EXPORTS CDVPrivate = BEGIN MyGraphicRef: TYPE = CDVPrivate.MyGraphicRef; CursorRec: TYPE = RECORD [mode: REF, doit: CDVPrivate.CursorModeProc]; CursorList: TYPE = LIST OF CursorRec; cursorList: CursorList _ LIST[CursorRec[mode: NIL, doit: UseDefaultCursor]]; <<--never NIL; used by ImplementACursor>> <<>> virtual: Terminal.Virtual = Terminal.Current[]; blackBrick: REF CDColors.Brick = NEW[CDColors.Brick_ALL[LAST[CARDINAL]]]; <<>> ImplementACursor: PUBLIC ENTRY PROC[mode: ATOM, proc: CDVPrivate.CursorModeProc] = <<--teaches SetCursorMode to call proc if mode mode is set>> BEGIN <<--invert the order: efficiency hack: the first installed cursor is found the fastest>> <<--cursorList is never NIL>> FOR list: CursorList _ cursorList, list.rest DO IF list.first.mode=mode THEN {list.first.doit _ proc; EXIT} ELSE IF list.rest=NIL THEN {list.rest _ LIST[CursorRec[mode: mode, doit: proc]]; EXIT} ENDLOOP END; SetCursorMode: PUBLIC PROC[me: MyGraphicRef, mode: REF] = BEGIN FOR list: CursorList _ cursorList, list.rest WHILE list#NIL DO IF list.first.mode=mode THEN { list.first.doit[me, mode ! RuntimeError.UNCAUGHT => CONTINUE]; RETURN } ENDLOOP; <<--error catch; cursorList is never NIL>> cursorList.first.doit[me, NIL ! RuntimeError.UNCAUGHT => CONTINUE]; END; DefaultCursor: PUBLIC PROC[me: MyGraphicRef] = BEGIN <<--probably this will be overwritten by a client>> END; UseDefaultCursor: CDVPrivate.CursorModeProc = { me.designRec.outlineProcLC _ DefaultCursor }; InvertArea: PUBLIC PROC[me: MyGraphicRef, x1, y1, x2, y2: INT] = <<--x1, y1, x2, y2 in viewers coordinates; inverts all the border points >> TRUSTED BEGIN ENABLE RuntimeError.UNCAUGHT => { IF CDVPrivate.catchAnyWhichDeadlock THEN GOTO SomeError ELSE REJECT; }; xBit: CARDINAL; xc1: CARDINAL _ MIN[MAX[x1, 0], LONG[me.viewer.cw-1]]; yc1: CARDINAL _ MIN[MAX[y1, 0], LONG[me.viewer.ch-1]]; xc2: CARDINAL _ MIN[MAX[x2, 0], LONG[me.viewer.cw-1]]; yc2: CARDINAL _ MIN[MAX[y2, 0], LONG[me.viewer.ch-1]]; IF xc1>xc2 THEN {t: CARDINAL=xc1; xc1_xc2; xc2_t}; IF yc1>yc2 THEN {t: CARDINAL=yc1; yc1_yc2; yc2_t}; me.xBBptr.width _ Basics.BITSHIFT[(xc2+1-xc1), me.logbpp]; me.xBBptr.height _ (yc2+1-yc1); xBit _ Basics.BITSHIFT[(xc1+me.vx), me.logbpp]; yc1 _ me.vy-yc2; --IF coordSys=top THEN yc1+me.vy ELSE me.vy-yc2; me.xBBptr.dst _ [ me.screen + Basics.LongMult[yc1, me.scWidthWords] + LONG[(xBit/Basics.bitsPerWord)],, xBit MOD Basics.bitsPerWord ]; me.xBBptr.flags.dstFunc _ xor; -- cursoring is monitored; no drawing! me.xBBptr.src _ [LOOPHOLE[blackBrick, LONG POINTER],,0]; me.xBBptr.srcDesc _ PrincOps.SrcDesc[gray[PrincOps.GrayParm[ yOffset: 0, widthMinusOne: 0, --words heightMinusOne: 0 --lines ]]]; IF me.bpp=1 THEN PrincOpsUtils.BITBLT[me.xBBptr] ELSE { TerminalExtras.LockColorFrame[vt: virtual, xmin: xc1+me.vx, ymin: yc1, xmax: xc2+me.vx+1, ymax: yc1+me.xBBptr.height ]; PrincOpsUtils.BITBLT[me.xBBptr]; TerminalExtras.UnlockColorFrame[virtual] }; EXITS SomeError => NULL; END; END.