Subversion Repositories MB01 Project

Rev

Blame | Last modification | View Log | Download | RSS feed


; need for include CRTC
_VBB_INC_       .SET    1
_KBD_INC_       .SET    1

        .INCLUDE inc\global.inc
        .LIST off
        .INCLUDE inc\dirp00.inc
        .INCLUDE inc\dirp01.inc
        .LIST on
        .INCLUDE inc\dpqedt.inc

        .CODEFD
        .LONGA off
        .LONGI off

;---------------------------------------------------

; editor main loop
editor:
        jsr     setcurs                 ; set cursor mode
?10:    ldy     scol                    ; current screen column
        jsr     edcurs                  ; set cursor position on edit window
        jsr     showcurs                ; show cursor
?12:    KBGETIN                         ; system call - get key
        tax
        bne     ?14                     ; a key was pressed
        jsr     garbc                   ; call garbage collection
        lda     #$02                    ; update caps & num only
        tsb     slfg
        jsr     updsl
        bra     ?12
?14:    sta     ctmp                    ; store key code
        xba
        sta     ctmp2                   ; store control key flag
        jsr     hidecurs
        lda     >DP01ADDR+KbdFlag       
        sta     keyfg                   ; flag ALT, CTL, SHIFT
        lda     ctmp                    ; A = key code
        bit     ctmp2                   ; check control key flag
        bpl     ?22                     ; no-control key        
        cmp     #KB_ALTF1               ; ALT-F1..ALT-F11 switch buffer
        bcc     ?16
        cmp     #KB_ALTF12
        bcs     ?16
        sbc     #KB_ALTF1-1
        cmp     xbuf                    ; is the current buffer?
        beq     ?10                     ; yes, skip
        jsr     ?50                     ; switch to buffer
        bra     ?10                     ; loop
?16:    ldx     #KEYTBLLEN              ; check control key
?18:    cmp     >KEYTBL,x
        beq     ?20
        dex
        bpl     ?18
        bmi     ?10                     ; discard
?20:    txa
        asl     a
        tax
        jsr     (KEYPROC,x)             ; execute key control function
        bra     ?23                     ; loop
?22:    tax                             ; no-control key
        bmi     ?10                     ; discard if key code >= 128
        jsr     ?80                     ; no-control key process
?23:    bit     edtfg                   ; test bit 7 for quit command
        bpl     ?10                     ; loop
?24:    rts

; switch current edit buffer
?50:    jsr     switchb
        bcs     ?24                     ; memory error
        stz     fslct                   ; clear select mode flag
        lda     #$01
        trb     slfg
        lda     #$0C
        sta     srow
        lda     #$27
        sta     scol
        ldx     xbuf
        lda     #$40
        trb     edtfg                   ; clear clipboard flag
        cpx     #CLIPBRD
        bne     ?52
        tsb     edtfg                   ; set clipboard flag
?52:    tsb     slfg                    ; force update status line
        lda     cursmode
        and     #$BF                    ; mask off bit 6
        bit     bflag
        bvs     ?54                     ; overwrite mode => block cursor
        ora     #$40                    ; insert mode => underline cursor
?54:    sta     cursmode
        jsr     setcurs
        jmp     updwin

; process key code < 128
?76:    txa
        asl     a
        tax
        jmp     (KEYPROC2,x)
?80:    cmp     #' '
        bcs     edkey                   ; printable key code, insert in buffer 
        ldx     #KEYTBLLEN2             ; find function for key code < 32
?84:    cmp     >KEYTBL2,x
        beq     ?76
        dex
        bpl     ?84
kpx:    rts                             ; discard

; P12AF:
edkey:
        LDX     fslct
        bne     kpx
        LDX     ccnt
        CPX     #MAXTEXTLEN-1
        beq     kpx
        LDX     ccol
        CPX     ecol
        bcc     kpx
        tax
        ACC16
        lda     cline
        cmp     #MAXLINES
        ACC08
        bcs     kpx
        txa
        JSR     insert
        bcs     kpx
        JSR     incptr2
        LDX     ccol
        INX
        STX     ccol
        STX     xcol
        INC     ccnt
        JSR     getbyte2
        BCC     ?02
        LDA     #$0D                    ; new line
        JSR     insert
        BCC     ?01
?00:    JSR     decptr2                 ; error
        JMP     delbyte
?01:    ACC16
        lda     ncount
        inc     a
        cmp     #MAXLINES
        ACC08
        bcs     ?00                     ; no insert a new line
        INC     scol
        JSR     mvpp2
        JSR     nextln
        ACC16
        LDA     ppage
        STA     pp6
        inc     ncount
        ACC08
        LDA     ixb
        STA     ix6
        JSR     pp2mv
        INC     rcnt
        JMP     updwin0
?02:    LDA     scol
        CMP     #COLX
        BCC     ?03
        INC     ecol
        JSR     scrlright
        bra     updrow8
?03:    INC     scol

; P145F:
updrow8:
        ACC16
        lda     curs
        sta     stxtp
        ora     #!TXTATTR
        sta     sattp
        ACC08
        LDX     pp8
        lda     pp8+1
        LDY     ix8
        JSR     setptr
        lda     #$01                    ; no update window while indent...
        bit     edtfg                   ; ... blank's insertion
        bne     tbx
        JSR     updrow
        JMP     updsl

; tasto TAB
; P313E:
tabkey: 
        lda     #0
?0:     clc
?1:     adc     deftab
        cmp     ccol
        beq     ?0
        bcc     ?1
        SBC     ccol
        STA     ctmp2
?02:    LDA     ccol
        CMP     ccnt
        BNE     ?03
        LDA     #$20
        JSR     edkey
        bra     ?04
?03:    jsr     csrrght
?04:    DEC     ctmp2
        BNE     ?02
tbx:    RTS 

; 'del' key
; execute 'csrright' and after a 'backkey'
delkey:
        LDX     ccol
        CPX     ccnt
        BEQ     tbx
        INX
        STX     ccol
        STX     xcol
        JSR     incptr2
        LDA     scol
        CMP     #COLX
        BCC     ?01
        INC     ecol
        bra     backkey
?01:    INC     scol

; tasto BACKSPACE
; P1316:
backkey:
        LDA     fslct
        bne     ?02
        LDA     ccol
        CMP     ecol
        bcc     ?02
        JSR     decptr2
        bcs     ?02
        JSR     getbyte2
        CMP     #$0D
        BEQ     ?03
        JSR     delbyte
        DEC     ccol
        LDA     ccol
        STA     xcol
        DEC     ccnt
        JSR     nextln8
        JSR     updrow8
        JSR     xcount
        INX
        CPX     scol
        BEQ     ?01
        DEC     ecol
        JMP     scrlleft
?01:    DEC     scol
?02:    RTS
?03:    JSR     mvpp2
        JSR     incptr2
        JSR     startln
        JSR     nextln
        STX     ctmp
        JSR     nextln
        JSR     pp2mv
        TXA
        CLC
        ADC     ctmp
        BCC     ?04
        JMP     incptr2
?04:    CMP     #MAXTEXTLEN
        BCC     ?05
        JMP     incptr2
?05:    JSR     incptr2
        JSR     getbyte2
        BCC     ?08
        JSR     decptr2
        JSR     decptr2
        BCS     ?09
        JSR     getbyte2
        CMP     #$0D
        BEQ     ?06
        JSR     incptr2
        JMP     incptr2
?06:    JSR     incptr2
        bra     ?09
?08:    JSR     decptr2
?09:    ACC16
        dec     cline
        dec     ncount                  ; check this !!
        ACC08
        JSR     delbyte
        LDA     #COLX
        STA     scol
        LDA     srow
        CMP     #$0D
        bcs     ?10
        JSR     startln4
        BCC     ?11
?10:    JSR     nextln6
        JSR     decrow
?11:    JMP     updwin0

; tasto CURSORE SX
; P1D31:
csrleft:
        LDX     ccol
        CPX     ecol
        BCS     ?01
        STX     xcol
        DEC     ecol
        JMP     scrlleft
?01:    CPX     #$00
        BEQ     slt
        DEX
        STX     ccol
        STX     xcol
        JSR     decptr2
        LDA     scol
        CMP     #$05
        BCS     ?02
        JSR     xcount
        INX
        CPX     scol
        BEQ     ?02
        DEC     ecol
        JSR     scrlleft
        JMP     updsl
?02:    DEC     scol
        JMP     updsl

; tasto CURSORE DX
; P1D0C:
csrrght:
        LDX     ccol
        CPX     ccnt
        BEQ     slt
        INX
        STX     ccol
        STX     xcol
        JSR     incptr2
        LDA     scol
        CMP     #COLX
        BCC     ?01
        INC     ecol
        JSR     scrlright                       ; scroll right
        JMP     updsl
?01:    INC     scol
        JMP     updsl

; toggle select mode flag
; P1F22:
seltxt:
        LDA     fslct
        BEQ     ?01
        STZ     fslct                           ; clear if enabled
        JMP     updwin0
?01:    JSR     getbyte
        BCS     slt
        INC     fslct
        LDA     pp8
        STA     pp0
        LDA     pp8+1
        STA     pp0+1
        LDA     ix8
        STA     ix0
        STZ     nslctl
        stz     nslcth
        jsr     updsl
slt:    RTS

; tasto CURSORE UP
; P1D66:
csrup:
        LDA     srow
        CMP     #$07
        BCC     ?01
        JSR     decrow
        bra     ?03
?01:    JSR     startln4
        BCC     ?02
        LDA     srow
        beq     slt                     ; exit
        JSR     decrow
        bra     ?03
?02:    JSR     startln6
        JSR     scrlup
        JSR     updfst
?03:    JSR     pp8mv
        JSR     startln
        JSR     mvpp8
        LDX     xcol
        JSR     xcnt2
        LDA     fslct
        BEQ     ?07
        ACC16CLC
        lda     curs
        dec     nslctl
        bpl     ?05
        ADC     #MAXCOLS
?05:    STA     stxtp
        ACC08
        JSR     revrow
?07:    ACC16
        dec     cline
        ACC08
        JMP     updsl

; tasto CURSORE DOWN
; P1E62:
csrdwn:
        JSR     getbyte2
        bcs     slt                     ; exit if end of buffer
        LDA     srow
        CMP     #$11
        BCS     ?01
        JSR     incrow
        bra     ?03
?01:    JSR     scrldown
        JSR     nextln4
        JSR     nextln6
        BCS     ?02
        JSR     updlst
        bra     ?03
?02:    JSR     clrlst
?03:    JSR     nextln
        JSR     mvpp8
        LDX     xcol
        JSR     xcnt2
        LDA     fslct
        ACC16CLC
        BEQ     ?07
        lda     curs
        bit     nslctl
        bmi     ?05
        SBC     #MAXCOLS-1              ; take in account CF = 0 !
?05:    sta     stxtp
        ACC08
        JSR     revrow
        ACC16
        inc     nslctl
?07:    inc     cline
        ACC08
        JMP     updsl

; SHIFT+END -> fine linea
; P310D:
goendln:
        JSR     nextln
        BCS     ?01
        JSR     decptr2
?01:    LDA     #COLX
        STA     scol
        JMP     updwin0

; ; SHIFT+HOME -> inizio linea
; P311D:
gostartln:
        JSR     nextln
        BCS     ?01
        JSR     startln
?01:    JMP     updwin0

; P1EC8:
pagedwn:
        LDA     #$14
        STA     ctmp
?01:    JSR     nextln
        BCS     ?03
        LDA     fslct
        ACC16
        BEQ     ?02
        INC     nslctl
?02:    INC     cline
        ACC08
?03:    DEC     ctmp
        BNE     ?01
        LDA     #$11
        bra     epage

; P1EF1:
pageup:
        LDA     #$14
        STA     ctmp
        JSR     pp8mv
?01:    JSR     startln
        BCS     ?05
        LDA     fslct
        ACC16
        BEQ     ?03
        DEC     nslctl
?03:    DEC     cline
        ACC08
?05:    DEC     ctmp
        BNE     ?01
        LDA     #$06

; P1F1D:
epage:
        STA     srow
        jmp     updwin

; HOME - inizio buffer
; P30C5:
gohome:
        ACC16
        LDA     pbuf                    ; set current block to first block
        STA     ppage
        LDX     #BSTART
        STX     ixb
        LDX     fslct                   
        BEQ     ?01                     ; no selection
        SEC
        LDA     nslctl                  ; update selection range
        SBC     cline
        STA     nslctl
?01:    STZ     cline                   ; current line = 0
        ACC08
        bra     updwin

; END - fine buffer
; P30EC:
goend:
        ACC16
?00a:   lda     [pblk]
        beq     ?00b
        sta     ppage
        bra     ?00a
?00b:   ACC08   
        ldy     #BSTART
        sty     ixb
        jsr     nextln
        bcs     ?04
        jsr     decptr2
        jsr     decptr2 
?00c:   jsr     nextln
        bcc     ?00c
        ACC16
        lda     ncount
        ldy     fslct
        beq     ?02
        sta     wtmp
        sec
        sbc     cline
        clc
        adc     nslctl
        sta     nslctl
        lda     wtmp
?02:    sta     cline
        ACC08
?04:    LDA     #$11                    ; set screen row
        STA     srow
        bra     updwin

; tasto SHIFT RETURN
; P3129:
kshenter:
        LDA     fslct
        beq     kshe
kshr:   rts
kshe:   JSR     nextln                  ; find next line
        BCS     ke2
        JSR     decptr2                 ; decrement pointer
        bra     ke2

; tasto RETURN
; P288F:
kenter:
        LDX     fslct
        bne     kshr
ke2:    jsr     xblank                  ; count of starting blanks
        jsr     inscr                   ; insert byte $0D (enter key code)
        bcs     kshr                    ; error
        JSR     incptr2
        LDA     srow
        CMP     #$11
        BCS     ?02
        JSR     incrow                  ; increment cursor row
        JSR     startln6
        bra     ?03
?02:    JSR     nextln4
?03:    STZ     scol                    ; screen column = 0
        ACC16
        INC     cline                   ; increment current line
        inc     ncount
?05:    ACC08
        jsr     indent

; P19DB:
updwin0:
        LDA     #$00                    ; no cursor address update
        BEQ     updatew

; P19E0:
updwin:
        LDA     #$01                    ; update cursor address

; P19E3:
updatew:
        PHA
        JSR     mvpp2
        JSR     getbyte
        BCS     ?02
        JSR     incptr
        JSR     startln
        DEX
        bra     ?03
?02:    LDX     #$00
?03:    STX     ccol                    ; update current editor column
        STX     xcol
        TXA
        SEC
        SBC     scol
        BCS     ?04
        LDA     ccol
        STA     scol
        LDA     #$00
?04:    STA     ecol
        JSR     mvpp8
        JSR     nextln
        STX     ccnt
        lda     $01,s
        BEQ     ?05
        JSR     pp8mv
        JSR     findrow
?05:    JSR     chksel
        ACC16
        sec
        LDA     #!TXTADDR
        SBC     #MAXCOLS
        STA     stxtp
        sec
        LDA     #!TXTATTR
        SBC     #MAXCOLS
        sta     sattp
        ACC08
        LDA     #$FF
        STA     ctmp
        LDX     pp4
        lda     pp4+1
        LDY     ix4
        JSR     setptr
?06:    ACC16CLC        
        LDA     stxtp
        ADC     #MAXCOLS
        sta     stxtp
        clc
        LDA     sattp
        ADC     #MAXCOLS
        sta     sattp
        ACC08
        INC     ctmp
        LDA     fslct
        BEQ     ?07
        LDA     ctmp
        CMP     rslctl
        BCC     ?07
        CMP     rslcth
        BCS     ?07
        LDA     #$80
        STA     frev
