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

jj2007

#15
Quote from: Tedd on July 18, 2008, 11:45:44 AM
I attempted to try JJ's method, but it resulted in an exception as soon as the line number is updated :dazzled:
Me dazzled, too :dazzled:
I have now implemented this - extract all files to root of Masm drive, then drag LineTest.asc over RichMasm.exe and press Control W to toggle wrap. It works over here on XP SP2...

LOCAL CurLine:DWORD
...
  .if NoWordWrap==0
sm hRE, EM_SETTARGETDEVICE, 0, 1
sm hRE, EM_EXLINEFROMCHAR, 0, -1 ; get current line
mov CurLine, eax
sm hRE, EM_SETTARGETDEVICE, 0, 0
mov eax, CurLine
  .else
sm hRE, EM_EXLINEFROMCHAR, 0, -1 ; get current line
mov CurLine, eax
  .endif

jj2007

Temporarily disabling the line wrap works but an additional redraw block might be needed. Will keep you posted ;-)

EDIT:
MSDN: For Microsoft Rich Edit 2.0 and later, Rich Edit no longer supports EditWordBreakProcEx. Users can send EM_SETWORDBREAKPROC to set EditWordBreakProc, which is now enhanced to support the passing of Unicode text.

Cute and clear, isn't it? "EX" is the obsolete one. Anyway, just as an idea: One might cheat the control in the callback that handles the line breaks.

The brute force alternative is to act on EN_CHANGE: save the whole stuff as plain text to a buffer, and count the 0D0A until the character pos. I love the RichEdit control, it is so full of challenges, and working with it requires the use of the whole programming toolbox, for finding workarounds tackling with "unexpected behaviour". :boohoo:

LOCAL txrg:TEXTRANGE
LOCAL CurLine:DWORD
  sm hRE, EM_EXGETSEL, 0, addr txrg ; get current sel
  .if NoWordWrap==0 ; still a problem with scrolling
Refresh_OFF
sm hRE, EM_SETTARGETDEVICE, 0, 1
sm hRE, EM_EXLINEFROMCHAR, 0, -1 ; get current line
mov CurLine, eax
sm hRE, EM_SETTARGETDEVICE, 0, 0
sm hRE, EM_EXSETSEL, 0, addr txrg ; set current sel
mov eax, CurLine
Refresh_ON
  .else
sm hRE, EM_EXLINEFROMCHAR, 0, -1 ; get current line
mov CurLine, eax
  .endif


Refresh_ON   EQU invoke UpdateRE, 1
Refresh_OFF   EQU invoke UpdateRE, 0

UpdateRE proc flag:DWORD ; 1=ON
  pushad
  .if flag
.if OldMask ; set might happen twice in a row, so let's be cautious
sm hRE, EM_SETEVENTMASK, 0, OldMask
clrx OldMask
.endif
sm hRE, WM_SETREDRAW, 1, 0
invoke InvalidateRect, hRE, 0, 0 ; redraw the RichEdit window
   .else
sm hRE, EM_SETEVENTMASK, 0, 0
.if eax
mov OldMask, eax
.endif
sm hRE, WM_SETREDRAW, 0, 0
  .endif
  popad
  ret
UpdateRE endp

[attachment deleted by admin]

PBrennick

Tedd,
I see your point. I guess I never realized that anyone would wish to use wordwrap in a .ASM source file. My solution would not be of much use, I guess. Really, the only reason I added the wordwrap function into my editor is for the generation of text readme type files and the like. Correct me if I am wrong, but would not wrapping a source file inject linebreaks into the middle of a line and cause the assembler to hiccup?

