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
DIRECTORY
CedarVersion USING [major, minor, patch],
Convert USING [ValueToRope],
Imager USING [black, Context, MaskIntRectangle, MaskCharacters, SetColor, SetCP, white],
InputFocus
USING [CaptureButtons, PopInputFocus, PushInputFocus, ReleaseButtons,
SetInputFocus],
IO USING [PutFR, time],
MessageWindow,
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 =
BEGIN
messageWindow: PUBLIC ViewerClasses.Viewer;
mode: {none, input, confirm} ← none;
ready: BOOLEAN ← FALSE;
confirm: BOOLEAN;
inputReady: CONDITION;
empty: BOOLEAN ← TRUE;
maxLength: INTEGER = 120;
static: REF TEXT ← NEW[TEXT[maxLength]];
typein: REF TEXT ← NEW[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:
BOOLEAN ←
FALSE] =
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.
ROPE ←
NIL]
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.ROPE ← IF 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
OPEN Imager;
IF whatChanged = $Invert
THEN
BEGIN
SetColor[context, $XOR];
MaskIntRectangle[context, [0, 0, self.cw, self.ch]];
END
ELSE
BEGIN
bottomOffset: REAL = 3;
leftOffset: REAL = 2;
IF ~clear
THEN
BEGIN
SetColor[context, white];
MaskIntRectangle[context, [0, 0, self.cw, self.ch]];
SetColor[context, black];
END;
SetCP[context, [leftOffset, bottomOffset]];
MaskCharacters[context, VFonts.defaultFont, static];
MaskCharacters[context, VFonts.defaultFont, 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 {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.