// CmdScanDisplay.bcpl -- Alto display dependent portion of
//			command scanner package
// Copyright Xerox Corporation 1979, 1980

//	Last modified February 28, 1980  7:47 PM by Taft

get "cmdscan.decl"
get "AltoDefs.d"

external
[
//outgoing procedures
DefErase; DefError; DefBreak; DefEcho; CmdError; InvertWindow

//incoming procedures
CharWidth; GetBitPos; GetLmarg; EraseBits
Puts; Resets; Wss; SysErr
CurrentPhrase; BackupPhrase; Dismiss
]


//---------------------------------------------------------------------------
let DefErase(cs, first, last, context) be
//---------------------------------------------------------------------------
[
let ds = cs>>CS.dspS
let bits = 0
for i = first to last do
   [
   let char = cs>>CS.buf>>Buf↑i
   if char ls #200 then
      [
      if char eq $*n then [ bits = 9999; break ]
      bits = bits + (char ge #40? CharWidth(ds, char),
       CharWidth(ds, $↑)+CharWidth(ds, char+#100))
      ]
   ]
test bits le GetBitPos(ds)-GetLmarg(ds)
   ifso EraseBits(ds, -bits)
   ifnot
      [  //erasing past left margin
      Resets(ds)
      for i = 0 to first-1 do
         if cs>>CS.buf>>Buf↑i ls #200 then Puts(ds, cs>>CS.buf>>Buf↑i)
      ]
]


//---------------------------------------------------------------------------
and DefBreak(cs, char) = char eq $*n % char eq $*s % char eq $*033
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
and DefEcho(cs, char) = not CurrentPhrase(cs)>>PD.PhraseTerminator(cs, char)
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
and DefError(cs, ec) be
//---------------------------------------------------------------------------
[
cs>>CS.errorCode = ec
switchon ec into
   [
   case ecCmdDelete:
      Wss(cs>>CS.dspS, " XXX")  //fall into next case
   case ecCmdDestroy:
      [ cs>>CS.destroy = true; BackupPhrase(cs, cs>>CS.iPhOut) ]
   case ecCmdTooLong:  //just blink window and do nothing
      [ CmdError(cs); endcase ]
   case ecKeyAmbiguous:
   case ecBackupAppend:
      [ CmdError(cs); BackupPhrase(cs, 0, editAppend) ]
   case ecTooManyPhrases:
   case ecEndOfPhrase:
      SysErr(cs, ec)
   default:  //all types of syntax errors get same handling
      CmdError(cs, " ?")  //fall into next case
   case ecBackupReplace:
      BackupPhrase(cs)
   ]
]


//---------------------------------------------------------------------------
and CmdError(cs, string; numargs na) be
//---------------------------------------------------------------------------
//Displays string if present, blinks display window, and resets keyboard
[
if na gr 1 & string ne 0 then Wss(cs, string)
InvertWindow(cs>>CS.dspS)
Dismiss(50)
InvertWindow(cs>>CS.dspS)
Resets(cs>>CS.keyS)
]


//---------------------------------------------------------------------------
and InvertWindow(ds) be
//---------------------------------------------------------------------------
[
let dcb = ds>>DS.fdcb
   [
   dcb>>DCB.background = not dcb>>DCB.background
   if dcb eq ds>>DS.ldcb then break
   dcb = dcb>>DCB.next
   ] repeat
]