-- JunoKeyboardImpl, coded by Greg Nelson & Donna Auguste,
 -- December 7, 1982 11:51 am
 DIRECTORY ViewerClasses, TIPUser, JunoKeyboard;

JunoKeyboardImpl: MONITOR
     EXPORTS JunoKeyboard =
BEGIN OPEN JunoKeyboard;
  x, y, oldx, oldy : PUBLIC INT ← 0;
  event : PUBLIC EventType;
  button : PUBLIC ButtonType;
  char: PUBLIC CHAR;
  status : PUBLIC ARRAY ButtonType OF StatusType;
  nonFull, nonEmpty: CONDITION;
  Quit : PUBLIC SIGNAL = CODE;
  ignoredCount: NAT ← 0;
  
  queueMax : INTEGER = 1000;
  queue : ARRAY [0..queueMax) OF REF ANY;
  queueLeft, queueRight : INT ← 0;
--  the active range of the queue is [queueLeft..queueRight), wrapped
--  entries are added to the right of the queue, and removed from the left.

--ENTERANDNOTIFY
  EnterAndNotify : PUBLIC ENTRY PROC    
  [self : ViewerClasses.Viewer,
   input : LIST OF REF ANY] =
{
      WHILE input # NIL DO
      WHILE (queueRight + 1) MOD queueMax = queueLeft
         DO 
         -- WAIT nonFull
         ignoredCount ← ignoredCount + 1;
         RETURN
      ENDLOOP;
      queue[queueRight] ←  input.first;
      queueRight ← (queueRight + 1) MOD queueMax;
      BROADCAST nonEmpty;
      input ← input.rest
   ENDLOOP;
};
      
 --NEXT (will pop off an entry)
 Next : PUBLIC ENTRY PROC =
    { 
        WHILE (queueLeft = queueRight) DO
        WAIT  nonEmpty
      ENDLOOP;
      WITH queue[queueLeft] SELECT FROM
         coords : TIPUser.TIPScreenCoords 
           => { event ← roll;
                 oldx ← x;
                 oldy ← y;
                 -- x ← coords.x;  (cedar 3.1)
                 -- y ← coords.y  (cedar 3.1)
                 x ← coords.mouseX;
                 y ← coords.mouseY
               };
         text : REF CHAR
            => { event ← keyDown;
                  char ← text↑
                };
         clickAtom: ATOM 
            =>{
               SELECT clickAtom FROM
               $Destroy => 
                  { event ← keyDown; char ← 33C; SIGNAL Quit[ ]};
                  --  if the event was $Destroy, act as though is was an ESC, so that JunoTop
                  -- will treat is as the Select Quit & ESC sequence.
               $RedUp => 
                  {status[red] ← up; event ← clickUp; button ← red};
               $RedDown =>
                   {status[red] ← down; event ← clickDown; button ← red};
               $BlueUp =>
                   {status[blue] ← up; event ← clickUp; button ← blue};
               $BlueDown =>
                   {status[blue] ← down; event ← clickDown; button ← blue};
               $YellowUp =>
                   {status[yellow] ← up; event ← clickUp; button ← yellow};
               $YellowDown =>
                   {status[yellow] ← down; event ← clickDown; button ← yellow}
               ENDCASE => ERROR;
              }
        ENDCASE => ERROR;
        queueLeft ← (queueLeft + 1) MOD queueMax;
        BROADCAST nonFull
       };

            
 
END.