home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / jsage / znode3 / z3sys / cled15.lbr / RCPCLED.LZB / RCPCLED.LIB
Encoding:
Text File  |  1991-07-05  |  26.3 KB  |  1,312 lines

  1.     page
  2.  
  3. ; Libary:    RCPCLED for Z34RCP
  4. ; Author:    Rob Friefeld
  5. ; Version:    1.5
  6. ; Date:        July 5, 1991
  7. ; Changes:
  8. ;          - Echos CR immediately
  9. ;          - Explicitly checks for comment line
  10. ;          - Simplified several routines
  11. ;          - Change to histaddr usage
  12. ;        - Shell bit reset on entry
  13. ;        - New command: Kill to next command
  14. ;        - Backspace destructive/non-destructive
  15. ;        - Alternate registers need not be preserved by BIOS on CIN
  16.  
  17. ; Syntax:    CLED [/]    if "/", then run for one command line only
  18. ;                e.g. from a shell like ZFILER
  19.  
  20. ;
  21. ; =====    D E F I N I T I O N S     S E C T I O N  =====================
  22. ;
  23.  
  24. clver        equ    15    ; Version number  (Install program compat.)
  25. clrev        equ    'a'    ; Revision        (Does not affect config.)
  26.  
  27. del        equ    7fh    ; not in sysdef.lib
  28.  
  29. clbsp        defl    yes    ; Destructive Backspace?
  30.  
  31. ;
  32. ;=====    C O N F I G U R A T I O N    A R E A ========================
  33. ;
  34.  
  35. ; The installation program and history save tool expect fixed locations
  36. ; in this data array.
  37.  
  38. shname:        db    'CLED',0    ; Name put on shell stack
  39. versid:        db    clver        ; CLED version
  40. ddsep:        db    dudir_sep    ; DU:DIR separator char
  41. ins_flag:    db    clins        ; Yes = insert mode
  42. minsave:    db    clmin        ; Discard line =< this 
  43. era_flag:    db    clera        ; Erase stored line on exit
  44. save_flag:    db    clsav        ; Save command lines
  45. bsp_flag:    db    clbsp        ; Destructive backspace
  46. tim_sep:    db    timesep        ; Time string separator
  47.  
  48. ; ---------------------------
  49.  
  50. ; Command list for RCPCLED, Version 1.5
  51. ; Set bit 7 to use a command with meta key
  52.  
  53. cmd_list:
  54.     db    'Q'    ; Meta key 1
  55.     db    'H'    ; Backspace
  56.     db    'S'    ; Cursor left
  57.     db    'D'    ; Cursor right
  58.     db    'A'    ; Word left
  59.     db    'F'    ; Word right
  60.     dc    'S'    ; Line start
  61.     dc    'D'    ; Line end
  62.     db    'B'    ; Line end/ start
  63.     db    'G'    ; Delete char
  64.     db    DEL    ; Delete left
  65.     db    'T'    ; Delete word
  66.     db    'L'    ; Delete word left
  67.     db    'X'    ; Delete to SOL
  68.     db    'Y'    ; Delete line
  69.     dc    'Y'    ; Delete to EOL
  70.     db    'K'    ; Kill to next command
  71.     db    'V'    ; Toggle insert
  72.     db    'P'    ; Enter control
  73.     db    'W'    ; Recall line
  74.     db    'E'    ; Recall reverse
  75.     db    'M'    ; Execute line
  76.     db    '['    ; ESC menu
  77.  
  78. cmd_end    equ    $ - 1
  79. cmdlen    equ    $ - cmd_list
  80.  
  81. ; ---------------------------
  82. ; Word separators
  83.  
  84. wrdseps:
  85.         db    0,', ;:.'
  86. wrdseplen    equ    $ - wrdseps
  87.  
  88. ; ---------------------------
  89. ; Highlight on/off codes for time display (installable)
  90. ;
  91. stndout:    db    0,0,0,0        ; Must terminate with hibit or binary 0
  92. stndend:    db    0,0,0,0        ; Ditto
  93.  
  94. ; ---------------------------
  95. ; 4 bytes are used here for the information of the history save/load tool,
  96. ; CLEDSAVE
  97.  
  98. histaddr:    dw    history-$    ; Offset from here to history buffer
  99. histsz:        dw    histsize    ; Buffer size
  100.  
  101. ;
  102. ;=====    M A I N    C O D E    S E C T I O N  ========================
  103. ;
  104. cled:
  105.     call    DEFINE        ; Set pointer to free mem
  106.     ld    de,-lbufwid-2    ; Free space for line input buffer
  107.     add    hl,de
  108.     ld    (line),hl    ; Set line buffer location
  109.     xor    a
  110.     ld    (hl),a        ; Zero line
  111.     ld    hl,history    ; History stack
  112.     ld    (recall_ptr),hl    ; Init position pointer to start
  113.  
  114.     ld    a,(fcb+1)    ; Check command line option
  115.     cp    '/'
  116.     jr    z,cledit    ; Go right to editing
  117.  
  118.     ld    a,(z3msg+3)    ; QSHELL
  119.     dec    a        ; <> 1 on manual invocation
  120.     jr    z,cledit    ; Skip installation
  121.  
  122. ;
  123. ;=====    S H E L L   I N S T A L L A T I O N =========================
  124. ;
  125. sh_inst:
  126.     ld    hl,shname
  127.     call    shpush        ; Z = OK
  128.     ret    z
  129.     call    print        ; Complain about stack and cancel
  130.     dc    cr,lf,'SH STK'    ; Full or non-existent
  131.     ret
  132.  
  133. ;
  134. ;=====    L I N E   E D I T ===========================================
  135. ;
  136.  
  137. ; This is the main entry point for the shell
  138. ; To do:
  139. ;  1 - Reset shell bit
  140. ;  2 - Display prompt
  141. ;  3 - Get a line
  142. ;  4 - Run the line
  143.  
  144. cledit:
  145. ; Subtask 1 -- 
  146.     xor    a
  147.     ld    (z3msg+3),a    ; PUTCST
  148.  
  149. ;----------------------------------------
  150. ; Subtask 2 -- Display system prompt
  151.     call    prompt
  152.  
  153. ;----------------------------------------
  154. ; Subtask 3 -- Get a line
  155.  
  156. ; The editor returns NZ if the shell pop command has been given.  If not, it
  157. ; returns the character count of the command line in B.
  158.  
  159.     call    edit
  160.  
  161. ;----------------------------------------
  162. ; Subtask 4 -- 
  163.  
  164.     jp    nz,shpop    ; Quit shell returned
  165.     ld    a,cr
  166.     call    conout        ; Echo a CR
  167.  
  168. ; Here we load the MCL directly from the line buffer.  On OVFL, loop to edit.
  169.  
  170. loadcl:
  171.     ld    a,(z3cl+2)    ; MCL size
  172.     inc    b        ; B contains line count, include terminating 0
  173.     cp    b        ; Compare to line size
  174.     jr    nc,loadcl1    ; OK
  175.  
  176. mclerr:
  177.     call    print
  178.     dc    cr,lf,'OVFL',cr,lf
  179.     jr    cledit
  180.  
  181. loadcl1:
  182.     ld    hl,(line)    ; Check first char of line
  183.     ld    a,';'        ; ...for comment mark
  184.     cp    (hl)
  185.     jr    z,cledit    ; Just loop back if so
  186.  
  187.     ld    de,z3cl+4    ; Set MCL pointer to start
  188.     ld    (z3cl),de
  189.     ld    c,b
  190.     ld    b,0
  191.     ldir            ; Move line buff to MCL
  192.     ret            ; Run it
  193.  
  194.  
  195. ;
  196. ;=====    S U B R O U T I N E S =======================================
  197. ;
  198.  
  199. ; Prompt -- PRINT a DU:DIR prompt.
  200. ;
  201. prompt:
  202.      if    systime
  203.     call    print_time
  204.      endif
  205.  
  206.     ld    bc,(cusr)    ; GDEFDU
  207.     ld    a,b        ; Drive
  208.     add    a,'A'        ; Make it a letter
  209.     call    conout        ; Write it
  210.     ld    a,c        ; Get user
  211.  
  212.      if    puser0
  213.     call    pusr        ; Write it
  214.      else
  215.     or    a
  216.     call    nz,pusr        ; Write it IF NONZERO
  217.      endif    ;puser0
  218.  
  219.     call    dutdir        ; Get the ndr
  220.     jr    z,prompt1
  221.     ld    a,(ddsep)    ; DU:DIR separator
  222.     call    conout
  223.     ld    b,8        ; Eight chars max
  224. nameloop:
  225.     ld    a,(hl)        ; Get the first char
  226.     cp    ' '
  227.     call    nz,conout    ; Write it if not blank
  228.     inc    hl
  229.     djnz    nameloop
  230.  
  231. prompt1:
  232.     call    prompt2
  233.     ld    a,(save_flag)    ; If save is OFF, prompt is >>
  234.     or    a
  235.     ret    nz
  236. prompt2:
  237.     ld    a,'>'
  238.     jp    conout
  239.  
  240.  
  241. ; PUSR -- Convert user # in A to decimal and print
  242. ; (Thanks to A.E. Hawley)
  243. pusr:
  244.     ld    hl,10 shl 8 + '0'-1    ; H=10, L='0'-1
  245.     cp    h            ; User < 10 ?
  246.     jr    c,pusr1
  247. pusr0:
  248.     inc    l        ; Advance character for user number tens digit
  249.     sub    h
  250.     jr    nc,pusr0
  251.     add    a,h
  252.     ld    h,a        ; Keep low digit of user number in H
  253.     ld    a,l        ; Display tens digit
  254.     call    conout
  255.     ld    a,h        ; Ready to process units digit
  256. pusr1:
  257.     jp    decout        ; Routine in RCPSUBS.LIB
  258. ;    add     '0'
  259. ;pusr2:
  260. ;    jp    conout
  261.  
  262. ; Console input without echo
  263.  
  264. cin:
  265.     push    hl
  266.     push    de
  267.     push    bc
  268. cin1:    ld    c,dirconf    ; DCIO
  269.     ld    e,-1
  270.     call    bdos
  271.     or    a
  272.     jr    z,cin1
  273.     pop    bc
  274.     pop    de
  275.     pop    hl
  276.     ret
  277.  
  278. ;
  279. ;=====    E D I T O R   S E C T I O N  ================================
  280.  
  281. ; Date:    July 5, 1991
  282.  
  283. ; Entry is EDIT
  284. ; Return Z = Execute command line, B = char count of line
  285. ;       NZ = Quit shell
  286.  
  287. ; Initialize to on-line environment.
  288. ; While editing, HL -> current position in LINE, B = char count,
  289. ; C = cursor position (0 .. count), DE = scratch
  290.  
  291. edit0:    pop    af        ; Internal restart
  292. edit:
  293.     ld    hl,(line)    ; Init to start of line
  294.     xor    a
  295.     ld    b,a        ; Line count = 0
  296.     ld    c,a        ; Cursor pos = 0
  297.  
  298.     push    hl        ; There may already be a line here
  299.     dec    b        ; Accumulate possible char count in B
  300. edit1:
  301.     inc    b
  302.     cp    (hl)        ; A = 0
  303.     inc    hl
  304.     jr    nz,edit1    ; Loop until 0 terminator
  305. edit2:
  306.     pop    hl        ; Point to line again
  307.     call    ptail        ; Print the line from cursor position
  308.  
  309. ;--------------------------------------------------------------------
  310.  
  311. ; EDIT COMMAND LOOP
  312.  
  313. ; The address of the command loop, ECMD, is pushed onto the stack so that
  314. ; a return from any of the line editor's routines comes back here.
  315. ; If the next char is text, jump to ENTER.  If it is a control, scan the
  316. ; CMD_LIST for a match, compute offset into CMD_VECTOR jump table, and go.
  317. ; A "shifted" key (high bit set in CMD_LST) is matched after the "meta-key"
  318. ; has been entered.
  319. ; * This routine doesn't protect the alternate registers across a DOS call
  320. ; to CIN.
  321.  
  322. ecmd:
  323.     call    cin        ; Next key...
  324.     cp    'C'-'@'        ; Warm boot?
  325.     jp    z,0000h
  326.  
  327.     exx            ; Main regs saved, trash regs active
  328.     ld    hl,meta_flag    ; Shift flag
  329.     or    (hl)        ; Mask in possible high bit
  330.     ld    (hl),0        ; Reset flag
  331.     ld    hl,ecmd        ; Save address so a return comes back here
  332.     push    hl
  333.     exx            ; Recover main regs
  334.  
  335.     cp    20h        ; Test key
  336.     jr    c,control_key    ; In control char range
  337.     cp    del        ; This control char > text chars
  338.     jp    c,enter        ; It's text
  339.  
  340. ; Convert a control key entry to cap char
  341. ;    Preserve high bit meta-key marker
  342. ;
  343. control_key:
  344.     push    af
  345.     and    10000000b    ; Retain high bit
  346.     ld    e,a        ; Keep it in temp register
  347.     pop    af
  348.     and    01111111b    ; Mask high bit
  349.     call    ucase        ; Convert char
  350.     or    e        ; Restore high bit
  351.  
  352.     exx            ; Must preserve main regs
  353.     ld    hl,cmd_end    ; Scan command list
  354.     ld    bc,cmdlen
  355.     cpdr
  356.     jr    nz,no_match
  357.     ld    hl,cmd_vector
  358.     add    hl,bc        ; Point to address in vector table
  359.     add    hl,bc
  360.     ld    c,(hl)
  361.     inc    hl
  362.     ld    b,(hl)
  363.     push    bc        ; Jump address
  364. no_match:
  365.     exx            ; Restore regs!
  366.     ret            ; Go
  367.  
  368. ; Mark meta-key flag
  369.  
  370. meta_key1:
  371.     ld    a,10000000b
  372.     ld    (meta_flag),a
  373.     ret
  374.  
  375. meta_flag:    db    0    ; Initial value 0 = no shift
  376.     
  377.  
  378. ; Jump table for commands
  379.  
  380. cmd_vector:
  381.     dw    meta_key1    ; Shift key
  382.     dw    bsp0        ; Backspace
  383.     dw    bsp        ; Cursor left
  384.     dw    fsp        ; Cursor right
  385.     dw    bwrd        ; Left word
  386.     dw    fwrd        ; Right word
  387.     dw    linbeg        ; To SOL
  388.     dw    linend        ; To EOL
  389.     dw    other_end    ; To EOL/SOL
  390.     dw    delete        ; Delete char
  391.     dw    delft        ; Delete char left
  392.     dw    delwrd        ; Delete word right
  393.     dw    delwlft        ; Delete word left
  394.     dw    delsol        ; Delete to start of line
  395.     dw    dline        ; Delete line
  396.     dw    deleol        ; Delete to end of line
  397.     dw    delcmd        ; Delete to next command
  398.     dw    instog        ; Toggle insert
  399.     dw    ctl_entry    ; Enter control char
  400.     dw    recall_back    ; Scroll back in history
  401.     dw    recall_fwrd    ; Scroll ahead in history
  402.     dw    eds$ex        ; Execute line
  403.     dw    esc_menu    ; Submenu
  404.  
  405. ;--------------------------------------------------------------------
  406.  
  407. ; ON-LINE ROUTINES, EDITING CURRENT LINE IN LINE BUFFER
  408.  
  409. ;  WHILE ON LINE:
  410. ;    Line Buffer is 0 terminated 
  411. ;    B =  Char Count (0..lbufwid)
  412. ;    C =  Cursor Position ( 0 <= C <= Char Count )
  413. ;    HL = Line buffer position
  414.  
  415.  
  416. ; Backspace
  417.  
  418. bsp0:    ld    a,(bsp_flag)    ; Destructive?
  419.     or    a
  420.     jr    nz,delft 
  421.  
  422. ; Char left
  423. ; Return Z = backspace not done, NZ = all OK
  424.  
  425. bsp:
  426.     xor    a
  427.     cp    c        ; Cursor pos
  428.     ret    z        ; At start
  429.     dec    hl        ; Back up in mem
  430.     dec    c        ; Cursor pos back
  431. bspace:
  432.     ld    a,bs        ; Back up on screen
  433.     or    a        ; Must ret nz
  434.     jp    conout
  435.  
  436.  
  437. ; Forward space
  438. ; Return Z = not done
  439.  
  440. fsp:
  441.     ld    a,(hl)        ; Look at current char
  442.     or    a
  443.     ret    z        ; At EOL
  444.     inc    hl        ; Advance mem ptr
  445.     inc    c        ; Advance cursor pos
  446.     jp    pctl        ; Advance screen by reprinting char
  447.  
  448.  
  449. ; Back word 
  450.  
  451. bwrd:
  452.     call    bsp        ; Backspace
  453.     ret    z        ; Nowhere to go
  454.     dec    hl
  455.     call    wrdsep        ; Look at char before this position
  456.     inc    hl
  457.     jr    nz,bwrd        ; Doesn't match a word sep, continue
  458.     ret
  459.  
  460. ; Forward word
  461.  
  462. fwrd:
  463.     call    wrdsep        ; Are we on a word separator now?
  464.     push    af        ; Save answer
  465.     call    fsp        ; Advance 1 char regardless
  466.     pop    af
  467.     ret    z        ; ...we just passed a word sep
  468.     jr    fwrd
  469.  
  470.  
  471. ; Delete char left
  472.  
  473. delft:
  474.     call    bsp        ; Backspace and fall through to delete
  475.  
  476. ; Delete char
  477.  
  478. delete:
  479.     call    delmem        ; In memory
  480.     jp    ptail        ; Refresh screen from cursor position
  481.  
  482. ; Delete to start of line
  483.  
  484. delsol:
  485.     ld    a,c        ; Get cursor pos
  486.     or    a
  487.     ret    z        ; Already at start
  488.     cp    b        ; Compare cursor pos to char count
  489.     jr    z,dline        ; At end, so delete entire line (quicker)
  490.     ld    e,a        ; Cursor pos = # chars to delete
  491.     call    linbeg        ; Go to start (preserves E)
  492. delsol1:
  493.     push    de        ; E is loop counter
  494.     call    delmem        ; Delete first char in memory
  495.     pop    de
  496.     dec    e
  497.     jr    nz,delsol1    ; Until # chars deletions
  498.     jp    ptail        ; Now update screen
  499.  
  500.  
  501. ; Delete to next command
  502.  
  503. delcmd:
  504.     ld    a,(hl)
  505.     cp    ';'
  506.     jr    z,delete    ; There now
  507.     or    a
  508.     jr    z,delete    ; At EOLN
  509.     call    delmem
  510.     jr    delcmd
  511.  
  512. ; Delete word left
  513.  
  514. delwlft:
  515.     call    bwrd        ; Back a word and fall thru ...
  516.  
  517.  
  518. ; Delete word right
  519.  
  520. delwrd:
  521.     call    wrdsep        ; On a word sep?
  522.     jr    z,delete    ; Yes, kill it
  523.     ld    a,b        ; Compare line count to cursor pos
  524.     cp    c
  525.     jr    z,delete    ; On last char of line
  526. delwrd1:
  527.     call    delmem        ; Delete in mem, update screen later
  528.     jr    delwrd        ; Go until word sep found
  529.  
  530.  
  531. ; Delete line
  532.  
  533. dline:
  534.     call    linbeg        ; Position at line start and fall thru ...
  535.  
  536. ; Delete to eoln
  537.  
  538. deleol:
  539.     call    ereol        ; Clear on screen
  540.     ld    b,c        ; Char count = current position
  541.     ld    (hl),0        ; Line terminator
  542.     ret
  543.  
  544. ; Insert/overwrite toggle
  545.  
  546. instog:
  547.     ld    a,(ins_flag)    ; Flag 0 -> owrt
  548.     cpl
  549.     ld    (ins_flag),a
  550.     ret
  551.  
  552. ; Enter a control
  553.  
  554. ctl_entry:
  555.     call    cin        ; Get the control
  556.     and    1fh        ; Fall thru to normal char entry
  557.  
  558. ; Enter a char
  559.  
  560. enter:
  561.     ex    af,af'        ; Save char
  562.     ld    a,b        ; At eoln?
  563.     cp    c
  564.     jr    z,ovrwrt    ; Yes, no need for insert mode
  565.     ld    a,(ins_flag)    ; Which mode are we in?
  566.     or    a        ; 0 = overwrite, nz = insert
  567.     jr    nz,insert
  568.  
  569.  
  570. ; Enter char in overwrite mode
  571.  
  572. ovrwrt:
  573. ;    ld    a,b        ; Char count
  574. ;    cp    lbufwid-2    ; Line full?
  575. ;    jr    c,ovr1        ; No
  576. ;    cp    c        ; Line is full.  At EOLN?
  577. ;    ret    z        ; Accept no more chars
  578.  
  579.     ld    a,c        ; Cursor pos
  580.     cp    lbufwid-2
  581.     ret    nc        ; Line full AND at EOLN
  582.  
  583.  
  584. ovr1:    ex    af,af'        ; Recover char
  585.     ld    (hl),a        ; Put char in place
  586.     call    fsp        ; Advance by printing it
  587.     ld    a,b        ; Char count -> a
  588.     cp    c
  589.     ret    nc        ; Inside line, no need to inc char count
  590.     inc    b        ; ...else add to count
  591.     ld    (hl),0        ; ...and terminate
  592.     ret
  593.  
  594. ; Enter char in insert mode
  595.  
  596. insert:
  597.     ld    a,b        ; Line full?
  598.     cp    lbufwid-2
  599.     ret    nc
  600.  
  601. ; Make a hole in the line buffer at current position
  602. insmem:
  603.     ld    a,b        ; Char count
  604.     sub    c        ; A = # chars to eoln
  605.     jr    z,insert1    ; At end, don't need any space
  606.     push    hl
  607.     exx            ; Save on-line environment
  608.     pop    hl
  609.     ld    c,a        ; Bc = # chars to move
  610.     xor    a
  611.     ld    b,a
  612.     add    hl,bc        ; New EOLN
  613.     ld    d,h        ; Now in DE
  614.     ld    e,l
  615.     inc    hl
  616.     ld    (hl),a        ; Insure a line terminator
  617.     dec    hl        ; Back up to..
  618.     dec    hl        ; ..current EOLN
  619.     lddr            ; Tail move
  620.     exx            ; Recover our starting position
  621.  
  622. insert1:
  623.     ex    af,af'        ; Recover new char
  624.     ld    (hl),a        ; Place char in line
  625.     call    ptail        ; Reprint entire line from here
  626.     inc    b        ; Inc char count
  627.     jp    fsp        ; Advance cursor
  628.  
  629.  
  630. ; Line end/start toggle
  631.  
  632. other_end:            ; Go to eoln or, if there, to start of line
  633.     ld    a,b
  634.     cp    c
  635.     jr    z,linbeg
  636.  
  637. linend:
  638.     call    fsp        ; Print ahead until EOL
  639.     jr    nz,linend
  640.     ret
  641.  
  642. linbeg:
  643.     call    bsp        ; Backspace until start
  644.     jr    nz,linbeg
  645.     ret
  646.  
  647.  
  648. ; Compare current char to list of word separators
  649. ;   Return Z = match.  Affect only AF.
  650.  
  651. wrdsep:
  652.     push    hl
  653.     push    bc
  654.     ld    bc,wrdseplen
  655.     ld    a,(hl)
  656.     ld    hl,wrdseps
  657.     cpir
  658.     pop    bc
  659.     pop    hl
  660.     ret
  661.  
  662.  
  663. ; Delete current char from line buffer
  664. ; Check for problem conditions, move remaining chars left
  665.  
  666. delmem:
  667.     ld    (hl),0        ; Terminal 0 or char to be deleted
  668.     ld    a,b        ; Char count in A
  669.     sub    c        ; A = (count-position) = chars from end
  670.     ret    z        ; At eoln, no char to delete
  671.     dec    b        ; Dec char count now
  672.     ret    z        ; 1 char line, done
  673.     dec    a        ; Are there any more to delete?
  674.     ret    z        ; On last char, just deleted it
  675. delmem1:
  676.     inc    a        ; A = # chars from end of longer line
  677.     push    hl
  678.     push    bc
  679.     ld    d,h        ; Dest of move is current pos
  680.     ld    e,l
  681.     inc    hl        ; Source is char right
  682.     ld    c,a        ; Chars to move includes terminal 0
  683.     ld    b,0
  684.     ldir
  685.     pop    bc
  686.     pop    hl
  687.     ret
  688.  
  689.  
  690.  
  691. ; Print line tail from cursor position, return to position
  692.  
  693. ptail:
  694.     push    hl        ; Save mem pos
  695.     push    bc        ; Save screen pos
  696.     call    linend        ; Print ahead to end of line
  697.     call    ereol        ; Clean off danglers
  698. ptail1:
  699.     ld    a,c        ; End of line cursor pos
  700.     pop    bc
  701.     pop    hl
  702.     sub    c        ; Current cursor pos
  703.     ret    z        ; At end of line already
  704.     ld    e,a        ; Loop counter
  705. ptail2:
  706.     call    bspace        ; Else back up to where we were
  707.     dec    e
  708.     jr    nz,ptail2
  709.     ret
  710.  
  711.  
  712. ; Print a char, turn a control char into a cap char
  713.  
  714. pctl:
  715.     push    af
  716.     cp    20h
  717.     jr    nc,pctl1
  718.     add    '@'
  719. pctl1:    call    conout
  720.     pop    af
  721.     ret
  722.  
  723.  
  724. ; Convert char or control key to upper case
  725.  
  726. ucase:
  727.     cp    ' '
  728.     jr    nc,notctl
  729.     add    '@'
  730. notctl:    cp    'a'
  731.     ret    c        ; Not a lowercase
  732.     cp    'z'+1
  733.     ret    nc        ; Not a lowercase
  734.     sub    ' '        ; Yes, a lowercase
  735.     ret
  736.  
  737.  
  738.  
  739. ; ESC key pressed - get submenu command
  740.  
  741. esc_menu:
  742.     call    cin
  743.     call    ucase
  744.     cp    'Q'        ; Quit
  745.     jr    z,edquit
  746.     cp    'S'        ; Toggle Save
  747.     ret    nz        ; Loop if none of these
  748.  
  749. ; Toggle recording state
  750. ;  - Alter line prompt to > if save ON, >> if save OFF
  751.  
  752. save_tog:
  753.     ld    a,(save_flag)    ; Flip flag byte
  754.     cpl
  755.     ld    (save_flag),a
  756.     call    crlf
  757.     call    prompt        ; Print new prompt string
  758.     jp    edit0        ; Restart
  759.  
  760.  
  761. ; Exit editor
  762.  
  763. eds$ex:
  764.     pop    af        ; Lift ECMD from stack
  765.     ld    a,(save_flag)    ; Are we recording?
  766.     or    a
  767.     ret    z        ; Nope
  768.  
  769.     ld    a,(minsave)    ; Is line worth keeping?
  770.     cp    b
  771.     push    bc        ; Save char count to return
  772.     call    c,save_line    ; Line is a keeper
  773.     pop    bc
  774.  
  775. edn$ex:
  776.     xor    a        ; Return Z
  777.     ret
  778.  
  779.  
  780. ; Exit and pop shell
  781.  
  782. edquit:
  783.     pop    af        ; Lift ECMD from stack
  784.     xor    a        ; Return NZ
  785.     dec    a
  786.     ret
  787.  
  788.  
  789. ; ---------------------------
  790.  
  791. ; HISTORY STACK ROUTINES for RCPCLED, Version 1.2
  792.  
  793. ; Each command line is pushed onto the history stack before execution.  
  794. ; Older lines eventually get pushed off the end and disappear.
  795. ; The history stack is internal to the RCP, but could be pointed elsewhere
  796. ; Stack structure --
  797. ;     Command lines from newest to oldest.
  798. ;     Each command line terminated with high bit set.
  799. ;     End of stack terminated with 0.
  800. ;
  801.  
  802. ; Save new line to stack
  803. ;  - This routine called only on exit, so on-line regs not preserved.
  804. ;  - Push contents down by size of current line
  805. ;  - Move line buffer to start of stack
  806. ;  - Terminate line with high bit set
  807. ;  - Terminate history with 0 after last COMPLETE line
  808. ;  - If current line is too big for buffer size chosen, do nothing
  809.  
  810. save_line:
  811.     ld    c,b        ; Line size from b to bc
  812.     xor    a
  813.     ld    b,a
  814.     push    bc
  815.     ld    hl,HISTSIZE
  816.     sbc    hl,bc        ; Buffer size - line length
  817.     jr    z,savel_err    ; Not enough room for 0 terminator
  818.     jr    c,savel_err    ; Definitely not enough room!
  819.     push    hl
  820.     ld    hl,hbuf_top
  821.     push    hl
  822.     sbc    hl,bc        ; hl -> bufftop - line size
  823.     pop    de        ; de -> bufftop
  824.     pop    bc        ; bc = buffsize - line size
  825.     lddr            ; tail move
  826.  
  827.     pop    bc        ; Recover line size in bc
  828.     ex    de,hl
  829.     inc    de        ; de -> buffstart
  830.     ld    hl,(line)    ; Move in line
  831.     ldir
  832.     dec    de
  833.     ex    de,hl
  834.     set    7,(hl)        ; Tag line terminus
  835.  
  836.     ld    hl,hbuf_top    ; Terminate history after last complete line
  837. savel1:
  838.     dec    hl        ; Back up to EOLN
  839.     bit    7,(hl)
  840.     jr    z,savel1    ; Loop until hi-bit encountered
  841.     inc    hl
  842.     ld    (hl),0
  843.     ret
  844.  
  845. savel_err:
  846.     pop    af        ; Lift BC push
  847.     ret
  848.  
  849. ; Recall command history, newest -> oldest
  850. ;  - RECALL_PTR is init to start of buffer on each CLED invocation
  851. ;  - return with pointer updated to next line
  852.  
  853. recall_back:
  854.     call    check_recall    ; Is there anything in buffer?
  855.     ret    nc        ; No
  856.  
  857. ; Transfer from recall pointer to line buffer
  858. ;   - enter hl @ recall_ptr
  859. ;   - return ptr -> start of next command if no OVFL
  860.  
  861. rc_back1:
  862.     ld    de,(line)    ; Destination for move
  863. rc_back1a:
  864.     ld    a,(hl)
  865.     or    a
  866.     jr    z,recall_quit    ; Buff end
  867.     ldi
  868.     bit    7,a
  869.     jr    z,rc_back1a
  870.  
  871.     ld    (recall_ptr),hl    ; Update ptr now
  872.     ex    de,hl        ; Point to end of line in line buffer
  873.     ld    (hl),0        ; Terminate it
  874.     dec    hl
  875.     res    7,(hl)        ; Fix high bit from storage
  876.  
  877.     jp    edit0        ; Restart on this line    
  878.  
  879. recall_quit0:
  880.     pop    af        ; Lift subroutine call from stack
  881. recall_quit:
  882.     exx            ; Recover main regs
  883.     ret            ; Back to editing
  884.  
  885.  
  886. ; Recall command history, oldest -> newest
  887.  
  888. recall_fwrd:
  889.     call    check_recall        ; Anything in buffer?
  890.     ret    nc            ; No
  891.     call    rc_fwrd1        ; Move to previous line
  892.     call    rc_fwrd1        ; No backlash on direction reversal
  893.     jr    rc_back1        ; Now same code as recall_back
  894.  
  895. rc_fwrd1:
  896.     dec    hl            ; Initially, HL -> next line to recall
  897.     ld    de,history        ; Underflow address
  898. rc_fwrd1a:
  899.     push    hl            ; Compute position relative to top
  900.     xor    a
  901.     sbc    hl,de
  902.     pop    hl
  903.     ret    z            ; Quit when start of buff reached
  904.     jr    c,recall_quit0        ; Underflow
  905.     dec    hl            ; Going backwards in buffer
  906.     bit    7,(hl)
  907.     jr    z,rc_fwrd1a
  908.     inc    hl            ; Point to char past command terminator
  909.     ret
  910.  
  911.  
  912. ; Check to see if anything in recall buffer yet
  913. ;   - Ret NC = no, main regs preserved
  914. ;   - Else switch main regs to alt, ret HL @ recall buffer line
  915.  
  916. check_recall:
  917.     ld    a,(history)    ; Is anything in buffer yet?
  918.     or    a
  919.     ret    z        ; Nope
  920.     call    linbeg
  921.     exx
  922.     ld    hl,(recall_ptr)
  923.     scf
  924.     ret
  925.  
  926. ; ---------------------------
  927.  
  928. ; Routine:    EREOL function for Z34RCP
  929. ; Author:    Rob Friefeld
  930. ; Version:    1.0
  931. ; Date:        September 19, 1989
  932. ;
  933. ; Entry:    EREOL
  934. ; Function:    To clear to end of line
  935. ; Comments:    The setting of the ERLTCAP equate determines whether this
  936. ;        command uses the TCAP information or not.  If not, it uses the
  937. ;        ereol string passed in macro CLR_EOL.  That string should
  938. ;        end with the high bit set. The setting of the ERLQUICK equate
  939. ;        determines whether to simply output the TCAP string for this
  940. ;        function or to interpret it as does Rick Conn's VLIB version.
  941. ;        Uses RCPSUBS.LIB routines  CONOUT and PRINTHL.
  942.  
  943.  
  944. ; -------------------------------------------------------------------
  945.  
  946.      if    [not erltcap]
  947. ;  Erase to end of line.  Return NZ.
  948.  
  949. ereol:    call    print
  950.     clr_eol
  951. ;    or    -1        ; For VLIB compatibility
  952.     ret
  953.  
  954.  
  955.      else
  956.      if    erlquick
  957.  
  958. ; ---------------------------
  959.  
  960. ; This version just prints the EREOL string: no delay, no interpretation.
  961.  
  962. ereol:
  963.     push    hl
  964.     ld    hl,z3tcap+17h    ; CLS string
  965.     xor    a        ; Skip to EREOL string
  966. ereol1:    cp    (hl)        ; Skip once
  967.     inc    hl
  968.     jr    nz,ereol1
  969. ereol2:    cp    (hl)        ; Skip twice
  970.     inc    hl
  971.     jr    nz,ereol2
  972.     call    printhl        ; Print it
  973.     pop    hl
  974.     ret
  975.  
  976. ; ---------------------------
  977.  
  978. ; This is a disassembly of EREOL from VLIB
  979.      else
  980.  
  981. ereol:
  982.     push    bc
  983.     push    de
  984.     push    hl
  985.     ld    hl,z3tcap+16h    ; Point to ereol delay
  986.     ld    d,(hl)
  987.     inc    hl
  988.     call    vidskp
  989.     call    vidskp
  990.     call    vidout
  991.     pop    hl
  992.     pop    de
  993.     pop    bc
  994.     xor    a
  995.     dec    a
  996.     ret
  997.  
  998. vidskp:
  999.     ld    a,(hl)
  1000.     inc    hl
  1001.     or    a
  1002.     ret    z
  1003.     cp    '\'
  1004.     jr    nz,vidskp
  1005.     inc    hl
  1006.     jr    vidskp
  1007.  
  1008. vidout:
  1009.     ld    a,(hl)
  1010.     or    a
  1011.     jr    z,vid2
  1012.     inc    hl
  1013.     cp    '\'
  1014.     jr    nz,vid1
  1015.     ld    a,(hl)
  1016. vid1:
  1017.     call    conout
  1018.     jr    vidout
  1019.  
  1020. vid2:
  1021.     ld    a,d
  1022.     or    a
  1023.     ret    z
  1024.     ld    c,a
  1025.     ld    hl,z3env+2bh    ; Processor speed
  1026.     ld    a,(hl)
  1027.     or    a
  1028.     jr    nz,vidl1
  1029.     ld    a,4
  1030. vidl1:
  1031.     ld    b,a
  1032.     push    bc
  1033.     call    vdelay
  1034.     pop    bc
  1035.     dec    c
  1036.     jr    nz,vidl2
  1037.     ret
  1038. vdelay:
  1039.     call    vdel1
  1040.     djnz    vdelay
  1041.     ret
  1042. vdel1:
  1043.     ld    c,20
  1044. vdel1a:
  1045.     ex    (sp),hl
  1046.     ex    (sp),hl
  1047.     dec    c
  1048.     jr    nz,vdel1a
  1049.     ret
  1050.  
  1051.      endif    ;erlquick
  1052.      endif    ;not erltcap
  1053.  
  1054. ;
  1055. ;=====    Z 3 L I B   R O U T I N E S  ================================
  1056. ;
  1057.  
  1058. ; DUTDIR, SHPUSH, SHPOP
  1059. ; For use with CLED RCP segment ONLY
  1060. ; These versions make use of named commons declarations
  1061. ; Does not save regs as does Z3LIB, and has less env error checking
  1062. ; This vesion was adapted from Z33 source code Copyright Jay P. Sage
  1063.  
  1064. ; Enter BC contains cdrv, cusr values
  1065. ; Return NZ, HL -> NDR entry if match
  1066.  
  1067. DUTDIR:    
  1068.     ld    hl,(z3env+15h)    ; Offset to NDR in Z3ENV
  1069.     ld    a,h
  1070.     or    l        ; Is NDR implemented?
  1071.     ret    z        ; If no NDR, return with zero flag set
  1072.     inc    b        ; CDRV is 0..15 but NDR is 1..16
  1073.     jr    du2dir2
  1074.  
  1075. du2dir1:            ; Advance to next entry in NDR
  1076.     ld    de,16+1        ; Skip user (1 byte) and name/pw (16 bytes)
  1077.     add    hl,de
  1078.  
  1079. du2dir2:
  1080.     ld    a,(hl)        ; End of NDR?
  1081.     or    a
  1082.     ret    z        ; If so, return with zero flag set
  1083.  
  1084.     inc    hl        ; Point to user number in NDR entry
  1085.     cp    b        ; Compare drive values
  1086.     jr    nz,du2dir1    ; If mismatch, back for another try
  1087.     ld    a,(hl)        ; Get user number
  1088.     sub    c        ; ..and compare
  1089.     jr    nz,du2dir1    ; If mismatch, back for another try
  1090.     inc    hl        ; Point to name
  1091.     dec    a        ; Force NZ to show successful match
  1092.     ret
  1093.  
  1094.  
  1095. ; Pop the top shell stack entry
  1096.  
  1097. SHPOP:
  1098.  
  1099. ; ***
  1100. ;Special function for RCPCLED -- null saved command line
  1101.     ld    a,(era_flag)    ; Erase?
  1102.     or    a
  1103.     jr    z,eflag1    ; Z = NO
  1104.     xor    a
  1105.     ld    (history),a
  1106. eflag1:
  1107. ; ***
  1108.  
  1109. ;shpop:
  1110.     call    getsh        ; HL -> stack, DE = size, B = entries
  1111.     ret    z        ; No stack
  1112.     ld    c,e        ; Entry size
  1113.     ld    a,(hl)
  1114.     or    a
  1115.     ret    z        ; Empty
  1116.     ex    de,hl
  1117.     add    hl,de        ; HL -> next entry, DE -> first entry
  1118.     xor    a
  1119. shpop1:
  1120.     ld    (de),a        ; Zero entry
  1121.     dec    b
  1122.     ret    z        ; Successful exit, no more entries
  1123.     push    bc        ; Pop next entry
  1124.     ld    b,0
  1125.     ldir
  1126.     pop    bc
  1127.     jr    shpop1
  1128.  
  1129.  
  1130. shpush:
  1131.     push    hl        ; Save string pointer
  1132.     call    getsh
  1133.     jr    z,shpush_err1    ; No stack
  1134.  
  1135. shpush3:    
  1136.     ld    a,(hl)        ; Look for free entry
  1137.     or    a
  1138.     jr    z,shpush4
  1139.     add    hl,de
  1140.     djnz    shpush3
  1141.     jr    shpush_err2    ; Stack full
  1142. shpush4:    
  1143.     call    getsh        ; Point to top of stack
  1144.     push    bc
  1145. shpush5:    
  1146.     dec    b
  1147.     jr    z,shpush6
  1148.     add    hl,de
  1149.     jr    shpush5
  1150. shpush6:    
  1151.     pop    bc
  1152.     ld    c,e
  1153.     dec    hl
  1154.     ex    de,hl
  1155.     add    hl,de        ; HL -> (entry-1) + size, DE -> (entry-1)
  1156.     ex    de,hl
  1157. shpush7:    
  1158.     ld    a,b
  1159.     cp    1
  1160.     jr    z,shpush8
  1161.     dec    b
  1162.     push    bc
  1163.     ld    b,0
  1164.     lddr
  1165.     pop    bc
  1166.     jr    shpush7
  1167. shpush8:    
  1168.     call    getsh
  1169.     pop    de
  1170.     ex    de,hl
  1171. shpush9:    
  1172.     ld    a,(hl)
  1173.     ldi
  1174.     or    a
  1175.     jr    nz,shpush9
  1176.  
  1177. shpushx:
  1178.     ret
  1179.  
  1180. shpush_err1:    
  1181. ;    ld    a,1    ; No stack
  1182. ;    jr    shpush_err
  1183.  
  1184. shpush_err2:
  1185.     ld    a,2    ; Stack full
  1186. shpush_err:
  1187.     pop    hl
  1188.     or    a
  1189.     ret
  1190.  
  1191.  
  1192. ; Get shell stack entry
  1193. ; Return HL -> top of stack
  1194. ;     DE =  entry size
  1195. ;      C =  unchanged
  1196. ;      B =  # entries
  1197. ;      A =  # entries
  1198. ;      Z =  no entries
  1199. getsh:
  1200.     ld    hl,(z3env+1eh)    ; Stack
  1201.     ld    a,(z3env+20h)    ; # entries
  1202.     ld    b,a
  1203.     ld    de,(z3env+21h)    ; Entry size in E
  1204.     ld    d,0
  1205.     or    a
  1206.     ret
  1207.  
  1208. ;
  1209. ;=====    C L O C K   R E A D I N G  ==================================
  1210. ;
  1211.  
  1212.      if    systime
  1213.  
  1214. ; Print system time from DateStamper, ZS/ZDDOS/Z3PLUS clock
  1215.  
  1216. ; Entry point
  1217. ;  Print the string with leading '0' suppression
  1218. ;  Format: "h.mm " or "hh.mm "
  1219.  
  1220. print_time:
  1221.  
  1222. ; 1. Test for DateStamper/ZSDOS/Z3PLUS and read clock if present
  1223.  
  1224.     ld    c,12        ; Return version
  1225.     ld    e,'D'        ; DateStamper test
  1226.     call    bdos
  1227.     ld    a,l        ; Version #
  1228.     cp    30h        ; Z3PLUS?
  1229.     jr    nc,time1    ; Yes
  1230.     ld    a,h
  1231.     cp    'D'
  1232.     ret    nz        ; No clock
  1233.  
  1234. ; 2. Get time
  1235.  
  1236.     ld    hl,time2
  1237.     push    hl        ; Return address on stack
  1238.     push    de        ; Clock address on stack
  1239.     ld    hl,dtbuf    ; Point to buffer
  1240.     ret            ; Call clock, return to time2
  1241. time1:                ; Z3PLUS entry point
  1242.     ld    c,105        ; CP/M Plus get time
  1243.     ld    de,dtbuf+1
  1244.     push    de
  1245.     call    bdos
  1246.     pop    hl
  1247.     ld    a,(hl)
  1248.     inc    hl
  1249.     ld    b,(hl)
  1250.     dec    a
  1251.     or    b
  1252.     ret    z        ; No clock if date = 0001
  1253. time2:
  1254.  
  1255. ; 3. Turn highlight on, if present
  1256.  
  1257.     ld    hl,stndout
  1258.     call    printhl
  1259.  
  1260.     ld    hl,dtbuf+3    ; Point to hours
  1261.  
  1262. ; 4. Convert military time to civilian, if selected
  1263.  
  1264.      if civtim    
  1265.     ld    a,(hl)        ; Hours
  1266.     or    a        ; Midnight?
  1267.     jr    nz,time3    ; No
  1268.     ld    a,24h        ; Yes, say "12"
  1269. time3:    sub    13h        ; Time past 12:59 pm?
  1270.     jr    c,time4        ; No, don't change
  1271.     daa            ; Decimal adjust
  1272.     inc    a        ; Yes, xlate to 12-hour
  1273.     daa
  1274.     ld    (hl),a        ; ..and patch in.
  1275.      endif    ; civtim
  1276.  
  1277. ; 5. Display time
  1278.  
  1279. time4:
  1280.     xor    a
  1281.     call    pmbcd        ; Print hours as 1 or 2 digits
  1282.     ld    a,(tim_sep)    ; Print separator between hours, minutes
  1283.     call    conout
  1284.     inc    hl        ; Point to minutes
  1285.     ld    a,80h        ; Say print leading 0
  1286.     call    pmbcd        ; Print minutes as 2 digits
  1287.  
  1288. ; 2. Turn highlight off, if present
  1289.  
  1290.     ld    hl,stndend
  1291.     call    printhl
  1292.     jp    spac        ; Space before rest of prompt
  1293.  
  1294. ;
  1295. ;=====    D A T A  ====================================================
  1296. ;
  1297.  
  1298. ; Buffer for date/time for read/write system clock
  1299.  
  1300. dtbuf:    ds    6
  1301.  
  1302.      endif    ;systime
  1303.  
  1304.  
  1305. line        ds    2        ; Pointer to line buffer
  1306. recall_ptr    ds    2        ; History position pointer
  1307. history        ds    HISTSIZE,0    ; History buffer
  1308. hbuf_top:    equ    $-1
  1309.  
  1310. ; End RCPCLED.LIB
  1311.