home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / ZCPR33 / Z3-33 / Z33VER10.LBR / Z33VER10.ZZ0 / Z33VER10.Z80
Text File  |  2000-06-30  |  38KB  |  1,691 lines

  1. ; PROGRAM:    Z33VERR
  2. ; DATE:     Oct 10,1987
  3. ; VERSION:    1.0
  4.  
  5. ; Version 1.0
  6. ; This version fixes a bug which caused the screen to be cleared
  7. ; any time the program was invoked. I also now make Z33VERR look
  8. ; at the quiet flag before printing it's install message. There
  9. ; is also a new command line parameter 'S' which will inhibit
  10. ; the initial screen clear when an error is detected. Also added
  11. ; <CR> as an alias to 'E'dit, <ESC> as an alias to 'A'bort, and
  12. ; <SP> as an alias to 'C'ontinue.
  13.  
  14. ; Version 0.9
  15. ; This version fixes a long standing bug in VERROR which causes the
  16. ; error command to be repeated if you answer no the 'Do you wish to
  17. ; edit this command ?' question when the shell stack is not empty.
  18. ; Thanks to Jay Sage for Z33ERROR & Paul Pomerleau for VERROR.
  19. ; Without the work of these authors, this program would not exist.
  20. ; Also thanks to Rick Charnes for proding me to fix the shell bug.
  21. ;
  22. ;                        Royce Shofner
  23.  
  24. ; Version 0.8
  25. ; This program combines the ZCPR33 prototype error handler (Z33ERR07)
  26. ; with VERR17A to produce an inteligent error handler for systems using
  27. ; ZCPR33. The internal command line modification routines in Z33ERR07
  28. ; have been removed & replaced with the entire VERR17A program. The only
  29. ; other changes made to Z33ERR07 is in the submit file delete routine. I
  30. ; added a test to inform the user in case the submit file could not be
  31. ; deleted (possibly because the system vectors had been modified & ZCPR33
  32. ; couldn't be found).
  33. ;
  34. ;                        Royce Shofner
  35.  
  36. ;=============================================================================
  37. ;
  38. ;    This section of code is derived from Z33ERR07
  39. ;
  40. ;=============================================================================
  41.  
  42. ;=============================================================================
  43. ;
  44. ;        D E F I N I T I O N S     S E C T I O N
  45. ;
  46. ;=============================================================================
  47.  
  48. version    equ    10
  49.  
  50. no    equ    0
  51. yes    equ    not no
  52.  
  53. bell1    equ    yes        ; Beep at user on entering error handler
  54. bell2    equ    yes        ; Beep at user on extra prompts (ZEX/SUBMIT)
  55.  
  56. cls1    equ    yes        ; Clear screen when error is detected
  57.  
  58. cret    equ    0dh
  59. lf    equ    0ah
  60. bell    equ    07h
  61. tab    equ    09h
  62. esc    equ    1bh
  63.  
  64. bdos    equ    0005h
  65. bios    equ    0000h
  66.  
  67. fcb1    equ    005ch
  68.  
  69. ; Z33LIB references
  70.  
  71.     extrn    qerror,getccp,getsrun,haltsub,z33chk
  72.     extrn    gcmddu,geter3,subon
  73.  
  74. ; Standard library references
  75.  
  76.     extrn    z3init
  77.     extrn    getefcb,getcst,putcst,geterc,getwhl,erradr,getcl1
  78.     extrn    cout,print,pstr,crlf,qprint,qpstr
  79.     extrn    mafdc,pafdc
  80.     extrn    getzrun,haltzex
  81.     extrn    capin,bline
  82.     extrn    acase1
  83.     extrn    getquiet
  84.     extrn    codend
  85.  
  86. ;=============================================================================
  87. ;
  88. ;        S T A N D A R D    P R O G R A M    H E A D E R
  89. ;
  90. ;=============================================================================
  91.  
  92.     cseg
  93.  
  94. entry:
  95.     jp    start
  96.     defb    'Z3ENV'
  97.     defb    3        ; Type-3 environment
  98. envaddr:
  99.     dw    0
  100.     dw    entry
  101.     defb    version
  102.  
  103. ;=============================================================================
  104. ;
  105. ;        C O N F I G U R A T I O N    A R E A
  106. ;
  107. ;=============================================================================
  108.  
  109. ; Allow bell to sound on error
  110.  
  111.     defb    'BEEPS'
  112. bell1fl:
  113.     defb    bell1
  114. bell2fl:
  115.     defb    bell2
  116.  
  117.     defb    'CLS'
  118. clsflg:
  119.     defb    cls1
  120.  
  121.     defb    'END'
  122.  
  123. ;=============================================================================
  124. ;
  125. ;        M A I N    C O D E    S E C T I O N
  126. ;
  127. ;=============================================================================
  128.  
  129. start:
  130.     ld    hl,(envaddr)    ; Get environment address
  131.     call    z3init        ; Initialize library routines
  132.     call    z3vini        ; initialize vlib
  133.     call    tinit        ; initialize the terminal
  134.     jr    start1
  135. ; We really should set up our own local stack, but I am going to skip
  136. ; that for now.
  137. qbanner:
  138.     call    getquiet
  139.     ret    nz
  140. banner:
  141.     call    print        ; Display the program header
  142.     defb    cret,lf
  143.     defb    ' Z33VERR Version '
  144.     defb    version    / 10 + '0'
  145.     defb    '.'
  146.     defb    version    mod 10 + '0'
  147.     defb    cret,lf,0
  148.     ret
  149.  
  150. start1:
  151.     ld    a,(fcb1+1)    ; Check for help request
  152.     cp    '/'
  153.     jr    z,help
  154.     cp    '?'
  155.     jr    nz,main
  156.  
  157. help:
  158.     call    banner
  159.     call    print
  160.     defb    cret,lf
  161.     defb    ' Syntax: ',0
  162.     call    name
  163.     call    print
  164.     defb    ' [Q][S]',cret,lf
  165.     defb    tab,'[Q]....quiet option (no bells)',cret,lf
  166.     defb    tab,'[S]....inhibit initial clearScreen',cret,lf,0
  167.     ret
  168.  
  169. main:
  170.     call    qerror        ; See if error handler invocation
  171.     jp    z,errorh    ; If so, branch to error processing
  172.     call    qbanner        ; Print install message if not quiet
  173.  
  174. ;=============================================================================
  175. ;
  176. ;        I N S T A L L A T I O N    C O D E
  177. ;
  178. ;=============================================================================
  179.  
  180. ; Program was invoked manually, so we need to set it up as the error handler.
  181.  
  182. ;----------------------------------------
  183.  
  184. ; Subtask 1 -- determine whether to use a DU, a DIR, or no prefix
  185. ;
  186. ; The program can examine the ZCPR33 option bytes to determine what features
  187. ; are supported (DU and/or DIR forms, which one first, wheel control over DU
  188. ; use, etc.).  For now I will just assume that a DU prefix will be used and
  189. ; will omit coding this block.
  190.  
  191. job1:
  192.  
  193. ;----------------------------------------
  194.  
  195. ; Subtask 2 -- build error handling command line including directory prefix
  196. ; using data from the external FCB.  We use the fact that the drive and user
  197. ; where the program was actually found along the path are stored in the
  198. ; command file control block.  The user number is kept in the usual place;
  199. ; the drive is kept in the following byte.  The drive is in the range 1..16
  200. ; (unless the command is resident, in which case the drive byte is 0).
  201.  
  202. job2:
  203.     call    gcmddu        ; See if we were invoked by GO or JUMP
  204.     inc    b        ; Shift drive back to range 1..16
  205.     jr    nz,job2a    ; If we were not, branch ahead
  206.  
  207.     call    qprint        ; If drive = 0, we have a resident command
  208.     defb    bell,' Cannot be installed using GO or JUMP',cret,lf,0
  209.     ret
  210.  
  211. job2a:
  212.     call    geterc        ; Get address of error command line
  213.     ex    de,hl        ; ..into DE
  214.  
  215.     call    z33chk        ; Make sure we have ZCPR33
  216.     jr    nz,job2b    ; Branch if not
  217.  
  218. ; If ZCPR33, use information in external command FCB to determine drive and
  219. ; user number where the file was found.
  220.  
  221.     call    gcmddu        ; Set BC to directory where program was found
  222.     ld    a,b        ; Work on drive first
  223.     add    a,'A'        ; Convert it to a letter
  224.     ld    (de),a        ; Save in error command line
  225.     inc    de        ; Increment command line pointer
  226.  
  227.     ld    a,c        ; Work on user number next
  228.     call    mafdc        ; Convert it to decimal number in command line
  229.  
  230.     ld    a,':'        ; Put in the colon
  231.     ld    (de),a
  232.     inc    de
  233.  
  234. job2b:
  235.     call    getefcb        ; Get pointer to name of this program
  236.     inc    hl
  237.     ld    bc,8        ; Copy 8 characters of name
  238.     ldir            ; ..into error command line
  239.  
  240.     ld    a,' '        ; Add a space
  241.     ld    (de),a
  242.     inc    de
  243.  
  244.     ld    a,(fcb1+1)    ; Copy any option character(s) on command line
  245.     ld    (de),a
  246.     inc    de
  247.     ld    a,(fcb1+2)
  248.     ld    (de),a
  249.     inc    de
  250.     xor    a        ; Store terminating null
  251.     ld    (de),a
  252.  
  253. ;----------------------------------------
  254.  
  255. ; Subtask 3 -- Report installation to the user
  256.  
  257. job3:
  258.     call    qprint
  259.     defb    ' Error handling command line set to: ',0
  260.  
  261.     call    geterc        ; Get pointer to error command line
  262.     call    qpstr        ; Print the string there
  263.     call    getquiet
  264.     ret    nz
  265.     jp    crlf        ; One extra line and quit
  266.  
  267.  
  268. ;=============================================================================
  269. ;
  270. ;        E R R O R    H A N D L I N G    C O D E
  271. ;
  272. ;=============================================================================
  273.  
  274. ; This is the main entry point for error handling
  275.  
  276. errorh:
  277.  
  278. ;----------------------------------------
  279.  
  280. ; Subtask 1 -- Display program signon message and determine whether Z33 is
  281. ; running or not.  Check for the 'Q' (quiet) command line option.  Optionally
  282. ; beep the bell. Also test for the 'S' (clearScreen) command line option and
  283. ; clear screen if indicated.
  284.  
  285. task1:
  286.     ld    a,(fcb1+1)    ; Get any option character
  287.     call    task1a        ; test for 'Q'
  288.     jr    z,task1b
  289.     ld    a,(fcb1+2)
  290.     call    task1a
  291.     jr    task1b
  292.  
  293. task1a:
  294.     cp    'Q'        ; If not quiet option, skip ahead
  295.     ret    nz
  296.  
  297.     ld    hl,0        ; Clear the bell flags
  298.     ld    (bell1fl),hl
  299.     ret
  300.  
  301. task1b:
  302.     ld    a,(bell1fl)
  303.     call    beep
  304.  
  305. task1c:
  306.     ld    a,(fcb1+1)    ; Get any option character
  307.     call    task1d        ; test for 'S'
  308.     jr    z,task1e
  309.     ld    a,(fcb1+2)
  310.     call    task1d
  311.     jr    task1e
  312.  
  313. task1d:
  314.     cp    'S'        ; If not cls option, skip ahead
  315.     ret    nz
  316.  
  317.     xor    a        ; reset the clear screen flag
  318.     ld    (clsflg),a
  319.     ret
  320.  
  321. task1e:
  322.     ld    a,(clsflg)    ; clear screen ?
  323.     or    a
  324.     call    nz,cls        ; if not 'S' option
  325.     call    banner        ; tell who we are
  326.  
  327. ;----------------------------------------
  328.  
  329. ; Subtask 2 -- Display system status
  330.  
  331. ; This task checks to see if there is anything about the system status that
  332. ; might be useful to the user in determining the cause of the error.
  333. ; Specifically, if either ZEX or SUBMIT is running or if the wheel byte is off,
  334. ; the user is given this information.  If not, there is no output.
  335.  
  336. task2:
  337.     call    z33chk        ; Check for ZCPR33 running
  338.     jp    nz,task4    ; If not, show only the bad command line
  339.  
  340.     call    getzrun        ; See if there is anything interesting
  341.     jr    nz,task2a    ; ..to report (ZEX or SUBMIT running or
  342.     call    getsrun        ; ..wheel byte off)
  343.     jr    nz,task2a
  344.     call    getwhl
  345.     jr    nz,task3    ; If none of above, on to task3
  346.  
  347. task2a:
  348.     call    print
  349.     defb    ' Status:    ',0
  350.  
  351.     call    getzrun        ; Find out if ZEX is running
  352.     jr    z,task2b    ; Skip ahead if not
  353.     call    print
  354.     defb    '    ZEX running',0
  355.  
  356. task2b:
  357.     call    getsrun        ; Find out if SUBMIT is running
  358.     jr    z,task2c    ; Skip ahead if not
  359.     call    print
  360.     defb    '    SUBMIT running',0
  361.  
  362. task2c:
  363.     call    getwhl        ; Find out if wheel is off
  364.     jr    nz,task2d    ; If not, on to task3
  365.     call    print
  366.     defb    '    WHEEL OFF',0
  367.  
  368. task2d:
  369.     call    crlf        ; End the line
  370.  
  371. ;----------------------------------------
  372.  
  373. ; Subtask 3 -- Display information about the type of error: error number,
  374. ; internal or external, and description.
  375.  
  376. task3:
  377.     call    print
  378.     defb    ' Error Type:',tab,0
  379.  
  380.     call    getcst        ; Get command status flag
  381.     bit    3,a        ; See if external command bit is set
  382.     jr    nz,task3a    ; Branch if external error
  383.  
  384.     call    print
  385.     defb    'CPR/ECP: (#',0
  386.     jr    task3b
  387.  
  388. task3a:
  389.     call    print
  390.     defb    'External: (#',0
  391.  
  392. task3b:
  393.     call    getcst        ; Get the command status flag
  394.     res    1,a        ; ..and clear the error
  395.     res    2,a        ; ..and ECP bits
  396.     call    putcst        ; Store the modified value
  397.  
  398.     call    geter3        ; Get the command error code
  399.     call    pafdc        ; Display the number
  400.     call    print
  401.     defb    ') ',0
  402.  
  403.     ld    hl,task3c    ; Set up return address
  404.     push    hl        ; ..on stack
  405.     call    geter3        ; Get command error code again
  406.     call    acase1        ; CASE function
  407.     defb    11        ; Eleven cases
  408.     defw    unknown        ; Default case
  409.  
  410.     defb    1
  411.     defw    duchange    ; Illegal attempt to change directory
  412.  
  413.     defb    2
  414.     defw    baddu        ; Invalid directory
  415.  
  416.     defb    3
  417.     defw    badpw        ; Incorrect password
  418.  
  419.     defb    5
  420.     defw    badform        ; Bad command form (wild or type given)
  421.  
  422.     defb    6
  423.     defw    badecp        ; Command not found by CPR or ECP
  424.  
  425.     defb    7
  426.     defw    badcmd        ; Command file not found by CPR
  427.  
  428.     defb    8
  429.     defw    ambig        ; Ambiguous file spec
  430.  
  431.     defb    9
  432.     defw    badnum        ; Bad numerical value
  433.  
  434.     defb    10
  435.     defw    nofile        ; Object file not found
  436.  
  437.     defb    11
  438.     defw    diskfull    ; Disk is full
  439.  
  440.     defb    12
  441.     defw    tpafull        ; TPA overflow
  442.  
  443. duchange:
  444.     call    print
  445.     defb    'Illegal attempt to change directory',0
  446.     ret
  447.  
  448. baddu:
  449.     call    print
  450.     defb    'Invalid directory specification',0
  451.     ret
  452.  
  453. badpw:
  454.     call    print
  455.     defb    'Incorrect password',0
  456.     ret
  457.  
  458. badform:
  459.     call    print
  460.     defb    'Bad command form (file type / wild card)',0
  461.     ret
  462.  
  463. badecp:
  464.     call    print
  465.     defb    'Command not found by CCP or ECP',0
  466.     ret
  467.  
  468. badcmd:
  469.     call    print
  470.     defb    'Requested load file not found',0
  471.     ret
  472.  
  473. ambig:
  474.     call    print
  475.     defb    'Ambiguous or missing file name',0
  476.     ret
  477.  
  478. badnum:
  479.     call    print
  480.     defb    'Bad numerical expression',0
  481.     ret
  482.  
  483. nofile:
  484.     call    print
  485.     defb    'Requested operand file not found',0
  486.     ret
  487.  
  488. diskfull:
  489.     call    print
  490.     defb    'Disk full',0
  491.     ret
  492.  
  493. tpafull:
  494.     call    print
  495.     defb    'TPA full (program too big)',0
  496.     ret
  497.  
  498. unknown:
  499.     call    print
  500.     defb    'Unknown error type',0
  501.     ret
  502.  
  503. task3c:
  504.     call    crlf        ; End the line
  505.  
  506. ;----------------------------------------
  507.  
  508. ; Subtask 4 -- Display bad command line
  509. ;
  510. ; In the final code, much more elaborate error processing would be performed
  511. ; here (or more likely, the code here will be used as a framework for existing
  512. ; error handlers).
  513.  
  514. task4:
  515.     call    print
  516.     defb    ' Bad Command:',tab,0
  517.  
  518.     call    erradr        ; Get pointer to bad command line
  519.     push    hl        ; Save for reuse below
  520.  
  521. scan:                ; Find end of this command
  522.     ld    a,(hl)
  523.     or    a        ; See if end of command line buffer
  524.     jr    z,task4a
  525.     cp    ';'        ; See if at command separator
  526.     jr    z,task4a
  527.     inc    hl        ; Point to next character
  528.     jr    scan        ; Continue scanning
  529.  
  530. task4a:
  531.     ld    (hl),0        ; Mark end of string
  532.     ld    (delimptr),hl    ; Save ptr to bad command's delimiter
  533.     ld    (delim),a    ; Store delimiter
  534.     pop    hl        ; Restore pointer to beginning of command
  535.     push    af        ; Save delimiting character
  536.     call    pstr        ; Display the bad command
  537.  
  538.     push    hl        ; Save pointer to rest of command line
  539.     call    print
  540.     defb    cret,lf
  541.     defb    ' Rest of Line:',tab,0
  542.     pop    hl
  543.  
  544.     pop    af        ; Get back delimiter of bad command
  545.     or    a
  546.     jr    nz,task4b    ; Branch if there are more commands
  547.  
  548.     call    print
  549.     defb    'none',0
  550.     jr    task4c
  551.  
  552. task4b:
  553.     dec    hl        ; Pt back to bad command delimiter
  554.     ld    (hl),a        ; Put semicolon back
  555.     inc    hl
  556.     call    pstr        ; Print rest of command line
  557.  
  558. task4c:
  559.     call    crlf        ; End the line
  560.  
  561. ;----------------------------------------
  562.  
  563. ; Subtask 5 -- Deal with the bad command
  564.  
  565. ; This is where the real error handling is performed.  With normal command
  566. ; lines (ZEX and SUBMIT not running), the user has the following three basic
  567. ; choices: fix the bad command, skip the bad command, or abort the entire
  568. ; command line.  If ZEX is running, there is an additional choice that should
  569. ; be available: abort the entire ZEX script.  Similarly, if SUBMIT is running,
  570. ; the user must be given the option to abort the entire submit job.
  571. ; This code implements all of the above with the additional feature
  572. ; that if the bad command is the last on the line, the option to skip
  573. ; to next command is not presented as it would be meaningless.    Similarly, if
  574. ; neither ZEX nor SUBMIT is running and there are no pending commands, there
  575. ; is nothing the user can do, so the code just returns.
  576.  
  577. task5:
  578.     call    abort        ; test for ZEX and/or SUBMIT
  579.  
  580. task5a:
  581.     call    print
  582.     defb    cret,lf,' Your options:',tab
  583.     defb    "'E' or <CR>.....Edit command line"
  584.     defb    cret,lf,tab,tab
  585.     defb    "'A' or <ESC>....Abort entire command line",0
  586.     ld    a,(delim)    ; Get bad command delimiter
  587.     or    a
  588.     jr    z,task5b    ; No trailing commands; skip next option
  589.     call    print
  590.     defb    cret,lf,tab,tab
  591.     defb    "'C' or <SP>.....Continue with rest of command line",0
  592.  
  593. task5b:
  594.     call    print
  595.     defb    cret,lf,' Enter choice: ',0
  596.  
  597.     call    capin        ; get response
  598.     ld    b,a        ; Save for a moment
  599.     ld    a,(delim)    ; Get command delimiter again
  600.     or    a
  601.     ld    a,b        ; Response back in A
  602.     jr    z,task5c    ; Don't allow 's' choice if no trailing command
  603.     cp    'C'        ; Continue?
  604.     jr    z,skip
  605.     cp    ' '        ; <space> is alias for continue
  606.     jr    z,skip
  607.  
  608. task5c:
  609.     cp    'A'        ; Abort?
  610.     jp    z,abortmsg
  611.     cp    esc        ; Abort ?
  612.     jp    z,abortmsg
  613.     cp    'E'        ; Edit?
  614.     jp    z,verror
  615.     cp    cret        ; Edit?
  616.     jp    z,verror
  617.     call    print
  618.     defb    bell,0
  619.     jr    task5b
  620.  
  621. ;-----------------------------------------------------------------------------
  622.  
  623. ; Skip over bad command and resume with next in line
  624.  
  625. skip:
  626.     call    getcl1        ; Pt to command line buffer
  627.     ld    de,(delimptr)    ; DE pts to bad command's delimiter
  628.     inc    de        ; Now pointing to next command
  629.     ld    (hl),e        ; Stuff address in
  630.     inc    hl        ; ..first two bytes
  631.     ld    (hl),d        ; ..of multiple command line buffer
  632.  
  633.     call    print
  634.     defb    '  Continuing ...',cret,lf,0
  635.     ret            ; Resume command execution with next command
  636.  
  637. ;=============================================================================
  638.  
  639. ; Abort zex job and/or submit job
  640.  
  641. abort:
  642.     call    getzrun        ; See if ZEX is running
  643.     jr    z,abort2    ; Branch if not
  644.  
  645. ; Deal with running ZEX script
  646.  
  647.     ld    a,(bell2fl)
  648.     call    beep
  649.  
  650.     call    print
  651.     defb    ' Abort ZEX script (Y/N)? '
  652.     defb    0
  653.  
  654.     call    getyesno    ; Get user's answer
  655.     jr    nz,abort1    ; Branch if negative response
  656.  
  657.     call    haltzex        ; Abort ZEX
  658.     call    abortmsg
  659.     jr    abort2
  660.  
  661. abort1:
  662.     call    print
  663.     defb    ' No'
  664.     defb    cret,lf,0
  665.  
  666. ; Deal with running SUBMIT job
  667.  
  668. abort2:
  669.     call    getsrun        ; Is a submit job running
  670.     ret    z        ; If not, return to command processor
  671.  
  672.     ld    a,(bell2fl)
  673.     call    beep
  674.  
  675.     call    print
  676.     defb    ' Abort SUBMIT job (Y/N)? '
  677.     defb    0
  678.  
  679.     call    getyesno    ; Get user's answer
  680.     jr    nz,abort3    ; Branch if negative response
  681.  
  682.     call    subon
  683.     jr    z,abort3    ; if ZCPR33 not found
  684.     call    haltsub        ; Abort SUBMIT
  685.  
  686.  
  687. abortmsg:
  688.     call    print
  689.     defb    '  Aborted'
  690.     defb    cret,lf,0
  691.     ret            ; Back to command processor
  692.  
  693. abort3:
  694.     call    print
  695.     defb    ' Not ',0
  696.     jr    abortmsg
  697.  
  698.  
  699. ;-----------------------------------------------------------------------------
  700.  
  701. ; BEEP -- sound bell if flag in A is nonzero
  702.  
  703. beep:
  704.     or    a
  705.     ret    z
  706.     call    print
  707.     defb    bell,0
  708.     ret
  709.  
  710. ;-----------------------------------------------------------------------------
  711.  
  712. ; GETYESNO -- get yes/no answer from user
  713.  
  714. ; Only 'Y' or 'y' accepted as affirmative answers.  Routine returns Z if
  715. ; affirmative, NZ otherwise.
  716.  
  717. getyesno:
  718.     call    capin        ; Get user response
  719.     cp    'Y'
  720.     ret
  721.  
  722. ;-----------------------------------------------------------------------------
  723.  
  724. ; PONOFF -- Print ON or OFF in message
  725. ;
  726. ; If the Z flag is set on entry, 'OFF' is displayed; otherwize 'ON' is
  727. ; displayed.
  728.  
  729. ponoff:
  730.     jr    z,poff
  731.  
  732.     call    print
  733.     defb    'ON',0
  734.     ret
  735.  
  736. poff:
  737.     call    print
  738.     defb    'OFF',0
  739.     ret
  740.  
  741. ;-----------------------------------------------------------------------------
  742.  
  743. ; NAME    -- Display name of command
  744.  
  745. name:
  746.     call    getefcb
  747.     ld    b,8        ; Maximum number of characters in name
  748. name1:
  749.     inc    hl
  750.     ld    a,(hl)
  751.     cp    ' '        ; If space, we are done
  752.     ret    z
  753.     call    cout        ; Display the next character
  754.     djnz    name1        ; Work through them
  755.     ret
  756.  
  757. ;=============================================================================
  758. ;
  759. ;        B U F F E R S
  760. ;
  761. ;=============================================================================
  762.  
  763.     dseg
  764.  
  765. delimptr:
  766.     defs    2        ; Pointer to bad command's delimiter
  767.  
  768. delim:
  769.     defs    1        ; Bad command's delimiting character
  770.  
  771. ;=============================================================================
  772. ;
  773. ;        The following code is derived from VERR17
  774. ;
  775. ;=============================================================================
  776.  
  777.     cseg
  778.  
  779.     extrn    z3vini,    stndou,    stnden        ; VLIB
  780.     extrn    cls, tinit, ereol, gotoxy
  781.  
  782.     extrn    dutdir                ; Z3LIB
  783.  
  784.     extrn    caps                ; SYSLIB
  785. ;
  786. ; customization equates
  787. ;
  788. false    equ    0
  789. true    equ    not false
  790. vhelp    equ    true        ; include help information?
  791. inverse    equ    true
  792. ;
  793. ; basic definitions
  794. ;
  795. quoffs    equ    28h        ; quiet byte offset
  796. ca    equ    'A'-'@'
  797. cc    equ    'C'-'@'
  798. cd    equ    'D'-'@'
  799. ce    equ    'E'-'@'
  800. cf    equ    'F'-'@'
  801. cg    equ    'G'-'@'
  802. ch    equ    'H'-'@'
  803. cj    equ    'J'-'@'
  804. ck    equ    'K'-'@'
  805. cl    equ    'L'-'@'
  806. cm    equ    'M'-'@'
  807. cp    equ    'P'-'@'
  808. cq    equ    'Q'-'@'
  809. cr    equ    'R'-'@'
  810. cs    equ    'S'-'@'
  811. ct    equ    'T'-'@'
  812. cu    equ    'U'-'@'
  813. cv    equ    'V'-'@'
  814. cx    equ    'X'-'@'
  815. cy    equ    'Y'-'@'
  816. del    equ    7FH
  817.  
  818. ;
  819. ; process faulty command buffer
  820. ;
  821.  
  822. verror:
  823.  
  824. ;
  825. ; initialize command buffer
  826. ;
  827.     call    getcl1
  828.     push    hl
  829.     ld    de,buffer
  830.     ld    bc,04h
  831.     ldir            ; move the first 4 bytes of the command
  832.                 ;  buffer to our copy of it.
  833.     call    erradr        ; get address of faulty command
  834.     ex    de,hl        ; put it into de
  835.     pop    hl        ; old buffer
  836.     push    de
  837.     ld    de,5
  838.     add    hl,de
  839.     pop    de
  840.     ex    de,hl
  841.     or    a
  842.     sbc    hl,de        ; get difference of new and old pointer
  843.     ld    c,l
  844.     ld    b,h        ; put it into bc
  845.     call    getcl1
  846.     ld    de,5
  847.     add    hl,de        ; beginning of actual command in buffer
  848.     ld    de,text    + 1    ; our beginning of buffer
  849.     add    hl,bc
  850.     ld    bc,0ffh        ; we can over shoot.  won't hurt anything
  851.     ldir            ; move z3's to ours
  852.  
  853. edit:
  854. ;
  855. ; initialize kill buffer
  856. ;
  857.     ld    a,0
  858.     ld    (kill),a
  859.  
  860. ;
  861. ; set up screen for editing
  862. ;
  863.     call    cls        ; clear the screen
  864.     jp    z,notcap    ; if it's not covered, we can't do it
  865.     ld    hl,101h        ; top of screen
  866.     call    gotoxy        ; position cusor so we can check for function
  867.     jp    z,notcap    ; bomb out if not covered
  868.     call    ereol        ; blast line so we can check for function
  869.     jp    z,notcap    ; bomb out if not covered
  870.     call    stndou        ; make dim
  871.     ld    de,instr
  872.     call    string        ; tell 'em what they're using
  873.     ld    e,':'
  874.     ld    c,2
  875.     call    bdos        ; put a colon at the end of it
  876.     ld    hl,012ah
  877.     call    gotoxy
  878.     ld    c,25
  879.     call    bdos        ; get the drive
  880.     push    af
  881.     add    a,'A'        ; make it a letter
  882.     ld    c,a
  883.     call    write        ; write it
  884.     ld    e,0ffh
  885.     ld    c,32
  886.     call    bdos        ; get the user
  887.     call    pafdc        ; write it as a number
  888.     ld    c,a
  889.     pop    af        ; get drive
  890.     ld    b,a
  891.     call    dutdir        ; get the ndr
  892.     jr    z,namedone
  893.     push    hl
  894.     ld    c,':'
  895.     call    write        ; and the colon to seperate
  896.     pop    hl
  897.     ld    b,8        ; eight chars max
  898. nameloop:
  899.     ld    a,(hl)        ; get the first char
  900.     cp    ' '        ; is it the last
  901.     jr    z,namedone    ; yup.    done
  902.     push    hl
  903.     ld    c,a
  904.     call    write        ; write it
  905.     pop    hl
  906.     inc    hl
  907.     djnz    nameloop    ; repeat
  908. namedone:
  909.     ld    c,'>'        ; print a '>'
  910.     call    write
  911. ;
  912.     if    vhelp
  913.     call    showhelp
  914.     endif
  915. ;
  916.     call    stnden        ; make normal
  917.  
  918. ;
  919. ; initialize buffer for editing
  920. ;
  921.     xor    a        ; a := 0
  922.     ld    bc,0ffh
  923.     ld    hl,text    + 1
  924.     cpir            ; find the zero at the end of the line
  925.     ld    a,c
  926.     cpl            ; a := 255 - a
  927.     ld    (length),a    ; store that in length
  928.     ld    hl,point
  929.     ld    (hl),1        ; put us at the start of the buffer
  930.     call    draw        ; write the buffer to screen
  931.  
  932. ;
  933. ; main program: keep calling loop
  934. ;
  935. doloop:    call    loop        ; execute the editing
  936.     jr    doloop        ; continue this
  937.  
  938. ;
  939. ; get input and determine what action results
  940. ;
  941. loop:
  942.     xor    a
  943.     ld    (beeper),a
  944.     call    getkey        ; bring in a character
  945.     ld    hl,cmdstr
  946.     ld    bc,cmdlst - cmdstr
  947.     cpir            ; compare to cmdstr
  948.     jr    nz,notcmd    ; no match, check for insertion
  949.     ld    a,cmdlst - cmdstr - 1
  950.     sub    c        ; get difference (how far in the command is)
  951.     add    a,a        ; double it (compensation for dws)
  952.     ld    c,a        ; put that offset in bc
  953.     ld    hl,cmdlst
  954.     add    hl,bc        ; add it to cmdlst
  955.     ld    e,(hl)        ; get low byte
  956.     inc    hl
  957.     ld    d,(hl)        ; get high byte
  958.     ex    de,hl        ; put location in hl
  959.     jp    (hl)        ; and go to that location
  960. cmdstr:
  961.     db    cs,ch,cd,cl,ce,ck,cx,cj,ca,cf
  962.     db    cc,cg,del,ct,cr,cu,cv,cp,cy,cm
  963.  
  964.     if    vhelp
  965.     db    cq
  966.     endif    ; help
  967.  
  968. cmdlst:
  969.     dw    left
  970.     dw    left
  971.     dw    right
  972.     dw    right
  973.     dw    up
  974.     dw    up
  975.     dw    down
  976.     dw    down
  977.     dw    wleft
  978.     dw    wright
  979.     dw    cright
  980.     dw    delrt
  981.     dw    dellft
  982.     dw    delwrd
  983.     dw    delcmd
  984.     dw    undo
  985.     dw    flmode
  986.     dw    vprint
  987.     dw    quit
  988.     dw    done
  989.  
  990.     if    vhelp
  991.     dw    needhelp
  992.     endif    ; help
  993.  
  994. notcmd:
  995.     cp    ' '        ; is it a control char that is unallocated?
  996.     ret    c        ; if so, return
  997.     cp    '{'        ; is it lower-case?
  998.     jr    nc,notlow    ; no
  999.     cp    'a'
  1000.     jr    c,notlow    ; no
  1001.     sub    ' '        ; yes.    so up-case it
  1002. notlow:
  1003.     jr    putchar        ; and enter it
  1004.  
  1005. ;
  1006. ; get next key for entry no matter what it is.
  1007. ;
  1008. vprint:
  1009.     call    getkey        ; bring in a key
  1010.                 ; don't strip control or lower-case chars
  1011.  
  1012. ;
  1013. ; put a character (in a) into current position
  1014. ;
  1015. putchar:
  1016.     ld    (char),a    ; save the character
  1017.     ld    a,(mode)    ; consider mode
  1018.     or    a
  1019.     jr    z,insert    ; if mode is 0 then insert, else overwrite
  1020. put:
  1021.     ld    a,(point)
  1022.     ld    hl,length
  1023.     cp    (hl)        ; find out if this is the null
  1024.     jr    z,insert    ; we're at the end so insert
  1025.     ld    de,text
  1026.     ld    l,a
  1027.     ld    h,0
  1028.     add    hl,de        ; find the place where the cursor is
  1029.     ld    a,(char)
  1030.     ld    (hl),a        ; put the character there
  1031.     call    vwrite        ; print it
  1032.     jp    right        ; bump the cursor
  1033. insert:
  1034.     ld    hl,length
  1035.     ld    a,(maxlen)
  1036.     cp    (hl)
  1037.     jp    z,beepit    ; if line would be too long then signal
  1038.     ld    a,(hl)        ; a := length
  1039.     ld    l,a
  1040.     ld    h,0
  1041.     ld    de,text
  1042.     add    hl,de        ; last character in hl
  1043.     ld    e,l
  1044.     ld    d,h
  1045.     inc    de        ; last character + 1 in de
  1046.     push    hl
  1047.     ld    hl,point
  1048.     sub    (hl)        ; a := length - point
  1049.     inc    a        ; a := a + 1
  1050.     ld    c,a
  1051.     ld    b,0
  1052.     pop    hl
  1053.     lddr            ; move everything over one
  1054.     ld    hl,length
  1055.     inc    (hl)        ; add one to the length
  1056.     ld    a,0ffh
  1057.     ld    (ins),a
  1058.     ld    a,(silent)
  1059.     or    a
  1060.     call    z,draw        ; refresh the display
  1061.     xor    a
  1062.     ld    (ins),a
  1063.     jr    put        ; now toss in the character
  1064.  
  1065. ;
  1066. ; put buffer into multi command buffer and reset values
  1067. ;
  1068. done:
  1069.     ld    a,h        ; get whether indexed or not
  1070.     push    af
  1071.     ld    hl,point
  1072.     ld    (hl),4        ; move pointer to beginning
  1073.     ld    hl,buffer + 1
  1074.     call    getcl1        ; get location of command line
  1075.     push    hl
  1076.     ld    de,buffer
  1077.     ex    de,hl
  1078.     ld    a,(length)
  1079.     add    a,4        ; move length + 4 bytes
  1080.     ld    c,a
  1081.     ld    b,0
  1082.     ldir            ; move our buffer to z3's
  1083.     pop    hl        ; consider command line location
  1084.     push    hl
  1085.     ld    de,4
  1086.     add    hl,de        ; calculate first character (cmd line + 4)
  1087.     pop    de
  1088.     ex    de,hl        ; put it in de and
  1089.     ld    (hl),e
  1090.     inc    hl
  1091.     ld    (hl),d        ; and store that to z3's pointer
  1092.     pop    af        ; get whether to do position or not
  1093.     pop    hl        ; remove loop's return location
  1094.     or    a
  1095.     ret    z        ; if hl was not used for index, h = 0
  1096. ;
  1097.     if    vhelp
  1098.     ld    hl,1701h
  1099.     ld    a,(hlpflg)
  1100.     or    a
  1101.     jr    nz,dogoxy
  1102.     endif    ; help
  1103. ;
  1104.     ld    hl,701h
  1105. dogoxy:    jp    gotoxy        ; move cursor to clear and exit
  1106.  
  1107. ;
  1108. ; abort editing
  1109. ;
  1110. quit:
  1111.     pop    hl        ; remove loop's return location
  1112.     ld    hl,301h
  1113.     call    gotoxy        ; move cursor to beginning of line
  1114.     call    drclr
  1115. ;
  1116.     if    vhelp
  1117.     ld    hl,1701h
  1118.     ld    a,(hlpflg)
  1119.     or    a
  1120.     jr    nz,qugoxy
  1121.     endif    ; help
  1122. ;
  1123.     ld    hl,701h
  1124. qugoxy:    jp    gotoxy        ; move cursor to clear and exit
  1125.  
  1126. ;
  1127. ; provide list of commands
  1128. ;
  1129. ;
  1130.     if    vhelp
  1131. needhelp:
  1132.     ld    a,0ffh
  1133.     ld    (hlpflg),a
  1134.     call    showhelp
  1135.     call    stnden
  1136.     jp    gopos
  1137.     endif    ; help
  1138. ;
  1139.  
  1140. ;
  1141. ; bring back text from last delete word
  1142. ;
  1143. undo:
  1144.     ld    a,0ffh
  1145.     ld    (silent),a
  1146.     ld    hl,kill
  1147. udloop:    ld    a,(hl)
  1148.     or    a
  1149.     jr    z,undone
  1150.     push    hl
  1151.     call    putchar
  1152.     pop    hl
  1153.     inc    hl
  1154.     jr    udloop
  1155. undone:
  1156.     xor    a
  1157.     ld    (silent),a
  1158.     jp    draw
  1159.  
  1160. ;
  1161. ; flip between insert and overwrite mode
  1162. ;
  1163. flmode:
  1164.  
  1165.     ld    hl,140h
  1166.     call    gotoxy        ; goto approx center of screen
  1167.     ld    hl,mode        ; consider mode
  1168.     ld    a,(hl)
  1169.     cpl            ; make    (255 := 0)  or    (0 := 255)
  1170.     ld    (hl),a        ; save that to mode
  1171.     or    a
  1172.     jr    z,inshed    ; if insert mode then ereol to rid us of over
  1173.     ld    de,over
  1174.     call    string        ; else print over and fall through
  1175. inshed:    call    ereol        ; delete over
  1176.     jp    gopos        ; reposition cursor
  1177.  
  1178. over:    db    'insert is off$'
  1179.  
  1180. ;
  1181. ; ring console bell
  1182. ;
  1183. beepit:
  1184.     ld    hl,beeper
  1185.     ld    a,(hl)        ; consider boolean beeper
  1186.     or    a
  1187.     ret    nz        ; if we already beeped, don't do it again
  1188.     cpl
  1189.     ld    (hl),a        ; make beep false
  1190.     ld    c,bell
  1191.     jp    write        ; ring bell
  1192.  
  1193. ;
  1194. ; delete command (from cursor to semicolon)
  1195. ;
  1196. delcmd:
  1197.     ld    a,0ffh
  1198.     ld    (cmd),a        ; set boolean value to true
  1199.     call    delwrd        ; pretend to delete a word
  1200.     xor    a        ; a := 0
  1201.     ld    (cmd),a        ; make cmd false again
  1202.     ret
  1203.  
  1204. ;
  1205. ; move right to end of command (from cursor to semicolon)
  1206. ;
  1207. cright:
  1208.     ld    a,0ffh
  1209.     ld    (cmd),a        ; set boolean value to true
  1210.     call    wright        ; pretend to move right a word
  1211.     xor    a        ; a := 0
  1212.     ld    (cmd),a        ; make cmd false again
  1213.     ret
  1214.  
  1215. ;
  1216. ; move one word to left
  1217. ;
  1218. wleft:
  1219.     xor    a
  1220.     ld    hl,endchr
  1221.     ld    (hl),a        ; endchr := 0
  1222. wlloop:
  1223.     exx            ; swap hl with hl'
  1224.     ld    hl,point
  1225.     dec    (hl)        ; move one to the left
  1226.     ld    a,(hl)
  1227.     cp    1        ; are we at position #1?
  1228.     jr    z,stop        ; if so, stop
  1229.     or    a        ; are we at position #zero?
  1230.     jr    nz,lnzero    ; if not, check for word end
  1231.     ld    a,(length)
  1232.     ld    (hl),a        ; else move pointer to the end of the buffer
  1233.     jr    stop        ; and stop
  1234. lnzero:
  1235.     call    check        ; check for word end
  1236.     exx            ; swap hl with hl'
  1237.     jr    nz,lnend    ; no, check to repeat
  1238.     ld    (hl),a        ; make value non-zero
  1239.     jr    wlloop        ; and repeat
  1240. lnend:    ld    a,(hl)
  1241.     or    a        ; have we already got a word end character?
  1242.     jr    z,wlloop    ; no, so continue
  1243.     jr    stop        ; else stop
  1244.  
  1245. ;
  1246. ; move one word to right
  1247. ;
  1248. wright:
  1249.     xor    a        ; a := 0
  1250.     ld    (rightc),a    ; rightc := 0
  1251.     ld    hl,endchr
  1252.     ld    (hl),a        ; endchr := 0
  1253. wrtloop:
  1254.     exx            ; swap hl with hl'
  1255.     ld    hl,rightc
  1256.     inc    (hl)        ; rightc := rightc + 1
  1257.     ld    hl,point
  1258.     inc    (hl)        ; move one to right
  1259.     ld    a,(length)
  1260.     cp    (hl)        ; are we at the end of the buffer?
  1261.     jr    z,stop        ; if so, stop
  1262.     jr    nc,rnzero    ; if not, proceed
  1263.     ld    (hl),1        ; if past the end, go to the beginning
  1264.     jr    stop        ;  and stop
  1265. rnzero:
  1266.     call    check        ; is it word end?
  1267.     exx            ; swap hl with hl'
  1268.     jr    nz,rnend    ; no, check to repeat
  1269.     ld    (hl),a        ; make value non-zero
  1270.     jr    wrtloop        ; and repeat
  1271. rnend:    ld    a,(hl)
  1272.     or    a        ; have we already got a word end character?
  1273.     jr    z,wrtloop    ; no, so continue
  1274. stop:
  1275.     jp    gopos        ; reposition cursor and return
  1276.  
  1277. ;
  1278. ; determine whether character ends word
  1279. ;
  1280. check:
  1281.     ld    d,0
  1282.     ld    e,(hl)        ; move position to de
  1283.     ld    hl,text
  1284.     add    hl,de        ; get position in memory
  1285.     ld    a,(hl)        ; consider that character
  1286.     ex    af,af'
  1287.     ld    a,(cmd)        ; are we just checking for a semicolon?
  1288.     or    a
  1289.     jr    z,word        ; no, check vs. the whole string
  1290.     ex    af,af'
  1291.     cp    ';'        ; is it a semicolon?
  1292.     ret            ; send the answer back
  1293. word:    ex    af,af'
  1294.     ld    hl,wordcs
  1295.     ld    bc,wclast-wordcs
  1296.     cpir            ; go through wordcs looking for the character
  1297.     ret            ; flag: zero set if match found
  1298. wordcs:
  1299.     db    ' ;,_/\|'''
  1300. wclast:
  1301.  
  1302. ;
  1303. ; delete word right
  1304. ;
  1305. delwrd:
  1306.     ld    a,(point)
  1307.     push    af
  1308.     call    wright        ; find length of word
  1309.     pop    af
  1310.     ld    (point),a    ; return to original position
  1311.     ld    a,(rightc)    ; rightc = length of word
  1312.     ld    hl,kill
  1313. delloop:
  1314.     ex    af,af'
  1315.     exx            ; swap hl and hl'
  1316.     call    delchar        ; delete the character we're sitting on
  1317.     exx            ; swap hl and hl'
  1318.     ld    a,(delchr)    ; consider deleted character
  1319.     ld    (hl),a        ; save deleted character
  1320.     inc    hl        ; go to next character in kill buffer
  1321.     ex    af,af'
  1322.     dec    a        ; is this the last character?
  1323.     jr    nz,delloop    ; no, do it again
  1324.     xor    a
  1325.     ld    (hl),a        ; end string with a null
  1326.     jp    draw        ; yes, refresh the screen
  1327.  
  1328. ;
  1329. ; move character left
  1330. ;
  1331. left:
  1332.     ld    hl,point
  1333.     dec    (hl)        ; move to left
  1334.     jp    nz,gopos    ; if (position > zero) then show it
  1335.     ld    a,(length)
  1336.     ld    (hl),a        ; else put cursor at end of buffer
  1337.     jp    gopos        ; then show it
  1338.  
  1339. ;
  1340. ; move character right
  1341. ;
  1342. right:
  1343.     ld    hl,point
  1344.     inc    (hl)        ; move to right
  1345.     ld    a,(length)
  1346.     cp    (hl)
  1347.     jp    nc,gopos    ; if (length > position) then show it
  1348.     ld    (hl),1        ; else put us at the beginning
  1349.     jp    gopos        ; and show it
  1350.  
  1351. ;
  1352. ; move line up
  1353. ;
  1354. up:
  1355.     ld    a,(point)
  1356.     cp    81
  1357.     ret    c
  1358.     sub    80
  1359.     ld    (point),a
  1360.     jp    gopos
  1361.  
  1362. ;
  1363. ; move line down
  1364. ;
  1365. down:
  1366.     ld    hl,point
  1367.     ld    a,(length)
  1368.     sub    (hl)        ; find difference between end and cursor
  1369.     cp    81        ; if (diff <= 80) then no char below
  1370.     jr    c,toend        ; should we put him at the end?
  1371.     ld    a,(hl)
  1372.     add    a,80        ; else add 80
  1373.     ld    (hl),a        ; and store it
  1374.     jp    gopos        ; and return
  1375. toend:    ld    a,(length)    ; consider length
  1376.     ld    c,(hl)
  1377.     cp    161        ; is there a third line?
  1378.     jr    c,nothrd    ; no, don't subtract a line
  1379.     sub    80        ; subtract a line
  1380.     push    af
  1381.     ld    a,c        ; consider point
  1382.     sub    80        ; subtract a line
  1383.     ld    c,a        ; store point
  1384.     pop    af
  1385. nothrd:    cp    81        ; is there a second line?
  1386.     ret    c        ; no, return
  1387.     ld    a,c        ; consider the point
  1388.     cp    81        ; is cursor is on the last line?
  1389.     ret    nc        ; yes, return
  1390.     ld    a,(length)
  1391.     ld    (hl),a        ; go to end
  1392.     jp    gopos        ; position and return
  1393.  
  1394. ;
  1395. ; delete character left
  1396. ;
  1397. dellft:
  1398.     call    left        ; move to the left
  1399.     call    delchar        ; then delete the character we're on
  1400.     jp    draw        ; and refresh the screen
  1401.  
  1402. ;
  1403. ; delete character right
  1404. ;
  1405. delrt:
  1406.     call    delchar        ; delete the character at our position
  1407.     jp    draw        ; and refresh the screen
  1408.  
  1409. ;
  1410. ; delete character at cursor position
  1411. ;
  1412. delchar:
  1413.     ld    a,(point)
  1414.     ld    l,a
  1415.     ld    h,0
  1416.     ld    de,text
  1417.     add    hl,de        ; get memory location of cursor
  1418.     ld    d,h
  1419.     ld    e,l        ; copy it to de
  1420.     ld    a,(hl)        ; consider current character
  1421.     ld    (delchr),a    ; save it for possible later use
  1422.     or    a
  1423.     ret    z        ; if the character is a null, then abort
  1424.     inc    hl
  1425.     push    hl
  1426.     ld    a,(length)
  1427.     ld    hl,point
  1428.     sub    (hl)        ; a := length - point
  1429.     inc    a        ; a := a + 1
  1430.     ld    c,a
  1431.     ld    b,0        ; bc := a
  1432.     pop    hl
  1433.     ldir            ; move the buffer down one (over character
  1434.                 ;  to delete, thus erasing it)
  1435.     ld    a,(length)
  1436.     dec    a
  1437.     ld    (length),a    ; subtract one from the length
  1438.     ret            ; and return
  1439.  
  1440. ;
  1441. ; write command line to screen
  1442. ;
  1443. draw:
  1444.     call    gopos        ; go to the cursor position
  1445.     ld    hl,point
  1446.     ld    e,(hl)
  1447. aldraw:    ld    d,0
  1448.     ld    hl,text
  1449.     add    hl,de        ; get the memory location of the cursor
  1450. drawl:    ld    a,(hl)        ; move current character to a
  1451.     or    a
  1452.     jr    z,drclr        ; if it's a null then we're done
  1453.     push    hl
  1454.     call    vwrite        ; else write it
  1455.     pop    hl
  1456.     inc    hl        ; point to next character
  1457.     jr    drawl        ; and repeat
  1458. drclr:
  1459.     ld    a,(ins)        ; if the calling routine was insert
  1460.     or    a
  1461.     jr    nz,gopos    ; then we don't need to ereol
  1462. clrloop:
  1463.     call    ereol        ; clear to end of line
  1464.     ld    c,cm
  1465.     call    write        ; write a ^m (carriage return)
  1466.     ld    c,lf
  1467.     call    write        ; write a ^j (line feed)
  1468.     call    ereol        ; clear to end of line, again
  1469.                 ; fall through to gopos
  1470.  
  1471. ;
  1472. ; position cursor as dictated by value of point
  1473. ;
  1474. gopos:
  1475.     ld    a,(point)
  1476.     ld    h,3        ; start at 3rd line
  1477. calc:
  1478.     cp    81
  1479.     jr    c,calcend    ; if (length <= 80) then we're done
  1480.     inc    h        ; else go down a line
  1481.     sub    80        ; and subtract 1 line from our number
  1482.     jr    calc        ; and check again
  1483. calcend:
  1484.     ld    l,a        ; make the remainder the x coordinate
  1485.     jp    gotoxy        ; and position the cursor
  1486.  
  1487. ;
  1488. ; get key from console -- return in a
  1489. ;
  1490. getkey:
  1491.     ld    c,6        ; select direct console i/o
  1492.     ld    e,0ffh        ; select get a key in
  1493.     call    bdos        ; do the function
  1494.     or    a
  1495.     jr    z,getkey    ; if zero keep checking for key
  1496.     ret            ; -- note that this will never return a null
  1497.  
  1498. ;
  1499. ; write characters:  control characters are highlighted
  1500. ;
  1501. vwrite:
  1502.     cp    ' '
  1503.     jr    c,cchar        ; if it's < ' ' then it's a control character
  1504.     ld    c,a
  1505.     jr    write        ; else print it
  1506. cchar:                ; it's a control char, so turn on
  1507.                 ;  highlight, then it off again
  1508.     push    af
  1509.     call    stndou        ; turn on highlight
  1510.     pop    af
  1511.     add    a,'@'        ; make control character a normal character
  1512.     ld    c,a
  1513.     call    write        ; print the character
  1514.     jp    stnden        ; turn off highlight
  1515.  
  1516. ;
  1517. ; abort program because of insufficient tcap
  1518. ;
  1519. notcap:
  1520.     ld    de,tcapstr
  1521.     jp    string
  1522. tcapstr:
  1523.     db    'terminal definition insufficient.$'
  1524.  
  1525. ;
  1526. ; write character through bios or bdos
  1527. ;
  1528. write:
  1529.     ld    hl,(1)        ; get base of bios
  1530.     ld    de,09        ; add offset for console out
  1531.     add    hl,de
  1532.     jp    (hl)        ; jump to that location
  1533.  
  1534. ;
  1535. ; write help msg
  1536. ;
  1537.     if    vhelp
  1538. showhelp:
  1539.     ld    hl,601h
  1540.     call    gotoxy
  1541. ;
  1542.     call    stndou
  1543.     ld    a,(hlpflg)
  1544.     or    a
  1545.     jr    nz,bighlp
  1546.     ld    de,lilhlp
  1547.     jr    string
  1548. bighlp:
  1549.     if    inverse
  1550.     ld    de,helpmsg
  1551.     jr    string        ; print older message
  1552.  
  1553.     else    ; inverse    ( if not inverse )
  1554.  
  1555.     ld    hl,helpmsg
  1556. shloop:    ld    a,(hl)
  1557.     or    a
  1558.     ret    z        ; end on a null
  1559.     cp    '~'
  1560.     jr    z,doline    ; do line function
  1561.     push    hl
  1562.     call    bwrite        ; write through bdos
  1563.     pop    hl
  1564.     inc    hl
  1565.     jr    shloop        ; repeat
  1566. doline:
  1567.     inc    hl
  1568.     push    hl
  1569.     call    stndou        ; make text dim
  1570.     ld    b,(hl)
  1571.     ld    e,'-'
  1572.     ld    c,2        ; set up to write '-'
  1573. lineloop:
  1574.     push    bc
  1575.     push    de
  1576.     call    bdos        ; do the bdos call (for print)
  1577.     pop    de
  1578.     pop    bc
  1579.     djnz    lineloop    ; repeat
  1580.     call    stnden        ; make normal again
  1581.     pop    hl
  1582.     inc    hl
  1583.     jr    shloop        ; repeat
  1584.  
  1585. ;
  1586. ; write character through bdos (there must be tabs)
  1587. ;
  1588. bwrite:    push    af
  1589.     ld    a,(contrl)    ; are we in the middle of a ^char?
  1590.     or    a
  1591.     jr    z,skipstnd    ; no, skip routine
  1592.     dec    a
  1593.     ld    (contrl),a    ; count down one
  1594.     call    z,stndou    ; if it's zero, make dim
  1595. skipstnd:
  1596.     pop    af
  1597.     cp    1
  1598.     jp    z,stnden    ; ^a = normal video
  1599.     cp    2
  1600.     jp    z,stndou    ; ^b = dim video
  1601.     cp    '|'
  1602.     jr    nz,chkctrl    ; so we can print '^'
  1603.     ld    a,'^'
  1604.     jr    notctrl
  1605. chkctrl:
  1606.     cp    '^'        ; is it a '^'?
  1607.     jr    nz,notctrl    ; no, skip
  1608.     push    af
  1609.     ld    a,2
  1610.     ld    (contrl),a    ; normal video for two chars
  1611.     call    stnden        ; call normal video
  1612.     pop    af
  1613. notctrl:
  1614.     ld    e,a
  1615.     ld    c,2
  1616.     jp    bdos        ; write the character
  1617.  
  1618.     endif    ; inverse
  1619.     endif    ; help
  1620.  
  1621. ;
  1622. ; write string through bdos
  1623. ;
  1624. string:
  1625.     ld    c,9
  1626.     jp    5
  1627.  
  1628. ;
  1629. ; misc. buffers
  1630. ;
  1631. mode:    db    0
  1632. endchr:    db    0
  1633. rightc:    db    0
  1634. ins:    db    0
  1635. cmd:    db    0
  1636. char:    db    0
  1637. beeper:    db    0
  1638. delchr:    db    0
  1639. contrl:    db    0
  1640. silent:    db    0
  1641. hlpflg:    db    0
  1642.  
  1643. instr:    db    'Z33VERR version ',[version / 10] + '0','.'
  1644.     db    [version mod 10] + '0',' -- error handler$'
  1645.  
  1646.     if    vhelp
  1647. lilhlp:    db    '^Q for help$'
  1648. helpmsg:
  1649.      if    inverse
  1650.  
  1651.     db cret,lf
  1652.     db 'movement commands | deletion commands |   miscellaneous commands    ',cret,lf,cret,lf
  1653.     db ' ^D - char right  | ^G - char right   | ^P - insert control-char    ',cret,lf
  1654.     db ' ^S - char left   | <del> - char left | ^V - toggle insert/overwrite',cret,lf
  1655.     db ' ^E - line up     | ^T - word right   | ^U - undelete last ^T or ^R ',cret,lf
  1656.     db ' ^X - line down   | ^R - cmd right    | ^Y - abort entire line      ',cret,lf
  1657.     db ' ^F - word right  |                   | <ret> - execute             ',cret,lf
  1658.     db ' ^A - word left   |                                                 ',cret,lf
  1659.     db ' ^C - cmd right   |                                                 ','$'
  1660.  
  1661.      else    ; inverse    ( if    not inverse )
  1662.  
  1663.     db '      ~',20,' movement ~',18,cret,lf,lf
  1664.     db '        ^E          ~',2,' word ~',2,'      ~',2,' command ~',2,2,cret,lf
  1665.     db '         |',cret,lf
  1666.     db '    ^S <-+-> ^D     ^A <-+-> ^F         <-+-> ^C',cret,lf
  1667.     db '         v',cret,lf
  1668.     db '        ^X',cret,lf,lf
  1669.     db '~',26,' deletion ~',25,cret,lf,lf
  1670.     db ' ~',2,' character ~',2,'   ~',2,' word ~',2,'        ~',2,' command ~',2,'    ~',2,' line ~',2,cret,lf
  1671.     db '  del',2,' <-+-> ^G       <-+-> ^T       <-+-> ^R     <- ^Y ->',cret,lf,lf
  1672.     db '~',24,' miscellaneous ~',22,cret,lf,lf
  1673.     db '^U undelete word or cmd                  ^V toggle insert mode',cret,lf
  1674.     db '^P insert control-char               ',1,'return',2,' execute command line',cret,lf,0
  1675.      endif    ; inverse
  1676.     endif    ; help
  1677.  
  1678. ;
  1679. last:
  1680.  
  1681.     dseg
  1682.  
  1683. kill    ds    255
  1684. buffer    ds    2
  1685. point    equ    buffer
  1686. maxlen    equ    buffer + 2
  1687. length    equ    buffer + 3
  1688. text    equ    buffer + 3
  1689.  
  1690.     end
  1691.