Mirror of CollapseOS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
3.6KB

  1. ; ed - line editor
  2. ;
  3. ; A text editor modeled after UNIX's ed, but simpler. The goal is to stay tight
  4. ; on resources and to avoid having to implement screen management code (that is,
  5. ; develop the machinery to have ncurses-like apps in Collapse OS).
  6. ;
  7. ; ed has a mechanism to avoid having to move a lot of memory around at each
  8. ; edit. Each line is an element in an doubly-linked list and each element point
  9. ; to an offset in the "scratchpad". The scratchpad starts with the file
  10. ; contents and every time we change or add a line, that line goes to the end of
  11. ; the scratch pad and linked lists are reorganized whenever lines are changed.
  12. ; Contents itself is always appended to the scratchpad.
  13. ;
  14. ; That's on a resourceful UNIX system.
  15. ;
  16. ; That doubly linked list on the z80 would use 7 bytes per line (prev, next,
  17. ; offset, len), which is a bit much.
  18. ;
  19. ; We sacrifice speed for memory usage by making that linked list into a simple
  20. ; array of pointers to line contents in scratchpad. This means that we
  21. ; don't have an easy access to line length and we have to move a lot of memory
  22. ; around whenever we add or delete lines. Hopefully, "LDIR" will be our friend
  23. ; here...
  24. ;
  25. ; *** Variables ***
  26. ;
  27. .equ ED_CURLINE ED_RAMSTART
  28. .equ ED_RAMEND @+2
  29. edMain:
  30. ; because ed only takes a single string arg, we can use HL directly
  31. call ioInit
  32. ret nz
  33. ; diverge from UNIX: start at first line
  34. ld hl, 0
  35. ld (ED_CURLINE), hl
  36. call bufInit
  37. .mainLoop:
  38. ld a, ':'
  39. call stdioPutC
  40. call stdioReadLine ; --> HL
  41. ; Now, process line.
  42. call printcrlf
  43. call cmdParse
  44. jp nz, .error
  45. ld a, (CMD_TYPE)
  46. cp 'q'
  47. jr z, .doQ
  48. cp 'w'
  49. jr z, .doW
  50. ; The rest of the commands need an address
  51. call edReadAddrs
  52. jr nz, .error
  53. ld a, (CMD_TYPE)
  54. cp 'i'
  55. jr z, .doI
  56. ; The rest of the commands don't allow addr == cnt
  57. push hl ; --> lvl 1
  58. ld hl, (BUF_LINECNT)
  59. call cpHLDE
  60. pop hl ; <-- lvl 1
  61. jr z, .error
  62. ld a, (CMD_TYPE)
  63. cp 'd'
  64. jr z, .doD
  65. cp 'a'
  66. jr z, .doA
  67. jr .doP
  68. .doQ:
  69. xor a
  70. ret
  71. .doW:
  72. ld a, 3 ; seek beginning
  73. call ioSeek
  74. ld de, 0 ; cur line
  75. .wLoop:
  76. push de \ pop hl
  77. call bufGetLine ; --> buffer in (HL)
  78. jr nz, .wEnd
  79. call ioPutLine
  80. jr nz, .error
  81. inc de
  82. jr .wLoop
  83. .wEnd:
  84. ; Set new file size
  85. call ioTell
  86. call ioSetSize
  87. ; for now, writing implies quitting
  88. ; TODO: reload buffer
  89. xor a
  90. ret
  91. .doD:
  92. ld (ED_CURLINE), de
  93. ; bufDelLines expects an exclusive upper bound, which is why we inc DE.
  94. inc de
  95. call bufDelLines
  96. jr .mainLoop
  97. .doA:
  98. inc de
  99. .doI:
  100. call stdioReadLine ; --> HL
  101. call bufScratchpadAdd ; --> HL
  102. ; insert index in DE, line offset in HL. We want the opposite.
  103. ex de, hl
  104. ld (ED_CURLINE), hl
  105. call bufInsertLine
  106. call printcrlf
  107. jr .mainLoop
  108. .doP:
  109. push hl
  110. call bufGetLine
  111. jr nz, .error
  112. call printstr
  113. call printcrlf
  114. pop hl
  115. call cpHLDE
  116. jr z, .doPEnd
  117. inc hl
  118. jr .doP
  119. .doPEnd:
  120. ld (ED_CURLINE), hl
  121. jp .mainLoop
  122. .error:
  123. ld a, '?'
  124. call stdioPutC
  125. call printcrlf
  126. jp .mainLoop
  127. ; Transform an address "cmd" in IX into an absolute address in HL.
  128. edResolveAddr:
  129. ld a, (ix)
  130. cp RELATIVE
  131. jr z, .relative
  132. cp EOF
  133. jr z, .eof
  134. ; absolute
  135. ld l, (ix+1)
  136. ld h, (ix+2)
  137. ret
  138. .relative:
  139. ld hl, (ED_CURLINE)
  140. push de
  141. ld e, (ix+1)
  142. ld d, (ix+2)
  143. add hl, de
  144. pop de
  145. ret
  146. .eof:
  147. ld hl, (BUF_LINECNT)
  148. dec hl
  149. ret
  150. ; Read absolute addr1 in HL and addr2 in DE. Also, check bounds and set Z if
  151. ; both addresses are within bounds, unset if not.
  152. edReadAddrs:
  153. ld ix, CMD_ADDR2
  154. call edResolveAddr
  155. ld de, (BUF_LINECNT)
  156. ex de, hl ; HL: cnt DE: addr2
  157. call cpHLDE
  158. jp c, unsetZ ; HL (cnt) < DE (addr2). no good
  159. ld ix, CMD_ADDR1
  160. call edResolveAddr
  161. ex de, hl ; HL: addr2, DE: addr1
  162. call cpHLDE
  163. jp c, unsetZ ; HL (addr2) < DE (addr1). no good
  164. ex de, hl ; HL: addr1, DE: addr2
  165. cp a ; ensure Z
  166. ret