EM_GETPARAFORMAT previously would overwrite the cbSize field with the
size of PARAFORMAT2, would read past the end of the struct, and might
indicate that PARAFORMAT2 fields are valid using the mask regardless
of the value of cbSize.
If a EM_SETPARAFORMAT message is sent to the richedit control with bits
in the dwMask field that correspond to PARAFORMAT2 fields, then these
fields should be ignored. Instead data was copied from outside of the
structure.
Using the WS_VSCROLL style causes the ES_AUTOVSCROLL option to be set,
and using the WS_HSCROLL style causes the ES_AUTOHSCROLL flag to be
set (except with richedit v1.0).
The contents of the text can be zoomed in with EM_SETZOOM, or with the
mouse wheel. EM_SETZOOM is implemented, but these tests show bugs in
the implementation, and zooming using the mouse wheel isn't
implemented at all yet.
Windowless richedit control will not be able to call GetCapture without
a handle to the host window (and there is no ITextHost_TxGetCapture
method), but there is a ITextHost_TxSetCapture method available for
setting and releasing the capture on the mouse. This means that the
richedit control will need to keep track of whether it has captured the
mouse or not to implement windowless richedit controls.
Previously the WM_NCCREATE was handled by the as if it was always for
later versions, then the window proc for version 1.0 would make
appropriate changes afterwards. Instead both versions should call the
same function (e.g. ME_MakeEditor) and provide the value for
bEmulateVersion10 to make the code clearer.
This fixes inconsistencies shown in the tests I added for the
WM_GETDLGCODE. The tests covered different cases handled by the
current implementation in order to show that the native implementation
is simpler for all these cases.
When the character or paragraph format is changed the paragraph that
is changed is already marked to be rewrapped, so ME_MarkAllForWrapping
shouldn't be called. Since ME_RewrapRepaint uses this function, it
shouldn't be called in these circumstances, since rewrapping all the
text can cause noticable delays when working with a lot of text.
A common case for richedit controls are that a large amount of text is
set initially with word wrap enabled. This causes the initially
wrapping of the text, which also calculates the text length. After
this the vertical scrollbar will be shown, which causes the text to be
rewrapped again. After this there are two redundant rewraps that are
done which this patch eliminates.
On WM_DESTROY the editor was getting freed, then it was used to obtain
a handle to the editor. This patch moves it just before the editor is
freed within ME_DestroyEditor.
In order to make the message handling available to windowless richedit
controls, the message handling must be in a function that can be
called from the ITextServices_TxSendMessage method. This method will
never have a handle to a window to pass to RichEditWndProc_common in
order to get the editor with GetWindowLongPtrW, but passing the editor
will work (even if hWnd is NULL).
When the text is wrapped, the positions for all the runs, paragraphs,
and cells are already calculated and stored. The only thing left to do
for painting is to offset them by the formatting rectangle and the
scroll position.
During wrapping there were three different heights that were being
stored, with only one of them being done correctly. The other ones
failed to incorporate the height of the paragraph or row, so ended up
being incorrect.
The formatting rectangle is set with EM_SETRECT, and retrieved with
EM_GETRECT, so it corresponds to rcFormat in the code. This defines the
area that the richedit control should draw the text so that it is
offset by the top-left corner of the formatting rectangle, and clipped
so that it doesn't draw past the bottom or right hand side. Thus this
is important for implementing windowless richedit controls to not
interfere with the rest of the window.
There were several methods that do not have a HRESULT for a return
value, so returning E_NOTIMPL is not appropriate. For all the BOOL
return values FALSE was returned to indicate the operation was not
performed.