Laemeur, on Sat Nov 21, 2009 4:16 PM, said:
Yeah, that's absolutely on my to-do list for the actual editor, although I'm still trying to puzzle out how to actually implement it.
Pretty easy, and quite elegant. Set up two pointers in page zero: I call them POS and LINK. POS is simply the "address" of the cursor position. LINK is the address of the text stored at the top of the buffer, beyond the empty space ahead of the cursor. When a file is first loaded, it's moved to the top of the buffer. POS points to the bottom of the buffer, while LINK points to the first character after the empty space. To cursor forward through the document, you say:
ldy #0
lda (link),y
sta (pos),y
inc link
bne *+4
inc link+1
inc pos
bne *+4
inc pos+1
Obviously you need bounds checking, etc. To insert a character at the cursor position, you say:
lda char
ldy #0
sta (link),y
sec
lda link
sbc #1
sta link
bcs *+4
dec link+1
The buffer is full when POS=LINK-1. The screen refresh obviously has to skip over the empty space, so I use the EOL character as a marker at POS as well as an end-of-text marker at the very top of the buffer. This saves having to check where we're at all the time, since there can only be at most twenty-odd EOLs on the screen at once. When the refresh routine finds a return character, it checks to see if it's the one at POS. If it is, it grabs the value in LINK and continues drawing the screen from there. If it's the end-of-text marker, it knows it's done. If it's neither of these, it must a normal EOL character, so a return is printed.
A problem arises when you cross the blank memory and then word-wrap back to a point before the gap. There are a few different ways around this, but it requires careful management.
Laemeur, on Sat Nov 21, 2009 4:16 PM, said:
It's nothing sophisticated at all. Right now the line-drawing routine starts at the current line and draws to the bottom of the screen, but it checks a flag when it's first called to see if it should start from the top line because the screen's been 'broken'. There are a few circumstances where that flag is set, and early-on my highly convoluted program-flow had it getting cleared before it should have. My incredibly crufty solution at the time was to have it get incremented/decremented rather than set/cleared so that requests for redraw could queue up. I'm back to setting/clearing now that I've got things happening in more or less proper order.
For a while I was trying to work out clever ways of 'marking' areas of the screen that needed updating, to save character-drawing cycles, but I eventually got the character drawing fast enough so that drawing a whole screen wasn't such an abhorrent time-suck anymore. Still, I would like to work on clever ways of avoiding redraws when not necessary, but I don't have any really useful information to that effect right now.
The character draw routine must be really fast. In The Last Word, I keep a map of all the characters on the screen and any that haven't changed don't get redrawn on the next refresh. On top of that, I keep a table of the start address in memory of each line on the screen, and for each address which hasn't altered on the next redraw, even comparisons with the screen map are skipped for that line. Only the current and "previous" lines are redrawn at all times.
What I'm trying to figure out now is how to make this work with proportional fonts. You could still keep a buffer of which characters are on a line, but obviously if a line full of "i" characters gets a "W" written at the start, the whole line will have to be redrawn because everything will shift along by a couple of pixels. I guess the starting address of lines technique will still work. I also wondered, if the option to have a wide scrolling horizontal screen is offered, how large the character buffers might get. On a 640 pixel wide page, you could have a good 320 instances of the letter
i on a line. This means double byte pointers and large buffers. Then there's the possibility that characters on the screen are italic or bold.
Anyway, your system already seems very fast and efficient. Well done!
Edited by flashjazzcat, Sun Nov 22, 2009 8:13 AM.