NewIOMiscImpl.mesa
Last editted: March 28, 1983 4:50 pm by Stewart
Last Edited by: Teitelman, April 20, 1983 3:49 pm
DIRECTORY
AMEvents USING [Debugged, Debugging],
Ascii USING [DEL],
Atom USING [GetPName, GetPropFromList],
IO USING [atom, char, PutChar, PutRope, GetChar, PutF, CharsAvail, STREAM, NewLine, UserAbort, UserAborted],
IOMisc USING [],
Rope USING [Upper, Fetch, ROPE],
Process USING [Pause, MsecToTicks],
ProcessProps USING [GetPropList]
;
IOMiscImpl: CEDAR PROGRAM
IMPORTS AMEvents, Atom, IO, Process, ProcessProps, Rope
defaultKeyList: LIST OF ATOM = LIST[$Yes, $No];
AskUser:
PUBLIC PROC [msg: Rope.
ROPE, in, out:
IO.
STREAM, defaultKey:
ATOM ←
NIL, keyList:
LIST
OF
ATOM ←
NIL, timeout:
INT ← -1]
RETURNS [value:
ATOM] = {
char: CHAR;
r: REF ANY = Atom.GetPropFromList[ProcessProps.GetPropList[], $AskUser]; -- a way for later packages, e.g. UserExec, to provide a more fancy version of AskUser.
IF r #
NIL
THEN value ← (
NARROW[r,
REF
PROC [msg: Rope.
ROPE, in, out:
IO.
STREAM, defaultKey:
ATOM, keyList:
LIST
OF
ATOM, timeout:
INT]
RETURNS [value:
ATOM]])^[msg, in, out, defaultKey, keyList, timeout !
AMEvents.Debugging, AMEvents.Debugged => REJECT;
UNWIND, IO.UserAborted, ABORTED => NULL;
ANY => CONTINUE
]; -- if anything goes wrong, drop through and use dumb askuser.
IF value # NIL THEN RETURN[value];
UNTIL in.backingStream =
NIL
DO
in ← in.backingStream;
ENDLOOP;
IF keyList = NIL THEN keyList ← defaultKeyList;
IF timeout > 0 AND timeout < 30 THEN timeout ← timeout * 1000; -- timeout expressed in seconds, should be milliseconds
DO
elapsedTime: INT ← 0;
out.NewLine[];
out.PutRope[msg];
out.PutRope[" (Respond using keyboard) "];
IF timeout # -1
THEN
UNTIL elapsedTime > timeout -- timeout is in seconds.
-- DO
Process.Pause[Process.MsecToTicks[100]];
elapsedTime ← elapsedTime + 100;
IF in.UserAbort[] THEN ERROR IO.UserAborted[in];
IF in.CharsAvail[] THEN EXIT;
REPEAT
FINISHED =>
{
out.PutF["...%g\n", IO.atom[defaultKey]];
RETURN[defaultKey];
};
ENDLOOP;
char ← in.GetChar[];
IF char = Ascii.DEL THEN char ← 'N;
timeout ← -1; -- once user types a character, don't timeout.
FOR l:
LIST
OF
ATOM ← keyList, l.rest
UNTIL l =
NIL
DO
r: Rope.ROPE = Atom.GetPName[l.first];
IF char = '\n
-- matches first key --
OR Rope.Upper[Rope.Fetch[r, 0]] = Rope.Upper[char]
THEN {
out.PutRope[r];
out.PutChar['\n];
RETURN[l.first];
};
REPEAT
FINISHED => {
-- didn't match
out.PutChar[char];
out.PutF["\nType one of: "];
FOR l:
LIST
OF
ATOM ← keyList, l.rest
UNTIL l =
NIL
DO
out.PutF["%g, ", IO.char[Rope.Fetch[Atom.GetPName[l.first], 0]]];
ENDLOOP;
};
ENDLOOP;
ENDLOOP;
};
END.