MessageWindowImpl.mesa; written by S. McGregor
Edited by McGregor on August 4, 1983 11:22 am
Last Edited by: Maxwell, February 14, 1983 10:22 am
Last Edited by: Pausch, July 18, 1983 5:01 pm
Last Edited by: Wyatt, October 24, 1983 3:29 pm
DIRECTORY
CedarVersion USING [major, minor, patch],
Convert USING [ValueToRope],
Imager USING [black, Context, IntegerMaskRectangle, IntegerSetXY, SetColor, ShowCharacters, white, XOR],
InputFocus USING [CaptureButtons, PopInputFocus, PushInputFocus, ReleaseButtons,
SetInputFocus],
IO USING [PutFR, time],
MessageWindow USING [],
MessageWindowPrivate USING [],
Process USING [MsecToTicks, Pause],
Rope USING [Cat, Fetch, FromRefText, ROPE, Size, Substr],
Runtime USING [GetBcdTime],
TIPUser USING [InstantiateNewTIPTable],
UserTerminal USING [BlinkDisplay],
VFonts USING [defaultFont],
ViewerClasses,
ViewerLocks USING [CallUnderWriteLock, Wedged],
ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass],
ViewerSpecs,
WindowManager USING [UnWaitCursor, WaitCursor];
MessageWindowImpl: CEDAR MONITOR
IMPORTS CedarVersion, Convert, Imager, IO, InputFocus, Process, Rope, Runtime, TIPUser, UserTerminal, VFonts, ViewerLocks, ViewerOps, WindowManager
EXPORTS MessageWindow, MessageWindowPrivate
= BEGIN
messageWindow: PUBLIC ViewerClasses.Viewer;
mode: {none, input, confirm} ← none;
ready: BOOLEANFALSE;
confirm: BOOLEAN;
inputReady: CONDITION;
empty: BOOLEANTRUE;
maxLength: INTEGER = 120;
static: REF TEXTNEW[TEXT[maxLength]];
typein: REF TEXTNEW[TEXT[maxLength]];
Clear: PUBLIC PROC = {
IF empty OR messageWindow=NIL OR mode#none THEN RETURN;
ViewerLocks.CallUnderWriteLock[LockedClear, messageWindow
! ViewerLocks.Wedged => CONTINUE]};
LockedClear: PROC = {
static.length ← typein.length ← 0; empty ← TRUE;
ViewerOps.PaintViewer[viewer: messageWindow, hint: client, whatChanged: $Clear]};
Append: PUBLIC PROC [message: Rope.ROPE, clearFirst: BOOLEANFALSE] = BEGIN
LockedAppend: PROC = {
IF clearFirst THEN static.length ← typein.length ← 0;
FOR n: LONG INTEGER IN [0..Rope.Size[message]) DO
IF static.length >= maxLength THEN EXIT;
static[static.length] ← Rope.Fetch[message, n];
static.length ← static.length + 1;
ENDLOOP;
ViewerOps.PaintViewer[messageWindow, client, TRUE, $Append];
empty ← FALSE};
IF messageWindow=NIL OR mode#none THEN RETURN;
ViewerLocks.CallUnderWriteLock[LockedAppend, messageWindow
! ViewerLocks.Wedged => CONTINUE];
END;
Blink: PUBLIC PROC = BEGIN
IF messageWindow=NIL THEN RETURN;
THROUGH [0..6) DO
ViewerOps.PaintViewer[messageWindow, client, FALSE, $Invert];
Process.Pause[Process.MsecToTicks[150]];
ENDLOOP;
END;
ReadFrom: PUBLIC ENTRY PROC RETURNS [message: Rope.ROPE] =
BEGIN
IF messageWindow=NIL OR mode#none THEN RETURN[""];
mode ← input;
typein.length ← 0;
InputFocus.PushInputFocus[messageWindow];
InputFocus.CaptureButtons[MessageWindowNotify, messageWindowClass.tipTable,
messageWindow];
WindowManager.WaitCursor[typeKey];
UNTIL ready=TRUE DO WAIT inputReady; ENDLOOP;
InputFocus.PopInputFocus[];
ready ← FALSE;
mode ← none;
WindowManager.UnWaitCursor[];
empty ← FALSE;
RETURN[Rope.FromRefText[typein]];
END;
nextInLine: CONDITION;
Confirm: PUBLIC ENTRY PROC [prompt: Rope.ROPENIL] RETURNS [BOOLEAN] = BEGIN
string: Rope.ROPE ← Rope.Cat["LeftMouse=>Yes, right=>No: ",prompt];
WHILE mode#none DO WAIT nextInLine; ENDLOOP; -- wait in line
InputFocus.CaptureButtons[MessageWindowNotify, messageWindowClass.tipTable,
messageWindow];
InputFocus.SetInputFocus[];
mode ← confirm;
typein.length ← 0;
WindowManager.WaitCursor[confirm];
IF string#NIL THEN BEGIN
static.length ← 0;
FOR n: LONG INTEGER IN [0..Rope.Size[string]) DO
IF static.length >= maxLength THEN ERROR;
static[static.length] ← Rope.Fetch[string, n];
static.length ← static.length + 1;
ENDLOOP;
ViewerOps.PaintViewer[messageWindow, client, FALSE, $Append];
END;
UNTIL ready=TRUE DO WAIT inputReady; ENDLOOP;
InputFocus.ReleaseButtons[];
ready ← FALSE;
WindowManager.UnWaitCursor[];
static.length ← 0;
ViewerOps.PaintViewer[messageWindow, client, TRUE, $Clear];
empty ← FALSE;
mode ← none;
NOTIFY nextInLine;
RETURN[confirm];
END;
Destroy: PUBLIC PROC = BEGIN
IF messageWindow#NIL THEN ViewerOps.DestroyViewer[messageWindow];
messageWindow ← NIL;
ERROR; -- no longer implemented
END;
PostReleaseVersion: PROC = BEGIN OPEN CedarVersion;
FromCard: PROC [c: CARDINAL] RETURNS [Rope.ROPE] = INLINE
{RETURN[Convert.ValueToRope[[unsigned[c, 10]]]]};
version: Rope.ROPE ← Rope.Cat[FromCard[major], ".", FromCard[minor]];
patchVersion: Rope.ROPEIF patch=0 THEN NIL ELSE Rope.Cat[".", FromCard[patch]];
timeLen: INT = 9; -- shortened to trim off time
cedarLen: INT = 6+3+(IF patch=0 THEN 0 ELSE IF patch>9 THEN 3 ELSE 2)+12;
cedarMsg: Rope.ROPE ← Rope.Cat["Cedar ", version, patchVersion, " release of %t"];
Append[Rope.Substr[IO.PutFR[cedarMsg,
IO.time[Runtime.GetBcdTime[]]], 0, cedarLen+timeLen], TRUE];
Append[" ... "];
END;
MessageWindowPaint: PRIVATE ViewerClasses.PaintProc = BEGIN
IF whatChanged = $Invert THEN BEGIN
Imager.SetColor[context, Imager.XOR];
Imager.IntegerMaskRectangle[context, 0, 0, self.cw, self.ch];
END
ELSE BEGIN
bottomOffset: INTEGER = 3;
leftOffset: INTEGER = 2;
IF ~clear THEN BEGIN
Imager.SetColor[context, Imager.white];
Imager.IntegerMaskRectangle[context, 0, 0, self.cw, self.ch];
Imager.SetColor[context, Imager.black];
END;
Imager.IntegerSetXY[context, leftOffset, bottomOffset];
Imager.ShowCharacters[context, static, VFonts.defaultFont];
Imager.ShowCharacters[context, typein, VFonts.defaultFont];
END;
END;
MessageWindowNotify: PRIVATE ENTRY ViewerClasses.NotifyProc = BEGIN
FOR l: LIST OF REF ANY ← input, l.rest UNTIL l=NIL DO
IF mode = input THEN WITH l.first SELECT FROM
c: REF CHARACTER => IF c^=15C OR c^=33C THEN BEGIN
ready ← TRUE;
NOTIFY inputReady;
END
ELSE BEGIN
IF c^=10C OR c^=01C OR c^=177C THEN BEGIN
typein.length ← IF c^=177C THEN 0 ELSE MAX[typein.length, 1]-1;
END
ELSE BEGIN
IF typein.length >= maxLength THEN ERROR;
typein[typein.length] ← c^;
typein.length ← typein.length + 1;
END;
ViewerOps.PaintViewer[messageWindow, client, FALSE, $Append];
END;
ENDCASE => TRUSTED {UserTerminal.BlinkDisplay[]}
ELSE IF mode=confirm THEN WITH l.first SELECT FROM
c: REF CHARACTER => SELECT c^ FROM
'y,'Y,15C,33C => BEGIN
ready ← confirm ← TRUE;
NOTIFY inputReady;
END;
'n,'N,177C => BEGIN
confirm ← FALSE;
ready ← TRUE;
NOTIFY inputReady;
END;
ENDCASE => TRUSTED {UserTerminal.BlinkDisplay[]};
a: ATOM => SELECT a FROM
$Yes  => BEGIN
ready ← confirm ← TRUE;
NOTIFY inputReady;
END;
$No  => BEGIN
confirm ← FALSE;
ready ← TRUE;
NOTIFY inputReady;
END;
ENDCASE => TRUSTED {UserTerminal.BlinkDisplay[]};
ENDCASE => ERROR
ELSE IF l.first=$Yes THEN LockedClear[];
ENDLOOP;
END;
MessageWindowModify: PRIVATE ENTRY ViewerClasses.ModifyProc = BEGIN
[self: Viewer, change: ModifyAction]
might want to start a caret someday
END;
messageWindowClass: ViewerClasses.ViewerClass ← NEW[ViewerClasses.ViewerClassRec ← [
paint: MessageWindowPaint,
notify: MessageWindowNotify,
modify: MessageWindowModify,
tipTable: TIPUser.InstantiateNewTIPTable["/Indigo/CedarViewers/Viewers/MessageWindow.tip"]
]];
ViewerOps.RegisterViewerClass[$MessageWindow, messageWindowClass];
messageWindow ← ViewerOps.CreateViewer[$MessageWindow, [name: "MW",
wy: ViewerSpecs.screenH-ViewerSpecs.messageWindowHeight,
ww: ViewerSpecs.messageWindowWidth, wh: ViewerSpecs.messageWindowHeight,
column: static]
];
PostReleaseVersion[];
END.