Using the ITextHost interface allows this notification to be received
for windowless richedit controls. Windowed richedit conrols have an
ITextHost implementation that will fill in hwndFrom and idFrom, but
these should probably be initialized to 0 for windowless richedit
controls.
The test that succeeded from this change was as a result of allowing the
end of the character format change be specified using NULL as the rest
of the text. Before, the end paragraph run at the end of the text was
not being set for this case, when all the text was supposed to have its
character format changed.
Plenty of places in the code find following or preceding runs, then
afterwards find the paragraph from the run. This is inefficient because
the same linked list is used for both runs and paragraphs, so changes in
paragraphs can be detected while returning the next or previous run.
The code was previously getting the same text in the loop from the
editor, and it was converting each of the prefixes to compare against
for each URL candidate.
Before a single length was used for the number of characters to retrieve
from the text, and to keep track of the size of the buffer. These are
not equivalent, since there is a possible end of line conversion.
Previously the only convenient way to get the start and end of the
selection was through offsets, which eventually need to get converted
back into items in the linked list storing the text. The new function
will help with eliminating these inefficiencies.
This function will make it easier to work with ME_Cursor objects, which
should be used in a lot of places instead of character offsets (which
often require seeking through the linked lists to perform operations
with).
Style objects are referenced counted in richedit controls, so I tried to
make sure styles were released properly. This can be checked using with
the all_refs global reference count to see if everything is cleaned up.
The application AutoGK was getting the length of the text with
WM_GETTEXTLENGTH to allocate an appropriate buffer size, but then
claimed the buffer was twice the size when sending WM_GETTEXTEX. This
caused the memcpy call to overflow the actual buffer since the count
is based on the size of the buffer alone, regardless of the amount of
text retrieved.
ME_GetTextEx directly handles EM_GETTEXTEX, and previously a NULL buffer
would be dereferenced, and a 0 buffer length would cause nCount an
underflow in the nCount value which would allow a buffer overflow to
occur.
The application Blitzin2 was sending WM_VSCROLL messages to the
richedit control directly, when normally this message is supposed to
be a notification sent after the scrollinfo is set. Native richedit
controls always use the 16-bit value passed to this message to set the
scroll position for SB_THUMBPOSITION, rather than trying to find a
32-bit value through GetScrollInfo like I had previously done.
Rich text files have groupings of text, where styles are pushed onto
the stack when encountering a start of the group, then popped at the
end of the group. This was being handled improperly before, because a
single styleChanged flag was being stored to keep track of whether the
style needed to be restored at the end of a group. This fails to work
properly since the single flag isn't keeping track of all the levels
of the stack, so some styles are not restored properly.
When a colour table entry is empty, then the default colour is used.
For an incomplete colour table entry 0 is used for the missing colours.
Previously the -1 value used internally for missing colours was being
converted into white, where it should be using the default colour that
is normally black.
This bug could be seen by loading the following rich text into wordpad:
{\rtf{\colortbl;;}\cf1 text}
Previously after initial window creation of a richedit control with the
ES_DISABLENOSCROLL window style flag the scrollbar would be shown but
not disabled. This patch fixes this issue by explicitly disabling and
showing the scrollbar.
WM_SETTEXT seems to check for {\rtf or {\urtf to determine if it is an
ascii RTF string, even if it is a unicode message. So I removed the
check to see if it is a unicode message, and added a check for {\urtf.
Wine was not doing bounds checks for EM_GETTEXTRANGE, which was causing
a crash in Bug 17822. The added tests would cause a crash without the
added bounds checks in the richedit code.
The bounds checks I put in HandleMessage, since ME_GetTextRange is also
called for ME_GETSELTEXT which should not have bounds checks, since it
uses the selection range.
When the ME_GETTEXTRANGE message returns 0, no text is copied, not even
the NULL terminating charter. This differs from EM_GETSELTEXT which
will copy the NULL terminating character when no text is selected. This
behaviour is consistent with native richedit controls.
EM_SETCHARFORMAT can be used to make text links. Automatic URL
detection being enable would cause these links to be removed if the text
is not a URL, so this must be prevented.
Previously checks were made for AutoURLDetect_bEnable before calling
ME_UpdateSelectionLinkAttribute, or ME_UpdateLinkAttribute. This is
more error prone than checking for this within the function, so one call
was missing this check.
ME_SetCursor also didn't respect this behaviour, since it wouldn't set
the cursor to the hand when hovering over a link without automatic URL
detection disabled.
Before the code was modifying the format rect to compensate for space
being added or removed for the selection bar, but this should only
happen when the ECO_SELECTIONBAR setting bit changes.
When all the text fits on the screen, the scrollbars are not shown from
EM_SHOWSCROLLBAR. The message instead adds support for the specified
scrollbar when lParam is TRUE, so that the scrollbar will be shown when
sufficient text is in the document.
This prevents some needless searching for the start of the paragraph
from a run stored in a cursor. Usually a pointer to the paragraph is
already available when the cursor is set anyway.
These functions were probably previously needed because of some wierd
special handling of backspace characters, but currently there is no
reason why the nLen field can't be accessed directly.
Having to functions that just access the string length field just causes
slightly more effort for someone to look at the code, because they need
to enter the function to find out what it actually is doing.
Wrapping is needed to be done even when repainting isn't done since
later messages expect line breaks to reflect the current text. Some
message can specify not to paint the sceen, but this should prevent
wrapping from being done.
Rather than get the paragraph from the run, the function allows the
caller to provide the paragraph, since it is already available. This
reduces unnecessary traversals of lists that take longer as more runs
and rows are in the paragraph.
The ME_RunOfsFromCharOfs function finds the paragraph before finding the
run and offset within the run, so the function may as well be able to
return this paragraph to the caller. Many callers to the function
instead find the paragraph from the run, which ends up unnecessarily
traversing a linked list of runs within the paragraph.
There was a bug in ME_FindText which would cause the final caracter
offset to be incorrect when a paragraph was crossed while matching
characters. The problem was the character offset of the wrong
paragraph was used in the calculation of the start offset of the
match.
The text mode is already stored, and EM_SETTEXTMODE already exists.
There was however a bug in EM_MakeEditor that could cause TM_PLAINTEXT
and TM_RICHEDIT to be set at the same time. This was corrected to ensure
EM_GETTEXTMODE returned the proper mode being used.
The width for EM_SETTARGETDEVICE is used by some applications to set the
wrapping width to a certain distance in twips. This can be used even
though the target device is ignored.
The internal style flags are used to determine whether to show or hide
the scrollbar when ME_UpdateScrollBar is called. EM_SHOWSCROLLBAR seems
to update this state in native richedit controls.
Previously a count of the carraige returns and line feeds were stored
for end of paragraph runs, and a paragraph sign was stored as the actual
string. This was causing many special cases where the length of the
run needed to be determined differently if the run was or wasn't an
end of paragraph run.
There wasn't any use for storing the paragraph sign unless some drawing
code gets commented out to allow the end paragraphs to be shown,
therefore I changed the code to store the actual string that gets
retrieved by WM_GETTEXT.
The two functions ME_FindItemAtOffset and ME_RunOfsFromCharOfs were almost
identically used, since ME_FindItemAtOffset was always used to find a run.
The only difference was how they returned the offset within the run for an
end of paragraph run.
For ME_FindItemAtOffset it would return the next run if it was in between \r
and \n. ME_RunOfsFromCharOfs would instead return an nOffset of 0 for end
paragraph runs. This subtle difference introduced bugs, so I decided to
avoid having special case in this function when creating this patch, and
instead let the caller handle this case.
EM_GETTEXTRANGE allows the start character offset and end characters
offset to be used to specify the range of text to retrieve. If the
start offset is in the middle of an end of paragraph run (i.e. \r\n),
then it should only retrieve the characters after the specified
character offset.
I found that ME_FindItemAtOffset and ME_CursorFromCharOfs are used
almost identically, except for how they handle a character offset that
is between a carriage return and line feed. In this case
ME_CursorFromCharOfs sets the cursor's run offset to 0, but
ME_FindItemAtOffset instead returns the next run which is what was
causing ME_LINELENGTH to incorrectly return the length of the next
line.