TextArea - XY at Insertion Point

Textarea has InsertionPointAtXY which returns the integer value of where the insertion point is closest to the supplied X,Y values

How to do the opposite???

Given an character postion (ie. Selstart for the most part)… get the X,Y pixel location of that character position…

+/- a few pixels is fine

I remember a thread about that very topic, a while ago. I don’t remember the specifics, but it could very well have been answered through some declares.

You could also scan the text and get coordinates for each character, and pick the closest one.

You had written something a while back

https://forum.xojo.com/29922-highlight-text-in-a-textarea/0

I was hoping for something a bit faster… .but I will use a varaition of this for now :slight_smile:

You could speed up the method by doing a binary search separately on the coordinates: first the y coordinate, then the x coordinate.

Yeah I thought that too… .but InserttionPointAtXY returns “Nearest”… so anything past the actual point doesn’t work out

so I start with Y=0 and step down in increments of Textheight… then across by 1 pixel

Dim p As New picture(10,10)
Dim g As graphics=p.Graphics
Dim th As Integer
g.TextFont=Me.TextFont
g.TextSize=Me.TextSize
th=g.TextHeight // ASSUMPTION : TextArea is only ONE Font/Size!
For y As Integer = 0 To Me.Height+th Step th
If Me.charPosAtXY (0, Y) = Me.selstart Then 
y=y-1
For x As Integer=0 To Me.width
If Me.charPosAtXY (x, Y) = Me.selstart Then 
xp=x
yp=y
Exit For y
End If
Next x
End If
Next y

This is what I meant:

Public Sub XYatCharPos(ta as textarea, cp As Integer, byRef x As Integer, byref y As Integer)
  'Return the x and y coordinates of the character at character position cp
  'in text field ta.
  
  dim targetLine As Integer = ta.LineNumAtCharPos(cp+1)
  dim targetY As Integer = ta.CharPosAtLineNum(targetLine)
  dim targetX As Integer = cp-targetY
  dim xMax As Integer = ta.Width
  dim yMax As Integer = ta.Height
  dim yTest As Integer
  dim Lbound As Integer = 0
  dim Hbound As Integer = yMax
  while Hbound>Lbound
    yTest = (Lbound+Hbound)\\2
    if ta.CharPosAtXY(0,yTest)<targetY then
      Lbound=yTest+1
    Else
      Hbound=yTest
    end if
  wend
  yTest=yTest+1
  y=yTest
  Lbound = 0
  Hbound = xMax
  dim xTest As Integer
  while Hbound>Lbound
    xTest = (Lbound+Hbound)\\2
    if ta.CharPosAtXY(xTest,yTest)<cp then
      Lbound=xTest+1
    Else
      Hbound=xTest
    end if
  wend
  x=xTest
End Sub

After some brief testing, it appears to work, but I didn’t take text field scrolling into account.