News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

how to get the Byte at a certain caret position ?

Started by Rainstorm, May 15, 2008, 04:08:14 PM

Previous topic - Next topic

Rainstorm

Suppose i have text being typed in a window..., how would i find the byte at a specific caret position
after i've been moving the caret around using the keyboard. - the text is being stored in a buffer.

this is what i've loosely thought about..
- Add 1 to the current y-co ordinate of the caret position
- Divide the sum by the character height of the font (this gives the line number)
- count the number of LFs from the beginning of the buffer
- divide the x-coordinate by the width
- use that number to arrive at the needed point in the buffer

don't know how correct that is.. & i may have probs with variable pitch fonts etc with it.

What would be the correct (& fastest ) way.. to return the byte at the position of the caret at anytime

would much appreciate any help & feedback

Thanks.

Rainstorm
-

MichaelW

Is the window that contains the text an edit control?
eschew obfuscation

Rainstorm

hi Michael,

no its just a normal window.. with a client area.

I've coded some basic character processing & caret movements.. that works.. but for a lot of the operation i realised I'd need to able to to get the character (in the buffer) at a given Caret Position.

thanks!

BogdanOntanu

If it is your own code then why are you not keeping the current carret buffer position in a variable?
Update this variable on each event (carret move or set) and you will always know where from to read a character.

However take care because making and edit control is NOT that simple unless the text buffer is small....say < 640k :P

You will have problems with variable pitch and size fonts on the display logic of your edit but not when getting the char, the ASCII chars are the same even if the chars are bigger or wider :P
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

Rainstorm

bogdan wrote
QuoteIf it is your own code then why are you not keeping the current carret buffer position in a variable?
I don't know exactly what you mean.- i don't know how to do that, I use GetCaretPos to get the Caret position & then store them in variables. - the code is my own. - for some cursor movements likeleft or right i could get the byte that it references in the buffer, but for some other movements like moving up or down from somewhere in the middle of the line.... i couldn't think of anything else than what i described above.

QuoteYou will have problems with variable pitch and size fonts on the display logic of your edit but not when getting the char, the ASCII chars are the same even if the chars are bigger or wider
yes the ascii char is the same, ..but for variable pitch fonts..maybe the position would get calculated wrong..& I would get the wrong character. - is what i was thinking ( in reference to what i described in my first post) like if i divided the caret coordinate by the caret width. or something like that.

thx.

Tedd

Your first idea is correct... for monospace fonts only :wink
Variable width fonts 'can' be done in a similar way, if you use the width of 'x' as the average character width (related: http://www.masm32.com/board/index.php?topic=7971.0) - this works roughly correct for 'normal' text, but will obviously fail for strings like "lllllllllllllllllllll" or "mmmmmmmmmmmmmmm"
The correct way to do it is to use 'GetCharWidth' and create a table containing the widths of all printable characters, then for your given line you can add up the widths of the characters until you get a width greater than the caret position, the character position is then the last one you counted.

Two speed-ups come to mind:
1 - keep a table containing the number of characters in each line, then you can quickly find where a line starts, rather than counting through to find line feeds every time. Since it's the number of chars in each line, not the offset of each line, you only need to update the count for a line that changes (not every line after.)
2 - for a quick guess to the number of chars in a width (when finding the caret position) you could divide by the average char width, and then add or subtract the real char widths until you get to the correct position; though it may not really be worth the extra complexity, except for long lines.
No snowflake in an avalanche feels responsible.

Rainstorm

#6
By table you mean, a buffer in memory containing the total characters in each line, right ?
just to confirm, so for example if i wanted the total chars in line 5 , I'd do..

mov linesize, word ptr [esi+4*2]     ; where esi is the start address of the buffer

the part about the crlfs seemed a bit too much .. especially for large files.
I was mainly coding for a fixed width font,.. but then i thought I might as well try & make some allowance for variable width fonts now that am at it.. rather than coming back to it later

tedd , appreciate all the tips..

That was very helpful, thanks.

[Edit] tedd wrote..
Quote2 - for a quick guess to the number of chars in a width (when finding the caret position) you could divide by the average char width, and then add or subtract the real char widths until you get to the correct position; though it may not really be worth the extra complexity, except for long lines.
for the caret movement Keys involving one char moves I could just use the 'avg char width' right ? (that's what am using now)

Tedd

Eat cake! :toothy


[attachment deleted by admin]
No snowflake in an avalanche feels responsible.

Rainstorm


Rainstorm

working on the code when i can...will post soon.

Rainstorm

hi

how do i find the linenumber the caret is at ? -  there is a hitch i think in the method i described in the 1st post, since somewhere after one pagedown (for example) the caret could have the same Y-coordinate but the line would actually be a different line in the text buffer. - in code something like this
          xor edx, edx
          mov eax, ypos                       
          add eax, char_height                  ; inc the ypos by 1 (since the ypos starts at 0)
          div char_height                       ; line number in eax (Ypos+1 รท charheight)

Tedd

So you need to find out which line is currently visible at the top of the window, and then adjust relative to that line :wink
No snowflake in an avalanche feels responsible.

Rainstorm

#12
tedd wrote..
QuoteSo you need to find out which line is currently visible at the top of the window, and then adjust relative to that line
got it. : ) - But About finding out which line is currently visible at the top of the window,.. I'd have to track the caret through all the caret movement commands,.. or maybe just track which line is on top...Or  is there another way ? - could you confirm this for me.

Tedd, i had a related question about the method i should use for redrawing the text in the window & started a new thread for it here..
http://www.masm32.com/board/index.php?topic=9394.msg68253#msg68253


Thankies!
-


Tedd

Quote from: Rainstorm on June 18, 2008, 03:32:44 PM
I'd have to track the caret through all the caret movement commands,.. or maybe just track which line is on top...Or  is there another way ? - could you confirm this for me.
If you're making your own text editing control, you should be tracking the caret position anyway?? You should already know its location. And to handle scrolling (by scrollbar, arrow keys, and pg-up/down) you should be keeping track of which line is currently visible at the top of the window, so you can redraw the text from the correct line.
No snowflake in an avalanche feels responsible.

Rainstorm

tedd, I made a mistake with the wording of that sentence.
I meant i'd have to track the position of the Top Line (not the caret) through all the caret movement actions. thanks for clearing that up. here's what i did
          mov eax, caret.y               ; current y coordinate of the caret
          xor edx, edx
          div char_height                ; offset from top line in window
          add eax, wintopmost_line       ; actual linenumber (starts from 0)