Hints on how to select a whole word in a TextArea?

Hello,

In a TextArea, I want to select the whole tag when the user clicks in the middle of the tag. It could be HTML tags:
“For example, is a tag and . And so on…”
If the user clicks inside the word “this”, I want “” (or “” given which “this” was clicked) to be selected. I would it to be as much as “integrated” as possible (e.g. if the shift key is used, the selection should extend from the initial selection to include the whole tag).

The goal is that the user must not be able to alter defined tags (e.g. if I allow only , , , , , and , the user can’t mess with them and, for example, start editing to become which would have no sense for my application). I’ll handle pasting and text dropping later; that will be easier once I figure out how to include whole tags in selection.

Being a lot of work in all cases, I’m not sure how to start.
I’m seeing 3 possible ways to start:
•rely only on the SelChange/TextChange events (or only one of these). I allow the user to do whatever (s)he wants (keystrokes, cut, paste, text drops) and clean the field after the fact. This lacks a lot of control and may result in destruction of data, should the allowed modification delete unexpected parts of the text.
•prevent modifications using “pre-processing” events (filtering KeyDown, handling selection in MouseDown, overwriting the Paste event handler, checking the dropped text in DropObject). This way, unwanted actions can’t be done in the first place. This may be a lot more work, but (1) is cleaner and (2) allows more control.
•use both methods. Try to prevent most possible things before modifications and use the SelChange/TextChange events to clean possible remaining errors. This looks the worst solution to me.

For each case, it’s so complex I’m not sure either way will fit my needs and be reliable in the long run.
I can prevent the command key to being used (in Mac, this allows separated characters/words to be selected, which would be disastrous and can’t be handled in Xojo). Keeping double clicks to be allowed to select whole words might also be difficult along with my own code…

I’ve already tried something in the MouseDown event. I ended up with a mess: sometimes the returned char is offset by one, sometimes not, so I have “random” -1 or +1 in my code, which ends up being not reliable for other cases. I’ll have to start again.

Well, any idea greatly welcome!

Are you trying to select real tags, or your own tags ? Your post refers to what seems to be sentences between brackets…

At any rate, the way I would to it would be :

  1. Starting from SelStart, explore the text character by character backward, until I find “<”. If I find “>” or if I am back to zero, or a given limit, I return from the method unsuccessful.

  2. The other way, I use Instr(), or IndexOf() in 2019R2, to find “>”.

  3. Then I set SelStart to the first “<” and Sellength is the total of the characters backward, plus the result of instr()/IndexOf().

BTW, I would not do it in MouseDown, but rather, in MouseUp.

@Arnaud Nicolet — Honestly, I think you are asking too much to Xojo

Not at all… the method the Michel described will work quite well.
And I bet if Kem sees this. he could even come up with a RegEx way that would be faster

while this blog doesn’t answer your question directly… it has TONS of useful information… including selecting active words as the mouse moves.

https://blog.xojo.com/2018/07/31/tutorial-active-words/

No need to defeat Arnaud because you don’t know how to do it.

In TextChange, scan for and index all opening brackets and their corresponding closing brackets. In SelChange, use those indexes to update the selection appropriately.

More accurately, my application lists user of a group (name, postal address, email address, phone number, …). I’d like to provide a light version of “mailing”, like in word (in french, it’s “Publipostage”; I’m not sure how it’s said in english, translation telling me just “mail”).
So, the user can write styled text in the text area, such as:
Dear ,
Hello, how are you? And such…

Then my app would print that, replacing by the real name of selected users, one page per user.
I chose my own separators (“?” and “?”) so the writer won’t type this himself/herself.

[quote=463352:@Michel Bujardet]At any rate, the way I would to it would be:

  1. Starting from SelStart, explore the text character by character backward, until I find “<”. If I find “>” or if I am back to zero, or a given limit, I return from the method unsuccessful.

  2. The other way, I use Instr(), or IndexOf() in 2019R2, to find “>”.

  3. Then I set SelStart to the first “<” and Sellength is the total of the characters backward, plus the result of instr()/IndexOf().

BTW, I would not do it in MouseDown, but rather, in MouseUp.[/quote]
Thank you for your answer.

