News:

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

Lines numbering in RichEdit with word wrap

Started by lamer, July 16, 2008, 09:01:58 PM

Previous topic - Next topic

lamer

Hi all!
I know one old truth - if I couldn't find any answer at any forum, search engine or discussion - this is the right place  :8)
I have a rich edit control with word wrap set by SendMessageW, hEdit, EM_SETTARGETDEVICE, 0, 0
Without word wrap I can retrieve line's index by EM_EXLINEFROMCHAR. But this message seems not to pay attention to wrapping. It just returns index after index for each line, no matter it's wrapped or not. All I need is to find right line number for first visible line. I tried to calculate new line characters amount from the beginning of control - it works until there are a small amount of lines, but if there are 5000 - 10000 lines, it just "dies".
You are my only hope... :boohoo:

jj2007

I assume you tried EM_GETFIRSTVISIBLELINE ?

lamer

Yes, of course.
It returns index for line as it appears in control, i.e. if I have one wrapped line and one not, then I'll get indexes 0, 1, 2, while the right indexes should be 0,1, because the first line is wrapped.

hutch--

Andre,

I confess that in a word wrap editor I turn the ine numbering off.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

#4
Hi lamer,
I checked my own editor for this behaviour and surprise, surprise, it works as it should. However, my own way of setting word wrap differs considerably from yours:
mov ecx, MyStyle
.if ExtAsc
or ecx, ES_AUTOHSCROLL ; DO NOT WRAP for Assembler Source Code files
.endif
or ecx, WS_CLIPSIBLINGS ; Test
invoke CreateWindowEx, 0, eax, 0,
ecx, 0, cHeight, rc.right, rc.bottom,
hwndOwner, NULL, hinst, NULL
mov hRE, eax

I attach temporarily the whole package (but without my confused source, sorry). It contains two almost identical files: Manual.rtf and Manual.asc; drag them one by one over richmasm.exe and watch the line counter in the upper right corner. If this is the behaviour you want, I would consider ES_AUTOHSCROLL.

EDIT: Modified attachment. I added

btc NoWordWrap, 0
sm hRE, EM_SETTARGETDEVICE, 0, NoWordWrap

triggered by Control W. I must confess this is confusing: It seems ES_AUTOHSCROLL during creation sets the word wrap mode, but only EM_SETTARGETDEVICE can change it at runtime. MSDN does not document this behaviour.

EDIT (2): Attachment removed. See later posts.

Tedd

JJ, the problem is that the wrapped portion of a line is numbered as an extra line, not as a part of the whole line. So a single long line wrapped into 3 sections becomes numbered as lines 1, 2, and 3 - whereas they should all be line 1, with the column value increasing along each.


Lamer, sorry I don't think there's any straightforward way to fix it. One way would be to parse the text to find the start each real line, but obviously that's nice and slow, and needs to be updated each time the text changes.
Notice that notepad simply hides the statusbar when wrapping, so there are no line numbers displayed.
No snowflake in an avalanche feels responsible.

PBrennick

#6
The following allows line numbering to work correctly in my editor.


WordWrap    proc
;---------------------------------------
    .if WWrap==0                        ; If wordwrap is off
      invoke  CheckMenuItem, hMenu, ID_MNU_WWRAP, MF_UNCHECKED  ; Clear the check mark
      push    1                         ; Save new setting
    .else
      invoke  CheckMenuItem, hMenu, ID_MNU_WWRAP, MF_CHECKED    ; Set the check mark
      push    0                         ; Save new setting
    .endif
    pop     WWrap                       ; Get WWrap setting
;
    invoke  SendMessage, hEditorBox, EM_SETTARGETDEVICE, 0, WWrap
    ret
;---------------------------------------
WordWrap    endp


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

jj2007

Quote from: Tedd on July 17, 2008, 11:12:47 AM
JJ, the problem is that the wrapped portion of a line is numbered as an extra line, not as a part of the whole line. So a single long line wrapped into 3 sections becomes numbered as lines 1, 2, and 3 - whereas they should all be line 1, with the column value increasing along each.

