/***************************************************************************/
/*                                                                          */
/*  int GetUOptions(void)                                                   */
/*                                                                          */
/*  Purpose:        Provide a functional portion of the operator interface  */
/*                                                                          */
/*  Calls:          void OptNoOfMode(unsigned long)                         */
/*                  all of the Mode functions via ubranch[]                 */
/*                                                                          */
/*  Inputs:         extern int mode flags                                   */
/*  Outputs:        none.                                                   */
/*                                                                          */
/*  Dependencies:   The programmer will have to go over this function when  */
/*                  new user options are added to the code and make sure    */
/*                  that all of the special cases of processing required by */
/*                  the new option will be followed.                        */
/*                                                                          */
/*  Err Conditions: none.                                                   */
/*                                                                          */
/*  Notes:          This function gets control when the user asks for the   */
/*                  options key and attempts to set or clear an option.     */
/*                                                                          */
/*                  To the programmer: code that needs to be updated when   */
/*                  new Options are written is or should be, marked with    */
/*                  outdented comments.                                     */
/*                                                                          */
/*                                                                          */
/*  History:        09/15/94 - JSS: Initial version.                        */
/*                  09/23/94 - JSS: Adjust wait time for opt code name      */
/*                  10/03/94 _ JSS: Add code to quit option mode            */
/*                  10/03/94 - JSS: Allow option code of 0                  */
/*                  10/04/94 - JSS: Allow OPTION and CLEAR keys during      */
/*                                  input.                                  */
/*                  10/12/94 - JSS: Revise call to enter_param              */
/*                  10/13/94 - JSS: Rename Wdat to UBranch                  */
/*                  10/14/94 - JSS: Replace reading loop with ReadCode      */
/*                  11/17/94 - JSS: Rename D_SET_OPT1 to D_SET_MSG          */
/*                  12/28/94 - JSS: Don't restore first keycode to mailbox  */
/*                  12/28/94 - JSS: Don't display mode msg for KeyLock      */
/*                  01/12/95 - JSS: When returning to RUN mode, first       */
/*                                  enter RunDisplay                        */
/*                  01/12/95 - JSS: Test for infusion complete while user   */
/*                                  was entering an option code             */
/*                  01/29/95 - JSS: Implement Vers 2 of Trans Diag          */
/*                  02/03/95 - JSS: Revise name and call of enter_param     */
/*                  02/06/95 - JSS: Force user to terminate option-code     */
/*                                  entry eith ENTER-key                    */
/*                  02/08/95 - JSS: Re-arrange code to use switch instead   */
/*                                  of repetitive if-else statements        */
/*                  03/09/95 - JSS: Restore keycode input after option      */
/*                                  search only when not opt 5              */
/*                  03/09/95 - JSS: Fix detection of numeric keys to        */
/*                                  eliminate total, stop etc.              */
/*                  03/22/95 - JSS: Display option name once only           */
/*                  03/24/95 - JSS: Log all CONTROL codes                   */
/*                  03/31/95 - JSS: Clear KeyCode before returning          */
/*                  05/24/95 - JSS: Handle a C_RUN while awaiting a key     */
/*                  05/24/95 - LSO: Removed alarm if undesired msg rcvd     */
/*                  05/31/95 - LSO: Bad Option message only blink once,     */
/*                                  changed all Mxx_MSG codes to D_Mxx_MSG  */
/*                  06/16/95 - JSS: Accept CONTROL code as return from      */
/*                                  option function and handle the code     */
/*                                  appropriately                           */
/*                  07/12/95 - LSO: Use Opt Err for unknown opt number for  */
/*                                  consistency with BioMed Options         */
/*                  08/29/95 - JSS: Fix option so that keyboardlock won't   */
/*                                  let user stop the pump                  */
/*                  08/30/95 - JSS: If user quits option mode with a        */
/*                                  keystroke, preserve it for ensuing code */
/*                  09/13/95 - JSS: Remove code to display option name      */
/*                                  before entering the specific option-    */
/*                                  processing module. Ignore OPTIONS key,  */
/*                                  Ignore CLEAR key before deciding what   */
/*                                  option was requested.                   */
/*                  09/22/95 - J W: CLEAR key exits from typing in an Opt   */
/*                                  number without showing OPT ERR          */
/*                  09/26/95 - J W: Options processing now displays KEY     */
/*                                  LOCK if entry is attempted in this      */
/*                                  condition.                              */
/*                  09/27/95 - J W: Allow entry to option in Keylock if it  */
/*                                  is an option mode.                      */
/*                  10/13/95 - J W: Add the push enter block that I wrote   */
/*                                  yesterday. Moved from beginning of all  */
/*                                  options (except simple options).        */
/*                                  Add EPRet, EnterParam return code local */
/*                                  to GetUOptions. Add alarm handling,     */
/*                                  change if-then-else to switch           */
/*                  10/25/95 - J W: Made many changes to accomodate correct */
/*                                  alarm handling                          */
/*                  10/26/95 - J W: Push the RUN key back in Ctrl Mailbox   */
/*                                  so that RUN will start the pump right   */
/*                                  away.                                   */
/*                                  Clear key erases option no in progress  */
/*                                  and lets you set something              */
/*                  10/27/95 - LSO: Changed OutLog to OUTLOG to follow      */
/*                                  naming conventions                      */
/*                  10/27/95 - J W: #if-out pump stop at options access.    */
/*                  10/27/95 - J W: Display KEY  LOCK before going into an  */
/*                                  option, if it is found.                 */
/*                                  Clear clears Opt Code if less than 2    */
/*                                  digits or if Opt Code is invalid, other */
/*                                  -wise it gets sent on into the option   */
/*                  10/30/95 - J W: Removed #if-ed out block that would     */
/*                                  stop the Pump upon accessing an Option. */
/*                                  Stop the user from accessing an Option  */
/*                                  if there is a pre-existing alarm        */
/*                                  condition.                              */
/*                  10/31/95 - J W: Allow access to the option if the alarm */
/*                                  msgdata is A_CLEAR.                     */
/*                  11/07/95 - J W: Allow access to the Keylock option      */
/*                                  during alarm status and add the         */
/*                                  concepts of Pending Alarm, OldKeyCode   */
/*                                  and OldMsg Data.                        */
/*                  11/09/95 - J W: Comment-in the UBranch indices for easy */
/*                                  reference.                              */
/*                  11/29/95 - J W: Don't go to Running after option access */
/*                                  following a non-key message if not      */
/*                                  already running.                        */
/*                  11/30/95 - J W: Remove specific cases that all fall     */
/*                                  into default anyway in IGNORE after     */
/*                                  return from option.                     */
/*                                  Add power-off to else (IGNORE) else     */
/*                                  (KeyCode not stuffed).                  */
/*                  01/16/96 - J W: Move UBranch table to rtxcmain.c and    */
/*                                  make it a global, ubranch, and a const. */
/*                  01/17/96 - J W: Make the pump respond properly during   */
/*                                  the OPT nn / PUSH ENTR prompt if the    */
/*                                  roller clamp is removed or some other   */
/*                                  non normal condition occurs while the   */
/*                                  pump is stopped.                        */
/*                  01/18/96 - J W: Add response to non-normal condition    */
/*                                  when in the middle of typing in an      */
/*                                  option number, in the top level switch  */
/*                                  after EnterParam.                       */
/*                  01/24/96 - J W: Go straight to RequestValues if there   */
/*                                  is a parameter needed as signaled by    */
/*                                  parmflag.                               */
/*                  02/07/96 - J W: Allow user to push options to set some  */
/*                                  other code if he doesn't want the one   */
/*                                  shown.                                  */
/*                  03/06/96 - J W: Utilize the new STUFFMSG macro          */
/*                  03/12/96 - J W: Respond to RATE and VOLUME key presses  */
/*                                  to enter dose mode. Call it review if   */
/*                                  everything set when entering an option  */
/*                                  mode.                                   */
/*                  03/13/96 - J W: Allow user in to view Dose Mode and     */
/*                                  Autoprogram Mode if in Keylock.         */
/*                  03/15/96 - J W: Make clearing of REVIEW after call to   */
/*                                  option mode consistent.                 */
/*                  03/15/96 - J W: Allow user in to view the alarm tone if */
/*                                  in Keylock                              */
/*                  03/25/96 - J W: Fix bug in the push enter block at the  */
/*                                  entrance to an option mode in which, if */
/*                                  off is not OK, the pump sticks in an    */
/*                                  infinite loop. Also make the loop stay  */
/*                                  in PUSH ENTR if invalid input occurs,   */
/*                                  rather than exiting.                    */
/*                  03/25/96 - J W: Remove the fix to make the loop stay in */
/*                                  PUSH ENTR because it was done with a    */
/*                                  goto.                                   */
/*                  04/17/96 - J W: Fix bug in which the pump stays in an   */
/*                                  infinite loop if RATE is pressed while  */
/*                                  prompting PUSH ENTR to access the       */
/*                                  option.                                 */
/*                  04/24/96 - J W: Go to CheckTube() after returning from  */
/*                                  the option. This fixes bugs in which    */
/*                                  accessing options during set loading    */
/*                                  causes an exit from the loading condit- */
/*                                  -ion, during "PUSH LOAD", fix codes,    */
/*                                  which get ignored after options are     */
/*                                  accessed, and during "LOAD CLMP", and   */
/*                                  probably others.                        */
/*                  04/25/96 - J W: Move setting of Review condition        */
/*                                  internally to Dose Mode if all set,     */
/*                              since it has its own internal PUSH ENTR */
/*                                  prompt.                                 */
/*                                  Option Modes must be disallowed if      */
/*                                  there is a fix code. Still do utility   */
/*                                  options and BioMed options.             */
/*                  05/02/96 - J W: Add comment about maintaining perror    */
/*                                  for accessing Factory Options during    */
/*                                  FIX conditions.                         */
/*                                  Only set Review condition if all set if */
/*                                  going to that Option Mode -- fixes      */
/*                                  problem of ignoring ENTER to Dose Mode  */
/*                                  if other option mode set up first.      */
/*                  05/03/96 - J W: Add catch-all to PUSH ENTR switch,      */
/*                                  prompted by Charlie's discovery that    */
/*                                  unplugging the flow sensor while at the */
/*                                  OPT 21 / PIG MODE / PUSH ENTR prompt    */
/*                                  locked up the pump. Added all cases     */
/*                                  that go to ReadytoRun or Running to it  */
/*                                  to save code space. Also add default to */
/*                                  the exit from getting the option number */
/*                  05/13/96 - J W: Make Option 99, CLR ALL, go through the */
/*                                  PUSH ENTR prompt.                       */
/*                  05/17/96 - LSO: Added support for History Log           */
/*                  05/24/96 - J W: Allow view of Set DS Occl Pressure if   */
/*                                  in Keylock. Let Clear All proceed to    */
/*                                  the function for Keylock display.       */
/*                  07/18/96 - J W: Add two option number in one function   */
/*                                  ability, for Manual Program Mode.       */
/*                  08/01/96 - J W: Add (more) support for the Manual       */
/*                                  Program Mode, by adding cases to handle */
/*                                  it where the option modes are special-  */
/*                                  cased. Add optionspressedinsetup        */
/*                                  to allow reentry to the previously      */
/*                                  selected option mode. This allows the   */
/*                                  user to press OPTIONS while in setup    */
/*                                  and bring up the option no.             */
/*                  08/02/96 - J W: Continue to ensure that the manual      */
/*                                  program mode is added to all special    */
/*                                  cases where necessary. Make sure that   */
/*                                  the new Option 12, Return to Primary    */
/*                                  Mode, is also handled where necessary.  */
/*                                  Send option.value to the history log,   */
/*                                  not the Dum_opt_no, because the former  */
/*                                  is the specific one.                    */
/*                  08/07/96 - J W: Remove the "PUSH ENTR" prompt from the  */
/*                                  opt # / mode name display if the pump   */
/*                                  is running.                             */
/*                  08/08/96 - J W: Restore the current mode's option # in  */
/*                                  case of a back-out via pressing OPTIONS */
/*                                  a second time from option 63 or 64, in  */
/*                                  order to review the correct mode when   */
/*                                  ENTER is pressed next.                  */
/*                  08/13/96 - J W: Add more thorough restoration of the    */
/*                                  correct manual program mode option no.  */
/*                                  in case of any exit point for any       */
/*                                  reason.                                 */
/*                  08/15/96 - J W: Add suppport for Option 61, Auto Taper  */
/*                  08/20/96 - J W: Don't stuff a message if it is C_NULL   */
/*                                  when the user option returns with       */
/*                                  IGNORE, when the pump is stopped.       */
/*                                  Modify comments to try to make it clear */
/*                                  that KeyCode is not expected to be      */
/*                                  stuffed when returning IGNORE, and is   */
/*                                  expected to be stuffed when returning   */
/*                                  OK.                                     */
/*                  09/10/96 - J W: Added infusionincomplete = TRUE when    */
/*                                  pump stopped.                           */
/*                  09/10/96 - J W: Add Keylock message and kick-out before */
/*                                  going to BMOs since the general kick -  */
/*                                  out was removed. Delete the #if-ed out  */
/*                                  block that we won't use any more.       */
/*                  09/24/96 - J W: Re-wrote this PUSH ENTR loop so that    */
/*                                  RUN and CLEAR will be rejected in all   */
/*                                  cases except where they are allowed,    */
/*                                  without needing a GOTO.                 */
/*                                  Change to address an Option number by   */
/*                                  its U_MODE_ constant, rather than out   */
/*                                  of the option table, to save a little   */
/*                                  code.                                   */
/*                  09/26/96 - J W: After the new PUSH ENTR loop has been   */
/*                                  satisfied and exited, the ENTER key has */
/*                                  to be cleared or else the user option   */
/*                                  may act on it.                          */
/*                  10/07/96 - J W: Convert value in PARAMs to a pointer to */
/*                                  the value.                              */
/*                  10/15/96 - J W: Add Greg and Kathy's request to auto-   */
/*                                  -matically continue from SET / OPT CODE */
/*                                  and from the PUSH ENTR prompt if the    */
/*                                  pump is running.                        */
/*                  10/26/96 - J W: Put the option number last in the alt-  */
/*                                  -ernation in the PUSH ENTR loop,        */
/*                                  because it was seen first while it was  */
/*                                  in the process of being typed in.       */
/*                  11/14/96 - J W: Comment change only                     */
/*                  11/15/96 - J W: Made Mode07() handle all Dose Modes.    */
/*                  11/21/96 - J W: Now set Review flag for Mode07() here.  */
/*                  11/26/96 - J W: Change to using a function, "Restore    */
/*                                  OptionModeNo()", in utils.c, to restore */
/*                                  the optionvalue of an option mode       */
/*                  11/27/96 - J W: Handle OPTIONS if an Option returns it  */
/*                                  under "IGNORE".                         */
/*                  12/04/96 - J W: Send optionspressedinsetup back around  */
/*                                  into Mode07 in order to do a GoThru     */
/*                                  (qv) from the PUSH ENTR prompt -- have  */
/*                                  to clear optionspressedinsetup          */
/*                                  carefully now, in order to be able to   */
/*                                  get back to SET / OPT CODE.             */
/*                  12/17/96 - LSO: Allow access to BioMed options while in */
/*                                  alarm; minor code optimization          */
/*                  12/17/96 - J W: Don't stuff ENTER key upon returning    */
/*                                  from a Mode function.                   */
/*                  12/19/96 - J W: Save whether the alarm was fast or slow */
/*                                  if PendingAlarm and regenerate the      */
/*                                  sound if not going into BioMed Options  */
/*                                  or Keylock while in an alarm; then      */
/*                                  after processing the option, only       */
/*                                  restore the alarm if Keylock was done.  */
/*                                  Added the explicit return code from the */
/*                                  Option in order to insert the alarm     */
/*                                  restore before exiting.                 */
/*                  12/20/96 - J W: Put in a ClearMode in case a different  */
/*                                  Option Mode from what is current was    */
/*                                  selected, so that if the newly selected */
/*                                  Option is exited, the pump will return  */
/*                                  to the Primary Mode as Kathy agreed.    */
/*                                  Have to put this in when it is definite */
/*                                  that the Option Mode will be called.    */
/*                                  Force optionspressedinsetup for Dose    */
/*                                  Modes, which will in turn clear it and  */
/*                                  set GoThru = TRUE. Changed the Keylock  */
/*                                  display at options entry to not stuff   */
/*                                  the ENTER key in order to allow cancel- */
/*                                  lation of the Keylock display.          */
/*                  12/30/96 - J W: Added clearing of optionspressedinsetup */
/*                                  in case an OPT ERR occurs, due to a bug */
/*                                  in which the optionvalue got smashed    */
/*                                  after OPTIONS was pressed in a non-Dose */
/*                                  Mode Option setup.                      */
/*                  12/31/96 - J W: Cause thorough clearing of options-     */
/*                                  pressedinsetup by clearing it right     */
/*                                  after the last place in which it is     */
/*                                  used.                                   */
/*                  01/02/97 - J W: Better just to not mess up optionvalue  */
/*                                  than to have to go restoring it all     */
/*                                  over the place -- fix bug in which      */
/*                                  pressing OPTIONS while in other Option  */
/*                                  Mode functions than Mode07 Dose Mode    */
/*                                  did not bring up the Option number, but */
/*                                  rather just SET / OPT CODE.             */
/*                  01/03/97 - J W: Continue fixing this bug.               */
/*                  01/04/97 - J W: Continue fixing this bug. Made Pending- */
/*                                  Alarm cover this whole file in order to */
/*                                  let it still be set up reentry to this  */
/*                                  routine, as planned.                    */
/*                  01/05/97 - J W: Fixed bug in which Option 61, Auto      */
/*                                  Taper, was being disallowed and kicking */
/*                                  the user out of Auto Program Mode too.  */
/*                                  Bug got in with additons of 12/20/96    */
/*                                  (see above); added ShowOptNoFirstIn-    */
/*                                  PushEnter to show the Option Number     */
/*                                  first if EnterParam was skipped due to  */
/*                                  optionspressedinsetup.                  */
/*                  01/28/97 - J W: Added the "Custom Program" Mode to the  */
/*                                  Option Number search.                   */
/*                  01/29/97 - J W: Added the setting of the pointer to the */
/*                                  Opt Mode specs for the Cust Prog.       */
/*                  01/31/97 - J W: Added a better explanation of why a     */
/*                                  ClearMode gets done before a new Option */
/*                                  Mode function gets entered.             */
/*                  02/03/97 - J W: Added the display of the Cust Prog Opt  */
/*                                  name.                                   */
/*                  02/04/97 - J W: Set the condition not to show the PUSH  */
/*                                  ENTR prompt for the parameters of the   */
/*                                  Cust Prog, too, if it is selected when  */
/*                                  all set up.                             */
/*                  02/05/97 - LSO: Replaced LONGWAIT/CLKTICK with global   */
/*                                  delaytime to make timeout adjustable    */
/*                  02/06/97 - LSO: Revised WAITCHAR calls to add / CLKTICK */
/*                  02/06/97 - J W: Added an input parameter to             */
/*                                  OptNoOfMode, fixing the bug in which    */
/*                                  reviewing an Auto Program Mode via      */
/*                                  pressing ENTER then pressing OPTIONS,   */
/*                                  then ENTER, then OPTIONS twice and      */
/*                                  clear, causes the pump to be kicked out */
/*                                  of Auto Taper, and back to the first    */
/*                                  step.                                   */
/*                  02/06/97 - J W: Fixed bug in which the PUSH ENTR prompt */
/*                                  presence ("REVIEW") was being set for   */
/*                                  one Auto Prog Mode or Manual Program    */
/*                                  Mode if the other was set.              */
/*                  02/17/97 - J W: Added an input parameter to EnterParam  */
/*                  02/21/97 - J W: Revised to ignore 4 minor power status  */
/*                                  messages during displays in this        */
/*                                  routine.                                */
/*                  03/14/97 - J W: Added the if-else block to implement    */
/*                                  the User Option Disable feature         */
/*                                  controlled by BMO 220, ModeB08 (qv),    */
/*                                  making sure to plan for the future in   */
/*                                  hard-coding in permanent access to BMOs */
/*                  03/17/97 - J W: Added a separate message for "OPT DISA" */
/*                                  so that the message in GetUOptions is   */
/*                                  not dependent upon the title of the     */
/*                                  BMO.                                    */
/*                  04/11/97 - J W: Moved entry to Biomed Options (BMOs) to */
/*                                  go after the PUSH ENTR prompt in order  */
/*                                  to make them look like the rest of the  */
/*                                  options and not be confusing to the     */
/*                                  user who does both. The pump stop       */
/*                                  command and setting of                  */
/*                                  "infusionincomplete" now will only      */
/*                                  get done if the pump is actually        */
/*                                  running when BMOs are successfully      */
/*                                  accessed.   When Factory Options are    */
/*                                  implemented, they will be accessed      */
/*                                  through the same user interface.        */
/*                  04/18/97 - J W: Made the PUSH ENTR prompt come first if */
/*                                  BMOs are selected, so that the user     */
/*                                  will be shown what to do if he          */
/*                                  frustratedly keeps pressing a number    */
/*                                  key, thinking he is in "SET / BIO OPT". */
/*                  04/22/97 - J W: Revised to give the user up to one sec  */
/*                                  after typing in a user option number    */
/*                                  to press CLEAR and return to the SET    */
/*                                  OPT CODE prompt.                        */
/*                  04/24/97 - J W: Prevented the user option number for    */
/*                                  access to BMOs (still 89 at this time)  */
/*                                  from being History-logged.              */
/*                  04/24/97 - J W: Took the semaphore out of the KS_send   */
/*                                  for the case in which a normal system   */
/*                                  message is being sent to the CONTROL    */
/*                                  mailbox, replaced it with a null sema,  */
/*                                  and signalled the CTRLSEMA separately,  */
/*                                  using a KS_signal, as it appears that   */
/*                                  there is a bug in RTXC, in which a      */
/*                                  signalled semaphore is not being picked */
/*                                  up by a KS_waitm (which I am doing in   */
/*                                  WaitMsg) if it was done as part of a    */
/*                                  KS_send.                                */
/*                  04/25/97 - J W: New format for DelayMsg; new version of */
/*                                  WaitMsg.                                */
/*                  05/06/97 - J W: Revised handling of Return Code from    */
/*                                  EnterParam; prevent automatic entry to  */
/*                                  BMOs when the pump is running.          */
/*                  06/03/97 - J W: Fix bug in which the BMO number (89) is */
/*                                  scribbling over the Option Mode number  */
/*                                  being displayed for the user.           */
/*                  06/05/97 - J W: Reduced the blinkon time to speed up    */
/*                                  alternations while keeping certain      */
/*                                  single pause times constant.            */
/*                  06/24/97 - LSO: Added useful comment.                   */
/*                  07/03/97 - J W: Revised to ignore the ENTER key upon    */
/*                                  exit in order to prevent unwanted       */
/*                                  Titration incomplete alarms if running  */
/*                                  in a Dose Mode.                         */
/*                  07/17/97 - J W: Reversed my change of April 22 in order */
/*                                  to make the CLEAR key press apply to    */
/*                                  the Option Mode entered as soon as it   */
/*                                  is pressed following the entry of two   */
/*                                  digits for the Option Mode.             */
/*                  07/22/97 - J W: Added useful comment.                   */
/*                  07/23/97 - J W: Added the support for doing two         */
/*                                  Options, 70 and 71, in one Mode         */
/*                                  function necessary to allow CLEAR       */
/*                                  operation from the OPT # / <mode name>  */
/*                                  / PUSH ENTR prompt.                     */
/*                  07/28/97 - J W: ...and added the resulting support      */
/*                                  necessary to show the distinguishing    */
/*                                  <mode name>.                            */
/*                  07/31/97 - J W: Added support for the special process-  */
/*                                  ing required by the new Options for DS  */
/*                                  pressure display: the respective mode   */
/*                                  functions should not be gone into if    */
/*                                  the pump is running; added note under   */
/*                                  dependencies in this function header    */
/*                                  block.                                  */
/*                  07/29/97 - J W: Added support for controlling whether   */
/*                                  or not EnterParam will give the user    */
/*                                  inactivity time-out alarm; added use of */
/*                                  NOTOKZEROES.                            */
/*                  07/29/97 - J W: Added support for controlling whether   */
/*                                  or not ReadCode will give the user      */
/*                                  inactivity time-out alarm.              */
/*                  08/09/97 - J W: Revised input spec of ReadCode.         */
/*                  08/26/97 - J W: Added support for Mode31, Delayed Start */
/*                  09/30/97 - J W: Added support for Mode03, Piggyback     */
/*                                  Time and Volume Mode.                   */
/*                  10/02/97 - J W: Added setting of pointer properly when  */
/*                                  accessing Piggyback Modes.              */
/*                  10/29/97 - J W: #if-ed out the access to the Delayed    */
/*                                  Run Mode function if CLEAR is pressed   */
/*                                  at its PUSH ENTR prompt. Delayed Run    */
/*                                  will not go in until after ver 3.22.    */
/*                  10/30/97 - J W: Added a reaction if NOSUCHOPTION in     */
/*                                  OptModeDisaEna. This will catch fall-   */
/*                                  throughs from the main Opt Code search  */
/*                                  (which fall-throughs should not be      */
/*                                  happening).                             */
/*                  12/05/97 - J W: Restored, added and adjusted support    */
/*                                  for Delayed Run.                        */
/*                  12/12/97 - J W: Disabled the CLEAR key if at the OPT 61 */
/*                                  / AUTO TAPR / PUSH ENTR prompt. Revised */
/*                                  clearing if going into a different Opt  */
/*                                  Mode to be compatible with Delayed      */
/*                                  Start.                                  */
/*                  12/16/97 - J W: Added the ability to access Keylock if  */
/*                                  in the non-running Delayed Start.       */
/*                  12/30/97 - J W: Revised to clear the Delayed Start Mode */
/*                                  if in Delayed End and going into a      */
/*                                  different main mode.                    */
/*                  01/13/98 - J W: Fixed bugs in which the Review          */
/*                                  statusflag wasn't getting set if going  */
/*                                  back into Auto Taper while in Delayed   */
/*                                  Run (End only, of course) and in which  */
/*                                  Delayed End wasn't being cleared if     */
/*                                  going from Delayed End with a Primary   */
/*                                  Mode to an Option Mode.                 */
/*                  01/29/98 - J W: Revised to use separate Delayed Start   */
/*                                  and Delayed End modeflags.              */
/*                  04/16/98 - CMA: Revised to handle proper mode clearing  */
/*                                  when in Time mode and entering a Piggy- */
/*                                  back mode and vice-versa.               */
/*                  05/18/98 - J W: Added detection of modules that are in  */
/*                                  the upper two megs, and revised to show */
/*                                  OPT N/A if one such is selected when a  */
/*                                  two meg PROM is in use.                 */
/*                  07/02/98 - EJL: Added support for PCA mg and ml modes.  */
/*                  07/21/98 - CMA: Revised to implement the SIGNAL method  */
/*                                  of calling PowerOff instead of being a  */
/*                                  direct function call.                   */
/*                  08/28/98 - CMA: Merged V3.25-V3.28 code back into the   */
/*                                  main path of development.               */
/*                  10/15/98 - CMA: Revised to reinstate Primary Time mode  */
/*                                  as its own entity, rather than its      */
/*                                  former Dose Mode foundation.            */
/*                  12/02/98 - J W: Added support for both PCA modes being  */
/*                                  entered via the same function, Mode21.  */
/*                                  Added code to keep PCA Mode and Delayed */
/*                                  Run separate. Revised setting of        */
/*                                  optiougot to save a little code.        */
/*                  12/03/98 - J W: Added a comment.                        */
/*                  12/08/98 - J W: Fixed relationship of U_MODE_21 to PCA  */
/*                                  MG mode and 26 to ML mode.              */
/*                  01/27/99 - J W: Revised comments in REVIEW statusflag   */
/*                                  setting for more clarity.               */
/*                  02/23/99 - J W: Revised exiting of Option Modes when    */
/*                                  accessing a different Option Mode to    */
/*                                  clear all PCA Params and PCA History    */
/*                                  Log data when it is a PCA Mode that is  */
/*                                  being exited.                           */
/*                  02/24/99 - CMA: Renamed the function that clears the    */
/*                                  PCA history log.                        */
/*                                  Added missing () on the function call   */
/*                                  of the previous entry.                  */
/*                  03/04/99 - J W: Removed clearing of PCA Modes when      */
/*                                  changing Option Modes to exit a PCA     */
/*                                  Mode, because other Option Modes are    */
/*                                  disallowed when in a PCA Mode.          */
/*                  03/11/99 - J W: Added said disallowing of other Option  */
/*                                  Modes while in a PCA Mode.              */
/*                  03/15/99 - J W: Revised this disallowing (saw mistakes) */
/*                  03/16/99 - J W: Removed code that exits PCA Mode if     */
/*                                  going into Delayed Run Mode, because    */
/*                                  this is now disallowed; added display   */
/*                                  of "EXIT PCA / TO SET / OPT CODE" if an */
/*                                  Option Mode is disallowed while in PCA  */
/*                                  Mode.                                   */
/*                  05/18/99 - J W: Removed CLEAR from the if statement     */
/*                                  that gives access to the Option Mode    */
/*                                  selected in the case of Options 82 and  */
/*                                  83.                                     */
/*                  05/19/99 - J W: Revised not to show KEY LOCK if in it   */
/*                                  when accessing Mode27 (Opt 83) - Clear  */
/*                                  PCA Mode.                               */
/*                  05/20/99 - J W: Revised not to show KEY LOCK when       */
/*                                  accessing Mode28 (Opt 82), because it   */
/*                                  is for information purposes only, with  */
/*                                  no prompts for the user to change       */
/*                                  anything.                               */
/*                  05/28/99 - J W: Revised to turn optionspressedinsetup   */
/*                                  back on for PCA Modes, in additon to    */
/*                                  Dose Modes, so that the set parameters  */
/*                                  will only be skipped when the Mode      */
/*                                  function is called from RequestValues.  */
/*                  05/31/99 - J W: Removed block that sets optionspressed- */
/*                                  insetup in case of Dose or PCA Modes,   */
/*                                  because optionugot should be used in    */
/*                                  Mode07 or Mode21.                       */
/*                  06/07/99 - J W: Revised to use optionspressedinsetup    */
/*                                  via a new LocalOptionsPressedInSetup in */
/*                                  PCA Mode (actually, when the            */
/*                                  appropriate Option Numbers have been    */
/*                                  entered).                               */
/*                                                                          */
/***************************************************************************/

