|
- ; *** Consts ***
- ; maximum number of lines (line number maximum, however, is always 0xffff)
- .equ BUF_MAXLINES 0x100
- ; Size of the string pool
- .equ BUF_POOLSIZE 0x1000
-
- ; *** Variables ***
- ; A pointer to the first free line
- .equ BUF_LFREE BUF_RAMSTART
- ; A pointer to the first free byte in the pool
- .equ BUF_PFREE @+2
- ; The line index. Each record consists of 4 bytes: 2 for line number,
- ; 2 for pointer to string in pool. Kept in order of line numbers.
- .equ BUF_LINES @+2
- ; The line pool. A list of null terminated strings. BUF_LINES records point
- ; to those strings.
- .equ BUF_POOL @+BUF_MAXLINES*4
- .equ BUF_RAMEND @+BUF_POOLSIZE
-
- bufInit:
- ld hl, BUF_LINES
- ld (BUF_LFREE), hl
- ld hl, BUF_POOL
- ld (BUF_PFREE), hl
- cp a ; ensure Z
- ret
-
- ; Add line at (HL) with line number DE to the buffer. The string at (HL) should
- ; not contain the line number prefix or the whitespace between the line number
- ; and the comment.
- ; Note that an empty string is *not* an error. It will be saved as a line.
- ; Z for success.
- ; Error conditions are:
- ; * not enough space in the pool
- ; * not enough space in the line index
- bufAdd:
- ; Check whether we have enough pool space. This is done in all cases.
- call strlen
- inc a ; strlen doesn't include line termination
- exx ; preserve HL and DE
- ld hl, (BUF_PFREE)
- call addHL
- ld de, BUF_RAMEND
- sbc hl, de
- exx ; restore
- ; no carry? HL >= BUF_RAMEND, error. Z already unset
- ret nc
-
- ; Check the kind of operation we make: add, insert or replace?
- call bufFind
- jr z, .replace ; exact match, replace
- call c, .insert ; near match, insert
-
- ; do we have enough index space?
- exx ; preserve HL and DE
- ld hl, (BUF_LFREE)
- ld de, BUF_POOL-4
- or a ; reset carry
- sbc hl, de
- exx ; restore
- ; no carry? HL >= BUF_POOL, error. Z already unset
- ret nc
-
- ; We have enough space.
- ; set line index data
- push de ; --> lvl 1
- ld (ix), e
- ld (ix+1), d
- ld de, (BUF_PFREE)
- ld (ix+2), e
- ld (ix+3), d
-
- ; Increase line index size
- ld de, (BUF_LFREE)
- inc de \ inc de \ inc de \ inc de
- ld (BUF_LFREE), de
-
- ; Fourth step: copy string to pool
- ld de, (BUF_PFREE)
- call strcpyM
- ld (BUF_PFREE), de
- pop de ; <-- lvl 1
- ret
-
- ; No need to add a new line, just replace the current one.
- .replace:
- ld (ix), e
- ld (ix+1), d
- push de
- ld de, (BUF_PFREE)
- ld (ix+2), e
- ld (ix+3), d
- call strcpyM
- ld (BUF_PFREE), de
- pop de
- ret
-
- ; An insert is exactly like an add, except that lines following insertion point
- ; first.
- .insert:
- push hl
- push de
- push bc
- ; We want a LDDR that moves from (BUF_LFREE)-1 to (BUF_LFREE)+3
- ; for a count of (BUF_LFREE)-BUF_LINES
- ld hl, (BUF_LFREE)
- ld de, BUF_LINES
- or a ; clear carry
- sbc hl, de
- ld b, h
- ld c, l
- ld hl, (BUF_LFREE)
- ld d, h
- ld e, l
- dec hl
- inc de \ inc de \ inc de
- lddr
- pop bc
- pop de
- pop hl
- ret
-
- ; Set IX to point to the beginning of the pool.
- ; Z set if (IX) is a valid line, unset if the pool is empty.
- bufFirst:
- ld ix, BUF_LINES
- jp bufEOF
-
- ; Given a valid line record in IX, move IX to the next line.
- ; This routine doesn't check that IX is valid. Ensure IX validity before
- ; calling.
- bufNext:
- inc ix \ inc ix \ inc ix \ inc ix
- jp bufEOF
-
- ; Returns whether line index at IX is past the end of file, that is,
- ; whether IX == (BUF_LFREE)
- ; Z is set when not EOF, unset when EOF.
- bufEOF:
- push hl
- push de
- push ix \ pop hl
- or a ; clear carry
- ld de, (BUF_LFREE)
- sbc hl, de
- jr z, .empty
- cp a ; ensure Z
- .end:
- pop de
- pop hl
- ret
- .empty:
- call unsetZ
- jr .end
-
- ; Given a line index in (IX), set HL to its associated string pointer.
- bufStr:
- ld l, (ix+2)
- ld h, (ix+3)
- ret
-
- ; Browse lines looking for number DE. Set IX to point to one of these :
- ; 1 - an exact match
- ; 2 - the first found line to have a higher line number
- ; 3 - EOF
- ; Set Z on an exact match, C on a near match, NZ and NC on EOF.
- bufFind:
- call bufFirst
- ret nz
- .loop:
- ld a, d
- cp (ix+1)
- ret c ; D < (IX+1), situation 2
- jr nz, .next
- ld a, e
- cp (ix)
- ret c ; E < (IX), situation 2
- ret z ; exact match!
- .next:
- call bufNext
- ret nz
- jr .loop
|