OK. In my editor, I have disabled word wrap for asc (Assembler Source Code) files, simply because it's rarely needed and may even confuse the reader.

Quote
Lamer, sorry I don't think there's any straightforward way to fix it. One way would be to parse the text to find the start each real line, but obviously that's nice and slow, and needs to be updated each time the text changes.
Notice that notepad simply hides the statusbar when wrapping, so there are no line numbers displayed.


Here is a faster option (tested, it works, but I will not implement it in RichMasm):

.if NoWordWrap==0
btc NoWordWrap, 0
sm hRE, EM_SETTARGETDEVICE, 0, NoWordWrap
sm hRE, EM_EXLINEFROMCHAR, 0, -1 ; get current line
push eax
btc NoWordWrap, 0
sm hRE, EM_SETTARGETDEVICE, 0, NoWordWrap
pop eax
.else
sm hRE, EM_EXLINEFROMCHAR, 0, -1 ; get current line
.endif

PBrennick

Tedd;

I do not see how the following is necessary as if everything is done correctly, wordwrap followed by some sort of line number update procedure (I use something called ShowPosition) works correctly.

Quote
Lamer, sorry I don't think there's any straightforward way to fix it. One way would be to parse the text to find the start each real line, but obviously that's nice and slow, and needs to be updated each time the text changes.
Notice that notepad simply hides the statusbar when wrapping, so there are no line numbers displayed.

as far as the settings used to create the edit window, I used the following:


;--------------------------------------------;
; This function creates a rich text editbox. ;
;--------------------------------------------;
CreateRichEdit proc uses ebx ecx edx edi esi hWin:DWORD,Xsize:DWORD,Ysize:DWORD,Xpos:DWORD,Ypos:DWORD
;---------------------------------------
    LOCAL hEdit:DWORD

    .if hRich == 0
      invoke  LoadLibrary, addr RichEditDLL
      mov     hRich, eax
      invoke  GetProcessHeap
      mov     hMainHeap, eax
    .endif
    invoke  CreateWindowEx, WS_EX_CLIENTEDGE, txt("RichEdit20A"), 0, WS_CHILD or \
            WS_VISIBLE or ES_MULTILINE or WS_VSCROLL or WS_HSCROLL or ES_SAVESEL or \
            ES_NOHIDESEL, Xpos, Ypos, Xsize, Ysize, hWin, 9400, hInstance, 0
    mov     hEdit, eax
    invoke  SendMessage, hEdit, EM_SETTYPOGRAPHYOPTIONS, TO_SIMPLELINEBREAK, TO_SIMPLELINEBREAK
    invoke  SendMessage, hEdit, EM_LIMITTEXT, -1, 0
    invoke  SendMessage, hEdit, EM_SETMODIFY, FALSE, 0
    invoke  SendMessage, hEdit, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS
    invoke  SendMessage, hEdit, EM_EMPTYUNDOBUFFER, 0, 0
    invoke  SendMessage, hEdit, EM_SETOPTIONS, ECOOP_XOR, ECO_SELECTIONBAR
    ;---------------------------
    ; Check the RichEdit version
    ;---------------------------
    invoke  SendMessage, hEdit, EM_SETTYPOGRAPHYOPTIONS, TO_SIMPLELINEBREAK, TO_SIMPLELINEBREAK
    invoke  SendMessage, hEdit, EM_GETTYPOGRAPHYOPTIONS, 1, 1
    .if eax == 0                        ; Means this message is not processed
      mov     RichEditVersion, 2
    .else
      mov     RichEditVersion, 3
    .endif
    ;------------------------------
    ; Subclass the RichEdit control
    ;------------------------------
    invoke  SetWindowLong, hEdit, GWL_WNDPROC, addr NewRichEditProc
    mov     lpOldRichProc, eax
    mov     eax, hEdit
    ret
