From: Daniel Lehman dlehman25@gmail.com
nCharOfs is the key for paragraphs added to the marked tree If it is updated, re-add the entry to update its position --- dlls/riched20/caret.c | 2 +- dlls/riched20/editor.h | 2 +- dlls/riched20/para.c | 4 ++-- dlls/riched20/run.c | 9 +++++++-- dlls/riched20/tests/editor.c | 11 +++++++++++ 5 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c index f89770ccc75..eed4bbf26bc 100644 --- a/dlls/riched20/caret.c +++ b/dlls/riched20/caret.c @@ -416,7 +416,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, /* c = updated data now */
if (c.run == cursor.run) c.run->nCharOfs -= shift; - editor_propagate_char_ofs( NULL, c.run, shift ); + editor_propagate_char_ofs( editor, NULL, c.run, shift );
if (!cursor.run->len) { diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 072d0f62782..d3e4f49da7b 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -129,7 +129,7 @@ static inline ME_DisplayItem *row_get_di( ME_Row *row ) void cursor_from_char_ofs( ME_TextEditor *editor, int char_ofs, ME_Cursor *cursor ) DECLSPEC_HIDDEN; BOOL cursor_next_run( ME_Cursor *cursor, BOOL all_para ) DECLSPEC_HIDDEN; BOOL cursor_prev_run( ME_Cursor *cursor, BOOL all_para ) DECLSPEC_HIDDEN; -void editor_propagate_char_ofs( ME_Paragraph *para, ME_Run *run, int shift ) DECLSPEC_HIDDEN; +void editor_propagate_char_ofs( ME_TextEditor *editor, ME_Paragraph *para, ME_Run *run, int shift ) DECLSPEC_HIDDEN; int run_char_ofs( ME_Run *run, int ofs ) DECLSPEC_HIDDEN; ME_Run *run_create( ME_Style *s, int nFlags ) DECLSPEC_HIDDEN; ME_Run *run_insert( ME_TextEditor *editor, ME_Cursor *cursor, diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c index 166b1fcd45b..357d6797c8c 100644 --- a/dlls/riched20/para.c +++ b/dlls/riched20/para.c @@ -671,7 +671,7 @@ ME_Paragraph *para_split( ME_TextEditor *editor, ME_Run *run, ME_Style *style, para_mark_rewrap( editor, &new_para->prev_para->member.para );
/* we've added the end run, so we need to modify nCharOfs in the next paragraphs */ - editor_propagate_char_ofs( next_para, NULL, eol_len ); + editor_propagate_char_ofs( editor, next_para, NULL, eol_len ); editor->nParagraphs++;
return new_para; @@ -774,7 +774,7 @@ ME_Paragraph *para_join( ME_TextEditor *editor, ME_Paragraph *para, BOOL use_fir ME_Remove( para_get_di(next) ); para_destroy( editor, next );
- editor_propagate_char_ofs( para_next( para ), NULL, -end_len ); + editor_propagate_char_ofs( editor, para_next( para ), NULL, -end_len );
ME_CheckCharOffsets(editor);
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c index f01f61c181a..8de2ba345cf 100644 --- a/dlls/riched20/run.c +++ b/dlls/riched20/run.c @@ -144,7 +144,7 @@ BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2) * the document) of the part of the text starting from given place. * Call with only one of para or run non-NULL. */ -void editor_propagate_char_ofs( ME_Paragraph *para, ME_Run *run, int shift ) +void editor_propagate_char_ofs( ME_TextEditor *editor, ME_Paragraph *para, ME_Run *run, int shift ) { assert( !para ^ !run );
@@ -160,7 +160,12 @@ void editor_propagate_char_ofs( ME_Paragraph *para, ME_Run *run, int shift )
do { + /* update position in marked tree, if added */ + if (para->nFlags & MEPF_REWRAP) + para_mark_remove( editor, para ); para->nCharOfs += shift; + if (para->nFlags & MEPF_REWRAP) + para_mark_add( editor, para ); para = para_next( para ); } while (para); } @@ -400,7 +405,7 @@ ME_Run *run_insert( ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style, ME_InsertString( run->para->text, run->nCharOfs, str, len ); ME_InsertBefore( run_get_di( insert_before ), run_get_di( run ) ); TRACE("Shift length:%d\n", len); - editor_propagate_char_ofs( NULL, insert_before, len ); + editor_propagate_char_ofs( editor, NULL, insert_before, len ); para_mark_rewrap( editor, insert_before->para );
/* Move any cursors that were at the end of the previous run to the end of the inserted run */ diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index 4f4d637b687..9682a4ad99f 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -8889,6 +8889,8 @@ static void test_rtf(void) 0x201d,0x200e,0x200f,0x200d,0x200c}; const char *pard = "{\rtf1 ABC\rtlpar\par DEF\par HIJ\pard\par}"; const char *highlight = "{\rtf1{\colortbl;\red0\green0\blue0;\red128\green128\blue128;\red192\green192\blue192;}\cf2\highlight3 foo\par}"; + const char *crash = "{\rtf2 {\par \pard \trowd \cellx6000 \intbl \cell \row \par \pard \li300 \bullet packages... \par }"; + const char *crash2 = "{\rtf1 \trowd row1 \intbl \cell \row \par \trowd row2 \intbl \cell \row}";
HWND edit = new_richeditW( NULL ); EDITSTREAM es; @@ -8940,6 +8942,15 @@ static void test_rtf(void) ok( cf.crTextColor == RGB(128,128,128), "got %08lx\n", cf.crTextColor ); ok( cf.crBackColor == RGB(192,192,192), "got %08lx\n", cf.crBackColor );
+ /* Test cases that crash */ + es.dwCookie = (DWORD_PTR)&crash; + es.dwError = 0; + SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es ); + + es.dwCookie = (DWORD_PTR)&crash2; + es.dwError = 0; + SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es ); + DestroyWindow( edit ); }