// GateConIO.bcpl

// Last modified March 6, 1979  10:39 PM by Boggs

get "AltoDefs.d"

external
[
// outgoing procedures
GetString; GetNumber; Confirm; Ws; Wss

// incoming procedures
Puts; Gets; Resets; Endofs; Block
PutTemplate; BackSpace; DefaultArgs
SetTimer; TimerHasExpired; MoveBlock

// incoming statics
dsp; keys
]

structure String [ length byte; char↑1,255 byte ]

//----------------------------------------------------------------------------
let GetString(prompt, addr, echo, char; numargs na) = valof
//----------------------------------------------------------------------------
// returns false if del is typed (return to command level)
// addr is the address of the string that should get the result.
// prompt is a prompt string printed in the obvious places
[
Resets(keys)
DefaultArgs(lv na, 2, true, 0)
if prompt ne 0 then Ws(prompt)
let count = 0

   [
   char = char ne 0 ? char, Gets(keys); switchon char into
      [
      case $*N: case $*S: case $*033: case $*T:
         [
         Puts(dsp, $*S)
         addr>>String.length = count
         resultis count
         ]
      case $*027:  //word delete
         [
         if echo then for i = count to 1 by -1 do
            BackSpace(dsp, addr>>String.char↑i)
         count = 0
         endcase
         ]
      case $*177:  //command delete
         [
         Ws(" XXX")
         resultis false
         endcase
         ]
      case $*001:  //↑A
      case $*010:  //BS
         [
         if count ne 0 & echo then
            [
            BackSpace(dsp, addr>>String.char↑count)
            count = count -1
            ]
         endcase
         ]
      default:
         [
         if count ls 255 & char gr 40b then
            [
            count = count +1
            addr>>String.char↑count = char
            if echo then Puts(dsp, char)
            ]
         endcase
         ]
      ]
   char = 0
   ] repeat
]

//----------------------------------------------------------------------------
and GetNumber(string; numargs na) = valof
//----------------------------------------------------------------------------
[
Resets(keys)
if na gr 0 then Ws(string)
let res = 0
let count = 0
   [
   let char = Gets(keys); switchon char into
      [
      case $0: case $1: case $2: case $3:
      case $4: case $5: case $6: case $7:
         [
         Puts(dsp, char)
         res = (res lshift 3) + (char&7)
         endcase
         ]
      case $*001: case $*010:
         [
         if count ne 0 then
            [
            BackSpace(dsp, $0+(res&7))
            res = res rshift 3
            ]
         endcase
         ]
      case $*N: case $*S: case $*033:
         [ Puts(dsp, $*S); resultis res ]
      case $*177:
         [ Ws(" XXX"); resultis 0 ]
      ]
   ] repeat
]

//----------------------------------------------------------------------------
and Confirm(prompt; numargs na) = valof
//----------------------------------------------------------------------------
[
Resets(keys)
if na gr 0 then Ws(prompt)
Ws(" [Confirm] ")

let cursor = vec 16; MoveBlock(cursor, cursorBitMap, 16)
MoveBlock(cursorBitMap, table [ 0; 1700b; 3740b; 7160b; 6060b; 60b
 160b; 340b; 700b; 600b; 600b; 600b; 0; 0; 600b; 600b ], 16)

manifest blinkInterval = 30
let timer = nil; SetTimer(lv timer, blinkInterval)
let down = false
let ok = valof
   [
   test utilIn>>UtilIn.yellow eq 0
      ifso down = true
      ifnot if down then [ Ws("Yes."); resultis true ]

   unless Endofs(keys) switchon Gets(keys) into
      [
      case $Y: case $y: case $*N:
         [ Ws("Yes."); resultis true ]
      case $N: case $n: case $*177:
         [ Ws("No."); resultis false ]
      default:
         [ Ws("Yes or No: "); endcase ]
      ]

   if TimerHasExpired(lv timer) then
      [
      for i = 0 to 15 do cursorBitMap!i = not cursorBitMap!i
      SetTimer(lv timer, blinkInterval)
      ]

   Block()
   ] repeat

MoveBlock(cursorBitMap, cursor, 16)
resultis ok
]

//----------------------------------------------------------------------------
and Wss(stream, string) be
//----------------------------------------------------------------------------
   for i = 1 to string>>String.length do
      Puts(stream, string>>String.char↑i)

//----------------------------------------------------------------------------
and Ws(string) be Wss(dsp, string)
//----------------------------------------------------------------------------