;
; Program: ERROR2
; Author: Richard Conn
; Version: 1.0
; Date: 5 Mar 84
;
version equ     10

;
;       This error handler displays the error line to the user and
; provides him with four options as to how to process this line:
;               1. Replace the command in error with a new command
;               2. Skip the command in error and resume execution
;                       with the next command
;               3. Replace the command line as it now stands
;               4. Throw away the command line and resume user
;                       control
;
;       Unlike ERROR1, ERROR2 is screen-oriented, using the Z3TCAP
; for support.
;
;       This program is transportable from one ZCPR3 system to another
; provided it is reassembled with the correct address for the ZCPR3
; Environment Descriptor (Z3ENV) or DDT is used to patch this address
; (which is the first two bytes after the opening JMP).  If an external
; ZCPR3 Environment Descriptor is not available, one will have to be
; provided by setting the Z3ENV equate to 0 and providing SYSENV.LIB in
; the current directory at assembly time.
;

;
; Equates for Key Values
;
z3env   SET     0f400h  ;address of ZCPR3 environment
cmtch   equ     ';'     ;comment character
cr      equ     0dh
lf      equ     0ah

;
; External Z3LIB and SYSLIB Routines
;
       ext     z3vinit
       ext     print,pstr,codend,capine,bbline,crlf,moveb
       ext     erradr,puter1,puterc            ;Error Handler Routines
       ext     qprint                          ;Quiet Mode Prints
       ext     getenv,getefcb,getcl1,qerror    ;Z3 Messages et al
       ext     at,cls,stndout,stndend,gotoxy,vprint,gxymsg     ;VLIB Routines

;
; 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    z3vinit ;initialize the ZCPR3 Environment
;
; Print Banner
;
       call    qprint
       db      'ERROR2, Version '
       db      (version/10)+'0','.',(version mod 10)+'0'
       db      cr,lf,0
;
; Determine if Program Invoked as an Error Handler or By the User
;
       call    qerror  ;error?
       jz      handler ;handle error
;
; Invoked by the User, so Install as an Error Handler
;
       call    getenv          ;must have a Z3TCAP entry
       lxi     d,80h           ;pt to Z3TCAP
       dad     d
       mov     a,m             ;must not be space or less
       cpi     ' '+1
       jnc     start0
       call    print
       db      cr,lf,' No Z3TCAP - Aborting',0
       ret
;
; Determine Name of Routine
;
start0:
       call    getefcb         ;pt to external FCB
       jz      start1          ;proceed if external FCB not available
;
; Make Name Invoked by User the Name of the Error Handler
;
       inx     h               ;pt to first char
       lxi     d,ername        ;pt to name of error handler message
       mvi     b,8             ;at most 8 bytes
       call    moveb           ;copy into buffer
;
; Make Command Line in Buffer the Error Handler
;
start1:
       lxi     h,ername        ;make name in buffer the error handler
       call    puterc          ;set command
       mvi     a,0ffh          ;set error code
       call    puter1          ;set message
       call    print
       db      ' Error Handler Installed',0
       ret
;
; Handle Error
;
handler:
       call    erradr          ;get address of error line
       xchg                    ;HL pts to free area, DE pts to error line
       call    codend          ;get ptr to free area
       shld    badcmd          ;save ptr to bad command
;
; Extract Bad Command and Store It in Memory Starting at BADCMD
;       DE pts to bad command, HL pts to location to store it at
;
savebad:
       ldax    d               ;get next char
       mov     m,a             ;put it
       ora     a               ;done?
       jz      sbad1
       cpi     cmtch           ;check for comment
       jz      sbad1
       inx     h               ;pt to next
       inx     d
       jmp     savebad
;
; Set ending 0 in bad command buffer and check for continuation
;
sbad1:
       mvi     m,0             ;store ending zero
       inx     h               ;pt to next
       cpi     cmtch           ;more?
       jnz     sbad2
       inx     d               ;pt to rest of command
sbad2:
       shld    restcmd         ;save rest of command line
;
; Extract Rest of Command Line and Store It in Memory Starting at RESTCMD
;
saverest:
       ldax    d               ;get next
       mov     m,a             ;put it
       inx     h               ;pt to next
       inx     d
       ora     a               ;done?
       jnz     saverest
       shld    scratch         ;save ptr to scratch area
