(FILECREATED "15-Feb-85 15:49:30" {ERIS}<SPEECH>MAILREADER>PROSE-CONTROLLER.;8 15506
previous date: "15-Feb-85 10:40:33" {ERIS}<SPEECH>MAILREADER>PROSE-CONTROLLER.;7)
(* Copyright (c) 1984, 1985 by Xerox Corporation. All rights reserved.)
(PRETTYCOMPRINT PROSE-CONTROLLERCOMS)
(RPAQQ PROSE-CONTROLLERCOMS ((VARS (P.PASSWORD NIL)
(P.HELP.FLG T)
(ALL.NUMERIC.PASSWORD NIL)
P.TOUCHTONE.LIST)
(CONSTANTS P.TOUCHTONE.LIST)
(FNS P.CONTROLLER P.SET.PASSWORD P.SET.USERNAME P.USER.INIT
P.DECIPHER.TOUCHTONES P.INVALID.TOUCHTONES P.CONTROLLER.RESET)))
(RPAQQ P.PASSWORD NIL)
(RPAQQ P.HELP.FLG T)
(RPAQQ ALL.NUMERIC.PASSWORD NIL)
(RPAQQ P.TOUCHTONE.LIST ((2 A B C)
(3 D E F)
(4 G H I)
(5 J K L)
(6 M N O)
(7 P R S)
(8 T U V)
(9 W X Y)))
(DECLARE: EVAL@COMPILE
(RPAQQ P.TOUCHTONE.LIST ((2 A B C)
(3 D E F)
(4 G H I)
(5 J K L)
(6 M N O)
(7 P R S)
(8 T U V)
(9 W X Y)))
(CONSTANTS P.TOUCHTONE.LIST)
)
(DEFINEQ
(P.CONTROLLER
[LAMBDA NIL (* BBB "15-Feb-85 10:36")
(* Top level control of the PROSE through the phone)
(* The structure of this function is one big COND; what branch is to be taken depends on the settings of the global
variables: P.USER P.PASSWORD P.QUIT and P.READING.MAIL)
(* Trigger button is the button which caused P.PROCESS to wake up and thus P.CONTROLLER to be called, i.e. the last
key pushed on the phone)
(IGNORETIMER T)
TRIGGERBUTTON←STATE:PHONEINPUT:1 (* Should the PROSESTATUS window be updated?)
(DEBUGOUTPUT?)
(* Parse the input to make sure it is well-formed; may be better to do this at various places in the code where we
know more about what the input ought to be)
(VERIFYINPUT STATE:STATE.PHONEINPUT) (* Set the COMMAND field)
(MAKECOMMAND)
(if STATE:QUIT=T and (STATE:STATE.COMMAND or TRIGGERBUTTON=(QUOTE #))
then (* A quit command was given but it was not immediately
followed by a quit command so we should reset the quit
flag)
(STATE:QUIT←NIL)) (* Main control of operations)
(if TRIGGERBUTTON=(QUOTE #) and (EQUAL STATE:STATE.COMMAND (QUOTE (0)))
then (* No user logged in; log the new user
(in; help is wanted))
(P.HELP (QUOTE LOGIN.HELP))
elseif TRIGGERBUTTON=(QUOTE *) and STATE:STATE.COMMAND=NIL
then (* If we get a * when STATE:QUIT is T then we want to
log out)
(if STATE:STATE.MESSAGEQUERY?=(QUOTE T)
then STATE:STATE.MESSAGEQUERY?←NIL
(P.CHUNK "Specify another message. ")
elseif STATE:QUIT=T
then (P.BYE)
elseif STATE:TALKING=(QUOTE HALTED)
then (PROSE.STOP)
STATE:STATE.TALKING←NIL
STATE:STATE.HALTSPEECH←NIL
STATE:MESSAGEQUERY?←NIL
(P.CHUNK " Message aborted. Ready to read another message. ")
else (* Prepare to quit)
STATE:STATE.QUIT←T
(PROSE.STOP)
(P.CHUNK
" You gave a command to quit. If you really want to quit type another asterisk. "))
elseif STATE:STATE.USERINFO.USER=NIL
then (* No user logged in; log the new user in)
(P.SET.USERNAME)
elseif STATE:STATE.USERINFO.PASSWORD=NIL
then (* Password not yet obtained;
obtain it)
(if ~ALL.NUMERIC.PASSWORD and ((EQUAL TRIGGERBUTTON (QUOTE #)) and STATE:COMMAND=NIL)
then ALL.NUMERIC.PASSWORD←T
elseif (P.SET.PASSWORD)
then (* Login was successfull so we start LAFITE up for the
new user)
(P.USER.INIT STATE:STATE.USER)
(P.LAFITE.START.NEW.USER))
elseif STATE:STATE.STATEINFO.QUIT
then (* Maybe quit from Lafite; or read old mail)
(* !!! It is hard to decide where in the hierarchy of states to put this is; It is here mainly because if there is
no new mail QUIT is T in order to allow the user to get out right away !!!)
(P.QUIT.OR.READ.OLD.MAIL TRIGGERBUTTON)
elseif (EQUAL STATE:STATE.STATEINFO.TALKING (QUOTE HALTED))
then (* Speech output has been halted
(during the utterance of a msg body))
(if (EQUAL TRIGGERBUTTON (QUOTE #))
then (* The user specified a number of sentences to back up)
(BACK.SENTENCE TRIGGERBUTTON STATE:STATE.COMMAND)
STATE:STATE.STATEINFO.HALTSPEECH←NIL
(COPYMSGBYTES STATE:STATE.PROSEINPUT.TEMPFILE (GETSTREAM (QUOTE {RS232})))
elseif (EQUAL TRIGGERBUTTON (QUOTE *))
then (* The user specified a number of sentences to back up)
(BACK.SENTENCE TRIGGERBUTTON STATE:STATE.COMMAND)
STATE:STATE.STATEINFO.HALTSPEECH←NIL
(COPYMSGBYTES STATE:STATE.PROSEINPUT.TEMPFILE (GETSTREAM (QUOTE {RS232})))
else (* The user simply wanted to quit out of reading the
msg alltogether)
(P.FINISHED.ACTIONS))
elseif ~(STATE:STATE.LAFITEINFO.FOLDEROPEN)
then (* No browser open so open one)
(if STATE:STATE.LAFITEINFO.NEWMAIL
then (* Both open it and get new mail)
(P.OPEN.FOLDER.AND.GET.NEW.MAIL STATE:STATE.USERINFO.USER)
elseif STATE:STATE.LAFITEINFO.NONEWMAIL
then (* No new mail, so we just open the browser on the
mailfile associated with USER)
(P.READ.OLD.MAIL (P.MAILFILE STATE:STATE.USERINFO.USER T))
else (SHOULDNT))
elseif STATE:STATE.STATEINFO.MESSAGEQUERY?
then
(* The user has selected a message or a message has been selected for him; he has been presented with the header of
the message; we now let the user decide whether or not to read the message body depeding on the button which was
pushed)
[if TRIGGERBUTTON=(QUOTE *)
then (* Don't read it)
(* Reset MESSAGEQUERY?; another # or MSG.NO# has to be
pushed in order to hear another message)
STATE:STATE.MESSAGEQUERY?←NIL
elseif TRIGGERBUTTON=(QUOTE #)
then (* Read it)
STATE:STATE.MESSAGEQUERY?←NIL
(P.SAY.BODY STATE:STATE.LAFITEINFO.MAILFOLDER (OR
STATE:STATE.PROSEINPUT.MSGDESCRIPTOR
(PROGN (P.SELECT.MSG
STATE:STATE.LAFITEINFO.MAILFOLDER)
STATE:STATE.PROSEINPUT.MSGDESCRIPTOR]
else (* Default case is that we are reading mail;
we select a message to utter from the phone input)
(P.SELECT.AND.SAY.MSG STATE:STATE.INPUTINFO.COMMAND))
(P.RESET.TIMER)
(IGNORETIMER NIL])
(P.SET.PASSWORD
[LAMBDA NIL (* pkh: "23-Jan-85 16:46")
(USEDFREE \LAFITE.AUTHENTICATION.FAILURE)
[SETQ PASSWORD (COND
(ALL.NUMERIC.PASSWORD (PACK (fetch (STATE INPUTINFO COMMAND) of STATE)))
(T (P.DECIPHER.TOUCHTONES (fetch (STATE INPUTINFO COMMAND) of STATE]
(SETQ ALL.NUMERIC.PASSWORD NIL) (* printout T "PASSWORD IS " PASSWORD T)
(COND
((AND PASSWORD (NEQ PASSWORD (PACK NIL)))
(SETUSERNAME (fetch (STATE USER) of STATE))
(SETPASSWORD NIL (fetch (STATE USER) of STATE)
(MKSTRING PASSWORD))
(SETPASSWORD (QUOTE PHYLUM)
(fetch (STATE USER) of STATE)
(MKSTRING PASSWORD))
(SETPASSWORD (QUOTE ERIS)
(fetch (STATE USER) of STATE)
(MKSTRING PASSWORD))
(SETPASSWORD (QUOTE IVY)
(fetch (STATE USER) of STATE)
(MKSTRING PASSWORD)) (* Indigo for fonts)
(SETPASSWORD (QUOTE INDIGO)
(fetch (STATE USER) of STATE)
(MKSTRING PASSWORD))
(LAFITECLEARCACHE) (* Set the password)
(SETQ \LAFITE.AUTHENTICATION.FAILURE NIL) (* Flush any user specific info)
(P.CHUNK "We are checking the password. ")
(P.AUTHENTICATE)
(SELECTQ \LAFITE.AUTHENTICATION.FAILURE
(BadRName (P.CHUNK " Please re-enter your name.")
(P.CONTROLLER.RESET)
NIL)
(BadPassword (replace (STATE USERINFO PASSWORD) of STATE with NIL)
(P.CHUNK " Please re-enter your password. ")
NIL)
(PROGN (replace (STATE USERINFO PASSWORD) of STATE with T)
(P.CHUNK "You are logged in, checking for new mail.")
T)))
(T (replace (STATE PASSWORD) of STATE with NIL)
(P.CHUNK " Please re-enter your password. ")
NIL])
(P.SET.USERNAME
[LAMBDA NIL (* edited: "17-Jan-85 13:58")
(PROG (POSSIBLE.NAMES NAME)
(SETQ POSSIBLE.NAMES (FIND.CODE NAME.TREE (fetch (STATE INPUTINFO COMMAND) of STATE)))
(COND
(POSSIBLE.NAMES [COND
((EQ (LENGTH POSSIBLE.NAMES)
1)
(SETQ NAME (CAR POSSIBLE.NAMES)))
(T
(* * The touchtone sequence is ambiguous ie. the touchtones represent more than on user name.
For now we will return the first one.)
(P.CHUNK
"Sorry, the touchtones you entered represent more than one name. You could be: ")
(for NAME in POSSIBLE.NAMES do (P.CHUNK (CONCAT " " NAME " ")))
(P.CHUNK " Assuming you are " (CAR POSSIBLE.NAMES))
(SETQ NAME (CAR POSSIBLE.NAMES]
(printout MAILREADERLOGFILE "User: " NAME T)
(replace (STATE USERINFO USER) of STATE with NAME)
(P.CHUNK (CONCAT " User " (L-CASE NAME T)
", Please enter your password.")))
(T (P.CHUNK " Please re-enter your name. ")
(P.CONTROLLER.RESET])
(P.USER.INIT
[LAMBDA (USER) (* pkh: "30-Jan-85 14:31")
(* * comment)
(COND
((EQ USER HALVORSEN)
(SETQ P.HELP.FLG NIL])
(P.DECIPHER.TOUCHTONES
[LAMBDA (TOUCHTONES) (* BBB " 9-Jan-85 09:26")
(* * This function takes an TOUCHTONES, a list of numbers representing the keys that the user has entered, and
decodes them with the following rules.)
(* * entering a key enters the first letter on the key)
(* * 0 followed by a key enters the second letter on the key)
(* * 1 followed by a key enters the third letter on the key)
(* * 0 followed by a key enters the number on that key)
(* * 0 1 enters Q)
(* * 11 enters Z)
(* * 10 rubouts the last encoded character)
(PROG (LETTER.LIST TOUCHTONE.STATE)
(SETQ TOUCHTONE.STATE (QUOTE SIMPLE))
(RETURN (for TONE in TOUCHTONES
do (SELECTQ TOUCHTONE.STATE
(SIMPLE (SELECTQ TONE
(0 (SETQ TOUCHTONE.STATE (QUOTE ZERO)))
(1 (SETQ TOUCHTONE.STATE (QUOTE ONE)))
[(2 3 4 5 6 7 8 9)
(push LETTER.LIST (CAR (NTH (ASSOC TONE
P.TOUCHTONE.LIST)
2]
(SHOULDNT)))
(ZERO (SELECTQ TONE
(0 (SETQ TOUCHTONE.STATE (QUOTE ZEROZERO)))
(1 (push LETTER.LIST (QUOTE Q))
(SETQ TOUCHTONE.STATE (QUOTE SIMPLE)))
((2 3 4 5 6 7 8 9)
(push LETTER.LIST (CAR (NTH (ASSOC TONE
P.TOUCHTONE.LIST)
3)))
(SETQ TOUCHTONE.STATE (QUOTE SIMPLE)))
(SHOULDNT)))
(ZEROZERO (SELECTQ TONE
((0 1 2 3 4 5 6 7 8 9)
(push LETTER.LIST TONE)
(SETQ TOUCHTONE.STATE (QUOTE SIMPLE)))
(SHOULDNT)))
(ONE (SELECTQ TONE
[0 (COND
(LETTER.LIST (SETQ LETTER.LIST (CDR LETTER.LIST]
(1 (push LETTER.LIST (QUOTE Z)))
[(2 3 4 5 6 7 8 9)
(push LETTER.LIST (CAR (NTH (ASSOC TONE
P.TOUCHTONE.LIST)
4]
(SHOULDNT))
(SETQ TOUCHTONE.STATE (QUOTE SIMPLE)))
(SHOULDNT))
finally (COND
[(EQ TOUCHTONE.STATE (QUOTE SIMPLE))
(RETURN (PACK (REVERSE LETTER.LIST]
(T (P.INVALID.TOUCHTONES TOUCHTONE.STATE])
(P.INVALID.TOUCHTONES
[LAMBDA (TOUCHTONE.STATE) (* BBB " 9-Jan-85 09:25")
(SELECTQ TOUCHTONE.STATE
(ZERO (P.CHUNK "Zero "))
(ONE (P.CHUNK "One "))
(ZEROZERO (P.CHUNK "Zero Zero "))
(SHOULDNT))
(P.CHUNK "with nothing following is invalid."])
(P.CONTROLLER.RESET
[LAMBDA (DONTTOUCH) (* pkh: " 4-Jan-85 12:31")
(* Initializes the variables which control the behavior
of P.CONTROLLER)
(COND
[DONTTOUCH (for X in (RECORDFIELDNAMES (QUOTE STATE)) unless (MEMBER X DONTTOUCH)
do (EVAL (BQUOTE (REPLACE (STATE , X) of STATE with NIL]
(T (LAFITECLEARCACHE)
(SETQ STATE (create STATE using NIL PROSESETTINGS ← PROSE.DEFAULT.SETTINGS)
(SETQ PROSESETTINGS PROSE.DEFAULT.SETTINGS))
(replace (STATE PROCESS) of STATE with \PROSE.PROCESS)
(replace (STATE TONEPROCESS) of STATE with \TONE.MONITOR.PROCESS)
(replace (STATE OPERATORPROCESS) of STATE with \PROSE.OPERATOR.PROCESS)
(* Make sure the PROCESS field is bound to the Prose
process)
(SETQ \LAFITE.LAST.STATUS NIL)
(SETQ LAFITEDEFAULTHOST&DIR)
(SETQ ALL.NUMERIC.PASSWORD NIL])
)
(PUTPROPS PROSE-CONTROLLER COPYRIGHT ("Xerox Corporation" 1984 1985))
(DECLARE: DONTCOPY
(FILEMAP (NIL (1038 15414 (P.CONTROLLER 1048 . 8038) (P.SET.PASSWORD 8040 . 10048) (P.SET.USERNAME
10050 . 11258) (P.USER.INIT 11260 . 11472) (P.DECIPHER.TOUCHTONES 11474 . 13918) (P.INVALID.TOUCHTONES
13920 . 14263) (P.CONTROLLER.RESET 14265 . 15412)))))
STOP