int GetUOptions(void)
{
    /* VARIABLES:                                                           */

    static MSG CtrlMsg;                 /* Main ctrl mbox msg element       */
    static  HLE_MSG HistMsg;            /* Message for History Log Entry    */
    int EPRet;                          /* Return code from EnterParam      */
    int Index;                          /* General-Purpose integer          */
    int RC;                             /* Return code from the Option      */

    byte Key;                           /* Value of code from ReadCode      */
    long Dum_opt_no;                    /* Search dummy in for loop         */
    char ADoseModeOptCode;              /* Whether A DM Opt Code was set    */

    char ShowOptNoFirstInPushEnter;     /* If optionspressedinsetup         */
    /* The three message codes to display at the OPT # / <mode name> / PUSH */
    /* ENTR prompt                                                          */
    int PushEntrPromptMsgs[3];
    int J, K;                           /* Handy loop counters in array     */

    int OurMsgs[2] = {                  /* For ReadCode to display          */
                      D_SET_MSG,
                      D_SET_OPT2
                     };

    /* Tell EnterParam not to beep if in Delayed Start                      */
    byte Beeps;
    /* Blow out of EnterParam if in Delayed Start                           */
    byte EnterParamWait;

    /* Save in case OPTIONS pressed in PCA Mode.                            */
    int LocalOptionsPressedInSetup = FALSE;


    /* CODE:                                                                */

    HistMsg.msgtype = OPTIONVAL_TYPE;   /* Set history log message type     */

    enteredoptparvalue = 0;             /* Always going to be setting it    */

    if (optionspressedinsetup)
    {
        /* Use the internal opt no from the Mode function just left         */
        enteredoptparvalue = localoptno;

        KeyCode = C_NULL;               /* OPTIONS has done its job         */
        ShowOptNoFirstInPushEnter = TRUE;

        if (
            (
             (localoptno == U_MODE_21)
             ||
             (localoptno == U_MODE_26)
            )
            &&
            (optionspressedinsetup)
           )
        {                               /* Need it for PCA Mode             */
            LocalOptionsPressedInSetup = TRUE;
            /* Use local to lose condition if Mode21 not entered            */
            /* successfully                                                 */
        }

        /* Use LocalOptionsPressedInSetup for Opts 80 and 81.               */
        optionspressedinsetup = FALSE;  /* and so has optionspressedinsetup */
                                        /*  (done its job - for now)        */
    }
    else /* The user will type in the enteredoptparvalue; he had not        */
         /* pressed OPTIONS while in an Option Mode setup function.         */
    {
        /* Display detail to make sure that the option name comes up as     */
        /* fast as possible after the user enters the number:               */
        ShowOptNoFirstInPushEnter = FALSE;

        /* KeyCode is not disturbed by any looping below before EnterParam  */

        if (!PendingAlarm)
        /* This processing has already been done if there was a loop-around */
        /* Don't allow access to options if there is a pre-existing         */
        /* condition. Must however allow access to Keylock. This            */
        /* complicates matters.                                             */
        {
            if (
                (statusflag & ALARM)
                &&
                (alm_msg.msgdata != A_WANT_KEY)
                &&
                (alm_msg.msgdata != A_CLEAR)
                /* This signifies that Want key was cleared.                */
               )
            {
                /* Remember that we were in the middle of an alarm:         */
                /* (These three codes are all TRUE, ie not 0 [FALSE])       */
                if (fastactive)
                    PendingAlarm = FASTACTIVE;
                else if (slowactive)
                    PendingAlarm = SLOWACTIVE;
                else
                    PendingAlarm = ALARMACTIVE;

                OldKeyCode = KeyCode;
                OldMsgData = alm_msg.msgdata;
            }                           /* Save all reasons for next time   */
            else
            {                           /* Alarm is on if previous code was */
                ALARM_OFF;              /*   not fielded in the switch.     */
                OldKeyCode = C_NULL;
            }
        /* Must also clear PendingAlarm and OldKeyCode if a new alarm pops  */
        /* up during keypress activity. New alarm code must then be sent by */
        /* the system. Options access must then be freely allowed until     */
        /* then.                                                            */
        }

        CtrlMsg.msgtype = CTL_MSG;      /* Set up for possible message      */

        ALTERNATE(2);                   /* Display "SET/OPT CODE"           */
        SHOWMSG(D_SET_MSG);
        SHOWMSG(D_SET_OPT2);

        if (
            (statusflag & PUMPRUN)
            ||
            (indelayfornokvo)
           )
        {
                                        /* Wait for only twelve seconds     */
            WaitMsg((unsigned long)(TWELVESECALTS*BLINKON-ALTREDUC)/CLKTICK,
                                                               4, ignorekeys);
            Key = (byte)KeyCode;
        }
        else
        {                               /* Force user to enter any key      */
            Key = ReadCode(OurMsgs, 2, C_NULL, BEEPS);
        }

        switch(Key)
        {
        case C_OPTIONS:                 /* If user hit OPTIONS key again    */
            SIGNAL(GETUOPTIONS);        /*   re-enter this routine again    */
            break;

        case C_CLEAR:                   /* If user pressed the CLEAR key    */
                                        /*   and pump is running            */
            if (statusflag & PUMPRUN)
            {
                SIGNAL(RUNDISPLAY);     /* Return to running                */
            }
            else                        /* Not running                      */
            {
                SIGNAL(CHECKTUBE);      /* Don't allow option               */
            }
            break;

                                        /* This could be powermon trying to */
                                        /*   stop the pump because of a     */
        case C_RUN:                     /*   Dead Battery situation    OR   */
                                        /*   it could be the user trying to */
                                        /*   either start or stop the pump  */
            if (statusflag & PUMPRUN)   /* If pump is running               */
            {
                if ( !(statusflag & KEYBDLOCK) )
                {
                    /* If keyboard isn't locked, stop it immediately        */
                    KS_signal(STOPSEMA);
                    infusionincomplete = TRUE;
                    PendingAlarm = FALSE;
                    OldKeyCode = C_NULL;
                }
                else
                {
                    DelayMsg(D_KBLOCK, ONESEC, DLYMSG_IGMKS);
                }                       /* Tell the user; No keying         */
                SIGNAL(GETUOPTIONS);    /*   but stay in option mode        */
            }
            else                        /* If pump is not running           */
            {                           /* Restore the code to CONTROL      */
                /* If in the Delayed Run non-running delay, this will cause */
                /* the pump to exit the delay.                              */
                CtrlMsg.msgdata = C_RUN;
                OUTLOG(C_RUN);          /* Log the message                  */
                KS_send(CONTROL, &CtrlMsg.msghdr, (PRIORITY)1, (SEMA)0);
                KS_signal(CTRLSEMA);    /* Patch RTXC bug for WaitMsg()     */

                KeyCode = C_NULL;       /* Clear previous keycode           */
                PendingAlarm = FALSE;
                OldKeyCode = C_NULL;
                SIGNAL(READYTORUN);     /*   go see what to do              */
            }
            break;

        case C_POWEROFF:                /* Abort now                        */
            if (                        /* If power-off is acceptable now   */
                (!indelayfornokvo)
                &&
                (OffIsOk())
               )
            {
                PendingAlarm = FALSE;
                OldKeyCode = C_NULL;
                SIGNAL(POWEROFF);       /*   go do it now!                  */
            }
            SIGNAL(GETUOPTIONS);        /* Otherwise, re-enter this routine */
            break;

        case C_INFCOMP:                 /* If an infusion completed         */
            PendingAlarm = FALSE;
            OldKeyCode = C_NULL;
            SIGNAL(INFSCHED);           /*   go see what to do next         */
            break;

        case C_RCREM:                   /* Someone removed the Roller Clamp */
        case C_RCCLOSE:                 /* Somebody shut the Roller Clamp   */
        case C_RCBETWEEN:               /* Somebody moved the R.C. slightly */
        case C_RCERROR:                 /* Roller Clamp has a problem       */
            PendingAlarm = FALSE;
            OldKeyCode = C_NULL;
            if (statusflag & PUMPRUN)   /* If the pump is running           */
            {                           /* Restore the code to the mailbox  */
                CtrlMsg.msgdata = Key;  /* Simulate the code                */
                OUTLOG(Key);            /* Log the message                  */
                KS_send(CONTROL, &CtrlMsg.msghdr, (PRIORITY)1, (SEMA)0);
                KS_signal(CTRLSEMA);    /* Patch RTXC bug for WaitMsg()     */

                KeyCode = C_NULL;       /* Clear previous keycode           */
                SIGNAL(RUNNING);        /*   go see what to do              */
            }
            else
            {
                SIGNAL(CHECKTUBE);      /* If not running, unload the set   */
            }
            break;

        case C_USAIR:                   /* An air bubble appeared upstream  */
        case C_USOCCL:                  /* An occlusion appeared upstream   */
        case C_DSOCCL:                  /* An occlusion appeared downstream */
            if (statusflag & PUMPRUN)   /* If the pump is running           */
            {                           /* Restore the code to the mailbox  */
                PendingAlarm = FALSE;
                OldKeyCode = C_NULL;
                CtrlMsg.msgdata = Key;  /* Simulate the code                */
                OUTLOG(Key);            /* Log the message                  */
                KS_send(CONTROL, &CtrlMsg.msghdr, (PRIORITY)1, (SEMA)0);
                KS_signal(CTRLSEMA);    /* Patch RTXC bug for WaitMsg()     */

                KeyCode = C_NULL;       /* Clear previous keycode           */
                SIGNAL(RUNNING);        /*   go see what to do              */
            }
            SIGNAL(GETUOPTIONS);        /* Otherwise, re-enter this routine */
            break;

        case C_0:                       /* If user typed a numeric          */
        case C_1:
        case C_2:
        case C_3:
        case C_4:
        case C_5:
        case C_6:
        case C_7:
        case C_8:
        case C_9:
            break;                      /* Go get the rest of the code      */

        case C_NULL:
            if (statusflag & PUMPRUN)   /* User wasn't interested           */
            {
                SIGNAL(RUNDISPLAY);     /* Go update the running display    */
            }
            if (indelayfornokvo)
            {
                SIGNAL(READYTORUN);     /* Go back to the delay loop        */
            }
            break;
            /* Fall through to the next case if the pump is stopped...      */
        default:
            SIGNAL(GETUOPTIONS);        /* And, re-enter this routine       */
            break;
        }

        /* Get rest of the option code; don't wait if in Delayed Start      */
        if (indelayfornokvo)
        {
            Beeps = NOBEEPS;            /* Don't beep if "running"          */
            EnterParamWait = GET_TIMEOUT;
        }
        else
        {
            Beeps = BEEPS;
            EnterParamWait = GET_ENTER;
        }

        EPRet = EnterParam(Key, &enteredoptpar, NOTOKZEROES, EnterParamWait,
                                                                       Beeps);

        enteredoptparvalue /= 10;       /* EnterParam multiplies * 10       */
                                        /* case blocks will use KeyCode     */
        if (EPRet != OK)                /* If user mis-entered code         */
        {
            ALARM_ON(A_OPT_ERR);        /* Sound the alarm                  */
                                        /* Show the message                 */
            DelayMsg(D_OPT_ERR, ONESEC, DLYMSG_IGMKS);

            ALARM_OFF;                  /* Turn the alarm off now           */

            SIGNAL(GETUOPTIONS);        /* Try again                        */
        }
    } /* end of else (ie: was not in the optionspressedinsetup condition)   */

   switch (KeyCode)
   {
    case C_POWEROFF:
        if (indelayfornokvo)
            break;

        if (OffIsOk())                  /* If power-off is OK now           */
        {
            PendingAlarm = FALSE;
            OldKeyCode = C_NULL;
            SIGNAL(POWEROFF);           /*   go do it now!                  */
        }
        break;

    case C_CLEAR:
        if (enteredoptparvalue < 10)
        {
            /* (Gets cleared at top of function)                            */
            SIGNAL(GETUOPTIONS);
        }
        /* However, if two digits were typed, Clear should continue,        */
        /* because all Options are two digits, Clear is used as mass option */
        /* clear and as soon as two digits are typed, Clear applies to that */
        /* unless the option didn't exist in which case Clear works. See    */
        /* below at "OPT ERR".                                              */

        /* No break here because CLEAR should continue.                     */


        /* Have to spell them out here to exclude the others which are in a */
        /* default block at the end of this switch statement                */
    case C_NULL:
        /* Expected from EnterParam in case of timeout                      */
    case C_0:
    case C_1:
    case C_2:
    case C_3:
    case C_4:
    case C_5:
    case C_6:
    case C_7:
    case C_8:
    case C_9:
    case C_DP:
    case C_RATE:
    case C_VOLUME:
    case C_RUN:
    case C_TOTAL:
    case C_OPTIONS:
    case C_ENTER:
        /* Expected from EnterParam if user pressed Enter                   */
    case C_LOAD:
        /* Most keystrokes, Including Enter                                 */
        /* Don't allow access in case of Keylock                            */
        /* except for modes, and Keylock of course.                         */

        /* This if block is intended to solve the problem of disallowing    */
        /* Options access during alarming, but allowing the Keylock option. */
        /* That made it impossible to stop the pump after infusion complete */
        /* if in Keylock. See where "Alarming" is set at top.               */
        /* We also want to be able to access BioMed Options if in alarm.    */
        if (
            PendingAlarm
            &&                          /* Option isn't Keylock             */
            (enteredoptparvalue != U_MODE_01)
            &&                          /* Option isn't BioMed Options      */
            (enteredoptparvalue != U_MODE_23)
           )
        {
            KeyCode = OldKeyCode;       /* recall the reason for the alarm  */
            OldKeyCode = C_NULL;        /* Reset defaults                   */

            alm_msg.msgdata = OldMsgData;
            statusflag |= ALARM;        /* make sure status is set          */

            /* Recreate the sound                                           */
            if (PendingAlarm == FASTACTIVE)
                KS_signal(FALMSEMA);
            else if (PendingAlarm == SLOWACTIVE)
                KS_signal(SALMSEMA);
            /* If ALARMACTIVE, what sound, if any?                          */

            /* Alarm now current, no longer Pending                         */
            PendingAlarm = FALSE;

            if (statusflag & PUMPRUN)   /* If pump is running               */
            {
                SIGNAL(RUNDISPLAY);     /* Return to running condition      */
            }
            else                        /* Not running;                     */
            {
                SIGNAL(CHECKTUBE);      /* Don't allow option               */
            }
        }

        /* Allow access only to Keylock if in the non-running Delayed Start */
        /* and the Options Key is pressed.                                  */
        if (
            (indelayfornokvo)
            &&
            (enteredoptparvalue != U_MODE_01)
           )
        {
            SIGNAL(READYTORUN);
        }


        /* Use a dummy option value in order to use the same function for   */
        /* more than one different option number:                           */

                                        /* First assumption:                */
        Dum_opt_no = enteredoptparvalue;

        ADoseModeOptCode = FALSE;
        for (Index=0; Index <= QDOSEMODES-1; Index++)
        {
            if (enteredoptparvalue == (long)(pdmspecsarray[Index]->OptCode))
            {
                ADoseModeOptCode = TRUE;
                Dum_opt_no = U_MODE_07;
                pdmspecsm07 = pdmspecsarray[Index];
                break;
            }
        }

/* Add support here for other functions that do two or more in one          */

        if (!ADoseModeOptCode)
        {
            switch (enteredoptparvalue)
            {
                case U_MODE_04:
                    /* Handles both Piggyback Modes setups                  */
                    /* Dum_opt_no already set                               */
                    ppgmspecsm04 = &pgmrv;
                    break;
                case U_MODE_03:         /* this one handled by Mode04()     */
                    Dum_opt_no = U_MODE_04;
                    ppgmspecsm04 = &pgmtv;
                    break;
                case U_MODE_MAN_PROG_VER_3:
                    /* Handles both Manual Progs' setup                     */
                    Dum_opt_no = U_MODE_19;
                    break;
                case U_MODE_16:
                    /* Handles both Auto and Cust Program Mode setups       */
                    /* Dum_opt_no already set                               */
                    ppmspecsm16 = &pmauto;
                    break;
                case U_MODE_CUST_PROG:  /* this one handled by Mode16()     */
                    Dum_opt_no = U_MODE_16;
                    ppmspecsm16 = &pmautocust;
                    break;
                case U_MODE_21:         /* PCA MG mode                      */
                    /* Dum_opt_no already set                               */
                    ppcaspecsm21 = &pcamgmode;
                    break;
                case U_MODE_26:         /* PCA ML mode - handled by Mode21  */
                    Dum_opt_no = U_MODE_21;
                    ppcaspecsm21 = &pcamlmode;
                    break;
                case U_MODE_30:
                    /* both flavors of DS Occl pressure are done by Mode20  */
                    Dum_opt_no = U_MODE_20;
                    break;
            }
        }


        /* Remove the whole if block that was here, [that did kick-out in   */
        /* the case of Keylock, excepting everything] because all options   */
        /* must be entered in the case of Keylock and this kick-out never   */
        /* done. The kick-outs will be done from the various option mode    */
        /* functions.                                                       */
                                        /* Search for this Option Code      */
        for (Index=0; Index < U_M_FUNCS; Index++ )
        {
            if (Dum_opt_no == ubranch[Index].OptCode)
            {
                /* Here is the very intro to the option. The PUSH ENTR      */
                /* block.                                                   */
                /* New block -- J W                                         */
                /* the last stop on the way to the option.                  */

                /* Re-wrote this PUSH ENTR loop so that RUN and CLEAR will  */
                /* be rejected in all cases except where they are allowed,  */
                /* without needing a GOTO.                                  */
                while (
                       /* Exempt Keylock, so that it will go and do it      */
                       /* discretely.                                       */
                       (Dum_opt_no != U_MODE_01)
                       &&
                       (KeyCode != C_ENTER)
                       &&               /* Opts that CLEAR accesses:        */
                       !
                       (
/* Add more as Options added (only for Options in which CLEAR is supposed   */
/* to work in some way)                                                 */
                        (KeyCode == C_CLEAR)
                        &&
                        (               /* Audio alarm default adjust       */
                         (Dum_opt_no == U_MODE_02)
                         ||
                                        /* Piggyback Modes - all            */
                         (Dum_opt_no == U_MODE_04)
                         ||
                                        /* Primary Time and Volume          */
                         (Dum_opt_no == U_MODE_05)
                         ||
                                        /* Dose Modes - all                 */
                         (Dum_opt_no == U_MODE_07)
                         ||
                                        /* Programming - automatic          */
                         (Dum_opt_no == U_MODE_16)
                         ||
                                        /* Programming - manual, ver 1 & 2  */
                         (Dum_opt_no == U_MODE_19)
                         ||
                                        /* PCA mode - mg and ml modes       */
                         (Dum_opt_no == U_MODE_21)
                         ||
                                        /* Delayed Run                      */
                         (Dum_opt_no == U_MODE_31)
                         ||
                                        /* Occlusion pressure set (PSI)     */
                         (Dum_opt_no == U_MODE_20)
                        )
                        &&
                        !(statusflag & KEYBDLOCK)
                        &&
                        !(statusflag & PUMPRUN)
                        /* Any options in which clearing is allowed while   */
                        /* the pump is running can be added here by         */
                        /* incorporating them as a sub-not in this pumprun  */
                        /* not.                                             */
                       )
                       &&
/* Opts that RUN accesses:                                                  */
                       !
                       (
                        (KeyCode == C_RUN)
                        &&
                        (               /* -- Piggyback Modes               */
                         (Dum_opt_no == U_MODE_04)
                         ||             /* Primary Time and Volume          */
                         (Dum_opt_no == U_MODE_05)
                         ||             /* -- Dose Modes                    */
                         (Dum_opt_no == U_MODE_07)
                         ||             /* -- Auto Program Modes            */
                         (Dum_opt_no == U_MODE_16)
                         ||             /* -- Auto Taper Mode               */
                         (Dum_opt_no == U_MODE_17)
                         ||             /* -- Manual Program Modes          */
                         (Dum_opt_no == U_MODE_19)
                         ||             /* -- PCA modes                     */
                         (Dum_opt_no == U_MODE_21)
                         ||             /* -- Delayed Run                   */
                         (Dum_opt_no == U_MODE_31)
                        )
                       )
                       &&               /* Opts that RATE and VOL access    */
                       !
                       (
                        (
                         (KeyCode == C_RATE)
                         ||
                         (KeyCode == C_VOLUME)
                        )
                        &&
                        (Dum_opt_no == U_MODE_07)
                       )
                      )
                /* NB Include all KeyCodes in the foregoing While condition */
                /* that do not unconditionally exit from this While, in the */
                /* case statement below, because then their KeyCodes will   */
                /* have to be changed to C_NULL, in order to prevent        */
                /* infinite loops.                                          */
                {
                    switch (KeyCode)
                    {
                    case C_NULL:        /* User waited; prompt for ENTER    */

                        /* Set the three messages                           */

                        PushEntrPromptMsgs[0] = D_OPT_TYPED;

/* Updates necessary here if more than one user opts in 1 mode func.        */
                        switch (Dum_opt_no)
                        {
                        case U_MODE_07:
                            PushEntrPromptMsgs[1] = pdmspecsm07->Titlemsg;
                            break;
                        case U_MODE_16:
                            PushEntrPromptMsgs[1] = ppmspecsm16->Titlemsg;
                            break;
                        case U_MODE_20:
                            if (enteredoptparvalue == U_MODE_20)
                                PushEntrPromptMsgs[1] = D_M20_MSG;
                            else
                                PushEntrPromptMsgs[1] = D_M30_MSG;
                            break;
                        case U_MODE_21: /* PCA Modes                        */
                            PushEntrPromptMsgs[1] = ppcaspecsm21->Titlemsg;
                            break;
                        default:
                            /* (Both Manu Progs and both Piggyback Modes    */
                            /* show same msg) The title name:               */
                            PushEntrPromptMsgs[1] = ubranch[Index].ModeMsg;
                            break;
                        }

                        PushEntrPromptMsgs[2] = D_PUSH_ENTR;

                        /* Show the PUSH ENTR prompt regardless of whether  */
                        /* the pump is running or not. For a while there,   */
                        /* PUSH ENTR was not programmed to display while    */
                        /* the pump was running, but nobody liked that.     */
                        /* Give the Option msg; Index arrived at from Dum   */
                        /* _opt_no, which is set to only Opt table values.  */

                        /* Choose the order of the three messages           */

                        if (Dum_opt_no == U_MODE_23)
                        /* User will see PUSH ENTR as long as he keeps      */
                        /* pressing the wrong key while trying go from      */
                        /* OPT 89 / BIO OPT / PUSH ENTR to SET / BIO OPT    */
                            J = 2;
                        else if (ShowOptNoFirstInPushEnter)
                            J = 0;
                        else
                        /* ...say OPT nn, from the enteredoptparvalue       */
                            J = 1;

                        /* Show the three messages                          */

                        ALTERNATE(3);

                        for (K=0; K<=2; K++)
                        {
                            SHOWMSG(PushEntrPromptMsgs[J++]);
                            J %= 3;
                        }

                        /* Pause to display the three messages              */

                        if (statusflag & PUMPRUN)
                        {
                            /* Show the sequence of three repeatedly, for   */
                            /* 18s.                                         */
                            WaitMsg((EIGHTEENSECALTS*BLINKON
                                           -ALTREDUC)/CLKTICK, 4, ignorekeys);
                        }
                        else
                        {
                            WaitMsg(delaytime, 4, ignorekeys);
                        }

                        /* For next time around the While loop, the user    */
                        /* should see the alternating message begin again   */
                        /* with the Option Number if he presses an ignored  */
                        /* key.                                             */
                        ShowOptNoFirstInPushEnter = TRUE;

                        if (KeyCode == C_NULL)
                        /* The user did not type anything                   */
                        {
                            /* If the pump is running, continue on with the */
                            /* User Option. It will straighten out the      */
                            /* correct option number if necessary and       */
                            /* handle the running case.                     */
                            /* Otherwise, trigger the alarm.                */
                            if (statusflag & PUMPRUN)
                            {
                                /* However, it is a requirement that BMOs   */
                                /* not be accessed without an ENTER-press,  */
                                /* since otherwise, BMOs would be entered   */
                                /* and would then stop the pump.            */
                                if (
                                    (Dum_opt_no != U_MODE_23)
                                    &&
/* Add support here for user */ /* Don't want either of these two DS    */
/* options that should not be*/ /* pressure displays if the pump is     */
/* accessed unless the user  */ /* running, unless the user presses     */
/* actually does press       */ /* ENTER:                               */
/* ENTER.                    */ (Dum_opt_no != U_MODE_32)
                                    &&
                                    (Dum_opt_no != U_MODE_33)
                                   )
                                    KeyCode = C_ENTER;
                                else
                                {
                                    SIGNAL(RUNDISPLAY);
                                }
                            }   /* -will cause an exit from this loop       */
                            else
                            {
                                if (!(statusflag & ALARM))
                                {
                                    ALARM_ON(A_WANT_KEY);
                                }
                            }
                        }
                        else
                        /* User did type something. Loop, go see what. Must */
                        /* go right to switch on KeyCode; No GOTOs allowed! */
                        {
                            if (statusflag & ALARM)
                            {
                                if (
                                    (KeyCode >= C_0)
                                    &&
                                    (KeyCode <= C_LOAD)
                                   )
                                {       /* An actual key was pressed        */
                                    ALARM_OFF;
                                }
                            }
                        }
                        break;

                    case C_CLEAR:
                        KeyCode = C_NULL;
                        if (statusflag & KEYBDLOCK)
                            DelayMsg(D_KBLOCK, ONESEC, DLYMSG_IGMKS);

                        break;

                    case C_POWEROFF:
                        KeyCode = C_NULL;

                        if (OffIsOk())
                        {
                            SIGNAL(POWEROFF);
                        }

                        break;

                    case C_OPTIONS:
                        /* Want to go back to SET / OPT CODE                */
                        SIGNAL(GETUOPTIONS);
                        break;

                    /* KeyCodes that cause a re-prompt:                     */
                    /* These must be explicit, because the default case at  */
                    /* the end of this switch sends processing back to      */
                    /* ReadyToRun or Running                                */
                    case C_0:
                    case C_1:
                    case C_2:
                    case C_3:
                    case C_4:
                    case C_5:
                    case C_6:
                    case C_7:
                    case C_8:
                    case C_9:
                    case C_DP:
                    case C_RATE:
                    case C_VOLUME:
                    case C_RUN:
                    case C_TOTAL:
                    case C_LOAD:        /* Screw 'em!                       */
                        KeyCode = C_NULL;
                        break;

                    default:
                    /* Will also handle:                                    */
                    /* case C_FLOWALM                                       */
                    /* case C_FSINST                                        */
                    /* case C_FSREM,                                        */
                    /* or even                                              */
                    /* case C_SILENCE if it should ever pop up.             */
                    /* Commenting out all this stuff will reduce code       */
                    /* size.                                                */

                    /* Where to go:          RE = ReadyToRun if stopped     */
                    /*                          RU = Running if running     */
                    /* If an entry is blank it shouldn't happen             */
                    /* case C_RCINST:     /* RE                             */
                    /* or any running alarms                                */
                    /* case C_RDCPT:                                        */
                    /*               Rev-Dependent checkpoint is not        */
                    /* implemented yet and should be handled in motor       */
                    /* control anyway                                       */
                    /* case C_RCREM:      /* RE RU                          */
                    /* case C_RCOPEN:     /* RE RU                          */
                    /* case C_RCBETWEEN:  /* RE RU                          */
                    /* case C_RCCLOSE:    /* RE RU                          */
                    /* case C_PLOCK:      /* RE                             */
                    /* case C_PUNLOCK:    /* RE RU                          */
                    /* case C_SYRINSTL:   /* RE                             */
                    /* case C_SYRIREM:    /* RE RU                          */
                    /* case C_USAIR:      /* RE RU                          */
                    /* case C_USOCCL:     /* RE RU                          */
                    /* case C_USNORMAL:   /* RE RU                          */
                    /* case C_USNOTUBE:                                     */
                    /*               can only happen during set loading     */
                    /* case C_DSOCCL:     /* RE RU                          */
                    /* case C_DSNORMAL:   /* RE RU                          */
                    /* case C_DSNOTUBE:                                     */
                    /*               can only happen during set loading     */
                    /* case C_INFCOMP:    /*    RU                          */
                    /* The minor power status messages, ACIN, ACOUT, BATTOK */
                    /* and BATTLOW are ignored in the core display pause,   */
                    /* above.                                               */
                    /* case C_ACIN:       /* RE RU                          */
                    /* case C_ACOUT:      /* RE RU                          */
                    /* case C_BATTLOW:    /* RE RU                          */
                    /* case C_BATTDEAD:   other task will take over         */
                    /* case C_BATTOK:     /* RE RU                          */
                    /* case C_UPSENSERR:  /* RE RU                          */
                    /* case C_DNSENSERR:  /* RE RU                          */
                    /* case C_MOT_HI:     /*    RU                          */
                    /* case C_MOT_LO:     /*    RU                          */
                    /* case C_RCERROR:    /* RE RU                          */
                    /* case C_LEVOPEN:    /* RE RU                          */
                    /* case C_LEVNOTOPEN: /* RE RU                          */

                        if (statusflag & PUMPRUN)
                        {
                            SIGNAL(RUNNING);
                                        /* Return to Running to process     */
                        }
                        else
                        {               /* put message back in ctrl mailbox */
                            STUFFMSG;
                            /* ReadyToRun checks mailbox first thing        */
                            SIGNAL(READYTORUN);
                        }

                        break;

                    } /* End of switch to analyze KeyCodes                  */
                } /* End of PUSH ENTR while loop                            */
                /* The ENTER key needs to be cleared or else the user opt   */
                /* will act on it.                                          */
                if (KeyCode == C_ENTER)
                    KeyCode = C_NULL;

/* Updates needed here when new Option Modes added                          */
                if (
                    (statusflag & FIXHAPPENED)
                    &&
                    (                   /* option isn't Pig Mode            */
                     (Dum_opt_no == U_MODE_04)
                     ||                 /* or Primary Time and Vol mode     */
                     (Dum_opt_no == U_MODE_05)
                     ||                 /* or Dose Mode                     */
                     (Dum_opt_no == U_MODE_07)
                     ||                 /* or Auto Program Mode             */
                     (Dum_opt_no == U_MODE_16)
                     ||                 /* or Auto Taper Mode               */
                     (Dum_opt_no == U_MODE_17)
                     ||                 /* or Manual Program Mode           */
                     (Dum_opt_no == U_MODE_19)
                     ||                 /* or PCA Modes                     */
                     (Dum_opt_no == U_MODE_21)
                     ||                 /* or Delayed Start                 */
                     (Dum_opt_no == U_MODE_31)
                    )
                   )
                /* The pump is stopped, and Option Modes must be disallowed */
                /* because we don't want the user to try any Mode while the */
                /* pump is in a fix condition                               */
                {
                    SIGNAL(CHECKTUBE);  /* Go handle the Fix Code           */
                }

                /* LAST CHANCE TO PREVENT THE USER FROM GOING IN!           */
                /* ...if BMO 220 was used to disable the user option:       */

                /* OptModeDisaEna works directly with the temp bytes.       */

                /* They must be restored here in case OPTIONS was pressed   */
                /* to blow out of BMO 220 without saving the changes made   */
                /* to the tempoptdisable bytes. Since OptModeDisaEna works  */
                /* with a working image, a better data representation could */
                /* be used by it, reading it and writing the NVRAM format   */
                /* upon entry and exit. Changing to do that would probably  */
                /* be more trouble than it is worth, however.               */

                if (enteredoptparvalue == (long)U_MODE_23)
                {
                    /* Always allow entry to BMOs.                          */
                    RC = ACTIVEOPT;
                    /* Actually, BMOs are now called above, but just in     */
                    /* case the action moves down here, we will be ready to */
                    /* always allow entry to BMOs.                          */
                }
                else
                {
                    /* The OptModeDisaEna function depends upon having      */
                    /* these working globals updated for it to read         */
                    tempoptdisablebyte0 = optiondisablebyte0;
                    tempoptdisablebyte1 = optiondisablebyte1;
                    tempoptdisablebyte2 = optiondisablebyte2;
                    tempoptdisablebyte3 = optiondisablebyte3;
                    tempoptdisablebyte4 = optiondisablebyte4;

                    RC = OptModeDisaEna(TESTINGOPT, enteredoptparvalue);
                }

                /* Note that we now do OPT N/A here rather than in the Mode */
                /* function, since we added this feature to disable Option  */
                /* Modes.                                                   */
                /* The TEMP_OPT_TABLE array in rtxcmain.c has to be updated */
                /* with the correct booleans (ie, the TRUE one) when        */
                /* another User Option function gets implemented, so that   */
                /* BMO 220 can track its status, too -- or else this test   */
                /* won't let the user into the option function.             */
                if (
                    (RC == OPTNA)
                    ||
                    /* Also, the function is N/A if it is in the upper 2    */
                    /* meg (bits) and we are only in the 2 meg PROM.        */
                    (
                     !fourmeg           /* ergo, in a two meg PROM          */
                     &&
                     ubranch[Index].InUpper2Megs
                    )
                   )
                {
                    DelayMsg(D_OPT_NA, TWOSEC, DLYMSG_IGMKS);
                    RC = OK;            /* Provide a return code for exit   */
                }
                else if (RC == NOTACTIVEOPT)
                {
                    /* Display "OPT DISA"                                   */
                    DelayMsg(D_MB08_INDIC, TWOSEC, DLYMSG_IGMKS);
                    RC = OK;            /* Provide a return code for exit   */
                }
                else if (RC == NOSUCHOPTION)
                {
                    /* This will lead to the "OPT ERR" display, with beep.  */
                    break;
                }

                /* else-if for PCA isolation.                               */

                /* Disallow any other Option Mode, including the other PCA  */
                /* Mode, if in a PCA Mode. Allow User and Biomed Options.   */
                else if (
                         (modeflag & PCAALL)
                         &&
/* Add support when new Option Modes are added, or else they will interfere*/
/* with the PCA Modes.                                                      */
/* Must blow out if accessing a different Option Mode if in PCA Mode.       */
                         (
                          (
                           (                /* option isn't Pig Mode            */
                            (Dum_opt_no == U_MODE_04)
                            ||          /* or Primary Time and Vol mode     */
                            (Dum_opt_no == U_MODE_05)
                            ||          /* or Dose Mode                     */
                            (Dum_opt_no == U_MODE_07)
                            ||          /* or Auto Program Mode             */
                            (Dum_opt_no == U_MODE_16)
                            ||          /* or Auto Taper Mode               */
                            (Dum_opt_no == U_MODE_17)
                            ||          /* or Manual Program Mode           */
                            (Dum_opt_no == U_MODE_19)
                            ||          /* or Delayed Start                 */
                            (Dum_opt_no == U_MODE_31)
                           )
                           /* Don't blow out if in Keylock or the pump is   */
                           /* running. The user can only look. What harm can    */
                           /* the user cause? What could go possibly go     */
                           /* wrong? ;-)                                        */
                           &&
                           !(statusflag & KEYBDLOCK)
                           &&
                           !(statusflag & PUMPRUN)
                          )
                          ||
                          (
                           (Dum_opt_no == U_MODE_21)
                           &&           /* Blow out if accessing other PCA  */
                           (enteredoptparvalue != (long)(ppcaspecs->OptCode))
                          )
                         )
                        )
                {
                    /* Here we blow out by setting RC to OK so that the     */
                    /* user is simply returned to the main prompt.          */
                    RC = OK;
                    /* Display "EXIT PCA / TO SET / OPT CODE" (once)        */
                    DelayMsg(D_PCA_EXIT, BLINKON, DLYMSG_IGMPS);
                    DelayMsg(D_TO_SET, BLINKON, DLYMSG_IGMPS);
                    /* Chain keystrokes by using IGMPS until last message,  */
                    /* in which we do IGMKS, so that any ENTER or digit     */
                    /* keypress, etc. ends the display but doesn't get      */
                    /* "stuffed". Any important keycode must be stuffed if  */
                    /* RC = OK.                                             */
                    DelayMsg(D_SET_OPT2, BLINKON, DLYMSG_IGMKS);
                }
                else /* ("Geez, Edith" -- Archie Bunker)                    */
                {
                    /* Refuse to let the user in to Biomed Options if       */
                    /* Keylock is on:                                       */

                    /* If the user selected BMOs                            */
                    if (Dum_opt_no == (long)U_MODE_23)
                    {
                        /* But the pump is in Keylock:                      */
                        if (statusflag & KEYBDLOCK)
                        {
                            DelayMsg(D_KBLOCK, ONESEC, DLYMSG_IGMKS);
                                        /* Return to "calling" routine      */
                            if (statusflag & PUMPRUN)
                            {           /* If the pump is running           */
                                SIGNAL(RUNDISPLAY);
                            }           /* Go back to Run mode              */
                            else
                            {           /*   quit so user can try again     */
                                SIGNAL(CHECKTUBE);
                            }
                        }

                        /* else, tell motorctl to stop, if the pump is      */
                        /* running.                                         */
                        if (statusflag & PUMPRUN)
                        {
                            KS_signal(STOPSEMA);
                            infusionincomplete = TRUE;
                        }
                    }

#if 0 /* Factory options remain to be implemented at some future date.      */
      /* They should be incorporated into the above block so that kick-out  */
       /* will be done if Keylock is on.                                    */
                                        /* If user selected Factory Options */
                    if ( Dum_opt_no == ubranch[MFGR].OptCode )
                    {
                        /* Perror.c will have to be modified, if it is      */
                        /* desired to access Factory options while in a FIX */
                        /* condition, to allow Factory Options as well as   */
                        /* BioMed options.                                  */

                        /* Go get the MFGR processor                        */
                        SIGNAL(SecretOpt);
                    }
#endif


            /* OK, BY HERE, WE'RE DEFINITELY GOING IN! (But first, a few    */
            /* points...)                                                   */


                    if (
                        (statusflag & KEYBDLOCK)
                        &&
                        /* Don't repeat KEY LOCK if we're going into it.    */
                        /* Don't be redundant, it's repetitive&superfluous. */
                        (Dum_opt_no != U_MODE_01)
                        /* Neither repeat if going into Option 12, 61, or   */
                        /* 83, which also do it themselves.                 */
                        &&
                        (Dum_opt_no != U_MODE_25)   /* Back to Pri Mode     */
                        &&
                        (Dum_opt_no != U_MODE_17)   /* Go to Taper down     */
                        &&
                        (Dum_opt_no != U_MODE_27)   /* Wipe the PCA Mode    */
                        &&
                        (Dum_opt_no != U_MODE_28)   /* Display PCA Hist Log */
/* Add exceptions here if other Options are implemented that display KEY    */
/* LOCK themselves or are Options that change nothing because they are for  */
/* information only, such as Mode28 for Opt 82, display the PCA History */
/* log.                                                                 */
                       )
                    {
                        /* Display KEYLOCK as a reminder but don't be       */
                        /* redundant:                                       */

                        /* Don't stuff ENTER, so that an impatient user can */
                        /* cancel this Keylock display and go on to the     */
                        /* next without having the next display skipped,    */
                        /* which could be frustrating.                      */

                        DelayMsg(D_M01_MSG, ONESEC, DLYMSG_IGMKS);

                    } /* OK, that wasn't redundant                          */


                    /* We are doing a review if the mode is all setup       */
                    /* REVIEW only gets set for Option Modes, ie Options    */
                    /* which are represented by a modeflag setting.         */

/* Maintain support here if there are auxiliary bits in the Modeflag that   */
/* we don't want to have causing confusion as to what Option Number gets    */
/* returned.                                                                */
                    if (
                        (
                         /* Check underlying mode                           */
                         (
                          enteredoptparvalue
                              == OptNoOfMode(
                                             modeflag
                                             &
                                             (PROGRAM5MASK & DELAYEDRUNMASK)
                                             /* (Otherwise those bits take  */
                                             /* precedence)                 */
                                            )
                         )
                         ||
                         /* Check if in AutoTaper by excluding only Delayed */
                         /* Run from consideration                          */
                         (enteredoptparvalue
                                  == OptNoOfMode(modeflag & DELAYEDRUNMASK))
                         ||
                         /* Check if in Delayed Run                         */
                         (
                          (enteredoptparvalue == U_MODE_31)
                          &&
                          (modeflag & DELAYEDRUN)
                         )
                        )
                        &&
                        (
                         (parmflag & PARMMEM)
                         ||
                         /* Pigback might be set up even if no Primary Vals */
                         (Dum_opt_no == U_MODE_04) /* (both types)          */
                         ||
                         /* Delayed Start might be set up if no other vals  */
                         (enteredoptparvalue == U_MODE_31)
                        )
                       )
                    {
                        statusflag |= REVIEW;
                    }


                    /* It is difficult to understand why the following      */
                    /* block is here. But, it is a general simplifying      */
                    /* assumption to realize that any new Option Mode will  */
                    /* start from a base of the Primary Mode, with the      */
                    /* Primary values cleared if they were old (pump was    */
                    /* not in Pig or Primary) when the new Option Mode was  */
                    /* selected.                                            */

                    /* For example, if the user sets up a Dose Mode and     */
                    /* then overrides it with a Piggyback, we want to find  */
                    /* the Primary values cleared, which will get done when */
                    /* doing this code to go from Dose -> Pig.              */

                    /* Exception for Delayed Run: don't clear the set mode  */
                    /* if going into Delayed Run - it is desired to run it  */
                    /* after a delay.                                       */

                    /* Other than this block, modes don't do clearing when  */
                    /* they are being set up, only when they are being      */
                    /* exited for one reason or another. Hence, overriding  */
                    /* an option mode would not otherwise do a ClearMode.   */


                    /* Note that this block will cause all Option Modes     */
                    /* except Delayed Run to be exited if any Option Mode   */
                    /* is selected and CLEAR is pressed, and of course      */
                    /* Delayed Run will be cleared too if it was the one    */
                    /* specifically selected.                               */

/* Add support here when new Option Modes are added                     */
                    if (
                       /* Going into an Option Mode                         */
                        (               /* Piggyback Modes - both           */
                         (
                          (Dum_opt_no == U_MODE_04)
                          &&            /* but currently NOT in Time mode   */
                          (!(modeflag & TIMEMODE))
                         )
                         ||
                         (              /* Primary Time Mode                */
                          (Dum_opt_no == U_MODE_05)
                          &&            /* but currently NOT in a Pig Mode  */
                          (!(modeflag & PIGBACKALL))
                         )
                         ||             /* Dose Modes - all                 */
                         (Dum_opt_no == U_MODE_07)
                         ||             /* Programming - automatic          */
                         (Dum_opt_no == U_MODE_16)
                         ||             /* Programming - manual, ver 1 & 2  */
                         (Dum_opt_no == U_MODE_19)
                         ||             /* PCA Modes                        */
                         (Dum_opt_no == U_MODE_21)

                         /* But not U_MODE_17 - that's not really a mode    */
                         /* but just a tweaking of Auto Program Mode(s).    */
                         /* Clearing any of the above (like Auto Program    */
                         /* Mode [duh]) would be wrong.                     */

                         /* Similarly, the underlying Mode needs to be      */
                         /* preserved if the Option being entered is        */
                         /* Delayed Start, Mode31.                          */
                         /* ... so also don't clear if U_MODE_31            */
                        )
                        &&
                        !(statusflag & PUMPRUN)
                        &&
                        !(statusflag & KEYBDLOCK)
                        &&
                        /* Going into a different Option Mode:              */
                        (
                         enteredoptparvalue
                              != OptNoOfMode(
                                             modeflag
                                             &
                                             (PROGRAM5MASK & DELAYEDRUNMASK)
                                            )
                        )
                       )
                    {
                        /* Exit Delayed Run if Going into PCA Mode.         */
                        /* Normally Delayed Run just applies to whatever    */
                        /* mode is selected.                                */
                        if (
                            (modeflag & DELAYEDRUN)
                            &&
                            (Dum_opt_no == U_MODE_21)
                           )
                        {
                            ClearMode();
                        }
                        else
                        {
                            /* If the user just selects an Option Mode that */
                            /* is not even set up yet and presses CLEAR,    */
                            /* Delayed End will be exited from.             */
                            ClrDlydEnd(TRUE);
                        }


                        /* Don't need to do ClearMode if already in the     */
                        /* Primary Mode                                     */
                        if (!(modeflag & NORMAL))
                        {
                            /* Can't exit a PCA mode because access to      */
                            /* other option modes is disallowed when in a   */
                            /* PCA Mode.                                    */
                            ClearModeCore();
                                        /* -decides if Pri vals get cleared */
                        }
                    }

                    /* Record the option number in the History Log          */
                    if (Dum_opt_no != U_MODE_23)
                    {
                        HISTLOG(enteredoptparvalue);
                    }


                    /* This is only set for Opts 80 and 81 (PCA)            */
                    if (LocalOptionsPressedInSetup)
                    {
                        optionspressedinsetup = TRUE;
                        LocalOptionsPressedInSetup = FALSE;
                    }

                    /* FINALLY, CALL THE CORRESPONDING FUNCTION - using     */
                    /* either C_NULL or C_CLEAR:                            */

/*         \                                                                */
/*---------\                                                                */
/*---------->   Now here is where the point of this whole DAMN EXERCISE     */
/*---------/        actually occurs!!!                                      */
/*         /                                                                */

                    /* Successful setup of an Option Mode sets optionvalue  */
                    if (Dum_opt_no != U_MODE_23)
                    {
                        /* Pass in the option number for Dose Modes, Manual */
                        /* Program Modes and other Modenn() that implement  */
                        /* more than one Option Mode:                       */
                        optionugot = enteredoptparvalue;
                        /* optionugot will be zero inside any Modenn func   */
                        /* if said function is not accessed by pressing     */
                        /* OPTIONS!                                         */

                        RC = ubranch[Index].Target(KeyCode);

                        optionugot = 0;
                    }
                    else /* It's BMOs                                       */
                    {
                        /* optionugot is 0 here. Option Modes depend on     */
                        /* having that cleared when Options selection is    */
                        /* done. BMOs don't need it.                        */

                                        /* Go get the BMO processor:        */
                        SIGNAL(GETBOPTIONS);
                        /* Don't worry about RC; won't be coming back here  */
                    }

                } /* End of if-else block to enable and disable user opts   */

                /* If an alarm is still pending, then that was just now     */
                /* either the Keylock Option that we went through or the    */
                /* BMOs. If it was not the BMOs, we still have to go and    */
                /* restore the alarm                                        */
                if (PendingAlarm)
                {
                    /* Restore alarm if option wasn't BioMed Options -      */
                    /* PendingAlarm could only otherwise have been set if   */
                    /* option was Keylock. If option was the BMOs, we       */
                    /* assume that the user knew what he was doing and has  */
                    /* fixed the cause of the alarm by now.                 */
                    if (enteredoptparvalue != U_MODE_23)
                    {
                        /* recall the reason for the alarm                  */
                        KeyCode = OldKeyCode;
                        alm_msg.msgdata = OldMsgData;
                        /* make sure status is set                          */
                        statusflag |= ALARM;

                        /* Recreate the sound                               */
                        if (PendingAlarm == FASTACTIVE)
                            KS_signal(FALMSEMA);
                        else if (PendingAlarm == SLOWACTIVE)
                            KS_signal(SALMSEMA);
                        /* (If ALARMACTIVE, what sound, if any?)            */
                    }

                    /* Reset defaults                                       */
                    OldKeyCode = C_NULL;
                    /* Alarm now current, no longer Pending                 */
                    PendingAlarm = FALSE;
                }

                if (RC == OK)
                /* KeyCode expected to be already stuffed if OK; not        */
                /* stuffed in case of IGNORE.                               */
                {                       /* Option completed successfully    */
                    statusflag &= REVIEWMASK;
                    if (statusflag & PUMPRUN)
                    {                   /* If the pump is running           */
                        SIGNAL(RUNDISPLAY);
                                        /* Return to running condition      */
                                        /* - checks mailbox first thing     */
                    }
                    else                /* Not running;                     */
                    {
                        SIGNAL(CHECKTUBE);
                        /* - checks mailbox pretty much right away          */
                    }
                }
                else                    /* IGNORE means some strange        */
                /* KeyCode was received that caused kick-out from the       */
                /* function. OK: stuffed. IGNORE: not stuffed.              */
                {
                    statusflag &= REVIEWMASK;
                    switch (KeyCode)
                    {
                    case C_INFCOMP:     /* An infusion has completed        */
                        SIGNAL(INFSCHED);
                        break;          /* Go handle the next infusion      */
                    case C_POWEROFF:
                        if (OffIsOk())
                        {
                            SIGNAL(POWEROFF);
                        }
                        break;
                    case C_OPTIONS:
                        SIGNAL(GETUOPTIONS);
                        break;
                    default:            /* handle any condition msg         */
                    /* Note: What leads into this part should be looked at  */
                    /* and tested carefully.                                */
                        if (statusflag & PUMPRUN)
                        {
                            /* Switches right away on KeyCode               */
                            SIGNAL(RUNNING);
                        }
                        else            /* Don't go run if not running      */
                        {
                            if (KeyCode == C_VOLUME)
                            {
                                SIGNAL(GETVOL);
                            }

                            if (
                                (KeyCode != C_NULL)
                                &&
                                (KeyCode != C_ENTER)
                               )
                            {           /* Stuff back in control mailbox    */
                                STUFFMSG;
                            }
                            SIGNAL(CHECKTUBE);
                            /* Checks mailbox; does not turn off my alarm.  */
                        }
                        break;
                    } /* end of switch on KeyCode for else, ie IGNORE       */
                } /* end of if-else after doing option                      */

            /* (Do you ever get the impression that life would have been a  */
            /* lot simpler if these Option functions had been made part of  */
            /* EntryPoint?)                                                 */

            } /* end of if option found                                     */
        } /* end of for loop to find option                                 */

        /* Error in case the option was not found, unless the Clear key is  */
        /* pending. (Look upwards a fair chunk for EPRet)                   */

        if (KeyCode == C_CLEAR)
        {
            enteredoptparvalue = 0;
            SIGNAL(GETUOPTIONS);
            /* Clear allows correction of bad Opt Code                      */
        }
        else
        {
            ALARM_ON(A_OPT_ERR);        /* Sound the alarm                  */
            DelayMsg(D_OPT_ERR, ONESEC, DLYMSG_IGMKS);
                                        /* Tell user                        */
            ALARM_OFF;                  /* Turn the alarm off now           */
        }
        break;

    default:
    /* Will also handle:                                                    */
    /* case C_FLOWALM                                                       */
    /* case C_FSINST                                                        */
    /* case C_FSREM                                                         */
    /* or even                                                              */
    /* case C_SILENCE if it should ever pop up                              */

    /* commenting out all this stuff will reduce code size:                 */

    /* case C_RCINST:                       /* or any running alarms        */
    /* case C_RDCPT:                                                        */
    /* Rev-Dependent checkpoint is not implemented yet and should be        */
    /* handled in motor control anyway                                      */
    /* case C_RCREM:                                                        */
    /* case C_RCOPEN:                                                       */
    /* case C_RCBETWEEN:                                                    */
    /* case C_RCCLOSE:                                                      */
    /* case C_PLOCK:                                                        */
    /* case C_PUNLOCK:                                                      */
    /* case C_SYRINSTL:                                                     */
    /* case C_SYRIREM:                                                      */
    /* case C_USAIR:                                                        */
    /* case C_USOCCL:                                                       */
    /* case C_USNORMAL:                                                     */
    /* case C_USNOTUBE:  can only happen during set loading                 */
    /* case C_DSOCCL:                                                       */
    /* case C_DSNORMAL:                                                     */
    /* case C_DSNOTUBE:  can only happen during set loading                 */
    /* case C_INFCOMP:                                                      */
    /* case C_ACIN:                                                         */
    /* case C_ACOUT:                                                        */
    /* case C_BATTLOW:                                                      */
    /* case C_BATTDEAD:  other task will take over                          */
    /* case C_BATTOK:                                                       */
    /* case C_UPSENSERR:                                                    */
    /* case C_DNSENSERR:                                                    */
    /* case C_MOT_HI:                                                       */
    /* case C_MOT_LO:                                                       */
    /* case C_RCERROR:                                                      */
    /* case C_LEVOPEN:                                                      */
    /* case C_LEVNOTOPEN:                                                   */

        PendingAlarm = FALSE;
        OldKeyCode = C_NULL;
        if (statusflag & PUMPRUN)
        {
            SIGNAL(RUNNING);            /* Return to Running to process     */
        }
        else
        {
            STUFFMSG;
            /* ReadyToRun checks mailbox first thing:                       */
            SIGNAL(READYTORUN);
        }
        break;

    } /* end - EPRet switch                                                 */

    if (statusflag & PUMPRUN)           /* If the pump is running           */
    {
        SIGNAL(RUNDISPLAY);             /* Go back to Run mode              */
    }
    else
    {
        SIGNAL(CHECKTUBE);              /*   quit so user can try again     */
    }

} /* end of GetUOptions()                                                   */

back

First posted Oct 13, 2003

Hosted by www.Geocities.ws

1