?07:    JSR     updrow
        BCS     ?08
        LDA     ctmp
        CMP     #$17
        BNE     ?06
        CLC 
?08:    lda     $01,s
        BEQ     ?11
        LDA     >updr1+2                ; page
        BCS     ?09
        STA     ppage
        lda     sbank                   ; bank
        STA     ppage+1
        STX     ixb
        JSR     startln
        LDA     ppage
        STA     pp6
        LDA     ppage+1
        STA     pp6+1
        LDA     ixb
        STA     ix6
        bra     ?10
?09:    STA     pp6
        lda     sbank
        sta     pp6+1   
        STX     ix6
?10:    LDA     ctmp
        STA     rcnt
?11:    LDA     ctmp
        CMP     #$17
        BEQ     ?13
        ACC16CLC
        LDA     stxtp
        ADC     #MAXCOLS
        STA     stxtp
        clc
        LDA     sattp
        ADC     #MAXCOLS
        STA     sattp
        ACC08
        LDA     #' '
        xba
        lda     eattr                   ; A = attribute, B = blank
        LDY     #MAXCOLS-1
?12:    sta     [sattp],y               ; store attribute
        xba
        sta     [stxtp],y               ; store blank
        xba
        DEY
        BPL     ?12
        INC     ctmp
        bra     ?11
?13:    JSR     pp2mv
        PLA
        beq     updsl
        STZ     curs+1
        LDA     srow
        ASL     a
        ASL     a                       ; srow * 4
        ADC     srow                    ; srow * 5
        ASL     a
        ASL     a                       ; srow * 20
        ROL     curs+1
        ASL     a                       ; * 40
        ROL     curs+1
        ASL     a                       ; * 80
        ROL     curs+1
        STA     curs
        LDA     curs+1
        ADC     #>TXTADDR
        STA     curs+1
        bra     updsl

; print error message in status line and wait for <enter> key pressed
; in:   X - error number
; P1C3D:
error:
        lda     seatt                   ; error attribute
        jsr     msgstr
        jsr     waitent
        lda     #$40                    ; force update status line
        ;tsb    slfg
        sta     slfg

; update status line (edit mode only)
; P2989:
updsl:
        bit     slfg
        bpl     ?00                     ; skip if in command line mode
        rts     
?00:    bvc     ?04                     ; partial update only
        lda     slattr                  ; status line attribute
        xba
        bit     edtfg
        bvc     ?02                     ; standard edit buffer
        ldx     #<stlstr2               ; clipboard status line string
        ldy     #>stlstr2
        bra     ?03
?02:    ldx     #<stlstr        ; std cbm fs buffer status line string
        ldy     #>stlstr
        bit     fsmode          ; <7>: cbm fs
        bmi     ?03
        ldx     #<stlstr1       ; std fat buffer status line string
        ldy     #>stlstr1
?03:    lda     #^stlstr
        jsr     outstr
        bra     ?05
?04:    ACC16
        lda     #!STLINE                ; set address of last screen row
        sta     stxtp
        lda     #!STLATTR
        sta     sattp
        ACC08
?05:    lda     #$02
        bit     slfg                    ; test bit 1
        beq     ?05a
        jmp     ?70                     ; update caps & num only        
?05a:   lda     xbuf                    ; update buffer # indicator
        cmp     xbuf1
        bne     ?06                     ; changed: update
        bit     slfg                    ; not changed, check if forced update
        bvc     ?12                     ; no forced update
?06:    sta     xbuf1                   ; store buffer #
        bit     edtfg                   ; skip buffer # for clipboard
        bvs     ?12 
?08:    ora     #'0'                     ; buffer # = 0..9
?10:    ldy     #8                      ; index of buffer #
        sta     [stxtp],y               ; update
        jsr     ?cfn            ; update filename
?12:    ACC16
        lda     ncount                  ; update total lines count
        cmp     ncount1
        sta     ncount1                 ; save in advance for update
        sta     wtmp                    ; save in advance for conversion
        ACC08
        bne     ?14                     ; changed: update
        bit     slfg                    ; not changed, check if forced update
        bvc     ?16                     ; no forced update
?14:    jsr     int2str                 ; convert in string
        ldx     #5                      ; 5 digits
        ldy     #$3B                    ; column of N#
        jsr     ?100
?16:    ACC16
        lda     cline                   ; update current line #
        cmp     cline1
        sta     cline1                  ; save in advance for update
        php
        inc     a
        sta     wtmp                    ; save in advance for conversion
        plp
        ACC08
        bne     ?18                     ; changed: update
        bit     slfg                    ; not changed, check if forced update
        bvc     ?20                     ; no forced update
?18:    jsr     int2str                 ; convert in string
        ldx     #5                      ; 5 digits
        ldy     #$44                    ; column of L#
        jsr     ?100
?20:    lda     ccol                    ; update current column #
        cmp     ccol1
        bne     ?22                     ; changed: update
        bit     slfg                    ; not changed, check if forced update
        bvc     ?24                     ; no forced update
?22:    sta     ccol1
        inc     a
        jsr     byte2str                ; convert in string
        ldx     #3                      ; 3 digits
        ldy     #$4C                    ; column of C#
        jsr     ?100    
?24:    lda     bflag                   ; update flag's indicator's
        cmp     bflag1
        bne     ?26                     ; changed: update
        bit     slfg                    ; not changed, check if forced update
        bvc     ?34                     ; no forced update
?26:    sta     bflag1
        ldx     fgatt                   ; X = disabled flag attribute
        clc
        bit     bflag1                  ; check modified flag
        bpl     ?28
        sec                             ; enabled
?28:    ldy     #$2E                    ; column of M indicator
        jsr     ?80
        clc
        bit     bflag1                  ; check overwrite flag
        bvc     ?30
        sec                             ; enabled
?30:    ldy     #$32                    ; column of O indicator
        jsr     ?80
        clc
        lda     #$20
        bit     bflag1                  ; check indent mode flag
        beq     ?32
        sec                             ; enabled
?32:    ldy     #$30                    ; column of I indicator
        jsr     ?80
?34:    lda     fslct                   ; select mode flag
        tax
        eor     slfg
        lsr     a                       ; bit 0 only
        bcs     ?36                     ; changed: update
        bit     slfg                    ; not changed, check if forced update
        bvc     ?40                     ; no forced update
?36:    lda     #$FE                    ; set/reset bit 0 of slfg
        and     slfg
        txy
        beq     ?38                     ; reset
        ora     #$01                    ; set
?38:    sta     slfg
        lsr     a                       ; CF = indicator status
        ldx     fgatt                   ; X = disabled flag attribute
        ldy     #$34                    ; column of S indicator
        jsr     ?80
        
?40:
?70:    ldx     fgatt                   ; X = disabled flag attribute
        lda     >DP01ADDR+KbdToggle
        sta     tmpf
        clc
        bpl     ?72                     ; caps lock disabled                    
        sec                             ; caps lock indicator enabled
?72:    ldy     #$35                    ; column of C indicator
        jsr     ?80
        clc
        bit     tmpf                    ; check num lock
        bvc     ?74
        sec                             ; num lock indicator enabled
?74:    ldy     #$36                    ; column of N indicator
        jsr     ?80
        lda     #$42                    ; clear forced update
        trb     slfg
        rts

; set/unset indicator flag on status line
?80:    lda     slattr                  ; set status
        bcs     ?82
        txa                             ; unset status
?82:    sta     [sattp],y
        rts

; output stringa tstr2 at column Y, X bytes
?100:   stx     tmp6
        ldx     #0
?102:   lda     <tstr2,x
        sta     [stxtp],y
        inx
        iny
        dec     tmp6
        bne     ?102
        rts

; update cbm filename field
?cfn:
        ldx     #0
        ldy     #$0B            ; index of cbm filename
?cfnl:  lda     >EDCURFILE,x
        beq     ?cfne
        sta     [stxtp],y
        inx
        iny
        cpx     #18
        bcc     ?cfnl
?cfne:  rts

; toggle insert flag
; control key: insert key
tins:
        lda     #$40                    ; insert flag
        tax
        eor     bflag                   ; toggle
        sta     bflag
        txa
        eor     cursmode                ; toggle under/block cursor
        sta     cursmode
        jsr     setcurs
        jmp     updsl

; toggle indent flag
; Ctrl+TAB or Ctrl+I (control key)
tind:
        lda     #$20                    ; indent flag
        eor     bflag
        sta     bflag
        jmp     updsl

; indent new line
indent:
        lda     #$20                    ; test indent flag
        bit     bflag
        beq     ?04                     ; no indent
        lda     ctmp
        beq     ?04                     ; no blanks
        lda     #$01                    ; no update edit window while indent...
        tsb     edtfg                   ; ... blank's insertion
?02:    lda     #' '                    ; insert starting blanks
        jsr     edkey
        dec     ctmp
        bne     ?02
        lda     #$01                    ; restore flag
        trb     edtfg
?04:    rts

;---------------------------------------------------

; CTRL Y
delline:
        jsr     mvpp2
        JSR     nextln
        bcc     ?04
?02:    jmp     pp2mv   
?04:    lda     ppage
        sta     pb+1
        lda     ppage+1
        sta     pb+2
        lda     ixb
        sta     tmpf
        JSR     startln                 ; first byte of this line
        bcs     ?02
        ACC16
        dec     ncount
        lda     ppage
        cmp     pb+1
        ACC08
        beq     ?10                     ; whole line just in one block
        LDA     ixb
        CMP     #BSTART
        BNE     ?06
        LDA     ppage+1                 ; block can be free'd
        xba
        lda     ppage
        JSR     delblk
        bra     ?08
?06:    dec     a                       ; just one byte less
        LDY     #BNDX
        STA     [pblk],Y
?08:    LDA     pb+1                    ; go in the next block
        sta     ppage
        lda     pb+2
        sta     ppage+1
        lda     #BSTART                 ; line continue at beginning... 
        sta     ixb                     ; ...of next block
?10:    LDY     #BNDX                   ; now move back bytes
        lda     [pblk],y
        sta     tmp6
        LDY     tmpf
        DEY
        STY     tmp7
        LDX     ixb
        DEX
?12:    INC     tmp7
        inx
        LDY     tmp7
        lda     [pblk],y
        txy
        STA     [pblk],Y
        lda     tmp6
        CMP     tmp7
        BNE     ?12
        txa
        LDY     #BNDX
        STA     [pblk],Y
        JMP     updwin

        
copysel:
        lda     #$02                    ; copy operation: reset flag
        trb     edtfg
        stz     ctmp2                   ; copy op (zero)
        bra     ct1

cberr:
        ldx     #$05
        jmp     error                   ; Clipboard: illegal command

; CUT
; P1F4F:
cutsel:
        lda     #$02                    ; cut operation: set flag
        tsb     edtfg
        sta     ctmp2                   ; cut op (not zero)                     
ct1:    bit     edtfg
        bvs     cberr                   ; clipboard error
        LDA     fslct
        beq     ?00a
        stz     fslct
        LDA     #CLIPBRD
        JSR     freebuf
        STZ     pb
        STZ     pd
        JSR     mvpp2
        JSR     newblk                  ; need at least of 2 free blocks
        BCS     ?00                     ; no free blocks
        ACC16
        STA     bka
        STA     pb+1
        lda     [pb]
        STA     pfree
        JSR     newblk
        BCC     ?01                     ; ok
        LDA     bka                     ; restore free list
        STA     pfree
        ACC08
?00:    jsr     updwin                  ; for clear selection on edit window
?00a:   rts
?01:    STA     bkb
        .LONGA  on                      ; remember here A/M 16 bit
        LDA     pp0
        STA     ppage
        LDY     ix0
        STY     ixb     
        LDA     nslctl
        BMI     ?02
        STA     rclip
        LDA     pp8
        STA     pp6
        LDY     ix8
        STY     ix6
        bra     ?04
?02:    EOR     #$FFFF
        inc     a
        STA     rclip
        ACC08
        JSR     nextln
        LDA     ppage
        STA     pp6
        LDA     ppage+1
        STA     pp6+1
        LDA     ixb
        STA     ix6
        JSR     pp2mv
        JSR     nextln
        ACC16
?04:    ldx     ctmp2
        beq     ?06                     ; copy op: skip update cline/ncount
        sec
        lda     ncount
        sbc     rclip
        sta     ncount
        LDA     nslctl
        BMI     ?05
        SEC
        LDA     cline
        SBC     rclip
        STA     cline
        bra     ?06
?05:    INC     cline
?06:    LDA     bka
        STA     pb+1
        LDX     #CLIPBRD*2
        STA     bstart,X
        STA     bcur,X
        LDA     #BSTART
        STA     bndx,X
        lda     rclip
        sta     btot,x
        stz     bline,x
        LDA     ppage
        CMP     pp6
        ACC08
        BNE     ?07
        JMP     ?13                     ; all in the same block
?07:    ldx     ctmp2
        bne     ?07a                    ; cut op
        jmp     ?20                     ; copy op
?07a:   LDY     #$00
        CPU16
        LDA     bkb                     ; take off bkb from free list
        STA     pd+1
        lda     [pd]
        STA     pfree
        lda     [pblk]
        STA     [pb]                    ; pb->next = cur->next
        STA     pd+1                    ; pd = cur->next
        TYA
        INY
        INY
        STA     [pb],Y                  ; pb->prev = NULL
        LDA     pb+1
        STA     [pd],Y                  ; cur->next->prev = pb
        CPU08
        INY
        INY                             ; index field
        lda     [pblk],y
        sta     tmp6
        SEC
        SBC     ixb
        CLC
        ADC     #BSTART
        STA     [pb],Y
        tyx                             ; BNDX
        LDY     ixb
        DEY
        STY     tmp7
?08:    INC     tmp7
        inx
        LDY     tmp7
        lda     [pblk],y        
        txy
        STA     [pb],Y
        lda     tmp6
        CMP     tmp7
        BNE     ?08
        ACC16
        LDA     bkb
        STA     pd+1
        LDA     pp6
        STA     pb+1
        lda     [pb]
        STA     [pd]
        ACC08
        LDY     #BNDX
        lda     [pb],y
        sta     tmp6
        SEC
        SBC     ix6
        CLC
        ADC     #BSTART
        STA     [pd],Y
        tyx
        LDY     ix6
        DEY
        STY     tmp7
?09:    INC     tmp7
        inx
        LDY     tmp7
        lda     [pb],y
        txy
        STA     [pd],Y
        lda     tmp6
        CMP     tmp7
        BNE     ?09
        LDY     #BNDX
        LDA     ix6
        STA     [pb],Y
        TAY
        LDA     #$00
        STA     [pb],Y
        xba
        lda     #0
        ACC16
        STA     [pb]                    ; next = NULL
        LDY     #BPREV
        LDA     ppage
        STA     [pd],Y
        LDA     pd+1
        STA     [pblk]
        lda     [pd]
        BEQ     ?10
        STA     pb+1
        LDA     pd+1
        STA     [pb],Y
?10:    ACC08   
        LDA     ixb
        CMP     #BSTART
        BNE     ?11
        LDA     ppage+1
        xba
        lda     ppage
        JSR     delblk
        bra     ?12
?11:    dec     a
        LDY     #BNDX
        STA     [pblk],Y
?12:    LDA     pd+1
        STA     ppage
        lda     pd+2
        sta     ppage+1
        LDA     #BSTART
        STA     ixb
        JMP     updwin

?13:    LDY     ixb
        STY     tmp7
        LDX     #BSTART
