News:

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

Rich edit messaging quirk

Started by hutch--, June 19, 2008, 01:25:50 PM

Previous topic - Next topic

hutch--


I have been having a ton of fun with this code, if the enter key is pressed when the caret is in the last character position in the edit control the line number is one less than the two structure members when nothing is selected, if I place the text caret back in the middile of the text, the line number is the same as the structure members.

It looks like I have to do something tacky like check the text length each keypress to test if the caret is at the last position or not and twiddle the line numer accordingly.

None of these problems existed in richedit 1 but coding a richedit 2 and later seems to have all sorts of funny effects. I originally tried to process the WM_CHAR character on an enter press but with richedit 2, even if you return zero, it still inserts the ascii 13. I then tried on a WM_KEYDOWN and it almost worked but the second keypress does not behave the same as the first one or any later ones so I had to give that one up.


    invoke SendMessage,Edit,EM_EXGETSEL,0,ADDR cr                   ; get char position
    mov lind, rv(SendMessage,Edit,EM_LINEINDEX,-1,0)                ; get 1st character index on current line
    mov lnum, rv(SendMessage,Edit,EM_EXLINEFROMCHAR,0,lind)         ; get line number from char position

    mbDebug "CHARRANGE struct","cr.cpMin = ",cr.cpMin,"cr.cpMax = ",cr.cpMax,"lnum ",lnum


Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

I use this code in RichMasm. What exactly is your problem?

sm hRE, EM_EXGETSEL, 0, addr chrG ; get line of current sel
sm hRE, EM_EXLINEFROMCHAR, 0, chrG.cpMin
inc eax ; Line n


Tedd

I've seen this problem too.
You can fix it by changing the 'textmode' -- invoke SendMessage, hRichWnd,EM_SETTEXTMODE,TM_RICHTEXT or TM_MULTILEVELUNDO or TM_SINGLECODEPAGE,NULL
(I don't remember if it's specifically richtext or multilevelundo that fixes it.)
No snowflake in an avalanche feels responsible.

jj2007

An application sends an EM_SETTEXTMODE message to set the text mode or undo level of a rich edit control. The message fails if the control contains any text.

Meaning you must do it before loading any text. Anyway, I would be surprised if that worked. What I noticed is that under Win XP SP1, you cannot undo anything after the file was saved. Under SP2, undo is possible after saving.

hutch--

Tedd,

I changed it from TM_MULTICODEPAGE to M_SINGLECODEPAGE but it does the same. If the caret is at the last position in the editor the line number is reported 1 lower than if the caret is further back in the text body. I am recoding an autoindent where I need to accurately identify the current line when the enter is pressed and the following line.

The most consistent calling location is by trapping the WM_KEYDOWN VK_RETURN directly from the message loop as it avoids the lag it had called from the rich edit subclass.

Its this line that is causing the problem.


mov lnum, rv(SendMessage,Edit,EM_EXLINEFROMCHAR,0,crng.cpMin)


With my current testing the EM_EXLINEFROMCHAR message looks like its broken when the caret is at the end of the text in the edit control.

LATER: If I comment out the following lines,


;         invoke SendMessage,hEdit,EM_SETTEXTMODE,TM_PLAINTEXT or \
;                                                 TM_MULTILEVELUNDO or \
;                                                 TM_MULTICODEPAGE, 0


it works correctly, the culprit is the EM_SETTEXTMODE message.

LATER AGAIN: If I remove the TM_PLAINTEXT style and use this form,


        invoke SendMessage,hEdit,EM_SETTEXTMODE,TM_MULTILEVELUNDO or TM_MULTICODEPAGE,0


I still get a reduced form of TM_MULTILEVELUNDO but its not as useful as the type of undo using the TM_PLAINTEXT style.

The more complext form is if you type 12345678 with the full option, you can do multilevel UNDO one character at a time, with the style removed it only does one action at a time on what seems to be a line basis only.

It seems to be a toss up between autoindent and multi level redo/undo.  :boohoo:
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

What if you just subtract 1 from .cpMin?
Are cpMin and cpMax identical in that moment?
If not, what happens if you use .cpMax instead?

Trying to guess what's wrong...

hutch--

jj,

