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:
BOOL ←
FALSE] = {
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:
BOOL ←
TRUE, 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: 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.