?14:    LDY     tmp7
        lda     [pblk],y
        txy
        STA     [pb],Y
        INC     tmp7
        inx
        LDA     tmp7
        CMP     ix6
        BNE     ?14
        LDY     #$00
        CPU16
        tya
        STA     [pb]                    ; next = NULL
        INY
        iny
        STA     [pb],Y                  ; prev = NULL
        CPU08
        txa
        INY
        iny
        STA     [pb],Y                  ; index
        TAY
        LDA     #$00
        STA     [pb],Y                  ; buffer terminator
        lda     #$02                    ; cut operation ?
        bit     edtfg
        bne     ?14a                    ; yes
        jsr     pp2mv                   ; restore current buffer pointer
        bra     ?16
?14a:   LDY     #BNDX                   ; move back
        lda     [pblk],y
        sta     tmp6
        LDY     ix6
        DEY
        STY     tmp7
        LDX     ixb
        DEX
?15:    INC     tmp7
        inx
        LDY     tmp7
        lda     [pblk],y
        txy
        STA     [pblk],Y
        lda     tmp6
        CMP     tmp7
        BNE     ?15
        txa
        LDY     #BNDX
        STA     [pblk],Y
?16:    JMP     updwin

?20:    ldx     #0
        CPU16                           ; count needs block's
        LDA     bkb                     ; take off bkb from free list
        STA     pd+1
        lda     [pd]
        STA     pfree
        lda     ppage
?22:    sta     pd+1    
        lda     [pd]                    ; next
        cmp     pp6                     ; loop until last block
        beq     ?24                     ; end loop
        inx
        bra     ?22
?24:    txa
        beq     ?28                     ; no more blocks need
        jsr     chkfree                 ; check needs blocks
        lda     #0
        bcc     ?28                     ; ok
        LDA     bka                     ; restore free list
        STA     pfree
        CPU08
        LDX     #$04                    ; Not enough memory error
        JMP     error
?28:    LONG_ON                         ; remember here A/M and X/Y 16 bit      
        ldy     #BPREV
        STA     [pb],Y                  ; prev = NULL
        CPU08
        INY
        INY                             ; index field
        lda     [pblk],y
        sta     tmp6                    ; copy tmp6 - ixb + 1 bytes...
        SEC                             ; ...from pblk to pb...
        SBC     ixb                     ; ...starting from ixb
        CLC
        ADC     #BSTART
        STA     [pb],Y
        tyx                             ; BNDX
        LDY     ixb
        DEY
        STY     tmp7
?30:    INC     tmp7
        inx
        LDY     tmp7
        lda     [pblk],y        
        txy
        STA     [pb],Y
        lda     tmp6
        CMP     tmp7
        BNE     ?30     
        ACC16
        LDA     [pblk]                  ; next
?32:    STA     pd+1
        cmp     pp6
        beq     ?36
        LDA     pb+1
        PHA
        JSR     newblk                  ; no give error now!
        STA     [pb]                    ; next
        STA     pb+1
        lda     [pb]
        STA     pfree
        PLA
        ldy     #BPREV
        STA     [pb],Y
        INY
        iny
        ACC08
?34:    lda     [pd],y
        STA     [pb],Y
        INY
        BNE     ?34
        ACC16
        lda     [pd]
        bra     ?32
?36:    lda     pb+1
        sta     bka
        LDA     bkb
        sta     [pb]
        STA     pb+1
        lda     #0
        sta     [pb]
        ldy     #BPREV
        lda     bka
        sta     [pb],y
        ACC08
        LDY     #BNDX
?38:    iny     
        lda     [pd],y
        STA     [pb],Y
        cpy     ix6
        BNE     ?38
        LDY     #BNDX
        LDA     ix6
        STA     [pb],Y
        TAY
        LDA     #$00
        STA     [pb],Y
        jsr     pp2mv
        jmp     updwin

; PASTE
; P215E:
pastesel:
        bit     edtfg
        bvc     ?00
        jmp     cberr                   ; clipboard error
?00:    LDA     fslct
        bne     ?01                     ; no selection
        LDX     #CLIPBRD*2
        ACC16CLC
        LDA     bstart,X
        beq     ?00b                    ; no selected text
        lda     btot,x                  ; # lines on clipboard
        adc     ncount                  ; check overflow
        bcs     ?00a                    ; overflow
        cmp     #MAXLINES
        bcc     ?02
?00a:   ACC08
        ldx     #6                      ; can't paste text: lines count overflow
        jmp     error
?00b:   ACC08
?01:    rts
?02:    .LONGA  on                      ; remember here A/M 16 bit
        LDA     bstart,X                ; block's count 
        JSR     blkcnt
        inc     a                       ; one more      
        jsr     chkfree                 ; check free blocks
        ACC08
        bcc     ?03
        LDX     #$04                    ; Not enough memory error
        JMP     error
?03:    JSR     pp8mv
        stz     pb
        stz     pd
        ACC16CLC
        LDX     #CLIPBRD*2
        lda     btot,x
        sta     rclip
        LDA     cline
        ADC     rclip
        STA     cline
        clc
        lda     ncount
        adc     rclip
        sta     ncount
        lda     [pblk]                  ; next
        PHA
        LDA     ppage
        STA     pb+1
        LDX     #CLIPBRD*2
        LDA     bstart,X
?03a:   STA     pd+1
        LDA     pb+1
        PHA
        JSR     newblk                  ; no give error now!
        STA     [pb]                    ; next
        STA     pb+1
        lda     [pb]
        STA     pfree
        PLA
        ldy     #BPREV
        STA     [pb],Y
        INY
        iny
        ACC08
?04:    lda     [pd],y
        STA     [pb],Y
        INY
        BNE     ?04
        ACC16
        lda     [pd]
        BNE     ?03a
        LDA     pb+1
        STA     bka
        JSR     newblk
        STA     [pb]
        STA     pb+1
        lda     [pb]
        STA     pfree
        LDA     bka
        ldy     #BPREV
        STA     [pb],Y
        PLA
        STA     [pb]
        BEQ     ?05
        STA     pd+1
        LDA     pb+1
        STA     [pd],Y
?05:    ACC08   
        LDY     ixb
        DEY
        STY     tmp7
        LDX     #BNDX
?06:    INC     tmp7
        inx
        LDY     tmp7
        lda     [pblk],y
        txy
        STA     [pb],Y
        LDY     #BNDX
        lda     [pblk],y
        CMP     tmp7
        BNE     ?06
        txa
        STA     [pb],Y
        LDA     ixb
        CMP     #BSTART
        BNE     ?07
        LDA     ppage+1
        xba
        lda     ppage
        JSR     delblk
        bra     ?08
?07:    dec     a
        LDY     #BNDX
        STA     [pblk],Y
?08:    ACC16   
        LDA     pb+1
        STA     ppage
        LDY     #BSTART
        STY     ixb
        LDA     bka
        STA     pd+1
        ACC08
        dey
        lda     [pd],y
        CMP     #BSTART
        BNE     ?09
        LDA     pd+2
        xba
        lda     pd+1
        JSR     delblk
        bra     ?10
?09:    dec     a
        STA     [pd],Y
?10:    LDA     srow
        CMP     #$06
        BCS     ?11
        LDA     #$06
        STA     srow
?11:    JMP     updwin

;---------------------------------------------------

; get new block of memory
; out:  C = page pointer to new block or NULL
;       CF = 1 if no left memory
; can be called in both 8/16 bit
; P230E:
newblk:
        php                             ; save 8/16 bit state
        CPU16
        LDA     pfree                   ; get next free block
        BNE     ?10                     ; OK
?02:    JSR     garbc                   ; try to free memory
        BCS     ?02     
        LDA     pfree
        BNE     ?10                     ; OK
        lda     #MINPAGE                ; try to allocate pages
        tax                             ; X = # pages
        clc
        SETBRK                          ; increase break level
        bcc     ?04                     ; ok
        tax                             ; max. # allocable pages
        beq     ?08                     ; no room !
        clc                             ; allocate max. available
        SETBRK
        bcs     ?08                     ; now will no give error in fact!
?04:    sta     pfree                   ; new free list
        dex
        stx     lpte                    ; # pages - 1
        adc     lpte                    ; last page! (here CF = 0)
        sta     lpte                    ; save last page ptr
        INDEX08
        ldx     #0
        stx     lptc                    ; clear low pointer
        INDEX16                         ; X = 0
        lda     pfree
?06:    sta     lptc+1                  ; init new free list
        inc     a                       ; next page
        sta     [lptc]                  ; next field in free list
        cmp     lpte                    ; till last page
        bne     ?06
        sta     lptc+1
        txa                             ; end of list
        sta     [lptc]
        lda     pfree                   ; return block pointer
        bra     ?10
?08:    CPU08
        LDX     #$01                    ; 'out of memory' error
        JSR     error
        lda     #0                      ; return NULL pointer
        xba
        lda     #0
        plp
        sec                             ; error flag
        rts
?10:    plp                             ; return pointer
        clc
        LONG_OFF
        RTS

; check if free list contain requested number of free blocks
; and add blocks allocating more memory if need
; in:   C = number of requested free block
; out:  CF = 0 if free list is large enough or if more blocks
;       was succesfully added
;       CF = 1 if free list is not large enough and more blocks
;       can't be added
;       C = number of blocks that can be added if CF = 1
; can be called in both 8/16 bit
chkfree:
        php                             ; save 8/16 bit status
        stz     lptc                    ; clear low pointer
        CPU16
        sta     lpte+1                  ; # blocks to add
        lda     pfree
        beq     ?02                     ; free list is empty
        jsr     blkcnt                  ; how much free blocks?
        cmp     lpte+1
        bcs     ?08                     ; ok, requested blocks are free
?02:    sta     lptc+1
        sec
        lda     lpte+1                  ; how much blocks to add?
        sbc     lptc+1
        tax
        clc                             ; set a new break level
        SETBRK
        bcc     ?04                     ; ok, no error
        plp
        sec                             ; return an error
        rts     
?04:    tay                             ; new pointer
        dex
        stx     lpte+1                  ; # pages - 1
        adc     lpte+1                  ; last page! (here CF = 0)
        sta     lpte+1                  ; save last page ptr
        tya
        pha                             ; save new free list pointer
?06:    sta     lptc+1                  ; init new free list
        inc     a                       ; next page
        sta     [lptc]                  ; next field in free list
        cmp     lpte+1                  ; till last page
        bne     ?06
        sta     lptc+1
        lda     pfree                   ; link old free list
        sta     [lptc]
        pla
        sta     pfree                   ; set new free list
?08:    plp
        clc
        LONG_OFF
        rts

; free one buffer
; in:   A = buffer number
; out:  CF = 1 if fail to allocate a new block
; P2D34:
freebuf:
        sta     ebtmp                   ; save buffer number to free
        asl     a
        sta     ebtmp2                  ; save index
        TAX                             ; table index
        stz     lptc                    ; prepare pointer
        ACC16
        LDA     bstart,X
        beq     ?02                     ; nothing to do
        STA     lptc+1
        stz     bstart,x                ; clear start block
        stz     bcur,x                  ; and all buffer data
        stz     bndx,x
        stz     bline,x
        stz     btot,x
        ldx     ebtmp
        stx     bka
        ldx     #0
        stx     bka+1
        lda     bka
        asl     a
        asl     a
        adc     bka
        asl     a               ; x 10
        asl     a
        asl     a
        asl     a               ; x 80
        adc     #EDBUFNAM
        sta     pb
        ACC08
        lda     #^EDBUFNAM
        sta     pb+2
        lda     #0
        sta     [pb]
        sta     >EDCURFILE
        ACC16
?01:    lda     [lptc]                  ; put all buffer blocks in free list
        PHA                             ; next
        LDA     pfree
        STA     [lptc]                  ; next free
        LDA     lptc+1
        STA     pfree                   ; update free list
        PLA
        STA     lptc+1                  ; next block
        BNE     ?01                     ; loop until next = NULL
        ldx     ebtmp                   ; if this is not the current buffer...
        CPX     xbuf
        BNE     ?02                     ; ...done
                                        ; ...otherwise alloc one block...
        JSR     newblk                  ; ...for a new empty buffer
        bcs     ?02                     ; error: no left memory
        sta     wtmp                    ; save new block
        ldx     ebtmp2
        JSR     bufinit                 ; init new buffer
        LDA     bstart,X                ; set up new buffer
        STA     pbuf
        LDA     bcur,X
        STA     ppage
        LDA     bndx,X
        STA     ixb
        LDA     bline,X
        STA     cline
        LDA     btot,X
        STA     ncount
        ldy     #$00
        sty     srow
?02:    ACC08   
?03:    RTS

; switch to another buffer
; in:   A = buffer number
; out:  CF = 1 if fail to allocate a new block
; P2D86:
switchb:
        pha                             ; save new buffer number
        asl     a
        tax                             ; X = buffer table index
        ACC16
        lda     bstart,x
        bne     ?02                     ; ok, buffer already initialized
        jsr     newblk                  ; get a new block
        bcc     ?01                     ; OK
        ACC08
        pla                             ; error -- no memory left
        rts                             ; exit with CF = 1
?01:    sta     wtmp                    ; save new page pointer
?02:    ACC08   
        ldx     xbuf                    ; current buffer index
        bmi     ?03                     ; no current editor buffer
        txa
        asl     a
        tax
        ACC16CLC
        lda     pbuf                    ; save in table current buffer data
        sta     bstart,x
        lda     ppage
        sta     bcur,x
        lda     ixb                     ; index + flag
        sta     bndx,x
        lda     cline
        sta     bline,x
        lda     ncount
        sta     btot,x
        ldx     xbuf
        stx     bka
        ldx     #0
        stx     bka+1
        lda     bka
        asl     a
        asl     a
        adc     bka
        asl     a               ; x 10
        asl     a
        asl     a
        asl     a               ; x 80
        adc     #EDBUFNAM
        sta     pb
        ACC08
        lda     #^EDBUFNAM
        sta     pb+2
        ldx     #0
        txy
?lp1:   lda     >EDCURFILE,x
        sta     [pb],y
        beq     ?03
        inx
        iny
        cpy     #MAXFNAME
        bcc     ?lp1
?03:    pla
        sta     xbuf                    ; set new current buffer
        asl     a
        tax                             ; table index access
        ACC16CLC
        lda     bstart,x
        bne     ?04
        jsr     bufinit
        clc
        lda     bstart,x
?04:    sta     pbuf                    ; start buffer
        lda     bcur,x
        sta     ppage                   ; current block
        lda     bndx,x
        sta     ixb                     ; block pointer + flag
        lda     bline,x
        sta     cline                   ; current line
        lda     btot,x
        sta     ncount                  ; total lines
        ldx     xbuf
        stx     bka
        ldx     #0
        stx     bka+1
        lda     bka
        asl     a
        asl     a
        adc     bka
        asl     a               ; x 10
        asl     a
        asl     a
        asl     a               ; x 80
        adc     #EDBUFNAM
        sta     pb
        ACC08
        lda     #^EDBUFNAM
        sta     pb+2
        ldx     #0
        txy
?lp2:   lda     [pb],y
        sta     >EDCURFILE,x
        beq     ?end
        inx
        iny
        cpy     #MAXFNAME
        bcc     ?lp2
?end:   clc                     ; no error
        rts

; init a new editor buffer -- init buffer table
; in:   X = buffer table index
;       wtmp = new page pointer
; can be called in both 8/16 bit
; P2D05:
bufinit:
        php
        CPU08
        ldy     #0
        sty     lptc
        CPU16
        lda     wtmp                    ; new page pointer
        sta     bstart,x                ; start buffer block
        sta     bcur,x                  ; current buffer block
        sta     lptc+1                  ; temp pointer
        sty     bline,x                 ; clear current line
        sty     btot,x                  ; clear tot. # lines
        lda     [lptc]                  ; next block will be in free list
        sta     pfree
        tya
        sta     [lptc]                  ; next = NULL
        iny
        iny                             ; Y = 2
        sta     [lptc],y                ; prev = NULL
        iny
        iny                             ; Y = 4;
        lda     #BSTART                 ; set pointer in block
        sta     [lptc],y                ; and mark end of buffer
        sta     bndx,x                  ; flag buffer = 0
        plp
        LONG_OFF
        rts