I tried that early on but there does not appear to be a reliable way to detect if the caret is at the end of the text or not. To complicate things GetWindowTextLength does not report accurate results from the rich edit 2+ edit control.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

Try comparing line counts for cpMin and cpMin+1?

jj2007

Hutch, since I use RichEd 2, too, why don't you have a look at the behaviour of RichMasm? The line and column counter is in the upper right corner; when text is selected, it's expressed as Line 123, Col 27+3. Watch what happens when you put the caret at the end of the line, then hold Shift and press right arrow once. Other exercise: Go into Col 1 of next line, hold Shift and press left arrow once. As far as I can see, it shows correct line numbers and columns, but the behaviour at end of line is indeed interesting. It might be "by design" - after all, it's a Microsoft product... :wink

Tedd

As I remember it, the problem is that the ln,col numbers are correct on all lines except for the last - and only then if the last line is actually empty (if it contains one or more characters then it's correct.) On that last line, what you get is: ln = number of lines - 1 (i.e. the number of the previous line); col = length of previous line + 1. I'm guessing there's something going on with trying to compensate for the last line ending with a newline character.
If you really want to go to the trouble of getting around it, I think you might be able to get the total number of lines (which I seem to remember was correct, amusingly), and if you're on the last line (which will numerically be the second to last line due to the mess up) check whether you're past its end (get that line's length, compare against it.)

On a related note, you should really be updating the ln,col display through the EN_SELCHANGE notification (you need to 'register' for it with EM_SETEVENTMASK), rather than trying to hook keypresses - which gives a noticable lag.
No snowflake in an avalanche feels responsible.

jj2007

#10
Quote from: Tedd on June 19, 2008, 07:09:37 PM
As I remember it, the problem is that the ln,col numbers are correct on all lines except for the last - and only then if the last line is actually empty (if it contains one or more characters then it's correct.)
RichMasm does not show this behaviour, it works correct - without any tricks. Therefore I do not quite understand what his problem is...

Quote
On a related note, you should really be updating the ln,col display through the EN_SELCHANGE notification (you need to 'register' for it with EM_SETEVENTMASK), rather than trying to hook keypresses - which gives a noticable lag.
DONE. Strangely enough, I found out that EN_CHANGE is handled in WM_COMMAND, while EN_SELCHANGE is part of WM_NOTIFY. Probably "by design"...

(old: Will look into it. Right no, I don't hook keypresses but rather use a 2 seconds timer.)

hutch--

The following code,


    mov lcnt, rv(SendMessage,Edit,EM_GETLINECOUNT,0,0)


performs consistently in any style setting of the ricedit 2 but the following line,


    mov lnum, rv(SendMessage,Edit,EM_EXLINEFROMCHAR,0,lind)


always lags 2 behind so the next rick is to try and find a method to relate tis info with the line count.

Trapping the keystroke from the main message loop with a WM_KEYDOWN does not appear laggy where working on WM_KEYUP in the edit control callback certainly is slow. I need the access after the enter key in pressed but before the edit control changes the caret position as it makes reading the current line tidier and changing the text output for indent a lot more trouble free.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

hutch--

 :bg

BINGO !!!

Tedd, you are a scholar and a gentleman or if the second offends you, a scholar.  :U

This works corectly.


    invoke SendMessage,Edit,EM_EXGETSEL,0,ADDR cr                   ; get char position
    mov lind, rv(SendMessage,Edit,EM_LINEINDEX,cr.cpMin,0)          ; get 1st character index on current line
    mov lcnt, rv(SendMessage,Edit,EM_GETLINECOUNT,0,0)
    mov eax, lcnt
    sub eax, 1
    mov lin2, rv(SendMessage,Edit,EM_LINEINDEX,eax,0)

    mov eax, lind
    .if eax == lin2
      fn MessageBox,hWnd,"At END","Caret Status",MB_OK
    .else
      fn MessageBox,hWnd,"Less than END","Caret Status",MB_OK
    .endif
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Tedd

No snowflake in an avalanche feels responsible.

PBrennick

Consider this...

    invoke  SendMessage, hEdit, EM_SETTYPOGRAPHYOPTIONS, TO_SIMPLELINEBREAK, TO_SIMPLELINEBREAK

-- Paul
The GeneSys Project is available from:
The Repository or My crappy website