DIRECTORY GraphCarets, Graph USING [CaretIndex, CaretState, Chart, GraphHandle], GraphOps USING [Lock, Unlock], GraphPrivate USING [IsGraphViewer, IsLocked], GraphUtil USING [HandleFromViewer, HandleNotNil, InViewer], Imager USING [Color, Context, MaskBits, SetColor], ImagerBackdoor USING [invert], InputFocus USING [GetInputFocus], Process USING [Detach, MsecToTicks, SecondsToTicks, SetTimeout], TerminalDefs USING [Cursor], ViewerClasses USING [Viewer], ViewerOps USING [UserToScreenCoords], ViewerPrivate USING [PaintScreen, Screen, ViewerScreen]; GraphCaretsImpl: CEDAR MONITOR IMPORTS GraphOps, GraphPrivate, GraphUtil, Imager, ImagerBackdoor, InputFocus, Process, ViewerOps, ViewerPrivate EXPORTS GraphCarets = { OPEN Graph, GraphOps, GraphPrivate, GraphUtil; blinkCondition: CONDITION; focusCondition: CONDITION; caretH, caretW: INTEGER = 16; caretXOffset, caretYOffset: CARDINAL = 8; CaretBits: TYPE ~ REF CaretBitsRep; -- ARRAY [0..16) OF WORD CaretBitsRep: TYPE = TerminalDefs.Cursor; caretBits: ARRAY CaretIndex OF CaretBits; graphFocus: GraphHandle _ NIL; caretHoldCount: INTEGER _ 0; -- number of requests pending to suspend caret TurnOn: PUBLIC ENTRY PROC [handle: GraphHandle _ NIL, index: CaretIndex _ primary] = { ENABLE UNWIND => NULL; IF HandleNotNil[handle] THEN On[handle, index]; }; -- TurnOn TurnOff: PUBLIC ENTRY PROC [handle: GraphHandle _ NIL, index: CaretIndex _ primary] = { ENABLE UNWIND => NULL; IF HandleNotNil[handle] THEN Off[handle, index]; }; -- TurnOn Move: PUBLIC ENTRY PROC [handle: GraphHandle _ NIL, x, y: INTEGER _ 0, index: CaretIndex _ primary, ensureOn: BOOL _ FALSE] = { ENABLE UNWIND => NULL; IF HandleNotNil[handle] THEN { OPEN handle; Disappear[chart, index]; -- erase old caret, if visible. chart.caretState[index].x _ x; chart.caretState[index].y _ y; IF ensureOn THEN On[handle, index]; }; }; -- Move AllOn: PUBLIC ENTRY PROC [handle: GraphHandle _ NIL] = { ENABLE UNWIND => NULL; IF HandleNotNil[handle] THEN FOR index: CaretIndex IN CaretIndex DO On[handle, index]; ENDLOOP; }; -- AllOn AllOff: PUBLIC ENTRY PROC [handle: GraphHandle _ NIL] = { ENABLE UNWIND => NULL; IF HandleNotNil[handle] THEN FOR index: CaretIndex IN CaretIndex DO Off[handle, index]; ENDLOOP; }; -- AllOff StartBlinking: PUBLIC ENTRY PROC [handle: GraphHandle _ NIL, index: CaretIndex _ primary] = { -- also turn it on. ENABLE UNWIND => NULL; IF HandleNotNil[handle] THEN {OPEN handle; chart.caretState[index].toBlink _ TRUE; On[handle, index]; }; }; -- StartBlinking StopBlinking: PUBLIC ENTRY PROC [handle: GraphHandle _ NIL, index: CaretIndex _ primary] = { ENABLE UNWIND => NULL; IF HandleNotNil[handle] THEN {OPEN handle; IF graph.caret[index].on AND chart.caretState[index].toBlink THEN Appear[chart, index]; chart.caretState[index].toBlink _ FALSE; }; }; -- StopBlinking GetFocus: PUBLIC ENTRY PROC [] RETURNS [handle: GraphHandle _ NIL] = { ENABLE UNWIND => NULL; RETURN[graphFocus]; }; SetFocus: PUBLIC ENTRY PROC [handle: GraphHandle _ NIL] = { ENABLE UNWIND => NULL; graphFocus _ handle; }; Suspend: PUBLIC ENTRY PROC[] = { ENABLE UNWIND => NULL; InternalSuspend[]; }; -- Suspend Resume: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; InternalResume[]; }; -- Resume On: INTERNAL PROC [handle: GraphHandle, index: CaretIndex _ primary] = { OPEN handle; Appear[chart, index]; graph.caret[index].on _ TRUE; }; -- On Off: INTERNAL PROC [handle: GraphHandle _ NIL, index: CaretIndex _ primary] = { OPEN handle; Disappear[chart, index]; graph.caret[index].on _ FALSE; }; -- Off Disappear: INTERNAL PROC [chart: Chart, index: CaretIndex] = { IF chart.caretState[index].visible THEN Invert[chart, index]; }; -- Disappear Appear: INTERNAL PROC [chart: Chart, index: CaretIndex] = { IF NOT chart.caretState[index].visible THEN Invert[chart, index]; }; -- Appear InternalSuspend: INTERNAL PROC[] = { IF graphFocus # NIL THEN FOR index: CaretIndex IN CaretIndex DO Disappear[graphFocus.chart, index]; ENDLOOP; caretHoldCount _ caretHoldCount+1; }; -- InternalSuspend InternalResume: INTERNAL PROC = { IF caretHoldCount > 0 THEN caretHoldCount _ caretHoldCount - 1; IF graphFocus # NIL THEN FOR index: CaretIndex IN CaretIndex DO IF graphFocus.graph.caret[index].on THEN Appear[graphFocus.chart, index]; ENDLOOP; }; -- InternalResume Invert: INTERNAL PROC [chart: Chart, index: CaretIndex] = { ENABLE UNWIND => NULL; viewer: ViewerClasses.Viewer _ chart.viewer; caret: CaretState _ chart.caretState[index]; IF InViewer[viewer, caret.x, caret.y] THEN { screen: ViewerPrivate.Screen ~ ViewerPrivate.ViewerScreen[viewer]; InvertAction: PROC [context: Imager.Context] ~ { sx, sy: INTEGER; [sx, sy] _ ViewerOps.UserToScreenCoords[viewer, caret.x, caret.y]; Imager.SetColor[context, ImagerBackdoor.invert]; Imager.MaskBits[context: context, base: LOOPHOLE[caretBits[index]], wordsPerLine: 1, sMin: 0, fMin: 0, sSize: caretH, fSize: caretW, tx: sx-caretXOffset, ty: sy+caretYOffset]; caret.visible _ NOT caret.visible; }; -- InvertAction ViewerPrivate.PaintScreen[screen: screen, action: InvertAction, suspendCarets: FALSE]; }; }; -- Invert GraphCaretsProcess: ENTRY PROC = { ENABLE UNWIND => NULL; suspended: BOOL _ FALSE; TRUSTED {Process.SetTimeout[@blinkCondition, Process.MsecToTicks[500]]}; DO WAIT blinkCondition; IF caretHoldCount # 0 THEN suspended _ TRUE -- suspended ELSE IF suspended THEN suspended _ FALSE ELSE IF graphFocus # NIL THEN { IF NOT IsLocked[graphFocus] THEN { Lock[graphFocus]; FOR index: CaretIndex IN CaretIndex DO IF graphFocus.graph.caret[index].on AND graphFocus.chart.caretState[index].toBlink THEN Invert[graphFocus.chart, index]; ENDLOOP; Unlock[graphFocus]; }; }; ENDLOOP; }; -- GraphCaretsProcess GraphFocusProcess: ENTRY PROC = { ENABLE UNWIND => NULL; TRUSTED {Process.SetTimeout[@focusCondition, Process.SecondsToTicks[2]]}; DO viewer: ViewerClasses.Viewer; WAIT focusCondition; viewer _ InputFocus.GetInputFocus[].owner; IF IsGraphViewer[viewer] THEN { graphFocus _ HandleFromViewer[viewer]; } ELSE { IF graphFocus # NIL THEN IF graphFocus.chart.viewer # NIL THEN FOR i: CaretIndex IN CaretIndex DO IF graphFocus.graph.caret[i].on THEN Appear[graphFocus.chart, i]; ENDLOOP; graphFocus _ NIL; }; ENDLOOP; }; -- GraphFocusProcess Init: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; graphFocus _ NIL; caretBits _ [ NEW[CaretBitsRep _ [ 000400B, -- 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 000400B, 000400B, 000400B, 000400B, 000400B, 000400B, 177776B, -- 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 000400B, 000400B, 000400B, 000400B, 000400B, 000400B, 000400B, 0]], -- primary crosshair NEW[CaretBitsRep _ [ 000400B, 0, 000400B, 0, 000400B, 0, 000400B, 125252B, -- 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 000400B, 0, 000400B, 0, 000400B, 0, 000400B, 0]], -- secondary crosshair NEW[CaretBitsRep _ [ 000400B, -- 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 040404B, -- 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 020410B, -- 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 010420B, -- 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 004440B, -- 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 002500B, -- 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 001600B, -- 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 177776B, -- 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 001600B, -- 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 002500B, -- 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 004440B, -- 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 010420B, -- 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 020410B, -- 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 040404B, -- 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 000400B, -- 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]] -- text caret ]; TRUSTED { Process.Detach[FORK GraphCaretsProcess]; -- start the blinker Process.Detach[FORK GraphFocusProcess]; }; }; -- Init }. CHANGE LOG. SChen, August 30, 1985 1:38:10 pm PDT, created taking reference of CaretsImpl.mesa ’GraphCaretsImpl.mesa, Copyright c 1985 by Xerox Corporation. All rights reserved. Reference: CaretsImpl.mesa Last edited: Sweetsun Chen, November 15, 1985 5:45:48 pm PST vars if mustTurnOn then make sure it's turned on, otherwise doesn't affect its visibility. sets handle.graph.caret[index].on, and update display on chart accordingly. Just turn it on. But it may not be blinking. IF HandleNotNil[graphFocus] THEN IF graphFocus.chart.dirty THEN { Lock[graphFocus]; InternalSuspend[]; PaintAll[graphFocus, FALSE]; InternalResume[]; Unlock[graphFocus]; }; make sure all on carets are visible. ChangeCaretShape: PROC [index: CaretIndex, bits: TerminalDefs.Cursor]; Κ ½– "Mesa" style˜Icodešœ Οmœ1™RK™™ Kšœ/™/—K™šΟk ˜ Kšœ ˜ Kšœžœ.˜9Kšœ žœ˜Kšœ žœ˜-Kšœ žœ,˜;Kšœžœ&˜2Kšœžœ ˜Kšœ žœ˜!Kšœžœ3˜@Kšœ žœ ˜Kšœžœ ˜Kšœ žœ˜%Kšœžœ%˜8—K˜šΠblœžœž˜Kšžœi˜pKšžœ˜—K˜Kšžœ*˜.K˜Kšœž œ˜Kšœž œ˜K˜Kšœžœ˜Kšœžœ˜)K˜Kšœ žœžœΟc˜Kšžœ!žœ˜=Kšœ  ˜—K˜š‘œž œ&˜;Kšžœžœ!žœ˜AKšœ  ˜ —K˜š‘œžœžœ˜$š žœžœžœžœžœ ž˜?Kšœ#˜#Kšžœ˜—K˜"Kšœ ˜K˜—š‘œžœžœ˜!Kšžœžœ%˜?š žœžœžœžœžœ ž˜?Kšžœ"žœ!˜IKšžœ˜—Kšœ ˜K˜—š‘œž œ&˜;Kšžœžœžœ˜Kšœ,˜,Kšœ,˜,šžœ$žœ˜,K˜Bš‘ œžœ˜0Kšœžœ˜K˜BKšœ0˜0šœ!˜!Kšœžœ%˜3Kšœ/˜/Kšœ*˜*—Kšœžœ˜"Kšœ ˜—KšœOžœ˜VK˜—Kšœ  ˜ —K˜š‘œžœžœ˜"Kšžœžœžœ˜Kšœ žœžœ˜KšžœA˜Hšž˜Kšžœ˜Kšžœžœ žœ  ˜8Kšžœžœ žœ ž˜(šžœžœžœžœ˜šžœžœžœ˜"Kšœ˜šžœžœ ž˜&Kšžœ"žœ+žœ!˜xKšžœ˜—Kšœ˜K˜—K˜—Kšžœ˜—Kšœ ˜—K˜š‘œžœžœ˜!Kšžœžœžœ˜KšžœB˜Išž˜Kšœ˜Kšžœ˜Kšœ*˜*šžœžœ˜Kšœ&˜&šžœžœžœ™AKšœ™K™Kšœžœ™K™Kšœ™K™—K˜—šžœ˜K™$š žœžœžœžœžœž˜>šžœžœ ž˜"Kšžœžœ˜AKšžœ˜——Kšœ žœ˜K˜—Kšžœ˜—Kšœ ˜—K™Kš‘œžœ0™FK™š‘œžœžœžœ˜Kšžœžœžœ˜Kšœ žœ˜šœ ˜ šžœ˜Kšœ  "˜+Kšœ6˜6Kšœ  "˜+Kšœ>˜>Kšœ ˜—šžœ˜Kšœ,˜,Kšœ  "˜+Kšœ,˜,Kšœ ˜—šžœ˜Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  "˜+Kšœ  ˜—K˜—šžœ˜ Kšœžœ ˜>Kšœžœ˜'K˜—Kšœ ˜ —Kšœ˜K˜šžœžœ˜ Kšœ"žœ-˜R—K˜—…—μ+K