; insert <enter> code - check if lines overflow
inscr:
        ACC16
        lda     ncount
        inc     a
        cmp     #MAXLINES+1
        ACC08
        bcs     ?02
        LDA     #$0D
        bra     insert                  ; insert byte $0D (enter key code)
?02:    ldx     #7                      ; Can't insert a new line: lines count overflow
        jsr     error
        sec
        rts

; insert byte into buffer at position specified by ixb
; in:   A = byte to insert
; A,X,Y preserved
; P227B:
insert:
        sta     ewtmp                   ; byte to insert        
        phx
        phy
        bit     bflag                   ; chek if overwrite mode
        bvc     ?00                     ; default insert mode
        cmp     #$0D                    ; insert anyway code $0D
        beq     ?00
        tax
        ldy     ixb
        lda     [pblk],y                ; A = byte at position where overwrite
        beq     ?00                     ; no overwrite null terminator
        cmp     #$0D
        beq     ?00                     ; no overwrite line terminator
        txa
        sta     [pblk],y                ; overwrite
        bra     ?08                     ; exit
?00:    LDY     #BNDX
        lda     [pblk],y
        sta     ewtmp+1                 ; save current pointer
        CMP     #$FF
        BNE     ?02                     ; ok, room for move one byte ahead
        JSR     newblk                  ; alloc new block...
        BCC     ?01                     ; ...for move bytes one room ahead
        PLY
        plx
        lda     ewtmp
        RTS
?01:    ACC16   
        STA     wtmp                    ; save new block
?02:    ACC16   
        LDA     pp6
        CMP     ppage
        ACC08
        BNE     ?03
        INC     ix6
?03     ldy     ewtmp+1
        INY
?04:    DEY                             ; loop for move ahead
        lda     [pblk],y                ; A = byte to move ahead
        INY
        BNE     ?06
        JSR     addblk                  ; insert new block and move byte
        LDY     ix6
        BNE     ?05
        LDA     lptmp2+1                ; save new block in pp6
        STA     pp6
        LDA     lptmp2+2
        STA     pp6+1
        LDA     #BSTART
        STA     ix6
?05:    LDY     #$00
        bra     ?07
?06:    sta     [pblk],y
?07:    DEY
        CPY     ixb                     ; move bytes until is free...
        BNE     ?04                     ; ...the position specified by ixb
        LDA     ewtmp
        STA     [pblk],Y                ; store byte
        lda     ewtmp+1                 ; update pointer
        inc     a
        BEQ     ?08
        LDY     #BNDX
        STA     [pblk],Y
?08:    ply
        plx
        lda     #$80
        tsb     bflag                   ; set modified flag
        lda     ewtmp
        CLC                             ; no error
        RTS 

; align buffer with minimum screen row and save block on pp4
; P1E14:
findrow:
        LDY     #$00                    ; start at row = 0
?01:    CPY     srow                    ; current screen row 
        BEQ     ?02                     ; already at first row
        JSR     startln                 ; find start of line            
        BCS     ?02                     ; beginning of buffer
        INY
        bra     ?01                     ; loop
?02:    STY     srow                    ; store row
        LDA     ppage                   ; save block pointer
        STA     pp4
        LDA     ppage+1
        STA     pp4+1
        LDA     ixb
        STA     ix4
        RTS

; get number of bytes from current column to end of line
; in:   X = text column
; out:  ccnt updated    
; P1474:
xcnt2:
        LDY     #$00
        STY     scol
        STY     ccol
        JSR     pp8mv
        INX
?01:    CPY     ecol
        BEQ     ?02
        DEX
        BEQ     ?06
        JSR     getbyte
        BCS     ?06
        CMP     #$0D
        BEQ     ?06
        INY
        JSR     incptr
        INC     ccol
        bra     ?01
?02:    DEX
        BEQ     ?03
        JSR     getbyte
        BCS     ?06
        CMP     #$0D
        BEQ     ?06
        INY
        JSR     incptr
        INC     scol
        INC     ccol
        bra     ?02
?03:    JSR     mvpp2
?04:    JSR     getbyte
        BCS     ?05
        CMP     #$0D
        BEQ     ?05
        INY
        JSR     incptr
        bra     ?04
?05:    JSR     pp2mv
?06:    STY     ccnt
        RTS

; find beginning of line on block pointed by pp6
; P2477:
startln6:
        LDA     rcnt
        CMP     #$17
        beq     ?01
        INC     rcnt
        RTS
?01:    JSR     mvpp2
        LDA     pp6
        STA     ppage
        LDA     pp6+1
        STA     ppage+1
        LDA     ix6
        STA     ixb
        JSR     startln
        LDA     ppage
        STA     pp6
        LDA     ppage+1
        STA     pp6+1
        LDA     ixb
        STA     ix6
        bra     pp2mv

; find next line on block pointed by pp4
; P249F:
nextln4:
        JSR     mvpp2
        LDA     pp4
        STA     ppage
        LDA     pp4+1
        STA     ppage+1
        LDA     ix4
        STA     ixb
        JSR     nextln
        LDA     ppage
        STA     pp4
        LDA     ppage+1
        STA     pp4+1
        LDA     ixb
        STA     ix4
        bra     pp2mv

; find beginning of line on block pointed by pp4
; P24BC:
startln4:
        JSR     mvpp2
        LDA     pp4
        STA     ppage
        LDA     pp4+1
        STA     ppage+1 
        LDA     ix4
        STA     ixb
        JSR     startln
        LDA     ppage
        STA     pp4
        LDA     ppage+1
        STA     pp4+1
        LDA     ixb
        STA     ix4
        bra     pp2mv

; calc the bytes count in current line
; P141A:
xcount:
        jsr     mvpp2
        jsr     incptr2
        jsr     startln
        dex

; move pp2 to page pointer
; P236D:
pp2mv:
        lda     pp2
        sta     ppage
        lda     pp2+1
        sta     ppage+1
        lda     ix2
        sta     ixb
        rts

; find next line on block pointed by pp6
; P2455:
nextln6:
        JSR     mvpp2
        LDA     pp6
        STA     ppage
        LDA     pp6+1
        STA     ppage+1
        LDA     ix6
        STA     ixb
        JSR     nextln
        BCC     ?01
        DEC     rcnt
?01:    LDA     ppage
        STA     pp6
        LDA     ppage+1
        STA     pp6+1
        LDA     ixb
        STA     ix6
        bra     pp2mv

; find next line and save in pp8
; X,Y preserved
; P1447:
nextln8:
        JSR     mvpp2
        phy
?01:    JSR     decptr2
        BCS     ?02
        lda     [pblk],y
        CMP     #$0D
        BNE     ?01
        JSR     incptr2
?02:    ply     
        JSR     mvpp8
        bra     pp2mv

; move page pointer to pp2
; P2362:
mvpp2:
        lda     ppage
        sta     pp2
        lda     ppage+1
        sta     pp2+1
        lda     ixb
        sta     ix2
        rts

; move page pointer to pp8
; P2378:
mvpp8:
        lda     ppage
        sta     pp8
        lda     ppage+1
        sta     pp8+1
        lda     ixb
        sta     ix8
        rts

; move pp8 to page pointer
; P2383:
pp8mv:
        lda     pp8
        sta     ppage
        lda     pp8+1
        sta     ppage+1
        lda     ix8
        sta     ixb
        rts

; count blank from start of line till first non blank
; out: ctmp = starting blanks counter
xblank:
        stz     ctmp
        lda     #$20                    ; test indent flag
        bit     bflag
        beq     ?06
        lda     ppage                   ; save current buffer pointer
        sta     lptc
        lda     ppage+1
        sta     lptc+1
        lda     ixb
        sta     lptc+2
        jsr     startln                 ; find start of line
        ldx     #$FF                    ; beginning blank counter
?02:    inx     
        jsr     getbyte2
        bcs     ?04                     ; end buffer
        cmp     #' '
        bne     ?04
        jsr     incptr2
        bra     ?02
?04:    stx     ctmp    
        lda     lptc                    ; restore buffer pointer
        sta     ppage
        lda     lptc+1
        sta     ppage+1
        lda     lptc+2
        sta     ixb
?06:    rts

; get blocks count of buffer
; in:   C = buffer start page
; out:  C = blocks count
; using lptmp1 long pointer
; can be called in 8/16 bit mode
; P2262:
blkcnt:
        php                             ; save 8/16 bit state
        INDEX08
        LDX     #$00
        STX     <lptmp1
        CPU16
        tay
        beq     ?03                     ; return C = 0
        STA     <lptmp1+1               ; page pointer
?01:    INX
        LDA     [lptmp1]
        BEQ     ?02                     ; end of buffer
        STA     <lptmp1+1
        bra     ?01
?02:    TXA
?03:    plp                             ; restore 8/16 bit mode
        LONG_OFF
        RTS

; delete byte at current position from block
; A,X,Y preserved
; using lptc, lptmp1 & lptmp2 long pointer
; using wtmp
; P238E:
delbyte:
        pha
        phx
        phy
        ACC16
        LDA     ppage
        sta     wtmp                    ; save current page pointer
        CMP     pp6
        ACC08
        BNE     ?01
        DEC     ix6                     ; update
?01:    LDY     #BNDX
        LDA     [pblk],Y
        TAX                             ; X = pointer in block
        CMP     ixb
        BNE     ?04                     ; not last byte in block        
        dec     a                       ; update pointer in block
        STA     [pblk],Y                ; this is last byte in block
        JSR     incptr2
        CPX     #BSTART                 ; empty buffer ?
        BNE     ?02                     ; no 
        lda     wtmp+1                  ; remove block
        xba
        lda     wtmp                    ; C = page pointer
        JSR     delblk
        bra     ?06                     ; exit
?02:    lda     pp8
        sta     lptc+1
        lda     pp8+1
        sta     lptc+2
        stz     lptc
        LDY     #BNDX
        LDA     [lptc],Y
        CMP     ix8
        BCS     ?06
        ACC16
        LDA     [lptc]
        STA     pp8
        ACC08
        LDA     #BSTART
        STA     ix8
        bra     ?06
?04:    dec     a                       ; update pointer
        STA     [pblk],Y
        LDY     ixb                     ; move back bytes from end of block
        INY                             ; to current position 
?05:    LDA     [pblk],Y                
        DEY
        STA     [pblk],Y
        INY
        INY
        BNE     ?05
?06:    lda     #$80
        tsb     bflag                   ; set modified flag
        ply
        plx
        pla
        rts

; find beginning of next line
; in:   none
; out:  CF = 0 if ok, CF = 1 if end of buffer
;       X = count of bytes till next line
; Y preserved
; P13CA:
nextln:
        phy
        ldx     #0                      ; bytes counter
        ldy     ixb
        sec
        lda     [pblk],y                ; get next byte
        beq     ?03                     ; if end of buffer exit with CF = 1
?01:    cmp     #$0D                    ; end of line ?
        beq     ?02                     ; yes
        inx
        jsr     incptr2                 ; Y = next index
        lda     [pblk],y                ; get next byte
        bra     ?01
?02:    jsr     incptr2                 ; beginning of next line
        clc
?03:    ply
        rts

; find beginning of current line
; in:   none
; out:  CF = 0 if ok, CF = 1 if beginning of buffer
;       X = count of bytes till start of line
; Y preserved
; P1427:
startln:
        phy
        ldx     #0                      ; bytes counter
        jsr     decptr2                 ; decrement buffer pointer
        bcs     ?04                     ; exit with CF = 1 if beginning
        inx
?01:    jsr     decptr2
        bcs     ?03                     ; we are at the beginning
        lda     [pblk],y                ; previous byte
        cmp     #$0D
        beq     ?02                     ; end of prev. line
        inx
        bra     ?01
?02:    jsr     incptr2                 ; beginning of line
?03:    clc
?04:    ply
        rts

; get byte from buffer at current index
; in:   none
; out:  A = current byte (CF = 0 if not null, CF = 1 if null)
; X,Y preserved
; P2353:
getbyte:
        phy
        ldy     ixb
        lda     [pblk],y
        clc
        bne     ?01
        sec
?01:    ply
        rts

; get byte from buffer at current index
; in:   none
; out:  A = current byte (CF = 0 if not null, CF = 1 if null)
; X preserved
; P2353:
getbyte2:
        ldy     ixb
        lda     [pblk],y
        beq     ?02
        clc
        rts
?02:    sec
        rts

; increment buffer pointer
; in:   none
; out:  CF = 1 if change block or if end of buffer
; A,X,Y preserved
; P2333:
incptr:
        pha
        phy
        lda     ixb
        ldy     #BNDX
        cmp     [pblk],y
        bcc     ?04                     ; ok, increment
        ACC16
        lda     [pblk]                  ; next block
        beq     ?08                     ; end of buffer, exit with CF = 1
        sta     ppage                   ; update page pointer
        ACC08
        lda     #BSTART-1               ; beginning of buffer
?04:    inc     a
        sta     ixb
        ply
        pla
        rts
?08:    ACC08   
        ply
        pla
        rts

; increment buffer pointer
; in:   none
; out:  CF = 1 if change block or if end of buffer
;       Y = index
; X preserved
incptr2:
        lda     ixb
        ldy     #BNDX
        cmp     [pblk],y
        tay
        bcc     ?04                     ; ok, increment
        ACC16
        lda     [pblk]                  ; next block
        beq     ?08                     ; end of buffer, exit with CF = 1
        sta     ppage                   ; update page pointer
        ldy     #BSTART-1               ; beginning of buffer
?04:    iny
        sty     ixb
?08:    ACC08   
        rts

; decrement buffer pointer
; in:   none
; out:  CF = 1 if at buffer beginning
; A,X,Y preserved
; P2430:
decptr:
        pha
        lda     ixb
        cmp     #BSTART
        bne     ?02                     ; ok, decrement
        phy
        ldy     #BPREV                  ; previous page pointer
        ACC16
        LDA     [pblk],Y
        beq     ?08                     ; exit with CF = 1
        sta     ppage                   ; update page pointer
        ACC08
        LDY     #BNDX
        LDA     [pblk],Y
        ply
        bra     ?04
?02:    dec     a       
?04:    sta     ixb
        clc                             ; ok, exit with CF = 0
        pla
        rts
?08:    ACC08SEC        
        ply
        pla
        rts

; decrement buffer pointer
; in:   none
; out:  CF = 1 if at buffer beginning
;       Y = index
; X preserved
decptr2:
        ldy     ixb
        cpy     #BSTART
        bne     ?02                     ; ok, decrement
        ldy     #BPREV                  ; previous page pointer
        ACC16
        LDA     [pblk],Y
        beq     ?08                     ; exit with CF = 1
        sta     ppage                   ; update page pointer
        ACC08
        LDY     #BNDX
        LDA     [pblk],Y
        tay
        iny
?02:    dey     
?04:    sty     ixb
        clc                             ; ok, exit with CF = 0
        rts
?08:    ACC08SEC        
        ldy     ixb
        rts

