SilDisplayCursorsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Tracy Larrabee: March 29, 1984 1:26:12 pm PST
Last Edited by Ken Pier, August 22, 1985 5:07:21 pm PDT
A module implementing the control of the carets and the input focus.
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;
GLOBAL VARIABLES:
Information about the state of the carets:
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;
Keep data about the viewer with current selection in case we need to talk to that viewer
dataOfCurrentSelection: SilData;
SilCursorsInit: PUBLIC ENTRY PROC [] = {
Initialize the behavior of the Sil Carets
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;
Keep data about the viewer with current selection in case we need to talk to that viewer
dataOfCurrentSelection ← NIL;
};
SilCursorsBlink: PUBLIC ENTRY PROC [] = {
Make sure that all the appropriate Sil Instances know to blink their carets.
Only blink the carets if Sil has the input focus.
This mght produce 2 calls to the same viewer, but this is OK
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] = {
For this window, blink the carets which should be blinking.
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] = {
Turn off the mark, wherever it is, and make sure the system knows the correct window for the mark to be in. Make sure we have the input focus.
TurnOffTheMark[data, ctx];
dataOfMarkViewer ← data;
SilUserInput.GetInputFocus[data.uiData];
};
TurnOffTheMark: INTERNAL PROC [data: SilData, ctx: Imager.Context ← NIL] = {
Turn off the mark, wherever it is.
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] = {
Turn off the origin, wherever it is, and make sure the system knows the correct window for the origin to be in.
TurnOffTheOrigin[data, ctx];
dataOfOriginViewer ← data;
IF NOT SilUserInput.HasInputFocus[] THEN SilUserInput.GetInputFocus[data.uiData];
};
TurnOffTheOrigin: INTERNAL PROC [data: SilData, ctx: Imager.Context ← NIL] = {
Turn off the origin, wherever it is.
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] = {
Make sure that if data is not the current selection window it is safe to change selection windows.
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] = {
Move the origin to the mark
TurnOffTheOrigin[data, ctx];
dataOfOriginViewer ← dataOfMarkViewer;
originX ← markX; originY ← markY;
SilUserInput.SetCaretChange[dataOfMarkViewer.uiData];
};
InterchangeMarkAndOrigin: PUBLIC ENTRY PROC [data: SilData, ctx: Imager.Context ← NIL] = {
Move the mark to the origin and the origin to the mark
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: BOOLFALSE] = {
Delete the selection.
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 [] = {
Deselect and Redraw the elements which used to be selected.
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] = {
Set the current Selection Window.
dataOfCurrentSelection ← data;
};
MouseAndMarkInSameWindow: PUBLIC ENTRY PROC [data: SilData] RETURNS [BOOL] = {
True if data is same window as window where mark is.
RETURN[data = dataOfMarkViewer];
};
MouseAndOriginInSameWindow: PUBLIC ENTRY PROC [data: SilData] RETURNS [BOOL] = {
True if data is same window as window where origin is.
RETURN[data = dataOfOriginViewer];
};
MouseAndSelectionInSameWindow: PUBLIC ENTRY PROC [data: SilData] RETURNS [BOOL] = {
True if data is same window as window where selection is.
RETURN[data = dataOfCurrentSelection];
};
MarkAndOriginInSameWindow: PUBLIC ENTRY PROC [] RETURNS [BOOL] = {
True if mark is same window as window where origin is.
RETURN[dataOfOriginViewer = dataOfMarkViewer];
};
MarkAndSelectionInSameWindow: PUBLIC ENTRY PROC [] RETURNS [BOOL] = {
True if mark is same window as window where selection is.
RETURN[dataOfCurrentSelection = dataOfMarkViewer];
};
OriginAndSelectionInSameWindow: PUBLIC ENTRY PROC [] RETURNS [BOOL] = {
True if origin is same window as window where selection is.
RETURN[dataOfCurrentSelection = dataOfOriginViewer];
};
DisableRopeInput: PUBLIC ENTRY PROC [data: SilData, ctx: Imager.Context ← NIL] = {
Make sure that any textual input with respect to the current window is stopped.
IF data = dataOfMarkViewer THEN
SilDisplayUtils.AbortRopeInput[data, markX, markY, ctx];
};
SetMarkX: PUBLIC ENTRY PROC [mX: INTEGER] = {
Set the Mark's position.
markX ← mX
};
SetMarkY: PUBLIC ENTRY PROC [mY: INTEGER] = {
Set the Mark's position.
markY ← mY;
};
SetOriginX: PUBLIC ENTRY PROC [ oX: INTEGER] = {
Set the Origin's position.
originX ← oX
};
SetOriginY: PUBLIC ENTRY PROC [oY: INTEGER] = {
Set the Origin's position.
originY ← oY;
};
GetMarkX: PUBLIC ENTRY PROC [] RETURNS [mX: INTEGER] = {
Get the Mark's position.
mX ← markX
};
GetMarkY: PUBLIC ENTRY PROC [] RETURNS [mY: INTEGER] = {
Get the Mark's position.
mY ← markY;
};
GetOriginX: PUBLIC ENTRY PROC [] RETURNS [oX: INTEGER] = {
Get the Origin's position.
oX ← originX
};
GetOriginY: PUBLIC ENTRY PROC [] RETURNS [oY: INTEGER] = {
Get the Origin's position.
oY ← originY;
};
GetBoundingBoxOfLast2Marks: PUBLIC ENTRY PROC [data: SilData] RETURNS [legalBox: BOOLTRUE, xMin, yMin, xMax, yMax: INTEGER ← 0] = {
Return the bounding box for the last 2 marks in this window.
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 {
Transfer the 16x16 bitmap with mark as upper left origin to the terminal cursor bitmap
x, y in screen coordinates
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];
Now, execute a magic line of code which sets up the cursorPMap origin to
"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: INTEGERMAX[(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.