collapseos/apps/ed/main.asm

171 lines
4.0 KiB
NASM
Raw Normal View History

2019-07-13 09:57:37 -04:00
; ed - line editor
;
; A text editor modeled after UNIX's ed, but simpler. The goal is to stay tight
; on resources and to avoid having to implement screen management code (that is,
; develop the machinery to have ncurses-like apps in Collapse OS).
;
; ed has a mechanism to avoid having to move a lot of memory around at each
; edit. Each line is an element in an doubly-linked list and each element point
; to an offset in the "scratchpad". The scratchpad starts with the file
; contents and every time we change or add a line, that line goes to the end of
; the scratch pad and linked lists are reorganized whenever lines are changed.
; Contents itself is always appended to the scratchpad.
;
; That's on a resourceful UNIX system.
;
; That doubly linked list on the z80 would use 7 bytes per line (prev, next,
; offset, len), which is a bit much. Moreover, there's that whole "scratchpad
; being loaded in memory" thing that's a bit iffy. We sacrifice speed for
; memory usage.
;
; So here's what we do. First, we have two scratchpads. The first one is the
2019-07-13 11:29:06 -04:00
; file being read itself. The second one is memory, for modifications we
2019-07-13 09:57:37 -04:00
; make to the file. When reading the file, we note the offset at which it ends.
; All offsets under this limit refer to the first scratchpad. Other offsets
; refer to the second.
;
2019-07-13 11:29:06 -04:00
; Then, our line list is just an array of 16-bit offsets. This means that we
2019-07-13 09:57:37 -04:00
; don't have an easy access to line length and we have to move a lot of memory
; around whenever we add or delete lines. Hopefully, "LDIR" will be our friend
; here...
;
2019-07-13 11:29:06 -04:00
; *** Usage ***
;
; ed takes no argument. It reads from the currently selected blkdev and writes
; to it. It repeatedly presents a prompt, waits for a command, execute the
; command. 'q' to quit.
;
; Enter a number to print this line's number. For ed, we break with Collapse
; OS's tradition of using hex representation. It would be needlessly confusing
; when combined with commands (p, c, d, a, i). All numbers in ed are
; represented in decimals.
;
2019-07-13 14:01:20 -04:00
; Like in ed, line indexing is one-based. This is only in the interface,
; however. In the code, line indexes are zero-based.
;
2019-07-13 09:57:37 -04:00
; *** Requirements ***
2019-07-13 11:29:06 -04:00
; BLOCKDEV_SIZE
2019-07-13 14:01:20 -04:00
; addHL
2019-07-13 11:29:06 -04:00
; blkGetC
; blkSeek
2019-07-13 14:01:20 -04:00
; blkTell
; cpHLDE
; intoHL
2019-07-13 09:57:37 -04:00
; printstr
; printcrlf
; stdioGetLine
2019-07-13 14:01:20 -04:00
; stdioPutC
; stdioReadC
; unsetZ
;
; *** Variables ***
;
.equ ED_CURLINE ED_RAMSTART
.equ ED_RAMEND ED_CURLINE+2
2019-07-13 09:57:37 -04:00
edMain:
; diverge from UNIX: start at first line
ld hl, 0
ld (ED_CURLINE), hl
2019-07-13 14:01:20 -04:00
; Fill line buffer
.fillLoop:
2019-07-13 14:01:20 -04:00
call blkTell ; --> HL
call blkGetC
jr nz, .mainLoop
2019-07-13 14:01:20 -04:00
call bufAddLine
2019-07-13 11:29:06 -04:00
call ioGetLine
jr .fillLoop
2019-07-13 11:29:06 -04:00
.mainLoop:
2019-07-13 14:01:20 -04:00
ld a, ':'
call stdioPutC
2019-07-13 09:57:37 -04:00
.inner:
call stdioReadC
jr nz, .inner ; not done? loop
; We're done. Process line.
call printcrlf
call stdioGetLine
2019-07-13 21:08:16 -04:00
call cmdParse
jr nz, .error
2019-07-14 09:04:51 -04:00
ld a, (CMD_TYPE)
2019-07-13 09:57:37 -04:00
cp 'q'
2019-07-14 09:04:51 -04:00
jr z, .doQuit
2019-07-14 10:32:28 -04:00
cp 'd'
jr z, .doDel
2019-07-13 21:08:16 -04:00
jr .doPrint
2019-07-14 09:04:51 -04:00
.doQuit:
xor a
ret
2019-07-14 10:32:28 -04:00
.doDel:
call edReadAddrs
jr nz, .error
; bufDelLines expects an exclusive upper bound, which is why we inc DE.
inc de
call bufDelLines
jr .mainLoop
2019-07-13 21:08:16 -04:00
.doPrint:
2019-07-14 09:04:51 -04:00
call edReadAddrs
jr nz, .error
2019-07-13 22:09:17 -04:00
.doPrintLoop:
push hl
2019-07-13 14:01:20 -04:00
call bufGetLine
2019-07-13 21:08:16 -04:00
jr nz, .error
call printstr
call printcrlf
2019-07-13 22:09:17 -04:00
pop hl
call cpHLDE
2019-07-14 09:04:51 -04:00
jr z, .doPrintEnd
2019-07-13 22:09:17 -04:00
inc hl
jr .doPrintLoop
2019-07-14 09:04:51 -04:00
.doPrintEnd:
ld (ED_CURLINE), hl
jr .mainLoop
2019-07-13 21:08:16 -04:00
.error:
2019-07-13 14:01:20 -04:00
ld a, '?'
call stdioPutC
call printcrlf
2019-07-13 21:08:16 -04:00
jr .mainLoop
2019-07-13 14:01:20 -04:00
2019-07-13 21:08:16 -04:00
; Transform an address "cmd" in IX into an absolute address in HL.
edResolveAddr:
ld a, (ix)
cp RELATIVE
jr z, .relative
; absolute
ld l, (ix+1)
ld h, (ix+2)
ret
2019-07-13 21:08:16 -04:00
.relative:
ld hl, (ED_CURLINE)
2019-07-13 22:09:17 -04:00
push de
2019-07-13 21:08:16 -04:00
ld e, (ix+1)
ld d, (ix+2)
add hl, de
2019-07-13 22:09:17 -04:00
pop de
ret
2019-07-14 09:04:51 -04:00
; Read absolute addr1 in HL and addr2 in DE. Also, check bounds and set Z if
; both addresses are within bounds, unset if not.
edReadAddrs:
ld ix, CMD_ADDR2
call edResolveAddr
ex de, hl
ld hl, (BUF_LINECNT)
ex de, hl ; HL: addr2 DE: cnt
call cpHLDE
jp nc, unsetZ ; HL (addr2) >= DE (cnt). no good
ex de, hl ; DE: addr2
ld ix, CMD_ADDR1
call edResolveAddr
ex de, hl ; HL: addr2, DE: addr1
call cpHLDE
jp c, unsetZ ; HL (addr2) < DE (addr1). no good
ex de, hl ; HL: addr1, DE: addr2
cp a ; ensure Z
ret