;  PROGRAM:  SAK (Strike Any Key)
;  AUTHOR:  Richard Conn
;  VERSION:  2.2
;  DATE:  1 October 85
;  PREVIOUS VERSIONS:  1.0 (18 Apr 83), 2.0 (18 May 84), 2.1 (8 June 85)

; Version 22a - added screen highlighting to built-in help msg.
;                                21 August 1986 - Frank Gaude'

vers    equ     22      ; Changed to allow the BIOS to return from
                       ; CONIN: with the zero flag set.  CONDIN:
                       ; subroutine in SYSLIB assumes, incorrectly,
                       ; this flag will always be non-zero.
                       ;        Joe Wright  21 September 1985
                       ;        program updated by Ken Davidson
z3env   set     0fe00h

;
;       SAK (Strike Any Key) is used for the following purposes:
;               1) to wait for user interaction before continuing
;                       and to allow the user to abort a Multiple
;                       Command Line
;               2) to command the user's attention by ringing the
;                       bell at his console
;               3) abort ZEX command file in execution (2.1 - RLC)
;
;       The SAK command line is:
;               SAK o...
;       SAK is invoked with the following options:
;               A     -- DO NOT Allow the User to Abort MCL
;               B     -- Ring Bell
;               Pnnnn -- Pause nnnn seconds and continue if no
;                        response by that time
;               Z     -- Allow the User to Abort ZEX
;
       ext     z3vinit,wait1s,getcl1,qprint,qcrlf
       ext     strtzex,stopzex,putzex,getznc,getzrun
       ext     pstr,print,vprint,cst,cin,eval10,cout

tbuff   equ     80h     ;command line buffer
cr      equ     0dh
lf      equ     0ah
ctrlc   equ     'C'-'@'
ctrlg   equ     'G'-'@'
dim     equ     1
bright  equ     2

;
; Environment Definition
;
       if      z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
       jp      start
       db      'Z3ENV' ;This is a ZCPR3 Utility
       db      1       ;External Environment Descriptor
z3eadr:
       dw      z3env
start:
       ld      hl,(z3eadr)     ;pt to ZCPR3 environment
;
       else
;
; Internal ZCPR3 Environment Descriptor
;
       MACLIB  Z3BASE.LIB
       MACLIB  SYSENV.LIB
z3eadr:
       jp      start
       SYSENV
start:
       ld      hl,z3eadr       ;pt to ZCPR3 environment
       endif

;
; Start of Program -- Initialize ZCPR3 Environment
;
       call    z3vinit ;initialize the ZCPR3 Env and the VLIB Env

;  Init Options and Parse and Interpret Command Line
;
       xor     a       ;turn options off
       ld      (mpflag),a      ;turn off message printed flag
       ld      (bell),a        ;turn off bell
       ld      (delay),a       ;turn off delay (pause)
       ld      (delay+1),a
       ld      (stopz),a       ;(2.1 - RLC) do not abort ZEX
       ld      a,0ffh          ;turn options on
       ld      (abortf),a      ;turn on abort
       ld      hl,tbuff+1      ;pt to command line
spskp:
       ld      a,(hl)  ;skip leading spaces
       inc     hl
       cp      ' '
       jp      z,spskp
       dec     hl      ;pt to char
       cp      '/'     ;option?
       jp      nz,optdone
       inc     hl      ;skip option char
opt:
       ld      a,(hl)  ;get option letter
       or      a       ;done?
       jp      z,optdone
       inc     hl      ;pt to next
       cp      ' '     ;process text
       jp      z,optdone
       cp      'A'     ;abort?
       jp      z,optabort
       cp      'B'     ;bell?
       jp      z,optbell
       cp      'P'     ;pause?
       jp      z,optpause
       cp      'Z'     ;(2.1 - RLC) ZEX abort?
       jp      z,optzex
       call    vprint
       db      'SAK, Version ',[vers/10]+'0','.',[vers mod 10]+'0'
       db      cr,lf,dim,'Syntax:',bright,cr,lf
       db      '   SAK /o... text',dim,' -or- ',bright,'SAK text'
       db      cr,lf,dim,'Options:',bright,cr,lf
       db      ' A     -- ',dim,'DO NOT Allow Abort',bright,cr,lf
       db      ' B     -- ',dim,'Ring Bell',bright,cr,lf
       db      ' Pnnnn -- ',dim,'Pause',bright,' nnnn ',dim,'secs'
       db      bright,cr,lf
       db      ' Z     -- ',dim,'Allow to Abort ZEX',bright,cr,lf
       db      0
       ret