;---------------------------------------
CreateRichEdit endp


Let's just Write the code correctly instead of trying to find nonexisting problems.

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

lamer

May be I miss something  :dazzled: but I still don't see how to find index of one , only one wretched line in word wrap case.
You have overloaded me with ways of rich edit creation  :green, but where is line numbering procedures everybody is speaking about?
Oh, I forgot - I use TM_PLAINTEXT for control, i.e. no rich edit options.
P.S.
I have to say - I really love this forum. There is a kind of magnetic force here (may be this is an "assembly" men's feature? or just a staff quality?) :wink

jj2007

Quote from: lamer on July 17, 2008, 06:15:41 PM
May be I miss something  :dazzled: but I still don't see how to find index of one , only one wretched line in word wrap case.

Try my "faster option" above. It temporarily disables wrapping, so that you can get the "true" line count. You may consider suspending screen updating, or setting a flag in case WM_PAINT makes trouble, but otherwise it works smoothly.

lamer

I do the numbering on WM_PAINT. Switching between wrap and no wrap within WM_PAINT? Hmmm....
But it gives me the idea: what if I had one more, unvisible rich edit with the same text without wrapping? Then I could find needed line index in it. But from the other side loading two controls will take a lot of time for big files :eek

PBrennick

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

jj2007

Quote from: lamer on July 17, 2008, 09:01:29 PM
I do the numbering on WM_PAINT. Switching between wrap and no wrap within WM_PAINT? Hmmm....

Set a global flag, and quit WM_PAINT if it's set. Clear it when you are done... if all that is needed. As I wrote above, I tested it, and it worked, apparently even without flicker.

Quote
But it gives me the idea: what if I had one more, unvisible rich edit with the same text without wrapping? Then I could find needed line index in it. But from the other side loading two controls will take a lot of time for big files :eek

And you need to synchronise them. Sounds like a big overkill for such a simple problem.

Tedd

Quote from: PBrennick on July 17, 2008, 04:55:46 PM
Let's just Write the code correctly instead of trying to find nonexisting problems.
I couldn't agree more :wink
Unfortunately, the problem still persist with your 'solution' - so I expect there may be a misunderstanding of what the problem actually is..

So, let say we have the following unwrapped text:
Quote
1: This is line one. Line 1. This is line one. Line 1. Line 1. Line 1.
2: Next comes line two. This is line 2. Line 2. Line 2. Line 2. Line 2.
3: After that is line three. Line 3. Line 3. Line 3. Line 3. Line 3. Line 3.
4: And finally, line four. Line 4.  Line 4. Line 4. Line 4. Line 4. Line 4.
The line numbers are pretty obvious.

Now, if we wrap it, there are two possibilities for how to number the lines:

Version 1
Quote
1: This is line one. Line 1. This is line
2: one. Line 1. Line 1. Line 1.
3: Next comes line two. This is line 2.
4: Line 2. Line 2. Line 2. Line 2.
5: After that is line three. Line 3. Line
6: 3. Line 3. Line 3. Line 3. Line 3.
7: And finally, line four. Line 4.  Line 4.
8: Line 4. Line 4. Line 4. Line 4.

Version 2
Quote
1: This is line one. Line 1. This is line
  one. Line 1. Line 1. Line 1.
2: Next comes line two. This is line 2.
  Line 2. Line 2. Line 2. Line 2.
3: After that is line three. Line 3. Line
  3. Line 3. Line 3. Line 3. Line 3.
4: And finally, line four. Line 4.  Line 4.
  Line 4. Line 4. Line 4. Line 4.


Your solution results in version 1, and indeed this is how richedit words. But that is the problem.
The question is how to get version 2. Why? Well let's say your compiler/assembler reports there's a syntax error on line 4 - which line 4 would that be??


I attempted to try JJ's method, but it resulted in an exception as soon as the line number is updated :dazzled:
No snowflake in an avalanche feels responsible.