MessageWindowImpl.mesa
Copyright © 1982, 1983, 1984 Xerox Corporation. All rights reserved.
McGregor on September 10, 1982 10:41 am
Maxwell, February 14, 1983 10:22 am
Paul Rovner, June 16, 1983 8:53 am
Russ Atkinson, November 18, 1983 1:30 pm
Doug Wyatt, September 4, 1984 3:34:17 pm PDT
DIRECTORY
Imager USING [black, Context, FONT, MaskRectangleI, SetColor, SetFont, SetXYI, ShowText, white],
ImagerOps USING [ImagerFromGraphics, XOR],
InputFocus USING [CaptureButtons, PopInputFocus, PushInputFocus, ReleaseButtons,
SetInputFocus],
Interminal USING [terminal],
MessageWindow USING [],
Process USING [MsecToTicks, Pause],
Rope USING [Fetch, FromRefText, ROPE, Size],
TIPUser USING [InstantiateNewTIPTable],
Terminal USING [BlinkBWDisplay],
VFonts USING [defaultFont],
ViewerClasses USING [ModifyProc, NotifyProc, PaintProc, Viewer, ViewerClass, ViewerClassRec],
ViewerExtras USING [ImagerFont],
ViewerLocks USING [CallUnderWriteLock, Wedged],
ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass],
ViewerSpecs USING [messageWindowHeight, messageWindowWidth, screenH],
WindowManager USING [UnWaitCursor, WaitCursor];
MessageWindowImpl: CEDAR MONITOR
IMPORTS Imager, ImagerOps, InputFocus, Interminal, Process, Rope, TIPUser, Terminal, VFonts, ViewerExtras, ViewerLocks, ViewerOps, WindowManager
EXPORTS MessageWindow
= 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
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 prompt#NIL THEN BEGIN
static.length ← 0;
FOR n: LONG INTEGER IN [0..Rope.Size[prompt]) DO
IF static.length >= maxLength THEN ERROR;
static[static.length] ← Rope.Fetch[prompt, 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;
version: Rope.ROPE ← Rope.Cat[IO.PutR[IO.card[major]], ".", IO.PutR[IO.card[minor]]];
patchVersion: Rope.ROPE ← IF patch=0 THEN NIL ELSE Rope.Cat[".", IO.PutR[IO.card[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;
messageFont: Imager.FONT ← ViewerExtras.ImagerFont[VFonts.defaultFont];
MessageWindowPaint: PRIVATE ViewerClasses.PaintProc = BEGIN
PROC[self: Viewer, context: Graphics.Context, whatChanged: REF ANY, clear: BOOL]
imager: Imager.Context ~ ImagerOps.ImagerFromGraphics[context];
IF whatChanged = $Invert THEN BEGIN
Imager.SetColor[imager, ImagerOps.XOR];
Imager.MaskRectangleI[imager, 0, 0, self.cw, self.ch];
END
ELSE BEGIN
bottomOffset: INTEGER = 3;
leftOffset: INTEGER = 2;
IF ~clear THEN BEGIN
Imager.SetColor[imager, Imager.white];
Imager.MaskRectangleI[imager, 0, 0, self.cw, self.ch];
END;
Imager.SetColor[imager, Imager.black];
Imager.SetXYI[imager, leftOffset, bottomOffset];
Imager.SetFont[imager, messageFont];
Imager.ShowText[imager, static];
Imager.ShowText[imager, typein];
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 {Interminal.terminal.BlinkBWDisplay[]}
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 {Interminal.terminal.BlinkBWDisplay[]};
a: ATOM => SELECT a FROM
$Yes  => BEGIN
ready ← confirm ← TRUE;
NOTIFY inputReady;
END;
$No  => BEGIN
confirm ← FALSE;
ready ← TRUE;
NOTIFY inputReady;
END;
ENDCASE => TRUSTED {Interminal.terminal.BlinkBWDisplay[]};
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["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.