; insert new block in buffer and store byte in new block
; in:   wtmp = page pointer of new block
;       A = byte to store
; out:  buffer linked list modified
; using lptmp2 long pointer
; A,X preserved
; P22DF:
addblk:
        stz     lptmp2                  ; using lptmp2 long pointer
        PHA                             ; save byte to store
        ACC16
        LDA     [pblk]                  ; next page pointer
        PHA                             ; save
        BEQ     ?01                     ; next = 0
        STA     lptmp2+1                ; lptmp2 = next
        LDA     wtmp                    ; new page pointer
        LDY     #BPREV
        STA     [lptmp2],Y              ; next->prev = new page pointer
        bra     ?02
?01:    LDA     wtmp                    ; next = new page pointer
?02:    STA     [pblk]
        STA     lptmp2+1
        LDA     [lptmp2]                ; next free page pointer
        STA     pfree
        PLA
        STA     [lptmp2]                ; new page next = cur->next
        LDA     ppage
        LDY     #BPREV
        STA     [lptmp2],Y              ; new page prev = cur
        ACC08
        LDA     #BSTART
        LDY     #BNDX
        STA     [lptmp2],Y              ; buffer index
        PLA
        INY
        STA     [lptmp2],Y              ; store byte
        RTS

; remove a block from buffer and put in free blocks list
; in:   C = page pointer of block to remove
; using lptmp1 & lptmp2 long pointers
; X preserved
; P23EC:
delblk:
        stz     lptmp1                  ; using lptmp1 & lptmp2 long pointer
        stz     lptmp2
        ACC16
        STA     lptmp1+1                ; page pointer to removing block
        CMP     pp4
        BNE     ?01
        lda     [lptmp1]
        STA     pp4                     ; next block
        LDY     #BSTART
        STY     ix4
?01:    lda     [lptmp1]
        BNE     ?02
        LDY     #BPREV                  ; this is the first block
        lda     [lptmp1],y
        bra     ?03
?02:    STA     lptmp2+1                ; next block
        LDY     #BPREV
        lda     [lptmp1],y              ; next->prev = this->prev
        STA     [lptmp2],Y
?03:    BNE     ?04                     ; prev != NULL
        LDA     lptmp2+1                ; prev = NULL => next block 
        STA     pbuf                    ; become first block of this buffer
        LDX     xbuf
        pha
        ACC08
        txa
        asl     a
        tax
        ACC16
        pla
        STA     bstart,X                ; store first block of this buffer
        bra     ?05
?04:    STA     lptmp2+1                ; prev block
        lda     [lptmp1]                ; prev->next = this->next
        STA     [lptmp2]
?05:    LDA     pfree                   ; insert this block on free list
        STA     [lptmp1]
        LDA     lptmp1+1
        STA     pfree
        ACC08
        RTS 

; garbage collection -- free unused memory assigned to a buffer
; out:  CF = 0 if completed, otherwise CF = 1
; can be called in both 8/16 bit
; P1855:
garbc:
        php                             ; save 8/16 bit mode
        CPU08
        stz     lptc                    ; clear used memory
        stz     lpte                    ; using long pointer lptc & lpte
        stz     tmpb
        stz     tmpc
        stz     tmpd
        stz     tmpe
        stz     tmpf
        ACC16CLC
        LDA     pbuf                    ; first block of the buffer
        PHA
?00:    PLA     
        STA     lptc+1
        LDA     [lptc]
        bne     ?01
        plp                             ; only this block -- done
        clc
        rts
?01:    pha                             ; save next block       
        ACC08   
        ldy     #BNDX
        LDA     [lptc],Y
        TAX                             ; X = pointer in block
        ACC16CLC
        INX                             ; full block?
        beq     ?00                     ; yes -- check next block
        STX     tmp7                    ; tmp7 = next free
        pla                             ; next block
        STA     lpte+1
        LDX     #1
        CMP     ppage
        BNE     ?02
        STX     tmpb                    ; tmpb = 1 if this block = current block
?02:    CMP     pp8
        bne     ?03
        STX     tmpc                    ; tmpc = 1 if this block = pp8
?03:    CMP     pp4
        bne     ?04
        STX     tmpd                    ; tmpd = 1 if this block = pp4
?04:    CMP     pp6
        bne     ?05
        STX     tmpe                    ; tmpe = 1 if this block = pp6
?05:    CMP     pp0
        bne     ?06
        STX     tmpf                    ; tmpf = 1 if this block = pp0
?06:    ACC08   
        LDY     #BNDX
        LDA     [lpte],Y
        STA     tmp9                    ; tmp9 = pointer in next block
        iny
        STY     tmp8                    ; tmp8 = dynamic pointer in next block
?07:    LDY     tmp8                    ; loop
        LDA     [lpte],Y                ; move first byte of next block
        LDY     tmp7                    ; to next free room in this block
        STA     [lptc],Y
        ACC16
        LDA     lptc+1                  ; C = this block
        LDX     tmpb
        beq     ?08
        LDX     ixb
        CPX     tmp8
        BNE     ?08
        STA     ppage                   ; set to this block
        STY     ixb
        LDX     #0
        STX     tmpb
?08:    LDX     tmpc
        BEQ     ?09
        LDX     ix8
        CPX     tmp8
        BNE     ?09
        STA     pp8                     ; set to this block
        STY     ix8
        LDX     #0
        STX     tmpc
?09:    LDX     tmpd
        BEQ     ?10
        LDX     ix4
        CPX     tmp8
        BNE     ?10
        STA     pp4                     ; set to this block
        STY     ix4
        LDX     #0
        STX     tmpd
?10:    LDX     tmpe
        BEQ     ?11
        LDX     ix6
        CPX     tmp8
        BNE     ?11
        STA     pp6                     ; set to this block
        STY     ix6
        LDX     #0
        STX     tmpe
?11:    LDX     tmpf
        BEQ     ?12
        LDX     ix0
        CPX     tmp8
        BNE     ?12
        STA     pp0                     ; set to this block
        STY     ix0
        LDX     #0
        STX     tmpf
?12:    LDX     tmp8                    ; X = pointer in next block
        LDA     lpte+1                  ; C = next block
        ACC08
        CPX     tmp9                    ; if same pointer then next block now
        BEQ     ?13                     ; is empty and can be freed
        INC     tmp8
        INC     tmp7
        bne     ?07                     ; loop move byte
        BEQ     ?15                     ; continue      
?13:    JSR     delblk                  ; remove next block (C)
        LDY     #BNDX
        LDA     tmp7                    ; set pointer in block
        STA     [lptc],Y
        plp
        CLC                             ; done
        RTS 
?15:    LDA     #$FF                    ; full block
        LDY     #BNDX
        STA     [lptc],Y
        INY
        STY     tmp7
        LDA     tmp8
        SEC
        SBC     #BSTART
        STA     tmpa                    ; residue
        INC     tmp9                    ; limit pointer in next block
        LDY     tmp8
        LDX     tmp7
?16:    LDA     [lpte],Y                ; move byte
        TXY
        STA     [lpte],Y
        INX
        INC     tmp8
        LDY     tmp8
        CPY     tmp9
        BNE     ?16                     ; move all bytes
        LDA     tmpb
        BEQ     ?17
        LDA     ixb
        SEC
        SBC     tmpa
        STA     ixb
?17:    LDA     tmpc
        BEQ     ?18
        LDA     ix8
        SEC
        SBC     tmpa
        STA     ix8
?18:    LDA     tmpd
        BEQ     ?19
        LDA     ix4
        SEC
        SBC     tmpa
        STA     ix4
?19:    LDA     tmpe
        BEQ     ?20
        LDA     ix6
        SEC
        SBC     tmpa
        STA     ix6
?20:    LDA     tmpf
        BEQ     ?21
        LDA     ix0
        SEC
        SBC     tmpa
        STA     ix0
?21:    LDA     tmp9
        CLC
        SBC     tmpa
        LDY     #BNDX                   ; update pointer in next buffer
        STA     [lpte],Y
        plp
        SEC                             ; not done
        RTS 

;-----------------------------------------------------------------
; high level screen

; update last edit text row on screen
; P13E5:
updlst:
        ACC16
        LDA     #!LSTLINE
        sta     stxtp
        ora     #!TXTATTR
        sta     sattp
        ACC08
        LDA     fslct
        BEQ     ?01
        LDA     nslcth
        BPL     ?01
        LDA     #$17
        SEC
        SBC     srow
        CLC
        ADC     nslctl
        LDA     #$00
        ADC     nslcth
        BPL     ?01
        LDA     #$80
        STA     frev
?01:    LDX     pp6
        lda     pp6+1
        LDY     ix6
        JSR     setptr
        bra     updrow

; update first edit text row on screen
; P1E30:
updfst:
        ACC16
        LDA     #!TXTADDR
        sta     stxtp
        ora     #!TXTATTR
        sta     sattp
        ACC08
        LDA     fslct
        BEQ     ?01
        LDA     nslcth
        BMI     ?01
        LDA     srow
        SEC
        SBC     nslctl
        LDA     #$00
        SBC     nslcth
        BPL     ?01
        LDA     #$80
        STA     frev
?01:    LDX     pp4
        lda     pp4+1
        LDY     ix4
        JSR     setptr

; update current row on screen
; P2779:
updrow:
        lda     !$FFFF,x
        BNE     ?04
        lda     #' '                    ; blank row
        xba
        lda     eattr                   ; A = attribute, B = blank
        ldy     #MAXCOLS-1
?02:    sta     [sattp],y               ; store attribute
        xba
        sta     [stxtp],y               ; store blank
        xba
        dey
        bpl     ?02
        SEC
        RTS
?04:    LDY     ecol
        BEQ     updr2
; P279F:
updr1:
        lda     !$FFFF,x
        CMP     #$0D
        BNE     ?02
        LDY     #$00
        bra     updr9
?02:    CPX     ebtmp2
        BNE     ?03
        JSR     updptr
?03:    INX
        DEY
        BNE     updr1
; P27B7:
updr2:
        lda     !$FFFF,x
        CMP     #$0D
        BEQ     updr9
        CPY     #MAXCOLS
        BNE     updr7
updr5:  CPX     ebtmp2
        BCC     ?06
        JSR     updptr
?06:    INX
; P27CC:
updr3:
        lda     !$FFFF,x
        CMP     #$0D
        BNE     updr5
        beq     updr9
updr7:  sta     [stxtp],y               ; store char in video ram
        lda     eattr                   ; editor attribute
        EOR     frev                    ; set reverse bit
        sta     [sattp],y               ; store attribute
        INY
        CPX     ebtmp2
        BCC     ?08
        JSR     updptr
?08:    INX
        bra     updr2
updr9:  CPX     ebtmp2
        BCC     ?10
        JSR     updptr
?10:    INX
        LDA     #' '                    ; pad row with blank
        xba                             ; B = char, A = attribute
        lda     eattr                   ; editor attribute      
        EOR     frev                    ; set reverse bit
?11:    CPY     #MAXCOLS
        BEQ     ?12
        sta     [sattp],y               ; store attribute
        xba
        sta     [stxtp],y               ; store blank
        xba
        INY
        BNE     ?11
?12:    STZ     frev                    ; clear reverse flag bit
        CLC
        RTS 

; scroll right editor window (move window left one column)
; P24D9:
scrlright:
        phb                             ; save DBR
        ACC16CLC
        lda     #!TXTADDR               ; set screen text pointer
        sta     stxtp
        lda     #!TXTATTR               ; set screen attributes pointer
        sta     sattp
        LDA     pp4                     ; buffer page pointer
        STA     lptc+1                  ; B = bank, A = page
        ACC08
        phk
        plb                             ; DBR = PBR
        STZ     !sclr1+1
        STZ     !sclr2+1
        STA     !sclr1+2
        STA     !sclr2+2
        STZ     lptc
        LDA     ecol
        ADC     #MAXCOLS-1
        STA     ewtmp2+1
        xba                             ; A = bank
        pha
        plb                             ; set DBR to current buffer
        LDY     #BNDX
        lda     (lptc),y
        STA     ebtmp
        JSR     chksel
        stz     ewtmp+1                 ; counter 24 rows
        LDX     ix4
;P2512:
sclr1:  lda     !$FFFF,x
        beq     sclr3
        LDY     #$00
        STY     ewtmp2
;P251D:
sclr2:  lda     !$FFFF,x
        CMP     #$0D
        BNE     ?03
        lda     ewtmp2
        BNE     ?06
        LDA     #' '                    ; blank padding
        sta     ewtmp
        bra     ?06
?03:    cpy     ewtmp2+1
        BNE     ?04
        sta     ewtmp
        INC     ewtmp2
?04:    CPX     ebtmp
        BNE     ?05
        JSR     setscrp
?05:    INX
        INY
        bra     sclr2
?06:    CPX     ebtmp
        BNE     ?07
        JSR     setscrp
?07:    INX
        lda     #^TXTADDR
        phb
        pha
        plb
        ldy     #$01                    ; move left text and attributes
?08:    lda     (stxtp),y
        xba
        lda     (sattp),y               ; A = attribute, B = text 
        dey
        sta     (sattp),y
        xba
        sta     (stxtp),y
        iny
        iny
        cpy     #MAXCOLS
        bcc     ?08
        DEY
        lda     ewtmp
        sta     (stxtp),y
        lda     eattr                   ; editor attribute      
        JSR     tglrev                  ; check reverse bit
        sta     (sattp),y
        plb
        ACC16CLC
        LDA     stxtp
        ADC     #MAXCOLS
        STA     stxtp
        ora     #!TXTATTR
        sta     sattp
        ACC08
        INC     ewtmp+1
        LDA     ewtmp+1
        CMP     #$18
        bne     sclr1
sclr3:  plb     
        RTS

; scroll left editor window (move window right one column)
; P25CF:
scrlleft:
        phb                             ; save DBR
        ACC16CLC
        lda     #!TXTADDR               ; set screen text pointer
        sta     stxtp
        lda     #!TXTATTR               ; set screen attributes pointer
        sta     sattp
        LDA     pp4                     ; buffer page pointer
        STA     lptc+1                  ; B = bank, A = page
        ACC08
        phk
        plb                             ; DBR = PBR
        STZ     !scll1+1
        STZ     !scll2+1
        STA     !scll1+2
        STA     !scll2+2
        STZ     lptc
        xba                             ; A = bank
        pha
        plb                             ; set DBR to current buffer
        LDY     #BNDX
        lda     (lptc),y
        STA     ebtmp
        JSR     chksel
        STZ     ewtmp+1                 ; counter 24 rows
        LDX     ix4
;P25FF:
scll1:
        lda     !$FFFF,x
        beq     sclr3
        LDY     #$00
        STY     ewtmp2
;P260A:
scll2:
        lda     !$FFFF,x
        CMP     #$0D
        BNE     ?05
        lda     ewtmp2
        BNE     ?07a
        LDA     #' '
        sta     ewtmp
?04:    bra     ?07a
?05:    CPY     ecol
        BNE     ?06
        sta     ewtmp
        INC     ewtmp2
?06:    CPX     ebtmp
        BNE     ?07
        JSR     setscrp
?07:    INX
        INY
        bra     scll2
?07a:   CPX     ebtmp
        BNE     ?08
        JSR     setscrp
?08:    INX
        lda     #^TXTADDR               ; move right text and attributes
        phb
        pha
        plb
        ldy     #MAXCOLS
?09:    dey
        dey
        bmi     ?10
        lda     (stxtp),y
        xba
        lda     (sattp),y               ; A = attribute, B = text 
        iny
        sta     (sattp),y
        xba
        sta     (stxtp),y
        bra     ?09
?10:    iny
        lda     ewtmp
        sta     (stxtp),y
        lda     eattr                   ; editor attribute      
        JSR     tglrev                  ; check reverse bit
        sta     (sattp),y
        plb
        ACC16CLC
        LDA     stxtp
        ADC     #MAXCOLS
        STA     stxtp
        ora     #!TXTATTR
        sta     sattp
        ACC08
        INC     ewtmp+1
        LDA     ewtmp+1
        CMP     #$18
        bne     scll1
        plb
        RTS

