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.

212 lines
5.6KB

  1. ; buf - manage line buffer
  2. ;
  3. ; *** Variables ***
  4. ; Number of lines currently in the buffer
  5. .equ BUF_LINECNT BUF_RAMSTART
  6. ; List of pointers to strings in scratchpad
  7. .equ BUF_LINES @+2
  8. ; Points to the end of the scratchpad, that is, one byte after the last written
  9. ; char in it.
  10. .equ BUF_PADEND @+ED_BUF_MAXLINES*2
  11. ; The in-memory scratchpad
  12. .equ BUF_PAD @+2
  13. .equ BUF_RAMEND @+ED_BUF_PADMAXLEN
  14. ; *** Code ***
  15. ; On initialization, we read the whole contents of target blkdev and add lines
  16. ; as we go.
  17. bufInit:
  18. ld hl, BUF_PAD ; running pointer to end of pad
  19. ld de, BUF_PAD ; points to beginning of current line
  20. ld ix, BUF_LINES ; points to current line index
  21. ld bc, 0 ; line count
  22. ; init pad end in case we have an empty file.
  23. ld (BUF_PADEND), hl
  24. .loop:
  25. call ioGetB
  26. jr nz, .loopend
  27. or a ; null? hum, weird. same as LF
  28. jr z, .lineend
  29. cp 0x0a
  30. jr z, .lineend
  31. ld (hl), a
  32. inc hl
  33. jr .loop
  34. .lineend:
  35. ; We've just finished reading a line, writing each char in the pad.
  36. ; Null terminate it.
  37. xor a
  38. ld (hl), a
  39. inc hl
  40. ; Now, let's register its pointer in BUF_LINES
  41. ld (ix), e
  42. inc ix
  43. ld (ix), d
  44. inc ix
  45. inc bc
  46. ld (BUF_PADEND), hl
  47. ld de, (BUF_PADEND)
  48. jr .loop
  49. .loopend:
  50. ld (BUF_LINECNT), bc
  51. ret
  52. ; transform line index HL into its corresponding memory address in BUF_LINES
  53. ; array.
  54. bufLineAddr:
  55. push de
  56. ex de, hl
  57. ld hl, BUF_LINES
  58. add hl, de
  59. add hl, de ; twice, because two bytes per line
  60. pop de
  61. ret
  62. ; Read line number specified in HL and make HL point to its contents.
  63. ; Sets Z on success, unset if out of bounds.
  64. bufGetLine:
  65. push de ; --> lvl 1
  66. ld de, (BUF_LINECNT)
  67. call cpHLDE
  68. pop de ; <-- lvl 1
  69. jp nc, unsetZ ; HL > (BUF_LINECNT)
  70. call bufLineAddr
  71. ; HL now points to an item in BUF_LINES.
  72. call intoHL
  73. ; Now, HL points to our contents
  74. cp a ; ensure Z
  75. ret
  76. ; Given line indexes in HL and DE where HL < DE < CNT, move all lines between
  77. ; DE and CNT by an offset of DE-HL. Also, adjust BUF_LINECNT by DE-HL.
  78. ; WARNING: no bounds check. The only consumer of this routine already does
  79. ; bounds check.
  80. bufDelLines:
  81. ; Let's start with setting up BC, which is (CNT-DE) * 2
  82. push hl ; --> lvl 1
  83. ld hl, (BUF_LINECNT)
  84. scf \ ccf
  85. sbc hl, de
  86. ; mult by 2 and we're done
  87. sla l \ rl h
  88. push hl \ pop bc
  89. pop hl ; <-- lvl 1
  90. ; Good! BC done. Now, let's adjust BUF_LINECNT by DE-HL
  91. push hl ; --> lvl 1
  92. scf \ ccf
  93. sbc hl, de ; HL -> nb of lines to delete, negative
  94. push de ; --> lvl 2
  95. ld de, (BUF_LINECNT)
  96. add hl, de ; adding DE to negative HL
  97. ld (BUF_LINECNT), hl
  98. pop de ; <-- lvl 2
  99. pop hl ; <-- lvl 1
  100. ; Line count updated!
  101. ; One other thing... is BC zero? Because if it is, then we shouldn't
  102. ; call ldir (otherwise we're on for a veeeery long loop), BC=0 means
  103. ; that only last lines were deleted. nothing to do.
  104. ld a, b
  105. or c
  106. ret z ; BC==0, return
  107. ; let's have invert HL and DE to match LDIR's signature
  108. ex de, hl
  109. ; At this point we have higher index in HL, lower index in DE and number
  110. ; of bytes to delete in BC. It's convenient because it's rather close
  111. ; to LDIR's signature! The only thing we need to do now is to translate
  112. ; those HL and DE indexes in memory addresses, that is, multiply by 2
  113. ; and add BUF_LINES
  114. push hl ; --> lvl 1
  115. ex de, hl
  116. call bufLineAddr
  117. ex de, hl
  118. pop hl ; <-- lvl 1
  119. call bufLineAddr
  120. ; Both HL and DE are translated. Go!
  121. ldir
  122. ret
  123. ; Insert string where DE points to memory scratchpad, then insert that line
  124. ; at index HL, offsetting all lines by 2 bytes.
  125. bufInsertLine:
  126. call bufIndexInBounds
  127. jr nz, .append
  128. push de ; --> lvl 1, scratchpad ptr
  129. push hl ; --> lvl 2, insert index
  130. ; The logic below is mostly copy-pasted from bufDelLines, but with a
  131. ; LDDR logic (to avoid overwriting). I learned, with some pain involved,
  132. ; that generalizing this code wasn't working very well. I don't repeat
  133. ; the comments, refer to bufDelLines
  134. ex de, hl ; line index now in DE
  135. ld hl, (BUF_LINECNT)
  136. scf \ ccf
  137. sbc hl, de
  138. ; mult by 2 and we're done
  139. sla l \ rl h
  140. push hl \ pop bc
  141. ; From this point, we don't need our line index in DE any more because
  142. ; LDDR will start from BUF_LINECNT-1 with count BC. We'll only need it
  143. ; when it's time to insert the line in the space we make.
  144. ld hl, (BUF_LINECNT)
  145. call bufLineAddr
  146. ; HL is pointing to *first byte* after last line. Our source needs to
  147. ; be the second byte of the last line and our dest is the second byte
  148. ; after the last line.
  149. push hl \ pop de
  150. dec hl ; second byte of last line
  151. inc de ; second byte beyond last line
  152. ; HL = BUF_LINECNT-1, DE = BUF_LINECNT, BC is set. We're good!
  153. lddr
  154. .set:
  155. ; We still need to increase BUF_LINECNT
  156. ld hl, (BUF_LINECNT)
  157. inc hl
  158. ld (BUF_LINECNT), hl
  159. ; A space has been opened at line index HL. Let's fill it with our
  160. ; inserted line.
  161. pop hl ; <-- lvl 2, insert index
  162. call bufLineAddr
  163. pop de ; <-- lvl 1, scratchpad offset
  164. ld (hl), e
  165. inc hl
  166. ld (hl), d
  167. ret
  168. .append:
  169. ; nothing to move, just put the line there. Let's piggy-back on the end
  170. ; of the regular routine by carefully pushing the right register in the
  171. ; right place.
  172. ; But before that, make sure that HL isn't too high. The only place we
  173. ; can append to is at (BUF_LINECNT)
  174. ld hl, (BUF_LINECNT)
  175. push de ; --> lvl 1
  176. push hl ; --> lvl 2
  177. jr .set
  178. ; copy string that HL points to to scratchpad and return its pointer in
  179. ; scratchpad, in HL.
  180. bufScratchpadAdd:
  181. push de
  182. ld de, (BUF_PADEND)
  183. push de ; --> lvl 1
  184. call strcpyM
  185. inc de ; pad end is last char + 1
  186. ld (BUF_PADEND), de
  187. pop hl ; <-- lvl 1
  188. pop de
  189. ret
  190. ; Sets Z according to whether the line index in HL is within bounds.
  191. bufIndexInBounds:
  192. push de
  193. ld de, (BUF_LINECNT)
  194. call cpHLDE
  195. pop de
  196. jr c, .withinBounds
  197. ; out of bounds
  198. jp unsetZ
  199. .withinBounds:
  200. cp a ; ensure Z
  201. ret