;
; Prompt User for Action
;
prompt:
       call    cls     ;clear screen
       call    gxymsg
       db      3,22
       db      '>>>> ',1,'VIDEO ERROR HANDLER',2,' <<<<',0
       call    gxymsg
       db      5,28
       db      '-- Error  Line --',0
       call    at
       db      6,10
       call    stndout ;reverse video
       call    erradr          ;get address of error line
       call    pstr
       call    stndend ;normal video
       mvi     h,10    ;position cursor
       mvi     l,15
       shld    infoxy
       call    gxymsg
       db      8,30
       db      '-- Options --',0
       call    atinfo
       call    vprint
       db      '1. Replace Command in Error with a New Command',0
       call    atinfo
       call    vprint
       db      '   Replace ',1,0
       lhld    badcmd
       call    pstr
       call    atinfo
       call    atinfo
       call    vprint
       db      2,'2. Advance to Next Command and Resume Processing',0
       call    atinfo
       call    vprint
       db      '   Advance to ',1,0
       lhld    restcmd
       call    pstr
       call    atinfo
       call    atinfo
       call    vprint
       db      2,'3. Replace Entire Line with a New Line',0
       call    atinfo
       call    vprint
       db      '   Replace ',1,0
       call    erradr          ;pt to error line
       call    pstr
       call    atinfo
       call    atinfo
       call    vprint
       db      2,'4. Throw Away Entire Line and Continue',0
       call    atinfo
       call    vprint
       db      '   Throw Away ',1,0
       call    erradr          ;pt to error line
       call    pstr
       call    stndend
userin:
       call    gxymsg
       db      22,20
       db      'Select Option - ',0
       call    capine
       cpi     '1'     ;option 1
       jz      replace ;replace command in error
       cpi     '2'     ;option 2
       jz      advance ;advance to next command
       cpi     '3'     ;option 3
       jz      newline ;enter new line
       cpi     '4'     ;option 4
       jz      flush   ;throw away line
       call    print
       db      8,'  Invalid Option - Retry',0  ;backspace over error
       jmp     userin
;
; Position at INFOXY and advance ptr to next line
;
atinfo:
       lhld    infoxy  ;pt to next position
       call    gotoxy  ;go there
       inr     h       ;next line
       shld    infoxy
       ret
;
; Replace Command in Error
;
replace:
       call    print
       db      '   Replacement Command?',cr,lf,'  ',0
       lhld    restcmd ;pt to rest of command line in DE
       xchg
       mvi     a,0ffh  ;capitalize
       call    bbline  ;get line from user
       call    build   ;build and run command
       jmp     prompt  ;continue if error
;
; Advance to Rest of Command Line
;
advance:
       lhld    restcmd ;pt to it
       xchg
       lxi     h,empty ;HL pts to empty command, DE pts to tail
       call    build   ;build and run command
       jmp     prompt  ;continue if error
;
; Enter New Line
;
newline:
       call    print
       db      '   New Command?',cr,lf,'  ',0
       mvi     a,0ffh  ;capitalize
       call    bbline  ;get line from user
       lxi     d,empty ;HL pts to user command, DE pts to empty command
       call    build   ;build and run command
       jmp     prompt  ;continue if error
;
; Flush Commands
;
flush:
       ret             ;simply exit if no more commands
;
; Build New Command Line in SCRATCH Area and Run it by returning to ZCPR3
;   On input, HL pts to header, DE pts to tail
;
build:
       lxi     b,1     ;set char count (1 for ending zero)
       push    d       ;save ptr to tail
       push    h       ;save ptr to header
       lhld    scratch ;pt to scratch area
       pop     d       ;get ptr to header
       ldax    d       ;get first char
       ora     a       ;any there?
       cnz     copy    ;copy line into buffer
       pop     d       ;get ptr to tail
       ldax    d       ;anything there?
       ora     a
       jz      bldt    ;terminate build if not
       mvi     m,cmtch ;begin with semicolon
       inx     h       ;pt to next
       call    copy
bldt:
       mvi     m,0     ;store ending zero
;
; Store Command Line into MCL Buffer
;
       call    getcl1  ;pt to command line
       cmp     c       ;check for char count within range
       rc
       mov     a,b     ;check for line too long
       ora     a       ;line too long?
       rnz             ;error if so
       lxi     d,4     ;pt to first char
       push    h       ;save ptr to current
       dad     d
       pop     d       ;get ptr to current
       xchg            ;DE pts to first char position, HL pts to CL buffer
       mov     m,e     ;set address to resume processing
       inx     h
       mov     m,d
       lhld    scratch         ;pt to new line
       xchg                    ;in DE, while HL pts to first char position
       call    copy            ;copy it
       mov     m,a             ;store ending zero
       pop     d               ;clear stack
       ret                     ;resume processing
;
; Copy string pted to by DE into buffer pted to by HL
;
copy:
       ldax    d       ;get next char
       ora     a       ;done?
       rz
       mov     m,a     ;store it
       inx     b       ;increment count
       inx     h       ;pt to next
       inx     d
       jmp     copy
;
; Buffers
;
ername:
       db      'ERROR2  ',0    ;name of error handler
empty:
       db      0       ;empty command line
infoxy:
       ds      2       ;xy-coordinate for display
badcmd:
       ds      2       ;ptr to bad command extracted
restcmd:
       ds      2       ;ptr to tail of bad command line
scratch:
       ds      2       ;ptr to scratch area used to build new lines

       end