; set scroll routine pointers
; this routine change DBR
; P25AF:
setscrp:
        phy
        ACC16
        lda     [lptc]
        STA     lptc+1                  ; B = bank, A = page
        ACC08
        phk
        plb                             ; DBR = PBR
        STA     !sclr1+2
        STA     !sclr2+2
        STA     !scll1+2
        STA     !scll2+2
        xba                             ; A = buffer bank
        pha
        plb                             ; DBR = buffer bank
        LDY     #BNDX
        lda     (lptc),y
        STA     ebtmp
        tyx
        ply
        rts

; set update routine pointers
; this routine change DBR
; in:   A = bank, X = page, Y = index
; out: X = index
; P2751:
setptr:
        phk
        plb                             ; DBR = PBR
        STZ     lptc
        STA     lptc+2
        STZ     !updrow+1
        STZ     !updr1+1
        STZ     !updr2+1
        STZ     !updr3+1
        STX     lptc+1
        STX     updrow+2
        STX     updr1+2
        STX     updr2+2
        STX     updr3+2
        TYX
        pha
        plb                             ; DBR = buffer bank
        sta     sbank                   ; save bank
        LDY     #BNDX
        lda     (lptc),y
        STA     ebtmp2
        RTS

; update routine pointers to start of a block
; this routine change DBR
; out: X = index
; P282A:
updptr:
        phy
        ACC16
        lda     [lptc]
        STA     lptc+1                  ; B = bank, A = page
        ACC08
        phk
        plb                             ; DBR = PBR
        STA     !updrow+2
        STA     !updr1+2
        STA     !updr2+2
        STA     !updr3+2
        xba                             ; A = buffer bank
        pha
        plb                             ; DBR = buffer bank
        sta     sbank                   ; save bank
        LDY     #BNDX
        lda     (lptc),y
        STA     ebtmp2
        tyx
        ply
        rts     

; check selected text range in screen row's
; rsctl is starting selection screen row
; rscth is ending selection screen row
; P2693:
chksel:
        LDA     fslct
        BEQ     ?03
        LDA     nslcth                  ; if negative range
        BMI     ?02
        LDA     srow
        STA     rslcth
        SEC
        SBC     nslctl
        STA     rslctl
        LDA     #$00
        SBC     nslcth
        BPL     ?01
        LDA     #$00
        STA     rslctl
?01:    rts
?02:    LDA     srow
        inc     a
        sta     rslctl
        SEC
        SBC     nslctl
        inc     a
        sta     rslcth
        LDA     #$FF
        SBC     nslcth
        BMI     ?03
        LDA     #$19
        STA     rslcth
?03:    RTS 

; invert reverse bit attribute
; in:   A = attribute
; P26D9:
tglrev:
        PHA
        LDA     fslct
        BEQ     ?01
        LDA     ewtmp+1                 ; current showed screen row
        CMP     rslctl
        BCC     ?01
        CMP     rslcth
        BCS     ?01
        PLA
        EOR     #$80
        rts
?01:    PLA
        RTS 

;-----------------------------------------------------------------
; low level screen

; clear last text line
; P154B:
clrlst:
        ldx     #<LSTLINE
        lda     #>LSTLINE
        ldy     #^LSTLINE
        stx     lptc
        stx     lptc1
        sta     lptc+1
        ora     #>TXTATTR
        sta     lptc1+1 
        sty     lptc+2
        sty     lptc1+2
        lda     #' '
        xba
        lda     eattr                   ; A = attribute, B = blank
        ldy     #MAXCOLS-1
?02:    sta     [lptc1],y               ; store attribute
        xba
        sta     [lptc],y                ; store blank
        xba
        dey
        bpl     ?02
        rts

; set default status line attributes
; P14C9:
setstla:
        ldx     #<STLATTR
        ldy     #>STLATTR
        lda     #^STLATTR
        stx     lptc
        sty     lptc+1
        sta     lptc+2
        lda     slattr                  ; status line attribute
        ldy     #MAXCOLS-1
?02:    sta     [lptc],y
        dey
        bpl     ?02
        rts

; set default editor attributes
; P14D5:
setattr:
        phb
        INDEX16
        ldx     #!TXTATTR
        lda     #^TXTATTR
        stx     lptc
        pha
        plb
        lda     eattr                   ; editor attribute
        ldy     #TXTCNT-1
?02:    sta     (lptc),y
        dey
        bpl     ?02
        INDEX08
        plb
        rts

; increment screen row
; P1529:
incrow:
        ACC16CLC
        lda     curs
        adc     #MAXCOLS
        sta     curs
        ACC08
        inc     srow
        rts

; decrement screen row
; P153A:
decrow:
        ACC16CLC
        lda     curs
        sbc     #MAXCOLS-1              ; take account carry !
        sta     curs
        ACC08
        dec     srow
        rts

; reverse screen row (invert "reverse" bit)
; P1DD3:
revrow:
        ACC16
        lda     stxtp
        ora     #!TXTATTR
        sta     sattp
        ACC08
        ldy     #MAXCOLS-1
?02:    lda     [sattp],y
        eor     #$80
        sta     [sattp],y
        dey
        bpl     ?02
        rts

; scroll down editor window (move window up one row)
; P28BD:
scrldown:
        phb
        CPU16CLC
        lda     #!TXTADDR
        tax
        sta     lptc
        adc     #MAXCOLS
        sta     lpte
        txa
        ora     #!TXTATTR
        sta     lptc1
        adc     #MAXCOLS
        sta     lpte1   
        CPU08
        lda     #^TXTADDR
        pha
        plb
        ldx     #$17                    ; move 23 rows
?02:    ldy     #MAXCOLS-1
?04:    lda     (lpte),y
        sta     (lptc),y
        lda     (lpte1),y
        sta     (lptc1),y
        dey
        bpl     ?04
        ACC16CLC
        lda     lpte
        sta     lptc
        adc     #MAXCOLS
        sta     lpte
        lda     lpte1
        sta     lptc1
        adc     #MAXCOLS
        sta     lpte1
        ACC08   
        dex
        bne     ?02
        plb
        rts

; scroll up editor window (move window down one row)
; P28F9:
scrlup:
        phb
        CPU16CLC
        lda     #!LSTLINE
        sta     lptc
        tax
        sbc     #MAXCOLS-1              ; take account of CF = 0 !
        sta     lpte
        txa
        ora     #!TXTATTR
        sta     lptc1
        sbc     #MAXCOLS                ; now CF = 1 !
        sta     lpte1
        CPU08
        lda     #^LSTLINE
        pha
        plb
        ldx     #$17                    ; move 23 rows
?02:    ldy     #MAXCOLS-1
?04:    lda     (lpte),y
        sta     (lptc),y
        lda     (lpte1),y
        sta     (lptc1),y       
        dey
        bpl     ?04
        ACC16CLC
        lda     lpte
        sta     lptc
        sbc     #MAXCOLS-1              ; take account carry !
        sta     lpte
        lda     lpte1
        sta     lptc1
        sbc     #MAXCOLS                ; now CF = 1 !
        sta     lpte1
        ACC08   
        dex
        bne     ?02
        plb
        rts

; wait for <enter> key pressed
; in:   Y - column in last screen row
; X preserved
waitent:
        phx
        ldx     #0
?02:    lda     >strent,x
        beq     ?04
        cpy     #MAXCOLS                ; not above limit
        bcs     ?04
        sta     [stxtp],y
        inx
        iny
        bne     ?02
?04:    plx

waitent2:
        jsr     slgkey                  ; wait key pressed
        bcs     waitent2                ; control key
        xba                             ; ALT,CTL,SHIFT
        bne     waitent2                ; will be no pressed
        xba
        cmp     #$0D
        bne     waitent2
        rts

; put string in status line row (last screen row)
; in:   A - attribute
;       X - string number # (if $FF is cbm disk error)
; out:  Y - next available column in last row
msgstr:
        xba                             ; B = attribute
        cpx     #$FF
        bne     ?01
        ldx     #<EDDSKERR
        ldy     #>EDDSKERR
        lda     #^EDDSKERR
        bra     outstr
?01:    cpx     #MAXSTR
        bcc     ?02
        ldx     #0                      ; blank string
?02:    lda     STRTBLL,x               ; take string address
        pha
        lda     STRTBLH,x
        tay                             ; Y = high address
        plx                             ; X = low  address
        lda     #^str01                 ; A = bank address
        
; out string in status line (last screen row)
; in:   X,Y,A - address of string
;       B - attribute
; out:  Y - next available column in last row
; P284A:
outstr:
        stx     lptc                    ; store string address
        sty     lptc+1
        sta     lptc+2
        xba                             ; attribute
        tax                             ; X = attribute
        ACC16
        lda     #!STLINE                ; store address of last screen row
        sta     stxtp
        lda     #!STLATTR
        sta     sattp
        ACC08
        ldy     #0                      ; out string
?02:    lda     [lptc],y
        beq     ?04
        cpy     #MAXCOLS                ; not above limit
        bcs     ?10
        sta     [stxtp],y
        txa
        sta     [sattp],y       
        iny
        bne     ?02
?04:    phy
        lda     #' '                    ; pad row with blanks
        xba
        txa                             ; A = attribute, B = blank
?06:    cpy     #MAXCOLS
        bcs     ?08
        sta     [sattp],y
        xba
        sta     [stxtp],y
        xba
        iny
        bne     ?06
?08:    ply
?10:    rts

; get key for command line/status line
; in:   X - number of keys stored
;       Y - column
; out:  A = key code
;       B = flag ALT, CTL, SHIFT
;       CF = 1 if control key
; X,Y preserved
; P1BBE:
slgkey:
        jsr     slcurs                  ; set cursor position
        jsr     showcurs                ; show cursor
?02:    KBGETIN                         ; system call - get key
        cmp     #0
        beq     ?02                     ; loop -- wait pressed key
        cmp     #' '
        bne     ?04                     ; no blank key
        txa
        beq     ?02                     ; skip beginning blanks
        lda     #' '
?04:    sta     tmpe                    ; store key code
        xba
        sta     tmpf                    ; store control key flag
        jsr     hidecurs
        lda     >DP01ADDR+KbdFlag       
        xba                             ; B = flag ALT, CTL, SHIFT
        clc
        lda     tmpe                    ; key code
        bit     tmpf
        bpl     ?06
        sec                             ; control key
?06:    rts

; hide cursor
hidecurs:
        lda     #$10                    ; bit PB4 = 1
        ora     >PIAVBB+PIAPRB
        sta     >PIAVBB+PIAPRB
        rts

; show cursor
showcurs:
        lda     >PIAVBB+PIAPRB
        and     #$EF                    ; bit PB4 = 0
        sta     >PIAVBB+PIAPRB
        rts

; set position of cursor in status line row
; in:   Y = column
; X,Y preserved
slcurs:
        clc
        lda     #$0E
        sta     >CRTAddr
        tya
        adc     stxtp
        xba
        lda     stxtp+1
        bra     pcurs

; set position of cursor in edit window
; in:   Y = column
; X,Y preserved
edcurs:
        clc
        lda     #$0E
        sta     >CRTAddr
        tya
        adc     curs
        xba
        lda     curs+1
        
pcurs:
        adc     #0
        sta     >CRTData
        lda     #$0F
        sta     >CRTAddr
        xba
        sta     >CRTData
        rts

; set default cursor mode basis cursmode value
setcurs:
        lda     #$0B                    ; set 'end scan line' register
        sta     >CRTAddr
        lda     #$0F                    ; end at last line
        sta     >CRTData
        lda     #$0A                    ; set 'start scan line' register
        sta     >CRTAddr
        lda     #$00                    ; block cursor: start scan line = 0
        bit     cursmode                ; check bit <6>
        bvc     ?02                     ; block cursor
        lda     #$0F                    ; under line cursor: start = end
?02:    sta     >CRTData
        lda     >PIAVBB+PIAPRB
        and     #$FB                    ; mask PB2
        bit     cursmode                ; check bit <7>
        bpl     ?04                     ; fixed cursor => PB2 = 0
        ora     #$04                    ; blink cursor => PB2 = 1
?04:    sta     >PIAVBB+PIAPRB
        rts

;---------------------------------------------------------------------
; COMMAND LINE
        
; input comand string in EDBUFLIN
; in:   X,Y,A - address of prompt string
; P1AF9:
inputstr:
        stx     longp
        sty     longp+1
        sta     longp+2
        lda     #$C0
        sta     slfg            ; status line input mode
?lp:    lda     #0              ; input loop
        sta     >EDBUFLIN
        lda     scatt
        xba                     ; attribute
        ldx     longp
        ldy     longp+1
        lda     longp+2
        jsr     outstr          ; print prompt
        ldx     #0              ; buffer index
?get:   jsr     slgkey          ; get key
        bcc     ?key            ; no control key
        cmp     #KB_DELETE      ; <DELETE> clear all input field
        beq     ?lp             ; restart input
        cmp     #KB_BACKSPACE
        bne     ?get            ; discard others control keys
        txa
        beq     ?get            ; at first column do nothing
        dex                     ; decrement index and column
        dey
        lda     #' '            ; put blank at column
        sta     [stxtp],y
        bra     ?get            ; continue input
?key:   xba                     ; check flag
        bit     #(AALTB.OR.ACTRLB)
        bne     ?get            ; discard alt/ctl keys but shift
        xba
        cmp     #KB_ESC         ; <ESC> exit from command line
        beq     ?ret            ; exit with CF=1
        cmp     #KB_CR          ; <ENTER> terminate input line
        beq     ?end
        cmp     #' '
        bcc     ?get            ; discard no-printables
        cmp     #$7F
        bcs     ?get
        cpy     #MAXCOLS-1      ; no store above max. column
        bcs     ?get
        sta     [stxtp],y       ; print char at column
        sta     >EDBUFLIN,x     ; store char at index
        iny
        inx
        bra     ?get            ; continue input
?end:   txa                     ; current index
        beq     ?lp             ; empty string: restart
?trm:   dex                     ; trim blanks
        bmi     ?lp             ; restart
        lda     >EDBUFLIN,x
        cmp     #' '
        beq     ?trm
        inx
        lda     #0
        sta     >EDBUFLIN,x     ; terminate input
        clc                     ; exit with CF=0
?ret:   rts

cmdline:
        ldx     #<CMDSTR
        ldy     #>CMDSTR
        lda     #^CMDSTR
        jsr     inputstr
        lda     #$80
        trb     slfg
        rts

CMDSTR:
        .DB     'CMD: ',0

;---------------------------------------------------------------------

; entry point (DBR and DP set by caller)
;
; stack frame
;
;       ---------
;       |  ...  |       0F
;       ---------
;       |  DPH  |       06
;       ---------
;       |  DPL  |       05
;       ---------
;       |  DBR  |       04
;       ---------
;       |  PBR  |       03
;       ---------
;       |  PCH  |       02
;       ---------       
;       |  PCL  |       01
;       ---------

STKPCL          .SET    $01
STKPCH          .SET    $02
STKPBR          .SET    $03     ; caller return address
STKDBR          .SET    $04     ; DBR for called procedure
STKDP           .SET    $05     ; DP for called procedure

        .PUBLIC qedtent


qedtent:        
        php                     ; save M/X status
        CPU08
        phb
        phd                     ; frame stack +4
        pea     #$4000
        pld
        pha
        phx
        ldx     #$00
?zp:    stz     <$0,x           ; clear DP memory
        inx
        bne     ?zp
        INDEX16
        ldx     #(EDWRKEND-EDBUFNAM-1)
        lda     #0
