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 EXPORTS IOMisc = BEGIN 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. ~NewIOMiscImpl.mesa Last editted: March 28, 1983 4:50 pm by Stewart Last Edited by: Teitelman, April 20, 1983 3:49 pm ÊŸ˜Jšœ™Jšœ/™/J™1šÏk ˜ Jšœ œ˜%Jšœœœ˜Jšœœ˜'Jšœœ;œ#˜lJšœœ˜Jšœœœ˜ Jšœœ˜#Jšœ œ˜ Jšœ˜J˜—JšÐbl œœ˜Jšœœ˜7šœ ˜J™—Jš œœœœœ ˜/J˜šÏnœ œ œ œœœœ œœœœ œœ œ˜›Jšœœ˜ Jšœœœ>ÏcX˜ š œœœ œœœ œ œœœ œœœ œœ œ2˜ÎJšœ)œ˜0Jšœœœœ˜(Jšœ˜Jšœ >˜B—Jšœ œœœ˜"šœœ˜J˜Jšœ˜—Jšœ œœ˜/Jšœ œœ 7˜wš˜Jšœ œ˜J˜J˜Jšœ*˜*šœœœ0˜PJšœ(˜(J˜ Jšœœœœ˜0Jšœœœ˜Jš˜šœ˜ Jšœœ˜)Jšœ ˜J˜Jšœ˜—Jšœ˜Jšœœœ ˜$Jšœ /˜>š œœœœœœ˜6Jšœœ˜&šœ  œœ1œ˜aJ˜J˜Jšœ ˜J˜—Jš˜šœ ˜Jšœ˜Jšœ˜š œœœœœœ˜6Jšœœ.˜AJšœ˜—J˜—Jšœ˜—Jšœ˜—J˜—J™Jšœ˜—J˜—…— Ð í