        section edline

err.bo  equ     -5
err.no  equ     -6
err.bp  equ     -15

bv_chbas equ    $30
bv_chp  equ     $34
bv_rip  equ     $58

ch.id   equ     $00
ch.lench equ    $28

io.edlin equ    $04
io.sbyte equ    $05
io.sstrg equ    $07
sd.chenq equ    $0B
sd.curs equ     $0F
sd.pos  equ     $10
sd.pcol equ     $13

bp.init equ     $110
ca.gtint equ    $112
ca.gtstr equ    $116
bv.chrix equ    $11A

* QL WORLD DIY TOOLKIT - EDLINE$ function, by Simon N Goodwin
* rewritten by Laurence W Reeves.

start
        lea     define,a1
        move.w  bp.init,a2
        jmp     (a2)

define
        dc.w    0,0             No procedures
        dc.w    1               One function
        dc.w    edline-*
        dc.b    7,'EDLINE$'
        dc.w    0               End of functions

edline
        moveq   #err.bp,d0      BAD PARAMETER error
        add.w   #3*8,a3
        cmp.l   a3,a5
        bne.s   rts0            Ensure exactly three parameters

* Get the default string

        subq.l  #8,a3           Retrieve just the last parameter
        move.w  ca.gtstr,a2     get a string
        jsr     (a2)
        bne.s   rts0

* Read the first two parameters: channel number and buffer size

        move.l  a3,a5
        sub.w   #2*8,a3         get the other two parameters
        move.w  ca.gtint,a2     get two ints
        jsr     (a2)
        bne.s   rts0
        movem.w 0(a1,a6.l),d5-d7 Get channel number, buffer and string lengths

* Convert channel number to channel ID

        moveq   #err.no,d0      CHANNEL NOT OPEN error
        mulu    #ch.lench,d5    Find offset in table
        add.l   bv_chbas(a6),d5 Add base offset
        cmp.l   bv_chp(a6),d5   Check not beyond end
        bge.s   rts0
        move.l  ch.id(a6,d5.l),d5 Get channel ID
        bmi.s   rts0            Channel must be open

* Validate initial string length

        moveq   #err.bo,d0      BUFFER FULL error
        move.l  d6,d1
        sub.w   d7,d1           is the string already too big for the buffer?
        blt.s   rts0            if so (or buffer length is negative), get out
        addq.l  #2,d1           allow extra for coordinates if string is null
        move.w  bv.chrix,a2
        jsr     (a2)            ensure enough space for longest text

        move.l  bv_rip(a6),a2
        addq.l  #6,a2           position to start of default string

* Find out where we are on the screen

        move.l  d5,a0           Channel ID
        moveq   #-1,d3          Timeout

        lea     -8(a2),a1       place to read initial coords to
        moveq   #sd.chenq,d0
        bsr.s   rel_QDOS
        move.l  -4(a6,a2.l),d5  pick up coords and save them

* Put the string in the buffer

        addq.l  #1,d6           add one to buffer length for terminator
        lea     0(a2,d7.l),a3
        sub.l   d6,a3           good enough for buffer location
        move.l  a3,a1
        move.w  d7,d1
        bra.s   buff_ent

rel_QDOS
        trap    #4
call_QDOS
        trap    #3              General-purpose ROM caller
        tst.l   d0
        beq.s   rts0
        addq.l  #4,a7           Return to previous caller
rts0
        rts

buff_lp
        move.b  0(a6,a2.l),0(a6,a1.l)
        addq.l  #1,a2
        addq.l  #1,a1
buff_ent
        dbra    d1,buff_lp
        moveq   #1,d1
        and.w   d7,d1
        add.w   d1,a2           set top of stack

* Go to the initial cursor position and print the text

go_there
        move.l  d5,d1
        swap    d1              Extract cursor X
        move.w  d5,d2           Extract cursor Y
        moveq   #sd.pos,d0
        bsr.s   call_QDOS
        move.l  a3,a1
        move.w  d7,d2
        moveq   #io.sstrg,d0
        bsr.s   rel_QDOS
        moveq   #' ',d1
        moveq   #io.sbyte,d0    blank end of line
        bsr.s   call_QDOS
        moveq   #sd.pcol,d0     move cursor to blank
        bsr.s   call_QDOS

* Call up the editor

        move.w  d7,d1           Put cursor at end of text
        swap    d1
        move.w  d7,d1           Indicate length of text
        lea     0(a3,d1.w),a1   Point to last character
        move.w  d6,d2           Maximum length
        moveq   #io.edlin,d0
        trap    #4
        trap    #3
        subq.w  #1,d1           Don't count last character
        move.w  d1,d7           Slide up to the end-stop
        move.l  d0,d2           Save and test the error code
        beq.s   edited          No error: check terminator
        moveq   #sd.curs,d0     for AH & JM ROMs & err.bo
        bsr.s   call_QDOS       which leave the cursor on
        move.l  d2,d0           restore the error code
        addq.l  #-err.bo,d2     Was it buffer overflow?
        beq.s   go_there        Yes, so try again
        rts                     Give up if anything else!

edited
        sub.b   #10,-1(a6,a1.l) (tidy to make pad byte come out zero)
        bne.s   go_there        Restart unless last character was ENTER
        btst    d0,d1           see if string is an odd length
        beq.s   fin_ent         no padding byte
fin_loop
        move.b  -1(a6,a1.l),-1(a6,a2.l)
        subq.l  #1,a2
fin_ent
        subq.l  #1,a1
        dbra    d7,fin_loop
        move.l  a2,a1
        subq.l  #2,a1           Make room to stack length 
        move.l  a1,bv_rip(a6)   Reset maths stack pointer
        move.w  d1,0(a6,a1.l)   set string length
        moveq   #1,d4           Return a string
        rts

        end