?zz:    sta     >EDBUFNAM,x
        dex
        bpl     ?zz
        INDEX08
        stx     xbuf            ; force buffer allocation at start
        plx
        pla
        sta     longp           ; A,X,Y : address of command line
        stx     longp+1
        sty     longp+2
        xba
        sta     fsmode          ; mode  
        ACC16
        lda     >pbrklv
        sta     brksav
        ACC08   
        jsr     crtsav
        jsr     init
        jsr     chkcmd          ; check command line
        jsr     editor          ; launch editor
        lda     saveps
        sta     >PIAVBB+PIAPRA  ; restore palette address
        jsr     crtrest
        ldx     embit
        sta     >CREMEOFF,x     ; restore video ram bit

        ACC16
        lda     brksav
        sta     >pbrklv
        ACC08

        pld
        plb
        plp
        rtl

; init editor
; P1631:
init:
        lda     #MINFREE
        jsr     chkfree
        lda     #DEFLTAB        ; default tab value
        sta     deftab
        lda     #EDEFCURS       ; default cursor mode edit window
        sta     cursmode
        lda     #^TXTADDR       ; bank of video ram
        sta     stxtp+2
        sta     sattp+2
        lda     #DEFATTR        ; default editor window attribute
        sta     eattr
        lda     #DEFSATTR       ; default status line attribute
        sta     slattr
        lda     #DEFEATTR       ; default error message attribute
        sta     seatt
        lda     #DEFCATTR       ; default command line attribute
        sta     scatt
        lda     #DFGATTR        ; disabled flag indicator attribute
        sta     fgatt
        lda     #$40
        sta     slfg            ; update whole status line
        lda     #0
        pha
        plb                     ; DBR = 0
        ldx     CREMEOFF        ; save current video ram bit
        stx     embit
        sta     !CREMEON        ; enable video ram
        lda     !PIAVBB+PIAPRA  ; save current palette address
        sta     saveps
        ora     #$0F            ; set palette address = 11 11XXX XXXX
        sta     !PIAVBB+PIAPRA
        lda     #0
        tay                     ; Y = 0
        xba                     ; B = 0
        lda     #$F0            ; set base address palette
        CPU16
        asl     a
        asl     a               ; this make base address = $03C0
        tax
        ACC08
        lda     #$D0            ; LIGHT YELLOW/BLACK -- editor
        sta     >VBBPALRAM,x    ; palette=0
        inx
        lda     #$F2            ; WHITE/DARK BLUE -- status line
        sta     >VBBPALRAM,x    ; palette=1
        inx
        lda     #$92            ; LIGHT RED/DARK BLUE -- error line
        sta     >VBBPALRAM,x    ; palette=2
        inx
        ;lda    #$0E            ; BLACK/LIGHT GRAY -- command line
        lda     #$2F            ; DARK BLUE/WHITE -- command line
        sta     >VBBPALRAM,x    ; palette=3
        inx
        lda     #$E2            ; GRAY/DARK BLUE -- status line
        sta     >VBBPALRAM,x    ; palette=4
        CPU08
        lda     #0              ; start with buffer #0
        jsr     switchb
        lda     #$20            ; enable indent
        tsb     bflag
        jsr     setattr
        jmp     updwin

;---------------------------------------------------------------------

; convert byte A in decimal (3 digits stored in tstr2) 
byte2str:
        sta     wtmp
        stz     wtmp+1
        lda     #$80                    ; flag byte
        sta     ebtmp
        bra     int2s

; convert integer in wtmp in decimal (5 digits stored in tstr2)         
int2str:
        stz     ebtmp                   ; flag integer
int2s:
        stz     ebtmp2                  ; string index
        phb
        phk                             ; set DBR = PBR
        plb
        ldy     #8                      ; power 10 table access index
?02:    ldx     #0                      ; partial quotient
        sec
        ACC16                           ; repeated subctract
        lda     wtmp
?04:    sbc     P10TBL,y
        bcc     ?06                     ; stop subctract
        inx                             ; increment quotient
        bra     ?04
?06:    adc     P10TBL,y                ; store result
        sta     wtmp
        ACC08SEC
        txa                             ; 0..9
        adc     #'0'-1                   ; decimal digit
        ldx     ebtmp2                  ; string index
        sta     tstr2,x                 ; store digit
        inx
        stx     ebtmp2                  ; update string index
        dey
        dey
        bpl     ?02
        plb
        bit     ebtmp
        bpl     ?10
        ldx     #2                      ; adjust for byte
        ldy     #0
?08:    lda     <tstr2,x
        stx     tmp6
        tyx
        sta     <tstr2,x
        ldx     tmp6
        inx
        iny
        cpy     #3
        bcc     ?08
?10:    rts


;------------------------
exit:
        lda     #$80
        tsb     edtfg
        rts

; ALT-O
open:
        ldx     #<?opn
        ldy     #>?opn
        lda     #^?opn
        jsr     inputstr
        bcs     ?end
        jsr     hidecurs
        jsr     cbmopn
        ;lda    #$80            ; clear input mode flag
        ;trb    slfg
        ;lda    #$80
        ;trb    bflag           ; not modified
        jsr     updsl
?end:   rts
?opn:   .DB     'Open: ', 0

; ALT-S
save:
        jsr     chkbuf
        beq     ?end            ; clipboard or empty buffer
        lda     #$10            ; named buffer?
        bit     bflag
        beq     saveas          ; no, call saveas
        bit     fsmode
        bpl     ?fat            ; save fat file
        jmp     csave           ; save cbm file         
?fat:   jmp     fsave
?end:   rts

saveas:
        ldx     #<?sav
        ldy     #>?sav
        lda     #^?sav
        jsr     inputstr
        bcs     ?end
        bit     fsmode
        bpl     fsaveas
        bmi     csaveas
?end:   rts

?sav:   .DB     'Save: ', 0

fsaveas:
        clc
        rts

csaveas:
        lda     #^EDBUFFILE     ; set pointer to filename
        sta     longp+2
        lda     #<EDBUFFILE
        sta     longp
        lda     #>EDBUFFILE
        sta     longp+1 
        ldx     #0
        lda     #'@'
        sta     [longp]         ; replace flag
        ldy     #1
        lda     >EDDSKERR+1     ; check drive
        cmp     #':'
        bne     ?dr             ; store deafult drive '0'
        lda     >EDDSKERR
        cmp     #'0'             ; continue if drive 0 or 1
        beq     ?mv
        cmp     #'1'
        beq     ?mv
?dr:    lda     #'0'             ; put default drive '0'
        sta     [longp],y
        iny
        lda     #':'
        sta     [longp],y
        iny
?mv:    lda     >EDDSKERR,x     ; set filename
        beq     ?nxt
        cmp     #'a'            ; upper case
        bcc     ?st
        cmp     #'z'+1
        bcs     ?st
        and     #$DF
?st:    sta     [longp],y
        inx
        iny
        cpy     #MAXFNAME-8
        bcc     ?mv
?nxt:   ldx     #3
        phy                     ; save index
?lp:    lda     >?rdw,x
        sta     [longp],y
        iny
        dex
        bpl     ?lp
        lda     #0
        sta     [longp],y
        ACC16
        inc     longp           ; no overwrite for now
        ACC08
?opn:   jsr     cdskopn         ; open file
        ply
        bcc     ?ok             ; no error
        sty     bka
        lda     >EDDSKERR       ; check error 63 (file exist)
        cmp     #'6'
        bne     ?derr           ; error of another kind
        lda     >EDDSKERR+1
        cmp     #'3'
        bne     ?derr
        ldx     #<?msg          ; ask overwrite confirmation
        ldy     #>?msg
        lda     #^?msg
        jsr     confirm         ; ask confirmation
        bcs     ?end            ; no, <ESC>
        bne     ?end            ; no, <N>
        ACC16
        dec     longp
        ACC08
        ldy     bka
        phy
        bra     ?opn            ; try again with replace flag
?ok:    jsr     csave2
        bcs     ?end            ; some error
        ldx     #0
?cp:    lda     >EDBUFFILE+1,x  ; skip '@'
        sta     >EDCURFILE,x
        beq     ?upd
        inx
        bra     ?cp
?upd:   lda     bflag
        and     #$7F
        ora     #$10
        sta     bflag
?end:   lda     #$40
        sta     slfg
        jsr     updsl
        jmp     updwin

?derr:
        ldx     #$FF            ; disk error    
        jsr     error
        bra     ?end

?msg:   .DB     'File exist; overwrite <Y/N>?', 0
?rdw:   .DB     'W,S,'


; save CBM file 
csave:
        lda     #<EDBUFFILE     ; prepare filename
        sta     longp
        lda     #>EDBUFFILE
        sta     longp+1
        lda     #^EDBUFFILE
        sta     longp+2
        lda     #'@'            ; replace flag
        sta     [longp]
        ldy     #1
        ldx     #0
?nam:   lda     >EDCURFILE,x
        beq     ?nxt
        sta     [longp],y
        iny
        inx
        cpy     #18
        bcc     ?nam
?nxt:   ldx     #3
        phy
?lp:    lda     >_?rdw,x
        sta     [longp],y
        iny
        dex
        bpl     ?lp
        lda     #0
        sta     [longp],y
        jsr     cdskopn         ; open file
        ply
        bcs     _?derr          ; error
csave2:
        lda     #0
        sta     [longp],y
        lda     longp+2
        pha
        pei     (longp)
        phk
        pea     #_?sav
        lda     #7
        pha
        BSPRINTF2               ; format in local string
        phx                     ; bank that hold string
        tax                     ; low address
        xba
        tay                     ; hi address
        lda     slattr          ; attribute
        xba
        pla                     ; bank
        jsr     outstr
        lda     #$40            ; force update status line
        sta     slfg
        jsr     savbuf
        bcs     _?derr
        jsr     updsl
        clc
_?end:  php     
        jsr     updwin
        plp
        rts

_?derr:
        ldx     #$FF            ; disk error    
        jsr     error
        sec
        bra     _?end

_?rdw:  .DB     'W,S,'
_?sav:  .DB     'Saving "%s"...', 0

; save current buffer
savbuf:
        jsr     mvpp2           ; save buffer pointer
        ACC16
        lda     pbuf            ; set pointer to start
        sta     ppage
        stz     bka
        lda     #EDDSKBUF       ; set disk buffer pointer
        sta     pb
        ldx     #^EDDSKBUF
        stx     pb+2
        ACC08
        lda     #BSTART
        sta     ixb
        bra     ?get
?nxt:   jsr     incptr          ; inc buffer pointer    
?get:   jsr     getbyte         ; get next byte
        bcs     ?end            ; end of text
        jsr     ?put            ; put into disk buffer
        bcs     ?rst            ; error
        cmp     #$0D
        bne     ?nxt
        lda     #$0A            ; dos style text file
        jsr     ?put
        bcs     ?rst            ; error
        bra     ?nxt            ; next byte
?end:   clc                     ; no error      
        lda     bka             ; check if must flush disk buffer
        ora     bka+1
        beq     ?cls            ; no flush: close file
        jsr     ?wr             ; flush buffer
?cls:   php     
        bit     fsmode          ; close file
        bpl     ?fcls
        lda     #$0E            ; close file
        CBMFSCLS        
        bra     ?go
?fcls:  nop
?go:    plp
?rst:   jsr     pp2mv           ; restore pointer
        bcs     ?end2
        lda     #$80
        trb     bflag           ; clear modified flag
?end2:  rts

?put:   INDEX16                 ; insert into disk buffer
        ldy     bka             ; current index
        sta     [pb],y          ; store byte
        iny                     ; update index
        sty     bka
        cpy     #EDDSKBUFSIZ    ; check if full
        INDEX08
        bcc     ?rts
?wr:    bit     fsmode          ; write buffer to disk
        bpl     ?wfat           ; fat file
        lda     pb+2            ; set buffer pointer
        pha
        pei     (pb)
        pei     (bka)           ; buffer size
        lda     #$0E
        pha                     ; chnl 14
        CBMFSWR                 ; write buffer
        bcc     ?ok
        jsr     cdskerr         ; get error string
        lda     #$0E            ; close file
        CBMFSCLS        
        sec                     ; error
        rts
?wfat:  clc
?ok:    stz     bka             ; clear index
        stz     bka+1
?rts:   rts

fsave:
        clc
        rts

; check current buffer
; ZF=1 if clipboard or empty buffer
chkbuf:
        lda     xbuf
        cmp     #CLIPBRD
        beq     ?end            ; is clipboard
        lda     pbuf
        sta     pb+1
        lda     pbuf+1
        sta     pb+2
        stz     pb
        ldy     #BSTART
        lda     [pb],y          ; ZF=1 if empty
?end:   rts

; ALT-N
clrbuf:
        jsr     chkbuf
        beq     ?end            ; clipboard or empty buffer
        ldx     #<?sclr
        ldy     #>?sclr
        lda     #^?sclr
        jsr     confirm         ; ask confirmation
        bcs     ?end            ; no, <ESC>
        bne     ?end            ; no, <N>
        bit     bflag           ; buffer modified?
        bpl     ?go             ; no
        jsr     save
?go:    stz     cline
        stz     cline+1
        lda     xbuf
        jsr     freebuf
        lda     #$40
        sta     slfg
        jsr     updwin
?end:   rts

?sclr:  .DB     'Are you sure to clear current buffer <Y/N>?', 0

; X,Y,A = string ptr
; CF = 1 if <ESC>
; CF=0, ZF=0 if <N>
; CF=0, ZF=1 if <Y>
confirm:
        xba
        lda     seatt
        xba
        jsr     outstr
?get:   jsr     slgkey          ; wait key pressed
        bcs     ?get            ; control key
        xba                     ; ALT,CTL,SHIFT
        bne     ?get            ; will be no pressed
        xba
        cmp     #KB_ESC
        beq     ?end            ; exit with CF=1
        cmp     #'a'
        bcc     ?nxt
        cmp     #'z'+1
        bcs     ?nxt
        and     #$DF            ; capitalize
?nxt:   cmp     #'Y'
        beq     ?ok             ; exit with CF=0, ZF=1
        cmp     #'N'
        bne     ?get
        inc     a               ; exit with CF=0, ZF=0
?ok:    clc
?end:   php     
        lda     #$40            ; force updare status line
        sta     slfg
        jsr     updsl
        plp
        rts

;ALT-T
settab:
        lda     deftab          ; prepare prompt string
        pha
        lda     #MAXTABVAL
        pha
        lda     #MINTABVAL
        pha
        phk                     ; bank of format string
        pea     #?tstr
        lda     #7
        pha
        BSPRINTF2               ; format in local string
        stx     bka             ; bank
        tax                     ; low address
        xba
        tay                     ; hi address
        lda     bka
        jsr     inputstr
        bcs     ?end
        jsr     getnum          ; get number in bka
        bcs     ?end            ; error
        ldx     bka
        lda     bka+1
        beq     ?ok
?err:   ldy     #MAXTABVAL
        phy
        ldy     #MINTABVAL
        phy
        pha                     ; illegal value
        phx
        pea     #EDERRSIZ       ; size of dest. string
        lda     #^EDDSKERR      ; eror dest. string
        pha
        pea     #EDDSKERR
        phk                     ; format string
        pea     #?serr
        lda     #13
        pha
        BSPRINTF
        ldx     #$FF            ; error string in EDDSKERR
        jsr     error
        bra     ?end
?ok:    cpx     #MINTABVAL
        bcc     ?err
        cpx     #MAXTABVAL+1
        bcs     ?err
        stx     deftab
?end:   lda     #$80            ; clear input mode flag
        trb     slfg
        rts

?tstr:  .DB     'Set tab value in range %bu..%bu (current value: %bu): ', 0
?serr:  .DB     'Illegal tab value: %hu (must be in range %bu..%bu)', 0