Everybody has their own idea of how things are done and I 'do' respect that. I just never have seen a source line that needs to be wrapped (except for the comments, which are ignored by the assembler, anyhow. So, I am certain I am missing the point of all this.

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

Tedd

Quote from: PBrennick on July 18, 2008, 03:35:19 PM
I see your point. I guess I never realized that anyone would wish to use wordwrap in a .ASM source file. My solution would not be of much use, I guess. Really, the only reason I added the wordwrap function into my editor is for the generation of text readme type files and the like.
The original question didn't specify any particular type of source file :wink I only used source code as an example, but yes, it's probably less useful for asm.

Quote
Correct me if I am wrong, but would not wrapping a source file inject linebreaks into the middle of a line and cause the assembler to hiccup?
Well when you save the file, you'd generally expect it to be saved without the 'soft' linebreaks that the edit control uses internally (to enforce wrapping) - it should be saved the same regardless of whether wrapping or not.

Quote
Everybody has their own idea of how things are done and I 'do' respect that. I just never have seen a source line that needs to be wrapped (except for the comments, which are ignored by the assembler, anyhow. So, I am certain I am missing the point of all this.
While it's not necessarily good style, it can/does happen in other languages. And as for comments, while they are largely ignored by the compiler, any references to proceeding lines would consequently be incorrect (as the wrapped lines would offset the count.)
The 'point' is simply that Lamer would like to do it this way :lol
No snowflake in an avalanche feels responsible.

jj2007

#19
I would seriously consider the brute force approach. Saving the whole file to a buffer via GETTEXTRANGE is pretty fast, and searching with a mov ax, [esi] is fast, too. You can search the whole \masm32\include\* in roughly 20 ms - too little to be noticed when typing a text.

EDIT: Sample code "brute force"

This could certainly be optimised; in particular, the EM_GETTEXTRANGE message is needed only after an EN_CHANGE notification. I did some timings on Windows.inc: If the cursor is in the last line, the algo takes about 25 ms, unnoticeable even with fast keyboard repeat settings.


sm   EQU invoke SendMessage,    ; makes typing easier ;-)

LOCAL txrg:TEXTRANGE
LOCAL CurLine:DWORD
  call DispMenu
  push edi
  push ebx
  sm hRE, EM_EXGETSEL, 0, addr txrg ; get current sel

  .if NoWordWrap==0
.if LcBuffer$==0
mov LcBuffer$, alloc$(1000000) ; free$ on exit! Needs checks on size.
.endif

; invoke GetTickCount
; push eax
; xor edi, edi ; counter
; .While edi<10
; inc edi

push esi
mov esi, LcBuffer$
mov txrg.lpstrText, esi
mov ebx, txrg.chrg.cpMin
push txrg.chrg.cpMax
mov txrg.chrg.cpMax, ebx ; current start of selection
m2m txrg.chrg.cpMin, 0
sm hRE, EM_GETTEXTRANGE, 0, addr txrg
pop txrg.chrg.cpMax
mov txrg.chrg.cpMin, ebx
xor edx, edx
mov CurLine, edx
add edx, 13 ; 0D
add ebx, esi

@@: mov al, [esi] ; inner loop - try lodsb...
add esi, 1
cmp esi, ebx
ja @F
cmp al, dl
jne @B

inc CurLine
jmp @B
@@: mov eax, CurLine
pop esi

; .Endw
; invoke GetTickCount
; pop edx
; sub eax, edx

  .else
sm hRE, EM_EXLINEFROMCHAR, 0, -1 ; get current line
mov CurLine, eax
  .endif
  inc eax ; Line n
  invoke dwtoa, eax, pDwToA

lamer

I'm glad to state that I have been right - this forum is really the best. Not just one question has got multiple answers and solutions, it's grown into some kind of philosophical discussion.
In my opinion calculating new line characters is still the best solution - at least for not very large files.
So thank you all very much! :clap:

jj2007

You are welcome, lamer. You raised a good question, and got qualified answers :bg
Re the code posted above, I use it now in my own rich editor. At the bottom of Windows.inc, response is a bit sluggish - maybe I should take away that .While ebx<100 loop ;-)
Jokes apart: Searching 800k of Windows.inc for CR takes about 1.8 milliseconds. The EM_GETTEXTRANGE is the bottleneck, but even if I use that message for each and every cursor movement, response is still ok in a 1 MB file. If you trigger that message only for EN_CHANGE, or with a WM_TIMER if there is more then x ms without EN_CHANGE, then response times will be ok even for 100 MB files.

hutch--

 :bg

Andre,

Quote
I'm glad to state that I have been right - this forum is really the best. Not just one question has got multiple answers and solutions, it's grown into some kind of philosophical discussion.

We have a secret in how this works, we only allow human beings as members (and a few martians).  :green2
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php