// KeyStreamsB.bcpl -- companion file is KeyStreamsA.asm
// Copyright Xerox Corporation 1979
// Last modified November 25, 1978  5:12 AM by Boggs

get "Streams.d"
get "SysDefs.d"
get "SysInternals.d"
get "AltoDefs.d"

external
[
//outgoing procedures
CreateKeyboardStream; SetKeyboardProc

//incoming procedures
Noop; Idle; Usc

//outgoing statics
keys

//incoming statics
OsBuffer
kbUserProc; kbUserProcStack; kbTable
kbInterrupt; kbInterruptReMask
]

static keys

//----------------------------------------------------------------------------
let CreateKeyboardStream() = valof
//----------------------------------------------------------------------------
[
keys = table [ 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0 ]
compileif lST gr 12 then [ foo = nil ]

// Copy info about keys already down into kb state.
let p = kbTable +1
for i = 0 to 4 do p!i = not @(p!(i+7))

// No user keyboard procedure
kbUserProcStack = 0

// Set up keys stream
for i = 0 to lST-1 do keys!i = Noop
keys>>ST.reset = KeyReset
keys>>ST.gets = KeyGets
keys>>ST.endof = KeyEofs
keys>>ST.type = stTypeKeys

let f = OsBuffer + size OsBUF/16  //Skip over buffer pointers
let l = f + OsBuffer!-1  //OsBuffer!-1 is how big it is

OsBuffer>>OsBUF.First = f
OsBuffer>>OsBUF.Last = l

//If the in and our pointers look reasonable, leave them alone.
if Usc(OsBuffer>>OsBUF.In, f) ls 0 % Usc(OsBuffer>>OsBUF.Out, f) ls 0 %
  Usc(OsBuffer>>OsBUF.In, l) ge 0 % Usc(OsBuffer>>OsBUF.Out, l) ge 0 then
   [	//Reset the buffer
   OsBuffer>>OsBUF.In = f
   OsBuffer>>OsBUF.Out = f
   ]

interruptVector!kbInterruptLevel = kbInterrupt
kbInterruptReMask = kbInterruptBit-1
@activeInterrupts = @activeInterrupts % kbInterruptBit
@displayInterrupt = @displayInterrupt % kbInterruptBit

resultis keys
]

//----------------------------------------------------------------------------
and SetKeyboardProc(proc, stack, length; numargs n) be
//----------------------------------------------------------------------------
[
test n eq 0
   ifso kbUserProcStack = 0
   ifnot
      [
      kbUserProc = proc
      kbUserProcStack = stack + length - (offset FRAME.temp/16) -1
      ]
]

//----------------------------------------------------------------------------
and KeyGets(s) = valof
//----------------------------------------------------------------------------
[
Idle() repeatwhile KeyEofs(s)
let newOut = OsBuffer>>OsBUF.Out +1
if newOut eq OsBuffer>>OsBUF.Last then newOut = OsBuffer>>OsBUF.First
let result = @(OsBuffer>>OsBUF.Out)
OsBuffer>>OsBUF.Out = newOut
resultis result
]

//----------------------------------------------------------------------------
and KeyReset(s) be
//----------------------------------------------------------------------------
[
OsBuffer>>OsBUF.In = OsBuffer>>OsBUF.First
OsBuffer>>OsBUF.Out = OsBuffer>>OsBUF.First
]

//----------------------------------------------------------------------------
and KeyEofs(s) = OsBuffer>>OsBUF.In eq OsBuffer>>OsBUF.Out
//----------------------------------------------------------------------------