;  PROGRAM:  SAK (Strike Any Key)
;  AUTHOR:  Richard Conn
;  VERSION:  2.0
;  DATE:  18 May 84
;  PREVIOUS VERSIONS:  1.0 (18 Apr 83)
vers    equ     20
z3env   SET     0f400h

;
;       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
;
;       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
;
       ext     z3init,wait1s,getcl1,qprint,qcrlf
       ext     strtzex,stopzex,putzex
       ext     pstr,print,condin,eval10,cout

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

;
; Environment Definition
;
       if      z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
       jmp     start
       db      'Z3ENV' ;This is a ZCPR3 Utility
       db      1       ;External Environment Descriptor
z3eadr:
       dw      z3env
start:
       lhld    z3eadr  ;pt to ZCPR3 environment
;
       else
;
; Internal ZCPR3 Environment Descriptor
;
       MACLIB  Z3BASE.LIB
       MACLIB  SYSENV.LIB
z3eadr:
       jmp     start
       SYSENV
start:
       lxi     h,z3eadr        ;pt to ZCPR3 environment
       endif

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

;  Init Options and Parse and Interpret Command Line
;
       xra     a       ;turn options off
       sta     mpflag  ;turn off message printed flag
       sta     bell    ;turn off bell
       sta     delay   ;turn off delay (pause)
       sta     delay+1
       mvi     a,0ffh  ;turn options on
       sta     abortf  ;turn on abort
       lxi     h,tbuff+1       ;pt to command line
spskp:
       mov     a,m     ;skip leading spaces
       inx     h
       cpi     ' '
       jz      spskp
       dcx     h       ;pt to char
       cpi     '/'     ;option?
       jnz     optdone
       inx     h       ;skip option char
opt:
       mov     a,m     ;get option letter
       ora     a       ;done?
       jz      optdone
       inx     h       ;pt to next
       cpi     ' '     ;process text
       jz      optdone
       cpi     'A'     ;abort?
       jz      optabort
       cpi     'B'     ;bell?
       jz      optbell
       cpi     'P'     ;pause?
       jz      optpause
       call    print
       db      'SAK, Version '
       db      (vers/10)+'0','.',(vers mod 10)+'0'
       db      cr,lf,'Syntax:'
       db      cr,lf,'   SAK /o... text  -or-  SAK text'
       db      cr,lf,'Options:'
       db      cr,lf,' A     -- DO NOT Allow the User to Abort'
       db      cr,lf,' B     -- Ring the Bell'
       db      cr,lf,' Pnnnn -- Pause nnnn seconds and then resume'
       db      0
       ret
;
;  Process A option (Abort MCL)
;
optabort:
       xra     a       ;turn off abort
       sta     abortf
       jmp     opt
;
;  Process B option (Ring Bell)
;
optbell:
       mvi     a,0ffh  ;turn on bell
       sta     bell
       jmp     opt
;
;  Process Pnnnn option (Pause nnnn seconds)
;
optpause:
       call    eval10  ;convert argument to decimal value in DE
       xchg            ;HL contains value
       shld    delay
       xchg            ;HL pts to next char
       jmp     opt
;
;  Continue Command Processing
;
optdone:
       mov     a,m     ;any message?
       ora     a
       jz      optdn1
       sta     mpflag  ;set message printed flag
       call    print   ;new line
       db      '  --> ',0
       call    pstr    ;print message
       call    print
       db      ' <--  ',0
optdn1:
       call    stopzex ;suspend ZEX processing
       lhld    delay   ;get delay count in HL
;
;  Main Delay Loop
;
sakloop:
;
;  Ring Bell if Option Selected
;
       lda     bell    ;get flag
       ora     a       ;set zero flag
       cnz     bout    ;ring bell and delay
;
;  Get character if one is available
;
       call    condin  ;optionally get character
       jnz     gotchar ;process character
;
;  Loop if No Delay
;
       mov     a,h     ;check for no delay
       ora     l
       jz      sakloop
;
;  Delay and test for input
;
       call    wait1s  ;delay 1 sec
       dcx     h       ;count down
       mov     a,h     ;done?
       ora     l
       jnz     sakloop
;
;  Process Input Character
;       If no input and timout instead, A=0 for continuation character
;
gotchar:
       cpi     ctrlc   ;abort?
       jz      abort
resume:
       lda     mpflag  ;message printed?
       ora     a       ;0=no
       cnz     qcrlf   ;new line if yes
       call    qprint
       db      'Resuming ...',0
       jmp     strtzex ;resume ZEX processing
;
;  Abort Multiple Command Line if there is one
;
abort:
       lda     abortf  ;abort allowed?
       ora     a       ;0=no
       jz      resume
       call    getcl1  ;get address of command line buffer
       mov     a,h     ;any buffer?
       ora     l
       jz      abort1
       mov     e,m     ;get address of next char
       inx     h
       mov     d,m
       xchg            ;HL pts to next char
       mvi     m,0     ;set no further command
abort1:
       lda     mpflag  ;message printed?
       ora     a       ;0=no
       cnz     qcrlf   ;new line if yes
       call    qprint
       db      'Aborting ...',0
       jmp     strtzex ;resume ZEX processing
;
;  Ring Bell and Delay Briefly
;
bout:
       mvi     a,ctrlg ;ring bell
       call    cout
       push    h       ;save HL
       lhld    delay   ;do not delay if pause already invoked
       mov     a,h     ;zero delay?
       ora     l
       jnz     bout1   ;skip delay
       call    wait1s  ;delay
bout1:
       pop     h
       ret

;
;  Other Buffers
;
abortf:
       ds      1       ;abort flag
bell:
       ds      1       ;bell flag
delay:
       ds      2       ;delay constant
mpflag:
       ds      1       ;message printed flag

       end