<> <> <> <> <<>> <> DIRECTORY Imager USING [black, Context, MaskRectangleI, SetColor, white], Terminal USING [Virtual, Current, FrameBuffer, BWCursorBitmap, GetBWFrameBuffer, SetBWCursorPattern, ColorCursorBitmap, GetColorFrameBufferA, SetColorCursorPattern, SetColorCursorPresentation], ViewerClasses USING [Viewer], SilFile, SilDisplayCursors, SilDisplayInternal, SilDisplayUtils, SilKernel, SilUserInput, ImagerPixelMap, ImagerOps, PrincOps ; SilDisplayCursorsImpl: CEDAR MONITOR IMPORTS Imager, Terminal, SilUserInput, SilDisplayUtils, SilFile, ImagerPixelMap, ImagerOps EXPORTS SilDisplayCursors, SilKernel = BEGIN OPEN SilFile; SilData: TYPE = SilKernel.SilData; SilDisplayData: TYPE = REF SilDisplayDataRec; SilDisplayDataRec: PUBLIC TYPE = SilDisplayInternal.SilDisplayDataRec; SilModel: TYPE = SilFile.SilModel; SilUIData: TYPE = SilKernel.SilUIData; markWidth: NAT _ 2; markLength: NAT _ 6; originWidth: NAT _ 4; originLength: NAT _ 2; defaultTicSpacing: NAT = 16; <> <> originBlackNow: BOOL; dataOfOriginViewer: SilData; originX: INTEGER; originY: INTEGER; oldOriginNeedsCleared: BOOL; dataOfOldOriginViewer: SilData; oldOriginX: INTEGER; oldOriginY: INTEGER; markBlackNow: BOOL; dataOfMarkViewer: SilData; markX: INTEGER; markY: INTEGER; oldMarkNeedsCleared: BOOL; dataOfOldMarkViewer: SilData; oldMarkX: INTEGER; oldMarkY: INTEGER; <> dataOfCurrentSelection: SilData; SilCursorsInit: PUBLIC ENTRY PROC [] = { <> originBlackNow _ FALSE; dataOfOriginViewer_ NIL; originX _ 0; originY _ 0; oldOriginNeedsCleared _ FALSE; dataOfOldOriginViewer _ NIL; oldOriginX _ 0; oldOriginY _ 0; markBlackNow _ FALSE; dataOfMarkViewer _ NIL; markX _ 0; markY _ 0; oldMarkNeedsCleared _ FALSE; dataOfOldMarkViewer _ NIL; oldMarkX _ 0; oldMarkY _ 0; <> dataOfCurrentSelection _ NIL; }; SilCursorsBlink: PUBLIC ENTRY PROC [] = { <> <> <> IF dataOfOriginViewer # NIL THEN IF SilUserInput.HasInputFocus[] OR originBlackNow THEN SilUserInput.SetCaretChange[dataOfOriginViewer.uiData]; IF dataOfMarkViewer # NIL THEN IF SilUserInput.HasInputFocus[] OR markBlackNow THEN SilUserInput.SetCaretChange[dataOfMarkViewer.uiData]; }; SilCaretSize: PUBLIC ENTRY PROC [newMarkWidth, newMarkLength, newOriginWidth, newOriginLength: NAT] = { markWidth _ newMarkWidth; markLength _ newMarkLength; originWidth _ newOriginWidth; originLength _ newOriginLength; }; SilCaretPaint: PUBLIC ENTRY PROC [data: SilData, ctx: Imager.Context] = { <> IF oldMarkNeedsCleared AND dataOfOldMarkViewer = data THEN { Imager.SetColor[ctx, Imager.white]; Imager.MaskRectangleI[ctx, oldMarkX, oldMarkY, markWidth, markLength]; SilDisplayUtils.MergeRebuild[data.displayData, data.model, oldMarkX, oldMarkY, oldMarkX + markWidth, oldMarkY + markLength]; oldMarkNeedsCleared _ FALSE; }; IF oldOriginNeedsCleared AND dataOfOldOriginViewer = data THEN { Imager.SetColor[ctx, Imager.white]; Imager.MaskRectangleI[ctx, oldOriginX, oldOriginY, originWidth, originLength]; SilDisplayUtils.MergeRebuild[data.displayData, data.model, oldOriginX, oldOriginY, oldOriginX + originWidth, oldOriginY + originLength]; oldOriginNeedsCleared _ FALSE; }; IF dataOfMarkViewer = data THEN { IF dataOfOriginViewer = data THEN originBlackNow _ markBlackNow;--blink in phase if possible IF markBlackNow THEN Imager.SetColor[ctx, Imager.white] ELSE Imager.SetColor[ctx, Imager.black]; markBlackNow _ NOT markBlackNow; Imager.MaskRectangleI[ctx, markX, markY, markWidth, markLength]; }; IF dataOfOriginViewer = data THEN { IF originBlackNow THEN Imager.SetColor[ctx, Imager.white] ELSE Imager.SetColor[ctx, Imager.black]; originBlackNow _ NOT originBlackNow; Imager.MaskRectangleI[ctx, originX, originY, originWidth, originLength]; }; }; AquireAndDisableTheMark: PUBLIC ENTRY PROC [data: SilData, ctx: Imager.Context _ NIL] = { <> TurnOffTheMark[data, ctx]; dataOfMarkViewer _ data; SilUserInput.GetInputFocus[data.uiData]; }; TurnOffTheMark: INTERNAL PROC [data: SilData, ctx: Imager.Context _ NIL] = { <> dataOfOldMarkViewer _ dataOfMarkViewer; oldMarkX _ markX; oldMarkY _ markY; IF dataOfMarkViewer # data AND dataOfMarkViewer # NIL THEN { oldMarkNeedsCleared _ TRUE; SilUserInput.SetCaretChange[dataOfOldMarkViewer.uiData]; } ELSE IF ctx # NIL THEN { Imager.SetColor[ctx, Imager.white]; Imager.MaskRectangleI[ctx, markX, markY, markWidth, markLength]; SilDisplayUtils.MergeRebuild[data.displayData, data.model, markX, markY, markX + markWidth, markY + markLength]; }; }; AquireAndDisableTheOrigin: PUBLIC ENTRY PROC [data: SilData, ctx: Imager.Context _ NIL] = { <> TurnOffTheOrigin[data, ctx]; dataOfOriginViewer _ data; IF NOT SilUserInput.HasInputFocus[] THEN SilUserInput.GetInputFocus[data.uiData]; }; TurnOffTheOrigin: INTERNAL PROC [data: SilData, ctx: Imager.Context _ NIL] = { <> dataOfOldOriginViewer _ dataOfOriginViewer; oldOriginX _ originX; oldOriginY _ originY; IF dataOfOriginViewer # data AND dataOfOriginViewer # NIL THEN { oldOriginNeedsCleared _ TRUE; SilUserInput.SetCaretChange[dataOfOldOriginViewer.uiData]; } ELSE IF ctx # NIL THEN { Imager.SetColor[ctx, Imager.white]; Imager.MaskRectangleI[ctx, originX, originY, originWidth, originLength]; SilDisplayUtils.MergeRebuild[data.displayData, data.model, originX, originY, originX + originWidth, originY + originLength]; }; }; CheckSelectionWindow: PUBLIC ENTRY PROC [data: SilData] = { <> <<>> IF data # dataOfCurrentSelection AND dataOfCurrentSelection # NIL THEN { sSel: SilSelection _ SilFile.GetSelection[]; xMin: INTEGER _ sSel.xMin; yMin: INTEGER _ sSel.yMin; xMax: INTEGER _ sSel.xMax; yMax: INTEGER _ sSel.yMax; SilFile.DeselectAll[]; SilDisplayUtils.MergeRebuild[ dData: dataOfCurrentSelection.displayData, model: dataOfCurrentSelection.model, xMin: xMin, yMin: yMin, xMax: xMax, yMax: yMax ]; }; dataOfCurrentSelection _ data; }; MoveOriginToMark: PUBLIC ENTRY PROC [data: SilData, ctx: Imager.Context _ NIL] = { <> <<>> TurnOffTheOrigin[data, ctx]; dataOfOriginViewer _ dataOfMarkViewer; originX _ markX; originY _ markY; SilUserInput.SetCaretChange[dataOfMarkViewer.uiData]; }; InterchangeMarkAndOrigin: PUBLIC ENTRY PROC [data: SilData, ctx: Imager.Context _ NIL] = { <> <<>> oMarkX: INTEGER _ markX; oMarkY: INTEGER _ markY; oDataOfMarkViewer: SilData _ dataOfMarkViewer; oDataOfOriginViewer: SilData _ dataOfOriginViewer; TurnOffTheOrigin[data, ctx]; TurnOffTheMark[data, ctx]; markX _ originX; markY _ originY; dataOfMarkViewer _ oDataOfOriginViewer; originX _ oMarkX; originY _ oMarkY; dataOfOriginViewer _ oDataOfMarkViewer; SilUserInput.GetInputFocus[dataOfMarkViewer.uiData]; SilUserInput.SetCaretChange[dataOfMarkViewer.uiData]; SilUserInput.SetCaretChange[dataOfOriginViewer.uiData]; }; DeleteAndEraseSelection: PUBLIC ENTRY PROC [data: SilData, ctx: Imager.Context _ NIL, cache: BOOL _ FALSE] = { <> <<>> fudge: INTEGER = 10; -- fudge factor for EraseArea needed to catch all descenders in fonts sSel: SilSelection _ SilFile.GetSelection[]; xMin: INTEGER _ sSel.xMin; yMin: INTEGER _ sSel.yMin; xMax: INTEGER _ sSel.xMax; yMax: INTEGER _ sSel.yMax; IF dataOfCurrentSelection # NIL AND sSel.objects # NIL THEN { SilUserInput.Enque[[MarkAsEdited[]], dataOfCurrentSelection.uiData]; IF data = dataOfCurrentSelection THEN { FOR s: SilObject _ sSel.objects, s.first.selectObj WHILE s # sSel.lastObject DO SilDisplayUtils.PaintObject[data.model, s.first, erase, ctx];--UNselect all objects ENDLOOP; } ELSE SilUserInput.Enque[[EraseArea[xMin-fudge, yMin-fudge, xMax+fudge, yMax+fudge]], dataOfCurrentSelection.uiData]; SilFile.DeleteAndCacheSelection[cache: cache]; SilDisplayUtils.MergeRebuild[ dataOfCurrentSelection.displayData, dataOfCurrentSelection.model, xMin-fudge, yMin-fudge, xMax+fudge, yMax+fudge ]; }; dataOfCurrentSelection _ NIL; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Selections, intArg1: 0]; }; DeselectAndRedraw: PUBLIC ENTRY PROC [] = { <> <<>> sSel: SilSelection _ SilFile.GetSelection[]; xMin: INTEGER _ sSel.xMin; yMin: INTEGER _ sSel.yMin; xMax: INTEGER _ sSel.xMax; yMax: INTEGER _ sSel.yMax; SilFile.DeselectAll[]; IF dataOfCurrentSelection # NIL AND sSel.objects # NIL THEN SilDisplayUtils.MergeRebuild[ dataOfCurrentSelection.displayData, dataOfCurrentSelection.model, xMin, yMin, xMax, yMax ]; dataOfCurrentSelection _ NIL; }; InitiateNewSelection: PUBLIC ENTRY PROC [data: SilData] = { <> dataOfCurrentSelection _ data; }; MouseAndMarkInSameWindow: PUBLIC ENTRY PROC [data: SilData] RETURNS [BOOL] = { <> RETURN[data = dataOfMarkViewer]; }; MouseAndOriginInSameWindow: PUBLIC ENTRY PROC [data: SilData] RETURNS [BOOL] = { <> RETURN[data = dataOfOriginViewer]; }; MouseAndSelectionInSameWindow: PUBLIC ENTRY PROC [data: SilData] RETURNS [BOOL] = { <> RETURN[data = dataOfCurrentSelection]; }; MarkAndOriginInSameWindow: PUBLIC ENTRY PROC [] RETURNS [BOOL] = { <> RETURN[dataOfOriginViewer = dataOfMarkViewer]; }; MarkAndSelectionInSameWindow: PUBLIC ENTRY PROC [] RETURNS [BOOL] = { <> RETURN[dataOfCurrentSelection = dataOfMarkViewer]; }; OriginAndSelectionInSameWindow: PUBLIC ENTRY PROC [] RETURNS [BOOL] = { <> RETURN[dataOfCurrentSelection = dataOfOriginViewer]; }; DisableRopeInput: PUBLIC ENTRY PROC [data: SilData, ctx: Imager.Context _ NIL] = { <> IF data = dataOfMarkViewer THEN SilDisplayUtils.AbortRopeInput[data, markX, markY, ctx]; }; SetMarkX: PUBLIC ENTRY PROC [mX: INTEGER] = { <> markX _ mX }; SetMarkY: PUBLIC ENTRY PROC [mY: INTEGER] = { <> markY _ mY; }; SetOriginX: PUBLIC ENTRY PROC [ oX: INTEGER] = { <> originX _ oX }; <<>> SetOriginY: PUBLIC ENTRY PROC [oY: INTEGER] = { <> originY _ oY; }; <<>> GetMarkX: PUBLIC ENTRY PROC [] RETURNS [mX: INTEGER] = { <> mX _ markX }; GetMarkY: PUBLIC ENTRY PROC [] RETURNS [mY: INTEGER] = { <> mY _ markY; }; GetOriginX: PUBLIC ENTRY PROC [] RETURNS [oX: INTEGER] = { <> oX _ originX }; <<>> GetOriginY: PUBLIC ENTRY PROC [] RETURNS [oY: INTEGER] = { <> oY _ originY; }; <<>> GetBoundingBoxOfLast2Marks: PUBLIC ENTRY PROC [data: SilData] RETURNS [legalBox: BOOL _ TRUE, xMin, yMin, xMax, yMax: INTEGER _ 0] = { <> IF dataOfMarkViewer # data OR dataOfOldMarkViewer # data THEN { legalBox _ FALSE; RETURN; }; IF oldMarkX < markX THEN { xMin _ oldMarkX; xMax _ markX; } ELSE { xMin _ markX; xMax _ oldMarkX; }; IF oldMarkY < markY THEN { yMin _ oldMarkY; yMax _ markY; } ELSE { yMin _ markY; yMax _ oldMarkY; }; }; <<>> BitmapToCursor: PUBLIC PROC [x, y: NAT, viewer: ViewerClasses.Viewer] = TRUSTED { <> <> vt: Terminal.Virtual = Terminal.Current[]; IF viewer.column#color THEN { --viewer on BW display dr: ImagerPixelMap.DeviceRectangle _ [sMin: MAX[(vt.bwHeight-y),0], fMin: x, sSize: 16, fSize: 16]; cursorBitmapRef: REF Terminal.BWCursorBitmap _ NEW[Terminal.BWCursorBitmap]; screenPMap: ImagerPixelMap.PixelMap _ ImagerOps.PixelMapFromFrameBuffer[frameBuffer: Terminal.GetBWFrameBuffer[vt]]; cursorPMap: ImagerPixelMap.PixelMap _ ImagerPixelMap.Create[lgBitsPerPixel: 0, bounds: [sMin: 0, fMin: 0, sSize: 16, fSize: 16]]; cursorPMap.refRep.ref _ cursorBitmapRef; cursorPMap.refRep.pointer _ LOOPHOLE[cursorBitmapRef]; screenPMap _ ImagerPixelMap.SetWindow[p: screenPMap, bounds: dr]; <> <<"match" the screenPMap origin>> cursorPMap.sOrigin _ screenPMap.sMin; cursorPMap.fOrigin _ screenPMap.fMin; ImagerPixelMap.Transfer[dest: cursorPMap, source: screenPMap, function: [null,null]]; IF cursorBitmapRef^=ALL[0] THEN RETURN; Terminal.SetBWCursorPattern[vt: vt, pattern: cursorBitmapRef^]; } ELSE { --viewer on color display Bit: TYPE = [0..1]; screenSMin: INTEGER _ MAX[(vt.colorHeight-y),0]; cursorBitmapRef: REF Terminal.ColorCursorBitmap _ NEW[Terminal.ColorCursorBitmap]; cursorBitmapArray: LONG POINTER TO PACKED ARRAY [0..0) OF Bit _ LOOPHOLE[cursorBitmapRef]; screenPMap: ImagerPixelMap.PixelMap _ ImagerOps.PixelMapFromFrameBuffer[frameBuffer: Terminal.GetColorFrameBufferA[vt]]; [] _ Terminal.SetColorCursorPresentation[vt: vt, new: onesAreBlack]; FOR i: INTEGER IN [0..256) DO cursorBitmapArray[i] _ IF ImagerPixelMap.GetPixel[screenPMap, screenSMin+(i/16), x+(i MOD 16)]=255 THEN 0 ELSE 1; ENDLOOP; IF cursorBitmapRef^=ALL[0] THEN RETURN; Terminal.SetColorCursorPattern[vt: vt, pattern: cursorBitmapRef^]; }; }; END.