; ALT-G
gotoln:
        ldx     #<?gto
        ldy     #>?gto
        lda     #^?gto
        jsr     inputstr
        bcs     ?end
        jsr     getnum          ; get number in bka
        bcs     ?end            ; error
        lda     bka
        ora     bka+1
        beq     ?hom
        cmp     #1
        bne     ?nxt
?hom:   jsr     gohome
        bra     ?end
?nxt:   ACC16
        lda     bka
        cmp     ncount
        ACC08
        bcc     ?gol
        jsr     goend
        bra     ?end
?gol:   ACC16
        cmp     cline
        ACC08
        beq     ?end
        ACC16
        ldx     #0
        bcs     ?gol1           ; > cline
        dex                     ; < cline
        sec
        lda     cline
        sbc     bka
        bra     ?gol2
?gol1:  sbc     cline
?gol2:  sta     bkb
        ACC08
        txy
        bpl     ?down           ; go down
        JSR     pp8mv
?01:    JSR     startln
        ACC16
        BCS     ?05
        ldx     fslct
        BEQ     ?03
        DEC     nslctl
?03:    DEC     cline
?05:    DEC     bkb
        ACC08
        BNE     ?01
        LDA     #$06
        bra     ?10
?down:
?01a:   JSR     nextln
        ACC16
        BCS     ?03a
        ldx     fslct
        BEQ     ?02a
        INC     nslctl
?02a:   INC     cline
?03a:   DEC     bkb
        ACC08
        BNE     ?01a
        LDA     #$11

?10:    jsr     epage
?end:   lda     #$80            ; clear input mode flag
        trb     slfg
        rts

?gto:   .DB     'Goto line #: ', 0

getnum:
        ldx     #0
        stx     bka
        stx     bka+1
        stx     bkb+1
?nxt:   jsr     ?get
        tay
        beq     ?ret            ; end of string
        bcs     ?err
        sbc     #'0'-1
        sta     bkb
        ACC16
        lda     bka
        cmp     #6554
        bcs     ?end            ; overflow
        asl     a
        asl     a
        adc     bka
        asl     a
        adc     bkb
        sta     bka
?end:   ACC08
        bcc     ?nxt
?err:   ldx     #8
        jsr     error
        lda     #$80
        trb     slfg
        sec
        rts
?ret:   clc     
        rts

?get:   lda     >EDBUFLIN,x
        inx
        cmp     #'9'+1
        bcs     ?ex
        sec
        sbc     #$30
        sec
        sbc     #$D0
?ex:    rts

;---------------------
; save crt buffer & page 01
crtsav:
        lda     >CREMEOFF       ; save current video ram bit
        tay
        sta     >CREMEON        ; enable video ram
        CPU16
        ldx     #$0FFF          ; move 4k
?lp:    lda     >VBBCHARRAM,x
        sta     >EDCRTSAV,x
        dex
        bpl     ?lp
        CPU08
        tyx
        sta     >CREMEOFF,x     ; restore video ram bit
        ldx     #ScnLinTmp      ; save page 01
?lp2:   lda     !DP01ADDR,x
        sta     >EDSAVE01,x
        inx
        bne     ?lp2
        rts

crtrest:
        lda     >CREMEOFF       ; save current video ram bit
        tay
        sta     >CREMEON        ; enable video ram
        CPU16
        ldx     #$0FFF          ; move 4k
?lp:    lda     >EDCRTSAV,x
        sta     >VBBCHARRAM,x
        dex
        bpl     ?lp
        CPU08
        lda     #$F0            ; who change this byte????
        sta     >VBBPALRAM
        tyx
        sta     >CREMEOFF,x     ; restore video ram bit
        ldx     #ScnLinTmp      ; restore page 01
?lp2:   lda     >EDSAVE01,x
        sta     !DP01ADDR,x
        inx
        bne     ?lp2
        rts

; --- load editor buffer
; longp: buffer pointer
; dbufsiz: buffer size
bufld:
        phx
        lda     dbufsiz
        ora     dbufsiz+1
        beq     ?end            ; empty
?nxt:   lda     [longp]         ; get byte
        cmp     #$0A            ; skip line feed
        beq     ?inc
        cmp     #$0D
        beq     ?ins
        cmp     #KB_TAB         ; discard non printable but TAB & CR
        beq     ?tab
        cmp     #' '
        bcc     ?inc
        ldx     bka
        cpx     #MAXTEXTLEN
        bcc     ?ins
        sta     bka+1
        lda     #$0D
        jsr     insert
        ACC16
        inc     ncount
        ACC08
        jsr     incptr2
        stz     bka
        lda     bka+1
?ins:   jsr     insert          ; insert byte in editor buffer
        inc     bka             ; update text lenght
        bcc     ?cr             ; ok, room available
        bcs     ?em             ; memory error
?tab:   jsr     ?tkey
        bra     ?inc
?em:    ldy     #$FE
        lda     #$0D    
        sta     [pblk],y
        iny
        lda     #0
        sta     [pblk],y
        ACC16
        inc     ncount
        ACC08
        bra     ?ret    
?cr:    cmp     #$0D            ; last byte was a CR?
        bne     ?upd            ; no
        stz     bka
        ACC16CLC
        inc     ncount          ; update lines count
        bne     ?nov
        sec                     ; lines count overflow
        dec     ncount
?nov:   ACC08
        bcc     ?upd
        jsr     incptr2
?ret:   plx
        sec                     ; error
        rts
?upd:   jsr     incptr2         ; update editor buffer pointer
?inc:   ACC16
        inc     longp           ; update buffer pointer
        dec     dbufsiz         ; update size
        ACC08
        bne     ?nxt
?end:   plx     
        clc
        rts

?tkey:  lda     #0              ; put blank's instead tab's
?tb0:   clc
?tb1:   adc     #8              ; assume default tab = 8
        cmp     bka
        beq     ?tb0
        bcc     ?tb1
        sbc     bka
        beq     ?tbx
        sta     ctmp2
?tbl:   lda     #' '
        jsr     insert
        jsr     incptr2
        inc     bka
        dec     ctmp2
        bne     ?tbl
?tbx:   rts

; check command line for open file
chkcmd:
        lda     longp
        ora     longp+1
        ora     longp+2
        beq     ?end            ; null pointer
        lda     [longp]
        beq     ?end            ; empty command line
        ldy     #0
        tyx
?mv:    lda     [longp],y
        sta     >EDDSKERR,x
        iny
        inx
        bne     ?mv
        jsr     cbmopn
?end:   rts

;------ CBM FS

; open CBM file
; filename in EDDSKERR buffer
cbmopn:
        lda     #^EDBUFFILE     ; set pointer to filename
        sta     longp+2
        lda     #<EDBUFFILE
        sta     longp
        lda     #>EDBUFFILE
        sta     longp+1 
        ldx     #0
        txy
        lda     >EDDSKERR+1     ; check drive
        cmp     #':'
        bne     ?dr             ; store deafult drive '0'
        lda     >EDDSKERR
        cmp     #'0'             ; continue if drive 0 or 1
        beq     ?mv
        cmp     #'1'
        beq     ?mv
?dr:    lda     #'0'             ; put default drive '0'
        sta     [longp]
        iny
        lda     #':'
        sta     [longp],y
        iny
?mv:    lda     >EDDSKERR,x     ; set filename
        beq     ?nxt
        cmp     #'a'            ; upper case
        bcc     ?st
        cmp     #'z'+1
        bcs     ?st
        and     #$DF
?st:    sta     [longp],y
        inx
        iny
        bne     ?mv
?nxt:   ldx     #3
        phy                     ; save index
?lp:    lda     >?rds,x
        sta     [longp],y
        iny
        dex
        bpl     ?lp
        lda     #0
        sta     [longp],y
        jsr     cdskopn         ; open file
        ply
        bcs     ?derr           ; error
        lda     #0
        sta     [longp],y
        lda     longp+2
        pha
        pei     (longp)
        lda     #^LOADMSG
        pha
        pea     #LOADMSG
        lda     #7
        pha
        BSPRINTF2               ; format in local string
        phx                     ; bank that hold string
        tax                     ; low address
        xba
        tay                     ; hi address
        lda     slattr          ; attribute
        xba
        pla                     ; bank
        jsr     outstr
        lda     #$40            ; force update status line
        sta     slfg
        jsr     mvpp2
        stz     bka             ; used for count text lenght
?ld:    jsr     cdskld          ; load buffer
        bcs     ?derr
        beq     ?end            ; end
        jsr     bufld
        bcs     ?end
        txa                     ; eof status
        bpl     ?ld
?end:   php
        lda     #$0E            ; close file
        CBMFSCLS        
        plp
        bcs     ?err04
        ldx     #$FF            ; update buffer filename
?fn:    inx     
        lda     >EDBUFFILE,x
        sta     >EDCURFILE,x
        bne     ?fn
        lda     bflag
        and     #$7F            ; clear modified flag
        ora     #$10            ; set valid fname flag
        sta     bflag
        jsr     decptr2
        bcs     ?err
        jsr     getbyte
        cmp     #$0D
        beq     ?err
        jsr     incptr2
        lda     #$0D
        jsr     insert
?err:   jsr     pp2mv
        jmp     updwin

?derr:  ldx     #$FF            ; disk error    
        jsr     error
        bra     ?err
?err02: ldx     #2      
        jsr     error
        bra     ?err
?err04: ldx     #4      
        jsr     error
        bra     ?err

?rds:   .DB     'R,S,'

; load a block from CBM disk on chnl 14
; CF = 1 if error
; ZF = 1 if buffer is empty
; X = $80 if eof
cdskld:
        lda     #^EDDSKBUF      ; set buffer pointer
        pha
        pea     #EDDSKBUF
        pea     #EDDSKBUFSIZ    ; buffer size
        lda     #$0E
        pha                     ; chnl 14
        CBMFSRD                 ; read buffer
        bcc     ?ok
        jsr     cdskerr         ; get error string
        lda     #$0E            ; close file
        CBMFSCLS        
        sec                     ; error
        rts
?ok:    ACC16   
        sta     dbufsiz         ; store size
        pha
        lda     #EDDSKBUF
        sta     longp           ; reset buffer pointer
        ldx     #^EDDSKBUF
        stx     longp+2
        ldx     #$80            ; eof flag
        pla                     ; eof
        beq     ?end            ; ZF = 1 if buffer is empty
        cmp     #EDDSKBUFSIZ
        bcc     ?end            ; eof
        dex                     ; not eof
?end:   ACC08
        clc
        rts

; send command to cbm fs emulator
; command string in longp
cdskcmd:
        lda     #15
        bra     cdsksnd
        
; open file 
cdskopn:
        lda     #$0E

cdsksnd:
        ldx     longp+2         ; bank of cmnd string
        phx
        pei     (longp)         ; address of cmnd string
        pha                     ; chnl
        CBMFSCMD                ; send command
        bcs     cdskerr         ; if error
        rts

; get CBM disk error (in: CF = 1 if error pending else CF = 0)
cdskerr:
        php                     ; save carry
        lda     #^EDDSKERR
        pha                     ; address of buffer
        pea     #EDDSKERR
        pea     #EDERRSIZ       ; size of buffer
        lda     #15             ; channel 15
        pha
        CBMFSRD                 ; read
        plp
        bcs     ?end            ; error pending
        lda     >EDDSKERR
        ora     >EDDSKERR+1
        cmp     #'0'
        clc
        beq     ?end
        sec
?end:   rts

        
; test load 
testl:
        .EXTERN PCERRS

        ;bra    ?110
        ldx     #0
?lp:    lda     >?100,x
        sta     >EDDSKERR,x
        beq     ?lp1
        inx
        bne     ?lp
?lp1:   jmp     cbmopn

?100    .DB     '1:test10.pas',0

?110:
        lda     #<PCERRS
        sta     pb
        lda     #>PCERRS
        sta     pb+1
        lda     #^PCERRS
        sta     pb+2
        jsr     mvpp2
?02:    lda     [pb]
        beq     ?06
        jsr     insert
        bcc     ?03
        ldy     #$FE
        lda     #$0D    
        sta     [pblk],y
        iny
        lda     #0
        sta     [pblk],y
        ACC16
        inc     ncount
        ACC08
        bra     ?08     
?03:    cmp     #$0D
        bne     ?04
        ACC16
        inc     ncount                  ; check overflow !!!
        ACC08
?04:    jsr     incptr2
        ACC16
        inc     pb
        ACC08
        bra     ?02
?06:    jsr     decptr2
        bcs     ?08
?07:    jsr     getbyte
        cmp     #$0D
        beq     ?08
        jsr     incptr2
        lda     #$0D
        jsr     insert
?08:    jsr     pp2mv
        jmp     updwin

P10TBL:
        .DW     1
        .DW     10
        .DW     100
        .DW     1000
        .DW     10000

STRTBLL:
        .DB     <str00, <str01, <str02, <str03, <str04, <str05, <str06, <str07
        .DB     <str08

MAXSTR  .EQU    ($ - STRTBLL)

STRTBLH:
        .DB     >str00, >str01, >str02, >str03, >str04, >str05, >str06, >str07
        .DB     >str08

strent:
        .DB     ' - hit <enter>...', 0

str00:
        .DB     'OK, no error', 0

str01:
        .DB     'Out of memory', 0

str02:
        .DB     'Invalid command', 0

str03:
        .DB     'Illegal tab value', 0

str04:
        .DB     'Not enough memory', 0
        
str05:
        .DB     'Clipboard: illegal command', 0

str06:
        .DB     'Can''t paste text: lines count overflow', 0

str07:
        .DB     'Can''t insert a new line: lines count overflow', 0

str08:
        .DB     'Illegal numeric value', 0

LOADMSG:
        .DB     'Loading "%s"...', 0

stlstr:
.DB     'buffer:#0 "                  "                M I O SCN  N:00000  L:00000 C:000 '
stlstr1:
.DB     'buffer:#0 "                                 " M I O SCN  N:00000  L:00000 C:000 '
;        0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
stlstr2:
.DB     'CLIPBOARD                                     M I O SCN  N:00000  L:00000 C:000 '

; control key's table
KEYTBL:
        .DB     KB_CSRLEFT, KB_CSRDOWN, KB_CSRUP, KB_CSRRIGHT
        .DB     KB_HOME, KB_END, KB_PGUP, KB_PGDOWN
        .DB     KB_BACKSPACE, KB_SHIFTHOME, KB_SHIFTEND, KB_CTLTAB
        .DB     KB_SHCR, KB_DELETE, KB_INSERT, KB_CTLESC

        ; ALT-X : quit | ALT-O: open | ALT-N: new | ALT-T: set tab
        .DB     'x', 'o', 'n', 't'
        ; ALT-G: goto | ALT-S: save
        .DB     'g', 's'

KEYTBLLEN       .EQU    ($ - KEYTBL - 1)

; control key's function table
KEYPROC:
        .DW     csrleft, csrdwn, csrup, csrrght
        .DW     gohome, goend, pageup, pagedwn
        .DW     backkey, gostartln, goendln, tind
        .DW     kshenter, delkey, tins, testl

        .DW     exit, open, clrbuf, settab
        .DW     gotoln, save

; key's table
KEYTBL2:
        .DB     KB_CTLC, KB_TAB, KB_CR, KB_CTLV
        .DB     KB_CTLX, KB_ESC, KB_CTLS, KB_CTLY

KEYTBLLEN2      .EQU    ($ - KEYTBL2 - 1)

; no-control key function table
KEYPROC2:
        .DW     copysel, tabkey, kenter, pastesel  
        .DW     cutsel, cmdline, seltxt, delline