Actually, I already have the logic of finding the previous and next separator from a given char position; given the fact that my tags can’t be longer than 11 characters, I also give up if I have parsed more than 12 chars (it avoids looking possibly for a lot of characters if there’s no tag “near” the selection).

In your example, I see either one, or another problem:
•If you use MouseUp, you can’t discard the actual click, and the OS will then overwrite the selection you made from code. The MouseDown event is the only one which can prevent the real click.
•But, if using MouseDown, you can’t “start from SelStart” as it’s not yet set; you have to rely upon CharPosAtXY and such, which aren’t accurate enough: for whatever obscure reason, if you click on some characters, “near its middle”, CharPosAtXY can return the “next” character, while letting the OS do the selection (with no code in Xojo) selects the “previous” character; this difference does not apply for all the characters and I can’t predict the pattern. Also, the “middle” of a given character isn’t always the “visible middle”, so the user wouldn’t make correct distinctions.
Another difference between CharPosAtXY and the mac OS is that beyond a given “physical” line (e.g. after a carriage return), CharPosAtXY returns the character of the next beginning line (the OS, on the other hand, puts the insert point at the end of the clicked line). Those 2 differences, albeit possibly not being the only ones, mean I must avoid mixing the “OS” selection handling and the Xojo approach, basically needing rewriting my own selection method (re-inventing the wheel from the ground). Perhaps it just means the CharPosAtXY method is “broken”, but waiting for a fix from Xojo isn’t going to help in the “meantime” (however long that is).

I could perhaps go with the first method (use MouseUp), store the computed selection in a variable and then use a timer to undo the OS “manual” selection from the click… Visually, it’d be a disaster.

Further ideas still welcome.

I remember 10 years ago So many things were just not feasible in RB/RS/Xojo. They were eventually added in the curse of upgrading
I think, with all these additions along the years, most of now unavailable things are logically the hardest to implement

Still, Word can do that, as can Mac OS, Windows and Linux (using the double click on a word). Not sure what too much to Xojo levels to.

Oh yes, that looks like a smart way! I’ll study what eventual drawbacks I encounter, but it’s definitively a nice approach.

The first drawback I imagine is slow indexing of the tags in the TextChange event, if the text exceeds number of characters. But, I may use the KeyDown/Paste/Cut (and other modifying) events to only re-index if the change includes/excludes new separators.

Still, dealing with unpaired opening/closing separators will have to be done (I can’t just rely on the TextChange event to actually find that one closing separator is missing and… do nothing; it has to be prevented).

I’m excited to try that, thank you!

[quote=463356:@Dave S]while this blog doesn’t answer your question directly… it has TONS of useful information… including selecting active words as the mouse moves.

https://blog.xojo.com/2018/07/31/tutorial-active-words/[/quote]
Great article, indeed. I’ve thrown a quick sight on it; it appears not too much complex (but for actual editing needs, it may become more intricate).
But the fact that CharPosAtXY may return different values than the OS “thinks” isn’t addressed in this article.

Whatever your solution, make sure it takes into account a paste or dropped text. Ali consider doing the processing in a timer some milliseconds after the last change.

Thanks. It’s rare I’m motivated to find solutions (only happen in programming, in fact), so thinking “you can’t do that” has side effects I know too well…

Stéphane, I’m sure you wanted to be helpful in saying “Xojo may not be able to do that”, sort of telling me “Abort before you throw too much resources for nothing” and I appreciate that fact.

I see both sides…

Yes, as I’ve mentioned, I’ll take care of that.
I’ll try to avoid the timer approach. I’ve already found a post (started by you, IIRC), where you found a way to handle the “Paste” item in a contextual menu (“hard” in Xojo’s Cocoa implementation); the paste handler for the menu bar will be “easy” as will be dropped text.
The fact that one can do so many things (e.g. using Services or Speech recognition, etc.) leads me to think I’ll probably miss one way or another, but most users won’t even try.
Thank you.

Could an administrator please remove my original post I’ve quoted above? I hate it when I express myself too much and I can’t find a way to remove it myself… Sorry.