;
;  Process A option (Abort MCL)
;
optabort:
       xor     a       ;turn off abort
       ld      (abortf),a
       jp      opt
;
;  Process B option (Ring Bell)
;
optbell:
       ld      a,0ffh  ;turn on bell
       ld      (bell),a
       jp      opt
;
;  Process Pnnnn option (Pause nnnn seconds)
;
optpause:
       call    eval10  ;convert argument to decimal value in DE
       ex      de,hl           ;HL contains value
       ld      (delay),hl
       ex      de,hl           ;HL pts to next char
       jp      opt
;
;  (2.1 - RLC) Process Z option (Allow ZEX abort)
;
optzex:
       ld      a,0ffh  ;allow abort
       ld      (stopz),a
       jp      opt
;
;  Continue Command Processing
;
optdone:
       ld      a,(hl)  ;any message?
       or      a
       jp      z,optdn1
       ld      (mpflag),a      ;set message printed flag
       call    print   ;new line
       db      '  --> ',0
       call    pstr    ;print message
       call    print
       db      ' <--  ',0
optdn1:
       call    stopzex ;suspend ZEX processing
       ld      hl,(delay)      ;get delay count in HL
;
;  Main Delay Loop
;
sakloop:
;
;  Ring Bell if Option Selected
;
       ld      a,(bell)        ;get flag
       or      a       ;set zero flag
       call    nz,bout ;ring bell and delay
;
;  Get character if one is available
;
;       call    condin  ;optionally get character
;       jp      nz,gotchar      ;process character
;
;  This change in case the BIOS CONIN: returns with zero flag set.
;
       call    cst
       jr      nz,nochar
getchar:
       call    cin
       jp      gotchar
nochar:

;  Loop if No Delay
;
       ld      a,h     ;check for no delay
       or      l
       jp      z,sakloop
;
;  Delay and test for input
;
       call    wait1s  ;delay 1 sec
       dec     hl      ;count down
       ld      a,h     ;done?
       or      l
       jp      nz,sakloop
;
;  Process Input Character
;       If no input and timout instead, A=0 for continuation character
;
gotchar:
       cp      ctrlc   ;abort?
       jp      z,abort
resume:
       ld      a,(mpflag)      ;message printed?
       or      a       ;0=no
       call    nz,qcrlf        ;new line if yes
       call    qprint
       db      'Resuming ...',0
       jp      strtzex ;resume ZEX processing
;
;  Abort Multiple Command Line if there is one
;
abort:
       ld      a,(abortf)      ;abort allowed?
       or      a       ;0=no
       jp      z,resume
       call    getcl1  ;get address of command line buffer
       ld      a,h     ;any buffer?
       or      l
       jp      z,abort1
       ld      e,(hl)  ;get address of next char
       inc     hl
       ld      d,(hl)
       ex      de,hl           ;HL pts to next char
       ld      (hl),0  ;set no further command
abort1:
       ld      a,(mpflag)      ;message printed?
       or      a       ;0=no
       call    nz,qcrlf        ;new line if yes
       call    qprint
       db      'Aborting ...',0
       call    getzrun ;(2.1 - RLC) is ZEX running?
       ret     z               ;(2.1 - RLC) done if not
       call    strtzex ;(2.1 - RLC) resume ZEX processing
       ld      a,(stopz)       ;(2.1 - RLC) stop ZEX?
       or      a       ;(2.1 - RLC) 0=no
       ret     z               ;(2.1 - RLC) resume processing
       call    getznc  ;(2.1 - RLC) get next ZEX char
       ld      (hl),0ffh       ;(2.1 - RLC) store abort ZEX code
       ret

;
;  Ring Bell and Delay Briefly
;
bout:
       ld      a,ctrlg ;ring bell
       call    cout
       push    hl      ;save HL
       ld      hl,(delay)      ;do not delay if pause already invoked
       ld      a,h     ;zero delay?
       or      l
       jp      nz,bout1        ;skip delay
       call    wait1s  ;delay
bout1:
       pop     hl
       ret

;
;  Other Buffers
;
abortf:
       ds      1       ;abort flag
bell:
       ds      1       ;bell flag
delay:
       ds      2       ;delay constant
mpflag:
       ds      1       ;message printed flag
stopz:
       ds      1       ;(2.1 - RLC) stop ZEX flag

       end
l flag
delay:
       ds      2       ;delay constant
mpflag:
       ds      1       ;message printed flag
stopz:
       ds      1       ;(2.1 - RLC) stop ZEX flag

       e