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.
For some reason the code previously mixed up a selection cursor with the
result cursor. The problem seemed to have corrected itself before as a
result of conversion between offsets and cursors, but my recent changes
made this bug more severe.
Previously the function was only used to move a single character in
either direction, so I made the function more general so that it could
be used in more places.
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.
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.
Previously inserting the object didn't result in the text being wrapped,
which would cause an assertion error when this is checked for during
repainting the text. It is also important to invalidate the affected
areas of text, update the scrollbar, and end the creation of undo
transactions for this insertion.
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 just being used for addition, so it was simpler to
remove the functions and modify the places it was used.
The ME_StrRelPos2 and ME_PosToVPos were just simple wrappers around
ME_StrRelPos, and ME_PosToVPos wasn't being used.
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.
ME_GetCursorCoordinates had two conditions that were always taken. The
first condition was if(pCursor->pRun->type == diRun) was following an
assertion making the exact same check. The next one, if(row), should
always be taken, otherwise the richedit controls are in a corrupt state,
therefore an assertion is more appropriate.
Previously it found the start or end by traversing the linked lists of
run, rows, paragraphs, and cells from the current position of the
cursors. Clearly it is better to get the start or end directly to make
it a constant time operation.