diff --git a/dll/win32/riched20/caret.c b/dll/win32/riched20/caret.c index 96a95872c2d..4785650bb78 100644 --- a/dll/win32/riched20/caret.c +++ b/dll/win32/riched20/caret.c @@ -26,16 +26,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); void ME_SetCursorToStart(ME_TextEditor *editor, ME_Cursor *cursor) { - cursor->pPara = editor->pBuffer->pFirst->member.para.next_para; - cursor->pRun = ME_FindItemFwd(cursor->pPara, diRun); + cursor->para = editor_first_para( editor ); + cursor->run = para_first_run( cursor->para ); cursor->nOffset = 0; } static void ME_SetCursorToEnd(ME_TextEditor *editor, ME_Cursor *cursor, BOOL final_eop) { - cursor->pPara = editor->pBuffer->pLast->member.para.prev_para; - cursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); - cursor->nOffset = final_eop ? cursor->pRun->member.run.len : 0; + cursor->para = para_prev( editor_end_para( editor ) ); + cursor->run = para_end_run( cursor->para ); + cursor->nOffset = final_eop ? cursor->run->len : 0; } @@ -99,7 +99,7 @@ int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how) length = ME_GetTextLength(editor); - if ((editor->styleFlags & ES_MULTILINE) + if ((editor->props & TXTBIT_MULTILINE) && (how->flags & GTL_USECRLF) && !editor->bEmulateVersion10) /* Ignore GTL_USECRLF flag in 1.0 emulation */ length += editor->nParagraphs - 1; @@ -201,16 +201,16 @@ int set_selection_cursors(ME_TextEditor *editor, int from, int to) return len; } - ME_CursorFromCharOfs(editor, from, &editor->pCursors[1]); + cursor_from_char_ofs( editor, from, &editor->pCursors[1] ); editor->pCursors[0] = editor->pCursors[1]; ME_MoveCursorChars(editor, &editor->pCursors[0], to - from, FALSE); /* Selection is not allowed in the middle of an end paragraph run. */ - if (editor->pCursors[1].pRun->member.run.nFlags & MERF_ENDPARA) + if (editor->pCursors[1].run->nFlags & MERF_ENDPARA) editor->pCursors[1].nOffset = 0; - if (editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA) + if (editor->pCursors[0].run->nFlags & MERF_ENDPARA) { if (to > len) - editor->pCursors[0].nOffset = editor->pCursors[0].pRun->member.run.len; + editor->pCursors[0].nOffset = editor->pCursors[0].run->len; else editor->pCursors[0].nOffset = 0; } @@ -218,54 +218,33 @@ int set_selection_cursors(ME_TextEditor *editor, int from, int to) } -void ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, - int *x, int *y, int *height) +void cursor_coords( ME_TextEditor *editor, ME_Cursor *cursor, + int *x, int *y, int *height ) { - ME_DisplayItem *row; - ME_DisplayItem *run = pCursor->pRun; - ME_DisplayItem *para = pCursor->pPara; - ME_DisplayItem *pSizeRun = run; + ME_Row *row; + ME_Run *run = cursor->run; + ME_Paragraph *para = cursor->para; + ME_Run *size_run = run, *prev; ME_Context c; int run_x; + HDC hdc = ITextHost_TxGetDC( editor->texthost ); - assert(height && x && y); - assert(~para->member.para.nFlags & MEPF_REWRAP); - assert(run && run->type == diRun); - assert(para && para->type == diParagraph); + assert(~para->nFlags & MEPF_REWRAP); - row = ME_FindItemBack(run, diStartRowOrParagraph); - assert(row && row->type == diStartRow); + row = row_from_cursor( cursor ); - ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost)); + ME_InitContext( &c, editor, hdc ); - if (!pCursor->nOffset) - { - ME_DisplayItem *prev = ME_FindItemBack(run, diRunOrParagraph); - assert(prev); - if (prev->type == diRun) - pSizeRun = prev; - } - if (editor->bCaretAtEnd && !pCursor->nOffset && - run == ME_FindItemFwd(row, diRun)) - { - ME_DisplayItem *tmp = ME_FindItemBack(row, diRunOrParagraph); - assert(tmp); - if (tmp->type == diRun) - { - row = ME_FindItemBack(tmp, diStartRow); - pSizeRun = run = tmp; - assert(run); - assert(run->type == diRun); - } - } - run_x = ME_PointFromCharContext( &c, &run->member.run, pCursor->nOffset, TRUE ); + if (!cursor->nOffset && (prev = run_prev( run ))) size_run = prev; - *height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent; - *x = c.rcView.left + run->member.run.pt.x + run_x - editor->horz_si.nPos; - *y = c.rcView.top + para->member.para.pt.y + row->member.row.nBaseline - + run->member.run.pt.y - pSizeRun->member.run.nAscent - - editor->vert_si.nPos; + run_x = ME_PointFromCharContext( &c, run, cursor->nOffset, TRUE ); + + *height = size_run->nAscent + size_run->nDescent; + *x = c.rcView.left + run->pt.x + run_x - editor->horz_si.nPos; + *y = c.rcView.top + para->pt.y + row->nBaseline + + run->pt.y - size_run->nAscent - editor->vert_si.nPos; ME_DestroyContext(&c); + ITextHost_TxReleaseDC( editor->texthost, hdc ); return; } @@ -273,7 +252,7 @@ void create_caret(ME_TextEditor *editor) { int x, y, height; - ME_GetCursorCoordinates(editor, &editor->pCursors[0], &x, &y, &height); + cursor_coords( editor, &editor->pCursors[0], &x, &y, &height ); ITextHost_TxCreateCaret(editor->texthost, NULL, 0, height); editor->caret_height = height; editor->caret_hidden = TRUE; @@ -302,7 +281,7 @@ void update_caret(ME_TextEditor *editor) if (!editor->bHaveFocus) return; if (!ME_IsSelection(editor)) { - ME_GetCursorCoordinates(editor, &editor->pCursors[0], &x, &y, &height); + cursor_coords( editor, &editor->pCursors[0], &x, &y, &height ); if (height != editor->caret_height) create_caret(editor); x = min(x, editor->rcFormat.right-1); ITextHost_TxSetCaretPos(editor->texthost, x, y); @@ -364,60 +343,57 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, int nOfs = ME_GetCursorOfs(start), text_len = ME_GetTextLength( editor ); int shift = 0; int totalChars = nChars; - ME_DisplayItem *start_para; + ME_Paragraph *start_para; BOOL delete_all = FALSE; /* Prevent deletion past last end of paragraph run. */ nChars = min(nChars, text_len - nOfs); if (nChars == text_len) delete_all = TRUE; - start_para = c.pPara; + start_para = c.para; if (!bForce) { - ME_ProtectPartialTableDeletion(editor, &c, &nChars); - if (nChars == 0) - return FALSE; + table_protect_partial_deletion( editor, &c, &nChars ); + if (nChars == 0) return FALSE; } - while(nChars > 0) + while (nChars > 0) { ME_Run *run; - ME_CursorFromCharOfs(editor, nOfs+nChars, &c); - if (!c.nOffset && - nOfs+nChars == (c.pRun->member.run.nCharOfs - + c.pPara->member.para.nCharOfs)) + cursor_from_char_ofs( editor, nOfs + nChars, &c ); + if (!c.nOffset) { /* We aren't deleting anything in this run, so we will go back to the * last run we are deleting text in. */ - ME_PrevRun(&c.pPara, &c.pRun, TRUE); - c.nOffset = c.pRun->member.run.len; + c.run = run_prev_all_paras( c.run ); + c.para = c.run->para; + c.nOffset = c.run->len; } - run = &c.pRun->member.run; - if (run->nFlags & MERF_ENDPARA) { - int eollen = c.pRun->member.run.len; + run = c.run; + if (run->nFlags & MERF_ENDPARA) + { + int eollen = c.run->len; BOOL keepFirstParaFormat; - if (!ME_FindItemFwd(c.pRun, diParagraph)) - { - return TRUE; - } + if (!para_next( para_next( c.para ) )) return TRUE; + keepFirstParaFormat = (totalChars == nChars && nChars <= eollen && run->nCharOfs); if (!editor->bEmulateVersion10) /* v4.1 */ { - ME_DisplayItem *next_para = ME_FindItemFwd(c.pRun, diParagraphOrEnd); - ME_DisplayItem *this_para = next_para->member.para.prev_para; + ME_Paragraph *this_para = run->para; + ME_Paragraph *next_para = para_next( this_para ); /* The end of paragraph before a table row is only deleted if there * is nothing else on the line before it. */ - if (this_para == start_para && - next_para->member.para.nFlags & MEPF_ROWSTART) + if (this_para == start_para && next_para->nFlags & MEPF_ROWSTART) { /* If the paragraph will be empty, then it should be deleted, however * it still might have text right now which would inherit the * MEPF_STARTROW property if we joined it right now. * Instead we will delete it after the preceding text is deleted. */ - if (nOfs > this_para->member.para.nCharOfs) { + if (nOfs > this_para->nCharOfs) + { /* Skip this end of line. */ nChars -= (eollen < nChars) ? eollen : nChars; continue; @@ -425,7 +401,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, keepFirstParaFormat = TRUE; } } - ME_JoinParagraphs(editor, c.pPara, keepFirstParaFormat); + para_join( editor, c.para, keepFirstParaFormat ); /* ME_SkipAndPropagateCharOffset(p->pRun, shift); */ ME_CheckCharOffsets(editor); nChars -= (eollen < nChars) ? eollen : nChars; @@ -439,7 +415,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, c.nOffset -= nCharsToDelete; - mark_para_rewrap(editor, ME_FindItemBack(c.pRun, diParagraph)); + para_mark_rewrap( editor, c.run->para ); cursor = c; /* nChars is the number of characters that should be deleted from the @@ -464,7 +440,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, for (i=-1; inCursors; i++) { ME_Cursor *pThisCur = editor->pCursors + i; if (i == -1) pThisCur = &c; - if (pThisCur->pRun == cursor.pRun) { + if (pThisCur->run == cursor.run) { if (pThisCur->nOffset > cursor.nOffset) { if (pThisCur->nOffset-cursor.nOffset < nCharsToDelete) pThisCur->nOffset = cursor.nOffset; @@ -475,8 +451,8 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, } if (pThisCur->nOffset == run->len) { - pThisCur->pRun = ME_FindItemFwd(pThisCur->pRun, diRunOrParagraphOrEnd); - assert(pThisCur->pRun->type == diRun); + pThisCur->run = run_next( pThisCur->run ); + assert( pThisCur->run ); pThisCur->nOffset = 0; } } @@ -484,26 +460,21 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, /* c = updated data now */ - if (c.pRun == cursor.pRun) - ME_SkipAndPropagateCharOffset(c.pRun, shift); - else - ME_PropagateCharOffset(c.pRun, shift); + if (c.run == cursor.run) c.run->nCharOfs -= shift; + editor_propagate_char_ofs( NULL, c.run, shift ); - if (!cursor.pRun->member.run.len) + if (!cursor.run->len) { TRACE("Removing empty run\n"); - ME_Remove(cursor.pRun); - ME_DestroyDisplayItem(cursor.pRun); + ME_Remove( run_get_di( cursor.run )); + ME_DestroyDisplayItem( run_get_di( cursor.run )); } shift = 0; - /* - ME_CheckCharOffsets(editor); - */ continue; } } - if (delete_all) ME_SetDefaultParaFormat( editor, &start_para->member.para.fmt ); + if (delete_all) editor_set_default_para_fmt( editor, &start_para->fmt ); return TRUE; } @@ -516,20 +487,6 @@ BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars) nChars, FALSE); } -static ME_DisplayItem * -ME_InternalInsertTextFromCursor(ME_TextEditor *editor, int nCursor, - const WCHAR *str, int len, ME_Style *style, - int flags) -{ - ME_Cursor *p = &editor->pCursors[nCursor]; - - editor->bCaretAtEnd = FALSE; - - assert(p->pRun->type == diRun); - - return ME_InsertRunAtCursor(editor, p, style, str, len, flags); -} - static struct re_object* create_re_object(const REOBJECT *reo) { struct re_object *reobj = heap_alloc(sizeof(*reobj)); @@ -545,66 +502,65 @@ static struct re_object* create_re_object(const REOBJECT *reo) void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor) { - ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor); - ME_DisplayItem *di; - WCHAR space = ' '; - ME_DisplayItem *di_prev = NULL; - struct re_object *reobj_prev = NULL; - + ME_Run *run, *prev; + const WCHAR space = ' '; + struct re_object *reobj_prev = NULL; + ME_Cursor *cursor = editor->pCursors + nCursor; + ME_Style *style = style_get_insert_style( editor, cursor ); + /* FIXME no no no */ if (ME_IsSelection(editor)) ME_DeleteSelection(editor); - di = ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle, - MERF_GRAPHICS); - di->member.run.reobj = create_re_object(reo); + run = run_insert( editor, cursor, style, &space, 1, MERF_GRAPHICS ); + + run->reobj = create_re_object( reo ); - di_prev = di; - while (ME_PrevRun(NULL, &di_prev, TRUE)) + prev = run; + while ((prev = run_prev_all_paras( prev ))) { - if (di_prev->member.run.reobj) + if (prev->reobj) { - reobj_prev = di_prev->member.run.reobj; + reobj_prev = prev->reobj; break; } } if (reobj_prev) - list_add_after(&reobj_prev->entry, &di->member.run.reobj->entry); + list_add_after(&reobj_prev->entry, &run->reobj->entry); else - list_add_head(&editor->reobj_list, &di->member.run.reobj->entry); + list_add_head(&editor->reobj_list, &run->reobj->entry); - ME_ReleaseStyle(pStyle); + ME_ReleaseStyle( style ); } void ME_InsertEndRowFromCursor(ME_TextEditor *editor, int nCursor) { - ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor); - WCHAR space = ' '; + const WCHAR space = ' '; + ME_Cursor *cursor = editor->pCursors + nCursor; + ME_Style *style = style_get_insert_style( editor, cursor ); /* FIXME no no no */ if (ME_IsSelection(editor)) ME_DeleteSelection(editor); - ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle, - MERF_ENDROW); - ME_ReleaseStyle(pStyle); + run_insert( editor, cursor, style, &space, 1, MERF_ENDROW ); + + ME_ReleaseStyle( style ); } void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, - const WCHAR *str, int len, ME_Style *style) + const WCHAR *str, int len, ME_Style *style) { const WCHAR *pos; - ME_Cursor *p = NULL; + ME_Cursor *cursor = editor->pCursors + nCursor; int oldLen; /* FIXME really HERE ? */ if (ME_IsSelection(editor)) ME_DeleteSelection(editor); - /* FIXME: is this too slow? */ - /* Didn't affect performance for WM_SETTEXT (around 50sec/30K) */ oldLen = ME_GetTextLength(editor); /* text operations set modified state */ @@ -612,34 +568,35 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, assert(style); - assert(nCursor>=0 && nCursornCursors); - if (len == -1) - len = lstrlenW(str); + if (len == -1) len = lstrlenW( str ); /* grow the text limit to fit our text */ - if(editor->nTextLimit < oldLen +len) - editor->nTextLimit = oldLen + len; + if (editor->nTextLimit < oldLen + len) editor->nTextLimit = oldLen + len; pos = str; while (len) { /* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */ - while(pos - str < len && *pos != '\r' && *pos != '\n' && *pos != '\t') + while (pos - str < len && *pos != '\r' && *pos != '\n' && *pos != '\t') pos++; - if (pos != str) { /* handle text */ - ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0); - } else if (*pos == '\t') { /* handle tabs */ - WCHAR tab = '\t'; - ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB); + if (pos != str) /* handle text */ + run_insert( editor, cursor, style, str, pos - str, 0 ); + else if (*pos == '\t') /* handle tabs */ + { + const WCHAR tab = '\t'; + run_insert( editor, cursor, style, &tab, 1, MERF_TAB ); pos++; - } else { /* handle EOLs */ - ME_DisplayItem *tp, *end_run, *run, *prev; + } + else /* handle EOLs */ + { + ME_Run *end_run, *run, *prev; + ME_Paragraph *new_para; int eol_len = 0; /* Check if new line is allowed for this control */ - if (!(editor->styleFlags & ES_MULTILINE)) + if (!(editor->props & TXTBIT_MULTILINE)) break; /* Find number of CR and LF in end of paragraph run */ @@ -651,7 +608,9 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, eol_len = 3; else eol_len = 1; - } else { + } + else + { assert(*pos == '\n'); eol_len = 1; } @@ -660,9 +619,11 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, if (!editor->bEmulateVersion10 && eol_len == 3) { /* handle special \r\r\n sequence (richedit 2.x and higher only) */ - WCHAR space = ' '; - ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, style, 0); - } else { + const WCHAR space = ' '; + run_insert( editor, cursor, style, &space, 1, 0 ); + } + else + { const WCHAR cr = '\r', *eol_str = str; if (!editor->bEmulateVersion10) @@ -671,35 +632,32 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, eol_len = 1; } - p = &editor->pCursors[nCursor]; - - if (p->nOffset == p->pRun->member.run.len) + if (cursor->nOffset == cursor->run->len) { - run = ME_FindItemFwd( p->pRun, diRun ); - if (!run) run = p->pRun; + run = run_next( cursor->run ); + if (!run) run = cursor->run; } else { - if (p->nOffset) ME_SplitRunSimple(editor, p); - run = p->pRun; + if (cursor->nOffset) run_split( editor, cursor ); + run = cursor->run; } - tp = ME_SplitParagraph(editor, run, style, eol_str, eol_len, 0); - - end_run = ME_FindItemBack(tp, diRun); + new_para = para_split( editor, run, style, eol_str, eol_len, 0 ); + end_run = para_end_run( para_prev( new_para ) ); /* Move any cursors that were at the end of the previous run to the beginning of the new para */ - prev = ME_FindItemBack( end_run, diRun ); + prev = run_prev( end_run ); if (prev) { int i; for (i = 0; i < editor->nCursors; i++) { - if (editor->pCursors[i].pRun == prev && - editor->pCursors[i].nOffset == prev->member.run.len) + if (editor->pCursors[i].run == prev && + editor->pCursors[i].nOffset == prev->len) { - editor->pCursors[i].pPara = tp; - editor->pCursors[i].pRun = run; + editor->pCursors[i].para = new_para; + editor->pCursors[i].run = run; editor->pCursors[i].nOffset = 0; } } @@ -722,18 +680,18 @@ int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs, BO cursor->nOffset += nRelOfs; if (cursor->nOffset < 0) { - cursor->nOffset += cursor->pRun->member.run.nCharOfs; + cursor->nOffset += cursor->run->nCharOfs; if (cursor->nOffset >= 0) { /* new offset in the same paragraph */ do { - cursor->pRun = ME_FindItemBack(cursor->pRun, diRun); - } while (cursor->nOffset < cursor->pRun->member.run.nCharOfs); - cursor->nOffset -= cursor->pRun->member.run.nCharOfs; + cursor->run = run_prev( cursor->run ); + } while (cursor->nOffset < cursor->run->nCharOfs); + cursor->nOffset -= cursor->run->nCharOfs; return nRelOfs; } - cursor->nOffset += cursor->pPara->member.para.nCharOfs; + cursor->nOffset += cursor->para->nCharOfs; if (cursor->nOffset <= 0) { /* moved to the start of the text */ @@ -744,28 +702,29 @@ int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs, BO /* new offset in a previous paragraph */ do { - cursor->pPara = cursor->pPara->member.para.prev_para; - } while (cursor->nOffset < cursor->pPara->member.para.nCharOfs); - cursor->nOffset -= cursor->pPara->member.para.nCharOfs; - - cursor->pRun = ME_FindItemBack(cursor->pPara->member.para.next_para, diRun); - while (cursor->nOffset < cursor->pRun->member.run.nCharOfs) { - cursor->pRun = ME_FindItemBack(cursor->pRun, diRun); - } - cursor->nOffset -= cursor->pRun->member.run.nCharOfs; - } else if (cursor->nOffset >= cursor->pRun->member.run.len) { - ME_DisplayItem *next_para; + cursor->para = para_prev( cursor->para ); + } while (cursor->nOffset < cursor->para->nCharOfs); + cursor->nOffset -= cursor->para->nCharOfs; + + cursor->run = para_end_run( cursor->para ); + while (cursor->nOffset < cursor->run->nCharOfs) + cursor->run = run_prev( cursor->run ); + cursor->nOffset -= cursor->run->nCharOfs; + } + else if (cursor->nOffset >= cursor->run->len) + { + ME_Paragraph *next_para; int new_offset; new_offset = ME_GetCursorOfs(cursor); - next_para = cursor->pPara->member.para.next_para; - if (new_offset < next_para->member.para.nCharOfs) + next_para = para_next( cursor->para ); + if (new_offset < next_para->nCharOfs) { /* new offset in the same paragraph */ do { - cursor->nOffset -= cursor->pRun->member.run.len; - cursor->pRun = ME_FindItemFwd(cursor->pRun, diRun); - } while (cursor->nOffset >= cursor->pRun->member.run.len); + cursor->nOffset -= cursor->run->len; + cursor->run = run_next( cursor->run ); + } while (cursor->nOffset >= cursor->run->len); return nRelOfs; } @@ -779,16 +738,16 @@ int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs, BO /* new offset in a following paragraph */ do { - cursor->pPara = next_para; - next_para = next_para->member.para.next_para; - } while (new_offset >= next_para->member.para.nCharOfs); + cursor->para = next_para; + next_para = para_next( next_para ); + } while (new_offset >= next_para->nCharOfs); - cursor->nOffset = new_offset - cursor->pPara->member.para.nCharOfs; - cursor->pRun = ME_FindItemFwd(cursor->pPara, diRun); - while (cursor->nOffset >= cursor->pRun->member.run.len) + cursor->nOffset = new_offset - cursor->para->nCharOfs; + cursor->run = para_first_run( cursor->para ); + while (cursor->nOffset >= cursor->run->len) { - cursor->nOffset -= cursor->pRun->member.run.len; - cursor->pRun = ME_FindItemFwd(cursor->pRun, diRun); + cursor->nOffset -= cursor->run->len; + cursor->run = run_next( cursor->run ); } } /* else new offset is in the same run */ return nRelOfs; @@ -798,8 +757,8 @@ int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs, BO BOOL ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) { - ME_DisplayItem *pRun = cursor->pRun, *pOtherRun; - ME_DisplayItem *pPara = cursor->pPara; + ME_Run *run = cursor->run, *other_run; + ME_Paragraph *para = cursor->para; int nOffset = cursor->nOffset; if (nRelOfs == -1) @@ -807,40 +766,31 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) /* Backward movement */ while (TRUE) { - nOffset = ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ), - pRun->member.run.len, nOffset, WB_MOVEWORDLEFT); - if (nOffset) - break; - pOtherRun = ME_FindItemBack(pRun, diRunOrParagraph); - if (pOtherRun->type == diRun) + nOffset = ME_CallWordBreakProc( editor, get_text( run, 0 ), run->len, nOffset, WB_MOVEWORDLEFT ); + if (nOffset) break; + other_run = run_prev( run ); + if (other_run) { - if (ME_CallWordBreakProc(editor, get_text( &pOtherRun->member.run, 0 ), - pOtherRun->member.run.len, - pOtherRun->member.run.len - 1, - WB_ISDELIMITER) - && !(pRun->member.run.nFlags & MERF_ENDPARA) - && !(cursor->pRun == pRun && cursor->nOffset == 0) - && !ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ), - pRun->member.run.len, 0, - WB_ISDELIMITER)) + if (ME_CallWordBreakProc( editor, get_text( other_run, 0 ), other_run->len, other_run->len - 1, WB_ISDELIMITER ) + && !(run->nFlags & MERF_ENDPARA) + && !(cursor->run == run && cursor->nOffset == 0) + && !ME_CallWordBreakProc( editor, get_text( run, 0 ), run->len, 0, WB_ISDELIMITER )) break; - pRun = pOtherRun; - nOffset = pOtherRun->member.run.len; + run = other_run; + nOffset = other_run->len; } - else if (pOtherRun->type == diParagraph) + else { - if (cursor->pRun == pRun && cursor->nOffset == 0) + if (cursor->run == run && cursor->nOffset == 0) { - pPara = pOtherRun; + para = run->para; /* Skip empty start of table row paragraph */ - if (pPara->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART) - pPara = pPara->member.para.prev_para; + if (para_prev( para ) && para_prev( para )->nFlags & MEPF_ROWSTART) + para = para_prev( para ); /* Paragraph breaks are treated as separate words */ - if (pPara->member.para.prev_para->type == diTextStart) - return FALSE; - - pRun = ME_FindItemBack(pPara, diRun); - pPara = pPara->member.para.prev_para; + if (!para_prev( para )) return FALSE; + para = para_prev( para ); + run = para_end_run( para ); } break; } @@ -853,43 +803,35 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) while (TRUE) { - if (last_delim && !ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ), - pRun->member.run.len, nOffset, WB_ISDELIMITER)) - break; - nOffset = ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ), - pRun->member.run.len, nOffset, WB_MOVEWORDRIGHT); - if (nOffset < pRun->member.run.len) + if (last_delim && !ME_CallWordBreakProc( editor, get_text( run, 0 ), run->len, nOffset, WB_ISDELIMITER )) break; - pOtherRun = ME_FindItemFwd(pRun, diRunOrParagraphOrEnd); - if (pOtherRun->type == diRun) + nOffset = ME_CallWordBreakProc( editor, get_text( run, 0 ), run->len, nOffset, WB_MOVEWORDRIGHT ); + if (nOffset < run->len) break; + other_run = run_next( run ); + if (other_run) { - last_delim = ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ), - pRun->member.run.len, nOffset - 1, WB_ISDELIMITER); - pRun = pOtherRun; + last_delim = ME_CallWordBreakProc( editor, get_text( run, 0 ), run->len, nOffset - 1, WB_ISDELIMITER ); + run = other_run; nOffset = 0; } - else if (pOtherRun->type == diParagraph) + else { - if (pOtherRun->member.para.nFlags & MEPF_ROWSTART) - pOtherRun = pOtherRun->member.para.next_para; - if (cursor->pRun == pRun) { - pPara = pOtherRun; - pRun = ME_FindItemFwd(pPara, diRun); + para = para_next( para ); + if (!para_next( para )) + { + if (cursor->run == run) return FALSE; + nOffset = 0; + break; } - nOffset = 0; - break; - } - else /* diTextEnd */ - { - if (cursor->pRun == pRun) - return FALSE; + if (para->nFlags & MEPF_ROWSTART) para = para_next( para ); + if (cursor->run == run) run = para_first_run( para ); nOffset = 0; break; } } } - cursor->pPara = pPara; - cursor->pRun = pRun; + cursor->para = para; + cursor->run = run; cursor->nOffset = nOffset; return TRUE; } @@ -914,38 +856,28 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType) editor->pCursors[1] = editor->pCursors[0]; ME_MoveCursorWords(editor, &editor->pCursors[1], -1); break; - case stLine: case stParagraph: - { - ME_DisplayItem *pItem; - ME_DIType fwdSearchType, backSearchType; - if (selectionType == stParagraph) { - backSearchType = diParagraph; - fwdSearchType = diParagraphOrEnd; - } else { - backSearchType = diStartRow; - fwdSearchType = diStartRowOrParagraphOrEnd; - } - pItem = ME_FindItemFwd(editor->pCursors[0].pRun, fwdSearchType); - assert(pItem); - if (pItem->type == diTextEnd) - editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun); - else - editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun); - editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun); - editor->pCursors[0].nOffset = 0; + editor->pCursors[1] = editor->pCursors[0]; + + editor->pCursors[0].run = para_end_run( editor->pCursors[0].para ); + editor->pCursors[0].para = editor->pCursors[0].run->para; + editor->pCursors[0].nOffset = editor->pCursors[0].run->len; - pItem = ME_FindItemBack(pItem, backSearchType); - editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun); - editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun); + editor->pCursors[1].run = para_first_run( editor->pCursors[1].para ); editor->pCursors[1].nOffset = 0; break; + case stLine: + { + ME_Row *row = row_from_cursor( editor->pCursors ); + + row_first_cursor( row, editor->pCursors + 1 ); + row_end_cursor( row, editor->pCursors, TRUE ); + break; } case stDocument: /* Select everything with cursor anchored from the start of the text */ - editor->nSelectionType = stDocument; ME_SetCursorToStart(editor, &editor->pCursors[1]); - ME_SetCursorToEnd(editor, &editor->pCursors[0], FALSE); + ME_SetCursorToEnd(editor, &editor->pCursors[0], TRUE); break; default: assert(0); } @@ -956,90 +888,81 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType) int ME_GetCursorOfs(const ME_Cursor *cursor) { - return cursor->pPara->member.para.nCharOfs - + cursor->pRun->member.run.nCharOfs + cursor->nOffset; + return cursor->para->nCharOfs + cursor->run->nCharOfs + cursor->nOffset; } -/* Helper function for ME_FindPixelPos to find paragraph within tables */ -static ME_DisplayItem* ME_FindPixelPosInTableRow(int x, int y, - ME_DisplayItem *para) +/* Helper function for cursor_from_virtual_coords() to find paragraph within tables */ +static ME_Paragraph *pixel_pos_in_table_row( int x, int y, ME_Paragraph *para ) { - ME_DisplayItem *cell, *next_cell; - assert(para->member.para.nFlags & MEPF_ROWSTART); - cell = para->member.para.next_para->member.para.pCell; - assert(cell); + ME_Cell *cell, *next_cell; + + assert( para->nFlags & MEPF_ROWSTART ); + cell = table_row_first_cell( para ); + assert( cell ); /* find the cell we are in */ - while ((next_cell = cell->member.cell.next_cell) != NULL) { - if (x < next_cell->member.cell.pt.x) + while ((next_cell = cell_next( cell )) != NULL) + { + if (x < next_cell->pt.x) { - para = ME_FindItemFwd(cell, diParagraph); + para = cell_first_para( cell ); /* Found the cell, but there might be multiple paragraphs in * the cell, so need to search down the cell for the paragraph. */ - while (cell == para->member.para.pCell) { - if (y < para->member.para.pt.y + para->member.para.nHeight) + while (cell == para_cell( para )) + { + if (y < para->pt.y + para->nHeight) { - if (para->member.para.nFlags & MEPF_ROWSTART) - return ME_FindPixelPosInTableRow(x, y, para); - else - return para; + if (para->nFlags & MEPF_ROWSTART) return pixel_pos_in_table_row( x, y, para ); + else return para; } - para = para->member.para.next_para; + para = para_next( para ); } /* Past the end of the cell, so go back to the last cell paragraph */ - return para->member.para.prev_para; + return para_prev( para ); } cell = next_cell; } /* Return table row delimiter */ - para = ME_FindItemFwd(cell, diParagraph); - assert(para->member.para.nFlags & MEPF_ROWEND); - assert(para->member.para.fmt.dwMask & PFM_TABLEROWDELIMITER); - assert(para->member.para.fmt.wEffects & PFE_TABLEROWDELIMITER); + para = table_row_end( para ); + assert( para->nFlags & MEPF_ROWEND ); + assert( para->fmt.dwMask & PFM_TABLEROWDELIMITER ); + assert( para->fmt.wEffects & PFE_TABLEROWDELIMITER ); return para; } -static BOOL ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pRow, - int x, ME_Cursor *cursor, BOOL *pbCaretAtEnd) +static BOOL row_cursor( ME_TextEditor *editor, ME_Row *row, int x, + ME_Cursor *cursor ) { - ME_DisplayItem *pNext, *pLastRun; - ME_Row *row = &pRow->member.row; - BOOL exact = TRUE; + ME_Run *run, *last; + BOOL exact = TRUE; - if (x < row->pt.x) - { - x = row->pt.x; - exact = FALSE; - } - pNext = ME_FindItemFwd(pRow, diRunOrStartRow); - assert(pNext->type == diRun); - if (pbCaretAtEnd) *pbCaretAtEnd = FALSE; - cursor->nOffset = 0; - do { - int run_x = pNext->member.run.pt.x; - int width = pNext->member.run.nWidth; - - if (x >= run_x && x < run_x+width) + if (x < row->pt.x) { - cursor->nOffset = ME_CharFromPoint(editor, x-run_x, &pNext->member.run, TRUE, TRUE); - cursor->pRun = pNext; - cursor->pPara = ME_GetParagraph( cursor->pRun ); - return exact; + x = row->pt.x; + exact = FALSE; } - pLastRun = pNext; - pNext = ME_FindItemFwd(pNext, diRunOrStartRow); - } while(pNext && pNext->type == diRun); - if ((pLastRun->member.run.nFlags & MERF_ENDPARA) == 0) - { - cursor->pRun = ME_FindItemFwd(pNext, diRun); - if (pbCaretAtEnd) *pbCaretAtEnd = TRUE; - } - else - cursor->pRun = pLastRun; + run = row_first_run( row ); + assert( run ); + cursor->nOffset = 0; + do + { + if (x >= run->pt.x && x < run->pt.x + run->nWidth) + { + cursor->nOffset = ME_CharFromPoint( editor, x - run->pt.x, run, TRUE, TRUE ); + cursor->run = run; + cursor->para = run->para; + return exact; + } + last = run; + run = row_next_run( row, run ); + } while (run); - cursor->pPara = ME_GetParagraph( cursor->pRun ); - return FALSE; + run = last; + + cursor->run = run; + cursor->para = run->para; + return FALSE; } /* Finds the run and offset from the pixel position. @@ -1052,57 +975,51 @@ static BOOL ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pRow, * returns TRUE if the result was exactly under the cursor, otherwise returns * FALSE, and result is set to the closest position to the coordinates. */ -static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y, - ME_Cursor *result, BOOL *is_eol, BOOL final_eop) +static BOOL cursor_from_virtual_coords( ME_TextEditor *editor, int x, int y, + ME_Cursor *result, BOOL final_eop ) { - ME_DisplayItem *p = editor->pBuffer->pFirst->member.para.next_para; + ME_Paragraph *para = editor_first_para( editor ); + ME_Row *row = NULL, *next_row; BOOL isExact = TRUE; x -= editor->rcFormat.left; y -= editor->rcFormat.top; - if (is_eol) - *is_eol = FALSE; - /* find paragraph */ - for (; p != editor->pBuffer->pLast; p = p->member.para.next_para) + for (; para_next( para ); para = para_next( para )) { - assert(p->type == diParagraph); - if (y < p->member.para.pt.y + p->member.para.nHeight) + if (y < para->pt.y + para->nHeight) { - if (p->member.para.nFlags & MEPF_ROWSTART) - p = ME_FindPixelPosInTableRow(x, y, p); - y -= p->member.para.pt.y; - p = ME_FindItemFwd(p, diStartRow); + if (para->nFlags & MEPF_ROWSTART) + para = pixel_pos_in_table_row( x, y, para ); + y -= para->pt.y; + row = para_first_row( para ); break; - } else if (p->member.para.nFlags & MEPF_ROWSTART) { - p = ME_GetTableRowEnd(p); + } + else if (para->nFlags & MEPF_ROWSTART) + { + para = table_row_end( para ); } } /* find row */ - for (; p != editor->pBuffer->pLast; ) + while (row) { - ME_DisplayItem *pp; - assert(p->type == diStartRow); - if (y < p->member.row.pt.y + p->member.row.nHeight) break; - pp = ME_FindItemFwd(p, diStartRow); - if (!pp) break; - p = pp; + if (y < row->pt.y + row->nHeight) break; + next_row = row_next( row ); + if (!next_row) break; + row = next_row; } - if (p == editor->pBuffer->pLast && !final_eop) + + if (!row && !final_eop && para_prev( para )) { /* The position is below the last paragraph, so the last row will be used * rather than the end of the text, so the x position will be used to * determine the offset closest to the pixel position. */ isExact = FALSE; - p = ME_FindItemBack(p, diStartRow); - if (!p) p = editor->pBuffer->pLast; + row = para_end_row( para_prev( para ) ); } - assert( p->type == diStartRow || p == editor->pBuffer->pLast ); - - if( p->type == diStartRow ) - return ME_FindRunInRow( editor, p, x, result, is_eol ) && isExact; + if (row) return row_cursor( editor, row, x, result ) && isExact; ME_SetCursorToEnd(editor, result, TRUE); return FALSE; @@ -1132,7 +1049,7 @@ BOOL ME_CharFromPos(ME_TextEditor *editor, int x, int y, } x += editor->horz_si.nPos; y += editor->vert_si.nPos; - bResult = ME_FindPixelPos(editor, x, y, cursor, NULL, FALSE); + bResult = cursor_from_virtual_coords( editor, x, y, cursor, FALSE ); if (isExact) *isExact = bResult; return TRUE; } @@ -1166,37 +1083,53 @@ static void ME_ExtendAnchorSelection(ME_TextEditor *editor) { /* Extend the left side of selection */ editor->pCursors[1] = tmp_cursor; - if (editor->nSelectionType == stWord) + switch (editor->nSelectionType) + { + case stWord: ME_MoveCursorWords(editor, &editor->pCursors[1], -1); - else + break; + + case stLine: { - ME_DisplayItem *pItem; - ME_DIType searchType = ((editor->nSelectionType == stLine) ? - diStartRowOrParagraph:diParagraph); - pItem = ME_FindItemBack(editor->pCursors[1].pRun, searchType); - editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun); - editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun); + ME_Row *row = row_from_cursor( editor->pCursors + 1 ); + row_first_cursor( row, editor->pCursors + 1 ); + break; + } + + case stParagraph: + editor->pCursors[1].run = para_first_run( editor->pCursors[1].para ); editor->pCursors[1].nOffset = 0; + break; + + default: + break; } } else if (curOfs >= anchorEndOfs) { /* Extend the right side of selection */ editor->pCursors[0] = tmp_cursor; - if (editor->nSelectionType == stWord) - ME_MoveCursorWords(editor, &editor->pCursors[0], +1); - else + switch (editor->nSelectionType) { - ME_DisplayItem *pItem; - ME_DIType searchType = ((editor->nSelectionType == stLine) ? - diStartRowOrParagraphOrEnd:diParagraphOrEnd); - pItem = ME_FindItemFwd(editor->pCursors[0].pRun, searchType); - if (pItem->type == diTextEnd) - editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun); - else - editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun); - editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun); - editor->pCursors[0].nOffset = 0; + case stWord: + ME_MoveCursorWords( editor, &editor->pCursors[0], +1 ); + break; + + case stLine: + { + ME_Row *row = row_from_cursor( editor->pCursors ); + row_end_cursor( row, editor->pCursors, TRUE ); + break; + } + + case stParagraph: + editor->pCursors[0].run = para_end_run( editor->pCursors[0].para ); + editor->pCursors[0].para = editor->pCursors[0].run->para; + editor->pCursors[0].nOffset = editor->pCursors[0].run->len; + break; + + default: + break; } } } @@ -1215,7 +1148,7 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum) is_selection = ME_IsSelection(editor); is_shift = GetKeyState(VK_SHIFT) < 0; - ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd, FALSE); + cursor_from_virtual_coords( editor, x, y, &editor->pCursors[0], FALSE ); if (x >= editor->rcFormat.left || is_shift) { @@ -1273,8 +1206,8 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y) y += editor->vert_si.nPos; tmp_cursor = editor->pCursors[0]; - /* FIXME: do something with the return value of ME_FindPixelPos */ - ME_FindPixelPos(editor, x, y, &tmp_cursor, &editor->bCaretAtEnd, TRUE); + /* FIXME: do something with the return value of cursor_from_virtual_coords */ + cursor_from_virtual_coords( editor, x, y, &tmp_cursor, TRUE ); ME_InvalidateSelection(editor); editor->pCursors[0] = tmp_cursor; @@ -1282,13 +1215,11 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y) if (editor->nSelectionType != stPosition && memcmp(&editor->pCursors[1], &editor->pCursors[3], sizeof(ME_Cursor))) - { /* The scroll the cursor towards the other end, since it was the one * extended by ME_ExtendAnchorSelection */ - ME_EnsureVisible(editor, &editor->pCursors[1]); - } else { - ME_EnsureVisible(editor, &editor->pCursors[0]); - } + editor_ensure_visible( editor, &editor->pCursors[1] ); + else + editor_ensure_visible( editor, &editor->pCursors[0] ); ME_InvalidateSelection(editor); update_caret(editor); @@ -1297,287 +1228,178 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y) static int ME_GetXForArrow(ME_TextEditor *editor, ME_Cursor *pCursor) { - ME_DisplayItem *pRun = pCursor->pRun; + ME_Run *run = pCursor->run; int x; if (editor->nUDArrowX != -1) x = editor->nUDArrowX; - else { - if (editor->bCaretAtEnd) - { - pRun = ME_FindItemBack(pRun, diRun); - assert(pRun); - x = pRun->member.run.pt.x + pRun->member.run.nWidth; - } - else { - x = pRun->member.run.pt.x; - x += ME_PointFromChar(editor, &pRun->member.run, pCursor->nOffset, TRUE); - } + else + { + x = run->pt.x; + x += ME_PointFromChar( editor, run, pCursor->nOffset, TRUE ); editor->nUDArrowX = x; } return x; } -static void -ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs, BOOL extend) +static void cursor_move_line( ME_TextEditor *editor, ME_Cursor *cursor, BOOL up, BOOL extend ) { - ME_DisplayItem *pRun = pCursor->pRun; - ME_DisplayItem *pOldPara = pCursor->pPara; - ME_DisplayItem *pItem, *pNewPara; - int x = ME_GetXForArrow(editor, pCursor); - - if (editor->bCaretAtEnd && !pCursor->nOffset) - if (!ME_PrevRun(&pOldPara, &pRun, TRUE)) - return; + ME_Paragraph *old_para = cursor->para, *new_para; + ME_Row *row = row_from_cursor( cursor ); + int x = ME_GetXForArrow( editor, cursor ); - if (nRelOfs == -1) - { - /* start of this row */ - pItem = ME_FindItemBack(pRun, diStartRow); - assert(pItem); - /* start of the previous row */ - pItem = ME_FindItemBack(pItem, diStartRow); - if (!pItem) /* row not found */ - { - if (extend) - ME_SetCursorToStart(editor, pCursor); - return; - } - pNewPara = ME_GetParagraph(pItem); - if (pOldPara->member.para.nFlags & MEPF_ROWEND || - (pOldPara->member.para.pCell && - pOldPara->member.para.pCell != pNewPara->member.para.pCell)) - { - /* Brought out of a cell */ - pNewPara = ME_GetTableRowStart(pOldPara)->member.para.prev_para; - if (pNewPara->type == diTextStart) - return; /* At the top, so don't go anywhere. */ - pItem = ME_FindItemFwd(pNewPara, diStartRow); - } - if (pNewPara->member.para.nFlags & MEPF_ROWEND) + if (up) { - /* Brought into a table row */ - ME_Cell *cell = &ME_FindItemBack(pNewPara, diCell)->member.cell; - while (x < cell->pt.x && cell->prev_cell) - cell = &cell->prev_cell->member.cell; - if (cell->next_cell) /* else - we are still at the end of the row */ - pItem = ME_FindItemBack(cell->next_cell, diStartRow); - } - } - else - { - /* start of the next row */ - pItem = ME_FindItemFwd(pRun, diStartRow); - if (!pItem) /* row not found */ - { - if (extend) - ME_SetCursorToEnd(editor, pCursor, TRUE); - return; - } - pNewPara = ME_GetParagraph(pItem); - if (pOldPara->member.para.nFlags & MEPF_ROWSTART || - (pOldPara->member.para.pCell && - pOldPara->member.para.pCell != pNewPara->member.para.pCell)) - { - /* Brought out of a cell */ - pNewPara = ME_GetTableRowEnd(pOldPara)->member.para.next_para; - if (pNewPara->type == diTextEnd) - return; /* At the bottom, so don't go anywhere. */ - pItem = ME_FindItemFwd(pNewPara, diStartRow); + /* start of the previous row */ + row = row_prev_all_paras( row ); + if (!row) + { + if (extend) ME_SetCursorToStart( editor, cursor ); + return; + } + new_para = row_para( row ); + if (old_para->nFlags & MEPF_ROWEND || + (para_cell( old_para ) && para_cell( old_para ) != para_cell( new_para ))) + { + /* Brought out of a cell */ + new_para = para_prev( table_row_start( old_para )); + if (!new_para) return; /* At the top, so don't go anywhere. */ + row = para_first_row( new_para ); + } + if (new_para->nFlags & MEPF_ROWEND) + { + /* Brought into a table row */ + ME_Cell *cell = table_row_end_cell( new_para ); + while (x < cell->pt.x && cell_prev( cell )) + cell = cell_prev( cell ); + if (cell_next( cell )) /* else - we are still at the end of the row */ + row = para_end_row( cell_end_para( cell ) ); + } } - if (pNewPara->member.para.nFlags & MEPF_ROWSTART) + else { - /* Brought into a table row */ - ME_DisplayItem *cell = ME_FindItemFwd(pNewPara, diCell); - while (cell->member.cell.next_cell && - x >= cell->member.cell.next_cell->member.cell.pt.x) - cell = cell->member.cell.next_cell; - pItem = ME_FindItemFwd(cell, diStartRow); + /* start of the next row */ + row = row_next_all_paras( row ); + if (!row) + { + if (extend) ME_SetCursorToEnd( editor, cursor, TRUE ); + return; + } + new_para = row_para( row ); + if (old_para->nFlags & MEPF_ROWSTART || + (para_cell( old_para ) && para_cell( old_para ) != para_cell( new_para ))) + { + /* Brought out of a cell */ + new_para = para_next( table_row_end( old_para ) ); + if (!para_next( new_para )) return; /* At the bottom, so don't go anywhere. */ + row = para_first_row( new_para ); + } + if (new_para->nFlags & MEPF_ROWSTART) + { + /* Brought into a table row */ + ME_Cell *cell = table_row_first_cell( new_para ); + while (cell_next( cell ) && x >= cell_next( cell )->pt.x) + cell = cell_next( cell ); + row = para_first_row( cell_first_para( cell ) ); + } } - } - if (!pItem) - { - /* row not found - ignore */ - return; - } - ME_FindRunInRow(editor, pItem, x, pCursor, &editor->bCaretAtEnd); - assert(pCursor->pRun); - assert(pCursor->pRun->type == diRun); + if (!row) return; + + row_cursor( editor, row, x, cursor ); } -static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowPageUp( ME_TextEditor *editor, ME_Cursor *cursor ) { - ME_DisplayItem *p = ME_FindItemFwd(editor->pBuffer->pFirst, diStartRow); + ME_Row *row = para_first_row( editor_first_para( editor ) ), *last_row; + int x, yd, old_scroll_pos = editor->vert_si.nPos; - if (editor->vert_si.nPos < p->member.row.nHeight) - { - ME_SetCursorToStart(editor, pCursor); - editor->bCaretAtEnd = FALSE; - /* Native clears seems to clear this x value on page up at the top - * of the text, but not on page down at the end of the text. - * Doesn't make sense, but we try to be bug for bug compatible. */ - editor->nUDArrowX = -1; - } else { - ME_DisplayItem *pRun = pCursor->pRun; - ME_DisplayItem *pLast; - int x, y, yd, yp; - int yOldScrollPos = editor->vert_si.nPos; - - x = ME_GetXForArrow(editor, pCursor); - if (!pCursor->nOffset && editor->bCaretAtEnd) - pRun = ME_FindItemBack(pRun, diRun); - - p = ME_FindItemBack(pRun, diStartRowOrParagraph); - assert(p->type == diStartRow); - yp = ME_FindItemBack(p, diParagraph)->member.para.pt.y; - y = yp + p->member.row.pt.y; + if (editor->vert_si.nPos < row->nHeight) + { + ME_SetCursorToStart( editor, cursor ); + /* Native clears seems to clear this x value on page up at the top + * of the text, but not on page down at the end of the text. + * Doesn't make sense, but we try to be bug for bug compatible. */ + editor->nUDArrowX = -1; + } + else + { + x = ME_GetXForArrow( editor, cursor ); + row = row_from_cursor( cursor ); - ME_ScrollUp(editor, editor->sizeWindow.cy); - /* Only move the cursor by the amount scrolled. */ - yd = y + editor->vert_si.nPos - yOldScrollPos; - pLast = p; + ME_ScrollUp( editor, editor->sizeWindow.cy ); + /* Only move the cursor by the amount scrolled. */ + yd = cursor->para->pt.y + row->pt.y + editor->vert_si.nPos - old_scroll_pos; + last_row = row; - do { - p = ME_FindItemBack(p, diStartRowOrParagraph); - if (!p) - break; - if (p->type == diParagraph) { /* crossing paragraphs */ - if (p->member.para.prev_para == NULL) - break; - yp = p->member.para.prev_para->member.para.pt.y; - continue; - } - y = yp + p->member.row.pt.y; - if (y < yd) - break; - pLast = p; - } while(1); + while ((row = row_prev_all_paras( row ))) + { + if (row_para( row )->pt.y + row->pt.y < yd) break; + last_row = row; + } - ME_FindRunInRow(editor, pLast, x, pCursor, &editor->bCaretAtEnd); - } - assert(pCursor->pRun); - assert(pCursor->pRun->type == diRun); + row_cursor( editor, last_row, x, cursor ); + } } -static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowPageDown( ME_TextEditor *editor, ME_Cursor *cursor ) { - ME_DisplayItem *pLast; - int x, y; + ME_Row *row = para_end_row( para_prev( editor_end_para( editor ) ) ), *last_row; + int x, yd, old_scroll_pos = editor->vert_si.nPos; - /* Find y position of the last row */ - pLast = editor->pBuffer->pLast; - y = pLast->member.para.prev_para->member.para.pt.y - + ME_FindItemBack(pLast, diStartRow)->member.row.pt.y; + x = ME_GetXForArrow( editor, cursor ); - x = ME_GetXForArrow(editor, pCursor); + if (editor->vert_si.nPos >= row_para( row )->pt.y + row->pt.y - editor->sizeWindow.cy) + ME_SetCursorToEnd( editor, cursor, FALSE ); + else + { + row = row_from_cursor( cursor ); - if (editor->vert_si.nPos >= y - editor->sizeWindow.cy) - { - ME_SetCursorToEnd(editor, pCursor, FALSE); - editor->bCaretAtEnd = FALSE; - } else { - ME_DisplayItem *pRun = pCursor->pRun; - ME_DisplayItem *p; - int yd, yp; - int yOldScrollPos = editor->vert_si.nPos; - - if (!pCursor->nOffset && editor->bCaretAtEnd) - pRun = ME_FindItemBack(pRun, diRun); - - p = ME_FindItemBack(pRun, diStartRowOrParagraph); - assert(p->type == diStartRow); - yp = ME_FindItemBack(p, diParagraph)->member.para.pt.y; - y = yp + p->member.row.pt.y; - - /* For native richedit controls: - * v1.0 - v3.1 can only scroll down as far as the scrollbar lets us - * v4.1 can scroll past this position here. */ - ME_ScrollDown(editor, editor->sizeWindow.cy); - /* Only move the cursor by the amount scrolled. */ - yd = y + editor->vert_si.nPos - yOldScrollPos; - pLast = p; + /* For native richedit controls: + * v1.0 - v3.1 can only scroll down as far as the scrollbar lets us + * v4.1 can scroll past this position here. */ + ME_ScrollDown( editor, editor->sizeWindow.cy ); + /* Only move the cursor by the amount scrolled. */ + yd = cursor->para->pt.y + row->pt.y + editor->vert_si.nPos - old_scroll_pos; + last_row = row; - do { - p = ME_FindItemFwd(p, diStartRowOrParagraph); - if (!p) - break; - if (p->type == diParagraph) { - yp = p->member.para.pt.y; - continue; - } - y = yp + p->member.row.pt.y; - if (y >= yd) - break; - pLast = p; - } while(1); + while ((row = row_next_all_paras( row ))) + { + if (row_para( row )->pt.y + row->pt.y >= yd) break; + last_row = row; + } - ME_FindRunInRow(editor, pLast, x, pCursor, &editor->bCaretAtEnd); - } - assert(pCursor->pRun); - assert(pCursor->pRun->type == diRun); + row_cursor( editor, last_row, x, cursor ); + } } -static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowHome( ME_TextEditor *editor, ME_Cursor *cursor ) { - ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow); - if (pRow) { - ME_DisplayItem *pRun; - if (editor->bCaretAtEnd && !pCursor->nOffset) { - pRow = ME_FindItemBack(pRow, diStartRow); - if (!pRow) - return; - } - pRun = ME_FindItemFwd(pRow, diRun); - if (pRun) { - pCursor->pRun = pRun; - assert(pCursor->pPara == ME_GetParagraph(pRun)); - pCursor->nOffset = 0; - } - } - editor->bCaretAtEnd = FALSE; + ME_Row *row = row_from_cursor( cursor ); + + row_first_cursor( row, cursor ); } static void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_SetCursorToStart(editor, pCursor); - editor->bCaretAtEnd = FALSE; } -static void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowEnd( ME_TextEditor *editor, ME_Cursor *cursor ) { - ME_DisplayItem *pRow; - - if (editor->bCaretAtEnd && !pCursor->nOffset) - return; - - pRow = ME_FindItemFwd(pCursor->pRun, diStartRowOrParagraphOrEnd); - assert(pRow); - if (pRow->type == diStartRow) { - ME_DisplayItem *pRun = ME_FindItemFwd(pRow, diRun); - assert(pRun); - pCursor->pRun = pRun; - assert(pCursor->pPara == ME_GetParagraph(pCursor->pRun)); - pCursor->nOffset = 0; - editor->bCaretAtEnd = TRUE; - return; - } - pCursor->pRun = ME_FindItemBack(pRow, diRun); - assert(pCursor->pRun && pCursor->pRun->member.run.nFlags & MERF_ENDPARA); - assert(pCursor->pPara == ME_GetParagraph(pCursor->pRun)); - pCursor->nOffset = 0; - editor->bCaretAtEnd = FALSE; + ME_Row *row = row_from_cursor( cursor ); + + row_end_cursor( row, cursor, FALSE ); } static void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_SetCursorToEnd(editor, pCursor, FALSE); - editor->bCaretAtEnd = FALSE; } BOOL ME_IsSelection(ME_TextEditor *editor) { - return editor->pCursors[0].pRun != editor->pCursors[1].pRun || + return editor->pCursors[0].run != editor->pCursors[1].run || editor->pCursors[0].nOffset != editor->pCursors[1].nOffset; } @@ -1592,7 +1414,7 @@ void ME_DeleteSelection(ME_TextEditor *editor) ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor) { - return ME_GetInsertStyle(editor, 0); + return style_get_insert_style( editor, editor->pCursors ); } void ME_SendSelChange(ME_TextEditor *editor) @@ -1637,24 +1459,22 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl) ME_CheckCharOffsets(editor); switch(nVKey) { case VK_LEFT: - editor->bCaretAtEnd = FALSE; if (ctrl) success = ME_MoveCursorWords(editor, &tmp_curs, -1); else success = ME_MoveCursorChars(editor, &tmp_curs, -1, extend); break; case VK_RIGHT: - editor->bCaretAtEnd = FALSE; if (ctrl) success = ME_MoveCursorWords(editor, &tmp_curs, +1); else success = ME_MoveCursorChars(editor, &tmp_curs, +1, extend); break; case VK_UP: - ME_MoveCursorLines(editor, &tmp_curs, -1, extend); + cursor_move_line( editor, &tmp_curs, TRUE, extend ); break; case VK_DOWN: - ME_MoveCursorLines(editor, &tmp_curs, +1, extend); + cursor_move_line( editor, &tmp_curs, FALSE, extend ); break; case VK_PRIOR: ME_ArrowPageUp(editor, &tmp_curs); @@ -1667,7 +1487,6 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl) ME_ArrowCtrlHome(editor, &tmp_curs); else ME_ArrowHome(editor, &tmp_curs); - editor->bCaretAtEnd = FALSE; break; } case VK_END: @@ -1685,7 +1504,7 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl) ME_InvalidateSelection(editor); ME_Repaint(editor); hide_caret(editor); - ME_EnsureVisible(editor, &tmp_curs); + editor_ensure_visible( editor, &tmp_curs ); update_caret(editor); ME_SendSelChange(editor); return success; diff --git a/dll/win32/riched20/clipboard.c b/dll/win32/riched20/clipboard.c index 578fb02fd99..10a814214be 100644 --- a/dll/win32/riched20/clipboard.c +++ b/dll/win32/riched20/clipboard.c @@ -344,13 +344,12 @@ static HGLOBAL get_unicode_text(ME_TextEditor *editor, const ME_Cursor *start, i int pars = 0; WCHAR *data; HANDLE ret; - ME_DisplayItem *para; + ME_Paragraph *para; int nEnd = ME_GetCursorOfs(start) + nChars; /* count paragraphs in range */ - para = start->pPara; - while((para = para->member.para.next_para) && - para->member.para.nCharOfs <= nEnd) + para = start->para; + while ((para = para_next( para )) && para->nCharOfs <= nEnd) pars++; ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR) * (nChars + pars + 1)); diff --git a/dll/win32/riched20/editor.c b/dll/win32/riched20/editor.c index cbc959851ec..a7794ab7901 100644 --- a/dll/win32/riched20/editor.c +++ b/dll/win32/riched20/editor.c @@ -250,24 +250,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); -static BOOL ME_RegisterEditorClass(HINSTANCE); static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, ME_Cursor *start, int nChars); -static const WCHAR REListBox20W[] = {'R','E','L','i','s','t','B','o','x','2','0','W', 0}; -static const WCHAR REComboBox20W[] = {'R','E','C','o','m','b','o','B','o','x','2','0','W', 0}; -static HCURSOR hLeft; - +HINSTANCE dll_instance = NULL; BOOL me_debug = FALSE; HANDLE me_heap = NULL; -static BOOL ME_ListBoxRegistered = FALSE; -static BOOL ME_ComboBoxRegistered = FALSE; - -static inline BOOL is_version_nt(void) -{ - return !(GetVersion() & 0x80000000); -} - static ME_TextBuffer *ME_MakeText(void) { ME_TextBuffer *buf = heap_alloc(sizeof(*buf)); ME_DisplayItem *p1 = ME_MakeDI(diTextStart); @@ -288,6 +276,21 @@ static ME_TextBuffer *ME_MakeText(void) { return buf; } +ME_Paragraph *editor_first_para( ME_TextEditor *editor ) +{ + return para_next( &editor->pBuffer->pFirst->member.para ); +} + +/* Note, returns the diTextEnd sentinel paragraph */ +ME_Paragraph *editor_end_para( ME_TextEditor *editor ) +{ + return &editor->pBuffer->pLast->member.para; +} + +static BOOL editor_beep( ME_TextEditor *editor, UINT type ) +{ + return editor->props & TXTBIT_ALLOWBEEP && MessageBeep( type ); +} static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, ME_InStream *stream, ME_Style *style) { @@ -583,27 +586,29 @@ void ME_RTFParAttrHook(RTF_Info *info) if (!info->editor->bEmulateVersion10) /* v4.1 */ { - if (info->tableDef && info->tableDef->tableRowStart && - info->tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) + if (info->tableDef && info->tableDef->row_start && + info->tableDef->row_start->nFlags & MEPF_ROWEND) { ME_Cursor cursor; - ME_DisplayItem *para; + ME_Paragraph *para; /* We are just after a table row. */ RTFFlushOutputBuffer(info); cursor = info->editor->pCursors[0]; - para = cursor.pPara; - if (para == info->tableDef->tableRowStart->member.para.next_para - && !cursor.nOffset && !cursor.pRun->member.run.nCharOfs) + para = cursor.para; + if (para == para_next( info->tableDef->row_start ) + && !cursor.nOffset && !cursor.run->nCharOfs) { /* Since the table row end, no text has been inserted, and the \intbl * control word has not be used. We can confirm that we are not in a * table anymore. */ - info->tableDef->tableRowStart = NULL; + info->tableDef->row_start = NULL; info->canInheritInTbl = FALSE; } } - } else { /* v1.0 - v3.0 */ + } + else /* v1.0 - v3.0 */ + { info->fmt.dwMask |= PFM_TABLE; info->fmt.wEffects &= ~PFE_TABLE; } @@ -611,26 +616,25 @@ void ME_RTFParAttrHook(RTF_Info *info) case rtfNestLevel: if (!info->editor->bEmulateVersion10) /* v4.1 */ { - while (info->rtfParam > info->nestingLevel) { + while (info->rtfParam > info->nestingLevel) + { RTFTable *tableDef = heap_alloc_zero(sizeof(*tableDef)); tableDef->parent = info->tableDef; info->tableDef = tableDef; RTFFlushOutputBuffer(info); - if (tableDef->tableRowStart && - tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) + if (tableDef->row_start && tableDef->row_start->nFlags & MEPF_ROWEND) + { + ME_Paragraph *para = para_next( tableDef->row_start ); + tableDef->row_start = table_insert_row_start_at_para( info->editor, para ); + } + else { - ME_DisplayItem *para = tableDef->tableRowStart; - para = para->member.para.next_para; - para = ME_InsertTableRowStartAtParagraph(info->editor, para); - tableDef->tableRowStart = para; - } else { ME_Cursor cursor; - WCHAR endl = '\r'; cursor = info->editor->pCursors[0]; - if (cursor.nOffset || cursor.pRun->member.run.nCharOfs) - ME_InsertTextFromCursor(info->editor, 0, &endl, 1, info->style); - tableDef->tableRowStart = ME_InsertTableRowStartFromCursor(info->editor); + if (cursor.nOffset || cursor.run->nCharOfs) + ME_InsertTextFromCursor(info->editor, 0, L"\r", 1, info->style); + tableDef->row_start = table_insert_row_start( info->editor, info->editor->pCursors ); } info->nestingLevel++; @@ -645,25 +649,19 @@ void ME_RTFParAttrHook(RTF_Info *info) if (info->nestingLevel < 1) { RTFTable *tableDef; + ME_Paragraph *para; + if (!info->tableDef) info->tableDef = heap_alloc_zero(sizeof(*info->tableDef)); tableDef = info->tableDef; RTFFlushOutputBuffer(info); - if (tableDef->tableRowStart && - tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) - { - ME_DisplayItem *para = tableDef->tableRowStart; - para = para->member.para.next_para; - para = ME_InsertTableRowStartAtParagraph(info->editor, para); - tableDef->tableRowStart = para; - } else { - ME_Cursor cursor; - WCHAR endl = '\r'; - cursor = info->editor->pCursors[0]; - if (cursor.nOffset || cursor.pRun->member.run.nCharOfs) - ME_InsertTextFromCursor(info->editor, 0, &endl, 1, info->style); - tableDef->tableRowStart = ME_InsertTableRowStartFromCursor(info->editor); - } + if (tableDef->row_start && tableDef->row_start->nFlags & MEPF_ROWEND) + para = para_next( tableDef->row_start ); + else + para = info->editor->pCursors[0].para; + + tableDef->row_start = table_insert_row_start_at_para( info->editor, para ); + info->nestingLevel = 1; info->canInheritInTbl = TRUE; } @@ -680,7 +678,7 @@ void ME_RTFParAttrHook(RTF_Info *info) { PARAFORMAT2 fmt; fmt.cbSize = sizeof(fmt); - ME_GetSelectionParaFormat(info->editor, &fmt); + editor_get_selection_para_fmt( info->editor, &fmt ); info->fmt.dwMask |= PFM_STARTINDENT | PFM_OFFSET; info->fmt.dxStartIndent = fmt.dxStartIndent; info->fmt.dxOffset = fmt.dxOffset; @@ -715,7 +713,7 @@ void ME_RTFParAttrHook(RTF_Info *info) { PARAFORMAT2 fmt; fmt.cbSize = sizeof(fmt); - ME_GetSelectionParaFormat(info->editor, &fmt); + editor_get_selection_para_fmt( info->editor, &fmt ); memcpy(info->fmt.rgxTabs, fmt.rgxTabs, fmt.cTabCount * sizeof(fmt.rgxTabs[0])); info->fmt.cTabCount = fmt.cTabCount; @@ -899,13 +897,13 @@ void ME_RTFTblAttrHook(RTF_Info *info) if (cellNum >= MAX_TABLE_CELLS) break; info->tableDef->cells[cellNum].rightBoundary = info->rtfParam; - if (cellNum < MAX_TAB_STOPS) { + if (cellNum < MAX_TAB_STOPS) + { /* Tab stops were used to store cell positions before v4.1 but v4.1 * still seems to set the tabstops without using them. */ - ME_DisplayItem *para = info->editor->pCursors[0].pPara; - PARAFORMAT2 *pFmt = ¶->member.para.fmt; - pFmt->rgxTabs[cellNum] &= ~0x00FFFFFF; - pFmt->rgxTabs[cellNum] |= 0x00FFFFFF & info->rtfParam; + PARAFORMAT2 *fmt = &info->editor->pCursors[0].para->fmt; + fmt->rgxTabs[cellNum] &= ~0x00FFFFFF; + fmt->rgxTabs[cellNum] |= 0x00FFFFFF & info->rtfParam; } info->tableDef->numCellsDefined++; break; @@ -958,25 +956,24 @@ void ME_RTFSpecialCharHook(RTF_Info *info) if (!tableDef) break; RTFFlushOutputBuffer(info); - if (!info->editor->bEmulateVersion10) { /* v4.1 */ - if (tableDef->tableRowStart) + if (!info->editor->bEmulateVersion10) /* v4.1 */ + { + if (tableDef->row_start) { - if (!info->nestingLevel && - tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) + if (!info->nestingLevel && tableDef->row_start->nFlags & MEPF_ROWEND) { - ME_DisplayItem *para = tableDef->tableRowStart; - para = para->member.para.next_para; - para = ME_InsertTableRowStartAtParagraph(info->editor, para); - tableDef->tableRowStart = para; + ME_Paragraph *para = para_next( tableDef->row_start ); + tableDef->row_start = table_insert_row_start_at_para( info->editor, para ); info->nestingLevel = 1; } - ME_InsertTableCellFromCursor(info->editor); + table_insert_cell( info->editor, info->editor->pCursors ); } - } else { /* v1.0 - v3.0 */ - ME_DisplayItem *para = info->editor->pCursors[0].pPara; - PARAFORMAT2 *pFmt = ¶->member.para.fmt; - if (pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE && - tableDef->numCellsInserted < tableDef->numCellsDefined) + } + else /* v1.0 - v3.0 */ + { + ME_Paragraph *para = info->editor->pCursors[0].para; + + if (para_in_table( para ) && tableDef->numCellsInserted < tableDef->numCellsDefined) { WCHAR tab = '\t'; ME_InsertTextFromCursor(info->editor, 0, &tab, 1, info->style); @@ -990,68 +987,68 @@ void ME_RTFSpecialCharHook(RTF_Info *info) /* else fall through since v4.1 treats rtfNestRow and rtfRow the same */ case rtfRow: { - ME_DisplayItem *para, *cell, *run; + ME_Run *run; + ME_Paragraph *para; + ME_Cell *cell; int i; if (!tableDef) break; RTFFlushOutputBuffer(info); - if (!info->editor->bEmulateVersion10) { /* v4.1 */ - if (!tableDef->tableRowStart) - break; - if (!info->nestingLevel && - tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) + if (!info->editor->bEmulateVersion10) /* v4.1 */ + { + if (!tableDef->row_start) break; + if (!info->nestingLevel && tableDef->row_start->nFlags & MEPF_ROWEND) { - para = tableDef->tableRowStart; - para = para->member.para.next_para; - para = ME_InsertTableRowStartAtParagraph(info->editor, para); - tableDef->tableRowStart = para; + para = para_next( tableDef->row_start ); + tableDef->row_start = table_insert_row_start_at_para( info->editor, para ); info->nestingLevel++; } - para = tableDef->tableRowStart; - cell = ME_FindItemFwd(para, diCell); - assert(cell && !cell->member.cell.prev_cell); + para = tableDef->row_start; + cell = table_row_first_cell( para ); + assert( cell && !cell_prev( cell ) ); if (tableDef->numCellsDefined < 1) { /* 2000 twips appears to be the cell size that native richedit uses * when no cell sizes are specified. */ - const int defaultCellSize = 2000; - int nRightBoundary = defaultCellSize; - cell->member.cell.nRightBoundary = nRightBoundary; - while (cell->member.cell.next_cell) { - cell = cell->member.cell.next_cell; - nRightBoundary += defaultCellSize; - cell->member.cell.nRightBoundary = nRightBoundary; + const int default_size = 2000; + int right_boundary = default_size; + cell->nRightBoundary = right_boundary; + while (cell_next( cell )) + { + cell = cell_next( cell ); + right_boundary += default_size; + cell->nRightBoundary = right_boundary; } - para = ME_InsertTableCellFromCursor(info->editor); - cell = para->member.para.pCell; - cell->member.cell.nRightBoundary = nRightBoundary; - } else { + para = table_insert_cell( info->editor, info->editor->pCursors ); + cell = para_cell( para ); + cell->nRightBoundary = right_boundary; + } + else + { for (i = 0; i < tableDef->numCellsDefined; i++) { RTFCell *cellDef = &tableDef->cells[i]; - cell->member.cell.nRightBoundary = cellDef->rightBoundary; - ME_ApplyBorderProperties(info, &cell->member.cell.border, - cellDef->border); - cell = cell->member.cell.next_cell; + cell->nRightBoundary = cellDef->rightBoundary; + ME_ApplyBorderProperties( info, &cell->border, cellDef->border ); + cell = cell_next( cell ); if (!cell) { - para = ME_InsertTableCellFromCursor(info->editor); - cell = para->member.para.pCell; + para = table_insert_cell( info->editor, info->editor->pCursors ); + cell = para_cell( para ); } } /* Cell for table row delimiter is empty */ - cell->member.cell.nRightBoundary = tableDef->cells[i-1].rightBoundary; + cell->nRightBoundary = tableDef->cells[i - 1].rightBoundary; } - run = ME_FindItemFwd(cell, diRun); - if (info->editor->pCursors[0].pRun != run || - info->editor->pCursors[0].nOffset) + run = para_first_run( cell_first_para( cell ) ); + if (info->editor->pCursors[0].run != run || info->editor->pCursors[0].nOffset) { int nOfs, nChars; /* Delete inserted cells that aren't defined. */ - info->editor->pCursors[1].pRun = run; - info->editor->pCursors[1].pPara = ME_GetParagraph(run); + info->editor->pCursors[1].run = run; + info->editor->pCursors[1].para = run->para; info->editor->pCursors[1].nOffset = 0; nOfs = ME_GetCursorOfs(&info->editor->pCursors[1]); nChars = ME_GetCursorOfs(&info->editor->pCursors[0]) - nOfs; @@ -1059,59 +1056,59 @@ void ME_RTFSpecialCharHook(RTF_Info *info) nChars, TRUE); } - para = ME_InsertTableRowEndFromCursor(info->editor); - para->member.para.fmt.dxOffset = abs(info->tableDef->gapH); - para->member.para.fmt.dxStartIndent = info->tableDef->leftEdge; - ME_ApplyBorderProperties(info, ¶->member.para.border, - tableDef->border); + para = table_insert_row_end( info->editor, info->editor->pCursors ); + para->fmt.dxOffset = abs(info->tableDef->gapH); + para->fmt.dxStartIndent = info->tableDef->leftEdge; + ME_ApplyBorderProperties( info, ¶->border, tableDef->border ); info->nestingLevel--; if (!info->nestingLevel) { - if (info->canInheritInTbl) { - tableDef->tableRowStart = para; - } else { - while (info->tableDef) { + if (info->canInheritInTbl) tableDef->row_start = para; + else + { + while (info->tableDef) + { tableDef = info->tableDef; info->tableDef = tableDef->parent; heap_free(tableDef); } } - } else { + } + else + { info->tableDef = tableDef->parent; heap_free(tableDef); } - } else { /* v1.0 - v3.0 */ - WCHAR endl = '\r'; - ME_DisplayItem *para = info->editor->pCursors[0].pPara; - PARAFORMAT2 *pFmt = ¶->member.para.fmt; - pFmt->dxOffset = info->tableDef->gapH; - pFmt->dxStartIndent = info->tableDef->leftEdge; - - ME_ApplyBorderProperties(info, ¶->member.para.border, - tableDef->border); + } + else /* v1.0 - v3.0 */ + { + para = info->editor->pCursors[0].para; + para->fmt.dxOffset = info->tableDef->gapH; + para->fmt.dxStartIndent = info->tableDef->leftEdge; + + ME_ApplyBorderProperties( info, ¶->border, tableDef->border ); while (tableDef->numCellsInserted < tableDef->numCellsDefined) { WCHAR tab = '\t'; ME_InsertTextFromCursor(info->editor, 0, &tab, 1, info->style); tableDef->numCellsInserted++; } - pFmt->cTabCount = min(tableDef->numCellsDefined, MAX_TAB_STOPS); - if (!tableDef->numCellsDefined) - pFmt->wEffects &= ~PFE_TABLE; - ME_InsertTextFromCursor(info->editor, 0, &endl, 1, info->style); + para->fmt.cTabCount = min(tableDef->numCellsDefined, MAX_TAB_STOPS); + if (!tableDef->numCellsDefined) para->fmt.wEffects &= ~PFE_TABLE; + ME_InsertTextFromCursor(info->editor, 0, L"\r", 1, info->style); tableDef->numCellsInserted = 0; } break; } case rtfTab: case rtfPar: - if (info->editor->bEmulateVersion10) { /* v1.0 - 3.0 */ - ME_DisplayItem *para; - PARAFORMAT2 *pFmt; + if (info->editor->bEmulateVersion10) /* v1.0 - 3.0 */ + { + ME_Paragraph *para; + RTFFlushOutputBuffer(info); - para = info->editor->pCursors[0].pPara; - pFmt = ¶->member.para.fmt; - if (pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) + para = info->editor->pCursors[0].para; + if (para_in_table( para )) { /* rtfPar is treated like a space within a table. */ info->rtfClass = rtfText; @@ -1132,7 +1129,6 @@ static HRESULT insert_static_object(ME_TextEditor *editor, HENHMETAFILE hemf, HB LPOLECLIENTSITE lpClientSite = NULL; LPDATAOBJECT lpDataObject = NULL; LPOLECACHE lpOleCache = NULL; - LPRICHEDITOLE lpReOle = NULL; STGMEDIUM stgm; FORMATETC fm; CLSID clsid; @@ -1151,6 +1147,8 @@ static HRESULT insert_static_object(ME_TextEditor *editor, HENHMETAFILE hemf, HB stgm.u.hBitmap = hbmp; fm.cfFormat = CF_BITMAP; } + else return E_FAIL; + stgm.pUnkForRelease = NULL; fm.ptd = NULL; @@ -1158,15 +1156,8 @@ static HRESULT insert_static_object(ME_TextEditor *editor, HENHMETAFILE hemf, HB fm.lindex = -1; fm.tymed = stgm.tymed; - if (!editor->reOle) - { - if (!CreateIRichEditOle(NULL, editor, (LPVOID *)&editor->reOle)) - return hr; - } - if (OleCreateDefaultHandler(&CLSID_NULL, NULL, &IID_IOleObject, (void**)&lpObject) == S_OK && - IUnknown_QueryInterface(editor->reOle, &IID_IRichEditOle, (void**)&lpReOle) == S_OK && - IRichEditOle_GetClientSite(lpReOle, &lpClientSite) == S_OK && + IRichEditOle_GetClientSite(editor->richole, &lpClientSite) == S_OK && IOleObject_SetClientSite(lpObject, lpClientSite) == S_OK && IOleObject_GetUserClassID(lpObject, &clsid) == S_OK && IOleObject_QueryInterface(lpObject, &IID_IOleCache, (void**)&lpOleCache) == S_OK && @@ -1198,7 +1189,6 @@ static HRESULT insert_static_object(ME_TextEditor *editor, HENHMETAFILE hemf, HB if (lpStorage) IStorage_Release(lpStorage); if (lpDataObject) IDataObject_Release(lpDataObject); if (lpOleCache) IOleCache_Release(lpOleCache); - if (lpReOle) IRichEditOle_Release(lpReOle); return hr; } @@ -1605,29 +1595,27 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre ME_InternalDeleteText(editor, selStart, to - from, FALSE); /* Don't insert text at the end of the table row */ - if (!editor->bEmulateVersion10) { /* v4.1 */ - ME_DisplayItem *para = editor->pCursors->pPara; - if (para->member.para.nFlags & MEPF_ROWEND) - { - para = para->member.para.next_para; - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); - editor->pCursors[0].nOffset = 0; - } - if (para->member.para.nFlags & MEPF_ROWSTART) + if (!editor->bEmulateVersion10) /* v4.1 */ + { + ME_Paragraph *para = editor->pCursors->para; + if (para->nFlags & (MEPF_ROWSTART | MEPF_ROWEND)) { - para = para->member.para.next_para; - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + para = para_next( para ); + editor->pCursors[0].para = para; + editor->pCursors[0].run = para_first_run( para ); editor->pCursors[0].nOffset = 0; } editor->pCursors[1] = editor->pCursors[0]; - } else { /* v1.0 - 3.0 */ - if (editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA && - ME_IsInTable(editor->pCursors[0].pRun)) + } + else /* v1.0 - 3.0 */ + { + if (editor->pCursors[0].run->nFlags & MERF_ENDPARA && + para_in_table( editor->pCursors[0].para )) return 0; } - } else { + } + else + { style = editor->pBuffer->pDefaultStyle; ME_AddRefStyle(style); set_selection_cursors(editor, 0, 0); @@ -1635,7 +1623,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre ME_GetTextLength(editor), FALSE); from = to = 0; ME_ClearTempStyle(editor); - ME_SetDefaultParaFormat(editor, &editor->pCursors[0].pPara->member.para.fmt); + editor_set_default_para_fmt( editor, &editor->pCursors[0].para->fmt ); } @@ -1695,13 +1683,14 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre /* do the parsing */ RTFRead(&parser); RTFFlushOutputBuffer(&parser); - if (!editor->bEmulateVersion10) { /* v4.1 */ - if (parser.tableDef && parser.tableDef->tableRowStart && + if (!editor->bEmulateVersion10) /* v4.1 */ + { + if (parser.tableDef && parser.tableDef->row_start && (parser.nestingLevel > 0 || parser.canInheritInTbl)) { /* Delete any incomplete table row at the end of the rich text. */ int nOfs, nChars; - ME_DisplayItem *para; + ME_Paragraph *para; parser.rtfMinor = rtfRow; /* Complete the table row before deleting it. @@ -1712,26 +1701,26 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre { while (parser.nestingLevel > 1) ME_RTFSpecialCharHook(&parser); /* Decrements nestingLevel */ - para = parser.tableDef->tableRowStart; + para = parser.tableDef->row_start; ME_RTFSpecialCharHook(&parser); - } else { - para = parser.tableDef->tableRowStart; + } + else + { + para = parser.tableDef->row_start; ME_RTFSpecialCharHook(&parser); - assert(para->member.para.nFlags & MEPF_ROWEND); - para = para->member.para.next_para; + assert( para->nFlags & MEPF_ROWEND ); + para = para_next( para ); } - editor->pCursors[1].pPara = para; - editor->pCursors[1].pRun = ME_FindItemFwd(para, diRun); + editor->pCursors[1].para = para; + editor->pCursors[1].run = para_first_run( para ); editor->pCursors[1].nOffset = 0; nOfs = ME_GetCursorOfs(&editor->pCursors[1]); nChars = ME_GetCursorOfs(&editor->pCursors[0]) - nOfs; ME_InternalDeleteText(editor, &editor->pCursors[1], nChars, TRUE); - if (parser.tableDef) - parser.tableDef->tableRowStart = NULL; + if (parser.tableDef) parser.tableDef->row_start = NULL; } } - ME_CheckTablesForCorruption(editor); RTFDestroy(&parser); if (parser.stackTop > 0) @@ -1790,7 +1779,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre /* put the cursor at the top */ if (!(format & SFF_SELECTION)) set_selection_cursors(editor, 0, 0); - ME_CursorFromCharOfs(editor, from, &start); + cursor_from_char_ofs( editor, from, &start ); ME_UpdateLinkAttribute(editor, &start, to - from); } @@ -1810,7 +1799,6 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre if (!(format & SFF_SELECTION)) { ME_ClearTempStyle(editor); } - update_caret(editor); ME_SendSelChange(editor); ME_SendRequestResize(editor, FALSE); @@ -1919,20 +1907,19 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH /* If possible, find the character before where the search starts */ if ((flags & FR_WHOLEWORD) && nMin) { - ME_CursorFromCharOfs(editor, nMin - 1, &cursor); - wLastChar = *get_text( &cursor.pRun->member.run, cursor.nOffset ); + cursor_from_char_ofs( editor, nMin - 1, &cursor ); + wLastChar = *get_text( cursor.run, cursor.nOffset ); ME_MoveCursorChars(editor, &cursor, 1, FALSE); - } else { - ME_CursorFromCharOfs(editor, nMin, &cursor); } + else cursor_from_char_ofs( editor, nMin, &cursor ); - while (cursor.pRun && ME_GetCursorOfs(&cursor) + nLen <= nMax) + while (cursor.run && ME_GetCursorOfs(&cursor) + nLen <= nMax) { - ME_DisplayItem *pCurItem = cursor.pRun; + ME_Run *run = cursor.run; int nCurStart = cursor.nOffset; int nMatched = 0; - while (pCurItem && ME_CharCompare( *get_text( &pCurItem->member.run, nCurStart + nMatched ), text[nMatched], (flags & FR_MATCHCASE))) + while (run && ME_CharCompare( *get_text( run, nCurStart + nMatched ), text[nMatched], (flags & FR_MATCHCASE))) { if ((flags & FR_WHOLEWORD) && iswalnum(wLastChar)) break; @@ -1940,21 +1927,21 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH nMatched++; if (nMatched == nLen) { - ME_DisplayItem *pNextItem = pCurItem; + ME_Run *next_run = run; int nNextStart = nCurStart; WCHAR wNextChar; /* Check to see if next character is a whitespace */ if (flags & FR_WHOLEWORD) { - if (nCurStart + nMatched == pCurItem->member.run.len) + if (nCurStart + nMatched == run->len) { - pNextItem = ME_FindItemFwd(pCurItem, diRun); + next_run = run_next_all_paras( run ); nNextStart = -nMatched; } - if (pNextItem) - wNextChar = *get_text( &pNextItem->member.run, nNextStart + nMatched ); + if (next_run) + wNextChar = *get_text( next_run, nNextStart + nMatched ); else wNextChar = ' '; @@ -1962,7 +1949,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH break; } - cursor.nOffset += cursor.pPara->member.para.nCharOfs + cursor.pRun->member.run.nCharOfs; + cursor.nOffset += cursor.para->nCharOfs + cursor.run->nCharOfs; if (chrgText) { chrgText->cpMin = cursor.nOffset; @@ -1971,22 +1958,28 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH TRACE("found at %d-%d\n", cursor.nOffset, cursor.nOffset + nLen); return cursor.nOffset; } - if (nCurStart + nMatched == pCurItem->member.run.len) + if (nCurStart + nMatched == run->len) { - pCurItem = ME_FindItemFwd(pCurItem, diRun); + run = run_next_all_paras( run ); nCurStart = -nMatched; } } - if (pCurItem) - wLastChar = *get_text( &pCurItem->member.run, nCurStart + nMatched ); + if (run) + wLastChar = *get_text( run, nCurStart + nMatched ); else wLastChar = ' '; cursor.nOffset++; - if (cursor.nOffset == cursor.pRun->member.run.len) + if (cursor.nOffset == cursor.run->len) { - ME_NextRun(&cursor.pPara, &cursor.pRun, TRUE); - cursor.nOffset = 0; + if (run_next_all_paras( cursor.run )) + { + cursor.run = run_next_all_paras( cursor.run ); + cursor.para = cursor.run->para; + cursor.nOffset = 0; + } + else + cursor.run = NULL; } } } @@ -1995,28 +1988,28 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH /* If possible, find the character after where the search ends */ if ((flags & FR_WHOLEWORD) && nMax < nTextLen - 1) { - ME_CursorFromCharOfs(editor, nMax + 1, &cursor); - wLastChar = *get_text( &cursor.pRun->member.run, cursor.nOffset ); + cursor_from_char_ofs( editor, nMax + 1, &cursor ); + wLastChar = *get_text( cursor.run, cursor.nOffset ); ME_MoveCursorChars(editor, &cursor, -1, FALSE); - } else { - ME_CursorFromCharOfs(editor, nMax, &cursor); } + else cursor_from_char_ofs( editor, nMax, &cursor ); - while (cursor.pRun && ME_GetCursorOfs(&cursor) - nLen >= nMin) + while (cursor.run && ME_GetCursorOfs(&cursor) - nLen >= nMin) { - ME_DisplayItem *pCurItem = cursor.pRun; - ME_DisplayItem *pCurPara = cursor.pPara; + ME_Run *run = cursor.run; + ME_Paragraph *para = cursor.para; int nCurEnd = cursor.nOffset; int nMatched = 0; - if (nCurEnd == 0) + if (nCurEnd == 0 && run_prev_all_paras( run )) { - ME_PrevRun(&pCurPara, &pCurItem, TRUE); - nCurEnd = pCurItem->member.run.len; + run = run_prev_all_paras( run ); + para = run->para; + nCurEnd = run->len; } - while (pCurItem && ME_CharCompare( *get_text( &pCurItem->member.run, nCurEnd - nMatched - 1 ), - text[nLen - nMatched - 1], (flags & FR_MATCHCASE) )) + while (run && ME_CharCompare( *get_text( run, nCurEnd - nMatched - 1 ), + text[nLen - nMatched - 1], (flags & FR_MATCHCASE) )) { if ((flags & FR_WHOLEWORD) && iswalnum(wLastChar)) break; @@ -2024,7 +2017,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH nMatched++; if (nMatched == nLen) { - ME_DisplayItem *pPrevItem = pCurItem; + ME_Run *prev_run = run; int nPrevEnd = nCurEnd; WCHAR wPrevChar; int nStart; @@ -2034,22 +2027,18 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH { if (nPrevEnd - nMatched == 0) { - pPrevItem = ME_FindItemBack(pCurItem, diRun); - if (pPrevItem) - nPrevEnd = pPrevItem->member.run.len + nMatched; + prev_run = run_prev_all_paras( run ); + if (prev_run) nPrevEnd = prev_run->len + nMatched; } - if (pPrevItem) - wPrevChar = *get_text( &pPrevItem->member.run, nPrevEnd - nMatched - 1 ); - else - wPrevChar = ' '; + if (prev_run) wPrevChar = *get_text( prev_run, nPrevEnd - nMatched - 1 ); + else wPrevChar = ' '; if (iswalnum(wPrevChar)) break; } - nStart = pCurPara->member.para.nCharOfs - + pCurItem->member.run.nCharOfs + nCurEnd - nMatched; + nStart = para->nCharOfs + run->nCharOfs + nCurEnd - nMatched; if (chrgText) { chrgText->cpMin = nStart; @@ -2060,22 +2049,32 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH } if (nCurEnd - nMatched == 0) { - ME_PrevRun(&pCurPara, &pCurItem, TRUE); + if (run_prev_all_paras( run )) + { + run = run_prev_all_paras( run ); + para = run->para; + } /* Don't care about pCurItem becoming NULL here; it's already taken * care of in the exterior loop condition */ - nCurEnd = pCurItem->member.run.len + nMatched; + nCurEnd = run->len + nMatched; } } - if (pCurItem) - wLastChar = *get_text( &pCurItem->member.run, nCurEnd - nMatched - 1 ); + if (run) + wLastChar = *get_text( run, nCurEnd - nMatched - 1 ); else wLastChar = ' '; cursor.nOffset--; if (cursor.nOffset < 0) { - ME_PrevRun(&cursor.pPara, &cursor.pRun, TRUE); - cursor.nOffset = cursor.pRun->member.run.len; + if (run_prev_all_paras( cursor.run ) ) + { + cursor.run = run_prev_all_paras( cursor.run ); + cursor.para = cursor.run->para; + cursor.nOffset = cursor.run->len; + } + else + cursor.run = NULL; } } } @@ -2137,22 +2136,11 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) } } -static int ME_GetTextRange(ME_TextEditor *editor, WCHAR *strText, - const ME_Cursor *start, int nLen, BOOL unicode) +static int get_text_range( ME_TextEditor *editor, WCHAR *buffer, + const ME_Cursor *start, int len ) { - if (!strText) return 0; - if (unicode) { - return ME_GetTextW(editor, strText, INT_MAX, start, nLen, FALSE, FALSE); - } else { - int nChars; - WCHAR *p = heap_alloc((nLen+1) * sizeof(*p)); - if (!p) return 0; - nChars = ME_GetTextW(editor, p, nLen, start, nLen, FALSE, FALSE); - WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)strText, - nLen+1, NULL, NULL); - heap_free(p); - return nChars; - } + if (!buffer) return 0; + return ME_GetTextW( editor, buffer, INT_MAX, start, len, FALSE, FALSE ); } int set_selection( ME_TextEditor *editor, int to, int from ) @@ -2211,8 +2199,6 @@ static DWORD CALLBACK ME_ReadFromHGLOBALRTF(DWORD_PTR dwCookie, LPBYTE lpBuff, L return 0; } -static const WCHAR rtfW[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0}; - static HRESULT paste_rtf(ME_TextEditor *editor, FORMATETC *fmt, STGMEDIUM *med) { EDITSTREAM es; @@ -2267,7 +2253,7 @@ static struct paste_format const WCHAR *name; } paste_formats[] = { - {{ -1, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, paste_rtf, rtfW }, + {{ -1, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, paste_rtf, L"Rich Text Format" }, {{ CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, paste_text }, {{ CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF }, paste_emf }, {{ 0 }} @@ -2297,10 +2283,9 @@ static BOOL paste_special(ME_TextEditor *editor, UINT cf, REPASTESPECIAL *ps, BO IDataObject *data; /* Protect read-only edit control from modification */ - if (editor->styleFlags & ES_READONLY) + if (editor->props & TXTBIT_READONLY) { - if (!check_only) - MessageBeep(MB_ICONERROR); + if (!check_only) editor_beep( editor, MB_ICONERROR ); return FALSE; } @@ -2337,146 +2322,111 @@ done: return hr == S_OK; } -static BOOL ME_Copy(ME_TextEditor *editor, const ME_Cursor *start, int nChars) +static HRESULT editor_copy( ME_TextEditor *editor, ME_Cursor *start, int chars, IDataObject **data_out ) { - LPDATAOBJECT dataObj = NULL; - HRESULT hr = S_OK; + IDataObject *data = NULL; + HRESULT hr = S_OK; - if (editor->cPasswordMask) - return FALSE; /* Copying or Cutting masked text isn't allowed */ + if (editor->lpOleCallback) + { + CHARRANGE range; + range.cpMin = ME_GetCursorOfs( start ); + range.cpMax = range.cpMin + chars; + hr = IRichEditOleCallback_GetClipboardData( editor->lpOleCallback, &range, RECO_COPY, &data ); + } - if(editor->lpOleCallback) - { - CHARRANGE range; - range.cpMin = ME_GetCursorOfs(start); - range.cpMax = range.cpMin + nChars; - hr = IRichEditOleCallback_GetClipboardData(editor->lpOleCallback, &range, RECO_COPY, &dataObj); - } - if(FAILED(hr) || !dataObj) - hr = ME_GetDataObject(editor, start, nChars, &dataObj); - if(SUCCEEDED(hr)) { - hr = OleSetClipboard(dataObj); - IDataObject_Release(dataObj); - } - return SUCCEEDED(hr); + if (FAILED( hr ) || !data) + hr = ME_GetDataObject( editor, start, chars, &data ); + + if (SUCCEEDED( hr )) + { + if (data_out) + *data_out = data; + else + { + hr = OleSetClipboard( data ); + IDataObject_Release( data ); + } + } + + return hr; } -static BOOL copy_or_cut(ME_TextEditor *editor, BOOL cut) +HRESULT editor_copy_or_cut( ME_TextEditor *editor, BOOL cut, ME_Cursor *start, int count, + IDataObject **data_out ) { - BOOL result; - int offs, num_chars; - int start_cursor = ME_GetSelectionOfs(editor, &offs, &num_chars); - ME_Cursor *sel_start = &editor->pCursors[start_cursor]; + HRESULT hr; - if (cut && (editor->styleFlags & ES_READONLY)) + if (cut && (editor->props & TXTBIT_READONLY)) { - MessageBeep(MB_ICONERROR); - return FALSE; + return E_ACCESSDENIED; } - num_chars -= offs; - result = ME_Copy(editor, sel_start, num_chars); - if (result && cut) + hr = editor_copy( editor, start, count, data_out ); + if (SUCCEEDED(hr) && cut) { - ME_InternalDeleteText(editor, sel_start, num_chars, FALSE); - ME_CommitUndo(editor); - ME_UpdateRepaint(editor, TRUE); + ME_InternalDeleteText( editor, start, count, FALSE ); + ME_CommitUndo( editor ); + ME_UpdateRepaint( editor, TRUE ); } - return result; + return hr; } -/* helper to send a msg filter notification */ -static BOOL -ME_FilterEvent(ME_TextEditor *editor, UINT msg, WPARAM* wParam, LPARAM* lParam) +static BOOL copy_or_cut( ME_TextEditor *editor, BOOL cut ) { - MSGFILTER msgf; - - if (!editor->hWnd || !editor->hwndParent) return FALSE; - msgf.nmhdr.hwndFrom = editor->hWnd; - msgf.nmhdr.idFrom = GetWindowLongW(editor->hWnd, GWLP_ID); - msgf.nmhdr.code = EN_MSGFILTER; - msgf.msg = msg; - msgf.wParam = *wParam; - msgf.lParam = *lParam; - if (SendMessageW(editor->hwndParent, WM_NOTIFY, msgf.nmhdr.idFrom, (LPARAM)&msgf)) - return FALSE; - *wParam = msgf.wParam; - *lParam = msgf.lParam; - msgf.wParam = *wParam; + HRESULT hr; + int offs, count; + int start_cursor = ME_GetSelectionOfs( editor, &offs, &count ); + ME_Cursor *sel_start = &editor->pCursors[start_cursor]; - return TRUE; + if (editor->password_char) return FALSE; + + count -= offs; + hr = editor_copy_or_cut( editor, cut, sel_start, count, NULL ); + if (FAILED( hr )) editor_beep( editor, MB_ICONERROR ); + + return SUCCEEDED( hr ); } static void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor) { - ME_DisplayItem *startPara, *endPara; - ME_DisplayItem *prev_para; - ME_Cursor *from, *to; - ME_Cursor start; - int nChars; + ME_Paragraph *start_para, *end_para; + ME_Cursor *from, *to, start; + int num_chars; if (!editor->AutoURLDetect_bEnable) return; ME_GetSelection(editor, &from, &to); /* Find paragraph previous to the one that contains start cursor */ - startPara = from->pPara; - prev_para = startPara->member.para.prev_para; - if (prev_para->type == diParagraph) startPara = prev_para; + start_para = from->para; + if (para_prev( start_para )) start_para = para_prev( start_para ); /* Find paragraph that contains end cursor */ - endPara = to->pPara->member.para.next_para; + end_para = para_next( to->para ); - start.pPara = startPara; - start.pRun = ME_FindItemFwd(startPara, diRun); + start.para = start_para; + start.run = para_first_run( start_para ); start.nOffset = 0; - nChars = endPara->member.para.nCharOfs - startPara->member.para.nCharOfs; + num_chars = end_para->nCharOfs - start_para->nCharOfs; - ME_UpdateLinkAttribute(editor, &start, nChars); + ME_UpdateLinkAttribute( editor, &start, num_chars ); } static BOOL handle_enter(ME_TextEditor *editor) { - BOOL ctrl_is_down = GetKeyState(VK_CONTROL) & 0x8000; BOOL shift_is_down = GetKeyState(VK_SHIFT) & 0x8000; - if (editor->bDialogMode) - { - if (ctrl_is_down) - return TRUE; - - if (!(editor->styleFlags & ES_WANTRETURN)) - { - if (editor->hwndParent) - { - DWORD dw; - dw = SendMessageW(editor->hwndParent, DM_GETDEFID, 0, 0); - if (HIWORD(dw) == DC_HASDEFID) - { - HWND hwDefCtrl = GetDlgItem(editor->hwndParent, LOWORD(dw)); - if (hwDefCtrl) - { - SendMessageW(editor->hwndParent, WM_NEXTDLGCTL, (WPARAM)hwDefCtrl, TRUE); - PostMessageW(hwDefCtrl, WM_KEYDOWN, VK_RETURN, 0); - } - } - } - return TRUE; - } - } - - if (editor->styleFlags & ES_MULTILINE) + if (editor->props & TXTBIT_MULTILINE) { - static const WCHAR endl = '\r'; - static const WCHAR endlv10[] = {'\r','\n'}; ME_Cursor cursor = editor->pCursors[0]; - ME_DisplayItem *para = cursor.pPara; + ME_Paragraph *para = cursor.para; int from, to; ME_Style *style, *eop_style; - if (editor->styleFlags & ES_READONLY) + if (editor->props & TXTBIT_READONLY) { - MessageBeep(MB_ICONERROR); + editor_beep( editor, MB_ICONERROR ); return TRUE; } @@ -2485,60 +2435,57 @@ static BOOL handle_enter(ME_TextEditor *editor) { if (!editor->bEmulateVersion10) /* v4.1 */ { - if (para->member.para.nFlags & MEPF_ROWEND) + if (para->nFlags & MEPF_ROWEND) { /* Add a new table row after this row. */ - para = ME_AppendTableRow(editor, para); - para = para->member.para.next_para; - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + para = table_append_row( editor, para ); + para = para_next( para ); + editor->pCursors[0].para = para; + editor->pCursors[0].run = para_first_run( para ); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; ME_CommitUndo(editor); - ME_CheckTablesForCorruption(editor); ME_UpdateRepaint(editor, FALSE); return TRUE; } - else if (para == editor->pCursors[1].pPara && - cursor.nOffset + cursor.pRun->member.run.nCharOfs == 0 && - para->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART && - !para->member.para.prev_para->member.para.nCharOfs) + else if (para == editor->pCursors[1].para && + cursor.nOffset + cursor.run->nCharOfs == 0 && + para_prev( para ) && para_prev( para )->nFlags & MEPF_ROWSTART && + !para_prev( para )->nCharOfs) { /* Insert a newline before the table. */ - para = para->member.para.prev_para; - para->member.para.nFlags &= ~MEPF_ROWSTART; - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + para = para_prev( para ); + para->nFlags &= ~MEPF_ROWSTART; + editor->pCursors[0].para = para; + editor->pCursors[0].run = para_first_run( para ); editor->pCursors[1] = editor->pCursors[0]; - ME_InsertTextFromCursor(editor, 0, &endl, 1, - editor->pCursors[0].pRun->member.run.style); - para = editor->pBuffer->pFirst->member.para.next_para; - ME_SetDefaultParaFormat(editor, ¶->member.para.fmt); - para->member.para.nFlags = 0; - mark_para_rewrap(editor, para); - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + ME_InsertTextFromCursor( editor, 0, L"\r", 1, editor->pCursors[0].run->style ); + para = editor_first_para( editor ); + editor_set_default_para_fmt( editor, ¶->fmt ); + para->nFlags = 0; + para_mark_rewrap( editor, para ); + editor->pCursors[0].para = para; + editor->pCursors[0].run = para_first_run( para ); editor->pCursors[1] = editor->pCursors[0]; - para->member.para.next_para->member.para.nFlags |= MEPF_ROWSTART; + para_next( para )->nFlags |= MEPF_ROWSTART; ME_CommitCoalescingUndo(editor); - ME_CheckTablesForCorruption(editor); ME_UpdateRepaint(editor, FALSE); return TRUE; } } else /* v1.0 - 3.0 */ { - ME_DisplayItem *para = cursor.pPara; - if (ME_IsInTable(para)) + ME_Paragraph *para = cursor.para; + if (para_in_table( para )) { - if (cursor.pRun->member.run.nFlags & MERF_ENDPARA) + if (cursor.run->nFlags & MERF_ENDPARA) { if (from == to) { ME_ContinueCoalescingTransaction(editor); - para = ME_AppendTableRow(editor, para); - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + para = table_append_row( editor, para ); + editor->pCursors[0].para = para; + editor->pCursors[0].run = para_first_run( para ); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; ME_CommitCoalescingUndo(editor); @@ -2549,27 +2496,26 @@ static BOOL handle_enter(ME_TextEditor *editor) else { ME_ContinueCoalescingTransaction(editor); - if (cursor.pRun->member.run.nCharOfs + cursor.nOffset == 0 && - !ME_IsInTable(para->member.para.prev_para)) + if (cursor.run->nCharOfs + cursor.nOffset == 0 && + para_prev( para ) && !para_in_table( para_prev( para ) )) { /* Insert newline before table */ - cursor.pRun = ME_FindItemBack(para, diRun); - if (cursor.pRun) + cursor.run = para_end_run( para_prev( para ) ); + if (cursor.run) { - editor->pCursors[0].pRun = cursor.pRun; - editor->pCursors[0].pPara = para->member.para.prev_para; + editor->pCursors[0].run = cursor.run; + editor->pCursors[0].para = para_prev( para ); } editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; - ME_InsertTextFromCursor(editor, 0, &endl, 1, - editor->pCursors[0].pRun->member.run.style); + ME_InsertTextFromCursor( editor, 0, L"\r", 1, editor->pCursors[0].run->style ); } else { editor->pCursors[1] = editor->pCursors[0]; - para = ME_AppendTableRow(editor, para); - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + para = table_append_row( editor, para ); + editor->pCursors[0].para = para; + editor->pCursors[0].run = para_first_run( para ); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; } @@ -2580,13 +2526,13 @@ static BOOL handle_enter(ME_TextEditor *editor) } } - style = ME_GetInsertStyle(editor, 0); + style = style_get_insert_style( editor, editor->pCursors ); /* Normally the new eop style is the insert style, however in a list it is copied from the existing eop style (this prevents the list label style changing when the new eop is inserted). No extra ref is taken here on eop_style. */ - if (para->member.para.fmt.wNumbering) - eop_style = para->member.para.eop_run->style; + if (para->fmt.wNumbering) + eop_style = para->eop_run->style; else eop_style = style; ME_ContinueCoalescingTransaction(editor); @@ -2594,9 +2540,9 @@ static BOOL handle_enter(ME_TextEditor *editor) ME_InsertEndRowFromCursor(editor, 0); else if (!editor->bEmulateVersion10) - ME_InsertTextFromCursor(editor, 0, &endl, 1, eop_style); + ME_InsertTextFromCursor(editor, 0, L"\r", 1, eop_style); else - ME_InsertTextFromCursor(editor, 0, endlv10, 2, eop_style); + ME_InsertTextFromCursor(editor, 0, L"\r\n", 2, eop_style); ME_CommitCoalescingUndo(editor); SetCursor(NULL); @@ -2640,7 +2586,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) case VK_DELETE: editor->nUDArrowX = -1; /* FIXME backspace and delete aren't the same, they act different wrt paragraph style of the merged paragraph */ - if (editor->styleFlags & ES_READONLY) + if (editor->props & TXTBIT_READONLY) return FALSE; if (ME_IsSelection(editor)) { @@ -2670,7 +2616,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) } else return TRUE; - ME_MoveCursorFromTableRowStartParagraph(editor); + table_move_from_row_start( editor ); ME_UpdateSelectionLinkAttribute(editor); ME_UpdateRepaint(editor, FALSE); ME_SendRequestResize(editor, FALSE); @@ -2679,14 +2625,6 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) if (!editor->bEmulateVersion10) return handle_enter(editor); break; - case VK_ESCAPE: - if (editor->bDialogMode && editor->hwndParent) - PostMessageW(editor->hwndParent, WM_CLOSE, 0, 0); - return TRUE; - case VK_TAB: - if (editor->bDialogMode && editor->hwndParent) - SendMessageW(editor->hwndParent, WM_NEXTDLGCTL, shift_is_down, 0); - return TRUE; case 'A': if (ctrl_is_down) { @@ -2742,35 +2680,24 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) return FALSE; } -static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode, - LPARAM flags, BOOL unicode) +static LRESULT handle_wm_char( ME_TextEditor *editor, WCHAR wstr, LPARAM flags ) { - WCHAR wstr; - if (editor->bMouseCaptured) return 0; - if (editor->styleFlags & ES_READONLY) + if (editor->props & TXTBIT_READONLY) { - MessageBeep(MB_ICONERROR); + editor_beep( editor, MB_ICONERROR ); return 0; /* FIXME really 0 ? */ } - if (unicode) - wstr = (WCHAR)charCode; - else - { - CHAR charA = charCode; - MultiByteToWideChar(CP_ACP, 0, &charA, 1, &wstr, 1); - } - if (editor->bEmulateVersion10 && wstr == '\r') handle_enter(editor); if ((unsigned)wstr >= ' ' || wstr == '\t') { ME_Cursor cursor = editor->pCursors[0]; - ME_DisplayItem *para = cursor.pPara; + ME_Paragraph *para = cursor.para; int from, to; BOOL ctrl_is_down = GetKeyState(VK_CONTROL) & 0x8000; ME_GetSelectionOfs(editor, &from, &to); @@ -2778,43 +2705,43 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode, /* v4.1 allows tabs to be inserted with ctrl key down */ !(ctrl_is_down && !editor->bEmulateVersion10)) { - ME_DisplayItem *para; - BOOL bSelectedRow = FALSE; + BOOL selected_row = FALSE; - para = cursor.pPara; if (ME_IsSelection(editor) && - cursor.pRun->member.run.nCharOfs + cursor.nOffset == 0 && - to == ME_GetCursorOfs(&editor->pCursors[0]) && - para->member.para.prev_para->type == diParagraph) + cursor.run->nCharOfs + cursor.nOffset == 0 && + to == ME_GetCursorOfs(&editor->pCursors[0]) && para_prev( para )) { - para = para->member.para.prev_para; - bSelectedRow = TRUE; + para = para_prev( para ); + selected_row = TRUE; } - if (ME_IsInTable(para)) + if (para_in_table( para )) { - ME_TabPressedInTable(editor, bSelectedRow); + table_handle_tab( editor, selected_row ); ME_CommitUndo(editor); return 0; } - } else if (!editor->bEmulateVersion10) { /* v4.1 */ - if (para->member.para.nFlags & MEPF_ROWEND) { - if (from == to) { - para = para->member.para.next_para; - if (para->member.para.nFlags & MEPF_ROWSTART) - para = para->member.para.next_para; - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + } + else if (!editor->bEmulateVersion10) /* v4.1 */ + { + if (para->nFlags & MEPF_ROWEND) + { + if (from == to) + { + para = para_next( para ); + if (para->nFlags & MEPF_ROWSTART) para = para_next( para ); + editor->pCursors[0].para = para; + editor->pCursors[0].run = para_first_run( para ); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; } } - } else { /* v1.0 - 3.0 */ - if (ME_IsInTable(cursor.pRun) && - cursor.pRun->member.run.nFlags & MERF_ENDPARA && - from == to) + } + else /* v1.0 - 3.0 */ + { + if (para_in_table( para ) && cursor.run->nFlags & MERF_ENDPARA && from == to) { /* Text should not be inserted at the end of the table. */ - MessageBeep(-1); + editor_beep( editor, -1 ); return 0; } } @@ -2822,7 +2749,7 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode, /* WM_CHAR is restricted to nTextLimit */ if(editor->nTextLimit > ME_GetTextLength(editor) - (to-from)) { - ME_Style *style = ME_GetInsertStyle(editor, 0); + ME_Style *style = style_get_insert_style( editor, editor->pCursors ); ME_ContinueCoalescingTransaction(editor); ME_InsertTextFromCursor(editor, 0, &wstr, 1, style); ME_ReleaseStyle(style); @@ -2894,104 +2821,52 @@ static BOOL is_link( ME_Run *run ) return (run->style->fmt.dwMask & CFM_LINK) && (run->style->fmt.dwEffects & CFE_LINK); } -static BOOL ME_SetCursor(ME_TextEditor *editor) +void editor_set_cursor( ME_TextEditor *editor, int x, int y ) { - ME_Cursor cursor; - POINT pt; - BOOL isExact; - SCROLLBARINFO sbi; - DWORD messagePos = GetMessagePos(); - pt.x = (short)LOWORD(messagePos); - pt.y = (short)HIWORD(messagePos); + ME_Cursor pos; + BOOL is_exact; + static HCURSOR cursor_arrow, cursor_hand, cursor_ibeam, cursor_reverse; + HCURSOR cursor; - if (editor->hWnd) - { - sbi.cbSize = sizeof(sbi); - GetScrollBarInfo(editor->hWnd, OBJID_HSCROLL, &sbi); - if (!(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE|STATE_SYSTEM_OFFSCREEN)) && - PtInRect(&sbi.rcScrollBar, pt)) + if (!cursor_arrow) { - ITextHost_TxSetCursor(editor->texthost, - LoadCursorW(NULL, (WCHAR*)IDC_ARROW), FALSE); - return TRUE; + cursor_arrow = LoadCursorW( NULL, MAKEINTRESOURCEW( IDC_ARROW ) ); + cursor_hand = LoadCursorW( NULL, MAKEINTRESOURCEW( IDC_HAND ) ); + cursor_ibeam = LoadCursorW( NULL, MAKEINTRESOURCEW( IDC_IBEAM ) ); + cursor_reverse = LoadCursorW( dll_instance, MAKEINTRESOURCEW( OCR_REVERSE ) ); } - sbi.cbSize = sizeof(sbi); - GetScrollBarInfo(editor->hWnd, OBJID_VSCROLL, &sbi); - if (!(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE|STATE_SYSTEM_OFFSCREEN)) && - PtInRect(&sbi.rcScrollBar, pt)) + + cursor = cursor_ibeam; + + if ((editor->nSelectionType == stLine && editor->bMouseCaptured) || + (!editor->bEmulateVersion10 && y < editor->rcFormat.top && x < editor->rcFormat.left)) + cursor = cursor_reverse; + else if (y < editor->rcFormat.top || y > editor->rcFormat.bottom) { - ITextHost_TxSetCursor(editor->texthost, - LoadCursorW(NULL, (WCHAR*)IDC_ARROW), FALSE); - return TRUE; + if (editor->bEmulateVersion10) cursor = cursor_arrow; + else cursor = cursor_ibeam; } - } - ITextHost_TxScreenToClient(editor->texthost, &pt); + else if (x < editor->rcFormat.left) cursor = cursor_reverse; + else + { + ME_CharFromPos( editor, x, y, &pos, &is_exact ); + if (is_exact) + { + ME_Run *run = pos.run; - if (editor->nSelectionType == stLine && editor->bMouseCaptured) { - ITextHost_TxSetCursor(editor->texthost, hLeft, FALSE); - return TRUE; - } - if (!editor->bEmulateVersion10 /* v4.1 */ && - pt.y < editor->rcFormat.top && - pt.x < editor->rcFormat.left) - { - ITextHost_TxSetCursor(editor->texthost, hLeft, FALSE); - return TRUE; - } - if (pt.y < editor->rcFormat.top || pt.y > editor->rcFormat.bottom) - { - if (editor->bEmulateVersion10) /* v1.0 - 3.0 */ - ITextHost_TxSetCursor(editor->texthost, - LoadCursorW(NULL, (WCHAR*)IDC_ARROW), FALSE); - else /* v4.1 */ - ITextHost_TxSetCursor(editor->texthost, - LoadCursorW(NULL, (WCHAR*)IDC_IBEAM), TRUE); - return TRUE; - } - if (pt.x < editor->rcFormat.left) - { - ITextHost_TxSetCursor(editor->texthost, hLeft, FALSE); - return TRUE; - } - ME_CharFromPos(editor, pt.x, pt.y, &cursor, &isExact); - if (isExact) - { - ME_Run *run; + if (is_link( run )) cursor = cursor_hand; - run = &cursor.pRun->member.run; - if (is_link( run )) - { - ITextHost_TxSetCursor(editor->texthost, - LoadCursorW(NULL, (WCHAR*)IDC_HAND), - FALSE); - return TRUE; - } + else if (ME_IsSelection( editor )) + { + int start, end, offset = ME_GetCursorOfs( &pos ); - if (ME_IsSelection(editor)) - { - int selStart, selEnd; - int offset = ME_GetCursorOfs(&cursor); - - ME_GetSelectionOfs(editor, &selStart, &selEnd); - if (selStart <= offset && selEnd >= offset) { - ITextHost_TxSetCursor(editor->texthost, - LoadCursorW(NULL, (WCHAR*)IDC_ARROW), - FALSE); - return TRUE; - } - } - } - ITextHost_TxSetCursor(editor->texthost, - LoadCursorW(NULL, (WCHAR*)IDC_IBEAM), TRUE); - return TRUE; -} + ME_GetSelectionOfs( editor, &start, &end ); + if (start <= offset && end >= offset) cursor = cursor_arrow; + } + } + } -static void ME_SetDefaultFormatRect(ME_TextEditor *editor) -{ - ITextHost_TxGetClientRect(editor->texthost, &editor->rcFormat); - editor->rcFormat.top += editor->exStyleFlags & WS_EX_CLIENTEDGE ? 1 : 0; - editor->rcFormat.left += 1 + editor->selofs; - editor->rcFormat.right -= 1; + ITextHost_TxSetCursor( editor->texthost, cursor, cursor == cursor_ibeam ); } static LONG ME_GetSelectionType(ME_TextEditor *editor) @@ -3011,11 +2886,9 @@ static LONG ME_GetSelectionType(ME_TextEditor *editor) { ME_Cursor cursor; - ME_CursorFromCharOfs(editor, start + i, &cursor); - if (cursor.pRun->member.run.reobj) - object_count++; - else - character_count++; + cursor_from_char_ofs( editor, start + i, &cursor ); + if (cursor.run->reobj) object_count++; + else character_count++; if (character_count >= 2 && object_count >= 2) return (SEL_TEXT | SEL_MULTICHAR | SEL_OBJECT | SEL_MULTIOBJECT); } @@ -3037,49 +2910,54 @@ static LONG ME_GetSelectionType(ME_TextEditor *editor) static BOOL ME_ShowContextMenu(ME_TextEditor *editor, int x, int y) { - CHARRANGE selrange; - HMENU menu; - int seltype; - - if(!editor->lpOleCallback || !editor->hWnd) - return FALSE; - ME_GetSelectionOfs(editor, &selrange.cpMin, &selrange.cpMax); - seltype = ME_GetSelectionType(editor); - if(SUCCEEDED(IRichEditOleCallback_GetContextMenu(editor->lpOleCallback, seltype, NULL, &selrange, &menu))) - { - TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, 0, editor->hwndParent, NULL); - DestroyMenu(menu); - } - return TRUE; + CHARRANGE selrange; + HMENU menu; + int seltype; + HWND hwnd, parent; + + if (!editor->lpOleCallback || !editor->have_texthost2) return FALSE; + if (FAILED( ITextHost2_TxGetWindow( editor->texthost, &hwnd ))) return FALSE; + parent = GetParent( hwnd ); + if (!parent) parent = hwnd; + + ME_GetSelectionOfs( editor, &selrange.cpMin, &selrange.cpMax ); + seltype = ME_GetSelectionType( editor ); + if (SUCCEEDED( IRichEditOleCallback_GetContextMenu( editor->lpOleCallback, seltype, NULL, &selrange, &menu ) )) + { + TrackPopupMenu( menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, 0, parent, NULL ); + DestroyMenu( menu ); + } + return TRUE; } ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) { ME_TextEditor *ed = heap_alloc(sizeof(*ed)); int i; - DWORD props; LONG selbarwidth; + HRESULT hr; - ed->hWnd = NULL; - ed->hwndParent = NULL; ed->sizeWindow.cx = ed->sizeWindow.cy = 0; - ed->texthost = texthost; - ed->reOle = NULL; + if (ITextHost_QueryInterface( texthost, &IID_ITextHost2, (void **)&ed->texthost ) == S_OK) + { + ITextHost_Release( texthost ); + ed->have_texthost2 = TRUE; + } + else + { + ed->texthost = (ITextHost2 *)texthost; + ed->have_texthost2 = FALSE; + } + ed->bEmulateVersion10 = bEmulateVersion10; - ed->styleFlags = 0; - ed->exStyleFlags = 0; - ed->first_marked_para = NULL; + ed->in_place_active = FALSE; ed->total_rows = 0; - ITextHost_TxGetPropertyBits(texthost, - (TXTBIT_RICHTEXT|TXTBIT_MULTILINE| - TXTBIT_READONLY|TXTBIT_USEPASSWORD| - TXTBIT_HIDESELECTION|TXTBIT_SAVESELECTION| - TXTBIT_AUTOWORDSEL|TXTBIT_VERTICAL| - TXTBIT_WORDWRAP|TXTBIT_DISABLEDRAG), - &props); - ITextHost_TxGetScrollBars(texthost, &ed->styleFlags); - ed->styleFlags &= (WS_VSCROLL|WS_HSCROLL|ES_AUTOVSCROLL| - ES_AUTOHSCROLL|ES_DISABLENOSCROLL); + ITextHost_TxGetPropertyBits( ed->texthost, TXTBIT_RICHTEXT | TXTBIT_MULTILINE | TXTBIT_READONLY | + TXTBIT_USEPASSWORD | TXTBIT_HIDESELECTION | TXTBIT_SAVESELECTION | + TXTBIT_AUTOWORDSEL | TXTBIT_VERTICAL | TXTBIT_WORDWRAP | TXTBIT_ALLOWBEEP | + TXTBIT_DISABLEDRAG, + &ed->props ); + ITextHost_TxGetScrollBars( ed->texthost, &ed->scrollbars ); ed->pBuffer = ME_MakeText(); ed->nZoomNumerator = ed->nZoomDenominator = 0; ed->nAvailWidth = 0; /* wrap to client area */ @@ -3100,9 +2978,6 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ed->nLastTotalLength = ed->nTotalLength = 0; ed->nLastTotalWidth = ed->nTotalWidth = 0; ed->nUDArrowX = -1; - ed->rgbBackColor = -1; - ed->hbrBackground = GetSysColorBrush(COLOR_WINDOW); - ed->bCaretAtEnd = FALSE; ed->nEventMask = 0; ed->nModifyStep = 0; ed->nTextLimit = TEXT_LIMIT_DEFAULT; @@ -3113,15 +2988,15 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ed->nUndoMode = umAddToUndo; ed->nParagraphs = 1; ed->nLastSelStart = ed->nLastSelEnd = 0; - ed->pLastSelStartPara = ed->pLastSelEndPara = ed->pCursors[0].pPara; + ed->last_sel_start_para = ed->last_sel_end_para = ed->pCursors[0].para; ed->bHideSelection = FALSE; ed->pfnWordBreak = NULL; + ed->richole = NULL; ed->lpOleCallback = NULL; ed->mode = TM_MULTILEVELUNDO | TM_MULTICODEPAGE; - ed->mode |= (props & TXTBIT_RICHTEXT) ? TM_RICHTEXT : TM_PLAINTEXT; + ed->mode |= (ed->props & TXTBIT_RICHTEXT) ? TM_RICHTEXT : TM_PLAINTEXT; ed->AutoURLDetect_bEnable = FALSE; ed->bHaveFocus = FALSE; - ed->bDialogMode = FALSE; ed->bMouseCaptured = FALSE; ed->caret_hidden = FALSE; ed->caret_height = 0; @@ -3134,39 +3009,17 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ME_CheckCharOffsets(ed); SetRectEmpty(&ed->rcFormat); - ed->bDefaultFormatRect = TRUE; - ITextHost_TxGetSelectionBarWidth(ed->texthost, &selbarwidth); - if (selbarwidth) { - /* FIXME: Convert selbarwidth from HIMETRIC to pixels */ - ed->selofs = SELECTIONBAR_WIDTH; - ed->styleFlags |= ES_SELECTIONBAR; - } else { - ed->selofs = 0; - } + hr = ITextHost_TxGetSelectionBarWidth( ed->texthost, &selbarwidth ); + /* FIXME: Convert selbarwidth from HIMETRIC to pixels */ + if (hr == S_OK && selbarwidth) ed->selofs = SELECTIONBAR_WIDTH; + else ed->selofs = 0; ed->nSelectionType = stPosition; - ed->cPasswordMask = 0; - if (props & TXTBIT_USEPASSWORD) - ITextHost_TxGetPasswordChar(texthost, &ed->cPasswordMask); - - if (props & TXTBIT_AUTOWORDSEL) - ed->styleFlags |= ECO_AUTOWORDSELECTION; - if (props & TXTBIT_MULTILINE) { - ed->styleFlags |= ES_MULTILINE; - ed->bWordWrap = (props & TXTBIT_WORDWRAP) != 0; - } else { - ed->bWordWrap = FALSE; - } - if (props & TXTBIT_READONLY) - ed->styleFlags |= ES_READONLY; - if (!(props & TXTBIT_HIDESELECTION)) - ed->styleFlags |= ES_NOHIDESEL; - if (props & TXTBIT_SAVESELECTION) - ed->styleFlags |= ES_SAVESEL; - if (props & TXTBIT_VERTICAL) - ed->styleFlags |= ES_VERTICAL; - if (props & TXTBIT_DISABLEDRAG) - ed->styleFlags |= ES_NOOLEDRAGDROP; + ed->password_char = 0; + if (ed->props & TXTBIT_USEPASSWORD) + ITextHost_TxGetPasswordChar( ed->texthost, &ed->password_char ); + + ed->bWordWrap = (ed->props & TXTBIT_WORDWRAP) && (ed->props & TXTBIT_MULTILINE); ed->notified_cr.cpMin = ed->notified_cr.cpMax = 0; @@ -3176,15 +3029,34 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ed->vert_si.nMax = 0; ed->vert_si.nPage = 0; ed->vert_si.nPos = 0; + ed->vert_sb_enabled = 0; ed->horz_si.cbSize = sizeof(SCROLLINFO); ed->horz_si.nMin = 0; ed->horz_si.nMax = 0; ed->horz_si.nPage = 0; ed->horz_si.nPos = 0; + ed->horz_sb_enabled = 0; + + if (ed->scrollbars & ES_DISABLENOSCROLL) + { + if (ed->scrollbars & WS_VSCROLL) + { + ITextHost_TxSetScrollRange( ed->texthost, SB_VERT, 0, 1, TRUE ); + ITextHost_TxEnableScrollBar( ed->texthost, SB_VERT, ESB_DISABLE_BOTH ); + } + if (ed->scrollbars & WS_HSCROLL) + { + ITextHost_TxSetScrollRange( ed->texthost, SB_HORZ, 0, 1, TRUE ); + ITextHost_TxEnableScrollBar( ed->texthost, SB_HORZ, ESB_DISABLE_BOTH ); + } + } ed->wheel_remain = 0; + ed->back_style = TXTBACK_OPAQUE; + ITextHost_TxGetBackStyle( ed->texthost, &ed->back_style ); + list_init( &ed->reobj_list ); OleInitialize(NULL); @@ -3200,10 +3072,11 @@ void ME_DestroyEditor(ME_TextEditor *editor) ME_ClearTempStyle(editor); ME_EmptyUndoStack(editor); editor->pBuffer->pFirst = NULL; - while(p) { + while(p) + { pNext = p->next; if (p->type == diParagraph) - destroy_para(editor, p); + para_destroy( editor, &p->member.para ); else ME_DestroyDisplayItem(p); p = pNext; @@ -3218,16 +3091,9 @@ void ME_DestroyEditor(ME_TextEditor *editor) if (editor->pFontCache[i].hFont) DeleteObject(editor->pFontCache[i].hFont); } - if (editor->rgbBackColor != -1) - DeleteObject(editor->hbrBackground); if(editor->lpOleCallback) IRichEditOleCallback_Release(editor->lpOleCallback); - ITextHost_Release(editor->texthost); - if (editor->reOle) - { - IUnknown_Release(editor->reOle); - editor->reOle = NULL; - } + OleUninitialize(); heap_free(editor->pBuffer); @@ -3235,37 +3101,6 @@ void ME_DestroyEditor(ME_TextEditor *editor) heap_free(editor); } -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - TRACE("\n"); - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls(hinstDLL); - me_heap = HeapCreate (0, 0x10000, 0); - if (!ME_RegisterEditorClass(hinstDLL)) return FALSE; - hLeft = LoadCursorW(hinstDLL, MAKEINTRESOURCEW(OCR_REVERSE)); - LookupInit(); - break; - - case DLL_PROCESS_DETACH: - if (lpvReserved) break; - UnregisterClassW(RICHEDIT_CLASS20W, 0); - UnregisterClassW(MSFTEDIT_CLASS, 0); - UnregisterClassA(RICHEDIT_CLASS20A, 0); - UnregisterClassA("RichEdit50A", 0); - if (ME_ListBoxRegistered) - UnregisterClassW(REListBox20W, 0); - if (ME_ComboBoxRegistered) - UnregisterClassW(REComboBox20W, 0); - LookupCleanup(); - HeapDestroy (me_heap); - release_typelib(); - break; - } - return TRUE; -} - static inline int get_default_line_height( ME_TextEditor *editor ) { int height = 0; @@ -3284,158 +3119,21 @@ static inline int calc_wheel_change( int *remain, int amount_per_click ) return change; } -static const char * const edit_messages[] = { - "EM_GETSEL", - "EM_SETSEL", - "EM_GETRECT", - "EM_SETRECT", - "EM_SETRECTNP", - "EM_SCROLL", - "EM_LINESCROLL", - "EM_SCROLLCARET", - "EM_GETMODIFY", - "EM_SETMODIFY", - "EM_GETLINECOUNT", - "EM_LINEINDEX", - "EM_SETHANDLE", - "EM_GETHANDLE", - "EM_GETTHUMB", - "EM_UNKNOWN_BF", - "EM_UNKNOWN_C0", - "EM_LINELENGTH", - "EM_REPLACESEL", - "EM_UNKNOWN_C3", - "EM_GETLINE", - "EM_LIMITTEXT", - "EM_CANUNDO", - "EM_UNDO", - "EM_FMTLINES", - "EM_LINEFROMCHAR", - "EM_UNKNOWN_CA", - "EM_SETTABSTOPS", - "EM_SETPASSWORDCHAR", - "EM_EMPTYUNDOBUFFER", - "EM_GETFIRSTVISIBLELINE", - "EM_SETREADONLY", - "EM_SETWORDBREAKPROC", - "EM_GETWORDBREAKPROC", - "EM_GETPASSWORDCHAR", - "EM_SETMARGINS", - "EM_GETMARGINS", - "EM_GETLIMITTEXT", - "EM_POSFROMCHAR", - "EM_CHARFROMPOS", - "EM_SETIMESTATUS", - "EM_GETIMESTATUS" -}; - -static const char * const richedit_messages[] = { - "EM_CANPASTE", - "EM_DISPLAYBAND", - "EM_EXGETSEL", - "EM_EXLIMITTEXT", - "EM_EXLINEFROMCHAR", - "EM_EXSETSEL", - "EM_FINDTEXT", - "EM_FORMATRANGE", - "EM_GETCHARFORMAT", - "EM_GETEVENTMASK", - "EM_GETOLEINTERFACE", - "EM_GETPARAFORMAT", - "EM_GETSELTEXT", - "EM_HIDESELECTION", - "EM_PASTESPECIAL", - "EM_REQUESTRESIZE", - "EM_SELECTIONTYPE", - "EM_SETBKGNDCOLOR", - "EM_SETCHARFORMAT", - "EM_SETEVENTMASK", - "EM_SETOLECALLBACK", - "EM_SETPARAFORMAT", - "EM_SETTARGETDEVICE", - "EM_STREAMIN", - "EM_STREAMOUT", - "EM_GETTEXTRANGE", - "EM_FINDWORDBREAK", - "EM_SETOPTIONS", - "EM_GETOPTIONS", - "EM_FINDTEXTEX", - "EM_GETWORDBREAKPROCEX", - "EM_SETWORDBREAKPROCEX", - "EM_SETUNDOLIMIT", - "EM_UNKNOWN_USER_83", - "EM_REDO", - "EM_CANREDO", - "EM_GETUNDONAME", - "EM_GETREDONAME", - "EM_STOPGROUPTYPING", - "EM_SETTEXTMODE", - "EM_GETTEXTMODE", - "EM_AUTOURLDETECT", - "EM_GETAUTOURLDETECT", - "EM_SETPALETTE", - "EM_GETTEXTEX", - "EM_GETTEXTLENGTHEX", - "EM_SHOWSCROLLBAR", - "EM_SETTEXTEX", - "EM_UNKNOWN_USER_98", - "EM_UNKNOWN_USER_99", - "EM_SETPUNCTUATION", - "EM_GETPUNCTUATION", - "EM_SETWORDWRAPMODE", - "EM_GETWORDWRAPMODE", - "EM_SETIMECOLOR", - "EM_GETIMECOLOR", - "EM_SETIMEOPTIONS", - "EM_GETIMEOPTIONS", - "EM_CONVPOSITION", - "EM_UNKNOWN_USER_109", - "EM_UNKNOWN_USER_110", - "EM_UNKNOWN_USER_111", - "EM_UNKNOWN_USER_112", - "EM_UNKNOWN_USER_113", - "EM_UNKNOWN_USER_114", - "EM_UNKNOWN_USER_115", - "EM_UNKNOWN_USER_116", - "EM_UNKNOWN_USER_117", - "EM_UNKNOWN_USER_118", - "EM_UNKNOWN_USER_119", - "EM_SETLANGOPTIONS", - "EM_GETLANGOPTIONS", - "EM_GETIMECOMPMODE", - "EM_FINDTEXTW", - "EM_FINDTEXTEXW", - "EM_RECONVERSION", - "EM_SETIMEMODEBIAS", - "EM_GETIMEMODEBIAS" -}; - -static const char * -get_msg_name(UINT msg) -{ - if (msg >= EM_GETSEL && msg <= EM_CHARFROMPOS) - return edit_messages[msg - EM_GETSEL]; - if (msg >= EM_CANPASTE && msg <= EM_GETIMEMODEBIAS) - return richedit_messages[msg - EM_CANPASTE]; - return ""; -} - -static void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam) +void link_notify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam) { int x,y; BOOL isExact; ME_Cursor cursor; /* The start of the clicked text. */ - + ME_Run *run; ENLINK info; + x = (short)LOWORD(lParam); y = (short)HIWORD(lParam); ME_CharFromPos(editor, x, y, &cursor, &isExact); if (!isExact) return; - if (is_link( &cursor.pRun->member.run )) + if (is_link( cursor.run )) { /* The clicked run has CFE_LINK set */ - ME_DisplayItem *di; - info.nmhdr.hwndFrom = NULL; info.nmhdr.idFrom = 0; info.nmhdr.code = EN_LINK; @@ -3446,15 +3144,15 @@ static void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM /* find the first contiguous run with CFE_LINK set */ info.chrg.cpMin = ME_GetCursorOfs(&cursor); - di = cursor.pRun; - while (ME_PrevRun( NULL, &di, FALSE ) && is_link( &di->member.run )) - info.chrg.cpMin -= di->member.run.len; + run = cursor.run; + while ((run = run_prev( run )) && is_link( run )) + info.chrg.cpMin -= run->len; /* find the last contiguous run with CFE_LINK set */ - info.chrg.cpMax = ME_GetCursorOfs(&cursor) + cursor.pRun->member.run.len; - di = cursor.pRun; - while (ME_NextRun( NULL, &di, FALSE ) && is_link( &di->member.run )) - info.chrg.cpMax += di->member.run.len; + info.chrg.cpMax = ME_GetCursorOfs(&cursor) + cursor.run->len; + run = cursor.run; + while ((run = run_next( run )) && is_link( run )) + info.chrg.cpMax += run->len; ITextHost_TxNotify(editor->texthost, info.nmhdr.code, &info); } @@ -3494,52 +3192,6 @@ static void ME_SetText(ME_TextEditor *editor, void *text, BOOL unicode) ME_EndToUnicode(codepage, wszText); } -static LRESULT ME_WmCreate(ME_TextEditor *editor, LPARAM lParam, BOOL unicode) -{ - CREATESTRUCTW *createW = (CREATESTRUCTW*)lParam; - CREATESTRUCTA *createA = (CREATESTRUCTA*)lParam; - void *text = NULL; - INT max; - - if (lParam) - text = unicode ? (void*)createW->lpszName : (void*)createA->lpszName; - - ME_SetDefaultFormatRect(editor); - - max = (editor->styleFlags & ES_DISABLENOSCROLL) ? 1 : 0; - if (~editor->styleFlags & ES_DISABLENOSCROLL || editor->styleFlags & WS_VSCROLL) - ITextHost_TxSetScrollRange(editor->texthost, SB_VERT, 0, max, TRUE); - - if (~editor->styleFlags & ES_DISABLENOSCROLL || editor->styleFlags & WS_HSCROLL) - ITextHost_TxSetScrollRange(editor->texthost, SB_HORZ, 0, max, TRUE); - - if (editor->styleFlags & ES_DISABLENOSCROLL) - { - if (editor->styleFlags & WS_VSCROLL) - { - ITextHost_TxEnableScrollBar(editor->texthost, SB_VERT, ESB_DISABLE_BOTH); - ITextHost_TxShowScrollBar(editor->texthost, SB_VERT, TRUE); - } - if (editor->styleFlags & WS_HSCROLL) - { - ITextHost_TxEnableScrollBar(editor->texthost, SB_HORZ, ESB_DISABLE_BOTH); - ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ, TRUE); - } - } - - if (text) - { - ME_SetText(editor, text, unicode); - ME_SetCursorToStart(editor, &editor->pCursors[0]); - ME_SetCursorToStart(editor, &editor->pCursors[1]); - } - - ME_CommitUndo(editor); - ME_WrapMarkedParagraphs(editor); - update_caret(editor); - return 0; -} - static LRESULT handle_EM_SETCHARFORMAT( ME_TextEditor *editor, WPARAM flags, const CHARFORMAT2W *fmt_in ) { CHARFORMAT2W fmt; @@ -3601,8 +3253,8 @@ static LRESULT handle_EM_SETCHARFORMAT( ME_TextEditor *editor, WPARAM flags, con * The LRESULT that is returned is a return value for window procs, * and the phresult parameter is the COM return code needed by the * text services interface. */ -LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, - LPARAM lParam, BOOL unicode, HRESULT* phresult) +LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam, + LPARAM lParam, HRESULT* phresult ) { *phresult = S_OK; @@ -3637,18 +3289,6 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, return ME_StreamIn(editor, wParam, (EDITSTREAM*)lParam, TRUE); case EM_STREAMOUT: return ME_StreamOut(editor, wParam, (EDITSTREAM *)lParam); - case WM_GETDLGCODE: - { - UINT code = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS; - - if (lParam) - editor->bDialogMode = TRUE; - if (editor->styleFlags & ES_MULTILINE) - code |= DLGC_WANTMESSAGE; - if (!(editor->styleFlags & ES_SAVESEL)) - code |= DLGC_HASSETSEL; - return code; - } case EM_EMPTYUNDOBUFFER: ME_EmptyUndoStack(editor); return 0; @@ -3690,16 +3330,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, return ME_Undo(editor); case EM_REDO: return ME_Redo(editor); - case EM_GETOPTIONS: - { - /* these flags are equivalent to the ES_* counterparts */ - DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL | - ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN | ECO_SELECTIONBAR; - DWORD settings = editor->styleFlags & mask; - - return settings; - } - case EM_SETFONTSIZE: + case EM_SETFONTSIZE: { CHARFORMAT2W cf; LONG tmp_size, size; @@ -3740,68 +3371,6 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, return TRUE; } - case EM_SETOPTIONS: - { - /* these flags are equivalent to ES_* counterparts, except for - * ECO_AUTOWORDSELECTION that doesn't have an ES_* counterpart, - * but is still stored in editor->styleFlags. */ - const DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL | - ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN | - ECO_SELECTIONBAR | ECO_AUTOWORDSELECTION; - DWORD settings = mask & editor->styleFlags; - DWORD oldSettings = settings; - DWORD changedSettings; - - switch(wParam) - { - case ECOOP_SET: - settings = lParam; - break; - case ECOOP_OR: - settings |= lParam; - break; - case ECOOP_AND: - settings &= lParam; - break; - case ECOOP_XOR: - settings ^= lParam; - } - changedSettings = oldSettings ^ settings; - - if (changedSettings) { - editor->styleFlags = (editor->styleFlags & ~mask) | (settings & mask); - - if (changedSettings & ECO_SELECTIONBAR) - { - ITextHost_TxInvalidateRect(editor->texthost, &editor->rcFormat, TRUE); - if (settings & ECO_SELECTIONBAR) { - assert(!editor->selofs); - editor->selofs = SELECTIONBAR_WIDTH; - editor->rcFormat.left += editor->selofs; - } else { - editor->rcFormat.left -= editor->selofs; - editor->selofs = 0; - } - ME_RewrapRepaint(editor); - } - - if ((changedSettings & settings & ES_NOHIDESEL) && !editor->bHaveFocus) - ME_InvalidateSelection( editor ); - - if (changedSettings & settings & ECO_VERTICAL) - FIXME("ECO_VERTICAL not implemented yet!\n"); - if (changedSettings & settings & ECO_AUTOHSCROLL) - FIXME("ECO_AUTOHSCROLL not implemented yet!\n"); - if (changedSettings & settings & ECO_AUTOVSCROLL) - FIXME("ECO_AUTOVSCROLL not implemented yet!\n"); - if (changedSettings & settings & ECO_WANTRETURN) - FIXME("ECO_WANTRETURN not implemented yet!\n"); - if (changedSettings & settings & ECO_AUTOWORDSELECTION) - FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n"); - } - - return settings; - } case EM_SETSEL: { return set_selection( editor, wParam, lParam ); @@ -3809,7 +3378,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case EM_SETSCROLLPOS: { POINT *point = (POINT *)lParam; - ME_ScrollAbs(editor, point->x, point->y); + scroll_abs( editor, point->x, point->y, TRUE ); return 0; } case EM_AUTOURLDETECT: @@ -3831,39 +3400,6 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, return set_selection( editor, range.cpMin, range.cpMax ); } - case EM_SHOWSCROLLBAR: - { - DWORD flags; - - switch (wParam) - { - case SB_HORZ: - flags = WS_HSCROLL; - break; - case SB_VERT: - flags = WS_VSCROLL; - break; - case SB_BOTH: - flags = WS_HSCROLL|WS_VSCROLL; - break; - default: - return 0; - } - - if (lParam) { - editor->styleFlags |= flags; - if (flags & WS_HSCROLL) - ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ, - editor->nTotalWidth > editor->sizeWindow.cx); - if (flags & WS_VSCROLL) - ITextHost_TxShowScrollBar(editor->texthost, SB_VERT, - editor->nTotalLength > editor->sizeWindow.cy); - } else { - editor->styleFlags &= ~flags; - ITextHost_TxShowScrollBar(editor->texthost, wParam, FALSE); - } - return 0; - } case EM_SETTEXTEX: { LPWSTR wszText; @@ -3938,28 +3474,6 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case EM_SELECTIONTYPE: return ME_GetSelectionType(editor); - case EM_SETBKGNDCOLOR: - { - LRESULT lColor; - if (editor->rgbBackColor != -1) { - DeleteObject(editor->hbrBackground); - lColor = editor->rgbBackColor; - } - else lColor = ITextHost_TxGetSysColor(editor->texthost, COLOR_WINDOW); - - if (wParam) - { - editor->rgbBackColor = -1; - editor->hbrBackground = GetSysColorBrush(COLOR_WINDOW); - } - else - { - editor->rgbBackColor = lParam; - editor->hbrBackground = CreateSolidBrush(editor->rgbBackColor); - } - ITextHost_TxInvalidateRect(editor->texthost, NULL, TRUE); - return lColor; - } case EM_GETMODIFY: return editor->nModifyStep == 0 ? 0 : -1; case EM_SETMODIFY: @@ -3971,14 +3485,6 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, return 0; } - case EM_SETREADONLY: - { - if (wParam) - editor->styleFlags |= ES_READONLY; - else - editor->styleFlags &= ~ES_READONLY; - return 1; - } case EM_SETEVENTMASK: { DWORD nOldMask = editor->nEventMask; @@ -4008,36 +3514,35 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case EM_SETPARAFORMAT: { - BOOL result = ME_SetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam); + BOOL result = editor_set_selection_para_fmt( editor, (PARAFORMAT2 *)lParam ); ME_WrapMarkedParagraphs(editor); ME_UpdateScrollBar(editor); ME_CommitUndo(editor); return result; } case EM_GETPARAFORMAT: - ME_GetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam); + editor_get_selection_para_fmt( editor, (PARAFORMAT2 *)lParam ); return ((PARAFORMAT2 *)lParam)->dwMask; case EM_GETFIRSTVISIBLELINE: { - ME_DisplayItem *p = editor->pBuffer->pFirst; + ME_Paragraph *para = editor_first_para( editor ); + ME_Row *row; int y = editor->vert_si.nPos; - int ypara = 0; int count = 0; - int ystart, yend; - while(p) { - p = ME_FindItemFwd(p, diStartRowOrParagraphOrEnd); - if (p->type == diTextEnd) - break; - if (p->type == diParagraph) { - ypara = p->member.para.pt.y; - continue; - } - ystart = ypara + p->member.row.pt.y; - yend = ystart + p->member.row.nHeight; - if (y < yend) { - break; - } + + while (para_next( para )) + { + if (y < para->pt.y + para->nHeight) break; + count += para->nRows; + para = para_next( para ); + } + + row = para_first_row( para ); + while (row) + { + if (y < para->pt.y + row->pt.y + row->nHeight) break; count++; + row = row_next( row ); } return count; } @@ -4049,7 +3554,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case EM_LINESCROLL: { - if (!(editor->styleFlags & ES_MULTILINE)) + if (!(editor->props & TXTBIT_MULTILINE)) return FALSE; ME_ScrollDown( editor, lParam * get_default_line_height( editor ) ); return TRUE; @@ -4065,18 +3570,15 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case EM_REPLACESEL: { - int len = 0; - LONG codepage = unicode ? CP_UNICODE : CP_ACP; - LPWSTR wszText = ME_ToUnicode(codepage, (void *)lParam, &len); + WCHAR *text = (WCHAR *)lParam; + int len = text ? lstrlenW( text ) : 0; - TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText)); - - ME_ReplaceSel(editor, !!wParam, wszText, len); - ME_EndToUnicode(codepage, wszText); + TRACE( "EM_REPLACESEL - %s\n", debugstr_w( text ) ); + ME_ReplaceSel( editor, !!wParam, text, len ); return len; } case EM_SCROLLCARET: - ME_EnsureVisible(editor, &editor->pCursors[0]); + editor_ensure_visible( editor, &editor->pCursors[0] ); return 0; case WM_SETFONT: { @@ -4102,7 +3604,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, ME_SetDefaultCharFormat(editor, &fmt); ME_CommitUndo(editor); - ME_MarkAllForWrapping(editor); + editor_mark_rewrap_all( editor ); ME_WrapMarkedParagraphs(editor); ME_UpdateScrollBar(editor); if (bRepaint) @@ -4132,7 +3634,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, ME_StreamInRTFString(editor, 0, (char *)lParam); } else - ME_SetText(editor, (void*)lParam, unicode); + ME_SetText( editor, (void*)lParam, TRUE ); } else TRACE("WM_SETTEXT - NULL\n"); @@ -4162,10 +3664,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case WM_GETTEXTLENGTH: { GETTEXTLENGTHEX how; - - /* CR/LF conversion required in 2.0 mode, verbatim in 1.0 mode */ how.flags = GTL_CLOSE | (editor->bEmulateVersion10 ? 0 : GTL_USECRLF) | GTL_NUMCHARS; - how.codepage = unicode ? CP_UNICODE : CP_ACP; + how.codepage = CP_UNICODE; return ME_GetTextLengthEx(editor, &how); } case EM_GETTEXTLENGTHEX: @@ -4173,9 +3673,9 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case WM_GETTEXT: { GETTEXTEX ex; - ex.cb = wParam * (unicode ? sizeof(WCHAR) : sizeof(CHAR)); + ex.cb = wParam * sizeof(WCHAR); ex.flags = GT_USECRLF; - ex.codepage = unicode ? CP_UNICODE : CP_ACP; + ex.codepage = CP_UNICODE; ex.lpDefaultChar = NULL; ex.lpUsedDefChar = NULL; return ME_GetTextEx(editor, &ex, lParam); @@ -4186,8 +3686,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, { int nFrom, nTo, nStartCur = ME_GetSelectionOfs(editor, &nFrom, &nTo); ME_Cursor *from = &editor->pCursors[nStartCur]; - return ME_GetTextRange(editor, (WCHAR *)lParam, from, - nTo - nFrom, unicode); + return get_text_range( editor, (WCHAR *)lParam, from, nTo - nFrom ); } case EM_GETSCROLLPOS: { @@ -4209,122 +3708,106 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, int nEnd = rng->chrg.cpMax; int textlength = ME_GetTextLength(editor); - TRACE("EM_GETTEXTRANGE min=%d max=%d unicode=%d textlength=%d\n", - rng->chrg.cpMin, rng->chrg.cpMax, unicode, textlength); + TRACE( "EM_GETTEXTRANGE min = %d max = %d textlength = %d\n", rng->chrg.cpMin, rng->chrg.cpMax, textlength ); if (nStart < 0) return 0; if ((nStart == 0 && nEnd == -1) || nEnd > textlength) nEnd = textlength; if (nStart >= nEnd) return 0; - ME_CursorFromCharOfs(editor, nStart, &start); - return ME_GetTextRange(editor, rng->lpstrText, &start, nEnd - nStart, unicode); + cursor_from_char_ofs( editor, nStart, &start ); + return get_text_range( editor, rng->lpstrText, &start, nEnd - nStart ); } case EM_GETLINE: { - ME_DisplayItem *run; + ME_Row *row; + ME_Run *run; const unsigned int nMaxChars = *(WORD *) lParam; unsigned int nCharsLeft = nMaxChars; char *dest = (char *) lParam; - BOOL wroteNull = FALSE; + ME_Cursor start, end; - TRACE("EM_GETLINE: row=%d, nMaxChars=%d (%s)\n", (int) wParam, nMaxChars, - unicode ? "Unicode" : "Ansi"); + TRACE( "EM_GETLINE: row=%d, nMaxChars=%d\n", (int)wParam, nMaxChars ); - run = ME_FindRowWithNumber(editor, wParam); - if (run == NULL) - return 0; + row = row_from_row_number( editor, wParam ); + if (row == NULL) return 0; - while (nCharsLeft && (run = ME_FindItemFwd(run, diRunOrStartRow)) - && run->type == diRun) + row_first_cursor( row, &start ); + row_end_cursor( row, &end, TRUE ); + run = start.run; + while (nCharsLeft) { - WCHAR *str = get_text( &run->member.run, 0 ); + WCHAR *str; unsigned int nCopy; + int ofs = (run == start.run) ? start.nOffset : 0; + int len = (run == end.run) ? end.nOffset : run->len; - nCopy = min(nCharsLeft, run->member.run.len); + str = get_text( run, ofs ); + nCopy = min( nCharsLeft, len ); - if (unicode) - memcpy(dest, str, nCopy * sizeof(WCHAR)); - else - nCopy = WideCharToMultiByte(CP_ACP, 0, str, nCopy, dest, - nCharsLeft, NULL, NULL); - dest += nCopy * (unicode ? sizeof(WCHAR) : 1); + memcpy(dest, str, nCopy * sizeof(WCHAR)); + dest += nCopy * sizeof(WCHAR); nCharsLeft -= nCopy; + if (run == end.run) break; + run = row_next_run( row, run ); } /* append line termination, space allowing */ - if (nCharsLeft > 0) - { - if (unicode) - *((WCHAR *)dest) = '\0'; - else - *dest = '\0'; - nCharsLeft--; - wroteNull = TRUE; - } + if (nCharsLeft > 0) *((WCHAR *)dest) = '\0'; TRACE("EM_GETLINE: got %u characters\n", nMaxChars - nCharsLeft); - return nMaxChars - nCharsLeft - (wroteNull ? 1 : 0); + return nMaxChars - nCharsLeft; } case EM_GETLINECOUNT: { - ME_DisplayItem *item = editor->pBuffer->pLast; - int nRows = editor->total_rows; - ME_DisplayItem *prev_para = NULL, *last_para = NULL; - - last_para = ME_FindItemBack(item, diRun); - prev_para = ME_FindItemBack(last_para, diRun); - assert(last_para); - assert(last_para->member.run.nFlags & MERF_ENDPARA); - if (editor->bEmulateVersion10 && prev_para && - last_para->member.run.nCharOfs == 0 && - prev_para->member.run.len == 1 && - *get_text( &prev_para->member.run, 0 ) == '\r') + int count = editor->total_rows; + ME_Run *prev_run, *last_run; + + last_run = para_end_run( para_prev( editor_end_para( editor ) ) ); + prev_run = run_prev_all_paras( last_run ); + + if (editor->bEmulateVersion10 && prev_run && last_run->nCharOfs == 0 && + prev_run->len == 1 && *get_text( prev_run, 0 ) == '\r') { /* In 1.0 emulation, the last solitary \r at the very end of the text (if one exists) is NOT a line break. FIXME: this is an ugly hack. This should have a more regular model. */ - nRows--; + count--; } - TRACE("EM_GETLINECOUNT: nRows==%d\n", nRows); - return max(1, nRows); + count = max(1, count); + TRACE("EM_GETLINECOUNT: count==%d\n", count); + return count; } case EM_LINEFROMCHAR: { - if (wParam == -1) - return ME_RowNumberFromCharOfs(editor, ME_GetCursorOfs(&editor->pCursors[1])); - else - return ME_RowNumberFromCharOfs(editor, wParam); + if (wParam == -1) wParam = ME_GetCursorOfs( editor->pCursors + 1 ); + return row_number_from_char_ofs( editor, wParam ); } case EM_EXLINEFROMCHAR: { - if (lParam == -1) - return ME_RowNumberFromCharOfs(editor, ME_GetCursorOfs(&editor->pCursors[1])); - else - return ME_RowNumberFromCharOfs(editor, lParam); + if (lParam == -1) lParam = ME_GetCursorOfs( editor->pCursors + 1 ); + return row_number_from_char_ofs( editor, lParam ); } case EM_LINEINDEX: { - ME_DisplayItem *item, *para; - int nCharOfs; + ME_Row *row; + ME_Cursor cursor; + int ofs; - if (wParam == -1) - item = ME_FindItemBack(editor->pCursors[0].pRun, diStartRow); - else - item = ME_FindRowWithNumber(editor, wParam); - if (!item) - return -1; - para = ME_GetParagraph(item); - item = ME_FindItemFwd(item, diRun); - nCharOfs = para->member.para.nCharOfs + item->member.run.nCharOfs; - TRACE("EM_LINEINDEX: nCharOfs==%d\n", nCharOfs); - return nCharOfs; + if (wParam == -1) row = row_from_cursor( editor->pCursors ); + else row = row_from_row_number( editor, wParam ); + if (!row) return -1; + + row_first_cursor( row, &cursor ); + ofs = ME_GetCursorOfs( &cursor ); + TRACE( "EM_LINEINDEX: nCharOfs==%d\n", ofs ); + return ofs; } case EM_LINELENGTH: { - ME_DisplayItem *item, *item_end; - int nChars = 0, nThisLineOfs = 0, nNextLineOfs = 0; - ME_DisplayItem *para, *run; + ME_Row *row; + int start_ofs, end_ofs; + ME_Cursor cursor; if (wParam > ME_GetTextLength(editor)) return 0; @@ -4333,20 +3816,14 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, FIXME("EM_LINELENGTH: returning number of unselected characters on lines with selection unsupported.\n"); return 0; } - ME_RunOfsFromCharOfs(editor, wParam, ¶, &run, NULL); - item = ME_RowStart(run); - nThisLineOfs = ME_CharOfsFromRunOfs(editor, para, ME_FindItemFwd(item, diRun), 0); - item_end = ME_FindItemFwd(item, diStartRowOrParagraphOrEnd); - if (item_end->type == diStartRow) { - nNextLineOfs = ME_CharOfsFromRunOfs(editor, para, ME_FindItemFwd(item_end, diRun), 0); - } else { - ME_DisplayItem *endRun = ME_FindItemBack(item_end, diRun); - assert(endRun && endRun->member.run.nFlags & MERF_ENDPARA); - nNextLineOfs = item_end->member.para.nCharOfs - endRun->member.run.len; - } - nChars = nNextLineOfs - nThisLineOfs; - TRACE("EM_LINELENGTH(%ld)==%d\n",wParam, nChars); - return nChars; + cursor_from_char_ofs( editor, wParam, &cursor ); + row = row_from_cursor( &cursor ); + row_first_cursor( row, &cursor ); + start_ofs = ME_GetCursorOfs( &cursor ); + row_end_cursor( row, &cursor, FALSE ); + end_ofs = ME_GetCursorOfs( &cursor ); + TRACE( "EM_LINELENGTH(%ld)==%d\n", wParam, end_ofs - start_ofs ); + return end_ofs - start_ofs; } case EM_EXLIMITTEXT: { @@ -4371,46 +3848,12 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, return editor->nTextLimit; } case EM_FINDTEXT: - { - LRESULT r; - if(!unicode){ - FINDTEXTA *ft = (FINDTEXTA *)lParam; - int nChars = MultiByteToWideChar(CP_ACP, 0, ft->lpstrText, -1, NULL, 0); - WCHAR *tmp; - - if ((tmp = heap_alloc(nChars * sizeof(*tmp))) != NULL) - MultiByteToWideChar(CP_ACP, 0, ft->lpstrText, -1, tmp, nChars); - r = ME_FindText(editor, wParam, &ft->chrg, tmp, NULL); - heap_free(tmp); - }else{ - FINDTEXTW *ft = (FINDTEXTW *)lParam; - r = ME_FindText(editor, wParam, &ft->chrg, ft->lpstrText, NULL); - } - return r; - } - case EM_FINDTEXTEX: - { - LRESULT r; - if(!unicode){ - FINDTEXTEXA *ex = (FINDTEXTEXA *)lParam; - int nChars = MultiByteToWideChar(CP_ACP, 0, ex->lpstrText, -1, NULL, 0); - WCHAR *tmp; - - if ((tmp = heap_alloc(nChars * sizeof(*tmp))) != NULL) - MultiByteToWideChar(CP_ACP, 0, ex->lpstrText, -1, tmp, nChars); - r = ME_FindText(editor, wParam, &ex->chrg, tmp, &ex->chrgText); - heap_free(tmp); - }else{ - FINDTEXTEXW *ex = (FINDTEXTEXW *)lParam; - r = ME_FindText(editor, wParam, &ex->chrg, ex->lpstrText, &ex->chrgText); - } - return r; - } case EM_FINDTEXTW: { FINDTEXTW *ft = (FINDTEXTW *)lParam; return ME_FindText(editor, wParam, &ft->chrg, ft->lpstrText, NULL); } + case EM_FINDTEXTEX: case EM_FINDTEXTEXW: { FINDTEXTEXW *ex = (FINDTEXTEXW *)lParam; @@ -4435,8 +3878,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case EM_POSFROMCHAR: { - ME_DisplayItem *pPara, *pRun; - int nCharOfs, nOffset, nLength; + ME_Cursor cursor; + int nCharOfs, nLength; POINTL pt = {0,0}; nCharOfs = wParam; @@ -4447,61 +3890,37 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, nCharOfs = min(nCharOfs, nLength); nCharOfs = max(nCharOfs, 0); - ME_RunOfsFromCharOfs(editor, nCharOfs, &pPara, &pRun, &nOffset); - assert(pRun->type == diRun); - pt.y = pRun->member.run.pt.y; - pt.x = pRun->member.run.pt.x + ME_PointFromChar(editor, &pRun->member.run, nOffset, TRUE); - pt.y += pPara->member.para.pt.y + editor->rcFormat.top; + cursor_from_char_ofs( editor, nCharOfs, &cursor ); + pt.y = cursor.run->pt.y; + pt.x = cursor.run->pt.x + + ME_PointFromChar( editor, cursor.run, cursor.nOffset, TRUE ); + pt.y += cursor.para->pt.y + editor->rcFormat.top; pt.x += editor->rcFormat.left; pt.x -= editor->horz_si.nPos; pt.y -= editor->vert_si.nPos; - if (wParam >= 0x40000) { - *(POINTL *)wParam = pt; - } + if (wParam >= 0x40000) *(POINTL *)wParam = pt; + return (wParam >= 0x40000) ? 0 : MAKELONG( pt.x, pt.y ); } - case WM_CREATE: - return ME_WmCreate(editor, lParam, unicode); - case WM_DESTROY: - ME_DestroyEditor(editor); - return 0; - case WM_SETCURSOR: - { - POINT cursor_pos; - if (wParam == (WPARAM)editor->hWnd && GetCursorPos(&cursor_pos) && - ScreenToClient(editor->hWnd, &cursor_pos)) - ME_LinkNotify(editor, msg, 0, MAKELPARAM(cursor_pos.x, cursor_pos.y)); - return ME_SetCursor(editor); - } case WM_LBUTTONDBLCLK: case WM_LBUTTONDOWN: { ME_CommitUndo(editor); /* End coalesced undos for typed characters */ - if ((editor->nEventMask & ENM_MOUSEEVENTS) && - !ME_FilterEvent(editor, msg, &wParam, &lParam)) - return 0; ITextHost_TxSetFocus(editor->texthost); ME_LButtonDown(editor, (short)LOWORD(lParam), (short)HIWORD(lParam), ME_CalculateClickCount(editor, msg, wParam, lParam)); ITextHost_TxSetCapture(editor->texthost, TRUE); editor->bMouseCaptured = TRUE; - ME_LinkNotify(editor, msg, wParam, lParam); - if (!ME_SetCursor(editor)) goto do_default; + link_notify( editor, msg, wParam, lParam ); break; } case WM_MOUSEMOVE: - if ((editor->nEventMask & ENM_MOUSEEVENTS) && - !ME_FilterEvent(editor, msg, &wParam, &lParam)) - return 0; if (editor->bMouseCaptured) ME_MouseMove(editor, (short)LOWORD(lParam), (short)HIWORD(lParam)); else - ME_LinkNotify(editor, msg, wParam, lParam); - /* Set cursor if mouse is captured, since WM_SETCURSOR won't be received. */ - if (editor->bMouseCaptured) - ME_SetCursor(editor); + link_notify( editor, msg, wParam, lParam ); break; case WM_LBUTTONUP: if (editor->bMouseCaptured) { @@ -4510,23 +3929,16 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } if (editor->nSelectionType == stDocument) editor->nSelectionType = stPosition; - if ((editor->nEventMask & ENM_MOUSEEVENTS) && - !ME_FilterEvent(editor, msg, &wParam, &lParam)) - return 0; else { - ME_SetCursor(editor); - ME_LinkNotify(editor, msg, wParam, lParam); + link_notify( editor, msg, wParam, lParam ); } break; case WM_RBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: ME_CommitUndo(editor); /* End coalesced undos for typed characters */ - if ((editor->nEventMask & ENM_MOUSEEVENTS) && - !ME_FilterEvent(editor, msg, &wParam, &lParam)) - return 0; - ME_LinkNotify(editor, msg, wParam, lParam); + link_notify( editor, msg, wParam, lParam ); goto do_default; case WM_CONTEXTMENU: if (!ME_ShowContextMenu(editor, (short)LOWORD(lParam), (short)HIWORD(lParam))) @@ -4536,8 +3948,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, editor->bHaveFocus = TRUE; create_caret(editor); update_caret(editor); - ME_SendOldNotify(editor, EN_SETFOCUS); - if (!editor->bHideSelection && !(editor->styleFlags & ES_NOHIDESEL)) + ITextHost_TxNotify( editor->texthost, EN_SETFOCUS, NULL ); + if (!editor->bHideSelection && (editor->props & TXTBIT_HIDESELECTION)) ME_InvalidateSelection( editor ); return 0; case WM_KILLFOCUS: @@ -4546,48 +3958,33 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, editor->wheel_remain = 0; hide_caret(editor); DestroyCaret(); - ME_SendOldNotify(editor, EN_KILLFOCUS); - if (!editor->bHideSelection && !(editor->styleFlags & ES_NOHIDESEL)) + ITextHost_TxNotify( editor->texthost, EN_KILLFOCUS, NULL ); + if (!editor->bHideSelection && (editor->props & TXTBIT_HIDESELECTION)) ME_InvalidateSelection( editor ); return 0; case WM_COMMAND: TRACE("editor wnd command = %d\n", LOWORD(wParam)); return 0; - case WM_KEYUP: - if ((editor->nEventMask & ENM_KEYEVENTS) && - !ME_FilterEvent(editor, msg, &wParam, &lParam)) - return 0; - goto do_default; case WM_KEYDOWN: - if ((editor->nEventMask & ENM_KEYEVENTS) && - !ME_FilterEvent(editor, msg, &wParam, &lParam)) - return 0; if (ME_KeyDown(editor, LOWORD(wParam))) return 0; goto do_default; case WM_CHAR: - if ((editor->nEventMask & ENM_KEYEVENTS) && - !ME_FilterEvent(editor, msg, &wParam, &lParam)) - return 0; - return ME_Char(editor, wParam, lParam, unicode); + return handle_wm_char( editor, wParam, lParam ); case WM_UNICHAR: - if (unicode) - { - if(wParam == UNICODE_NOCHAR) return TRUE; - if(wParam <= 0x000fffff) - { - if(wParam > 0xffff) /* convert to surrogates */ - { - wParam -= 0x10000; - ME_Char(editor, (wParam >> 10) + 0xd800, 0, TRUE); - ME_Char(editor, (wParam & 0x03ff) + 0xdc00, 0, TRUE); - } else { - ME_Char(editor, wParam, 0, TRUE); - } - } - return 0; - } - break; + if (wParam == UNICODE_NOCHAR) return TRUE; + if (wParam <= 0x000fffff) + { + if (wParam > 0xffff) /* convert to surrogates */ + { + wParam -= 0x10000; + handle_wm_char( editor, (wParam >> 10) + 0xd800, 0 ); + handle_wm_char( editor, (wParam & 0x03ff) + 0xdc00, 0 ); + } + else + handle_wm_char( editor, wParam, 0 ); + } + return 0; case EM_STOPGROUPTYPING: ME_CommitUndo(editor); /* End coalesced undos for typed characters */ return 0; @@ -4598,12 +3995,11 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, switch(LOWORD(wParam)) { case SB_LEFT: - ME_ScrollAbs(editor, 0, 0); + scroll_abs( editor, 0, 0, TRUE ); break; case SB_RIGHT: - ME_ScrollAbs(editor, - editor->horz_si.nMax - (int)editor->horz_si.nPage, - editor->vert_si.nMax - (int)editor->vert_si.nPage); + scroll_abs( editor, editor->horz_si.nMax - (int)editor->horz_si.nPage, + editor->vert_si.nMax - (int)editor->vert_si.nPage, TRUE ); break; case SB_LINELEFT: ME_ScrollLeft(editor, scrollUnit); @@ -4623,7 +4019,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, int pos = HIWORD(wParam); if (editor->horz_si.nMax > 0xffff) pos = MulDiv(pos, editor->horz_si.nMax, 0xffff); - ME_HScrollAbs(editor, pos); + scroll_h_abs( editor, pos, FALSE ); break; } } @@ -4640,12 +4036,11 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, switch(LOWORD(wParam)) { case SB_TOP: - ME_ScrollAbs(editor, 0, 0); + scroll_abs( editor, 0, 0, TRUE ); break; case SB_BOTTOM: - ME_ScrollAbs(editor, - editor->horz_si.nMax - (int)editor->horz_si.nPage, - editor->vert_si.nMax - (int)editor->vert_si.nPage); + scroll_abs( editor, editor->horz_si.nMax - (int)editor->horz_si.nPage, + editor->vert_si.nMax - (int)editor->vert_si.nPage, TRUE ); break; case SB_LINEUP: ME_ScrollUp(editor,lineHeight); @@ -4665,7 +4060,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, int pos = HIWORD(wParam); if (editor->vert_si.nMax > 0xffff) pos = MulDiv(pos, editor->vert_si.nMax, 0xffff); - ME_VScrollAbs(editor, pos); + scroll_v_abs( editor, pos, FALSE ); break; } } @@ -4675,16 +4070,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case WM_MOUSEWHEEL: { - int delta; - BOOL ctrl_is_down; - - if ((editor->nEventMask & ENM_MOUSEEVENTS) && - !ME_FilterEvent(editor, msg, &wParam, &lParam)) - return 0; - - ctrl_is_down = GetKeyState(VK_CONTROL) & 0x8000; - - delta = GET_WHEEL_DELTA_WPARAM(wParam); + int delta = GET_WHEEL_DELTA_WPARAM( wParam ); + BOOL ctrl_is_down = GetKeyState( VK_CONTROL ) & 0x8000; /* if scrolling changes direction, ignore left overs */ if ((delta < 0 && editor->wheel_remain < 0) || @@ -4719,78 +4106,9 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } break; } - case EM_GETRECT: - { - *((RECT *)lParam) = editor->rcFormat; - if (editor->bDefaultFormatRect) - ((RECT *)lParam)->left -= editor->selofs; - return 0; - } - case EM_SETRECT: - case EM_SETRECTNP: - { - if (lParam) - { - int border = 0; - RECT clientRect; - RECT *rc = (RECT *)lParam; - - border = editor->exStyleFlags & WS_EX_CLIENTEDGE ? 1 : 0; - ITextHost_TxGetClientRect(editor->texthost, &clientRect); - if (wParam == 0) - { - editor->rcFormat.top = max(0, rc->top - border); - editor->rcFormat.left = max(0, rc->left - border); - editor->rcFormat.bottom = min(clientRect.bottom, rc->bottom); - editor->rcFormat.right = min(clientRect.right, rc->right + border); - } else if (wParam == 1) { - /* MSDN incorrectly says a wParam value of 1 causes the - * lParam rect to be used as a relative offset, - * however, the tests show it just prevents min/max bound - * checking. */ - editor->rcFormat.top = rc->top - border; - editor->rcFormat.left = rc->left - border; - editor->rcFormat.bottom = rc->bottom; - editor->rcFormat.right = rc->right + border; - } else { - return 0; - } - editor->bDefaultFormatRect = FALSE; - } - else - { - ME_SetDefaultFormatRect(editor); - editor->bDefaultFormatRect = TRUE; - } - ME_MarkAllForWrapping(editor); - ME_WrapMarkedParagraphs(editor); - ME_UpdateScrollBar(editor); - if (msg != EM_SETRECTNP) - ME_Repaint(editor); - return 0; - } case EM_REQUESTRESIZE: ME_SendRequestResize(editor, TRUE); return 0; - case WM_SETREDRAW: - goto do_default; - case WM_WINDOWPOSCHANGED: - { - RECT clientRect; - WINDOWPOS *winpos = (WINDOWPOS *)lParam; - - if (winpos->flags & SWP_NOCLIENTSIZE) goto do_default; - ITextHost_TxGetClientRect(editor->texthost, &clientRect); - if (editor->bDefaultFormatRect) { - ME_SetDefaultFormatRect(editor); - } else { - editor->rcFormat.right += clientRect.right - editor->prevClientRect.right; - editor->rcFormat.bottom += clientRect.bottom - editor->prevClientRect.bottom; - } - editor->prevClientRect = clientRect; - ME_RewrapRepaint(editor); - goto do_default; - } #ifndef __REACTOS__ /* IME messages to make richedit controls IME aware */ #endif @@ -4843,7 +4161,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, { HIMC hIMC; - ME_Style *style = ME_GetInsertStyle(editor, 0); + ME_Style *style = style_get_insert_style( editor, editor->pCursors ); hIMC = ITextHost_TxImmGetContext(editor->texthost); ME_DeleteSelection(editor); ME_SaveTempStyle(editor, style); @@ -4890,18 +4208,10 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, #endif } case EM_GETOLEINTERFACE: - { - if (!editor->reOle) - if (!CreateIRichEditOle(NULL, editor, (LPVOID *)&editor->reOle)) - return 0; - if (IUnknown_QueryInterface(editor->reOle, &IID_IRichEditOle, (LPVOID *)lParam) == S_OK) - return 1; - return 0; - } - case EM_GETPASSWORDCHAR: - { - return editor->cPasswordMask; - } + IRichEditOle_AddRef( editor->richole ); + *(IRichEditOle **)lParam = editor->richole; + return 1; + case EM_SETOLECALLBACK: if(editor->lpOleCallback) IRichEditOleCallback_Release(editor->lpOleCallback); @@ -4947,24 +4257,18 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, /* plain text can only have the default style. */ ME_ClearTempStyle(editor); ME_AddRefStyle(editor->pBuffer->pDefaultStyle); - ME_ReleaseStyle(editor->pCursors[0].pRun->member.run.style); - editor->pCursors[0].pRun->member.run.style = editor->pBuffer->pDefaultStyle; + ME_ReleaseStyle( editor->pCursors[0].run->style ); + editor->pCursors[0].run->style = editor->pBuffer->pDefaultStyle; } } /* FIXME: Currently no support for undo level and code page options */ editor->mode = (editor->mode & ~mask) | changes; return 0; } - case EM_SETPASSWORDCHAR: - { - editor->cPasswordMask = wParam; - ME_RewrapRepaint(editor); - return 0; - } case EM_SETTARGETDEVICE: if (wParam == 0) { - BOOL new = (lParam == 0 && (editor->styleFlags & ES_MULTILINE)); + BOOL new = (lParam == 0 && (editor->props & TXTBIT_MULTILINE)); if (editor->nAvailWidth || editor->bWordWrap != new) { editor->bWordWrap = new; @@ -4973,7 +4277,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } } else { int width = max(0, lParam); - if ((editor->styleFlags & ES_MULTILINE) && + if ((editor->props & TXTBIT_MULTILINE) && (!editor->bWordWrap || editor->nAvailWidth != width)) { editor->nAvailWidth = width; @@ -4991,192 +4295,6 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, return 0L; } -static BOOL create_windowed_editor(HWND hwnd, CREATESTRUCTW *create, BOOL emulate_10) -{ - ITextHost *host = ME_CreateTextHost( hwnd, create, emulate_10 ); - ME_TextEditor *editor; - - if (!host) return FALSE; - - editor = ME_MakeEditor( host, emulate_10 ); - if (!editor) - { - ITextHost_Release( host ); - return FALSE; - } - - editor->exStyleFlags = GetWindowLongW( hwnd, GWL_EXSTYLE ); - editor->styleFlags |= GetWindowLongW( hwnd, GWL_STYLE ) & ES_WANTRETURN; - editor->hWnd = hwnd; /* FIXME: Remove editor's dependence on hWnd */ - editor->hwndParent = create->hwndParent; - - SetWindowLongPtrW( hwnd, 0, (LONG_PTR)editor ); - - return TRUE; -} - -static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, - LPARAM lParam, BOOL unicode) -{ - ME_TextEditor *editor; - HRESULT hresult; - LRESULT lresult = 0; - - TRACE("enter hwnd %p msg %04x (%s) %lx %lx, unicode %d\n", - hWnd, msg, get_msg_name(msg), wParam, lParam, unicode); - - editor = (ME_TextEditor *)GetWindowLongPtrW(hWnd, 0); - if (!editor) - { - if (msg == WM_NCCREATE) - { - CREATESTRUCTW *pcs = (CREATESTRUCTW *)lParam; - - TRACE("WM_NCCREATE: hWnd %p style 0x%08x\n", hWnd, pcs->style); - return create_windowed_editor( hWnd, pcs, FALSE ); - } - else - { - return DefWindowProcW(hWnd, msg, wParam, lParam); - } - } - - switch (msg) - { - case WM_PAINT: - { - HDC hdc; - RECT rc; - PAINTSTRUCT ps; - HBRUSH old_brush; - - update_caret(editor); - hdc = BeginPaint(editor->hWnd, &ps); - if (!editor->bEmulateVersion10 || (editor->nEventMask & ENM_UPDATE)) - ME_SendOldNotify(editor, EN_UPDATE); - old_brush = SelectObject(hdc, editor->hbrBackground); - - /* Erase area outside of the formatting rectangle */ - if (ps.rcPaint.top < editor->rcFormat.top) - { - rc = ps.rcPaint; - rc.bottom = editor->rcFormat.top; - PatBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); - ps.rcPaint.top = editor->rcFormat.top; - } - if (ps.rcPaint.bottom > editor->rcFormat.bottom) { - rc = ps.rcPaint; - rc.top = editor->rcFormat.bottom; - PatBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); - ps.rcPaint.bottom = editor->rcFormat.bottom; - } - if (ps.rcPaint.left < editor->rcFormat.left) { - rc = ps.rcPaint; - rc.right = editor->rcFormat.left; - PatBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); - ps.rcPaint.left = editor->rcFormat.left; - } - if (ps.rcPaint.right > editor->rcFormat.right) { - rc = ps.rcPaint; - rc.left = editor->rcFormat.right; - PatBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); - ps.rcPaint.right = editor->rcFormat.right; - } - - ME_PaintContent(editor, hdc, &ps.rcPaint); - SelectObject(hdc, old_brush); - EndPaint(editor->hWnd, &ps); - return 0; - } - case WM_ERASEBKGND: - { - HDC hDC = (HDC)wParam; - RECT rc; - - if (GetUpdateRect(editor->hWnd, &rc, TRUE)) - FillRect(hDC, &rc, editor->hbrBackground); - return 1; - } - case EM_SETOPTIONS: - { - DWORD dwStyle; - const DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL | - ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN | - ECO_SELECTIONBAR; - lresult = ME_HandleMessage(editor, msg, wParam, lParam, unicode, &hresult); - dwStyle = GetWindowLongW(hWnd, GWL_STYLE); - dwStyle = (dwStyle & ~mask) | (lresult & mask); - SetWindowLongW(hWnd, GWL_STYLE, dwStyle); - return lresult; - } - case EM_SETREADONLY: - { - DWORD dwStyle; - lresult = ME_HandleMessage(editor, msg, wParam, lParam, unicode, &hresult); - dwStyle = GetWindowLongW(hWnd, GWL_STYLE); - dwStyle &= ~ES_READONLY; - if (wParam) - dwStyle |= ES_READONLY; - SetWindowLongW(hWnd, GWL_STYLE, dwStyle); - return lresult; - } - default: - lresult = ME_HandleMessage(editor, msg, wParam, lParam, unicode, &hresult); - } - - if (hresult == S_FALSE) - lresult = DefWindowProcW(hWnd, msg, wParam, lParam); - - TRACE("exit hwnd %p msg %04x (%s) %lx %lx, unicode %d -> %lu\n", - hWnd, msg, get_msg_name(msg), wParam, lParam, unicode, lresult); - - return lresult; -} - -static LRESULT WINAPI RichEditWndProcW(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - BOOL unicode = TRUE; - - /* Under Win9x RichEdit20W returns ANSI strings, see the tests. */ - if (msg == WM_GETTEXT && (GetVersion() & 0x80000000)) - unicode = FALSE; - - return RichEditWndProc_common(hWnd, msg, wParam, lParam, unicode); -} - -static LRESULT WINAPI RichEditWndProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - return RichEditWndProc_common(hWnd, msg, wParam, lParam, FALSE); -} - -/****************************************************************** - * RichEditANSIWndProc (RICHED20.10) - */ -LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - return RichEditWndProcA(hWnd, msg, wParam, lParam); -} - -/****************************************************************** - * RichEdit10ANSIWndProc (RICHED20.9) - */ -LRESULT WINAPI RichEdit10ANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (msg == WM_NCCREATE && !GetWindowLongPtrW(hWnd, 0)) - { - CREATESTRUCTW *pcs = (CREATESTRUCTW *)lParam; - - TRACE("WM_NCCREATE: hWnd %p style 0x%08x\n", hWnd, pcs->style); - return create_windowed_editor( hWnd, pcs, TRUE ); - } - return RichEditANSIWndProc(hWnd, msg, wParam, lParam); -} - -void ME_SendOldNotify(ME_TextEditor *editor, int nCode) -{ - ITextHost_TxNotify(editor->texthost, nCode, NULL); -} - /* Fill buffer with srcChars unicode characters from the start cursor. * * buffer: destination buffer @@ -5193,27 +4311,23 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, const ME_Cursor *start, int srcChars, BOOL bCRLF, BOOL bEOP) { - ME_DisplayItem *pRun, *pNextRun; + ME_Run *run, *next_run; const WCHAR *pStart = buffer; - const WCHAR cr_lf[] = {'\r', '\n', 0}; const WCHAR *str; int nLen; /* bCRLF flag is only honored in 2.0 and up. 1.0 must always return text verbatim */ if (editor->bEmulateVersion10) bCRLF = FALSE; - pRun = start->pRun; - assert(pRun); - pNextRun = ME_FindItemFwd(pRun, diRun); + run = start->run; + next_run = run_next_all_paras( run ); - nLen = pRun->member.run.len - start->nOffset; - str = get_text( &pRun->member.run, start->nOffset ); + nLen = run->len - start->nOffset; + str = get_text( run, start->nOffset ); - while (srcChars && buflen && pNextRun) + while (srcChars && buflen && next_run) { - int nFlags = pRun->member.run.nFlags; - - if (bCRLF && nFlags & MERF_ENDPARA && ~nFlags & MERF_ENDCELL) + if (bCRLF && run->nFlags & MERF_ENDPARA && ~run->nFlags & MERF_ENDCELL) { if (buflen == 1) break; /* FIXME: native fails to reduce srcChars here for WM_GETTEXT or @@ -5221,8 +4335,10 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, * also uses this function. */ srcChars -= min(nLen, srcChars); nLen = 2; - str = cr_lf; - } else { + str = L"\r\n"; + } + else + { nLen = min(nLen, srcChars); srcChars -= nLen; } @@ -5234,14 +4350,14 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, buffer += nLen; - pRun = pNextRun; - pNextRun = ME_FindItemFwd(pRun, diRun); + run = next_run; + next_run = run_next_all_paras( run ); - nLen = pRun->member.run.len; - str = get_text( &pRun->member.run, 0 ); + nLen = run->len; + str = get_text( run, 0 ); } /* append '\r' to the last paragraph. */ - if (pRun->next->type == diTextEnd && bEOP) + if (run == para_end_run( para_prev( editor_end_para( editor ) ) ) && bEOP) { *buffer = '\r'; buffer ++; @@ -5250,114 +4366,6 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, return buffer - pStart; } -static BOOL ME_RegisterEditorClass(HINSTANCE hInstance) -{ - WNDCLASSW wcW; - WNDCLASSA wcA; - - wcW.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS; - wcW.lpfnWndProc = RichEditWndProcW; - wcW.cbClsExtra = 0; - wcW.cbWndExtra = sizeof(ME_TextEditor *); - wcW.hInstance = NULL; /* hInstance would register DLL-local class */ - wcW.hIcon = NULL; - wcW.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_IBEAM); - wcW.hbrBackground = GetStockObject(NULL_BRUSH); - wcW.lpszMenuName = NULL; - - if (is_version_nt()) - { - wcW.lpszClassName = RICHEDIT_CLASS20W; - if (!RegisterClassW(&wcW)) return FALSE; - wcW.lpszClassName = MSFTEDIT_CLASS; - if (!RegisterClassW(&wcW)) return FALSE; - } - else - { - /* WNDCLASSA/W have the same layout */ - wcW.lpszClassName = (LPCWSTR)"RichEdit20W"; - if (!RegisterClassA((WNDCLASSA *)&wcW)) return FALSE; - wcW.lpszClassName = (LPCWSTR)"RichEdit50W"; - if (!RegisterClassA((WNDCLASSA *)&wcW)) return FALSE; - } - - wcA.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS; - wcA.lpfnWndProc = RichEditWndProcA; - wcA.cbClsExtra = 0; - wcA.cbWndExtra = sizeof(ME_TextEditor *); - wcA.hInstance = NULL; /* hInstance would register DLL-local class */ - wcA.hIcon = NULL; - wcA.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_IBEAM); - wcA.hbrBackground = GetStockObject(NULL_BRUSH); - wcA.lpszMenuName = NULL; - wcA.lpszClassName = RICHEDIT_CLASS20A; - if (!RegisterClassA(&wcA)) return FALSE; - wcA.lpszClassName = "RichEdit50A"; - if (!RegisterClassA(&wcA)) return FALSE; - - return TRUE; -} - -static LRESULT WINAPI REComboWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - /* FIXME: Not implemented */ - TRACE("hWnd %p msg %04x (%s) %08lx %08lx\n", - hWnd, msg, get_msg_name(msg), wParam, lParam); - return DefWindowProcW(hWnd, msg, wParam, lParam); -} - -static LRESULT WINAPI REListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - /* FIXME: Not implemented */ - TRACE("hWnd %p msg %04x (%s) %08lx %08lx\n", - hWnd, msg, get_msg_name(msg), wParam, lParam); - return DefWindowProcW(hWnd, msg, wParam, lParam); -} - -/****************************************************************** - * REExtendedRegisterClass (RICHED20.8) - * - * FIXME undocumented - * Need to check for errors and implement controls and callbacks - */ -LRESULT WINAPI REExtendedRegisterClass(void) -{ - WNDCLASSW wcW; - UINT result; - - FIXME("semi stub\n"); - - wcW.cbClsExtra = 0; - wcW.cbWndExtra = 4; - wcW.hInstance = NULL; - wcW.hIcon = NULL; - wcW.hCursor = NULL; - wcW.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcW.lpszMenuName = NULL; - - if (!ME_ListBoxRegistered) - { - wcW.style = CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS; - wcW.lpfnWndProc = REListWndProc; - wcW.lpszClassName = REListBox20W; - if (RegisterClassW(&wcW)) ME_ListBoxRegistered = TRUE; - } - - if (!ME_ComboBoxRegistered) - { - wcW.style = CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW; - wcW.lpfnWndProc = REComboWndProc; - wcW.lpszClassName = REComboBox20W; - if (RegisterClassW(&wcW)) ME_ComboBoxRegistered = TRUE; - } - - result = 0; - if (ME_ListBoxRegistered) - result += 1; - if (ME_ComboBoxRegistered) - result += 2; - - return result; -} - static int __cdecl wchar_comp( const void *key, const void *elem ) { return *(const WCHAR *)key - *(const WCHAR *)elem; @@ -5368,13 +4376,13 @@ static int __cdecl wchar_comp( const void *key, const void *elem ) static BOOL isurlneutral( WCHAR c ) { /* NB this list is sorted */ - static const WCHAR neutral_chars[] = {'!','\"','\'','(',')',',','-','.',':',';','<','>','?','[',']','{','}'}; + static const WCHAR neutral_chars[] = L"!\"'(),-.:;<>?[]{}"; /* Some shortcuts */ if (isalnum( c )) return FALSE; - if (c > neutral_chars[ARRAY_SIZE( neutral_chars ) - 1]) return FALSE; + if (c > L'}') return FALSE; - return !!bsearch( &c, neutral_chars, ARRAY_SIZE( neutral_chars ), sizeof(c), wchar_comp ); + return !!bsearch( &c, neutral_chars, ARRAY_SIZE( neutral_chars ) - 1, sizeof(c), wchar_comp ); } /** @@ -5396,8 +4404,8 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, while (nChars > 0) { - WCHAR *str = get_text( &cursor.pRun->member.run, 0 ); - int run_len = cursor.pRun->member.run.len; + WCHAR *str = get_text( cursor.run, 0 ); + int run_len = cursor.run->len; nChars -= run_len - cursor.nOffset; @@ -5411,8 +4419,8 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, { *candidate_min = cursor; candidateStarted = TRUE; - neutral_end.pPara = NULL; - space_end.pPara = NULL; + neutral_end.para = NULL; + space_end.para = NULL; cursor.nOffset++; break; } @@ -5431,9 +4439,9 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, { if (quoted && c != '\r') { - if (!space_end.pPara) + if (!space_end.para) { - if (neutral_end.pPara) + if (neutral_end.para) space_end = neutral_end; else space_end = cursor; @@ -5446,31 +4454,31 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, { if (quoted && c == '>') { - neutral_end.pPara = NULL; - space_end.pPara = NULL; + neutral_end.para = NULL; + space_end.para = NULL; goto done; } - if (!neutral_end.pPara) + if (!neutral_end.para) neutral_end = cursor; } else - neutral_end.pPara = NULL; + neutral_end.para = NULL; cursor.nOffset++; } } cursor.nOffset = 0; - if (!ME_NextRun(&cursor.pPara, &cursor.pRun, TRUE)) + if (!cursor_next_run( &cursor, TRUE )) goto done; } done: if (candidateStarted) { - if (space_end.pPara) + if (space_end.para) *candidate_max = space_end; - else if (neutral_end.pPara) + else if (neutral_end.para) *candidate_max = neutral_end; else *candidate_max = cursor; @@ -5486,23 +4494,25 @@ done: static BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, const ME_Cursor *start, int nChars) { #define MAX_PREFIX_LEN 9 +#define X(str) str, ARRAY_SIZE(str) - 1 struct prefix_s { const WCHAR text[MAX_PREFIX_LEN]; int length; }prefixes[] = { - {{'p','r','o','s','p','e','r','o',':'}, 9}, - {{'t','e','l','n','e','t',':'}, 7}, - {{'g','o','p','h','e','r',':'}, 7}, - {{'m','a','i','l','t','o',':'}, 7}, - {{'h','t','t','p','s',':'}, 6}, - {{'f','i','l','e',':'}, 5}, - {{'n','e','w','s',':'}, 5}, - {{'w','a','i','s',':'}, 5}, - {{'n','n','t','p',':'}, 5}, - {{'h','t','t','p',':'}, 5}, - {{'w','w','w','.'}, 4}, - {{'f','t','p',':'}, 4}, + {X(L"prospero:")}, + {X(L"telnet:")}, + {X(L"gopher:")}, + {X(L"mailto:")}, + {X(L"https:")}, + {X(L"file:")}, + {X(L"news:")}, + {X(L"wais:")}, + {X(L"nntp:")}, + {X(L"http:")}, + {X(L"www.")}, + {X(L"ftp:")}, }; +#undef X WCHAR bufferW[MAX_PREFIX_LEN + 1]; unsigned int i; @@ -5559,7 +4569,7 @@ static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, ME_Cursor *start, int nChars = 0; } - if (startCur.pRun != candidateStart.pRun || + if (startCur.run != candidateStart.run || startCur.nOffset != candidateStart.nOffset) { /* CFE_LINK effect should be consistently unset */ @@ -5576,15 +4586,15 @@ static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, ME_Cursor *start, int /* Update candidateEnd since setting character formats may split * runs, which can cause a cursor to be at an invalid offset within * a split run. */ - while (candidateEnd.nOffset >= candidateEnd.pRun->member.run.len) + while (candidateEnd.nOffset >= candidateEnd.run->len) { - candidateEnd.nOffset -= candidateEnd.pRun->member.run.len; - candidateEnd.pRun = ME_FindItemFwd(candidateEnd.pRun, diRun); + candidateEnd.nOffset -= candidateEnd.run->len; + candidateEnd.run = run_next_all_paras( candidateEnd.run ); } modified = TRUE; } } - if (candidateStart.pRun != candidateEnd.pRun || + if (candidateStart.run != candidateEnd.run || candidateStart.nOffset != candidateEnd.nOffset) { /* CFE_LINK effect should be consistently set */ diff --git a/dll/win32/riched20/editor.h b/dll/win32/riched20/editor.h index 2bd06be2cf6..141e9034a6a 100644 --- a/dll/win32/riched20/editor.h +++ b/dll/win32/riched20/editor.h @@ -18,12 +18,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#pragma once - #include "editstr.h" struct _RTF_Info; +extern HINSTANCE dll_instance DECLSPEC_HIDDEN; extern HANDLE me_heap DECLSPEC_HIDDEN; #define RUN_IS_HIDDEN(run) ((run)->style->fmt.dwMask & CFM_HIDDEN \ @@ -49,11 +48,11 @@ static inline const char *debugstr_run( const ME_Run *run ) } /* style.c */ +ME_Style *style_get_insert_style( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN; ME_Style *ME_MakeStyle(CHARFORMAT2W *style) DECLSPEC_HIDDEN; void ME_AddRefStyle(ME_Style *item) DECLSPEC_HIDDEN; void ME_DestroyStyle(ME_Style *item) DECLSPEC_HIDDEN; void ME_ReleaseStyle(ME_Style *item) DECLSPEC_HIDDEN; -ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor) DECLSPEC_HIDDEN; ME_Style *ME_ApplyStyle(ME_TextEditor *ed, ME_Style *sSrc, CHARFORMAT2W *style) DECLSPEC_HIDDEN; void select_style(ME_Context *c, ME_Style *s) DECLSPEC_HIDDEN; void ME_InitCharFormat2W(CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN; @@ -69,15 +68,12 @@ void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt) DE /* list.c */ void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat) DECLSPEC_HIDDEN; void ME_Remove(ME_DisplayItem *diWhere) DECLSPEC_HIDDEN; -BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run, BOOL all_para) DECLSPEC_HIDDEN; -BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run, BOOL all_para) DECLSPEC_HIDDEN; ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN; ME_DisplayItem *ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN; ME_DisplayItem *ME_FindItemBackOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN; ME_DisplayItem *ME_MakeDI(ME_DIType type) DECLSPEC_HIDDEN; void ME_DestroyDisplayItem(ME_DisplayItem *item) DECLSPEC_HIDDEN; void ME_DumpDocument(ME_TextBuffer *buffer) DECLSPEC_HIDDEN; -void destroy_para(ME_TextEditor *editor, ME_DisplayItem *item) DECLSPEC_HIDDEN; /* string.c */ ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars) DECLSPEC_HIDDEN; @@ -114,32 +110,47 @@ int ME_ReverseFindNonWhitespaceV(const ME_String *s, int nVChar) DECLSPEC_HIDDEN int ME_ReverseFindWhitespaceV(const ME_String *s, int nVChar) DECLSPEC_HIDDEN; /* row.c */ -ME_DisplayItem *ME_RowStart(ME_DisplayItem *item) DECLSPEC_HIDDEN; -/* ME_DisplayItem *ME_RowEnd(ME_DisplayItem *item); */ -ME_DisplayItem *ME_FindRowWithNumber(ME_TextEditor *editor, int nRow) DECLSPEC_HIDDEN; -int ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs) DECLSPEC_HIDDEN; +void row_end_cursor( ME_Row *row, ME_Cursor *cursor, BOOL include_eop ) DECLSPEC_HIDDEN; +void row_first_cursor( ME_Row *row, ME_Cursor *cursor ) DECLSPEC_HIDDEN; +ME_Run *row_first_run( ME_Row *row ) DECLSPEC_HIDDEN; +ME_Row *row_from_cursor( ME_Cursor *cursor ) DECLSPEC_HIDDEN; +ME_Row *row_from_row_number( ME_TextEditor *editor, int row_num ) DECLSPEC_HIDDEN; +ME_Row *row_next( ME_Row *row ) DECLSPEC_HIDDEN; +ME_Row *row_next_all_paras( ME_Row *row ) DECLSPEC_HIDDEN; +ME_Run *row_next_run( ME_Row *row, ME_Run *run ) DECLSPEC_HIDDEN; +int row_number_from_char_ofs( ME_TextEditor *editor, int ofs ) DECLSPEC_HIDDEN; +ME_Paragraph *row_para( ME_Row *row ) DECLSPEC_HIDDEN; +ME_Row *row_prev_all_paras( ME_Row *row ) DECLSPEC_HIDDEN; +static inline ME_DisplayItem *row_get_di( ME_Row *row ) +{ + return (ME_DisplayItem *)((ptrdiff_t)row - offsetof(ME_DisplayItem, member)); +} /* run.c */ -ME_DisplayItem *ME_MakeRun(ME_Style *s, int nFlags) DECLSPEC_HIDDEN; -ME_DisplayItem *ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, - ME_Style *style, const WCHAR *str, int len, int flags) DECLSPEC_HIDDEN; +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; +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, + ME_Style *style, const WCHAR *str, int len, int flags ) DECLSPEC_HIDDEN; void ME_CheckCharOffsets(ME_TextEditor *editor) DECLSPEC_HIDDEN; -void ME_PropagateCharOffset(ME_DisplayItem *p, int shift) DECLSPEC_HIDDEN; /* this one accounts for 1/2 char tolerance */ int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BOOL visual_order) DECLSPEC_HIDDEN; int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, BOOL visual_order) DECLSPEC_HIDDEN; int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN; int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN; BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2) DECLSPEC_HIDDEN; -void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) DECLSPEC_HIDDEN; -ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_Cursor *cursor) DECLSPEC_HIDDEN; +void run_join( ME_TextEditor *editor, ME_Run *run ) DECLSPEC_HIDDEN; +ME_Run *run_next( ME_Run *run ) DECLSPEC_HIDDEN; +ME_Run *run_next_all_paras( ME_Run *run ) DECLSPEC_HIDDEN; +ME_Run *run_prev( ME_Run *run ) DECLSPEC_HIDDEN; +ME_Run *run_prev_all_paras( ME_Run *run ) DECLSPEC_HIDDEN; +ME_Run *run_split( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN; void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run) DECLSPEC_HIDDEN; SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, int nLen, int startx, int *pAscent, int *pDescent) DECLSPEC_HIDDEN; -void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor) DECLSPEC_HIDDEN; -void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **ppPara, ME_DisplayItem **ppRun, int *pOfs) DECLSPEC_HIDDEN; -int ME_CharOfsFromRunOfs(ME_TextEditor *editor, const ME_DisplayItem *pPara, const ME_DisplayItem *pRun, int nOfs) DECLSPEC_HIDDEN; -void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift) DECLSPEC_HIDDEN; void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN; void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN; void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from, @@ -147,8 +158,13 @@ void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from, void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN; void ME_GetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN; void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod) DECLSPEC_HIDDEN; +static inline ME_DisplayItem *run_get_di( ME_Run *run ) +{ + return (ME_DisplayItem *)((ptrdiff_t)run - offsetof(ME_DisplayItem, member)); +} /* caret.c */ +void cursor_coords( ME_TextEditor *editor, ME_Cursor *cursor, int *x, int *y, int *height ) DECLSPEC_HIDDEN; void ME_SetCursorToStart(ME_TextEditor *editor, ME_Cursor *cursor) DECLSPEC_HIDDEN; int set_selection_cursors(ME_TextEditor *editor, int from, int to) DECLSPEC_HIDDEN; BOOL ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) DECLSPEC_HIDDEN; @@ -177,7 +193,6 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, int nChars, int ME_GetTextLength(ME_TextEditor *editor) DECLSPEC_HIDDEN; int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how) DECLSPEC_HIDDEN; ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor) DECLSPEC_HIDDEN; -void ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, int *x, int *y, int *height) DECLSPEC_HIDDEN; /* context.c */ void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC) DECLSPEC_HIDDEN; @@ -185,36 +200,49 @@ void ME_DestroyContext(ME_Context *c) DECLSPEC_HIDDEN; /* wrap.c */ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) DECLSPEC_HIDDEN; -void ME_InvalidateParagraphRange(ME_TextEditor *editor, ME_DisplayItem *start_para, ME_DisplayItem *last_para) DECLSPEC_HIDDEN; +void para_range_invalidate( ME_TextEditor *editor, ME_Paragraph *start_para, ME_Paragraph *last_para ) DECLSPEC_HIDDEN; void ME_SendRequestResize(ME_TextEditor *editor, BOOL force) DECLSPEC_HIDDEN; +BOOL wrap_marked_paras_dc( ME_TextEditor *editor, HDC hdc, BOOL invalidate ) DECLSPEC_HIDDEN; /* para.c */ -ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run) DECLSPEC_HIDDEN; -void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end) DECLSPEC_HIDDEN; +void editor_get_selection_paras(ME_TextEditor *editor, ME_Paragraph **para, ME_Paragraph **para_end ) DECLSPEC_HIDDEN; +void editor_get_selection_para_fmt( ME_TextEditor *editor, PARAFORMAT2 *fmt ) DECLSPEC_HIDDEN; +void editor_mark_rewrap_all( ME_TextEditor *editor ) DECLSPEC_HIDDEN; +void editor_set_default_para_fmt(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN; +BOOL editor_set_selection_para_fmt( ME_TextEditor *editor, const PARAFORMAT2 *fmt ) DECLSPEC_HIDDEN; void ME_MakeFirstParagraph(ME_TextEditor *editor) DECLSPEC_HIDDEN; -ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style, const WCHAR *eol_str, int eol_len, int paraFlags) DECLSPEC_HIDDEN; -ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, - BOOL keepFirstParaFormat) DECLSPEC_HIDDEN; void ME_DumpParaStyle(ME_Paragraph *s) DECLSPEC_HIDDEN; void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]) DECLSPEC_HIDDEN; -BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN; -void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN; -void ME_MarkAllForWrapping(ME_TextEditor *editor) DECLSPEC_HIDDEN; -void ME_SetDefaultParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN; -void para_num_init( ME_Context *c, ME_Paragraph *para ) DECLSPEC_HIDDEN; -void para_num_clear( struct para_num *pn ) DECLSPEC_HIDDEN; int get_total_width(ME_TextEditor *editor) DECLSPEC_HIDDEN; -void mark_para_rewrap(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN; -ME_DisplayItem *get_di_from_para(ME_Paragraph *para) DECLSPEC_HIDDEN; -void add_marked_para(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN; -void remove_marked_para(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN; +ME_Cell *para_cell( ME_Paragraph *para ) DECLSPEC_HIDDEN; +void para_destroy( ME_TextEditor *editor, ME_Paragraph *item ) DECLSPEC_HIDDEN; +ME_Row *para_end_row( ME_Paragraph *para ) DECLSPEC_HIDDEN; +ME_Run *para_end_run( ME_Paragraph *para ) DECLSPEC_HIDDEN; +ME_Row *para_first_row( ME_Paragraph *para ) DECLSPEC_HIDDEN; +ME_Run *para_first_run( ME_Paragraph *para ) DECLSPEC_HIDDEN; +BOOL para_in_table( ME_Paragraph *para ) DECLSPEC_HIDDEN; +ME_Paragraph *para_join( ME_TextEditor *editor, ME_Paragraph *para, BOOL use_first_fmt ) DECLSPEC_HIDDEN; +void para_mark_add( ME_TextEditor *editor, ME_Paragraph *para ) DECLSPEC_HIDDEN; +void para_mark_remove( ME_TextEditor *editor, ME_Paragraph *para ) DECLSPEC_HIDDEN; +void para_mark_rewrap( ME_TextEditor *editor, ME_Paragraph *para ) DECLSPEC_HIDDEN; +ME_Paragraph *para_next( ME_Paragraph *para ) DECLSPEC_HIDDEN; +void para_num_clear( struct para_num *pn ) DECLSPEC_HIDDEN; +void para_num_init( ME_Context *c, ME_Paragraph *para ) DECLSPEC_HIDDEN; +ME_Paragraph *para_prev( ME_Paragraph *para ) DECLSPEC_HIDDEN; +ME_Paragraph *para_split( ME_TextEditor *editor, ME_Run *run, ME_Style *style, + const WCHAR *eol_str, int eol_len, int paraFlags ) DECLSPEC_HIDDEN; + +static inline ME_DisplayItem *para_get_di(ME_Paragraph *para) +{ + return (ME_DisplayItem *)((ptrdiff_t)para - offsetof(ME_DisplayItem, member)); +} /* paint.c */ -void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate) DECLSPEC_HIDDEN; +void editor_draw( ME_TextEditor *editor, HDC hDC, const RECT *update ) DECLSPEC_HIDDEN; void ME_Repaint(ME_TextEditor *editor) DECLSPEC_HIDDEN; void ME_RewrapRepaint(ME_TextEditor *editor) DECLSPEC_HIDDEN; void ME_UpdateRepaint(ME_TextEditor *editor, BOOL update_now) DECLSPEC_HIDDEN; -void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor) DECLSPEC_HIDDEN; +void editor_ensure_visible( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN; void ME_InvalidateSelection(ME_TextEditor *editor) DECLSPEC_HIDDEN; BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator) DECLSPEC_HIDDEN; int ME_twips2pointsX(const ME_Context *c, int x) DECLSPEC_HIDDEN; @@ -222,9 +250,9 @@ int ME_twips2pointsY(const ME_Context *c, int y) DECLSPEC_HIDDEN; /* scroll functions in paint.c */ -void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) DECLSPEC_HIDDEN; -void ME_HScrollAbs(ME_TextEditor *editor, int x) DECLSPEC_HIDDEN; -void ME_VScrollAbs(ME_TextEditor *editor, int y) DECLSPEC_HIDDEN; +void scroll_abs( ME_TextEditor *editor, int x, int y, BOOL notify ) DECLSPEC_HIDDEN; +void scroll_h_abs( ME_TextEditor *editor, int x, BOOL notify ) DECLSPEC_HIDDEN; +void scroll_v_abs( ME_TextEditor *editor, int y, BOOL notify ) DECLSPEC_HIDDEN; void ME_ScrollUp(ME_TextEditor *editor, int cy) DECLSPEC_HIDDEN; void ME_ScrollDown(ME_TextEditor *editor, int cy) DECLSPEC_HIDDEN; void ME_ScrollLeft(ME_TextEditor *editor, int cx) DECLSPEC_HIDDEN; @@ -235,18 +263,19 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) DECLSPEC_HIDDEN; int ME_GetParaBorderWidth(const ME_Context *c, int flags) DECLSPEC_HIDDEN; /* richole.c */ -LRESULT CreateIRichEditOle(IUnknown *outer_unk, ME_TextEditor *editor, LPVOID *ppvObj) DECLSPEC_HIDDEN; -void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run* run, BOOL selected) DECLSPEC_HIDDEN; +void draw_ole( ME_Context *c, int x, int y, ME_Run* run, BOOL selected ) DECLSPEC_HIDDEN; void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize) DECLSPEC_HIDDEN; void ME_CopyReObject(REOBJECT *dst, const REOBJECT *src, DWORD flags) DECLSPEC_HIDDEN; void ME_DeleteReObject(struct re_object *re_object) DECLSPEC_HIDDEN; +void richole_release_children( struct text_services *services ) DECLSPEC_HIDDEN; +extern const IRichEditOleVtbl re_ole_vtbl DECLSPEC_HIDDEN; +extern const ITextDocument2OldVtbl text_doc2old_vtbl DECLSPEC_HIDDEN; /* editor.c */ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) DECLSPEC_HIDDEN; void ME_DestroyEditor(ME_TextEditor *editor) DECLSPEC_HIDDEN; -LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, - LPARAM lParam, BOOL unicode, HRESULT* phresult) DECLSPEC_HIDDEN; -void ME_SendOldNotify(ME_TextEditor *editor, int nCode) DECLSPEC_HIDDEN; +LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam, + LPARAM lParam, HRESULT* phresult ) DECLSPEC_HIDDEN; int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, const ME_Cursor *start, int srcChars, BOOL bCRLF, BOOL bEOP) DECLSPEC_HIDDEN; void ME_RTFCharAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN; @@ -257,32 +286,47 @@ void ME_StreamInFill(ME_InStream *stream) DECLSPEC_HIDDEN; extern BOOL me_debug DECLSPEC_HIDDEN; void ME_ReplaceSel(ME_TextEditor *editor, BOOL can_undo, const WCHAR *str, int len) DECLSPEC_HIDDEN; int set_selection( ME_TextEditor *editor, int to, int from ) DECLSPEC_HIDDEN; +HRESULT editor_copy_or_cut( ME_TextEditor *editor, BOOL cut, ME_Cursor *start, int count, + IDataObject **data_out ) DECLSPEC_HIDDEN; +ME_Paragraph *editor_end_para( ME_TextEditor *editor ) DECLSPEC_HIDDEN; +ME_Paragraph *editor_first_para( ME_TextEditor *editor ) DECLSPEC_HIDDEN; +void editor_set_cursor( ME_TextEditor *editor, int x, int y ) DECLSPEC_HIDDEN; +void link_notify( ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN; /* table.c */ -BOOL ME_IsInTable(ME_DisplayItem *pItem) DECLSPEC_HIDDEN; -ME_DisplayItem *ME_InsertTableRowStartFromCursor(ME_TextEditor *editor) DECLSPEC_HIDDEN; -ME_DisplayItem *ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor, - ME_DisplayItem *para) DECLSPEC_HIDDEN; -ME_DisplayItem *ME_InsertTableCellFromCursor(ME_TextEditor *editor) DECLSPEC_HIDDEN; -ME_DisplayItem *ME_InsertTableRowEndFromCursor(ME_TextEditor *editor) DECLSPEC_HIDDEN; -ME_DisplayItem *ME_GetTableRowEnd(ME_DisplayItem *para) DECLSPEC_HIDDEN; -ME_DisplayItem *ME_GetTableRowStart(ME_DisplayItem *para) DECLSPEC_HIDDEN; -ME_DisplayItem *ME_GetOuterParagraph(ME_DisplayItem *para) DECLSPEC_HIDDEN; -void ME_CheckTablesForCorruption(ME_TextEditor *editor) DECLSPEC_HIDDEN; -void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, ME_Cursor *c, int *nChars) DECLSPEC_HIDDEN; -ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, ME_DisplayItem *table_row) DECLSPEC_HIDDEN; -void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow) DECLSPEC_HIDDEN; -void ME_MoveCursorFromTableRowStartParagraph(ME_TextEditor *editor) DECLSPEC_HIDDEN; +ME_Cell *cell_create( void ) DECLSPEC_HIDDEN; +ME_Paragraph *cell_end_para( ME_Cell *cell ) DECLSPEC_HIDDEN; +ME_Paragraph *cell_first_para( ME_Cell *cell ) DECLSPEC_HIDDEN; +ME_Cell *cell_next( ME_Cell *cell ) DECLSPEC_HIDDEN; +ME_Cell *cell_prev( ME_Cell *cell ) DECLSPEC_HIDDEN; +ME_Paragraph *table_append_row( ME_TextEditor *editor, ME_Paragraph *table_row ) DECLSPEC_HIDDEN; +void table_handle_tab( ME_TextEditor *editor, BOOL selected_row ) DECLSPEC_HIDDEN; +ME_Paragraph *table_insert_cell( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN; +ME_Paragraph *table_insert_row_end( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN; +ME_Paragraph *table_insert_row_start( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN; +ME_Paragraph *table_insert_row_start_at_para( ME_TextEditor *editor, ME_Paragraph *para ) DECLSPEC_HIDDEN; +void table_move_from_row_start( ME_TextEditor *editor ) DECLSPEC_HIDDEN; +ME_Paragraph *table_outer_para( ME_Paragraph *para ) DECLSPEC_HIDDEN; +void table_protect_partial_deletion( ME_TextEditor *editor, ME_Cursor *c, int *num_chars ) DECLSPEC_HIDDEN; +ME_Paragraph *table_row_end( ME_Paragraph *para ) DECLSPEC_HIDDEN; +ME_Cell *table_row_end_cell( ME_Paragraph *para ) DECLSPEC_HIDDEN; +ME_Cell *table_row_first_cell( ME_Paragraph *para ) DECLSPEC_HIDDEN; +ME_Paragraph *table_row_start( ME_Paragraph *para ) DECLSPEC_HIDDEN; struct RTFTable *ME_MakeTableDef(ME_TextEditor *editor) DECLSPEC_HIDDEN; void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef) DECLSPEC_HIDDEN; +static inline ME_DisplayItem *cell_get_di(ME_Cell *cell) +{ + return (ME_DisplayItem *)((ptrdiff_t)cell - offsetof(ME_DisplayItem, member)); +} + /* txthost.c */ -ITextHost *ME_CreateTextHost(HWND hwnd, CREATESTRUCTW *cs, BOOL bEmulateVersion10) DECLSPEC_HIDDEN; -#if defined(__i386__) && !defined(__MINGW32__) /* Use wrappers to perform thiscall on i386 */ -#define TXTHOST_VTABLE(This) (&itextHostStdcallVtbl) -#else /* __i386__ */ +#ifdef __ASM_USE_THISCALL_WRAPPER +extern const struct ITextHost2Vtbl text_host2_stdcall_vtbl DECLSPEC_HIDDEN; +#define TXTHOST_VTABLE(This) (&text_host2_stdcall_vtbl) +#else #define TXTHOST_VTABLE(This) (This)->lpVtbl -#endif /* __i386__ */ +#endif /*** ITextHost methods ***/ #define ITextHost_TxGetDC(This) TXTHOST_VTABLE(This)->TxGetDC(This) #define ITextHost_TxReleaseDC(This,a) TXTHOST_VTABLE(This)->TxReleaseDC(This,a) @@ -323,6 +367,19 @@ ITextHost *ME_CreateTextHost(HWND hwnd, CREATESTRUCTW *cs, BOOL bEmulateVersion1 #define ITextHost_TxImmGetContext(This) TXTHOST_VTABLE(This)->TxImmGetContext(This) #define ITextHost_TxImmReleaseContext(This,a) TXTHOST_VTABLE(This)->TxImmReleaseContext(This,a) #define ITextHost_TxGetSelectionBarWidth(This,a) TXTHOST_VTABLE(This)->TxGetSelectionBarWidth(This,a) +/* ITextHost2 */ +#define ITextHost2_TxIsDoubleClickPending(This) TXTHOST_VTABLE(This)->TxIsDoubleClickPending(This) +#define ITextHost2_TxGetWindow(This,a) TXTHOST_VTABLE(This)->TxGetWindow(This,a) +#define ITextHost2_TxSetForegroundWindow(This) TXTHOST_VTABLE(This)->TxSetForegroundWindow(This) +#define ITextHost2_TxGetPalette(This) TXTHOST_VTABLE(This)->TxGetPalette(This) +#define ITextHost2_TxGetEastAsianFlags(This,a) TXTHOST_VTABLE(This)->TxGetEastAsianFlags(This,a) +#define ITextHost2_TxSetCursor2(This,a,b) TXTHOST_VTABLE(This)->TxSetCursor2(This,a,b) +#define ITextHost2_TxFreeTextServicesNotification(This) TXTHOST_VTABLE(This)->TxFreeTextServicesNotification(This) +#define ITextHost2_TxGetEditStyle(This,a,b) TXTHOST_VTABLE(This)->TxGetEditStyle(This,a,b) +#define ITextHost2_TxGetWindowStyles(This,a,b) TXTHOST_VTABLE(This)->TxGetWindowStyles(This,a,b) +#define ITextHost2_TxShowDropCaret(This,a,b,c) TXTHOST_VTABLE(This)->TxShowDropCaret(This,a,b,c) +#define ITextHost2_TxDestroyCaret(This) TXTHOST_VTABLE(This)->TxDestroyCaret(This) +#define ITextHost2_TxGetHorzExtent(This,a) TXTHOST_VTABLE(This)->TxGetHorzExtent(This,a) /* undo.c */ BOOL add_undo_insert_run( ME_TextEditor *, int pos, const WCHAR *str, int len, int flags, ME_Style *style ) DECLSPEC_HIDDEN; @@ -338,6 +395,33 @@ BOOL ME_Undo(ME_TextEditor *editor) DECLSPEC_HIDDEN; BOOL ME_Redo(ME_TextEditor *editor) DECLSPEC_HIDDEN; void ME_EmptyUndoStack(ME_TextEditor *editor) DECLSPEC_HIDDEN; +/* txtsrv.c */ +HRESULT create_text_services( IUnknown *outer, ITextHost *text_host, IUnknown **unk, BOOL emulate_10 ) DECLSPEC_HIDDEN; +#ifdef __ASM_USE_THISCALL_WRAPPER +extern const struct ITextServicesVtbl text_services_stdcall_vtbl DECLSPEC_HIDDEN; +#define TXTSERV_VTABLE(This) (&text_services_stdcall_vtbl) +#else +#define TXTSERV_VTABLE(This) (This)->lpVtbl +#endif +#define ITextServices_TxSendMessage(This,a,b,c,d) TXTSERV_VTABLE(This)->TxSendMessage(This,a,b,c,d) +#define ITextServices_TxDraw(This,a,b,c,d,e,f,g,h,i,j,k,l) TXTSERV_VTABLE(This)->TxDraw(This,a,b,c,d,e,f,g,h,i,j,k,l) +#define ITextServices_TxGetHScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetHScroll(This,a,b,c,d,e) +#define ITextServices_TxGetVScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetVScroll(This,a,b,c,d,e) +#define ITextServices_OnTxSetCursor(This,a,b,c,d,e,f,g,h,i) TXTSERV_VTABLE(This)->OnTxSetCursor(This,a,b,c,d,e,f,g,h,i) +#define ITextServices_TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j) TXTSERV_VTABLE(This)->TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j) +#define ITextServices_OnTxInPlaceActivate(This,a) TXTSERV_VTABLE(This)->OnTxInPlaceActivate(This,a) +#define ITextServices_OnTxInPlaceDeactivate(This) TXTSERV_VTABLE(This)->OnTxInPlaceDeactivate(This) +#define ITextServices_OnTxUIActivate(This) TXTSERV_VTABLE(This)->OnTxUIActivate(This) +#define ITextServices_OnTxUIDeactivate(This) TXTSERV_VTABLE(This)->OnTxUIDeactivate(This) +#define ITextServices_TxGetText(This,a) TXTSERV_VTABLE(This)->TxGetText(This,a) +#define ITextServices_TxSetText(This,a) TXTSERV_VTABLE(This)->TxSetText(This,a) +#define ITextServices_TxGetCurTargetX(This,a) TXTSERV_VTABLE(This)->TxGetCurTargetX(This,a) +#define ITextServices_TxGetBaseLinePos(This,a) TXTSERV_VTABLE(This)->TxGetBaseLinePos(This,a) +#define ITextServices_TxGetNaturalSize(This,a,b,c,d,e,f,g,h) TXTSERV_VTABLE(This)->TxGetNaturalSize(This,a,b,c,d,e,f,g,h) +#define ITextServices_TxGetDropTarget(This,a) TXTSERV_VTABLE(This)->TxGetDropTarget(This,a) +#define ITextServices_OnTxPropertyBitsChange(This,a,b) TXTSERV_VTABLE(This)->OnTxPropertyBitsChange(This,a,b) +#define ITextServices_TxGetCachedSize(This,a,b) TXTSERV_VTABLE(This)->TxGetCachedSize(This,a,b) + /* writer.c */ LRESULT ME_StreamOutRange(ME_TextEditor *editor, DWORD dwFormat, const ME_Cursor *start, int nChars, EDITSTREAM *stream) DECLSPEC_HIDDEN; LRESULT ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream) DECLSPEC_HIDDEN; diff --git a/dll/win32/riched20/editstr.h b/dll/win32/riched20/editstr.h index 337750c4052..115e550f5af 100644 --- a/dll/win32/riched20/editstr.h +++ b/dll/win32/riched20/editstr.h @@ -41,15 +41,14 @@ #include #include "imm.h" #include +#include #include "usp10.h" +#include "wine/asm.h" #include "wine/debug.h" #include "wine/heap.h" #include "wine/list.h" - -#if defined(__i386__) && !defined(__MINGW32__) -extern const struct ITextHostVtbl itextHostStdcallVtbl DECLSPEC_HIDDEN; -#endif /* __i386__ */ +#include "wine/rbtree.h" typedef struct tagME_String { @@ -204,7 +203,7 @@ typedef struct tagME_Paragraph PARAFORMAT2 fmt; ME_String *text; - struct tagME_DisplayItem *pCell; /* v4.1 */ + struct tagME_Cell *cell; /* v4.1 */ ME_BorderRect border; int nCharOfs; @@ -215,7 +214,7 @@ typedef struct tagME_Paragraph struct para_num para_num; ME_Run *eop_run; /* ptr to the end-of-para run */ struct tagME_DisplayItem *prev_para, *next_para; - struct tagME_DisplayItem *prev_marked, *next_marked; + struct wine_rb_entry marked_entry; } ME_Paragraph; typedef struct tagME_Cell /* v4.1 */ @@ -226,7 +225,7 @@ typedef struct tagME_Cell /* v4.1 */ POINT pt; int nHeight, nWidth; int yTextOffset; /* The text offset is caused by the largest top border. */ - struct tagME_DisplayItem *prev_cell, *next_cell, *parent_cell; + struct tagME_Cell *prev_cell, *next_cell, *parent_cell; } ME_Cell; typedef struct tagME_Row @@ -272,8 +271,8 @@ typedef struct tagME_TextBuffer typedef struct tagME_Cursor { - ME_DisplayItem *pPara; - ME_DisplayItem *pRun; + ME_Paragraph *para; + ME_Run *run; int nOffset; } ME_Cursor; @@ -379,14 +378,20 @@ typedef struct tagME_InStream ME_InStream; typedef struct tagME_TextEditor { +#ifdef __REACTOS__ HWND hWnd, hwndParent; - ITextHost *texthost; - IUnknown *reOle; - BOOL bEmulateVersion10; +#endif + ITextHost2 *texthost; + unsigned int bEmulateVersion10 : 1; + unsigned int in_place_active : 1; + unsigned int have_texthost2 : 1; ME_TextBuffer *pBuffer; ME_Cursor *pCursors; +#ifdef __REACTOS__ DWORD styleFlags; - DWORD exStyleFlags; +#endif + DWORD props; + DWORD scrollbars; int nCursors; SIZE sizeWindow; int nTotalLength, nLastTotalLength; @@ -394,9 +399,6 @@ typedef struct tagME_TextEditor int nAvailWidth; /* 0 = wrap to client area, else wrap width in twips */ int nUDArrowX; int total_rows; - COLORREF rgbBackColor; - HBRUSH hbrBackground; - BOOL bCaretAtEnd; int nEventMask; int nModifyStep; struct list undo_stack; @@ -406,15 +408,14 @@ typedef struct tagME_TextEditor ME_UndoMode nUndoMode; int nParagraphs; int nLastSelStart, nLastSelEnd; - ME_DisplayItem *pLastSelStartPara, *pLastSelEndPara; + ME_Paragraph *last_sel_start_para, *last_sel_end_para; ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE]; int nZoomNumerator, nZoomDenominator; - RECT prevClientRect; RECT rcFormat; - BOOL bDefaultFormatRect; BOOL bWordWrap; int nTextLimit; EDITWORDBREAKPROCW pfnWordBreak; + IRichEditOle *richole; LPRICHEDITOLECALLBACK lpOleCallback; /*TEXTMODE variable; contains only one of each of the following options: *TM_RICHTEXT or TM_PLAINTEXT @@ -423,29 +424,31 @@ typedef struct tagME_TextEditor int mode; BOOL bHideSelection; BOOL AutoURLDetect_bEnable; - WCHAR cPasswordMask; + WCHAR password_char; BOOL bHaveFocus; - BOOL bDialogMode; /* Indicates that we are inside a dialog window */ #ifndef __REACTOS__ /*for IME */ int imeStartIndex; #endif DWORD selofs; /* The size of the selection bar on the left side of control */ ME_SelectionType nSelectionType; - ME_DisplayItem *first_marked_para; /* Track previous notified selection */ CHARRANGE notified_cr; /* Cache previously set scrollbar info */ SCROLLINFO vert_si, horz_si; + unsigned int vert_sb_enabled : 1; + unsigned int horz_sb_enabled : 1; int caret_height; BOOL caret_hidden; BOOL bMouseCaptured; int wheel_remain; + TXTBACKSTYLE back_style; struct list style_list; struct list reobj_list; + struct wine_rb_tree marked_paras; } ME_TextEditor; typedef struct tagME_Context @@ -462,4 +465,27 @@ typedef struct tagME_Context ME_TextEditor *editor; } ME_Context; +struct text_selection +{ + ITextSelection ITextSelection_iface; + LONG ref; + + struct text_services *services; +}; + +struct text_services +{ + IUnknown IUnknown_inner; + ITextServices ITextServices_iface; + IRichEditOle IRichEditOle_iface; + ITextDocument2Old ITextDocument2Old_iface; + IUnknown *outer_unk; + LONG ref; + ME_TextEditor *editor; + struct text_selection *text_selection; + struct list rangelist; + struct list clientsites; + char spare[256]; /* for bug #12179 */ +}; + #endif diff --git a/dll/win32/riched20/paint.c b/dll/win32/riched20/paint.c index 05be17e24c5..6ab7e4de76b 100644 --- a/dll/win32/riched20/paint.c +++ b/dll/win32/riched20/paint.c @@ -23,14 +23,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); -static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph); +static void draw_paragraph( ME_Context *c, ME_Paragraph *para ); -void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate) +static inline BOOL editor_opaque( ME_TextEditor *editor ) { - ME_DisplayItem *item; + return editor->back_style != TXTBACK_TRANSPARENT; +} + +void editor_draw( ME_TextEditor *editor, HDC hDC, const RECT *update ) +{ + ME_Paragraph *para; ME_Context c; + ME_Cell *cell; int ys, ye; HRGN oldRgn; + RECT rc, client; + HBRUSH brush = CreateSolidBrush( ITextHost_TxGetSysColor( editor->texthost, COLOR_WINDOW ) ); + + ME_InitContext( &c, editor, hDC ); + if (!update) + { + client = c.rcView; + client.left -= editor->selofs; + update = &client; + } oldRgn = CreateRectRgn(0, 0, 0, 0); if (!GetClipRgn(hDC, oldRgn)) @@ -38,69 +54,66 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate) DeleteObject(oldRgn); oldRgn = NULL; } - IntersectClipRect(hDC, rcUpdate->left, rcUpdate->top, - rcUpdate->right, rcUpdate->bottom); + IntersectClipRect( hDC, update->left, update->top, update->right, update->bottom ); - ME_InitContext(&c, editor, hDC); + brush = SelectObject( hDC, brush ); SetBkMode(hDC, TRANSPARENT); - item = editor->pBuffer->pFirst->next; + para = editor_first_para( editor ); /* This context point is an offset for the paragraph positions stored * during wrapping. It shouldn't be modified during painting. */ c.pt.x = c.rcView.left - editor->horz_si.nPos; c.pt.y = c.rcView.top - editor->vert_si.nPos; - while(item != editor->pBuffer->pLast) + while (para_next( para )) { - assert(item->type == diParagraph); - - ys = c.pt.y + item->member.para.pt.y; - if (item->member.para.pCell - != item->member.para.next_para->member.para.pCell) - { - ME_Cell *cell = NULL; - cell = &ME_FindItemBack(item->member.para.next_para, diCell)->member.cell; + ys = c.pt.y + para->pt.y; + cell = para_cell( para ); + if (cell && para == cell_end_para( cell )) ye = c.pt.y + cell->pt.y + cell->nHeight; - } else { - ye = ys + item->member.para.nHeight; - } - if (item->member.para.pCell && !(item->member.para.nFlags & MEPF_ROWEND) && - item->member.para.pCell != item->member.para.prev_para->member.para.pCell) + else ye = ys + para->nHeight; + + if (cell && !(para->nFlags & MEPF_ROWEND) && para == cell_first_para( cell )) { /* the border shifts the text down */ - ys -= item->member.para.pCell->member.cell.yTextOffset; + ys -= para_cell( para )->yTextOffset; } /* Draw the paragraph if any of the paragraph is in the update region. */ - if (ys < rcUpdate->bottom && ye > rcUpdate->top) - ME_DrawParagraph(&c, item); - item = item->member.para.next_para; + if (ys < update->bottom && ye > update->top) + draw_paragraph( &c, para ); + para = para_next( para ); } - if (c.pt.y + editor->nTotalLength < c.rcView.bottom) + if (editor_opaque( editor )) { - /* Fill space after the end of the text. */ - RECT rc; - rc.top = c.pt.y + editor->nTotalLength; - rc.left = c.rcView.left; - rc.bottom = c.rcView.bottom; - rc.right = c.rcView.right; + if (c.pt.y + editor->nTotalLength < c.rcView.bottom) + { /* space after the end of the text */ + rc.top = c.pt.y + editor->nTotalLength; + rc.left = c.rcView.left; + rc.bottom = c.rcView.bottom; + rc.right = c.rcView.right; + if (IntersectRect( &rc, &rc, update )) + PatBlt(hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); + } + if (editor->selofs) + { /* selection bar */ + rc.left = c.rcView.left - editor->selofs; + rc.top = c.rcView.top; + rc.right = c.rcView.left; + rc.bottom = c.rcView.bottom; + if (IntersectRect( &rc, &rc, update )) + PatBlt( hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY ); + } + } - IntersectRect(&rc, &rc, rcUpdate); + DeleteObject( SelectObject( hDC, brush ) ); + SelectClipRgn( hDC, oldRgn ); + if (oldRgn) DeleteObject( oldRgn ); + ME_DestroyContext( &c ); - if (!IsRectEmpty(&rc)) - PatBlt(hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); - } - if (editor->nTotalLength != editor->nLastTotalLength || - editor->nTotalWidth != editor->nLastTotalWidth) + if (editor->nTotalLength != editor->nLastTotalLength || editor->nTotalWidth != editor->nLastTotalWidth) ME_SendRequestResize(editor, FALSE); editor->nLastTotalLength = editor->nTotalLength; editor->nLastTotalWidth = editor->nTotalWidth; - - SelectClipRgn(hDC, oldRgn); - if (oldRgn) - DeleteObject(oldRgn); - - c.hDC = NULL; - ME_DestroyContext(&c); } void ME_Repaint(ME_TextEditor *editor) @@ -123,17 +136,18 @@ void ME_UpdateRepaint(ME_TextEditor *editor, BOOL update_now) ME_UpdateScrollBar(editor); /* Ensure that the cursor is visible */ - ME_EnsureVisible(editor, &editor->pCursors[0]); + editor_ensure_visible( editor, &editor->pCursors[0] ); + + update_caret( editor ); ITextHost_TxViewChange(editor->texthost, update_now); ME_SendSelChange(editor); - /* send EN_CHANGE if the event mask asks for it */ if(editor->nEventMask & ENM_CHANGE) { editor->nEventMask &= ~ENM_CHANGE; - ME_SendOldNotify(editor, EN_CHANGE); + ITextHost_TxNotify( editor->texthost, EN_CHANGE, NULL ); editor->nEventMask |= ENM_CHANGE; } } @@ -144,7 +158,7 @@ ME_RewrapRepaint(ME_TextEditor *editor) /* RewrapRepaint should be called whenever the control has changed in * looks, but not content. Like resizing. */ - ME_MarkAllForWrapping(editor); + editor_mark_rewrap_all( editor ); ME_WrapMarkedParagraphs(editor); ME_UpdateScrollBar(editor); ME_Repaint(editor); @@ -276,8 +290,8 @@ static void draw_space( ME_Context *c, ME_Run *run, int x, int y, SetRect( &rect, x, ymin, x + run->nWidth, ymin + cy ); - if (c->editor->bHideSelection || (!c->editor->bHaveFocus && - !(c->editor->styleFlags & ES_NOHIDESEL))) selected = FALSE; + if (c->editor->bHideSelection || (!c->editor->bHaveFocus && (c->editor->props & TXTBIT_HIDESELECTION))) + selected = FALSE; if (c->editor->bEmulateVersion10) { old_style_selected = selected; @@ -339,9 +353,9 @@ static void draw_text( ME_Context *c, ME_Run *run, int x, int y, BOOL selected, && !(CFE_AUTOBACKCOLOR & run->style->fmt.dwEffects) ) ); - if (c->editor->cPasswordMask) + if (c->editor->password_char) { - masked = ME_MakeStringR( c->editor->cPasswordMask, run->len ); + masked = ME_MakeStringR( c->editor->password_char, run->len ); text = masked->szData; } @@ -365,14 +379,14 @@ static void draw_text( ME_Context *c, ME_Run *run, int x, int y, BOOL selected, } -static void ME_DrawTextWithStyle(ME_Context *c, ME_Run *run, int x, int y, - int nSelFrom, int nSelTo, int ymin, int cy) +static void draw_text_with_style( ME_Context *c, ME_Run *run, int x, int y, + int nSelFrom, int nSelTo, int ymin, int cy ) { HDC hDC = c->hDC; int yOffset = 0; BOOL selected = (nSelFrom < run->len && nSelTo >= 0 && nSelFrom < nSelTo && !c->editor->bHideSelection && - (c->editor->bHaveFocus || (c->editor->styleFlags & ES_NOHIDESEL))); + (c->editor->bHaveFocus || !(c->editor->props & TXTBIT_HIDESELECTION))); BOOL old_style_selected = FALSE; RECT sel_rect; HRGN clip = NULL, sel_rgn = NULL; @@ -440,17 +454,16 @@ static void ME_DebugWrite(HDC hDC, const POINT *pt, LPCWSTR szText) { SetTextColor(hDC, color); } -static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Paragraph *para) +static void draw_run( ME_Context *c, int x, int y, ME_Cursor *cursor ) { - ME_Run *run = &rundi->member.run; - ME_DisplayItem *start; - int runofs = run->nCharOfs+para->nCharOfs; + ME_Row *row; + ME_Run *run = cursor->run; + int runofs = run_char_ofs( run, cursor->nOffset ); int nSelFrom, nSelTo; - - if (run->nFlags & MERF_HIDDEN) - return; - start = ME_FindItemBack(rundi, diStartRow); + if (run->nFlags & MERF_HIDDEN) return; + + row = row_from_cursor( cursor ); ME_GetSelectionOfs(c->editor, &nSelFrom, &nSelTo); /* Draw selected end-of-paragraph mark */ @@ -459,8 +472,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa if (runofs >= nSelFrom && runofs < nSelTo) { draw_space( c, run, x, y, TRUE, FALSE, - c->pt.y + para->pt.y + start->member.row.pt.y, - start->member.row.nHeight ); + c->pt.y + run->para->pt.y + row->pt.y, row->nHeight ); } return; } @@ -470,19 +482,15 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa BOOL selected = runofs >= nSelFrom && runofs < nSelTo; draw_space( c, run, x, y, selected, TRUE, - c->pt.y + para->pt.y + start->member.row.pt.y, - start->member.row.nHeight ); + c->pt.y + run->para->pt.y + row->pt.y, row->nHeight ); return; } if (run->nFlags & MERF_GRAPHICS) - ME_DrawOLE(c, x, y, run, (runofs >= nSelFrom) && (runofs < nSelTo)); + draw_ole( c, x, y, run, (runofs >= nSelFrom) && (runofs < nSelTo) ); else - { - ME_DrawTextWithStyle(c, run, x, y, nSelFrom - runofs, nSelTo - runofs, - c->pt.y + para->pt.y + start->member.row.pt.y, - start->member.row.nHeight); - } + draw_text_with_style( c, run, x, y, nSelFrom - runofs, nSelTo - runofs, + c->pt.y + run->para->pt.y + row->pt.y, row->nHeight ); } /* The documented widths are in points (72 dpi), but converting them to @@ -593,22 +601,28 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT if (para->fmt.dwMask & PFM_SPACEBEFORE) { - rc.left = c->rcView.left; - rc.right = c->rcView.right; - rc.top = y; bounds->top = ME_twips2pointsY(c, para->fmt.dySpaceBefore); - rc.bottom = y + bounds->top + top_border; - PatBlt(c->hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); + if (editor_opaque( c->editor )) + { + rc.left = c->rcView.left; + rc.right = c->rcView.right; + rc.top = y; + rc.bottom = y + bounds->top + top_border; + PatBlt(c->hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); + } } if (para->fmt.dwMask & PFM_SPACEAFTER) { - rc.left = c->rcView.left; - rc.right = c->rcView.right; - rc.bottom = y + para->nHeight; bounds->bottom = ME_twips2pointsY(c, para->fmt.dySpaceAfter); - rc.top = rc.bottom - bounds->bottom - bottom_border; - PatBlt(c->hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); + if (editor_opaque( c->editor )) + { + rc.left = c->rcView.left; + rc.right = c->rcView.right; + rc.bottom = y + para->nHeight; + rc.top = rc.bottom - bounds->bottom - bottom_border; + PatBlt(c->hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); + } } /* Native richedit doesn't support paragraph borders in v1.0 - 4.1, @@ -696,51 +710,54 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT } } -static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) +static void draw_table_borders( ME_Context *c, ME_Paragraph *para ) { - ME_Paragraph *para = ¶graph->member.para; if (!c->editor->bEmulateVersion10) /* v4.1 */ { - if (para->pCell) + if (para_cell( para )) { RECT rc; - ME_Cell *cell = ¶->pCell->member.cell; - ME_DisplayItem *paraAfterRow; + ME_Cell *cell = para_cell( para ); + ME_Paragraph *after_row; HPEN pen, oldPen; LOGBRUSH logBrush; HBRUSH brush; COLORREF color; POINT oldPt; int width; - BOOL atTop = (para->pCell != para->prev_para->member.para.pCell); - BOOL atBottom = (para->pCell != para->next_para->member.para.pCell); + BOOL atTop = (para == cell_first_para( cell )); + BOOL atBottom = (para == cell_end_para( cell )); int top = c->pt.y + (atTop ? cell->pt.y : para->pt.y); int bottom = (atBottom ? c->pt.y + cell->pt.y + cell->nHeight : top + para->nHeight + (atTop ? cell->yTextOffset : 0)); rc.left = c->pt.x + cell->pt.x; rc.right = rc.left + cell->nWidth; - if (atTop) { + if (atTop) + { /* Erase gap before text if not all borders are the same height. */ width = max(ME_twips2pointsY(c, cell->border.top.width), 1); rc.top = top + width; width = cell->yTextOffset - width; rc.bottom = rc.top + width; - if (width) + if (width && editor_opaque( c->editor )) PatBlt(c->hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); } /* Draw cell borders. * The order borders are draw in is left, top, bottom, right in order * to be consistent with native richedit. This is noticeable from the * overlap of borders of different colours. */ - if (!(para->nFlags & MEPF_ROWEND)) { + if (!(para->nFlags & MEPF_ROWEND)) + { rc.top = top; rc.bottom = bottom; if (cell->border.left.width > 0) { color = cell->border.left.colorRef; width = max(ME_twips2pointsX(c, cell->border.left.width), 1); - } else { + } + else + { color = RGB(192,192,192); width = 1; } @@ -757,12 +774,15 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) MoveToEx(c->hDC, oldPt.x, oldPt.y, NULL); } - if (atTop) { + if (atTop) + { if (cell->border.top.width > 0) { brush = CreateSolidBrush(cell->border.top.colorRef); width = max(ME_twips2pointsY(c, cell->border.top.width), 1); - } else { + } + else + { brush = GetStockObject(LTGRAY_BRUSH); width = 1; } @@ -775,29 +795,24 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) /* Draw the bottom border if at the last paragraph in the cell, and when * in the last row of the table. */ - if (atBottom) { + if (atBottom) + { int oldLeft = rc.left; width = max(ME_twips2pointsY(c, cell->border.bottom.width), 1); - paraAfterRow = ME_GetTableRowEnd(paragraph)->member.para.next_para; - if (paraAfterRow->member.para.nFlags & MEPF_ROWSTART) { - ME_DisplayItem *nextEndCell; - nextEndCell = ME_FindItemBack(ME_GetTableRowEnd(paraAfterRow), diCell); - assert(nextEndCell && !nextEndCell->member.cell.next_cell); - rc.left = c->pt.x + nextEndCell->member.cell.pt.x; - /* FIXME: Native draws FROM the bottom of the table rather than - * TO the bottom of the table in this case, but just doing so here - * will cause the next row to erase the border. */ - /* - rc.top = bottom; - rc.bottom = rc.top + width; - */ + after_row = para_next( table_row_end( para ) ); + if (after_row->nFlags & MEPF_ROWSTART) + { + ME_Cell *next_end; + next_end = table_row_end_cell( after_row ); + assert( next_end && !cell_next( next_end ) ); + rc.left = c->pt.x + next_end->pt.x; } - if (rc.left < rc.right) { - if (cell->border.bottom.width > 0) { + if (rc.left < rc.right) + { + if (cell->border.bottom.width > 0) brush = CreateSolidBrush(cell->border.bottom.colorRef); - } else { + else brush = GetStockObject(LTGRAY_BRUSH); - } rc.bottom = bottom; rc.top = rc.bottom - width; FillRect(c->hDC, &rc, brush); @@ -808,15 +823,17 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) } /* Right border only drawn if at the end of the table row. */ - if (!cell->next_cell->member.cell.next_cell && - !(para->nFlags & MEPF_ROWSTART)) + if (!cell_next( cell_next( cell ) ) && !(para->nFlags & MEPF_ROWSTART)) { rc.top = top; rc.bottom = bottom; - if (cell->border.right.width > 0) { + if (cell->border.right.width > 0) + { color = cell->border.right.colorRef; width = max(ME_twips2pointsX(c, cell->border.right.width), 1); - } else { + } + else + { color = RGB(192,192,192); width = 1; } @@ -833,19 +850,21 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) MoveToEx(c->hDC, oldPt.x, oldPt.y, NULL); } } - } else { /* v1.0 - 3.0 */ + } + else /* v1.0 - 3.0 */ + { /* Draw simple table border */ - if (para->fmt.dwMask & PFM_TABLE && para->fmt.wEffects & PFE_TABLE) { + if (para_in_table( para )) + { HPEN pen = NULL, oldpen = NULL; int i, firstX, startX, endX, rowY, rowBottom, nHeight; POINT oldPt; - PARAFORMAT2 *pNextFmt; pen = CreatePen(PS_SOLID, 0, para->border.top.colorRef); oldpen = SelectObject(c->hDC, pen); /* Find the start relative to the text */ - firstX = c->pt.x + ME_FindItemFwd(paragraph, diRun)->member.run.pt.x; + firstX = c->pt.x + para_first_run( para )->pt.x; /* Go back by the horizontal gap, which is stored in dxOffset */ firstX -= ME_twips2pointsX(c, para->fmt.dxOffset); /* The left edge, stored in dxStartIndent affected just the first edge */ @@ -853,7 +872,7 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) rowY = c->pt.y + para->pt.y; if (para->fmt.dwMask & PFM_SPACEBEFORE) rowY += ME_twips2pointsY(c, para->fmt.dySpaceBefore); - nHeight = ME_FindItemFwd(paragraph, diStartRow)->member.row.nHeight; + nHeight = para_first_row( para )->nHeight; rowBottom = rowY + nHeight; /* Draw horizontal lines */ @@ -861,11 +880,9 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) i = para->fmt.cTabCount - 1; endX = startX + ME_twips2pointsX(c, para->fmt.rgxTabs[i] & 0x00ffffff) + 1; LineTo(c->hDC, endX, rowY); - pNextFmt = ¶->next_para->member.para.fmt; /* The bottom of the row only needs to be drawn if the next row is * not a table. */ - if (!(pNextFmt && pNextFmt->dwMask & PFM_TABLE && pNextFmt->wEffects && - para->nRows == 1)) + if (!(para_next( para ) && para_in_table( para_next( para ) ) && para->nRows == 1)) { /* Decrement rowBottom to draw the bottom line within the row, and * to not draw over this line when drawing the vertical lines. */ @@ -892,9 +909,8 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) } } -static void draw_para_number( ME_Context *c, ME_DisplayItem *p ) +static void draw_para_number( ME_Context *c, ME_Paragraph *para ) { - ME_Paragraph *para = &p->member.para; int x, y; COLORREF old_text; @@ -912,12 +928,12 @@ static void draw_para_number( ME_Context *c, ME_DisplayItem *p ) } } -static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) +static void draw_paragraph( ME_Context *c, ME_Paragraph *para ) { int align = SetTextAlign(c->hDC, TA_BASELINE); ME_DisplayItem *p; + ME_Cell *cell; ME_Run *run; - ME_Paragraph *para = NULL; RECT rc, bounds; int y; int height = 0, baseline = 0, no=0; @@ -926,32 +942,33 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) rc.left = c->pt.x; rc.right = c->rcView.right; - assert(paragraph); - para = ¶graph->member.para; y = c->pt.y + para->pt.y; - if (para->pCell) + if ((cell = para_cell( para ))) { - ME_Cell *cell = ¶->pCell->member.cell; rc.left = c->pt.x + cell->pt.x; rc.right = rc.left + cell->nWidth; } - if (para->nFlags & MEPF_ROWSTART) { - ME_Cell *cell = ¶->next_para->member.para.pCell->member.cell; + if (para->nFlags & MEPF_ROWSTART) + { + cell = table_row_first_cell( para ); rc.right = c->pt.x + cell->pt.x; - } else if (para->nFlags & MEPF_ROWEND) { - ME_Cell *cell = ¶->prev_para->member.para.pCell->member.cell; + } + else if (para->nFlags & MEPF_ROWEND) + { + cell = table_row_end_cell( para ); rc.left = c->pt.x + cell->pt.x + cell->nWidth; } ME_DrawParaDecoration(c, para, y, &bounds); y += bounds.top; - if (bounds.left || bounds.right) { + if (bounds.left || bounds.right) + { rc.left = max(rc.left, c->pt.x + bounds.left); rc.right = min(rc.right, c->pt.x - bounds.right + max(c->editor->sizeWindow.cx, c->editor->nTotalWidth)); } - for (p = paragraph->next; p != para->next_para; p = p->next) + for (p = para_get_di( para )->next; p != para_get_di( para_next( para ) ); p = p->next) { switch(p->type) { case diParagraph: @@ -966,7 +983,7 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) rc.bottom = y + p->member.row.nHeight; } visible = RectVisible(c->hDC, &rc); - if (visible) + if (editor_opaque( c->editor ) && visible) PatBlt(c->hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); if (bounds.right) { @@ -975,16 +992,15 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) RECT after_bdr = rc; after_bdr.left = rc.right + bounds.right; after_bdr.right = c->rcView.right; - if (RectVisible(c->hDC, &after_bdr)) + if (editor_opaque( c->editor ) && RectVisible( c->hDC, &after_bdr )) PatBlt(c->hDC, after_bdr.left, after_bdr.top, after_bdr.right - after_bdr.left, after_bdr.bottom - after_bdr.top, PATCOPY); } if (me_debug) { - static const WCHAR wszRowDebug[] = {'r','o','w','[','%','d',']',0}; WCHAR buf[128]; POINT pt = c->pt; - wsprintfW(buf, wszRowDebug, no); + wsprintfW( buf, L"row[%d]", no ); pt.y = 12+y; ME_DebugWrite(c->hDC, &pt, buf); } @@ -1005,44 +1021,71 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) FrameRect(c->hDC, &rc, GetSysColorBrush(COLOR_GRAYTEXT)); } if (visible) - ME_DrawRun(c, c->pt.x + run->pt.x, - c->pt.y + para->pt.y + run->pt.y + baseline, p, para); + { + ME_Cursor cursor; + + cursor.run = run; + cursor.para = para; + cursor.nOffset = 0; + draw_run( c, c->pt.x + run->pt.x, c->pt.y + para->pt.y + run->pt.y + baseline, &cursor ); + } if (me_debug) { - static const WCHAR wszRunDebug[] = {'[','%','d',':','%','x',']',' ','%','l','s',0}; WCHAR buf[2560]; POINT pt; pt.x = c->pt.x + run->pt.x; pt.y = c->pt.y + para->pt.y + run->pt.y; - wsprintfW(buf, wszRunDebug, no, p->member.run.nFlags, get_text( &p->member.run, 0 )); + wsprintfW( buf, L"[%d:%x] %ls", no, p->member.run.nFlags, get_text( &p->member.run, 0 )); ME_DebugWrite(c->hDC, &pt, buf); } break; - case diCell: - /* Clear any space at the bottom of the cell after the text. */ - if (para->nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) - break; - y += height; - rc.top = c->pt.y + para->pt.y + para->nHeight; - rc.bottom = c->pt.y + p->member.cell.pt.y + p->member.cell.nHeight; - if (RectVisible(c->hDC, &rc)) - PatBlt(c->hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); - break; default: break; } no++; } - ME_DrawTableBorders(c, paragraph); - draw_para_number(c, paragraph); + if (editor_opaque( c->editor ) && para_cell( para )) + { + /* Clear any space at the bottom of the cell after the text. */ + rc.top = c->pt.y + para->pt.y + para->nHeight; + rc.bottom = c->pt.y + cell->pt.y + cell->nHeight; + PatBlt( c->hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY ); + } + + draw_table_borders( c, para ); + draw_para_number( c, para ); + + SetTextAlign( c->hDC, align ); +} + +static void enable_show_scrollbar( ME_TextEditor *editor, INT bar, BOOL enable ) +{ + if (enable || editor->scrollbars & ES_DISABLENOSCROLL) + ITextHost_TxEnableScrollBar( editor->texthost, bar, enable ? 0 : ESB_DISABLE_BOTH ); + if (!(editor->scrollbars & ES_DISABLENOSCROLL)) + ITextHost_TxShowScrollBar( editor->texthost, bar, enable ); +} - SetTextAlign(c->hDC, align); +static void set_scroll_range_pos( ME_TextEditor *editor, INT bar, SCROLLINFO *info, BOOL set_range, BOOL notify ) +{ + LONG max_pos = info->nMax, pos = info->nPos; + + /* Scale the scrollbar info to 16-bit values. */ + if (max_pos > 0xffff) + { + pos = MulDiv( pos, 0xffff, max_pos ); + max_pos = 0xffff; + } + if (set_range) ITextHost_TxSetScrollRange( editor->texthost, bar, 0, max_pos, FALSE ); + ITextHost_TxSetScrollPos( editor->texthost, bar, pos, TRUE ); + + if (notify && editor->nEventMask & ENM_SCROLL) + ITextHost_TxNotify( editor->texthost, bar == SB_VERT ? EN_VSCROLL : EN_HSCROLL, NULL ); } -void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) +void scroll_abs( ME_TextEditor *editor, int x, int y, BOOL notify ) { - BOOL bScrollBarIsVisible, bScrollBarWillBeVisible; int scrollX = 0, scrollY = 0; if (editor->horz_si.nPos != x) { @@ -1050,9 +1093,7 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) x = max(x, editor->horz_si.nMin); scrollX = editor->horz_si.nPos - x; editor->horz_si.nPos = x; - if (editor->horz_si.nMax > 0xFFFF) /* scale to 16-bit value */ - x = MulDiv(x, 0xFFFF, editor->horz_si.nMax); - ITextHost_TxSetScrollPos(editor->texthost, SB_HORZ, x, TRUE); + set_scroll_range_pos( editor, SB_HORZ, &editor->horz_si, FALSE, notify ); } if (editor->vert_si.nPos != y) { @@ -1060,269 +1101,153 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) y = max(y, editor->vert_si.nMin); scrollY = editor->vert_si.nPos - y; editor->vert_si.nPos = y; - if (editor->vert_si.nMax > 0xFFFF) /* scale to 16-bit value */ - y = MulDiv(y, 0xFFFF, editor->vert_si.nMax); - ITextHost_TxSetScrollPos(editor->texthost, SB_VERT, y, TRUE); + set_scroll_range_pos( editor, SB_VERT, &editor->vert_si, FALSE, notify ); } - if (abs(scrollX) > editor->sizeWindow.cx || - abs(scrollY) > editor->sizeWindow.cy) + if (abs(scrollX) > editor->sizeWindow.cx || abs(scrollY) > editor->sizeWindow.cy) ITextHost_TxInvalidateRect(editor->texthost, NULL, TRUE); else ITextHost_TxScrollWindowEx(editor->texthost, scrollX, scrollY, &editor->rcFormat, &editor->rcFormat, NULL, NULL, SW_INVALIDATE); - ME_Repaint(editor); - - if (editor->hWnd) - { - LONG winStyle = GetWindowLongW(editor->hWnd, GWL_STYLE); - if (editor->styleFlags & WS_HSCROLL) - { - bScrollBarIsVisible = (winStyle & WS_HSCROLL) != 0; - bScrollBarWillBeVisible = (editor->nTotalWidth > editor->sizeWindow.cx - && (editor->styleFlags & WS_HSCROLL)) - || (editor->styleFlags & ES_DISABLENOSCROLL); - if (bScrollBarIsVisible != bScrollBarWillBeVisible) - ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ, - bScrollBarWillBeVisible); - } - - if (editor->styleFlags & WS_VSCROLL) - { - bScrollBarIsVisible = (winStyle & WS_VSCROLL) != 0; - bScrollBarWillBeVisible = (editor->nTotalLength > editor->sizeWindow.cy - && (editor->styleFlags & WS_VSCROLL) - && (editor->styleFlags & ES_MULTILINE)) - || (editor->styleFlags & ES_DISABLENOSCROLL); - if (bScrollBarIsVisible != bScrollBarWillBeVisible) - ITextHost_TxShowScrollBar(editor->texthost, SB_VERT, - bScrollBarWillBeVisible); - } - } ME_UpdateScrollBar(editor); + ME_Repaint(editor); } -void ME_HScrollAbs(ME_TextEditor *editor, int x) +void scroll_h_abs( ME_TextEditor *editor, int x, BOOL notify ) { - ME_ScrollAbs(editor, x, editor->vert_si.nPos); + scroll_abs( editor, x, editor->vert_si.nPos, notify ); } -void ME_VScrollAbs(ME_TextEditor *editor, int y) +void scroll_v_abs( ME_TextEditor *editor, int y, BOOL notify ) { - ME_ScrollAbs(editor, editor->horz_si.nPos, y); + scroll_abs( editor, editor->horz_si.nPos, y, notify ); } void ME_ScrollUp(ME_TextEditor *editor, int cy) { - ME_VScrollAbs(editor, editor->vert_si.nPos - cy); + scroll_v_abs( editor, editor->vert_si.nPos - cy, TRUE ); } void ME_ScrollDown(ME_TextEditor *editor, int cy) { - ME_VScrollAbs(editor, editor->vert_si.nPos + cy); + scroll_v_abs( editor, editor->vert_si.nPos + cy, TRUE ); } void ME_ScrollLeft(ME_TextEditor *editor, int cx) { - ME_HScrollAbs(editor, editor->horz_si.nPos - cx); + scroll_h_abs( editor, editor->horz_si.nPos - cx, TRUE ); } void ME_ScrollRight(ME_TextEditor *editor, int cx) { - ME_HScrollAbs(editor, editor->horz_si.nPos + cx); -} - -/* Calculates the visibility after a call to SetScrollRange or - * SetScrollInfo with SIF_RANGE. */ -static BOOL ME_PostSetScrollRangeVisibility(SCROLLINFO *si) -{ - if (si->fMask & SIF_DISABLENOSCROLL) - return TRUE; - - /* This must match the check in SetScrollInfo to determine whether - * to show or hide the scrollbars. */ - return si->nMin < si->nMax - max(si->nPage - 1, 0); + scroll_h_abs( editor, editor->horz_si.nPos + cx, TRUE ); } void ME_UpdateScrollBar(ME_TextEditor *editor) { /* Note that this is the only function that should ever call * SetScrollInfo with SIF_PAGE or SIF_RANGE. */ - - SCROLLINFO si; - BOOL bScrollBarWasVisible, bScrollBarWillBeVisible; + BOOL enable; if (ME_WrapMarkedParagraphs(editor)) FIXME("ME_UpdateScrollBar had to call ME_WrapMarkedParagraphs\n"); - si.cbSize = sizeof(si); - si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; - si.nMin = 0; - if (editor->styleFlags & ES_DISABLENOSCROLL) - si.fMask |= SIF_DISABLENOSCROLL; - /* Update horizontal scrollbar */ - bScrollBarWasVisible = editor->horz_si.nMax > editor->horz_si.nPage; - bScrollBarWillBeVisible = editor->nTotalWidth > editor->sizeWindow.cx; - if (editor->horz_si.nPos && !bScrollBarWillBeVisible) + enable = editor->nTotalWidth > editor->sizeWindow.cx; + if (editor->horz_si.nPos && !enable) { - ME_HScrollAbs(editor, 0); - /* ME_HScrollAbs will call this function, - * so nothing else needs to be done here. */ + scroll_h_abs( editor, 0, TRUE ); + /* ME_HScrollAbs will call this function, so nothing else needs to be done here. */ return; } - si.nMax = editor->nTotalWidth; - si.nPos = editor->horz_si.nPos; - si.nPage = editor->sizeWindow.cx; - - if (si.nMax != editor->horz_si.nMax || - si.nPage != editor->horz_si.nPage) + if (editor->scrollbars & WS_HSCROLL && !enable ^ !editor->horz_sb_enabled) { - TRACE("min=%d max=%d page=%d\n", si.nMin, si.nMax, si.nPage); - editor->horz_si.nMax = si.nMax; - editor->horz_si.nPage = si.nPage; - if ((bScrollBarWillBeVisible || bScrollBarWasVisible) && - editor->styleFlags & WS_HSCROLL) - { - if (si.nMax > 0xFFFF) - { - /* Native scales the scrollbar info to 16-bit external values. */ - si.nPos = MulDiv(si.nPos, 0xFFFF, si.nMax); - si.nMax = 0xFFFF; - } - if (editor->hWnd) { - SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE); - } else { - ITextHost_TxSetScrollRange(editor->texthost, SB_HORZ, si.nMin, si.nMax, FALSE); - ITextHost_TxSetScrollPos(editor->texthost, SB_HORZ, si.nPos, TRUE); - } - /* SetScrollInfo or SetScrollRange change scrollbar visibility. */ - bScrollBarWasVisible = ME_PostSetScrollRangeVisibility(&si); - } + editor->horz_sb_enabled = enable; + enable_show_scrollbar( editor, SB_HORZ, enable ); } - if (editor->styleFlags & WS_HSCROLL) + if (editor->horz_si.nMax != editor->nTotalWidth || editor->horz_si.nPage != editor->sizeWindow.cx) { - if (si.fMask & SIF_DISABLENOSCROLL) { - bScrollBarWillBeVisible = TRUE; - } else if (!(editor->styleFlags & WS_HSCROLL)) { - bScrollBarWillBeVisible = FALSE; - } - - if (bScrollBarWasVisible != bScrollBarWillBeVisible) - ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ, bScrollBarWillBeVisible); + editor->horz_si.nMax = editor->nTotalWidth; + editor->horz_si.nPage = editor->sizeWindow.cx; + TRACE( "min = %d max = %d page = %d\n", editor->horz_si.nMin, editor->horz_si.nMax, editor->horz_si.nPage ); + if ((enable || editor->horz_sb_enabled) && editor->scrollbars & WS_HSCROLL) + set_scroll_range_pos( editor, SB_HORZ, &editor->horz_si, TRUE, TRUE ); } /* Update vertical scrollbar */ - bScrollBarWasVisible = editor->vert_si.nMax > editor->vert_si.nPage; - bScrollBarWillBeVisible = editor->nTotalLength > editor->sizeWindow.cy && - (editor->styleFlags & ES_MULTILINE); + enable = editor->nTotalLength > editor->sizeWindow.cy && (editor->props & TXTBIT_MULTILINE); - if (editor->vert_si.nPos && !bScrollBarWillBeVisible) + if (editor->vert_si.nPos && !enable) { - ME_VScrollAbs(editor, 0); - /* ME_VScrollAbs will call this function, - * so nothing else needs to be done here. */ + scroll_v_abs( editor, 0, TRUE ); + /* ME_VScrollAbs will call this function, so nothing else needs to be done here. */ return; } - si.nMax = editor->nTotalLength; - si.nPos = editor->vert_si.nPos; - si.nPage = editor->sizeWindow.cy; - - if (si.nMax != editor->vert_si.nMax || - si.nPage != editor->vert_si.nPage) + if (editor->scrollbars & WS_VSCROLL && !enable ^ !editor->vert_sb_enabled) { - TRACE("min=%d max=%d page=%d\n", si.nMin, si.nMax, si.nPage); - editor->vert_si.nMax = si.nMax; - editor->vert_si.nPage = si.nPage; - if ((bScrollBarWillBeVisible || bScrollBarWasVisible) && - editor->styleFlags & WS_VSCROLL) - { - if (si.nMax > 0xFFFF) - { - /* Native scales the scrollbar info to 16-bit external values. */ - si.nPos = MulDiv(si.nPos, 0xFFFF, si.nMax); - si.nMax = 0xFFFF; - } - if (editor->hWnd) { - SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE); - } else { - ITextHost_TxSetScrollRange(editor->texthost, SB_VERT, si.nMin, si.nMax, FALSE); - ITextHost_TxSetScrollPos(editor->texthost, SB_VERT, si.nPos, TRUE); - } - /* SetScrollInfo or SetScrollRange change scrollbar visibility. */ - bScrollBarWasVisible = ME_PostSetScrollRangeVisibility(&si); - } + editor->vert_sb_enabled = enable; + enable_show_scrollbar( editor, SB_VERT, enable ); } - if (editor->styleFlags & WS_VSCROLL) + if (editor->vert_si.nMax != editor->nTotalLength || editor->vert_si.nPage != editor->sizeWindow.cy) { - if (si.fMask & SIF_DISABLENOSCROLL) { - bScrollBarWillBeVisible = TRUE; - } else if (!(editor->styleFlags & WS_VSCROLL)) { - bScrollBarWillBeVisible = FALSE; - } - - if (bScrollBarWasVisible != bScrollBarWillBeVisible) - ITextHost_TxShowScrollBar(editor->texthost, SB_VERT, - bScrollBarWillBeVisible); + editor->vert_si.nMax = editor->nTotalLength; + editor->vert_si.nPage = editor->sizeWindow.cy; + TRACE( "min = %d max = %d page = %d\n", editor->vert_si.nMin, editor->vert_si.nMax, editor->vert_si.nPage ); + if ((enable || editor->vert_sb_enabled) && editor->scrollbars & WS_VSCROLL) + set_scroll_range_pos( editor, SB_VERT, &editor->vert_si, TRUE, TRUE ); } } -void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor) +void editor_ensure_visible( ME_TextEditor *editor, ME_Cursor *cursor ) { - ME_Run *pRun = &pCursor->pRun->member.run; - ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow); - ME_DisplayItem *pPara = pCursor->pPara; + ME_Run *run = cursor->run; + ME_Row *row = row_from_cursor( cursor ); + ME_Paragraph *para = cursor->para; int x, y, yheight; -#ifdef __REACTOS__ - if (!pRow || !pPara) - return; -#else - assert(pRow); - assert(pPara); -#endif - if (editor->styleFlags & ES_AUTOHSCROLL) + if (editor->scrollbars & ES_AUTOHSCROLL) { - x = pRun->pt.x + ME_PointFromChar(editor, pRun, pCursor->nOffset, TRUE); + x = run->pt.x + ME_PointFromChar( editor, run, cursor->nOffset, TRUE ); if (x > editor->horz_si.nPos + editor->sizeWindow.cx) x = x + 1 - editor->sizeWindow.cx; else if (x > editor->horz_si.nPos) x = editor->horz_si.nPos; - if (~editor->styleFlags & ES_AUTOVSCROLL) + if (~editor->scrollbars & ES_AUTOVSCROLL) { - ME_HScrollAbs(editor, x); + scroll_h_abs( editor, x, TRUE ); return; } - } else { - if (~editor->styleFlags & ES_AUTOVSCROLL) - return; + } + else + { + if (~editor->scrollbars & ES_AUTOVSCROLL) return; x = editor->horz_si.nPos; } - y = pPara->member.para.pt.y + pRow->member.row.pt.y; - yheight = pRow->member.row.nHeight; + y = para->pt.y + row->pt.y; + yheight = row->nHeight; if (y < editor->vert_si.nPos) - ME_ScrollAbs(editor, x, y); + scroll_abs( editor, x, y, TRUE ); else if (y + yheight > editor->vert_si.nPos + editor->sizeWindow.cy) - ME_ScrollAbs(editor, x, y + yheight - editor->sizeWindow.cy); + scroll_abs( editor, x, y + yheight - editor->sizeWindow.cy, TRUE ); else if (x != editor->horz_si.nPos) - ME_ScrollAbs(editor, x, editor->vert_si.nPos); + scroll_abs( editor, x, editor->vert_si.nPos, TRUE ); } void ME_InvalidateSelection(ME_TextEditor *editor) { - ME_DisplayItem *sel_start, *sel_end; - ME_DisplayItem *repaint_start = NULL, *repaint_end = NULL; + ME_Paragraph *sel_start, *sel_end; + ME_Paragraph *repaint_start = NULL, *repaint_end = NULL; int nStart, nEnd; int len = ME_GetTextLength(editor); @@ -1332,41 +1257,47 @@ ME_InvalidateSelection(ME_TextEditor *editor) if (nStart == nEnd && editor->nLastSelStart == editor->nLastSelEnd) return; ME_WrapMarkedParagraphs(editor); - ME_GetSelectionParas(editor, &sel_start, &sel_end); - assert(sel_start->type == diParagraph); - assert(sel_end->type == diParagraph); + editor_get_selection_paras( editor, &sel_start, &sel_end ); + /* last selection markers aren't always updated, which means * they can point past the end of the document */ - if (editor->nLastSelStart > len || editor->nLastSelEnd > len) { - repaint_start = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph); - repaint_end = editor->pBuffer->pLast->member.para.prev_para; - } else { + if (editor->nLastSelStart > len || editor->nLastSelEnd > len) + { + repaint_start = editor_first_para( editor ); + repaint_end = para_prev( editor_end_para( editor ) ); + } + else + { /* if the start part of selection is being expanded or contracted... */ - if (nStart < editor->nLastSelStart) { + if (nStart < editor->nLastSelStart) + { repaint_start = sel_start; - repaint_end = editor->pLastSelStartPara; - } else if (nStart > editor->nLastSelStart) { - repaint_start = editor->pLastSelStartPara; + repaint_end = editor->last_sel_start_para; + } + else if (nStart > editor->nLastSelStart) + { + repaint_start = editor->last_sel_start_para; repaint_end = sel_start; } /* if the end part of selection is being contracted or expanded... */ - if (nEnd < editor->nLastSelEnd) { + if (nEnd < editor->nLastSelEnd) + { if (!repaint_start) repaint_start = sel_end; - repaint_end = editor->pLastSelEndPara; - } else if (nEnd > editor->nLastSelEnd) { - if (!repaint_start) repaint_start = editor->pLastSelEndPara; + repaint_end = editor->last_sel_end_para; + } + else if (nEnd > editor->nLastSelEnd) + { + if (!repaint_start) repaint_start = editor->last_sel_end_para; repaint_end = sel_end; } } if (repaint_start) - ME_InvalidateParagraphRange(editor, repaint_start, repaint_end); + para_range_invalidate( editor, repaint_start, repaint_end ); /* remember the last invalidated position */ ME_GetSelectionOfs(editor, &editor->nLastSelStart, &editor->nLastSelEnd); - ME_GetSelectionParas(editor, &editor->pLastSelStartPara, &editor->pLastSelEndPara); - assert(editor->pLastSelStartPara->type == diParagraph); - assert(editor->pLastSelEndPara->type == diParagraph); + editor_get_selection_paras( editor, &editor->last_sel_start_para, &editor->last_sel_end_para ); } BOOL diff --git a/dll/win32/riched20/para.c b/dll/win32/riched20/para.c index 3b3951b3986..44264e0f2de 100644 --- a/dll/win32/riched20/para.c +++ b/dll/win32/riched20/para.c @@ -23,42 +23,47 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); -void mark_para_rewrap(ME_TextEditor *editor, ME_DisplayItem *para) +void para_mark_rewrap( ME_TextEditor *editor, ME_Paragraph *para ) { - para->member.para.nFlags |= MEPF_REWRAP; - add_marked_para(editor, para); + para->nFlags |= MEPF_REWRAP; + para_mark_add( editor, para ); } -ME_DisplayItem *get_di_from_para(ME_Paragraph *para) -{ - return (ME_DisplayItem *)((ptrdiff_t)para - offsetof(ME_DisplayItem, member)); -} - -static ME_DisplayItem *make_para(ME_TextEditor *editor) +static ME_Paragraph *para_create( ME_TextEditor *editor ) { ME_DisplayItem *item = ME_MakeDI(diParagraph); - ME_SetDefaultParaFormat(editor, &item->member.para.fmt); + editor_set_default_para_fmt( editor, &item->member.para.fmt ); item->member.para.nFlags = MEPF_REWRAP; - item->member.para.next_marked = item->member.para.prev_marked = NULL; - return item; + return &item->member.para; } -void destroy_para(ME_TextEditor *editor, ME_DisplayItem *item) +void para_destroy( ME_TextEditor *editor, ME_Paragraph *para ) { - assert(item->type == diParagraph); - - if (item->member.para.nWidth == editor->nTotalWidth) + if (para->nWidth == editor->nTotalWidth) { - item->member.para.nWidth = 0; + para->nWidth = 0; editor->nTotalWidth = get_total_width(editor); } - editor->total_rows -= item->member.para.nRows; - ME_DestroyString(item->member.para.text); - para_num_clear( &item->member.para.para_num ); - remove_marked_para(editor, item); - ME_DestroyDisplayItem(item); + editor->total_rows -= para->nRows; + ME_DestroyString( para->text ); + para_num_clear( ¶->para_num ); + para_mark_remove( editor, para ); + ME_DestroyDisplayItem( para_get_di( para ) ); +} + +/* Note para_next/prev will return the start and end doc nodes */ +ME_Paragraph *para_next( ME_Paragraph *para ) +{ + if (para->next_para) return ¶->next_para->member.para; + return NULL; +} + +ME_Paragraph *para_prev( ME_Paragraph *para ) +{ + if (para->prev_para && para->prev_para->type == diParagraph) return ¶->prev_para->member.para; + return NULL; } int get_total_width(ME_TextEditor *editor) @@ -79,90 +84,85 @@ int get_total_width(ME_TextEditor *editor) return total_width; } -void remove_marked_para(ME_TextEditor *editor, ME_DisplayItem *di) +static int para_mark_compare( const void *key, const struct wine_rb_entry *entry ) { - ME_DisplayItem *head = editor->first_marked_para; + ME_Paragraph *para = WINE_RB_ENTRY_VALUE( entry, ME_Paragraph, marked_entry ); - assert(di->type == diParagraph); - if (!di->member.para.next_marked && !di->member.para.prev_marked) - { - if (di == head) - editor->first_marked_para = NULL; - } - else if (di->member.para.next_marked && di->member.para.prev_marked) - { - di->member.para.prev_marked->member.para.next_marked = di->member.para.next_marked; - di->member.para.next_marked->member.para.prev_marked = di->member.para.prev_marked; - di->member.para.prev_marked = di->member.para.next_marked = NULL; - } - else if (di->member.para.next_marked) - { - assert(di == editor->first_marked_para); - editor->first_marked_para = di->member.para.next_marked; - di->member.para.next_marked->member.para.prev_marked = NULL; - di->member.para.next_marked = NULL; - } - else - { - di->member.para.prev_marked->member.para.next_marked = NULL; - di->member.para.prev_marked = NULL; - } + return *(int *)key - para->nCharOfs; +} + +void para_mark_remove( ME_TextEditor *editor, ME_Paragraph *para ) +{ + wine_rb_remove_key( &editor->marked_paras, ¶->nCharOfs ); +} + +void para_mark_add( ME_TextEditor *editor, ME_Paragraph *para ) +{ + wine_rb_put( &editor->marked_paras, ¶->nCharOfs, ¶->marked_entry ); } -void add_marked_para(ME_TextEditor *editor, ME_DisplayItem *di) +ME_Run *para_first_run( ME_Paragraph *para ) { - ME_DisplayItem *iter = editor->first_marked_para; + ME_DisplayItem *di; - if (!iter) + for (di = para_get_di( para ); di != para->next_para; di = di->next ) { - editor->first_marked_para = di; - return; - } - while (iter) - { - if (iter == di) - return; - else if (di->member.para.nCharOfs < iter->member.para.nCharOfs) - { - if (iter == editor->first_marked_para) - editor->first_marked_para = di; - di->member.para.next_marked = iter; - iter->member.para.prev_marked = di; - break; - } - else if (di->member.para.nCharOfs >= iter->member.para.nCharOfs) - { - if (!iter->member.para.next_marked || di->member.para.nCharOfs < iter->member.para.next_marked->member.para.nCharOfs) - { - if (iter->member.para.next_marked) - { - di->member.para.next_marked = iter->member.para.next_marked; - iter->member.para.next_marked->member.para.prev_marked = di; - } - di->member.para.prev_marked = iter; - iter->member.para.next_marked = di; - break; - } - } - iter = iter->member.para.next_marked; + if (di->type != diRun) continue; + return &di->member.run; } + ERR( "failed to find run in paragraph\n" ); + return NULL; +} + +ME_Run *para_end_run( ME_Paragraph *para ) +{ + return para->eop_run; +} + +BOOL para_in_table( ME_Paragraph *para ) +{ + return para->fmt.wEffects & PFE_TABLE; +} + +ME_Cell *para_cell( ME_Paragraph *para ) +{ + return para->cell; +} + +ME_Row *para_first_row( ME_Paragraph *para ) +{ + ME_DisplayItem *item; + + item = ME_FindItemFwd( para_get_di( para ), diStartRowOrParagraph ); + if (!item || item->type != diStartRow) return NULL; + return &item->member.row; +} + +ME_Row *para_end_row( ME_Paragraph *para ) +{ + ME_DisplayItem *item; + + para = para_next( para ); + item = ME_FindItemBack( para_get_di( para ), diStartRowOrParagraph ); + if (!item || item->type != diStartRow) return NULL; + return &item->member.row; } void ME_MakeFirstParagraph(ME_TextEditor *editor) { - static const WCHAR cr_lf[] = {'\r','\n',0}; ME_Context c; CHARFORMAT2W cf; const CHARFORMATW *host_cf; LOGFONTW lf; HFONT hf; ME_TextBuffer *text = editor->pBuffer; - ME_DisplayItem *para = make_para(editor); - ME_DisplayItem *run; + ME_Paragraph *para = para_create( editor ); + ME_Run *run; ME_Style *style; int eol_len; + HDC hdc = ITextHost_TxGetDC( editor->texthost ); - ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost)); + ME_InitContext( &c, editor, hdc ); hf = GetStockObject(SYSTEM_FONT); assert(hf); @@ -202,59 +202,57 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor) } eol_len = editor->bEmulateVersion10 ? 2 : 1; - para->member.para.text = ME_MakeStringN( cr_lf, eol_len ); + para->text = ME_MakeStringN( L"\r\n", eol_len ); - run = ME_MakeRun(style, MERF_ENDPARA); - run->member.run.nCharOfs = 0; - run->member.run.len = eol_len; - run->member.run.para = ¶->member.para; + run = run_create( style, MERF_ENDPARA ); + run->nCharOfs = 0; + run->len = eol_len; + run->para = para; + para->eop_run = run; - para->member.para.eop_run = &run->member.run; - - ME_InsertBefore(text->pLast, para); - ME_InsertBefore(text->pLast, run); - para->member.para.prev_para = text->pFirst; - para->member.para.next_para = text->pLast; - text->pFirst->member.para.next_para = para; - text->pLast->member.para.prev_para = para; + ME_InsertBefore( text->pLast, para_get_di( para) ); + ME_InsertBefore( text->pLast, run_get_di( run ) ); + para->prev_para = text->pFirst; + para->next_para = text->pLast; + text->pFirst->member.para.next_para = para_get_di( para ); + text->pLast->member.para.prev_para = para_get_di( para ); text->pLast->member.para.nCharOfs = editor->bEmulateVersion10 ? 2 : 1; - add_marked_para(editor, para); + wine_rb_init( &editor->marked_paras, para_mark_compare ); + para_mark_add( editor, para ); ME_DestroyContext(&c); + ITextHost_TxReleaseDC( editor->texthost, hdc ); } -static void ME_MarkForWrapping(ME_TextEditor *editor, ME_DisplayItem *first, const ME_DisplayItem *last) +static void para_mark_rewrap_paras( ME_TextEditor *editor, ME_Paragraph *first, const ME_Paragraph *end ) { - while(first != last) - { - mark_para_rewrap(editor, first); - first = first->member.para.next_para; - } + while (first != end) + { + para_mark_rewrap( editor, first ); + first = para_next( first ); + } } -void ME_MarkAllForWrapping(ME_TextEditor *editor) +void editor_mark_rewrap_all( ME_TextEditor *editor ) { - ME_MarkForWrapping(editor, editor->pBuffer->pFirst->member.para.next_para, editor->pBuffer->pLast); + para_mark_rewrap_paras( editor, editor_first_para( editor ), editor_end_para( editor ) ); } -static void ME_UpdateTableFlags(ME_DisplayItem *para) +static void table_update_flags( ME_Paragraph *para ) { - para->member.para.fmt.dwMask |= PFM_TABLE|PFM_TABLEROWDELIMITER; - if (para->member.para.pCell) { - para->member.para.nFlags |= MEPF_CELL; - } else { - para->member.para.nFlags &= ~MEPF_CELL; - } - if (para->member.para.nFlags & MEPF_ROWEND) { - para->member.para.fmt.wEffects |= PFE_TABLEROWDELIMITER; - } else { - para->member.para.fmt.wEffects &= ~PFE_TABLEROWDELIMITER; - } - if (para->member.para.nFlags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND)) - para->member.para.fmt.wEffects |= PFE_TABLE; - else - para->member.para.fmt.wEffects &= ~PFE_TABLE; + para->fmt.dwMask |= PFM_TABLE | PFM_TABLEROWDELIMITER; + + if (para_cell( para )) para->nFlags |= MEPF_CELL; + else para->nFlags &= ~MEPF_CELL; + + if (para->nFlags & MEPF_ROWEND) para->fmt.wEffects |= PFE_TABLEROWDELIMITER; + else para->fmt.wEffects &= ~PFE_TABLEROWDELIMITER; + + if (para->nFlags & (MEPF_ROWSTART | MEPF_CELL | MEPF_ROWEND)) + para->fmt.wEffects |= PFE_TABLE; + else + para->fmt.wEffects &= ~PFE_TABLE; } static inline BOOL para_num_same_list( const PARAFORMAT2 *item, const PARAFORMAT2 *base ) @@ -283,7 +281,6 @@ static ME_String *para_num_get_str( ME_Paragraph *para, WORD num ) /* max 4 Roman letters (representing '8') / decade + '(' + ')' */ ME_String *str = ME_MakeStringEmpty( 20 + 2 ); WCHAR *p; - static const WCHAR fmtW[] = {'%', 'd', 0}; static const WORD letter_base[] = { 1, 26, 26 * 26, 26 * 26 * 26 }; /* roman_base should start on a '5' not a '1', otherwise the 'total' code will need adjusting. 'N' and 'O' are what MS uses for 5000 and 10000, their version doesn't work well above 30000, @@ -312,7 +309,11 @@ static ME_String *para_num_get_str( ME_Paragraph *para, WORD num ) { case PFN_ARABIC: default: - p += swprintf( p, fmtW, num ); +#ifdef __REACTOS__ + p += swprintf( p, L"%d", num ); +#else + p += swprintf( p, 20, L"%d", num ); +#endif break; case PFN_LCLETTER: @@ -396,9 +397,6 @@ void para_num_init( ME_Context *c, ME_Paragraph *para ) { ME_Style *style; CHARFORMAT2W cf; - static const WCHAR bullet_font[] = {'S','y','m','b','o','l',0}; - static const WCHAR bullet_str[] = {0xb7, 0}; - static const WCHAR spaceW[] = {' ', 0}; SIZE sz; if (!para->fmt.wNumbering) return; @@ -412,7 +410,7 @@ void para_num_init( ME_Context *c, ME_Paragraph *para ) { cf.cbSize = sizeof(cf); cf.dwMask = CFM_FACE | CFM_CHARSET; - memcpy( cf.szFaceName, bullet_font, sizeof(bullet_font) ); + lstrcpyW( cf.szFaceName, L"Symbol" ); cf.bCharSet = SYMBOL_CHARSET; style = ME_ApplyStyle( c->editor, style, &cf ); } @@ -429,13 +427,13 @@ void para_num_init( ME_Context *c, ME_Paragraph *para ) if (para->fmt.wNumbering != PFN_BULLET) para->para_num.text = para_num_get_str( para, para_num_get_num( para ) ); else - para->para_num.text = ME_MakeStringConst( bullet_str, 1 ); + para->para_num.text = ME_MakeStringConst( L"\x00b7", 1 ); } select_style( c, para->para_num.style ); GetTextExtentPointW( c->hDC, para->para_num.text->szData, para->para_num.text->nLen, &sz ); para->para_num.width = sz.cx; - GetTextExtentPointW( c->hDC, spaceW, 1, &sz ); + GetTextExtentPointW( c->hDC, L" ", 1, &sz ); para->para_num.width += sz.cx; } @@ -454,14 +452,14 @@ static void para_num_clear_list( ME_TextEditor *editor, ME_Paragraph *para, cons { do { - mark_para_rewrap(editor, get_di_from_para(para)); + para_mark_rewrap( editor, para ); para_num_clear( ¶->para_num ); if (para->next_para->type != diParagraph) break; para = ¶->next_para->member.para; } while (para_num_same_list( ¶->fmt, orig_fmt )); } -static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PARAFORMAT2 *pFmt) +static BOOL para_set_fmt( ME_TextEditor *editor, ME_Paragraph *para, const PARAFORMAT2 *pFmt ) { PARAFORMAT2 copy; DWORD dwMask; @@ -494,8 +492,8 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PA COPY_FIELD(PFM_ALIGNMENT, wAlignment); if (dwMask & PFM_TABSTOPS) { - para->fmt.cTabCount = max(0, min(pFmt->cTabCount, MAX_TAB_STOPS)); /* Clamp between 0 and MAX_TAB_STOPS */ - memcpy(para->fmt.rgxTabs, pFmt->rgxTabs, para->fmt.cTabCount*sizeof(LONG)); + para->fmt.cTabCount = pFmt->cTabCount; + memcpy(para->fmt.rgxTabs, pFmt->rgxTabs, pFmt->cTabCount*sizeof(LONG)); } #define EFFECTS_MASK (PFM_RTLPARA|PFM_KEEP|PFM_KEEPNEXT|PFM_PAGEBREAKBEFORE| \ @@ -529,7 +527,7 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PA if (memcmp(©, ¶->fmt, sizeof(PARAFORMAT2))) { - mark_para_rewrap(editor, get_di_from_para(para)); + para_mark_rewrap( editor, para ); if (((dwMask & PFM_NUMBERING) && (copy.wNumbering != para->fmt.wNumbering)) || ((dwMask & PFM_NUMBERINGSTART) && (copy.wNumberingStart != para->fmt.wNumberingStart)) || ((dwMask & PFM_NUMBERINGSTYLE) && (copy.wNumberingStyle != para->fmt.wNumberingStyle))) @@ -542,278 +540,251 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PA } /* split paragraph at the beginning of the run */ -ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, - ME_Style *style, const WCHAR *eol_str, int eol_len, - int paraFlags) -{ - ME_DisplayItem *next_para = NULL; - ME_DisplayItem *run_para = NULL; - ME_DisplayItem *new_para = make_para(editor); - ME_DisplayItem *end_run; +ME_Paragraph *para_split( ME_TextEditor *editor, ME_Run *run, ME_Style *style, + const WCHAR *eol_str, int eol_len, int paraFlags ) +{ + ME_Paragraph *new_para = para_create( editor ), *old_para, *next_para; + ME_Run *end_run, *next_run; int ofs, i; - ME_DisplayItem *pp; int run_flags = MERF_ENDPARA; - if (!editor->bEmulateVersion10) { /* v4.1 */ + if (!editor->bEmulateVersion10) /* v4.1 */ + { /* At most 1 of MEPF_CELL, MEPF_ROWSTART, or MEPF_ROWEND should be set. */ - assert(!(paraFlags & ~(MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND))); - assert(!(paraFlags & (paraFlags-1))); + assert( !(paraFlags & ~(MEPF_CELL | MEPF_ROWSTART | MEPF_ROWEND)) ); + assert( !(paraFlags & (paraFlags-1)) ); if (paraFlags == MEPF_CELL) - run_flags |= MERF_ENDCELL; + run_flags |= MERF_ENDCELL; else if (paraFlags == MEPF_ROWSTART) - run_flags |= MERF_TABLESTART|MERF_HIDDEN; - } else { /* v1.0 - v3.0 */ - assert(!(paraFlags & (MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND))); + run_flags |= MERF_TABLESTART | MERF_HIDDEN; } - assert(run->type == diRun); - run_para = ME_GetParagraph(run); - assert(run_para->member.para.fmt.cbSize == sizeof(PARAFORMAT2)); + else /* v1.0 - v3.0 */ + assert( !(paraFlags & (MEPF_CELL |MEPF_ROWSTART | MEPF_ROWEND)) ); + + old_para = run->para; + assert( old_para->fmt.cbSize == sizeof(PARAFORMAT2) ); /* Clear any cached para numbering following this paragraph */ - if (run_para->member.para.fmt.wNumbering) - para_num_clear_list( editor, &run_para->member.para, &run_para->member.para.fmt ); + if (old_para->fmt.wNumbering) + para_num_clear_list( editor, old_para, &old_para->fmt ); - new_para->member.para.text = ME_VSplitString( run_para->member.para.text, run->member.run.nCharOfs ); + new_para->text = ME_VSplitString( old_para->text, run->nCharOfs ); - end_run = ME_MakeRun(style, run_flags); - ofs = end_run->member.run.nCharOfs = run->member.run.nCharOfs; - end_run->member.run.len = eol_len; - end_run->member.run.para = run->member.run.para; - ME_AppendString( run_para->member.para.text, eol_str, eol_len ); - next_para = run_para->member.para.next_para; - assert(next_para == ME_FindItemFwd(run_para, diParagraphOrEnd)); + end_run = run_create( style, run_flags ); + ofs = end_run->nCharOfs = run->nCharOfs; + end_run->len = eol_len; + end_run->para = run->para; + ME_AppendString( old_para->text, eol_str, eol_len ); + next_para = &old_para->next_para->member.para; - add_undo_join_paras( editor, run_para->member.para.nCharOfs + ofs ); + add_undo_join_paras( editor, old_para->nCharOfs + ofs ); /* Update selection cursors to point to the correct paragraph. */ - for (i = 0; i < editor->nCursors; i++) { - if (editor->pCursors[i].pPara == run_para && - run->member.run.nCharOfs <= editor->pCursors[i].pRun->member.run.nCharOfs) + for (i = 0; i < editor->nCursors; i++) + { + if (editor->pCursors[i].para == old_para && + run->nCharOfs <= editor->pCursors[i].run->nCharOfs) { - editor->pCursors[i].pPara = new_para; + editor->pCursors[i].para = new_para; } } - /* the new paragraph will have a different starting offset, so let's update its runs */ - pp = run; - while(pp->type == diRun) { - pp->member.run.nCharOfs -= ofs; - pp->member.run.para = &new_para->member.para; - pp = ME_FindItemFwd(pp, diRunOrParagraphOrEnd); + /* the new paragraph will have a different starting offset, so update its runs */ + for (next_run = run; next_run; next_run = run_next( next_run )) + { + next_run->nCharOfs -= ofs; + next_run->para = new_para; } - new_para->member.para.nCharOfs = run_para->member.para.nCharOfs + ofs; - new_para->member.para.nCharOfs += eol_len; - new_para->member.para.nFlags = 0; - mark_para_rewrap(editor, new_para); + + new_para->nCharOfs = old_para->nCharOfs + ofs; + new_para->nCharOfs += eol_len; + new_para->nFlags = 0; + para_mark_rewrap( editor, new_para ); /* FIXME initialize format style and call ME_SetParaFormat blah blah */ - new_para->member.para.fmt = run_para->member.para.fmt; - new_para->member.para.border = run_para->member.para.border; + new_para->fmt = old_para->fmt; + new_para->border = old_para->border; /* insert paragraph into paragraph double linked list */ - new_para->member.para.prev_para = run_para; - new_para->member.para.next_para = next_para; - run_para->member.para.next_para = new_para; - next_para->member.para.prev_para = new_para; + new_para->prev_para = para_get_di( old_para ); + new_para->next_para = para_get_di( next_para ); + old_para->next_para = para_get_di( new_para ); + next_para->prev_para = para_get_di( new_para ); /* insert end run of the old paragraph, and new paragraph, into DI double linked list */ - ME_InsertBefore(run, new_para); - ME_InsertBefore(new_para, end_run); + ME_InsertBefore( run_get_di( run ), para_get_di( new_para ) ); + ME_InsertBefore( para_get_di( new_para ), run_get_di( end_run ) ); /* Fix up the paras' eop_run ptrs */ - new_para->member.para.eop_run = run_para->member.para.eop_run; - run_para->member.para.eop_run = &end_run->member.run; + new_para->eop_run = old_para->eop_run; + old_para->eop_run = end_run; - if (!editor->bEmulateVersion10) { /* v4.1 */ - if (paraFlags & (MEPF_ROWSTART|MEPF_CELL)) + if (!editor->bEmulateVersion10) /* v4.1 */ + { + if (paraFlags & (MEPF_ROWSTART | MEPF_CELL)) { - ME_DisplayItem *cell = ME_MakeDI(diCell); - ME_InsertBefore(new_para, cell); - new_para->member.para.pCell = cell; - cell->member.cell.next_cell = NULL; + ME_Cell *cell = cell_create(); + ME_InsertBefore( para_get_di( new_para ), cell_get_di( cell ) ); + new_para->cell = cell; + cell->next_cell = NULL; if (paraFlags & MEPF_ROWSTART) { - run_para->member.para.nFlags |= MEPF_ROWSTART; - cell->member.cell.prev_cell = NULL; - cell->member.cell.parent_cell = run_para->member.para.pCell; - if (run_para->member.para.pCell) - cell->member.cell.nNestingLevel = run_para->member.para.pCell->member.cell.nNestingLevel + 1; + old_para->nFlags |= MEPF_ROWSTART; + cell->prev_cell = NULL; + cell->parent_cell = old_para->cell; + if (para_cell( old_para )) + cell->nNestingLevel = para_cell( old_para )->nNestingLevel + 1; else - cell->member.cell.nNestingLevel = 1; - } else { - cell->member.cell.prev_cell = run_para->member.para.pCell; - assert(cell->member.cell.prev_cell); - cell->member.cell.prev_cell->member.cell.next_cell = cell; - assert(run_para->member.para.nFlags & MEPF_CELL); - assert(!(run_para->member.para.nFlags & MEPF_ROWSTART)); - cell->member.cell.nNestingLevel = cell->member.cell.prev_cell->member.cell.nNestingLevel; - cell->member.cell.parent_cell = cell->member.cell.prev_cell->member.cell.parent_cell; + cell->nNestingLevel = 1; } - } else if (paraFlags & MEPF_ROWEND) { - run_para->member.para.nFlags |= MEPF_ROWEND; - run_para->member.para.pCell = run_para->member.para.pCell->member.cell.parent_cell; - new_para->member.para.pCell = run_para->member.para.pCell; - assert(run_para->member.para.prev_para->member.para.nFlags & MEPF_CELL); - assert(!(run_para->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART)); - if (new_para->member.para.pCell != new_para->member.para.next_para->member.para.pCell - && new_para->member.para.next_para->member.para.pCell - && !new_para->member.para.next_para->member.para.pCell->member.cell.prev_cell) + else + { + cell->prev_cell = old_para->cell; + cell_prev( cell )->next_cell = cell; + assert( old_para->nFlags & MEPF_CELL ); + assert( !(old_para->nFlags & MEPF_ROWSTART) ); + cell->nNestingLevel = cell_prev( cell )->nNestingLevel; + cell->parent_cell = cell_prev( cell )->parent_cell; + } + } + else if (paraFlags & MEPF_ROWEND) + { + old_para->nFlags |= MEPF_ROWEND; + old_para->cell = old_para->cell->parent_cell; + new_para->cell = old_para->cell; + assert( para_prev( old_para )->nFlags & MEPF_CELL ); + assert( !(para_prev( old_para )->nFlags & MEPF_ROWSTART) ); + if (new_para->cell != para_next( new_para )->cell + && para_next( new_para )->cell + && !cell_prev( para_next( new_para )->cell )) { /* Row starts just after the row that was ended. */ - new_para->member.para.nFlags |= MEPF_ROWSTART; + new_para->nFlags |= MEPF_ROWSTART; } - } else { - new_para->member.para.pCell = run_para->member.para.pCell; } - ME_UpdateTableFlags(run_para); - ME_UpdateTableFlags(new_para); + else new_para->cell = old_para->cell; + + table_update_flags( old_para ); + table_update_flags( new_para ); } /* force rewrap of the */ - if (run_para->member.para.prev_para->type == diParagraph) - mark_para_rewrap(editor, run_para->member.para.prev_para); + if (old_para->prev_para->type == diParagraph) + para_mark_rewrap( editor, &old_para->prev_para->member.para ); - mark_para_rewrap(editor, new_para->member.para.prev_para); + 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 */ - ME_PropagateCharOffset(next_para, eol_len); + editor_propagate_char_ofs( next_para, NULL, eol_len ); editor->nParagraphs++; return new_para; } -/* join tp with tp->member.para.next_para, keeping tp's style; this - * is consistent with the original */ -ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, - BOOL keepFirstParaFormat) +/* join para with the next para keeping para's style using the paragraph fmt + specified in use_first_fmt */ +ME_Paragraph *para_join( ME_TextEditor *editor, ME_Paragraph *para, BOOL use_first_fmt ) { - ME_DisplayItem *pNext, *pFirstRunInNext, *pRun, *pTmp, *pCell = NULL; - int i, shift; - int end_len; + ME_Paragraph *next = para_next( para ); + ME_Run *end_run, *next_first_run, *tmp_run; + ME_Cell *cell = NULL; + int i, end_len; CHARFORMAT2W fmt; ME_Cursor startCur, endCur; ME_String *eol_str; - assert(tp->type == diParagraph); - assert(tp->member.para.next_para); - assert(tp->member.para.next_para->type == diParagraph); + assert( next && para_next( next ) ); /* Clear any cached para numbering following this paragraph */ - if (tp->member.para.fmt.wNumbering) - para_num_clear_list( editor, &tp->member.para, &tp->member.para.fmt ); + if (para->fmt.wNumbering) para_num_clear_list( editor, para, ¶->fmt ); - pNext = tp->member.para.next_para; + end_run = para_end_run( para ); + next_first_run = para_first_run( next ); - /* Need to locate end-of-paragraph run here, in order to know end_len */ - pRun = ME_FindItemBack(pNext, diRunOrParagraph); - - assert(pRun); - assert(pRun->type == diRun); - assert(pRun->member.run.nFlags & MERF_ENDPARA); - - end_len = pRun->member.run.len; - eol_str = ME_VSplitString( tp->member.para.text, pRun->member.run.nCharOfs ); - ME_AppendString( tp->member.para.text, pNext->member.para.text->szData, pNext->member.para.text->nLen ); + end_len = end_run->len; + eol_str = ME_VSplitString( para->text, end_run->nCharOfs ); + ME_AppendString( para->text, next->text->szData, next->text->nLen ); /* null char format operation to store the original char format for the ENDPARA run */ ME_InitCharFormat2W(&fmt); - endCur.pPara = pNext; - endCur.pRun = ME_FindItemFwd(pNext, diRun); - endCur.nOffset = 0; - startCur = endCur; - ME_PrevRun(&startCur.pPara, &startCur.pRun, TRUE); - ME_SetCharFormat(editor, &startCur, &endCur, &fmt); + startCur.para = para; + startCur.run = end_run; + endCur.para = next; + endCur.run = next_first_run; + startCur.nOffset = endCur.nOffset = 0; - if (!editor->bEmulateVersion10) { /* v4.1 */ - /* Table cell/row properties are always moved over from the removed para. */ - tp->member.para.nFlags = pNext->member.para.nFlags; - tp->member.para.pCell = pNext->member.para.pCell; + ME_SetCharFormat(editor, &startCur, &endCur, &fmt); + if (!editor->bEmulateVersion10) /* v4.1 */ + { /* Remove cell boundary if it is between the end paragraph run and the next * paragraph display item. */ - for (pTmp = pRun->next; pTmp != pNext; pTmp = pTmp->next) - { - if (pTmp->type == diCell) - { - pCell = pTmp; - break; - } - } + if (para->cell != next->cell) cell = next->cell; + + /* Table cell/row properties are always moved over from the removed para. */ + para->nFlags = next->nFlags; + para->cell = next->cell; } - add_undo_split_para( editor, &pNext->member.para, eol_str, pCell ? &pCell->member.cell : NULL ); + add_undo_split_para( editor, next, eol_str, cell ); - if (pCell) + if (cell) { - ME_Remove( pCell ); - if (pCell->member.cell.prev_cell) - pCell->member.cell.prev_cell->member.cell.next_cell = pCell->member.cell.next_cell; - if (pCell->member.cell.next_cell) - pCell->member.cell.next_cell->member.cell.prev_cell = pCell->member.cell.prev_cell; - ME_DestroyDisplayItem( pCell ); + ME_Remove( cell_get_di( cell ) ); + if (cell_prev( cell )) cell_prev( cell )->next_cell = cell_next( cell ); + if (cell_next( cell )) cell_next( cell )->prev_cell = cell_prev( cell ); + ME_DestroyDisplayItem( cell_get_di( cell ) ); } - if (!keepFirstParaFormat) + if (!use_first_fmt) { - add_undo_set_para_fmt( editor, &tp->member.para ); - tp->member.para.fmt = pNext->member.para.fmt; - tp->member.para.border = pNext->member.para.border; + add_undo_set_para_fmt( editor, para ); + para->fmt = next->fmt; + para->border = next->border; } - shift = pNext->member.para.nCharOfs - tp->member.para.nCharOfs - end_len; - - pFirstRunInNext = ME_FindItemFwd(pNext, diRunOrParagraph); - - assert(pFirstRunInNext->type == diRun); - /* Update selection cursors so they don't point to the removed end * paragraph run, and point to the correct paragraph. */ - for (i=0; i < editor->nCursors; i++) { - if (editor->pCursors[i].pRun == pRun) { - editor->pCursors[i].pRun = pFirstRunInNext; + for (i = 0; i < editor->nCursors; i++) + { + if (editor->pCursors[i].run == end_run) + { + editor->pCursors[i].run = next_first_run; editor->pCursors[i].nOffset = 0; - } else if (editor->pCursors[i].pPara == pNext) { - editor->pCursors[i].pPara = tp; } + else if (editor->pCursors[i].para == next) + editor->pCursors[i].para = para; } - pTmp = pNext; - do { - pTmp = ME_FindItemFwd(pTmp, diRunOrParagraphOrEnd); - if (pTmp->type != diRun) - break; - TRACE("shifting %s by %d (previous %d)\n", debugstr_run( &pTmp->member.run ), shift, pTmp->member.run.nCharOfs); - pTmp->member.run.nCharOfs += shift; - pTmp->member.run.para = &tp->member.para; - } while(1); + for (tmp_run = next_first_run; tmp_run; tmp_run = run_next( tmp_run )) + { + tmp_run->nCharOfs += next->nCharOfs - para->nCharOfs - end_len; + tmp_run->para = para; + } /* Fix up the para's eop_run ptr */ - tp->member.para.eop_run = pNext->member.para.eop_run; + para->eop_run = next->eop_run; - ME_Remove(pRun); - ME_DestroyDisplayItem(pRun); + ME_Remove( run_get_di( end_run ) ); + ME_DestroyDisplayItem( run_get_di( end_run) ); - if (editor->pLastSelStartPara == pNext) - editor->pLastSelStartPara = tp; - if (editor->pLastSelEndPara == pNext) - editor->pLastSelEndPara = tp; + if (editor->last_sel_start_para == next) + editor->last_sel_start_para = para; + if (editor->last_sel_end_para == next) + editor->last_sel_end_para = para; - tp->member.para.next_para = pNext->member.para.next_para; - pNext->member.para.next_para->member.para.prev_para = tp; - ME_Remove(pNext); - destroy_para(editor, pNext); + para->next_para = next->next_para; + next->next_para->member.para.prev_para = para_get_di( para ); + ME_Remove( para_get_di(next) ); + para_destroy( editor, next ); - ME_PropagateCharOffset(tp->member.para.next_para, -end_len); + editor_propagate_char_ofs( para_next( para ), NULL, -end_len ); ME_CheckCharOffsets(editor); editor->nParagraphs--; - mark_para_rewrap(editor, tp); - return tp; -} - -ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *item) { - return ME_FindItemBackOrHere(item, diParagraph); + para_mark_rewrap( editor, para ); + return para; } void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]) @@ -879,18 +850,18 @@ void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]) #undef DUMP_EFFECT } -void -ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end) +void editor_get_selection_paras( ME_TextEditor *editor, ME_Paragraph **para, ME_Paragraph **para_end ) { ME_Cursor *pEndCursor = &editor->pCursors[1]; - *para = editor->pCursors[0].pPara; - *para_end = editor->pCursors[1].pPara; + *para = editor->pCursors[0].para; + *para_end = editor->pCursors[1].para; if (*para == *para_end) return; - if ((*para_end)->member.para.nCharOfs < (*para)->member.para.nCharOfs) { - ME_DisplayItem *tmp = *para; + if ((*para_end)->nCharOfs < (*para)->nCharOfs) + { + ME_Paragraph *tmp = *para; *para = *para_end; *para_end = tmp; @@ -899,78 +870,78 @@ ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayIte /* The paragraph at the end of a non-empty selection isn't included * if the selection ends at the start of the paragraph. */ - if (!pEndCursor->pRun->member.run.nCharOfs && !pEndCursor->nOffset) - *para_end = (*para_end)->member.para.prev_para; + if (!pEndCursor->run->nCharOfs && !pEndCursor->nOffset) + *para_end = para_prev( *para_end ); } -BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) +BOOL editor_set_selection_para_fmt( ME_TextEditor *editor, const PARAFORMAT2 *fmt ) { - ME_DisplayItem *para, *para_end; + ME_Paragraph *para, *para_end; - ME_GetSelectionParas(editor, ¶, ¶_end); + editor_get_selection_paras( editor, ¶, ¶_end ); - do { - ME_SetParaFormat(editor, ¶->member.para, pFmt); - if (para == para_end) - break; - para = para->member.para.next_para; - } while(1); + do + { + para_set_fmt( editor, para, fmt ); + if (para == para_end) break; + para = para_next( para ); + } while(1); - return TRUE; + return TRUE; } -static void ME_GetParaFormat(ME_TextEditor *editor, - const ME_DisplayItem *para, - PARAFORMAT2 *pFmt) +static void para_copy_fmt( const ME_Paragraph *para, PARAFORMAT2 *fmt ) { - UINT cbSize = pFmt->cbSize; - if (pFmt->cbSize >= sizeof(PARAFORMAT2)) { - *pFmt = para->member.para.fmt; - } else { - CopyMemory(pFmt, ¶->member.para.fmt, pFmt->cbSize); - pFmt->dwMask &= PFM_ALL; - } - pFmt->cbSize = cbSize; + UINT size = fmt->cbSize; + + if (fmt->cbSize >= sizeof(PARAFORMAT2)) + *fmt = para->fmt; + else + { + memcpy( fmt, ¶->fmt, fmt->cbSize ); + fmt->dwMask &= PFM_ALL; + } + fmt->cbSize = size; } -void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) +void editor_get_selection_para_fmt( ME_TextEditor *editor, PARAFORMAT2 *fmt ) { - ME_DisplayItem *para, *para_end; - PARAFORMAT2 *curFmt; + ME_Paragraph *para, *para_end; - if (pFmt->cbSize < sizeof(PARAFORMAT)) { - pFmt->dwMask = 0; + if (fmt->cbSize < sizeof(PARAFORMAT)) + { + fmt->dwMask = 0; return; } - ME_GetSelectionParas(editor, ¶, ¶_end); + editor_get_selection_paras( editor, ¶, ¶_end ); - ME_GetParaFormat(editor, para, pFmt); + para_copy_fmt( para, fmt ); /* Invalidate values that change across the selected paragraphs. */ while (para != para_end) { - para = para->member.para.next_para; - curFmt = ¶->member.para.fmt; + para = para_next( para ); #define CHECK_FIELD(m, f) \ - if (pFmt->f != curFmt->f) pFmt->dwMask &= ~(m); + if (fmt->f != para->fmt.f) fmt->dwMask &= ~(m); CHECK_FIELD(PFM_NUMBERING, wNumbering); CHECK_FIELD(PFM_STARTINDENT, dxStartIndent); CHECK_FIELD(PFM_RIGHTINDENT, dxRightIndent); CHECK_FIELD(PFM_OFFSET, dxOffset); CHECK_FIELD(PFM_ALIGNMENT, wAlignment); - if (pFmt->dwMask & PFM_TABSTOPS) { - if (pFmt->cTabCount != para->member.para.fmt.cTabCount || - memcmp(pFmt->rgxTabs, curFmt->rgxTabs, curFmt->cTabCount*sizeof(int))) - pFmt->dwMask &= ~PFM_TABSTOPS; + if (fmt->dwMask & PFM_TABSTOPS) + { + if (fmt->cTabCount != para->fmt.cTabCount || + memcmp(fmt->rgxTabs, para->fmt.rgxTabs, para->fmt.cTabCount * sizeof(int) )) + fmt->dwMask &= ~PFM_TABSTOPS; } - if (pFmt->dwMask >= sizeof(PARAFORMAT2)) + if (fmt->cbSize >= sizeof(PARAFORMAT2)) { - pFmt->dwMask &= ~((pFmt->wEffects ^ curFmt->wEffects) << 16); + fmt->dwMask &= ~((fmt->wEffects ^ para->fmt.wEffects) << 16); CHECK_FIELD(PFM_SPACEBEFORE, dySpaceBefore); CHECK_FIELD(PFM_SPACEAFTER, dySpaceAfter); CHECK_FIELD(PFM_LINESPACING, dyLineSpacing); @@ -989,7 +960,7 @@ void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) } } -void ME_SetDefaultParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) +void editor_set_default_para_fmt( ME_TextEditor *editor, PARAFORMAT2 *pFmt ) { const PARAFORMAT2 *host_fmt; HRESULT hr; diff --git a/dll/win32/riched20/reader.c b/dll/win32/riched20/reader.c index dc551bf5841..e73b8b87e9d 100644 --- a/dll/win32/riched20/reader.c +++ b/dll/win32/riched20/reader.c @@ -2519,7 +2519,7 @@ static void SpecialChar (RTF_Info *info) case rtfSect: case rtfPar: RTFFlushOutputBuffer(info); - ME_SetSelectionParaFormat(info->editor, &info->fmt); + editor_set_selection_para_fmt( info->editor, &info->fmt ); memset(&info->fmt, 0, sizeof(info->fmt)); info->fmt.cbSize = sizeof(info->fmt); RTFPutUnicodeChar (info, '\r'); diff --git a/dll/win32/riched20/richole.c b/dll/win32/riched20/richole.c index 3bfc4663a28..72840a4cafa 100644 --- a/dll/win32/riched20/richole.c +++ b/dll/win32/riched20/richole.c @@ -136,7 +136,6 @@ static HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo) /* private IID used to get back IRichEditOleImpl pointer */ DEFINE_GUID(IID_Igetrichole, 0xe3ce5c7a, 0x8247, 0x4622, 0x81, 0xad, 0x11, 0x81, 0x02, 0xaa, 0x01, 0x30); -typedef struct ITextSelectionImpl ITextSelectionImpl; typedef struct IOleClientSiteImpl IOleClientSiteImpl; typedef struct ITextRangeImpl ITextRangeImpl; @@ -206,23 +205,9 @@ enum range_update_op { RANGE_UPDATE_DELETE }; -typedef struct IRichEditOleImpl { - IUnknown IUnknown_inner; - IRichEditOle IRichEditOle_iface; - ITextDocument2Old ITextDocument2Old_iface; - IUnknown *outer_unk; - LONG ref; - - ME_TextEditor *editor; - ITextSelectionImpl *txtSel; - - struct list rangelist; - struct list clientsites; -} IRichEditOleImpl; - struct reole_child { struct list entry; - IRichEditOleImpl *reole; + struct text_services *reole; }; struct ITextRangeImpl { @@ -232,13 +217,6 @@ struct ITextRangeImpl { LONG start, end; }; -struct ITextSelectionImpl { - ITextSelection ITextSelection_iface; - LONG ref; - - IRichEditOleImpl *reOle; -}; - typedef struct ITextFontImpl { ITextFont ITextFont_iface; LONG ref; @@ -263,19 +241,14 @@ struct IOleClientSiteImpl { LONG ref; }; -static inline IRichEditOleImpl *impl_from_IRichEditOle(IRichEditOle *iface) +static inline struct text_services *impl_from_IRichEditOle( IRichEditOle *iface ) { - return CONTAINING_RECORD(iface, IRichEditOleImpl, IRichEditOle_iface); + return CONTAINING_RECORD( iface, struct text_services, IRichEditOle_iface ); } -static inline IRichEditOleImpl *impl_from_ITextDocument2Old(ITextDocument2Old *iface) +static inline struct text_services *impl_from_ITextDocument2Old( ITextDocument2Old *iface ) { - return CONTAINING_RECORD(iface, IRichEditOleImpl, ITextDocument2Old_iface); -} - -static inline IRichEditOleImpl *impl_from_IUnknown(IUnknown *iface) -{ - return CONTAINING_RECORD(iface, IRichEditOleImpl, IUnknown_inner); + return CONTAINING_RECORD( iface, struct text_services, ITextDocument2Old_iface ); } static inline IOleClientSiteImpl *impl_from_IOleInPlaceSite(IOleInPlaceSite *iface) @@ -288,9 +261,9 @@ static inline ITextRangeImpl *impl_from_ITextRange(ITextRange *iface) return CONTAINING_RECORD(iface, ITextRangeImpl, ITextRange_iface); } -static inline ITextSelectionImpl *impl_from_ITextSelection(ITextSelection *iface) +static inline struct text_selection *impl_from_ITextSelection(ITextSelection *iface) { - return CONTAINING_RECORD(iface, ITextSelectionImpl, ITextSelection_iface); + return CONTAINING_RECORD(iface, struct text_selection, ITextSelection_iface); } static inline ITextFontImpl *impl_from_ITextFont(ITextFont *iface) @@ -305,7 +278,7 @@ static inline ITextParaImpl *impl_from_ITextPara(ITextPara *iface) static HRESULT create_textfont(ITextRange*, const ITextFontImpl*, ITextFont**); static HRESULT create_textpara(ITextRange*, ITextPara**); -static ITextSelectionImpl *CreateTextSelection(IRichEditOleImpl*); +static struct text_selection *text_selection_create( struct text_services * ); static HRESULT textrange_get_storylength(ME_TextEditor *editor, LONG *length) { @@ -316,11 +289,11 @@ static HRESULT textrange_get_storylength(ME_TextEditor *editor, LONG *length) return S_OK; } -static void textranges_update_ranges(IRichEditOleImpl *reole, LONG start, LONG end, enum range_update_op op) +static void textranges_update_ranges(struct text_services *services, LONG start, LONG end, enum range_update_op op) { ITextRangeImpl *range; - LIST_FOR_EACH_ENTRY(range, &reole->rangelist, ITextRangeImpl, child.entry) { + LIST_FOR_EACH_ENTRY(range, &services->rangelist, ITextRangeImpl, child.entry) { switch (op) { case RANGE_UPDATE_DELETE: @@ -434,7 +407,7 @@ static inline FLOAT points_to_twips(FLOAT value) return value * 1440 / 72.0; } -static HRESULT get_textfont_prop_for_pos(const IRichEditOleImpl *reole, int pos, enum textfont_prop_id propid, +static HRESULT get_textfont_prop_for_pos(const struct text_services *services, int pos, enum textfont_prop_id propid, textfont_prop_val *value) { ME_Cursor from, to; @@ -444,10 +417,10 @@ static HRESULT get_textfont_prop_for_pos(const IRichEditOleImpl *reole, int pos, fmt.cbSize = sizeof(fmt); fmt.dwMask = textfont_prop_masks[propid][0]; - ME_CursorFromCharOfs(reole->editor, pos, &from); + cursor_from_char_ofs( services->editor, pos, &from ); to = from; - ME_MoveCursorChars(reole->editor, &to, 1, FALSE); - ME_GetCharFormat(reole->editor, &from, &to, &fmt); + ME_MoveCursorChars( services->editor, &to, 1, FALSE ); + ME_GetCharFormat( services->editor, &from, &to, &fmt ); switch (propid) { @@ -508,11 +481,11 @@ static HRESULT get_textfont_prop_for_pos(const IRichEditOleImpl *reole, int pos, return S_OK; } -static inline const IRichEditOleImpl *get_range_reole(ITextRange *range) +static inline const struct text_services *get_range_reole(ITextRange *range) { - IRichEditOleImpl *reole = NULL; - ITextRange_QueryInterface(range, &IID_Igetrichole, (void**)&reole); - return reole; + struct text_services *services = NULL; + ITextRange_QueryInterface(range, &IID_Igetrichole, (void**)&services); + return services; } static void textrange_set_font(ITextRange *range, ITextFont *font) @@ -662,23 +635,24 @@ static void textrange_set_font(ITextRange *range, ITextFont *font) fmt.wWeight = value; } - if (fmt.dwMask) { - const IRichEditOleImpl *reole = get_range_reole(range); + if (fmt.dwMask) + { + const struct text_services *services = get_range_reole(range); ME_Cursor from, to; LONG start, end; ITextRange_GetStart(range, &start); ITextRange_GetEnd(range, &end); - ME_CursorFromCharOfs(reole->editor, start, &from); - ME_CursorFromCharOfs(reole->editor, end, &to); - ME_SetCharFormat(reole->editor, &from, &to, &fmt); + cursor_from_char_ofs( services->editor, start, &from ); + cursor_from_char_ofs( services->editor, end, &to ); + ME_SetCharFormat( services->editor, &from, &to, &fmt ); } } static HRESULT get_textfont_prop(const ITextFontImpl *font, enum textfont_prop_id propid, textfont_prop_val *value) { - const IRichEditOleImpl *reole; + const struct text_services *services; textfont_prop_val v; LONG start, end, i; HRESULT hr; @@ -689,7 +663,7 @@ static HRESULT get_textfont_prop(const ITextFontImpl *font, enum textfont_prop_i return S_OK; } - if (!(reole = get_range_reole(font->range))) + if (!(services = get_range_reole(font->range))) return CO_E_RELEASED; init_textfont_prop_value(propid, value); @@ -698,14 +672,14 @@ static HRESULT get_textfont_prop(const ITextFontImpl *font, enum textfont_prop_i ITextRange_GetEnd(font->range, &end); /* iterate trough a range to see if property value is consistent */ - hr = get_textfont_prop_for_pos(reole, start, propid, &v); + hr = get_textfont_prop_for_pos( services, start, propid, &v ); if (FAILED(hr)) return hr; for (i = start + 1; i < end; i++) { textfont_prop_val cur; - hr = get_textfont_prop_for_pos(reole, i, propid, &cur); + hr = get_textfont_prop_for_pos( services, i, propid, &cur ); if (FAILED(hr)) return hr; @@ -746,7 +720,7 @@ static HRESULT get_textfont_propl(const ITextFontImpl *font, enum textfont_prop_ /* Value should already have a terminal value, for boolean properties it means tomToggle is not handled */ static HRESULT set_textfont_prop(ITextFontImpl *font, enum textfont_prop_id propid, const textfont_prop_val *value) { - const IRichEditOleImpl *reole; + const struct text_services *services; ME_Cursor from, to; CHARFORMAT2W fmt; LONG start, end; @@ -762,7 +736,7 @@ static HRESULT set_textfont_prop(ITextFontImpl *font, enum textfont_prop_id prop return S_OK; } - if (!(reole = get_range_reole(font->range))) + if (!(services = get_range_reole(font->range))) return CO_E_RELEASED; memset(&fmt, 0, sizeof(fmt)); @@ -828,9 +802,9 @@ static HRESULT set_textfont_prop(ITextFontImpl *font, enum textfont_prop_id prop ITextRange_GetStart(font->range, &start); ITextRange_GetEnd(font->range, &end); - ME_CursorFromCharOfs(reole->editor, start, &from); - ME_CursorFromCharOfs(reole->editor, end, &to); - ME_SetCharFormat(reole->editor, &from, &to, &fmt); + cursor_from_char_ofs( services->editor, start, &from ); + cursor_from_char_ofs( services->editor, end, &to ); + ME_SetCharFormat( services->editor, &from, &to, &fmt ); return S_OK; } @@ -879,16 +853,16 @@ static HRESULT set_textfont_propd(ITextFontImpl *font, enum textfont_prop_id pro static HRESULT textfont_getname_from_range(ITextRange *range, BSTR *ret) { - const IRichEditOleImpl *reole; + const struct text_services *services; textfont_prop_val v; HRESULT hr; LONG start; - if (!(reole = get_range_reole(range))) + if (!(services = get_range_reole( range ))) return CO_E_RELEASED; ITextRange_GetStart(range, &start); - hr = get_textfont_prop_for_pos(reole, start, FONT_NAME, &v); + hr = get_textfont_prop_for_pos( services, start, FONT_NAME, &v ); *ret = v.str; return hr; } @@ -933,126 +907,48 @@ static HRESULT textrange_expand(ITextRange *range, LONG unit, LONG *delta) return S_OK; } -static HRESULT WINAPI IRichEditOleImpl_inner_fnQueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj) -{ - IRichEditOleImpl *This = impl_from_IUnknown(iface); - - TRACE("%p %s\n", This, debugstr_guid(riid)); - - *ppvObj = NULL; - if (IsEqualGUID(riid, &IID_IUnknown)) - *ppvObj = &This->IUnknown_inner; - else if (IsEqualGUID(riid, &IID_IRichEditOle)) - *ppvObj = &This->IRichEditOle_iface; - else if (IsEqualGUID(riid, &IID_ITextDocument) || IsEqualGUID(riid, &IID_ITextDocument2Old)) - *ppvObj = &This->ITextDocument2Old_iface; - if (*ppvObj) - { - IUnknown_AddRef((IUnknown *)*ppvObj); - return S_OK; - } - - if (IsEqualGUID(riid, &IID_ITextServices)) - { - static int once; - if (!once++) FIXME("%p: unhandled interface IID_ITextServices\n", This); - return E_NOINTERFACE; - } - - FIXME("%p: unhandled interface %s\n", This, debugstr_guid(riid)); - - return E_NOINTERFACE; -} - -static ULONG WINAPI IRichEditOleImpl_inner_fnAddRef(IUnknown *iface) -{ - IRichEditOleImpl *This = impl_from_IUnknown(iface); - ULONG ref = InterlockedIncrement(&This->ref); - - TRACE("%p ref = %u\n", This, ref); - - return ref; -} - -static ULONG WINAPI IRichEditOleImpl_inner_fnRelease(IUnknown *iface) -{ - IRichEditOleImpl *This = impl_from_IUnknown(iface); - ULONG ref = InterlockedDecrement(&This->ref); - - TRACE ("%p ref=%u\n", This, ref); - - if (!ref) - { - IOleClientSiteImpl *clientsite; - ITextRangeImpl *txtRge; - - This->editor->reOle = NULL; - if (This->txtSel) { - This->txtSel->reOle = NULL; - ITextSelection_Release(&This->txtSel->ITextSelection_iface); - } - - LIST_FOR_EACH_ENTRY(txtRge, &This->rangelist, ITextRangeImpl, child.entry) - txtRge->child.reole = NULL; - - LIST_FOR_EACH_ENTRY(clientsite, &This->clientsites, IOleClientSiteImpl, child.entry) - clientsite->child.reole = NULL; - - heap_free(This); - } - return ref; -} - -static const IUnknownVtbl reo_unk_vtbl = -{ - IRichEditOleImpl_inner_fnQueryInterface, - IRichEditOleImpl_inner_fnAddRef, - IRichEditOleImpl_inner_fnRelease -}; - static HRESULT WINAPI -IRichEditOle_fnQueryInterface(IRichEditOle *me, REFIID riid, LPVOID *ppvObj) +IRichEditOle_fnQueryInterface(IRichEditOle *iface, REFIID riid, LPVOID *ppvObj) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); + struct text_services *services = impl_from_IRichEditOle( iface ); + return IUnknown_QueryInterface( services->outer_unk, riid, ppvObj ); } static ULONG WINAPI -IRichEditOle_fnAddRef(IRichEditOle *me) +IRichEditOle_fnAddRef(IRichEditOle *iface) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - return IUnknown_AddRef(This->outer_unk); + struct text_services *services = impl_from_IRichEditOle( iface ); + return IUnknown_AddRef( services->outer_unk ); } static ULONG WINAPI -IRichEditOle_fnRelease(IRichEditOle *me) +IRichEditOle_fnRelease(IRichEditOle *iface) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - return IUnknown_Release(This->outer_unk); + struct text_services *services = impl_from_IRichEditOle( iface ); + return IUnknown_Release( services->outer_unk ); } static HRESULT WINAPI -IRichEditOle_fnActivateAs(IRichEditOle *me, REFCLSID rclsid, REFCLSID rclsidAs) +IRichEditOle_fnActivateAs(IRichEditOle *iface, REFCLSID rclsid, REFCLSID rclsidAs) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_IRichEditOle( iface ); + FIXME( "stub %p\n", services ); return E_NOTIMPL; } static HRESULT WINAPI -IRichEditOle_fnContextSensitiveHelp(IRichEditOle *me, BOOL fEnterMode) +IRichEditOle_fnContextSensitiveHelp(IRichEditOle *iface, BOOL fEnterMode) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_IRichEditOle( iface ); + FIXME( "stub %p\n", services ); return E_NOTIMPL; } static HRESULT WINAPI -IRichEditOle_fnConvertObject(IRichEditOle *me, LONG iob, - REFCLSID rclsidNew, LPCSTR lpstrUserTypeNew) +IRichEditOle_fnConvertObject( IRichEditOle *iface, LONG iob, REFCLSID class, LPCSTR user_type ) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_IRichEditOle( iface ); + FIXME( "stub %p\n", services ); return E_NOTIMPL; } @@ -1202,20 +1098,19 @@ static ULONG STDMETHODCALLTYPE IOleInPlaceSite_fnRelease(IOleInPlaceSite *iface) return IOleClientSite_Release(&This->IOleClientSite_iface); } -static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnGetWindow(IOleInPlaceSite *iface, HWND *phwnd) +static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnGetWindow( IOleInPlaceSite *iface, HWND *window ) { IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface); - TRACE("(%p)->(%p)\n", This, phwnd); + TRACE( "(%p)->(%p)\n", This, window ); if (!This->child.reole) return CO_E_RELEASED; - if (!phwnd) - return E_INVALIDARG; + if (!window) return E_INVALIDARG; - *phwnd = This->child.reole->editor->hWnd; - return S_OK; + if (!This->child.reole->editor->have_texthost2) return E_NOTIMPL; + return ITextHost2_TxGetWindow( This->child.reole->editor->texthost, window ); } static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode) @@ -1316,7 +1211,7 @@ static const IOleInPlaceSiteVtbl olestvt = IOleInPlaceSite_fnOnPosRectChange }; -static HRESULT CreateOleClientSite(IRichEditOleImpl *reOle, IOleClientSite **ret) +static HRESULT CreateOleClientSite( struct text_services *services, IOleClientSite **ret ) { IOleClientSiteImpl *clientSite = heap_alloc(sizeof *clientSite); @@ -1326,64 +1221,67 @@ static HRESULT CreateOleClientSite(IRichEditOleImpl *reOle, IOleClientSite **ret clientSite->IOleClientSite_iface.lpVtbl = &ocst; clientSite->IOleInPlaceSite_iface.lpVtbl = &olestvt; clientSite->ref = 1; - clientSite->child.reole = reOle; - list_add_head(&reOle->clientsites, &clientSite->child.entry); + clientSite->child.reole = services; + list_add_head( &services->clientsites, &clientSite->child.entry ); *ret = &clientSite->IOleClientSite_iface; return S_OK; } static HRESULT WINAPI -IRichEditOle_fnGetClientSite(IRichEditOle *me, IOleClientSite **clientsite) +IRichEditOle_fnGetClientSite( IRichEditOle *iface, IOleClientSite **clientsite ) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); + struct text_services *services = impl_from_IRichEditOle( iface ); - TRACE("(%p)->(%p)\n", This, clientsite); + TRACE("(%p)->(%p)\n", services, clientsite); if (!clientsite) return E_INVALIDARG; - return CreateOleClientSite(This, clientsite); + return CreateOleClientSite( services, clientsite ); } static HRESULT WINAPI -IRichEditOle_fnGetClipboardData(IRichEditOle *me, CHARRANGE *lpchrg, +IRichEditOle_fnGetClipboardData(IRichEditOle *iface, CHARRANGE *lpchrg, DWORD reco, LPDATAOBJECT *lplpdataobj) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); + struct text_services *services = impl_from_IRichEditOle( iface ); ME_Cursor start; int nChars; - TRACE("(%p,%p,%d)\n",This, lpchrg, reco); + TRACE("(%p,%p,%d)\n", services, lpchrg, reco); if(!lplpdataobj) return E_INVALIDARG; - if(!lpchrg) { - int nFrom, nTo, nStartCur = ME_GetSelectionOfs(This->editor, &nFrom, &nTo); - start = This->editor->pCursors[nStartCur]; + if(!lpchrg) + { + int nFrom, nTo, nStartCur = ME_GetSelectionOfs( services->editor, &nFrom, &nTo ); + start = services->editor->pCursors[nStartCur]; nChars = nTo - nFrom; - } else { - ME_CursorFromCharOfs(This->editor, lpchrg->cpMin, &start); + } + else + { + cursor_from_char_ofs( services->editor, lpchrg->cpMin, &start ); nChars = lpchrg->cpMax - lpchrg->cpMin; } - return ME_GetDataObject(This->editor, &start, nChars, lplpdataobj); + return ME_GetDataObject( services->editor, &start, nChars, lplpdataobj ); } -static LONG WINAPI IRichEditOle_fnGetLinkCount(IRichEditOle *me) +static LONG WINAPI IRichEditOle_fnGetLinkCount(IRichEditOle *iface) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_IRichEditOle( iface ); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI -IRichEditOle_fnGetObject(IRichEditOle *me, LONG iob, +IRichEditOle_fnGetObject(IRichEditOle *iface, LONG iob, REOBJECT *lpreobject, DWORD dwFlags) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); + struct text_services *services = impl_from_IRichEditOle( iface ); struct re_object *reobj = NULL; LONG count = 0; - TRACE("(%p)->(%x, %p, %x)\n", This, iob, lpreobject, dwFlags); + TRACE("(%p)->(%x, %p, %x)\n", services, iob, lpreobject, dwFlags); if (!lpreobject || !lpreobject->cbStruct) return E_INVALIDARG; @@ -1393,27 +1291,27 @@ IRichEditOle_fnGetObject(IRichEditOle *me, LONG iob, ME_Cursor cursor; TRACE("character offset: %d\n", lpreobject->cp); - ME_CursorFromCharOfs(This->editor, lpreobject->cp, &cursor); - if (!cursor.pRun->member.run.reobj) + cursor_from_char_ofs( services->editor, lpreobject->cp, &cursor ); + if (!cursor.run->reobj) return E_INVALIDARG; else - reobj = cursor.pRun->member.run.reobj; + reobj = cursor.run->reobj; } else if (iob == REO_IOB_SELECTION) { ME_Cursor *from, *to; - ME_GetSelection(This->editor, &from, &to); - if (!from->pRun->member.run.reobj) + ME_GetSelection(services->editor, &from, &to); + if (!from->run->reobj) return E_INVALIDARG; else - reobj = from->pRun->member.run.reobj; + reobj = from->run->reobj; } else { - if (iob > IRichEditOle_GetObjectCount(me)) + if (iob < 0 || iob >= IRichEditOle_GetObjectCount( iface )) return E_INVALIDARG; - LIST_FOR_EACH_ENTRY(reobj, &This->editor->reobj_list, struct re_object, entry) + LIST_FOR_EACH_ENTRY(reobj, &services->editor->reobj_list, struct re_object, entry) { if (count == iob) break; @@ -1425,89 +1323,90 @@ IRichEditOle_fnGetObject(IRichEditOle *me, LONG iob, } static LONG WINAPI -IRichEditOle_fnGetObjectCount(IRichEditOle *me) +IRichEditOle_fnGetObjectCount( IRichEditOle *iface ) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - TRACE("(%p)\n",This); - return list_count(&This->editor->reobj_list); + struct text_services *services = impl_from_IRichEditOle( iface ); + TRACE("(%p)\n", services); + return list_count( &services->editor->reobj_list ); } static HRESULT WINAPI -IRichEditOle_fnHandsOffStorage(IRichEditOle *me, LONG iob) +IRichEditOle_fnHandsOffStorage(IRichEditOle *iface, LONG iob) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_IRichEditOle( iface ); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI -IRichEditOle_fnImportDataObject(IRichEditOle *me, LPDATAOBJECT lpdataobj, +IRichEditOle_fnImportDataObject(IRichEditOle *iface, LPDATAOBJECT lpdataobj, CLIPFORMAT cf, HGLOBAL hMetaPict) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_IRichEditOle( iface ); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI -IRichEditOle_fnInPlaceDeactivate(IRichEditOle *me) +IRichEditOle_fnInPlaceDeactivate(IRichEditOle *iface) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_IRichEditOle( iface ); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI -IRichEditOle_fnInsertObject(IRichEditOle *me, REOBJECT *reo) +IRichEditOle_fnInsertObject(IRichEditOle *iface, REOBJECT *reo) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); + struct text_services *services = impl_from_IRichEditOle( iface ); - TRACE("(%p,%p)\n", This, reo); + TRACE("(%p,%p)\n", services, reo); if (!reo) return E_INVALIDARG; if (reo->cbStruct < sizeof(*reo)) return STG_E_INVALIDPARAMETER; - ME_InsertOLEFromCursor(This->editor, reo, 0); - ME_CommitUndo(This->editor); - ME_UpdateRepaint(This->editor, FALSE); + ME_InsertOLEFromCursor(services->editor, reo, 0); + ME_CommitUndo(services->editor); + ME_UpdateRepaint(services->editor, FALSE); return S_OK; } -static HRESULT WINAPI IRichEditOle_fnSaveCompleted(IRichEditOle *me, LONG iob, +static HRESULT WINAPI IRichEditOle_fnSaveCompleted(IRichEditOle *iface, LONG iob, LPSTORAGE lpstg) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_IRichEditOle( iface ); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI -IRichEditOle_fnSetDvaspect(IRichEditOle *me, LONG iob, DWORD dvaspect) +IRichEditOle_fnSetDvaspect(IRichEditOle *iface, LONG iob, DWORD dvaspect) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_IRichEditOle( iface ); + FIXME("stub %p\n", services); return E_NOTIMPL; } -static HRESULT WINAPI IRichEditOle_fnSetHostNames(IRichEditOle *me, +static HRESULT WINAPI IRichEditOle_fnSetHostNames(IRichEditOle *iface, LPCSTR lpstrContainerApp, LPCSTR lpstrContainerObj) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p %s %s\n",This, lpstrContainerApp, lpstrContainerObj); + struct text_services *services = impl_from_IRichEditOle( iface ); + FIXME("stub %p %s %s\n", services, lpstrContainerApp, lpstrContainerObj); return E_NOTIMPL; } static HRESULT WINAPI -IRichEditOle_fnSetLinkAvailable(IRichEditOle *me, LONG iob, BOOL fAvailable) +IRichEditOle_fnSetLinkAvailable(IRichEditOle *iface, LONG iob, BOOL fAvailable) { - IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_IRichEditOle( iface ); + FIXME("stub %p\n", services); return E_NOTIMPL; } -static const IRichEditOleVtbl revt = { +const IRichEditOleVtbl re_ole_vtbl = +{ IRichEditOle_fnQueryInterface, IRichEditOle_fnAddRef, IRichEditOle_fnRelease, @@ -1655,15 +1554,15 @@ static HRESULT WINAPI ITextRange_fnGetText(ITextRange *me, BSTR *str) } editor = This->child.reole->editor; - ME_CursorFromCharOfs(editor, This->start, &start); - ME_CursorFromCharOfs(editor, This->end, &end); + cursor_from_char_ofs( editor, This->start, &start ); + cursor_from_char_ofs( editor, This->end, &end ); length = This->end - This->start; *str = SysAllocStringLen(NULL, length); if (!*str) return E_OUTOFMEMORY; - bEOP = (end.pRun->next->type == diTextEnd && This->end > ME_GetTextLength(editor)); + bEOP = (!para_next( para_next( end.para )) && This->end > ME_GetTextLength(editor)); ME_GetTextW(editor, *str, length, &start, length, FALSE, bEOP); return S_OK; } @@ -1684,12 +1583,14 @@ static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR str) editor = This->child.reole->editor; /* delete only where's something to delete */ - if (This->start != This->end) { - ME_CursorFromCharOfs(editor, This->start, &cursor); + if (This->start != This->end) + { + cursor_from_char_ofs( editor, This->start, &cursor ); ME_InternalDeleteText(editor, &cursor, This->end - This->start, FALSE); } - if (!str || !*str) { + if (!str || !*str) + { /* will update this range as well */ textranges_update_ranges(This->child.reole, This->start, This->end, RANGE_UPDATE_DELETE); return S_OK; @@ -1698,8 +1599,8 @@ static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR str) /* it's safer not to rely on stored BSTR length */ len = lstrlenW(str); cursor = editor->pCursors[0]; - ME_CursorFromCharOfs(editor, This->start, &editor->pCursors[0]); - style = ME_GetInsertStyle(editor, 0); + cursor_from_char_ofs( editor, This->start, &editor->pCursors[0] ); + style = style_get_insert_style( editor, editor->pCursors ); ME_InsertTextFromCursor(editor, 0, str, len, style); ME_ReleaseStyle(style); editor->pCursors[0] = cursor; @@ -1716,7 +1617,7 @@ static HRESULT range_GetChar(ME_TextEditor *editor, ME_Cursor *cursor, LONG *pch { WCHAR wch[2]; - ME_GetTextW(editor, wch, 1, cursor, 1, FALSE, cursor->pRun->next->type == diTextEnd); + ME_GetTextW(editor, wch, 1, cursor, 1, FALSE, !para_next( para_next( cursor->para ) )); *pch = wch[0]; return S_OK; @@ -1737,7 +1638,7 @@ static HRESULT WINAPI ITextRange_fnGetChar(ITextRange *me, LONG *pch) return E_INVALIDARG; editor = This->child.reole->editor; - ME_CursorFromCharOfs(editor, This->start, &cursor); + cursor_from_char_ofs( editor, This->start, &cursor ); return range_GetChar(editor, &cursor, pch); } @@ -1753,7 +1654,7 @@ static HRESULT WINAPI ITextRange_fnSetChar(ITextRange *me, LONG ch) return E_NOTIMPL; } -static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, ITextRange** ppRange); +static HRESULT CreateITextRange(struct text_services *services, LONG start, LONG end, ITextRange** ppRange); static HRESULT WINAPI ITextRange_fnGetDuplicate(ITextRange *me, ITextRange **ppRange) { @@ -1810,7 +1711,7 @@ static HRESULT WINAPI ITextRange_fnGetStart(ITextRange *me, LONG *start) return S_OK; } -static HRESULT textrange_setstart(const IRichEditOleImpl *reole, LONG value, LONG *start, LONG *end) +static HRESULT textrange_setstart(const struct text_services *services, LONG value, LONG *start, LONG *end) { int len; @@ -1825,7 +1726,7 @@ static HRESULT textrange_setstart(const IRichEditOleImpl *reole, LONG value, LON return S_OK; } - len = ME_GetTextLength(reole->editor); + len = ME_GetTextLength(services->editor); *start = *end = value > len ? len : value; return S_OK; } @@ -1858,7 +1759,7 @@ static HRESULT WINAPI ITextRange_fnGetEnd(ITextRange *me, LONG *end) return S_OK; } -static HRESULT textrange_setend(const IRichEditOleImpl *reole, LONG value, LONG *start, LONG *end) +static HRESULT textrange_setend(const struct text_services *services, LONG value, LONG *start, LONG *end) { int len; @@ -1870,7 +1771,7 @@ static HRESULT textrange_setend(const IRichEditOleImpl *reole, LONG value, LONG return S_OK; } - len = ME_GetTextLength(reole->editor); + len = ME_GetTextLength( services->editor ); *end = value > len ? len + 1 : value; return S_OK; } @@ -2056,7 +1957,7 @@ static HRESULT WINAPI ITextRange_fnSetRange(ITextRange *me, LONG anchor, LONG ac { ITextRangeImpl *This = impl_from_ITextRange(me); - FIXME("(%p)->(%d %d): stub\n", This, anchor, active); + TRACE("(%p)->(%d %d)\n", This, anchor, active); if (!This->child.reole) return CO_E_RELEASED; @@ -2161,17 +2062,89 @@ static HRESULT WINAPI ITextRange_fnSelect(ITextRange *me) return S_OK; } +static HRESULT textrange_startof(ITextRange *range, LONG unit, LONG extend, LONG *delta) +{ + HRESULT hr; + LONG start, end; + LONG moved; + + ITextRange_GetStart(range, &start); + ITextRange_GetEnd(range, &end); + + switch (unit) + { + case tomCharacter: + { + moved = 0; + if (extend == tomMove) { + if (start != end) { + ITextRange_SetEnd(range, start); + moved = -1; + } + } + if (delta) + *delta = moved; + hr = moved ? S_OK : S_FALSE; + break; + } + default: + FIXME("unit %d is not supported\n", unit); + return E_NOTIMPL; + } + return hr; +} + static HRESULT WINAPI ITextRange_fnStartOf(ITextRange *me, LONG unit, LONG extend, LONG *delta) { ITextRangeImpl *This = impl_from_ITextRange(me); - FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta); + TRACE("(%p)->(%d %d %p)\n", This, unit, extend, delta); if (!This->child.reole) return CO_E_RELEASED; - return E_NOTIMPL; + return textrange_startof(me, unit, extend, delta); +} + +static HRESULT textrange_endof(ITextRange *range, ME_TextEditor *editor, LONG unit, LONG extend, LONG *delta) +{ + HRESULT hr; + LONG old_start, old_end, new_end; + LONG moved; + + ITextRange_GetStart(range, &old_start); + ITextRange_GetEnd(range, &old_end); + + switch (unit) + { + case tomCharacter: + { + moved = 0; + new_end = old_end; + if (old_end == 0) + { + ME_Cursor cursor; + cursor_from_char_ofs( editor, old_end, &cursor ); + moved = ME_MoveCursorChars(editor, &cursor, 1, TRUE); + new_end = old_end + moved; + } + else if (extend == tomMove && old_start != old_end) + moved = 1; + + ITextRange_SetEnd(range, new_end); + if (extend == tomMove) + ITextRange_SetStart(range, new_end); + if (delta) + *delta = moved; + hr = moved ? S_OK : S_FALSE; + break; + } + default: + FIXME("unit %d is not supported\n", unit); + return E_NOTIMPL; + } + return hr; } static HRESULT WINAPI ITextRange_fnEndOf(ITextRange *me, LONG unit, LONG extend, @@ -2179,24 +2152,133 @@ static HRESULT WINAPI ITextRange_fnEndOf(ITextRange *me, LONG unit, LONG extend, { ITextRangeImpl *This = impl_from_ITextRange(me); - FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta); + TRACE("(%p)->(%d %d %p)\n", This, unit, extend, delta); if (!This->child.reole) return CO_E_RELEASED; - return E_NOTIMPL; + return textrange_endof(me, This->child.reole->editor, unit, extend, delta); +} + +static HRESULT textrange_move(ITextRange *range, ME_TextEditor *editor, LONG unit, LONG count, LONG *delta) +{ + LONG old_start, old_end, new_start, new_end; + LONG move_by; + LONG moved; + HRESULT hr = S_OK; + + if (!count) + { + if (delta) + *delta = 0; + return S_FALSE; + } + + ITextRange_GetStart(range, &old_start); + ITextRange_GetEnd(range, &old_end); + switch (unit) + { + case tomCharacter: + { + ME_Cursor cursor; + + if (count > 0) + { + cursor_from_char_ofs( editor, old_end, &cursor ); + move_by = count; + if (old_start != old_end) + --move_by; + } + else + { + cursor_from_char_ofs( editor, old_start, &cursor ); + move_by = count; + if (old_start != old_end) + ++move_by; + } + moved = ME_MoveCursorChars(editor, &cursor, move_by, FALSE); + if (count > 0) + { + new_end = old_end + moved; + new_start = new_end; + if (old_start != old_end) + ++moved; + } + else + { + new_start = old_start + moved; + new_end = new_start; + if (old_start != old_end) + --moved; + } + if (delta) *delta = moved; + break; + } + default: + FIXME("unit %d is not supported\n", unit); + return E_NOTIMPL; + } + if (moved == 0) + hr = S_FALSE; + ITextRange_SetStart(range, new_start); + ITextRange_SetEnd(range, new_end); + + return hr; } static HRESULT WINAPI ITextRange_fnMove(ITextRange *me, LONG unit, LONG count, LONG *delta) { ITextRangeImpl *This = impl_from_ITextRange(me); - FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta); + TRACE("(%p)->(%d %d %p)\n", This, unit, count, delta); if (!This->child.reole) return CO_E_RELEASED; - return E_NOTIMPL; + return textrange_move(me, This->child.reole->editor, unit, count, delta); +} + +static HRESULT textrange_movestart(ITextRange *range, ME_TextEditor *editor, LONG unit, LONG count, LONG *delta) +{ + LONG old_start, old_end, new_start, new_end; + HRESULT hr = S_OK; + + if (!count) + { + if (delta) + *delta = 0; + return S_FALSE; + } + + ITextRange_GetStart(range, &old_start); + ITextRange_GetEnd(range, &old_end); + switch (unit) + { + case tomCharacter: + { + ME_Cursor cursor; + LONG moved; + + cursor_from_char_ofs( editor, old_start, &cursor ); + moved = ME_MoveCursorChars(editor, &cursor, count, FALSE); + new_start = old_start + moved; + new_end = old_end; + if (new_end < new_start) + new_end = new_start; + if (delta) + *delta = moved; + break; + } + default: + FIXME("unit %d is not supported\n", unit); + return E_NOTIMPL; + } + if (new_start == old_start) + hr = S_FALSE; + ITextRange_SetStart(range, new_start); + ITextRange_SetEnd(range, new_end); + + return hr; } static HRESULT WINAPI ITextRange_fnMoveStart(ITextRange *me, LONG unit, LONG count, @@ -2204,15 +2286,15 @@ static HRESULT WINAPI ITextRange_fnMoveStart(ITextRange *me, LONG unit, LONG cou { ITextRangeImpl *This = impl_from_ITextRange(me); - FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta); + TRACE("(%p)->(%d %d %p)\n", This, unit, count, delta); if (!This->child.reole) return CO_E_RELEASED; - return E_NOTIMPL; + return textrange_movestart(me, This->child.reole->editor, unit, count, delta); } -static HRESULT textrange_moveend(ITextRange *range, LONG unit, LONG count, LONG *delta) +static HRESULT textrange_moveend(ITextRange *range, ME_TextEditor *editor, LONG unit, LONG count, LONG *delta) { LONG old_start, old_end, new_start, new_end; HRESULT hr = S_OK; @@ -2228,6 +2310,21 @@ static HRESULT textrange_moveend(ITextRange *range, LONG unit, LONG count, LONG ITextRange_GetEnd(range, &old_end); switch (unit) { + case tomCharacter: + { + ME_Cursor cursor; + LONG moved; + + cursor_from_char_ofs( editor, old_end, &cursor ); + moved = ME_MoveCursorChars(editor, &cursor, count, TRUE); + new_start = old_start; + new_end = old_end + moved; + if (new_end < new_start) + new_start = new_end; + if (delta) + *delta = moved; + break; + } case tomStory: if (count < 0) new_start = new_end = 0; @@ -2268,7 +2365,7 @@ static HRESULT WINAPI ITextRange_fnMoveEnd(ITextRange *me, LONG unit, LONG count if (!This->child.reole) return CO_E_RELEASED; - return textrange_moveend(me, unit, count, delta); + return textrange_moveend(me, This->child.reole->editor, unit, count, delta); } static HRESULT WINAPI ITextRange_fnMoveWhile(ITextRange *me, VARIANT *charset, LONG count, @@ -2400,28 +2497,53 @@ static HRESULT WINAPI ITextRange_fnDelete(ITextRange *me, LONG unit, LONG count, return E_NOTIMPL; } +static HRESULT textrange_copy_or_cut( ITextRange *range, ME_TextEditor *editor, BOOL cut, VARIANT *v ) +{ + LONG start, end; + ME_Cursor cursor; + IDataObject **data_out = NULL; + + ITextRange_GetStart( range, &start ); + ITextRange_GetEnd( range, &end ); + if (start == end) + { + /* If the range is empty, all text is copied */ + LONG prev_end = end; + ITextRange_SetEnd( range, MAXLONG ); + start = 0; + ITextRange_GetEnd( range, &end ); + ITextRange_SetEnd( range, prev_end ); + } + cursor_from_char_ofs( editor, start, &cursor ); + + if (v && V_VT(v) == (VT_UNKNOWN | VT_BYREF) && V_UNKNOWNREF( v )) + data_out = (IDataObject **)V_UNKNOWNREF( v ); + + return editor_copy_or_cut( editor, cut, &cursor, end - start, data_out ); +} + static HRESULT WINAPI ITextRange_fnCut(ITextRange *me, VARIANT *v) { ITextRangeImpl *This = impl_from_ITextRange(me); - FIXME("(%p)->(%p): stub\n", This, v); + TRACE("(%p)->(%p)\n", This, v); if (!This->child.reole) return CO_E_RELEASED; - return E_NOTIMPL; + return textrange_copy_or_cut(me, This->child.reole->editor, TRUE, v); } static HRESULT WINAPI ITextRange_fnCopy(ITextRange *me, VARIANT *v) { ITextRangeImpl *This = impl_from_ITextRange(me); - FIXME("(%p)->(%p): stub\n", This, v); + TRACE("(%p)->(%p)\n", This, v); if (!This->child.reole) return CO_E_RELEASED; - return E_NOTIMPL; + return textrange_copy_or_cut(me, This->child.reole->editor, FALSE, v); } static HRESULT WINAPI ITextRange_fnPaste(ITextRange *me, VARIANT *v, LONG format) @@ -2514,18 +2636,18 @@ static HRESULT WINAPI ITextRange_fnScrollIntoView(ITextRange *me, LONG value) switch (value) { case tomStart: - ME_CursorFromCharOfs(editor, This->start, &cursor); - ME_GetCursorCoordinates(editor, &cursor, &x, &y, &height); + cursor_from_char_ofs( editor, This->start, &cursor ); + cursor_coords( editor, &cursor, &x, &y, &height ); break; case tomEnd: - ME_CursorFromCharOfs(editor, This->end, &cursor); - ME_GetCursorCoordinates(editor, &cursor, &x, &y, &height); + cursor_from_char_ofs( editor, This->end, &cursor ); + cursor_coords( editor, &cursor, &x, &y, &height ); break; default: FIXME("bStart value %d not handled\n", value); return E_NOTIMPL; } - ME_ScrollAbs(editor, x, y); + scroll_abs( editor, x, y, TRUE ); return S_OK; } @@ -2785,9 +2907,8 @@ static void textfont_reset_to_default(ITextFontImpl *font) font->props[id].l = GetSystemDefaultLCID(); break; case FONT_NAME: { - static const WCHAR sysW[] = {'S','y','s','t','e','m',0}; SysFreeString(font->props[id].str); - font->props[id].str = SysAllocString(sysW); + font->props[id].str = SysAllocString(L"System"); break; } case FONT_WEIGHT: @@ -3430,16 +3551,6 @@ static ULONG WINAPI TextPara_Release(ITextPara *iface) return ref; } -static IRichEditOleImpl *para_get_reole(ITextParaImpl *This) -{ - if (This->range) - { - ITextRangeImpl *rng = impl_from_ITextRange(This->range); - return rng->child.reole; - } - return NULL; -} - static HRESULT WINAPI TextPara_GetTypeInfoCount(ITextPara *iface, UINT *pctinfo) { ITextParaImpl *This = impl_from_ITextPara(iface); @@ -3507,10 +3618,6 @@ static HRESULT WINAPI TextPara_GetDuplicate(ITextPara *iface, ITextPara **ret) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, ret); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3518,10 +3625,6 @@ static HRESULT WINAPI TextPara_SetDuplicate(ITextPara *iface, ITextPara *para) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, para); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3529,10 +3632,6 @@ static HRESULT WINAPI TextPara_CanChange(ITextPara *iface, LONG *ret) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, ret); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3540,10 +3639,6 @@ static HRESULT WINAPI TextPara_IsEqual(ITextPara *iface, ITextPara *para, LONG * { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p %p)\n", This, para, ret); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3551,10 +3646,6 @@ static HRESULT WINAPI TextPara_Reset(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3562,10 +3653,6 @@ static HRESULT WINAPI TextPara_GetStyle(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3573,23 +3660,13 @@ static HRESULT WINAPI TextPara_SetStyle(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } static HRESULT WINAPI TextPara_GetAlignment(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); - static int once; - - if (!once++) FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - + FIXME("(%p)->(%p)\n", This, value); return E_NOTIMPL; } @@ -3597,10 +3674,6 @@ static HRESULT WINAPI TextPara_SetAlignment(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3608,10 +3681,6 @@ static HRESULT WINAPI TextPara_GetHyphenation(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3619,10 +3688,6 @@ static HRESULT WINAPI TextPara_SetHyphenation(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3630,10 +3695,6 @@ static HRESULT WINAPI TextPara_GetFirstLineIndent(ITextPara *iface, FLOAT *value { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3641,10 +3702,6 @@ static HRESULT WINAPI TextPara_GetKeepTogether(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3652,10 +3709,6 @@ static HRESULT WINAPI TextPara_SetKeepTogether(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3663,10 +3716,6 @@ static HRESULT WINAPI TextPara_GetKeepWithNext(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3674,10 +3723,6 @@ static HRESULT WINAPI TextPara_SetKeepWithNext(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3685,10 +3730,6 @@ static HRESULT WINAPI TextPara_GetLeftIndent(ITextPara *iface, FLOAT *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3696,10 +3737,6 @@ static HRESULT WINAPI TextPara_GetLineSpacing(ITextPara *iface, FLOAT *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3707,10 +3744,6 @@ static HRESULT WINAPI TextPara_GetLineSpacingRule(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3718,10 +3751,6 @@ static HRESULT WINAPI TextPara_GetListAlignment(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3729,10 +3758,6 @@ static HRESULT WINAPI TextPara_SetListAlignment(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3740,10 +3765,6 @@ static HRESULT WINAPI TextPara_GetListLevelIndex(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3751,10 +3772,6 @@ static HRESULT WINAPI TextPara_SetListLevelIndex(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3762,10 +3779,6 @@ static HRESULT WINAPI TextPara_GetListStart(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3773,10 +3786,6 @@ static HRESULT WINAPI TextPara_SetListStart(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3784,10 +3793,6 @@ static HRESULT WINAPI TextPara_GetListTab(ITextPara *iface, FLOAT *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3795,10 +3800,6 @@ static HRESULT WINAPI TextPara_SetListTab(ITextPara *iface, FLOAT value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%.2f)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3806,10 +3807,6 @@ static HRESULT WINAPI TextPara_GetListType(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3817,10 +3814,6 @@ static HRESULT WINAPI TextPara_SetListType(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3828,10 +3821,6 @@ static HRESULT WINAPI TextPara_GetNoLineNumber(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3839,10 +3828,6 @@ static HRESULT WINAPI TextPara_SetNoLineNumber(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3850,10 +3835,6 @@ static HRESULT WINAPI TextPara_GetPageBreakBefore(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3861,10 +3842,6 @@ static HRESULT WINAPI TextPara_SetPageBreakBefore(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3872,10 +3849,6 @@ static HRESULT WINAPI TextPara_GetRightIndent(ITextPara *iface, FLOAT *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3883,10 +3856,6 @@ static HRESULT WINAPI TextPara_SetRightIndent(ITextPara *iface, FLOAT value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%.2f)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3894,10 +3863,6 @@ static HRESULT WINAPI TextPara_SetIndents(ITextPara *iface, FLOAT StartIndent, F { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%.2f %.2f %.2f)\n", This, StartIndent, LeftIndent, RightIndent); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3905,10 +3870,6 @@ static HRESULT WINAPI TextPara_SetLineSpacing(ITextPara *iface, LONG LineSpacing { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d %.2f)\n", This, LineSpacingRule, LineSpacing); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3916,10 +3877,6 @@ static HRESULT WINAPI TextPara_GetSpaceAfter(ITextPara *iface, FLOAT *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3927,10 +3884,6 @@ static HRESULT WINAPI TextPara_SetSpaceAfter(ITextPara *iface, FLOAT value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%.2f)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3938,10 +3891,6 @@ static HRESULT WINAPI TextPara_GetSpaceBefore(ITextPara *iface, FLOAT *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3949,10 +3898,6 @@ static HRESULT WINAPI TextPara_SetSpaceBefore(ITextPara *iface, FLOAT value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%.2f)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3960,10 +3905,6 @@ static HRESULT WINAPI TextPara_GetWidowControl(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3971,10 +3912,6 @@ static HRESULT WINAPI TextPara_SetWidowControl(ITextPara *iface, LONG value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3982,10 +3919,6 @@ static HRESULT WINAPI TextPara_GetTabCount(ITextPara *iface, LONG *value) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%p)\n", This, value); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -3993,10 +3926,6 @@ static HRESULT WINAPI TextPara_AddTab(ITextPara *iface, FLOAT tbPos, LONG tbAlig { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%.2f %d %d)\n", This, tbPos, tbAlign, tbLeader); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -4004,10 +3933,6 @@ static HRESULT WINAPI TextPara_ClearAllTabs(ITextPara *iface) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)\n", This); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -4015,10 +3940,6 @@ static HRESULT WINAPI TextPara_DeleteTab(ITextPara *iface, FLOAT pos) { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%.2f)\n", This, pos); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -4026,10 +3947,6 @@ static HRESULT WINAPI TextPara_GetTab(ITextPara *iface, LONG iTab, FLOAT *ptbPos { ITextParaImpl *This = impl_from_ITextPara(iface); FIXME("(%p)->(%d %p %p %p)\n", This, iTab, ptbPos, ptbAlign, ptbLeader); - - if (!para_get_reole(This)) - return CO_E_RELEASED; - return E_NOTIMPL; } @@ -4113,27 +4030,27 @@ static HRESULT create_textpara(ITextRange *range, ITextPara **ret) static HRESULT WINAPI ITextDocument2Old_fnQueryInterface(ITextDocument2Old* iface, REFIID riid, void **ppvObject) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - return IRichEditOle_QueryInterface(&This->IRichEditOle_iface, riid, ppvObject); + struct text_services *services = impl_from_ITextDocument2Old(iface); + return IUnknown_QueryInterface( services->outer_unk, riid, ppvObject ); } static ULONG WINAPI ITextDocument2Old_fnAddRef(ITextDocument2Old *iface) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - return IRichEditOle_AddRef(&This->IRichEditOle_iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); + return IUnknown_AddRef( services->outer_unk ); } static ULONG WINAPI ITextDocument2Old_fnRelease(ITextDocument2Old *iface) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - return IRichEditOle_Release(&This->IRichEditOle_iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); + return IUnknown_Release( services->outer_unk ); } static HRESULT WINAPI ITextDocument2Old_fnGetTypeInfoCount(ITextDocument2Old *iface, UINT *pctinfo) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - TRACE("(%p)->(%p)\n", This, pctinfo); + struct text_services *services = impl_from_ITextDocument2Old(iface); + TRACE("(%p)->(%p)\n", services, pctinfo); *pctinfo = 1; return S_OK; } @@ -4141,10 +4058,10 @@ static HRESULT WINAPI ITextDocument2Old_fnGetTypeInfoCount(ITextDocument2Old *if static HRESULT WINAPI ITextDocument2Old_fnGetTypeInfo(ITextDocument2Old *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); HRESULT hr; - TRACE("(%p)->(%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo); + TRACE("(%p)->(%u,%d,%p)\n", services, iTInfo, lcid, ppTInfo); hr = get_typeinfo(ITextDocument_tid, ppTInfo); if (SUCCEEDED(hr)) @@ -4156,11 +4073,11 @@ static HRESULT WINAPI ITextDocument2Old_fnGetIDsOfNames(ITextDocument2Old *iface LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), + TRACE("(%p)->(%s, %p, %u, %d, %p)\n", services, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); hr = get_typeinfo(ITextDocument_tid, &ti); @@ -4174,11 +4091,11 @@ static HRESULT WINAPI ITextDocument2Old_fnInvoke(ITextDocument2Old *iface, DISPI DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember, + TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", services, dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); @@ -4190,142 +4107,144 @@ static HRESULT WINAPI ITextDocument2Old_fnInvoke(ITextDocument2Old *iface, DISPI static HRESULT WINAPI ITextDocument2Old_fnGetName(ITextDocument2Old *iface, BSTR *pName) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnGetSelection(ITextDocument2Old *iface, ITextSelection **selection) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); TRACE("(%p)->(%p)\n", iface, selection); if (!selection) return E_INVALIDARG; - if (!This->txtSel) { - This->txtSel = CreateTextSelection(This); - if (!This->txtSel) { - *selection = NULL; - return E_OUTOFMEMORY; - } + if (!services->text_selection) + { + services->text_selection = text_selection_create( services ); + if (!services->text_selection) + { + *selection = NULL; + return E_OUTOFMEMORY; + } } - *selection = &This->txtSel->ITextSelection_iface; + *selection = &services->text_selection->ITextSelection_iface; ITextSelection_AddRef(*selection); return S_OK; } static HRESULT WINAPI ITextDocument2Old_fnGetStoryCount(ITextDocument2Old *iface, LONG *pCount) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnGetStoryRanges(ITextDocument2Old *iface, ITextStoryRanges **ppStories) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnGetSaved(ITextDocument2Old *iface, LONG *pValue) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnSetSaved(ITextDocument2Old *iface, LONG Value) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnGetDefaultTabStop(ITextDocument2Old *iface, float *pValue) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnSetDefaultTabStop(ITextDocument2Old *iface, float Value) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnNew(ITextDocument2Old *iface) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnOpen(ITextDocument2Old *iface, VARIANT *pVar, LONG Flags, LONG CodePage) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnSave(ITextDocument2Old *iface, VARIANT *pVar, LONG Flags, LONG CodePage) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnFreeze(ITextDocument2Old *iface, LONG *pCount) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnUnfreeze(ITextDocument2Old *iface, LONG *pCount) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnBeginEditCollection(ITextDocument2Old *iface) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnEndEditCollection(ITextDocument2Old *iface) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnUndo(ITextDocument2Old *iface, LONG Count, LONG *prop) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnRedo(ITextDocument2Old *iface, LONG Count, LONG *prop) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } -static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, ITextRange** ppRange) +static HRESULT CreateITextRange(struct text_services *services, LONG start, LONG end, ITextRange** ppRange) { ITextRangeImpl *txtRge = heap_alloc(sizeof(ITextRangeImpl)); @@ -4333,10 +4252,10 @@ static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, I return E_OUTOFMEMORY; txtRge->ITextRange_iface.lpVtbl = &trvt; txtRge->ref = 1; - txtRge->child.reole = reOle; + txtRge->child.reole = services; txtRge->start = start; txtRge->end = end; - list_add_head(&reOle->rangelist, &txtRge->child.entry); + list_add_head( &services->rangelist, &txtRge->child.entry ); *ppRange = &txtRge->ITextRange_iface; return S_OK; } @@ -4344,84 +4263,84 @@ static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, I static HRESULT WINAPI ITextDocument2Old_fnRange(ITextDocument2Old *iface, LONG cp1, LONG cp2, ITextRange **ppRange) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - TRACE("%p %p %d %d\n", This, ppRange, cp1, cp2); + TRACE("%p %p %d %d\n", services, ppRange, cp1, cp2); if (!ppRange) return E_INVALIDARG; - cp2range(This->editor, &cp1, &cp2); - return CreateITextRange(This, cp1, cp2, ppRange); + cp2range(services->editor, &cp1, &cp2); + return CreateITextRange(services, cp1, cp2, ppRange); } static HRESULT WINAPI ITextDocument2Old_fnRangeFromPoint(ITextDocument2Old *iface, LONG x, LONG y, ITextRange **ppRange) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); - FIXME("stub %p\n",This); + struct text_services *services = impl_from_ITextDocument2Old(iface); + FIXME("stub %p\n", services); return E_NOTIMPL; } /* ITextDocument2Old methods */ static HRESULT WINAPI ITextDocument2Old_fnAttachMsgFilter(ITextDocument2Old *iface, IUnknown *filter) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%p): stub\n", This, filter); + FIXME("(%p)->(%p): stub\n", services, filter); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnSetEffectColor(ITextDocument2Old *iface, LONG index, COLORREF cr) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%d, 0x%x): stub\n", This, index, cr); + FIXME("(%p)->(%d, 0x%x): stub\n", services, index, cr); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnGetEffectColor(ITextDocument2Old *iface, LONG index, COLORREF *cr) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%d, %p): stub\n", This, index, cr); + FIXME("(%p)->(%d, %p): stub\n", services, index, cr); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnGetCaretType(ITextDocument2Old *iface, LONG *type) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%p): stub\n", This, type); + FIXME("(%p)->(%p): stub\n", services, type); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnSetCaretType(ITextDocument2Old *iface, LONG type) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%d): stub\n", This, type); + FIXME("(%p)->(%d): stub\n", services, type); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnGetImmContext(ITextDocument2Old *iface, LONG *context) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%p): stub\n", This, context); + FIXME("(%p)->(%p): stub\n", services, context); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnReleaseImmContext(ITextDocument2Old *iface, LONG context) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%d): stub\n", This, context); + FIXME("(%p)->(%d): stub\n", services, context); return E_NOTIMPL; } @@ -4430,9 +4349,9 @@ static HRESULT WINAPI ITextDocument2Old_fnGetPreferredFont(ITextDocument2Old *if LONG options, LONG current_charrep, LONG current_fontsize, BSTR *bstr, LONG *pitch_family, LONG *new_fontsize) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%d, %d, %d, %d, %d, %p, %p, %p): stub\n", This, cp, charrep, options, current_charrep, + FIXME("(%p)->(%d, %d, %d, %d, %d, %p, %p, %p): stub\n", services, cp, charrep, options, current_charrep, current_fontsize, bstr, pitch_family, new_fontsize); return E_NOTIMPL; @@ -4440,18 +4359,18 @@ static HRESULT WINAPI ITextDocument2Old_fnGetPreferredFont(ITextDocument2Old *if static HRESULT WINAPI ITextDocument2Old_fnGetNotificationMode(ITextDocument2Old *iface, LONG *mode) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%p): stub\n", This, mode); + FIXME("(%p)->(%p): stub\n", services, mode); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnSetNotificationMode(ITextDocument2Old *iface, LONG mode) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(0x%x): stub\n", This, mode); + FIXME("(%p)->(0x%x): stub\n", services, mode); return E_NOTIMPL; } @@ -4459,95 +4378,96 @@ static HRESULT WINAPI ITextDocument2Old_fnSetNotificationMode(ITextDocument2Old static HRESULT WINAPI ITextDocument2Old_fnGetClientRect(ITextDocument2Old *iface, LONG type, LONG *left, LONG *top, LONG *right, LONG *bottom) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%d, %p, %p, %p, %p): stub\n", This, type, left, top, right, bottom); + FIXME("(%p)->(%d, %p, %p, %p, %p): stub\n", services, type, left, top, right, bottom); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnGetSelectionEx(ITextDocument2Old *iface, ITextSelection **selection) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%p): stub\n", This, selection); + FIXME("(%p)->(%p): stub\n", services, selection); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnGetWindow(ITextDocument2Old *iface, LONG *hwnd) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%p): stub\n", This, hwnd); + FIXME("(%p)->(%p): stub\n", services, hwnd); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnGetFEFlags(ITextDocument2Old *iface, LONG *flags) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%p): stub\n", This, flags); + FIXME("(%p)->(%p): stub\n", services, flags); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnUpdateWindow(ITextDocument2Old *iface) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p): stub\n", This); + FIXME("(%p): stub\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnCheckTextLimit(ITextDocument2Old *iface, LONG cch, LONG *exceed) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%d, %p): stub\n", This, cch, exceed); + FIXME("(%p)->(%d, %p): stub\n", services, cch, exceed); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnIMEInProgress(ITextDocument2Old *iface, LONG mode) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(0x%x): stub\n", This, mode); + FIXME("(%p)->(0x%x): stub\n", services, mode); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnSysBeep(ITextDocument2Old *iface) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p): stub\n", This); + FIXME("(%p): stub\n", services); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnUpdate(ITextDocument2Old *iface, LONG mode) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(0x%x): stub\n", This, mode); + FIXME("(%p)->(0x%x): stub\n", services, mode); return E_NOTIMPL; } static HRESULT WINAPI ITextDocument2Old_fnNotify(ITextDocument2Old *iface, LONG notify) { - IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface); + struct text_services *services = impl_from_ITextDocument2Old(iface); - FIXME("(%p)->(%d): stub\n", This, notify); + FIXME("(%p)->(%d): stub\n", services, notify); return E_NOTIMPL; } -static const ITextDocument2OldVtbl tdvt = { +const ITextDocument2OldVtbl text_doc2old_vtbl = +{ ITextDocument2Old_fnQueryInterface, ITextDocument2Old_fnAddRef, ITextDocument2Old_fnRelease, @@ -4603,7 +4523,7 @@ static HRESULT WINAPI ITextSelection_fnQueryInterface( REFIID riid, void **ppvObj) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); *ppvObj = NULL; if (IsEqualGUID(riid, &IID_IUnknown) @@ -4617,7 +4537,7 @@ static HRESULT WINAPI ITextSelection_fnQueryInterface( } else if (IsEqualGUID(riid, &IID_Igetrichole)) { - *ppvObj = This->reOle; + *ppvObj = This->services; return S_OK; } @@ -4626,13 +4546,13 @@ static HRESULT WINAPI ITextSelection_fnQueryInterface( static ULONG WINAPI ITextSelection_fnAddRef(ITextSelection *me) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); return InterlockedIncrement(&This->ref); } static ULONG WINAPI ITextSelection_fnRelease(ITextSelection *me) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ULONG ref = InterlockedDecrement(&This->ref); if (ref == 0) heap_free(This); @@ -4641,7 +4561,7 @@ static ULONG WINAPI ITextSelection_fnRelease(ITextSelection *me) static HRESULT WINAPI ITextSelection_fnGetTypeInfoCount(ITextSelection *me, UINT *pctinfo) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); TRACE("(%p)->(%p)\n", This, pctinfo); *pctinfo = 1; return S_OK; @@ -4650,7 +4570,7 @@ static HRESULT WINAPI ITextSelection_fnGetTypeInfoCount(ITextSelection *me, UINT static HRESULT WINAPI ITextSelection_fnGetTypeInfo(ITextSelection *me, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); HRESULT hr; TRACE("(%p)->(%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo); @@ -4664,7 +4584,7 @@ static HRESULT WINAPI ITextSelection_fnGetTypeInfo(ITextSelection *me, UINT iTIn static HRESULT WINAPI ITextSelection_fnGetIDsOfNames(ITextSelection *me, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ITypeInfo *ti; HRESULT hr; @@ -4688,7 +4608,7 @@ static HRESULT WINAPI ITextSelection_fnInvoke( EXCEPINFO *pExcepInfo, UINT *puArgErr) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ITypeInfo *ti; HRESULT hr; @@ -4704,20 +4624,20 @@ static HRESULT WINAPI ITextSelection_fnInvoke( /*** ITextRange methods ***/ static HRESULT WINAPI ITextSelection_fnGetText(ITextSelection *me, BSTR *pbstr) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ME_Cursor *start = NULL, *end = NULL; int nChars, endOfs; BOOL bEOP; TRACE("(%p)->(%p)\n", This, pbstr); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; if (!pbstr) return E_INVALIDARG; - ME_GetSelection(This->reOle->editor, &start, &end); + ME_GetSelection(This->services->editor, &start, &end); endOfs = ME_GetCursorOfs(end); nChars = endOfs - ME_GetCursorOfs(start); if (!nChars) @@ -4730,8 +4650,8 @@ static HRESULT WINAPI ITextSelection_fnGetText(ITextSelection *me, BSTR *pbstr) if (!*pbstr) return E_OUTOFMEMORY; - bEOP = (end->pRun->next->type == diTextEnd && endOfs > ME_GetTextLength(This->reOle->editor)); - ME_GetTextW(This->reOle->editor, *pbstr, nChars, start, nChars, FALSE, bEOP); + bEOP = (!para_next( para_next( end->para ) ) && endOfs > ME_GetTextLength(This->services->editor)); + ME_GetTextW(This->services->editor, *pbstr, nChars, start, nChars, FALSE, bEOP); TRACE("%s\n", wine_dbgstr_w(*pbstr)); return S_OK; @@ -4739,50 +4659,50 @@ static HRESULT WINAPI ITextSelection_fnGetText(ITextSelection *me, BSTR *pbstr) static HRESULT WINAPI ITextSelection_fnSetText(ITextSelection *me, BSTR str) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ME_TextEditor *editor; int len, to, from; TRACE("(%p)->(%s)\n", This, debugstr_w(str)); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; - editor = This->reOle->editor; + editor = This->services->editor; len = lstrlenW(str); ME_GetSelectionOfs(editor, &from, &to); ME_ReplaceSel(editor, FALSE, str, len); if (len < to - from) - textranges_update_ranges(This->reOle, from, len, RANGE_UPDATE_DELETE); + textranges_update_ranges(This->services, from, len, RANGE_UPDATE_DELETE); return S_OK; } static HRESULT WINAPI ITextSelection_fnGetChar(ITextSelection *me, LONG *pch) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ME_Cursor *start = NULL, *end = NULL; TRACE("(%p)->(%p)\n", This, pch); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; if (!pch) return E_INVALIDARG; - ME_GetSelection(This->reOle->editor, &start, &end); - return range_GetChar(This->reOle->editor, start, pch); + ME_GetSelection(This->services->editor, &start, &end); + return range_GetChar(This->services->editor, start, pch); } static HRESULT WINAPI ITextSelection_fnSetChar(ITextSelection *me, LONG ch) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%x): stub\n", This, ch); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -4790,12 +4710,12 @@ static HRESULT WINAPI ITextSelection_fnSetChar(ITextSelection *me, LONG ch) static HRESULT WINAPI ITextSelection_fnGetDuplicate(ITextSelection *me, ITextRange **range) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); LONG start, end; TRACE("(%p)->(%p)\n", This, range); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; if (!range) @@ -4803,16 +4723,16 @@ static HRESULT WINAPI ITextSelection_fnGetDuplicate(ITextSelection *me, ITextRan ITextSelection_GetStart(me, &start); ITextSelection_GetEnd(me, &end); - return CreateITextRange(This->reOle, start, end, range); + return CreateITextRange(This->services, start, end, range); } static HRESULT WINAPI ITextSelection_fnGetFormattedText(ITextSelection *me, ITextRange **range) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%p): stub\n", This, range); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -4820,11 +4740,11 @@ static HRESULT WINAPI ITextSelection_fnGetFormattedText(ITextSelection *me, ITex static HRESULT WINAPI ITextSelection_fnSetFormattedText(ITextSelection *me, ITextRange *range) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%p): stub\n", This, range); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; FIXME("not implemented\n"); @@ -4833,83 +4753,83 @@ static HRESULT WINAPI ITextSelection_fnSetFormattedText(ITextSelection *me, ITex static HRESULT WINAPI ITextSelection_fnGetStart(ITextSelection *me, LONG *pcpFirst) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); LONG lim; TRACE("(%p)->(%p)\n", This, pcpFirst); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; if (!pcpFirst) return E_INVALIDARG; - ME_GetSelectionOfs(This->reOle->editor, pcpFirst, &lim); + ME_GetSelectionOfs(This->services->editor, pcpFirst, &lim); return S_OK; } static HRESULT WINAPI ITextSelection_fnSetStart(ITextSelection *me, LONG value) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); LONG start, end; HRESULT hr; TRACE("(%p)->(%d)\n", This, value); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; - ME_GetSelectionOfs(This->reOle->editor, &start, &end); - hr = textrange_setstart(This->reOle, value, &start, &end); + ME_GetSelectionOfs(This->services->editor, &start, &end); + hr = textrange_setstart(This->services, value, &start, &end); if (hr == S_OK) - set_selection(This->reOle->editor, start, end); + set_selection(This->services->editor, start, end); return hr; } static HRESULT WINAPI ITextSelection_fnGetEnd(ITextSelection *me, LONG *pcpLim) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); LONG first; TRACE("(%p)->(%p)\n", This, pcpLim); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; if (!pcpLim) return E_INVALIDARG; - ME_GetSelectionOfs(This->reOle->editor, &first, pcpLim); + ME_GetSelectionOfs(This->services->editor, &first, pcpLim); return S_OK; } static HRESULT WINAPI ITextSelection_fnSetEnd(ITextSelection *me, LONG value) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); LONG start, end; HRESULT hr; TRACE("(%p)->(%d)\n", This, value); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; - ME_GetSelectionOfs(This->reOle->editor, &start, &end); - hr = textrange_setend(This->reOle, value, &start, &end); + ME_GetSelectionOfs(This->services->editor, &start, &end); + hr = textrange_setend(This->services, value, &start, &end); if (hr == S_OK) - set_selection(This->reOle->editor, start, end); + set_selection(This->services->editor, start, end); return hr; } static HRESULT WINAPI ITextSelection_fnGetFont(ITextSelection *me, ITextFont **font) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ITextRange *range = NULL; HRESULT hr; TRACE("(%p)->(%p)\n", This, font); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; if (!font) @@ -4923,7 +4843,7 @@ static HRESULT WINAPI ITextSelection_fnGetFont(ITextSelection *me, ITextFont **f static HRESULT WINAPI ITextSelection_fnSetFont(ITextSelection *me, ITextFont *font) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ITextRange *range = NULL; TRACE("(%p)->(%p)\n", This, font); @@ -4931,7 +4851,7 @@ static HRESULT WINAPI ITextSelection_fnSetFont(ITextSelection *me, ITextFont *fo if (!font) return E_INVALIDARG; - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range); @@ -4942,13 +4862,13 @@ static HRESULT WINAPI ITextSelection_fnSetFont(ITextSelection *me, ITextFont *fo static HRESULT WINAPI ITextSelection_fnGetPara(ITextSelection *me, ITextPara **para) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ITextRange *range = NULL; HRESULT hr; TRACE("(%p)->(%p)\n", This, para); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; if (!para) @@ -4962,11 +4882,11 @@ static HRESULT WINAPI ITextSelection_fnGetPara(ITextSelection *me, ITextPara **p static HRESULT WINAPI ITextSelection_fnSetPara(ITextSelection *me, ITextPara *para) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%p): stub\n", This, para); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; FIXME("not implemented\n"); @@ -4975,23 +4895,23 @@ static HRESULT WINAPI ITextSelection_fnSetPara(ITextSelection *me, ITextPara *pa static HRESULT WINAPI ITextSelection_fnGetStoryLength(ITextSelection *me, LONG *length) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); TRACE("(%p)->(%p)\n", This, length); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; - return textrange_get_storylength(This->reOle->editor, length); + return textrange_get_storylength(This->services->editor, length); } static HRESULT WINAPI ITextSelection_fnGetStoryType(ITextSelection *me, LONG *value) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); TRACE("(%p)->(%p)\n", This, value); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; if (!value) @@ -5003,31 +4923,31 @@ static HRESULT WINAPI ITextSelection_fnGetStoryType(ITextSelection *me, LONG *va static HRESULT WINAPI ITextSelection_fnCollapse(ITextSelection *me, LONG bStart) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); LONG start, end; HRESULT hres; TRACE("(%p)->(%d)\n", This, bStart); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; - ME_GetSelectionOfs(This->reOle->editor, &start, &end); + ME_GetSelectionOfs(This->services->editor, &start, &end); hres = range_Collapse(bStart, &start, &end); if (SUCCEEDED(hres)) - set_selection(This->reOle->editor, start, end); + set_selection(This->services->editor, start, end); return hres; } static HRESULT WINAPI ITextSelection_fnExpand(ITextSelection *me, LONG unit, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ITextRange *range = NULL; HRESULT hr; TRACE("(%p)->(%d %p)\n", This, unit, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range); @@ -5038,11 +4958,11 @@ static HRESULT WINAPI ITextSelection_fnExpand(ITextSelection *me, LONG unit, LON static HRESULT WINAPI ITextSelection_fnGetIndex(ITextSelection *me, LONG unit, LONG *index) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %p): stub\n", This, unit, index); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5051,11 +4971,11 @@ static HRESULT WINAPI ITextSelection_fnGetIndex(ITextSelection *me, LONG unit, L static HRESULT WINAPI ITextSelection_fnSetIndex(ITextSelection *me, LONG unit, LONG index, LONG extend) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %d %d): stub\n", This, unit, index, extend); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5063,11 +4983,11 @@ static HRESULT WINAPI ITextSelection_fnSetIndex(ITextSelection *me, LONG unit, L static HRESULT WINAPI ITextSelection_fnSetRange(ITextSelection *me, LONG anchor, LONG active) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %d): stub\n", This, anchor, active); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5075,7 +4995,7 @@ static HRESULT WINAPI ITextSelection_fnSetRange(ITextSelection *me, LONG anchor, static HRESULT WINAPI ITextSelection_fnInRange(ITextSelection *me, ITextRange *range, LONG *ret) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ITextSelection *selection = NULL; LONG start, end; @@ -5084,7 +5004,7 @@ static HRESULT WINAPI ITextSelection_fnInRange(ITextSelection *me, ITextRange *r if (ret) *ret = tomFalse; - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; if (!range) @@ -5102,11 +5022,11 @@ static HRESULT WINAPI ITextSelection_fnInRange(ITextSelection *me, ITextRange *r static HRESULT WINAPI ITextSelection_fnInStory(ITextSelection *me, ITextRange *range, LONG *ret) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%p %p): stub\n", This, range, ret); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5114,7 +5034,7 @@ static HRESULT WINAPI ITextSelection_fnInStory(ITextSelection *me, ITextRange *r static HRESULT WINAPI ITextSelection_fnIsEqual(ITextSelection *me, ITextRange *range, LONG *ret) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ITextSelection *selection = NULL; LONG start, end; @@ -5123,7 +5043,7 @@ static HRESULT WINAPI ITextSelection_fnIsEqual(ITextSelection *me, ITextRange *r if (ret) *ret = tomFalse; - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; if (!range) @@ -5141,11 +5061,11 @@ static HRESULT WINAPI ITextSelection_fnIsEqual(ITextSelection *me, ITextRange *r static HRESULT WINAPI ITextSelection_fnSelect(ITextSelection *me) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); TRACE("(%p)\n", This); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; /* nothing to do */ @@ -5155,68 +5075,88 @@ static HRESULT WINAPI ITextSelection_fnSelect(ITextSelection *me) static HRESULT WINAPI ITextSelection_fnStartOf(ITextSelection *me, LONG unit, LONG extend, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); + ITextRange *range = NULL; + HRESULT hr; - FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta); + TRACE("(%p)->(%d %d %p)\n", This, unit, extend, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; - return E_NOTIMPL; + ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range); + hr = textrange_startof(range, unit, extend, delta); + ITextRange_Release(range); + return hr; } static HRESULT WINAPI ITextSelection_fnEndOf(ITextSelection *me, LONG unit, LONG extend, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); + ITextRange *range = NULL; + HRESULT hr; - FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta); + TRACE("(%p)->(%d %d %p)\n", This, unit, extend, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; - return E_NOTIMPL; + ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range); + hr = textrange_endof(range, This->services->editor, unit, extend, delta); + ITextRange_Release(range); + return hr; } static HRESULT WINAPI ITextSelection_fnMove(ITextSelection *me, LONG unit, LONG count, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); + ITextRange *range = NULL; + HRESULT hr; - FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta); + TRACE("(%p)->(%d %d %p)\n", This, unit, count, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; - return E_NOTIMPL; + ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range); + hr = textrange_movestart(range, This->services->editor, unit, count, delta); + ITextRange_Release(range); + return hr; } static HRESULT WINAPI ITextSelection_fnMoveStart(ITextSelection *me, LONG unit, LONG count, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); + ITextRange *range = NULL; + HRESULT hr; - FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta); + TRACE("(%p)->(%d %d %p)\n", This, unit, count, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; - return E_NOTIMPL; + ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range); + hr = textrange_movestart(range, This->services->editor, unit, count, delta); + ITextRange_Release(range); + return hr; } static HRESULT WINAPI ITextSelection_fnMoveEnd(ITextSelection *me, LONG unit, LONG count, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); ITextRange *range = NULL; HRESULT hr; TRACE("(%p)->(%d %d %p)\n", This, unit, count, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range); - hr = textrange_moveend(range, unit, count, delta); + hr = textrange_moveend(range, This->services->editor, unit, count, delta); ITextRange_Release(range); return hr; } @@ -5224,11 +5164,11 @@ static HRESULT WINAPI ITextSelection_fnMoveEnd(ITextSelection *me, LONG unit, LO static HRESULT WINAPI ITextSelection_fnMoveWhile(ITextSelection *me, VARIANT *charset, LONG count, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5237,11 +5177,11 @@ static HRESULT WINAPI ITextSelection_fnMoveWhile(ITextSelection *me, VARIANT *ch static HRESULT WINAPI ITextSelection_fnMoveStartWhile(ITextSelection *me, VARIANT *charset, LONG count, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5250,11 +5190,11 @@ static HRESULT WINAPI ITextSelection_fnMoveStartWhile(ITextSelection *me, VARIAN static HRESULT WINAPI ITextSelection_fnMoveEndWhile(ITextSelection *me, VARIANT *charset, LONG count, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5263,11 +5203,11 @@ static HRESULT WINAPI ITextSelection_fnMoveEndWhile(ITextSelection *me, VARIANT static HRESULT WINAPI ITextSelection_fnMoveUntil(ITextSelection *me, VARIANT *charset, LONG count, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5276,11 +5216,11 @@ static HRESULT WINAPI ITextSelection_fnMoveUntil(ITextSelection *me, VARIANT *ch static HRESULT WINAPI ITextSelection_fnMoveStartUntil(ITextSelection *me, VARIANT *charset, LONG count, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5289,11 +5229,11 @@ static HRESULT WINAPI ITextSelection_fnMoveStartUntil(ITextSelection *me, VARIAN static HRESULT WINAPI ITextSelection_fnMoveEndUntil(ITextSelection *me, VARIANT *charset, LONG count, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5302,11 +5242,11 @@ static HRESULT WINAPI ITextSelection_fnMoveEndUntil(ITextSelection *me, VARIANT static HRESULT WINAPI ITextSelection_fnFindText(ITextSelection *me, BSTR text, LONG count, LONG flags, LONG *length) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; FIXME("not implemented\n"); @@ -5316,11 +5256,11 @@ static HRESULT WINAPI ITextSelection_fnFindText(ITextSelection *me, BSTR text, L static HRESULT WINAPI ITextSelection_fnFindTextStart(ITextSelection *me, BSTR text, LONG count, LONG flags, LONG *length) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5329,11 +5269,11 @@ static HRESULT WINAPI ITextSelection_fnFindTextStart(ITextSelection *me, BSTR te static HRESULT WINAPI ITextSelection_fnFindTextEnd(ITextSelection *me, BSTR text, LONG count, LONG flags, LONG *length) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5342,11 +5282,11 @@ static HRESULT WINAPI ITextSelection_fnFindTextEnd(ITextSelection *me, BSTR text static HRESULT WINAPI ITextSelection_fnDelete(ITextSelection *me, LONG unit, LONG count, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5354,35 +5294,45 @@ static HRESULT WINAPI ITextSelection_fnDelete(ITextSelection *me, LONG unit, LON static HRESULT WINAPI ITextSelection_fnCut(ITextSelection *me, VARIANT *v) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); + ITextRange *range = NULL; + HRESULT hr; - FIXME("(%p)->(%p): stub\n", This, v); + TRACE("(%p)->(%p): stub\n", This, v); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; - return E_NOTIMPL; + ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range); + hr = textrange_copy_or_cut(range, This->services->editor, TRUE, v); + ITextRange_Release(range); + return hr; } static HRESULT WINAPI ITextSelection_fnCopy(ITextSelection *me, VARIANT *v) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); + ITextRange *range = NULL; + HRESULT hr; - FIXME("(%p)->(%p): stub\n", This, v); + TRACE("(%p)->(%p)\n", This, v); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; - return E_NOTIMPL; + ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range); + hr = textrange_copy_or_cut(range, This->services->editor, FALSE, v); + ITextRange_Release(range); + return hr; } static HRESULT WINAPI ITextSelection_fnPaste(ITextSelection *me, VARIANT *v, LONG format) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s %x): stub\n", This, debugstr_variant(v), format); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5391,11 +5341,11 @@ static HRESULT WINAPI ITextSelection_fnPaste(ITextSelection *me, VARIANT *v, LON static HRESULT WINAPI ITextSelection_fnCanPaste(ITextSelection *me, VARIANT *v, LONG format, LONG *ret) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s %x %p): stub\n", This, debugstr_variant(v), format, ret); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5403,11 +5353,11 @@ static HRESULT WINAPI ITextSelection_fnCanPaste(ITextSelection *me, VARIANT *v, static HRESULT WINAPI ITextSelection_fnCanEdit(ITextSelection *me, LONG *ret) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%p): stub\n", This, ret); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5415,11 +5365,11 @@ static HRESULT WINAPI ITextSelection_fnCanEdit(ITextSelection *me, LONG *ret) static HRESULT WINAPI ITextSelection_fnChangeCase(ITextSelection *me, LONG type) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d): stub\n", This, type); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5427,11 +5377,11 @@ static HRESULT WINAPI ITextSelection_fnChangeCase(ITextSelection *me, LONG type) static HRESULT WINAPI ITextSelection_fnGetPoint(ITextSelection *me, LONG type, LONG *cx, LONG *cy) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %p %p): stub\n", This, type, cx, cy); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5440,11 +5390,11 @@ static HRESULT WINAPI ITextSelection_fnGetPoint(ITextSelection *me, LONG type, L static HRESULT WINAPI ITextSelection_fnSetPoint(ITextSelection *me, LONG x, LONG y, LONG type, LONG extend) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %d %d %d): stub\n", This, x, y, type, extend); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5452,11 +5402,11 @@ static HRESULT WINAPI ITextSelection_fnSetPoint(ITextSelection *me, LONG x, LONG static HRESULT WINAPI ITextSelection_fnScrollIntoView(ITextSelection *me, LONG value) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d): stub\n", This, value); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5464,11 +5414,11 @@ static HRESULT WINAPI ITextSelection_fnScrollIntoView(ITextSelection *me, LONG v static HRESULT WINAPI ITextSelection_fnGetEmbeddedObject(ITextSelection *me, IUnknown **ppv) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%p): stub\n", This, ppv); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5477,11 +5427,11 @@ static HRESULT WINAPI ITextSelection_fnGetEmbeddedObject(ITextSelection *me, IUn /*** ITextSelection methods ***/ static HRESULT WINAPI ITextSelection_fnGetFlags(ITextSelection *me, LONG *flags) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%p): stub\n", This, flags); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5489,11 +5439,11 @@ static HRESULT WINAPI ITextSelection_fnGetFlags(ITextSelection *me, LONG *flags) static HRESULT WINAPI ITextSelection_fnSetFlags(ITextSelection *me, LONG flags) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%x): stub\n", This, flags); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5501,11 +5451,11 @@ static HRESULT WINAPI ITextSelection_fnSetFlags(ITextSelection *me, LONG flags) static HRESULT WINAPI ITextSelection_fnGetType(ITextSelection *me, LONG *type) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%p): stub\n", This, type); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5514,11 +5464,11 @@ static HRESULT WINAPI ITextSelection_fnGetType(ITextSelection *me, LONG *type) static HRESULT WINAPI ITextSelection_fnMoveLeft(ITextSelection *me, LONG unit, LONG count, LONG extend, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %d %d %p): stub\n", This, unit, count, extend, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5527,11 +5477,11 @@ static HRESULT WINAPI ITextSelection_fnMoveLeft(ITextSelection *me, LONG unit, L static HRESULT WINAPI ITextSelection_fnMoveRight(ITextSelection *me, LONG unit, LONG count, LONG extend, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %d %d %p): stub\n", This, unit, count, extend, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5540,11 +5490,11 @@ static HRESULT WINAPI ITextSelection_fnMoveRight(ITextSelection *me, LONG unit, static HRESULT WINAPI ITextSelection_fnMoveUp(ITextSelection *me, LONG unit, LONG count, LONG extend, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %d %d %p): stub\n", This, unit, count, extend, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5553,11 +5503,11 @@ static HRESULT WINAPI ITextSelection_fnMoveUp(ITextSelection *me, LONG unit, LON static HRESULT WINAPI ITextSelection_fnMoveDown(ITextSelection *me, LONG unit, LONG count, LONG extend, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %d %d %p): stub\n", This, unit, count, extend, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5566,11 +5516,11 @@ static HRESULT WINAPI ITextSelection_fnMoveDown(ITextSelection *me, LONG unit, L static HRESULT WINAPI ITextSelection_fnHomeKey(ITextSelection *me, LONG unit, LONG extend, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5579,11 +5529,11 @@ static HRESULT WINAPI ITextSelection_fnHomeKey(ITextSelection *me, LONG unit, LO static HRESULT WINAPI ITextSelection_fnEndKey(ITextSelection *me, LONG unit, LONG extend, LONG *delta) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5591,11 +5541,11 @@ static HRESULT WINAPI ITextSelection_fnEndKey(ITextSelection *me, LONG unit, LON static HRESULT WINAPI ITextSelection_fnTypeText(ITextSelection *me, BSTR text) { - ITextSelectionImpl *This = impl_from_ITextSelection(me); + struct text_selection *This = impl_from_ITextSelection(me); FIXME("(%p)->(%s): stub\n", This, debugstr_w(text)); - if (!This->reOle) + if (!This->services) return CO_E_RELEASED; return E_NOTIMPL; @@ -5672,46 +5622,18 @@ static const ITextSelectionVtbl tsvt = { ITextSelection_fnTypeText }; -static ITextSelectionImpl * -CreateTextSelection(IRichEditOleImpl *reOle) +static struct text_selection *text_selection_create(struct text_services *services) { - ITextSelectionImpl *txtSel = heap_alloc(sizeof *txtSel); + struct text_selection *txtSel = heap_alloc(sizeof *txtSel); if (!txtSel) return NULL; txtSel->ITextSelection_iface.lpVtbl = &tsvt; txtSel->ref = 1; - txtSel->reOle = reOle; + txtSel->services = services; return txtSel; } -LRESULT CreateIRichEditOle(IUnknown *outer_unk, ME_TextEditor *editor, LPVOID *ppvObj) -{ - IRichEditOleImpl *reo; - - reo = heap_alloc(sizeof(IRichEditOleImpl)); - if (!reo) - return 0; - - reo->IUnknown_inner.lpVtbl = &reo_unk_vtbl; - reo->IRichEditOle_iface.lpVtbl = &revt; - reo->ITextDocument2Old_iface.lpVtbl = &tdvt; - reo->ref = 1; - reo->editor = editor; - reo->txtSel = NULL; - - TRACE("Created %p\n",reo); - list_init(&reo->rangelist); - list_init(&reo->clientsites); - if (outer_unk) - reo->outer_unk = outer_unk; - else - reo->outer_unk = &reo->IUnknown_inner; - *ppvObj = &reo->IUnknown_inner; - - return 1; -} - static void convert_sizel(const ME_Context *c, const SIZEL* szl, SIZE* sz) { /* sizel is in .01 millimeters, sz in pixels */ @@ -5801,7 +5723,7 @@ void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize) } } -void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run *run, BOOL selected) +void draw_ole( ME_Context *c, int x, int y, ME_Run *run, BOOL selected ) { IDataObject* ido; FORMATETC fmt; @@ -5927,3 +5849,21 @@ void ME_CopyReObject(REOBJECT *dst, const REOBJECT *src, DWORD flags) IOleClientSite_AddRef(dst->polesite); } } + +void richole_release_children( struct text_services *services ) +{ + ITextRangeImpl *range; + IOleClientSiteImpl *site; + + if (services->text_selection) + { + services->text_selection->services = NULL; + ITextSelection_Release( &services->text_selection->ITextSelection_iface ); + } + + LIST_FOR_EACH_ENTRY( range, &services->rangelist, ITextRangeImpl, child.entry ) + range->child.reole = NULL; + + LIST_FOR_EACH_ENTRY( site, &services->clientsites, IOleClientSiteImpl, child.entry ) + site->child.reole = NULL; +} diff --git a/dll/win32/riched20/row.c b/dll/win32/riched20/row.c index 1bf153f6ca9..715d2adbf62 100644 --- a/dll/win32/riched20/row.c +++ b/dll/win32/riched20/row.c @@ -24,69 +24,132 @@ #include "editor.h" -/* I'm sure these functions would simplify some code in caret ops etc, - * I just didn't remember them when I wrote that code - */ +ME_Row *row_next( ME_Row *row ) +{ + ME_DisplayItem *item; -ME_DisplayItem *ME_RowStart(ME_DisplayItem *item) { - return ME_FindItemBackOrHere(item, diStartRow); + item = ME_FindItemFwd( row_get_di( row ), diStartRowOrParagraphOrEnd ); + if (!item || item->type != diStartRow) return NULL; + return &item->member.row; } -/* -ME_DisplayItem *ME_RowEnd(ME_DisplayItem *item) { - ME_DisplayItem *item2 = ME_FindItemFwd(item, diStartRowOrParagraphOrEnd); - if (!item2) return NULL; - return ME_FindItemBack(item, diRun); +ME_Row *row_next_all_paras( ME_Row *row ) +{ + ME_DisplayItem *item; + + item = ME_FindItemFwd( row_get_di( row ), diStartRow ); + if (!item) return NULL; + return &item->member.row; +} + +ME_Row *row_prev_all_paras( ME_Row *row ) +{ + ME_DisplayItem *item; + + item = ME_FindItemBack( row_get_di( row ), diStartRow ); + if (!item) return NULL; + return &item->member.row; +} + +ME_Run *row_first_run( ME_Row *row ) +{ + ME_DisplayItem *item; + + item = ME_FindItemFwd( row_get_di( row ), diRunOrStartRow ); + assert( item->type == diRun ); + return &item->member.run; +} + +ME_Run *row_next_run( ME_Row *row, ME_Run *run ) +{ + ME_DisplayItem *item; + + assert( row == &ME_FindItemBack( run_get_di( run ), diStartRow )->member.row ); + + item = ME_FindItemFwd( run_get_di( run ), diRunOrStartRow ); + if (!item || item->type == diStartRow) return NULL; + return &item->member.run; +} + +ME_Row *row_from_cursor( ME_Cursor *cursor ) +{ + ME_DisplayItem *item; + + item = ME_FindItemBack( run_get_di( cursor->run ), diStartRow ); + return &item->member.row; } -*/ -ME_DisplayItem * -ME_FindRowWithNumber(ME_TextEditor *editor, int nRow) +void row_first_cursor( ME_Row *row, ME_Cursor *cursor ) { - ME_DisplayItem *item = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph); - int nCount = 0; - - while (item->type == diParagraph && - nCount + item->member.para.nRows <= nRow) - { - nCount += item->member.para.nRows; - item = item->member.para.next_para; - } - if (item->type != diParagraph) - return NULL; - for (item = ME_FindItemFwd(item, diStartRow); item && nCount < nRow; nCount++) - item = ME_FindItemFwd(item, diStartRow); - return item; + ME_DisplayItem *item; + + item = ME_FindItemFwd( row_get_di( row ), diRun ); + cursor->run = &item->member.run; + cursor->para = cursor->run->para; + cursor->nOffset = 0; +} + +void row_end_cursor( ME_Row *row, ME_Cursor *cursor, BOOL include_eop ) +{ + ME_DisplayItem *item, *run; + + item = ME_FindItemFwd( row_get_di( row ), diStartRowOrParagraphOrEnd ); + run = ME_FindItemBack( item, diRun ); + cursor->run = &run->member.run; + cursor->para = cursor->run->para; + cursor->nOffset = (item->type == diStartRow || include_eop) ? cursor->run->len : 0; +} + +ME_Paragraph *row_para( ME_Row *row ) +{ + ME_Cursor cursor; + + row_first_cursor( row, &cursor ); + return cursor.para; +} + +ME_Row *row_from_row_number( ME_TextEditor *editor, int row_num ) +{ + ME_Paragraph *para = editor_first_para( editor ); + ME_Row *row; + int count = 0; + + while (para_next( para ) && count + para->nRows <= row_num) + { + count += para->nRows; + para = para_next( para ); + } + if (!para_next( para )) return NULL; + + for (row = para_first_row( para ); row && count < row_num; count++) + row = row_next( row ); + + return row; } -int -ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs) +int row_number_from_char_ofs( ME_TextEditor *editor, int ofs ) { - ME_DisplayItem *item = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph); - int nRow = 0; - - while (item->type == diParagraph && - item->member.para.next_para->member.para.nCharOfs <= nOfs) - { - nRow += item->member.para.nRows; - item = item->member.para.next_para; - } - if (item->type == diParagraph) - { - ME_DisplayItem *next_para = item->member.para.next_para; - - nOfs -= item->member.para.nCharOfs; - item = ME_FindItemFwd(item, diRun); - while ((item = ME_FindItemFwd(item, diStartRowOrParagraph)) != NULL) + ME_Paragraph *para = editor_first_para( editor ); + ME_Row *row; + ME_Cursor cursor; + int row_num = 0; + + while (para_next( para ) && para_next( para )->nCharOfs <= ofs) { - if (item == next_para) - break; - item = ME_FindItemFwd(item, diRun); - if (item->member.run.nCharOfs > nOfs) - break; - nRow++; + row_num += para->nRows; + para = para_next( para ); } - } - return nRow; + + if (para_next( para )) + { + for (row = para_first_row( para ); row; row = row_next( row )) + { + row_end_cursor( row, &cursor, TRUE ); + if (ME_GetCursorOfs( &cursor ) > ofs ) break; + row_num++; + } + } + + return row_num; } diff --git a/dll/win32/riched20/rtf.h b/dll/win32/riched20/rtf.h index 66d88b55da9..35a0ee878e9 100644 --- a/dll/win32/riched20/rtf.h +++ b/dll/win32/riched20/rtf.h @@ -1035,10 +1035,10 @@ struct RTFTable int numCellsInserted; /* v4.1 */ - /* tableRowStart may be the start row paragraph of the table row, + /* row_start may be the start row paragraph of the table row, * or it may store the end of the previous row if it may still be * continued, otherwise NULL is stored. */ - ME_DisplayItem *tableRowStart; + ME_Paragraph *row_start; /* Table definitions are stored as a stack to support nested tables. */ RTFTable *parent; diff --git a/dll/win32/riched20/run.c b/dll/win32/riched20/run.c index 3912384451c..51e768f8441 100644 --- a/dll/win32/riched20/run.c +++ b/dll/win32/riched20/run.c @@ -27,6 +27,100 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); WINE_DECLARE_DEBUG_CHANNEL(richedit_check); WINE_DECLARE_DEBUG_CHANNEL(richedit_lists); +BOOL cursor_next_run( ME_Cursor *cursor, BOOL all_para ) +{ + ME_DisplayItem *p = run_get_di( cursor->run )->next; + + while (p->type != diTextEnd) + { + if (p->type == diParagraph && !all_para) return FALSE; + else if (p->type == diRun) + { + cursor->run = &p->member.run; + cursor->para = cursor->run->para; + cursor->nOffset = 0; + return TRUE; + } + p = p->next; + } + return FALSE; +} + +BOOL cursor_prev_run( ME_Cursor *cursor, BOOL all_para ) +{ + ME_DisplayItem *p = run_get_di( cursor->run )->prev; + + while (p->type != diTextStart) + { + if (p->type == diParagraph && !all_para) return FALSE; + else if (p->type == diRun) + { + cursor->run = &p->member.run; + cursor->para = cursor->run->para; + cursor->nOffset = 0; + return TRUE; + } + p = p->prev; + } + return FALSE; +} + +ME_Run *run_next( ME_Run *run ) +{ + ME_Cursor cursor; + + cursor.run = run; + cursor.para = run->para; + cursor.nOffset = 0; + + if (cursor_next_run( &cursor, FALSE )) + return cursor.run; + + return NULL; +} + +ME_Run *run_prev( ME_Run *run ) +{ + ME_Cursor cursor; + + cursor.run = run; + cursor.para = run->para; + cursor.nOffset = 0; + + if (cursor_prev_run( &cursor, FALSE )) + return cursor.run; + + return NULL; +} + +ME_Run *run_next_all_paras( ME_Run *run ) +{ + ME_Cursor cursor; + + cursor.run = run; + cursor.para = run->para; + cursor.nOffset = 0; + + if (cursor_next_run( &cursor, TRUE )) + return cursor.run; + + return NULL; +} + +ME_Run *run_prev_all_paras( ME_Run *run ) +{ + ME_Cursor cursor; + + cursor.run = run; + cursor.para = run->para; + cursor.nOffset = 0; + + if (cursor_prev_run( &cursor, TRUE )) + return cursor.run; + + return NULL; +} + /****************************************************************************** * ME_CanJoinRuns * @@ -43,54 +137,32 @@ BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2) return TRUE; } -void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift) -{ - p = ME_FindItemFwd(p, diRunOrParagraphOrEnd); - assert(p); - ME_PropagateCharOffset(p, shift); -} - /****************************************************************************** - * ME_PropagateCharOffsets + * editor_propagate_char_ofs * * Shifts (increases or decreases) character offset (relative to beginning of - * the document) of the part of the text starting from given place. + * the document) of the part of the text starting from given place. + * Call with only one of para or run non-NULL. */ -void ME_PropagateCharOffset(ME_DisplayItem *p, int shift) +void editor_propagate_char_ofs( ME_Paragraph *para, ME_Run *run, int shift ) { - /* Runs in one paragraph contain character offset relative to their owning - * paragraph. If we start the shifting from the run, we need to shift - * all the relative offsets until the end of the paragraph - */ - if (p->type == diRun) /* propagate in all runs in this para */ - { - TRACE("PropagateCharOffset(%s, %d)\n", debugstr_run( &p->member.run ), shift); - do { - p->member.run.nCharOfs += shift; - assert(p->member.run.nCharOfs >= 0); - p = ME_FindItemFwd(p, diRunOrParagraphOrEnd); - } while(p->type == diRun); - } - /* Runs in next paragraphs don't need their offsets updated, because they, - * again, those offsets are relative to their respective paragraphs. - * Instead of that, we're updating paragraphs' character offsets. - */ - if (p->type == diParagraph) /* propagate in all next paras */ - { - do { - p->member.para.nCharOfs += shift; - assert(p->member.para.nCharOfs >= 0); - p = p->member.para.next_para; - } while(p->type == diParagraph); - } - /* diTextEnd also has character offset in it, which makes finding text length - * easier. But it needs to be up to date first. - */ - if (p->type == diTextEnd) - { - p->member.para.nCharOfs += shift; - assert(p->member.para.nCharOfs >= 0); - } + assert( !para ^ !run ); + + if (run) + { + para = para_next( run->para ); + do + { + run->nCharOfs += shift; + run = run_next( run ); + } while (run); + } + + do + { + para->nCharOfs += shift; + para = para_next( para ); + } while (para); } /****************************************************************************** @@ -147,231 +219,208 @@ void ME_CheckCharOffsets(ME_TextEditor *editor) } /****************************************************************************** - * ME_CharOfsFromRunOfs + * run_char_ofs * - * Converts a character position relative to the start of the run, to a + * Converts a character position relative to the start of the run to a * character position relative to the start of the document. - * Kind of a "local to global" offset conversion. */ -int ME_CharOfsFromRunOfs(ME_TextEditor *editor, const ME_DisplayItem *pPara, - const ME_DisplayItem *pRun, int nOfs) + +int run_char_ofs( ME_Run *run, int ofs ) { - assert(pRun && pRun->type == diRun); - assert(pPara && pPara->type == diParagraph); - return pPara->member.para.nCharOfs + pRun->member.run.nCharOfs + nOfs; + return run->para->nCharOfs + run->nCharOfs + ofs; } /****************************************************************************** - * ME_CursorFromCharOfs + * cursor_from_char_ofs * * Converts a character offset (relative to the start of the document) to * a cursor structure (which contains a run and a position relative to that * run). */ -void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor) +void cursor_from_char_ofs( ME_TextEditor *editor, int char_ofs, ME_Cursor *cursor ) { - ME_RunOfsFromCharOfs(editor, nCharOfs, &pCursor->pPara, - &pCursor->pRun, &pCursor->nOffset); -} + ME_Paragraph *para; + ME_Run *run; -/****************************************************************************** - * ME_RunOfsFromCharOfs - * - * Find a run and relative character offset given an absolute character offset - * (absolute offset being an offset relative to the start of the document). - * Kind of a "global to local" offset conversion. - */ -void ME_RunOfsFromCharOfs(ME_TextEditor *editor, - int nCharOfs, - ME_DisplayItem **ppPara, - ME_DisplayItem **ppRun, - int *pOfs) -{ - ME_DisplayItem *item, *next_item; - int endOfs = nCharOfs, len = ME_GetTextLength(editor); + char_ofs = min( max( char_ofs, 0 ), ME_GetTextLength( editor ) ); - nCharOfs = max(nCharOfs, 0); - nCharOfs = min(nCharOfs, len); + /* Find the paragraph at the offset. */ + for (para = editor_first_para( editor ); + para_next( para )->nCharOfs <= char_ofs; + para = para_next( para )) + ; - /* Find the paragraph at the offset. */ - next_item = editor->pBuffer->pFirst->member.para.next_para; - do { - item = next_item; - next_item = item->member.para.next_para; - } while (next_item->member.para.nCharOfs <= nCharOfs); - assert(item->type == diParagraph); - nCharOfs -= item->member.para.nCharOfs; - if (ppPara) *ppPara = item; - - /* Find the run at the offset. */ - next_item = ME_FindItemFwd(item, diRun); - do { - item = next_item; - next_item = ME_FindItemFwd(item, diRunOrParagraphOrEnd); - } while (next_item->type == diRun && - next_item->member.run.nCharOfs <= nCharOfs); - assert(item->type == diRun); - nCharOfs -= item->member.run.nCharOfs; - - if (ppRun) *ppRun = item; - if (pOfs) { - if (((*ppRun)->member.run.nFlags & MERF_ENDPARA) && endOfs > len) - *pOfs = (*ppRun)->member.run.len; - else *pOfs = nCharOfs; - } + char_ofs -= para->nCharOfs; + + /* Find the run at the offset. */ + for (run = para_first_run( para ); + run_next( run ) && run_next( run )->nCharOfs <= char_ofs; + run = run_next( run )) + ; + + char_ofs -= run->nCharOfs; + + cursor->para = para; + cursor->run = run; + cursor->nOffset = char_ofs; } /****************************************************************************** - * ME_JoinRuns + * run_join * * Merges two adjacent runs, the one given as a parameter and the next one. */ -void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) +void run_join( ME_TextEditor *editor, ME_Run *run ) { - ME_DisplayItem *pNext = p->next; + ME_Run *next = run_next( run ); int i; - assert(p->type == diRun && pNext->type == diRun); - assert(p->member.run.nCharOfs != -1); - mark_para_rewrap(editor, ME_GetParagraph(p)); + + assert( run ); + assert( run->nCharOfs != -1 ); + para_mark_rewrap( editor, run->para ); /* Update all cursors so that they don't contain the soon deleted run */ - for (i=0; inCursors; i++) { - if (editor->pCursors[i].pRun == pNext) { - editor->pCursors[i].pRun = p; - editor->pCursors[i].nOffset += p->member.run.len; + for (i = 0; i < editor->nCursors; i++) + { + if (editor->pCursors[i].run == next) + { + editor->pCursors[i].run = run; + editor->pCursors[i].nOffset += run->len; } } - p->member.run.len += pNext->member.run.len; - ME_Remove(pNext); - ME_DestroyDisplayItem(pNext); - ME_UpdateRunFlags(editor, &p->member.run); - ME_CheckCharOffsets(editor); + run->len += next->len; + ME_Remove( run_get_di( next ) ); + ME_DestroyDisplayItem( run_get_di( next ) ); + ME_UpdateRunFlags( editor, run ); + ME_CheckCharOffsets( editor ); } /****************************************************************************** - * ME_SplitRunSimple + * run_split * * Does the most basic job of splitting a run into two - it does not * update the positions and extents. */ -ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_Cursor *cursor) +ME_Run *run_split( ME_TextEditor *editor, ME_Cursor *cursor ) { - ME_DisplayItem *run = cursor->pRun; - ME_DisplayItem *new_run; - int i; - int nOffset = cursor->nOffset; - - assert(!(run->member.run.nFlags & MERF_NONTEXT)); - - new_run = ME_MakeRun(run->member.run.style, - run->member.run.nFlags & MERF_SPLITMASK); - new_run->member.run.nCharOfs = run->member.run.nCharOfs + nOffset; - new_run->member.run.len = run->member.run.len - nOffset; - new_run->member.run.para = run->member.run.para; - run->member.run.len = nOffset; - cursor->pRun = new_run; - cursor->nOffset = 0; - - ME_InsertBefore(run->next, new_run); - - ME_UpdateRunFlags(editor, &run->member.run); - ME_UpdateRunFlags(editor, &new_run->member.run); - for (i = 0; i < editor->nCursors; i++) { - if (editor->pCursors[i].pRun == run && - editor->pCursors[i].nOffset >= nOffset) { - editor->pCursors[i].pRun = new_run; - editor->pCursors[i].nOffset -= nOffset; + ME_Run *run = cursor->run, *new_run; + int i; + int nOffset = cursor->nOffset; + + assert( !(run->nFlags & MERF_NONTEXT) ); + + new_run = run_create( run->style, run->nFlags & MERF_SPLITMASK ); + new_run->nCharOfs = run->nCharOfs + nOffset; + new_run->len = run->len - nOffset; + new_run->para = run->para; + run->len = nOffset; + cursor->run = new_run; + cursor->nOffset = 0; + + ME_InsertBefore( run_get_di( run )->next, run_get_di( new_run ) ); + + ME_UpdateRunFlags( editor, run ); + ME_UpdateRunFlags( editor, new_run ); + for (i = 0; i < editor->nCursors; i++) + { + if (editor->pCursors[i].run == run && + editor->pCursors[i].nOffset >= nOffset) + { + editor->pCursors[i].run = new_run; + editor->pCursors[i].nOffset -= nOffset; + } } - } - mark_para_rewrap(editor, cursor->pPara); - return run; + para_mark_rewrap( editor, run->para ); + return run; } /****************************************************************************** - * ME_MakeRun + * run_create * * A helper function to create run structures quickly. */ -ME_DisplayItem *ME_MakeRun(ME_Style *s, int nFlags) +ME_Run *run_create( ME_Style *s, int flags ) { - ME_DisplayItem *item = ME_MakeDI(diRun); - item->member.run.style = s; - item->member.run.reobj = NULL; - item->member.run.nFlags = nFlags; - item->member.run.nCharOfs = -1; - item->member.run.len = 0; - item->member.run.para = NULL; - item->member.run.num_glyphs = 0; - item->member.run.max_glyphs = 0; - item->member.run.glyphs = NULL; - item->member.run.vis_attrs = NULL; - item->member.run.advances = NULL; - item->member.run.offsets = NULL; - item->member.run.max_clusters = 0; - item->member.run.clusters = NULL; - ME_AddRefStyle(s); - return item; + ME_DisplayItem *item = ME_MakeDI( diRun ); + ME_Run *run = &item->member.run; + + if (!item) return NULL; + + ME_AddRefStyle( s ); + run->style = s; + run->reobj = NULL; + run->nFlags = flags; + run->nCharOfs = -1; + run->len = 0; + run->para = NULL; + run->num_glyphs = 0; + run->max_glyphs = 0; + run->glyphs = NULL; + run->vis_attrs = NULL; + run->advances = NULL; + run->offsets = NULL; + run->max_clusters = 0; + run->clusters = NULL; + return run; } /****************************************************************************** - * ME_InsertRunAtCursor + * run_insert * * Inserts a new run with given style, flags and content at a given position, * which is passed as a cursor structure (which consists of a run and * a run-relative character offset). */ -ME_DisplayItem * -ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style, - const WCHAR *str, int len, int flags) +ME_Run *run_insert( ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style, + const WCHAR *str, int len, int flags ) { - ME_DisplayItem *pDI, *insert_before = cursor->pRun, *prev; + ME_Run *insert_before = cursor->run, *run, *prev; if (cursor->nOffset) { - if (cursor->nOffset == cursor->pRun->member.run.len) + if (cursor->nOffset == insert_before->len) { - insert_before = ME_FindItemFwd( cursor->pRun, diRun ); - if (!insert_before) insert_before = cursor->pRun; /* Always insert before the final eop run */ + insert_before = run_next_all_paras( insert_before ); + if (!insert_before) insert_before = cursor->run; /* Always insert before the final eop run */ } else { - ME_SplitRunSimple( editor, cursor ); - insert_before = cursor->pRun; + run_split( editor, cursor ); + insert_before = cursor->run; } } - add_undo_delete_run( editor, insert_before->member.run.para->nCharOfs + - insert_before->member.run.nCharOfs, len ); + add_undo_delete_run( editor, insert_before->para->nCharOfs + insert_before->nCharOfs, len ); - pDI = ME_MakeRun(style, flags); - pDI->member.run.nCharOfs = insert_before->member.run.nCharOfs; - pDI->member.run.len = len; - pDI->member.run.para = insert_before->member.run.para; - ME_InsertString( pDI->member.run.para->text, pDI->member.run.nCharOfs, str, len ); - ME_InsertBefore( insert_before, pDI ); + run = run_create( style, flags ); + run->nCharOfs = insert_before->nCharOfs; + run->len = len; + run->para = insert_before->para; + 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); - ME_PropagateCharOffset( insert_before, len ); - mark_para_rewrap(editor, get_di_from_para(insert_before->member.run.para)); + editor_propagate_char_ofs( 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 */ - prev = ME_FindItemBack( pDI, diRun ); + prev = run_prev_all_paras( run ); if (prev) { int i; for (i = 0; i < editor->nCursors; i++) { - if (editor->pCursors[i].pRun == prev && - editor->pCursors[i].nOffset == prev->member.run.len) + if (editor->pCursors[i].run == prev && + editor->pCursors[i].nOffset == prev->len) { - editor->pCursors[i].pRun = pDI; + editor->pCursors[i].run = run; editor->pCursors[i].nOffset = len; } } } - return pDI; + return run; } static BOOL run_is_splittable( const ME_Run *run ) @@ -494,9 +543,9 @@ int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BO return closest ? cp + trailing : cp; } - if (c->editor->cPasswordMask) + if (c->editor->password_char) { - mask_text = ME_MakeStringR( c->editor->cPasswordMask, run->len ); + mask_text = ME_MakeStringR( c->editor->password_char, run->len ); str = mask_text->szData; } else @@ -522,10 +571,12 @@ int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, B { ME_Context c; int ret; + HDC hdc = ITextHost_TxGetDC( editor->texthost ); - ME_InitContext( &c, editor, ITextHost_TxGetDC( editor->texthost ) ); + ME_InitContext( &c, editor, hdc ); ret = ME_CharFromPointContext( &c, cx, run, closest, visual_order ); ME_DestroyContext(&c); + ITextHost_TxReleaseDC( editor->texthost, hdc ); return ret; } @@ -577,9 +628,9 @@ int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visua if (visual_order && pRun->script_analysis.fRTL) x = pRun->nWidth - x - 1; return x; } - if (c->editor->cPasswordMask) + if (c->editor->password_char) { - mask_text = ME_MakeStringR(c->editor->cPasswordMask, pRun->len); + mask_text = ME_MakeStringR( c->editor->password_char, pRun->len ); str = mask_text->szData; } else @@ -599,10 +650,12 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visu { ME_Context c; int ret; + HDC hdc = ITextHost_TxGetDC( editor->texthost ); - ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost)); + ME_InitContext( &c, editor, hdc ); ret = ME_PointFromCharContext( &c, pRun, nOffset, visual_order ); ME_DestroyContext(&c); + ITextHost_TxReleaseDC( editor->texthost, hdc ); return ret; } @@ -616,7 +669,6 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visu SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, int nLen, int startx, int *pAscent, int *pDescent) { - static const WCHAR spaceW[] = {' ',0}; SIZE size; nLen = min( nLen, run->len ); @@ -624,15 +676,15 @@ SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, i if (run->nFlags & MERF_ENDPARA) { nLen = min( nLen, 1 ); - ME_GetTextExtent(c, spaceW, nLen, run->style, &size); + ME_GetTextExtent( c, L" ", nLen, run->style, &size ); } else if (para->nFlags & MEPF_COMPLEX) { size.cx = run->nWidth; } - else if (c->editor->cPasswordMask) + else if (c->editor->password_char) { - ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,nLen); + ME_String *szMasked = ME_MakeStringR( c->editor->password_char, nLen ); ME_GetTextExtent(c, szMasked->szData, nLen,run->style, &size); ME_DestroyString(szMasked); } @@ -699,7 +751,7 @@ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) { ME_Style *s; if (!editor->pBuffer->pCharStyle) - editor->pBuffer->pCharStyle = ME_GetInsertStyle(editor, 0); + editor->pBuffer->pCharStyle = style_get_insert_style( editor, editor->pCursors ); s = ME_ApplyStyle(editor, editor->pBuffer->pCharStyle, pFmt); ME_ReleaseStyle(editor->pBuffer->pCharStyle); editor->pBuffer->pCharStyle = s; @@ -722,63 +774,63 @@ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) * * If no text is selected, then nothing is done. */ -void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *pFmt) +void ME_SetCharFormat( ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *fmt ) { - ME_DisplayItem *run, *start_run = start->pRun, *end_run = NULL; + ME_Run *run, *start_run = start->run, *end_run = NULL; - if (end && start->pRun == end->pRun && start->nOffset == end->nOffset) + if (end && start->run == end->run && start->nOffset == end->nOffset) return; - if (start->nOffset == start->pRun->member.run.len) - start_run = ME_FindItemFwd( start->pRun, diRun ); + if (start->nOffset == start->run->len) + start_run = run_next_all_paras( start->run ); else if (start->nOffset) { - /* SplitRunSimple may or may not update the cursors, depending on whether they + /* run_split() may or may not update the cursors, depending on whether they * are selection cursors, but we need to make sure they are valid. */ int split_offset = start->nOffset; - ME_DisplayItem *split_run = ME_SplitRunSimple(editor, start); - start_run = start->pRun; - if (end && end->pRun == split_run) + ME_Run *split_run = run_split( editor, start ); + start_run = start->run; + if (end && end->run == split_run) { - end->pRun = start->pRun; + end->run = start->run; end->nOffset -= split_offset; } } if (end) { - if (end->nOffset == end->pRun->member.run.len) - end_run = ME_FindItemFwd( end->pRun, diRun ); + if (end->nOffset == end->run->len) + end_run = run_next_all_paras( end->run ); else { - if (end->nOffset) ME_SplitRunSimple(editor, end); - end_run = end->pRun; + if (end->nOffset) run_split( editor, end ); + end_run = end->run; } } - for (run = start_run; run != end_run; run = ME_FindItemFwd( run, diRun )) + for (run = start_run; run != end_run; run = run_next_all_paras( run )) { - ME_Style *new_style = ME_ApplyStyle(editor, run->member.run.style, pFmt); - ME_Paragraph *para = run->member.run.para; + ME_Style *new_style = ME_ApplyStyle( editor, run->style, fmt ); + ME_Paragraph *para = run->para; - add_undo_set_char_fmt( editor, run->member.run.para->nCharOfs + run->member.run.nCharOfs, - run->member.run.len, &run->member.run.style->fmt ); - ME_ReleaseStyle(run->member.run.style); - run->member.run.style = new_style; + add_undo_set_char_fmt( editor, para->nCharOfs + run->nCharOfs, + run->len, &run->style->fmt ); + ME_ReleaseStyle( run->style ); + run->style = new_style; /* The para numbering style depends on the eop style */ - if ((run->member.run.nFlags & MERF_ENDPARA) && para->para_num.style) + if ((run->nFlags & MERF_ENDPARA) && para->para_num.style) { ME_ReleaseStyle(para->para_num.style); para->para_num.style = NULL; } - mark_para_rewrap(editor, get_di_from_para(para)); + para_mark_rewrap( editor, para ); } } -static void ME_GetRunCharFormat(ME_TextEditor *editor, ME_DisplayItem *run, CHARFORMAT2W *pFmt) +static void run_copy_char_fmt( ME_Run *run, CHARFORMAT2W *fmt ) { - ME_CopyCharFormat(pFmt, &run->member.run.style->fmt); + ME_CopyCharFormat( fmt, &run->style->fmt ); } /****************************************************************************** @@ -816,33 +868,25 @@ void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) * Returns the style consisting of those attributes which are consistently set * in the whole character range. */ -void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from, - const ME_Cursor *to, CHARFORMAT2W *pFmt) +void ME_GetCharFormat( ME_TextEditor *editor, const ME_Cursor *from, + const ME_Cursor *to, CHARFORMAT2W *fmt ) { - ME_DisplayItem *run, *run_end; + ME_Run *run, *run_end, *prev_run; CHARFORMAT2W tmp; - run = from->pRun; + run = from->run; /* special case - if selection is empty, take previous char's formatting */ - if (from->pRun == to->pRun && from->nOffset == to->nOffset) + if (from->run == to->run && from->nOffset == to->nOffset) { - if (!from->nOffset) - { - ME_DisplayItem *tmp_run = ME_FindItemBack(run, diRunOrParagraph); - if (tmp_run->type == diRun) { - ME_GetRunCharFormat(editor, tmp_run, pFmt); - return; - } - } - ME_GetRunCharFormat(editor, run, pFmt); + if (!from->nOffset && (prev_run = run_prev( run ))) run = prev_run; + run_copy_char_fmt( run, fmt ); return; } - run_end = to->pRun; - if (!to->nOffset) - run_end = ME_FindItemBack(run_end, diRun); + run_end = to->run; + if (!to->nOffset) run_end = run_prev_all_paras( run_end ); - ME_GetRunCharFormat(editor, run, pFmt); + run_copy_char_fmt( run, fmt ); if (run == run_end) return; @@ -851,40 +895,37 @@ void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from, DWORD dwAttribs = CFM_SIZE | CFM_FACE | CFM_COLOR | CFM_UNDERLINETYPE; DWORD dwEffects = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_STRIKEOUT | CFM_PROTECTED | CFM_LINK | CFM_SUPERSCRIPT; - run = ME_FindItemFwd(run, diRun); + run = run_next_all_paras( run ); - ZeroMemory(&tmp, sizeof(tmp)); + memset( &tmp, 0, sizeof(tmp) ); tmp.cbSize = sizeof(tmp); - ME_GetRunCharFormat(editor, run, &tmp); + run_copy_char_fmt( run, &tmp ); assert((tmp.dwMask & dwAttribs) == dwAttribs); /* reset flags that differ */ - if (pFmt->yHeight != tmp.yHeight) - pFmt->dwMask &= ~CFM_SIZE; - if (pFmt->dwMask & CFM_FACE) + if (fmt->yHeight != tmp.yHeight) fmt->dwMask &= ~CFM_SIZE; + if (fmt->dwMask & CFM_FACE) { if (!(tmp.dwMask & CFM_FACE)) - pFmt->dwMask &= ~CFM_FACE; - else if (wcscmp(pFmt->szFaceName, tmp.szFaceName) || - pFmt->bPitchAndFamily != tmp.bPitchAndFamily) - pFmt->dwMask &= ~CFM_FACE; + fmt->dwMask &= ~CFM_FACE; + else if (wcscmp( fmt->szFaceName, tmp.szFaceName ) || + fmt->bPitchAndFamily != tmp.bPitchAndFamily) + fmt->dwMask &= ~CFM_FACE; } - if (pFmt->yHeight != tmp.yHeight) - pFmt->dwMask &= ~CFM_SIZE; - if (pFmt->bUnderlineType != tmp.bUnderlineType) - pFmt->dwMask &= ~CFM_UNDERLINETYPE; - if (pFmt->dwMask & CFM_COLOR) + if (fmt->yHeight != tmp.yHeight) fmt->dwMask &= ~CFM_SIZE; + if (fmt->bUnderlineType != tmp.bUnderlineType) fmt->dwMask &= ~CFM_UNDERLINETYPE; + if (fmt->dwMask & CFM_COLOR) { - if (!((pFmt->dwEffects&CFE_AUTOCOLOR) & (tmp.dwEffects&CFE_AUTOCOLOR))) + if (!((fmt->dwEffects&CFE_AUTOCOLOR) & (tmp.dwEffects&CFE_AUTOCOLOR))) { - if (pFmt->crTextColor != tmp.crTextColor) - pFmt->dwMask &= ~CFM_COLOR; + if (fmt->crTextColor != tmp.crTextColor) + fmt->dwMask &= ~CFM_COLOR; } } - pFmt->dwMask &= ~((pFmt->dwEffects ^ tmp.dwEffects) & dwEffects); - pFmt->dwEffects = tmp.dwEffects; + fmt->dwMask &= ~((fmt->dwEffects ^ tmp.dwEffects) & dwEffects); + fmt->dwEffects = tmp.dwEffects; } while(run != run_end); } diff --git a/dll/win32/riched20/style.c b/dll/win32/riched20/style.c index 37c0509621f..917a5bd8100 100644 --- a/dll/win32/riched20/style.c +++ b/dll/win32/riched20/style.c @@ -429,7 +429,7 @@ void select_style( ME_Context *c, ME_Style *s ) c->orig_font = NULL; } - if (c->current_style && c->current_style->font_cache) + if (c->current_style) { release_font_cache( c->current_style->font_cache ); c->current_style->font_cache = NULL; @@ -473,42 +473,26 @@ void ME_ReleaseStyle(ME_Style *s) ME_DestroyStyle(s); } -ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor) +ME_Style *style_get_insert_style( ME_TextEditor *editor, ME_Cursor *cursor ) { - if (ME_IsSelection(editor)) - { + ME_Style *style; ME_Cursor *from, *to; + ME_Run *prev; - ME_GetSelection(editor, &from, &to); - ME_AddRefStyle(from->pRun->member.run.style); - return from->pRun->member.run.style; - } - if (editor->pBuffer->pCharStyle) { - ME_AddRefStyle(editor->pBuffer->pCharStyle); - return editor->pBuffer->pCharStyle; - } - else - { - ME_Cursor *pCursor = &editor->pCursors[nCursor]; - ME_DisplayItem *pRunItem = pCursor->pRun; - ME_DisplayItem *pPrevItem = NULL; - if (pCursor->nOffset) { - ME_Run *pRun = &pRunItem->member.run; - ME_AddRefStyle(pRun->style); - return pRun->style; - } - pPrevItem = ME_FindItemBack(pRunItem, diRunOrParagraph); - if (pPrevItem->type == diRun) + if (ME_IsSelection( editor )) { - ME_AddRefStyle(pPrevItem->member.run.style); - return pPrevItem->member.run.style; + ME_GetSelection( editor, &from, &to ); + style = from->run->style; } + else if (editor->pBuffer->pCharStyle) + style = editor->pBuffer->pCharStyle; + else if (!cursor->nOffset && (prev = run_prev( cursor->run ))) + style = prev->style; else - { - ME_AddRefStyle(pRunItem->member.run.style); - return pRunItem->member.run.style; - } - } + style = cursor->run->style; + + ME_AddRefStyle( style ); + return style; } void ME_SaveTempStyle(ME_TextEditor *editor, ME_Style *style) @@ -552,5 +536,5 @@ void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod) } ScriptFreeCache( &def->script_cache ); ME_ReleaseStyle( style ); - ME_MarkAllForWrapping( editor ); + editor_mark_rewrap_all( editor ); } diff --git a/dll/win32/riched20/table.c b/dll/win32/riched20/table.c index 1b4b9143d16..c3823e3b493 100644 --- a/dll/win32/riched20/table.c +++ b/dll/win32/riched20/table.c @@ -54,449 +54,362 @@ #include "editor.h" #include "rtf.h" -WINE_DEFAULT_DEBUG_CHANNEL(richedit_lists); +static ME_Paragraph* table_insert_end_para( ME_TextEditor *editor, ME_Cursor *cursor, + const WCHAR *eol_str, int eol_len, int para_flags ) +{ + ME_Style *style = style_get_insert_style( editor, cursor ); + ME_Paragraph *para; -static const WCHAR cr_lf[] = {'\r', '\n', 0}; + if (cursor->nOffset) run_split( editor, cursor ); -static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor, - int nCursor, - const WCHAR *eol_str, int eol_len, - int paraFlags) -{ - ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor); - ME_DisplayItem *tp; - ME_Cursor* cursor = &editor->pCursors[nCursor]; - if (cursor->nOffset) - ME_SplitRunSimple(editor, cursor); - - tp = ME_SplitParagraph(editor, cursor->pRun, pStyle, eol_str, eol_len, paraFlags); - ME_ReleaseStyle(pStyle); - cursor->pPara = tp; - cursor->pRun = ME_FindItemFwd(tp, diRun); - return tp; + para = para_split( editor, cursor->run, style, eol_str, eol_len, para_flags ); + ME_ReleaseStyle( style ); + cursor->para = para; + cursor->run = para_first_run( para ); + return para; } -ME_DisplayItem* ME_InsertTableRowStartFromCursor(ME_TextEditor *editor) +ME_Paragraph* table_insert_row_start( ME_TextEditor *editor, ME_Cursor *cursor ) { - ME_DisplayItem *para; - para = ME_InsertEndParaFromCursor(editor, 0, cr_lf, 2, MEPF_ROWSTART); - return para->member.para.prev_para; + ME_Paragraph *para; + + para = table_insert_end_para( editor, cursor, L"\r\n", 2, MEPF_ROWSTART ); + return para_prev( para ); } -ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor, - ME_DisplayItem *para) +ME_Paragraph* table_insert_row_start_at_para( ME_TextEditor *editor, ME_Paragraph *para ) { - ME_DisplayItem *prev_para, *end_para; - ME_Cursor savedCursor = editor->pCursors[0]; - ME_DisplayItem *startRowPara; - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); - editor->pCursors[0].nOffset = 0; - editor->pCursors[1] = editor->pCursors[0]; - startRowPara = ME_InsertTableRowStartFromCursor(editor); - savedCursor.pPara = ME_GetParagraph(savedCursor.pRun); - editor->pCursors[0] = savedCursor; - editor->pCursors[1] = editor->pCursors[0]; - - end_para = editor->pCursors[0].pPara->member.para.next_para; - prev_para = startRowPara->member.para.next_para; - para = prev_para->member.para.next_para; - while (para != end_para) - { - para->member.para.pCell = prev_para->member.para.pCell; - para->member.para.nFlags |= MEPF_CELL; - para->member.para.nFlags &= ~(MEPF_ROWSTART|MEPF_ROWEND); - para->member.para.fmt.dwMask |= PFM_TABLE|PFM_TABLEROWDELIMITER; - para->member.para.fmt.wEffects |= PFE_TABLE; - para->member.para.fmt.wEffects &= ~PFE_TABLEROWDELIMITER; - prev_para = para; - para = para->member.para.next_para; - } - return startRowPara; + ME_Paragraph *prev_para, *end_para, *start_row; + ME_Cursor cursor; + + cursor.para = para; + cursor.run = para_first_run( para ); + cursor.nOffset = 0; + + start_row = table_insert_row_start( editor, &cursor ); + + end_para = para_next( editor->pCursors[0].para ); + prev_para = para_next( start_row ); + para = para_next( prev_para ); + + while (para != end_para) + { + para->cell = para_cell( prev_para ); + para->nFlags |= MEPF_CELL; + para->nFlags &= ~(MEPF_ROWSTART | MEPF_ROWEND); + para->fmt.dwMask |= PFM_TABLE | PFM_TABLEROWDELIMITER; + para->fmt.wEffects |= PFE_TABLE; + para->fmt.wEffects &= ~PFE_TABLEROWDELIMITER; + prev_para = para; + para = para_next( para ); + } + return start_row; } /* Inserts a diCell and starts a new paragraph for the next cell. * * Returns the first paragraph of the new cell. */ -ME_DisplayItem* ME_InsertTableCellFromCursor(ME_TextEditor *editor) +ME_Paragraph* table_insert_cell( ME_TextEditor *editor, ME_Cursor *cursor ) { - ME_DisplayItem *para; - WCHAR tab = '\t'; - para = ME_InsertEndParaFromCursor(editor, 0, &tab, 1, MEPF_CELL); - return para; + WCHAR tab = '\t'; + + return table_insert_end_para( editor, editor->pCursors, &tab, 1, MEPF_CELL ); } -ME_DisplayItem* ME_InsertTableRowEndFromCursor(ME_TextEditor *editor) +ME_Paragraph* table_insert_row_end( ME_TextEditor *editor, ME_Cursor *cursor ) { - ME_DisplayItem *para; - para = ME_InsertEndParaFromCursor(editor, 0, cr_lf, 2, MEPF_ROWEND); - return para->member.para.prev_para; + ME_Paragraph *para; + + para = table_insert_end_para( editor, cursor, L"\r\n", 2, MEPF_ROWEND ); + return para_prev( para ); } -ME_DisplayItem* ME_GetTableRowEnd(ME_DisplayItem *para) +ME_Paragraph* table_row_end( ME_Paragraph *para ) { - ME_DisplayItem *cell; - assert(para); - if (para->member.para.nFlags & MEPF_ROWEND) - return para; - if (para->member.para.nFlags & MEPF_ROWSTART) - para = para->member.para.next_para; - cell = para->member.para.pCell; - assert(cell && cell->type == diCell); - while (cell->member.cell.next_cell) - cell = cell->member.cell.next_cell; - - para = ME_FindItemFwd(cell, diParagraph); - assert(para && para->member.para.nFlags & MEPF_ROWEND); + ME_Cell *cell; + + if (para->nFlags & MEPF_ROWEND) return para; + if (para->nFlags & MEPF_ROWSTART) para = para_next( para ); + cell = para_cell( para ); + while (cell_next( cell )) + cell = cell_next( cell ); + + para = &ME_FindItemFwd( cell_get_di( cell ), diParagraph )->member.para; + assert( para && para->nFlags & MEPF_ROWEND ); return para; } -ME_DisplayItem* ME_GetTableRowStart(ME_DisplayItem *para) +ME_Paragraph* table_row_start( ME_Paragraph *para ) { - ME_DisplayItem *cell; - assert(para); - if (para->member.para.nFlags & MEPF_ROWSTART) - return para; - if (para->member.para.nFlags & MEPF_ROWEND) - para = para->member.para.prev_para; - cell = para->member.para.pCell; - assert(cell && cell->type == diCell); - while (cell->member.cell.prev_cell) - cell = cell->member.cell.prev_cell; - - para = ME_FindItemBack(cell, diParagraph); - assert(para && para->member.para.nFlags & MEPF_ROWSTART); + ME_Cell *cell; + + if (para->nFlags & MEPF_ROWSTART) return para; + if (para->nFlags & MEPF_ROWEND) para = para_prev( para ); + cell = para_cell( para ); + + while (cell_prev( cell )) + cell = cell_prev( cell ); + + para = &ME_FindItemBack( cell_get_di( cell ), diParagraph )->member.para; + assert( para && para->nFlags & MEPF_ROWSTART ); return para; } -ME_DisplayItem* ME_GetOuterParagraph(ME_DisplayItem *para) +ME_Paragraph* table_outer_para( ME_Paragraph *para ) { - if (para->member.para.nFlags & MEPF_ROWEND) - para = para->member.para.prev_para; - while (para->member.para.pCell) + if (para->nFlags & MEPF_ROWEND) para = para_prev( para ); + while (para_cell( para )) { - para = ME_GetTableRowStart(para); - if (!para->member.para.pCell) - break; - para = ME_FindItemBack(para->member.para.pCell, diParagraph); + para = table_row_start( para ); + if (!para_cell( para )) break; + para = &ME_FindItemBack( cell_get_di( para_cell( para ) ), diParagraph )->member.para; } return para; } -/* Make a bunch of assertions to make sure tables haven't been corrupted. - * - * These invariants may not hold true in the middle of streaming in rich text - * or during an undo and redo of streaming in rich text. It should be safe to - * call this method after an event is processed. - */ -void ME_CheckTablesForCorruption(ME_TextEditor *editor) +ME_Cell *table_row_first_cell( ME_Paragraph *para ) { - if(TRACE_ON(richedit_lists)) - { - TRACE("---\n"); - ME_DumpDocument(editor->pBuffer); - } -#ifndef NDEBUG - { - ME_DisplayItem *p, *pPrev; - pPrev = editor->pBuffer->pFirst; - p = pPrev->next; - if (!editor->bEmulateVersion10) /* v4.1 */ - { - while (p->type == diParagraph) - { - assert(p->member.para.fmt.dwMask & PFM_TABLE); - assert(p->member.para.fmt.dwMask & PFM_TABLEROWDELIMITER); - if (p->member.para.pCell) - { - assert(p->member.para.nFlags & MEPF_CELL); - assert(p->member.para.fmt.wEffects & PFE_TABLE); - } - if (p->member.para.pCell != pPrev->member.para.pCell) - { - /* There must be a diCell in between the paragraphs if pCell changes. */ - ME_DisplayItem *pCell = ME_FindItemBack(p, diCell); - assert(pCell); - assert(ME_FindItemBack(p, diRun) == ME_FindItemBack(pCell, diRun)); - } - if (p->member.para.nFlags & MEPF_ROWEND) - { - /* ROWEND must come after a cell. */ - assert(pPrev->member.para.pCell); - assert(p->member.para.pCell - == pPrev->member.para.pCell->member.cell.parent_cell); - assert(p->member.para.fmt.wEffects & PFE_TABLEROWDELIMITER); - } - else if (p->member.para.pCell) - { - assert(!(p->member.para.fmt.wEffects & PFE_TABLEROWDELIMITER)); - assert(pPrev->member.para.pCell || - pPrev->member.para.nFlags & MEPF_ROWSTART); - if (pPrev->member.para.pCell && - !(pPrev->member.para.nFlags & MEPF_ROWSTART)) - { - assert(p->member.para.pCell->member.cell.parent_cell - == pPrev->member.para.pCell->member.cell.parent_cell); - if (pPrev->member.para.pCell != p->member.para.pCell) - assert(pPrev->member.para.pCell - == p->member.para.pCell->member.cell.prev_cell); - } - } - else if (!(p->member.para.nFlags & MEPF_ROWSTART)) - { - assert(!(p->member.para.fmt.wEffects & PFE_TABLEROWDELIMITER)); - /* ROWSTART must be followed by a cell. */ - assert(!(p->member.para.nFlags & MEPF_CELL)); - /* ROWSTART must be followed by a cell. */ - assert(!(pPrev->member.para.nFlags & MEPF_ROWSTART)); - } - pPrev = p; - p = p->member.para.next_para; - } - } else { /* v1.0 - 3.0 */ - while (p->type == diParagraph) - { - assert(!(p->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL))); - assert(p->member.para.fmt.dwMask & PFM_TABLE); - assert(!(p->member.para.fmt.wEffects & PFE_TABLEROWDELIMITER)); - assert(!p->member.para.pCell); - p = p->member.para.next_para; - } - return; - } - assert(p->type == diTextEnd); - assert(!pPrev->member.para.pCell); - } -#endif + if (!para_in_table( para )) return NULL; + + para = para_next( table_row_start( para ) ); + return para_cell( para ); +} + +ME_Cell *table_row_end_cell( ME_Paragraph *para ) +{ + if (!para_in_table( para )) return NULL; + + para = para_prev( table_row_end( para )); + return cell_next( para_cell( para ) ); +} + +ME_Cell *cell_create( void ) +{ + ME_DisplayItem *item = ME_MakeDI( diCell ); + return &item->member.cell; } -BOOL ME_IsInTable(ME_DisplayItem *pItem) +ME_Cell *cell_next( ME_Cell *cell ) { - PARAFORMAT2 *pFmt; - if (!pItem) - return FALSE; - if (pItem->type == diRun) - pItem = ME_GetParagraph(pItem); - if (pItem->type != diParagraph) - return FALSE; - pFmt = &pItem->member.para.fmt; - return pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE; + return cell->next_cell; +} + +ME_Cell *cell_prev( ME_Cell *cell ) +{ + return cell->prev_cell; +} + +ME_Paragraph *cell_first_para( ME_Cell *cell ) +{ + return &ME_FindItemFwd( cell_get_di( cell ), diParagraph )->member.para; +} + +ME_Paragraph *cell_end_para( ME_Cell *cell ) +{ + ME_Cell *next = cell_next( cell ); + + if (!next) return cell_first_para( cell ); /* End of row */ + + return &ME_FindItemBack( cell_get_di( next ), diParagraph )->member.para; } /* Table rows should either be deleted completely or not at all. */ -void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, ME_Cursor *c, int *nChars) +void table_protect_partial_deletion( ME_TextEditor *editor, ME_Cursor *c, int *num_chars ) { - int nOfs = ME_GetCursorOfs(c); + int start_ofs = ME_GetCursorOfs( c ); ME_Cursor c2 = *c; - ME_DisplayItem *this_para = c->pPara; - ME_DisplayItem *end_para; + ME_Paragraph *this_para = c->para, *end_para; - ME_MoveCursorChars(editor, &c2, *nChars, FALSE); - end_para = c2.pPara; - if (c2.pRun->member.run.nFlags & MERF_ENDPARA) { + ME_MoveCursorChars( editor, &c2, *num_chars, FALSE ); + end_para = c2.para; + if (c2.run->nFlags & MERF_ENDPARA) + { /* End offset might be in the middle of the end paragraph run. * If this is the case, then we need to use the next paragraph as the last * paragraphs. */ - int remaining = nOfs + *nChars - c2.pRun->member.run.nCharOfs - - end_para->member.para.nCharOfs; + int remaining = start_ofs + *num_chars - c2.run->nCharOfs - end_para->nCharOfs; if (remaining) { - assert(remaining < c2.pRun->member.run.len); - end_para = end_para->member.para.next_para; + assert( remaining < c2.run->len ); + end_para = para_next( end_para ); } } - if (!editor->bEmulateVersion10) { /* v4.1 */ - if (this_para->member.para.pCell != end_para->member.para.pCell || - ((this_para->member.para.nFlags|end_para->member.para.nFlags) - & (MEPF_ROWSTART|MEPF_ROWEND))) + if (!editor->bEmulateVersion10) /* v4.1 */ + { + if (para_cell( this_para ) != para_cell( end_para ) || + ((this_para->nFlags | end_para->nFlags) & (MEPF_ROWSTART | MEPF_ROWEND))) { while (this_para != end_para) { - ME_DisplayItem *next_para = this_para->member.para.next_para; - BOOL bTruancateDeletion = FALSE; - if (this_para->member.para.nFlags & MEPF_ROWSTART) { + ME_Paragraph *next_para = para_next( this_para ); + BOOL truancate_del = FALSE; + if (this_para->nFlags & MEPF_ROWSTART) + { /* The following while loop assumes that next_para is MEPF_ROWSTART, - * so moving back one paragraph let's it be processed as the start + * so moving back one paragraph lets it be processed as the start * of the row. */ next_para = this_para; - this_para = this_para->member.para.prev_para; - } else if (next_para->member.para.pCell != this_para->member.para.pCell - || this_para->member.para.nFlags & MEPF_ROWEND) + this_para = para_prev( this_para ); + } + else if (para_cell( next_para) != para_cell( this_para ) || this_para->nFlags & MEPF_ROWEND) { /* Start of the deletion from after the start of the table row. */ - bTruancateDeletion = TRUE; + truancate_del = TRUE; } - while (!bTruancateDeletion && - next_para->member.para.nFlags & MEPF_ROWSTART) + while (!truancate_del && next_para->nFlags & MEPF_ROWSTART) { - next_para = ME_GetTableRowEnd(next_para)->member.para.next_para; - if (next_para->member.para.nCharOfs > nOfs + *nChars) + next_para = para_next( table_row_end( next_para ) ); + if (next_para->nCharOfs > start_ofs + *num_chars) { /* End of deletion is not past the end of the table row. */ - next_para = this_para->member.para.next_para; + next_para = para_next( this_para ); /* Delete the end paragraph preceding the table row if the * preceding table row will be empty. */ - if (this_para->member.para.nCharOfs >= nOfs) - { - next_para = next_para->member.para.next_para; - } - bTruancateDeletion = TRUE; - } else { - this_para = next_para->member.para.prev_para; + if (this_para->nCharOfs >= start_ofs) next_para = para_next( next_para ); + truancate_del = TRUE; } + else this_para = para_prev( next_para ); } - if (bTruancateDeletion) + if (truancate_del) { - ME_Run *end_run = &ME_FindItemBack(next_para, diRun)->member.run; - int nCharsNew = (next_para->member.para.nCharOfs - nOfs - - end_run->len); - nCharsNew = max(nCharsNew, 0); - assert(nCharsNew <= *nChars); - *nChars = nCharsNew; + ME_Run *end_run = para_end_run( para_prev( next_para ) ); + int new_chars = next_para->nCharOfs - start_ofs - end_run->len; + new_chars = max( new_chars, 0 ); + assert( new_chars <= *num_chars); + *num_chars = new_chars; break; } this_para = next_para; } } - } else { /* v1.0 - 3.0 */ - ME_DisplayItem *pRun; - int nCharsToBoundary; + } + else /* v1.0 - 3.0 */ + { + ME_Run *run; + int chars_to_boundary; - if ((this_para->member.para.nCharOfs != nOfs || this_para == end_para) && - this_para->member.para.fmt.dwMask & PFM_TABLE && - this_para->member.para.fmt.wEffects & PFE_TABLE) + if ((this_para->nCharOfs != start_ofs || this_para == end_para) && para_in_table( this_para )) { - pRun = c->pRun; + run = c->run; /* Find the next tab or end paragraph to use as a delete boundary */ - while (!(pRun->member.run.nFlags & (MERF_TAB|MERF_ENDPARA))) - pRun = ME_FindItemFwd(pRun, diRun); - nCharsToBoundary = pRun->member.run.nCharOfs - - c->pRun->member.run.nCharOfs - - c->nOffset; - *nChars = min(*nChars, nCharsToBoundary); - } else if (end_para->member.para.fmt.dwMask & PFM_TABLE && - end_para->member.para.fmt.wEffects & PFE_TABLE) + while (!(run->nFlags & (MERF_TAB | MERF_ENDPARA))) + run = run_next( run ); + chars_to_boundary = run->nCharOfs - c->run->nCharOfs - c->nOffset; + *num_chars = min( *num_chars, chars_to_boundary ); + } + else if (para_in_table( end_para )) { /* The deletion starts from before the row, so don't join it with * previous non-empty paragraphs. */ - ME_DisplayItem *curPara; - pRun = NULL; - if (nOfs > this_para->member.para.nCharOfs) { - pRun = ME_FindItemBack(end_para, diRun); - curPara = end_para->member.para.prev_para; + ME_Paragraph *cur_para; + run = NULL; + if (start_ofs > this_para->nCharOfs) + { + cur_para = para_prev( end_para ); + run = para_end_run( cur_para ); } - if (!pRun) { - pRun = ME_FindItemFwd(end_para, diRun); - curPara = end_para; + if (!run) + { + cur_para = end_para; + run = para_first_run( end_para ); } - if (pRun) + if (run) { - nCharsToBoundary = curPara->member.para.nCharOfs - + pRun->member.run.nCharOfs - - nOfs; - if (nCharsToBoundary >= 0) - *nChars = min(*nChars, nCharsToBoundary); + chars_to_boundary = cur_para->nCharOfs + run->nCharOfs - start_ofs; + if (chars_to_boundary >= 0) *num_chars = min( *num_chars, chars_to_boundary ); } } - if (*nChars < 0) - *nChars = 0; + if (*num_chars < 0) *num_chars = 0; } } -ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, - ME_DisplayItem *table_row) +ME_Paragraph* table_append_row( ME_TextEditor *editor, ME_Paragraph *table_row ) { WCHAR endl = '\r', tab = '\t'; - ME_DisplayItem *run; - PARAFORMAT2 *pFmt; + ME_Run *run; int i; - assert(table_row); - assert(table_row->type == diParagraph); - if (!editor->bEmulateVersion10) { /* v4.1 */ - ME_DisplayItem *insertedCell, *para, *cell, *prevTableEnd; - cell = ME_FindItemFwd(ME_GetTableRowStart(table_row), diCell); - prevTableEnd = ME_GetTableRowEnd(table_row); - para = prevTableEnd->member.para.next_para; - run = ME_FindItemFwd(para, diRun); - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = run; + if (!editor->bEmulateVersion10) /* v4.1 */ + { + ME_Cell *new_cell, *cell; + ME_Paragraph *para, *prev_table_end, *new_row_start; + + cell = table_row_first_cell( table_row ); + prev_table_end = table_row_end( table_row ); + para = para_next( prev_table_end ); + run = para_first_run( para ); + editor->pCursors[0].para = para; + editor->pCursors[0].run = run; editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; - para = ME_InsertTableRowStartFromCursor(editor); - insertedCell = ME_FindItemFwd(para, diCell); + new_row_start = table_insert_row_start( editor, editor->pCursors ); + new_cell = table_row_first_cell( new_row_start ); /* Copy cell properties */ - insertedCell->member.cell.nRightBoundary = cell->member.cell.nRightBoundary; - insertedCell->member.cell.border = cell->member.cell.border; - while (cell->member.cell.next_cell) { - cell = cell->member.cell.next_cell; - para = ME_InsertTableCellFromCursor(editor); - insertedCell = ME_FindItemBack(para, diCell); + new_cell->nRightBoundary = cell->nRightBoundary; + new_cell->border = cell->border; + while (cell_next( cell )) + { + cell = cell_next( cell ); + para = table_insert_cell( editor, editor->pCursors ); + new_cell = para_cell( para ); /* Copy cell properties */ - insertedCell->member.cell.nRightBoundary = cell->member.cell.nRightBoundary; - insertedCell->member.cell.border = cell->member.cell.border; + new_cell->nRightBoundary = cell->nRightBoundary; + new_cell->border = cell->border; }; - para = ME_InsertTableRowEndFromCursor(editor); - para->member.para.fmt = prevTableEnd->member.para.fmt; + para = table_insert_row_end( editor, editor->pCursors ); + para->fmt = prev_table_end->fmt; /* return the table row start for the inserted paragraph */ - return ME_FindItemFwd(cell, diParagraph)->member.para.next_para; - } else { /* v1.0 - 3.0 */ - run = ME_FindItemBack(table_row->member.para.next_para, diRun); - pFmt = &table_row->member.para.fmt; - assert(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE); - editor->pCursors[0].pPara = table_row; - editor->pCursors[0].pRun = run; + return new_row_start; + } + else /* v1.0 - 3.0 */ + { + run = para_end_run( table_row ); + assert( para_in_table( table_row ) ); + editor->pCursors[0].para = table_row; + editor->pCursors[0].run = run; editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; - ME_InsertTextFromCursor(editor, 0, &endl, 1, run->member.run.style); - run = editor->pCursors[0].pRun; - for (i = 0; i < pFmt->cTabCount; i++) { - ME_InsertTextFromCursor(editor, 0, &tab, 1, run->member.run.style); - } - return table_row->member.para.next_para; + ME_InsertTextFromCursor( editor, 0, &endl, 1, run->style ); + run = editor->pCursors[0].run; + for (i = 0; i < table_row->fmt.cTabCount; i++) + ME_InsertTextFromCursor( editor, 0, &tab, 1, run->style ); + + return para_next( table_row ); } } /* Selects the next table cell or appends a new table row if at end of table */ -static void ME_SelectOrInsertNextCell(ME_TextEditor *editor, - ME_DisplayItem *run) +static void table_select_next_cell_or_append( ME_TextEditor *editor, ME_Run *run ) { - ME_DisplayItem *para = ME_GetParagraph(run); + ME_Paragraph *para = run->para; + ME_Cell *cell; int i; - assert(run && run->type == diRun); - assert(ME_IsInTable(run)); - if (!editor->bEmulateVersion10) { /* v4.1 */ - ME_DisplayItem *cell; + assert( para_in_table( para ) ); + if (!editor->bEmulateVersion10) /* v4.1 */ + { /* Get the initial cell */ - if (para->member.para.nFlags & MEPF_ROWSTART) { - cell = para->member.para.next_para->member.para.pCell; - } else if (para->member.para.nFlags & MEPF_ROWEND) { - cell = para->member.para.prev_para->member.para.pCell; - } else { - cell = para->member.para.pCell; - } - assert(cell); + if (para->nFlags & MEPF_ROWSTART) cell = para_cell( para_next( para ) ); + else if (para->nFlags & MEPF_ROWEND) cell = para_cell( para_prev( para ) ); + else cell = para_cell( para ); + /* Get the next cell. */ - if (cell->member.cell.next_cell && - cell->member.cell.next_cell->member.cell.next_cell) + if (cell_next( cell ) && cell_next( cell_next( cell ) )) + cell = cell_next( cell ); + else { - cell = cell->member.cell.next_cell; - } else { - para = ME_GetTableRowEnd(ME_FindItemFwd(cell, diParagraph)); - para = para->member.para.next_para; - assert(para); - if (para->member.para.nFlags & MEPF_ROWSTART) { - cell = para->member.para.next_para->member.para.pCell; - } else { + para = para_next( table_row_end( para ) ); + if (para->nFlags & MEPF_ROWSTART) cell = para_cell( para_next( para ) ); + else + { /* Insert row */ - para = para->member.para.prev_para; - para = ME_AppendTableRow(editor, ME_GetTableRowStart(para)); + para = para_prev( para ); + para = table_append_row( editor, table_row_start( para ) ); /* Put cursor at the start of the new table row */ - para = para->member.para.next_para; - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + para = para_next( para ); + editor->pCursors[0].para = para; + editor->pCursors[0].run = para_first_run( para ); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; ME_WrapMarkedParagraphs(editor); @@ -504,62 +417,60 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor, } } /* Select cell */ - editor->pCursors[1].pRun = ME_FindItemFwd(cell, diRun); - editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun); + editor->pCursors[1].para = cell_first_para( cell ); + editor->pCursors[1].run = para_first_run( editor->pCursors[1].para ); editor->pCursors[1].nOffset = 0; - assert(editor->pCursors[0].pRun); - cell = cell->member.cell.next_cell; - editor->pCursors[0].pRun = ME_FindItemBack(cell, diRun); - editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun); + editor->pCursors[0].para = cell_end_para( cell ); + editor->pCursors[0].run = para_end_run( editor->pCursors[0].para ); editor->pCursors[0].nOffset = 0; - assert(editor->pCursors[1].pRun); - } else { /* v1.0 - 3.0 */ - if (run->member.run.nFlags & MERF_ENDPARA && - ME_IsInTable(ME_FindItemFwd(run, diParagraphOrEnd))) + } + else /* v1.0 - 3.0 */ + { + if (run->nFlags & MERF_ENDPARA && para_in_table( para_next( para ) )) { - run = ME_FindItemFwd(run, diRun); + run = run_next_all_paras( run ); assert(run); } for (i = 0; i < 2; i++) { - while (!(run->member.run.nFlags & MERF_TAB)) + while (!(run->nFlags & MERF_TAB)) { - run = ME_FindItemFwd(run, diRunOrParagraphOrEnd); - if (run->type != diRun) + if (!run_next( run )) { - para = run; - if (ME_IsInTable(para)) + para = para_next( run->para ); + if (para_in_table( para )) { - run = ME_FindItemFwd(para, diRun); - assert(run); - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = run; + run = para_first_run( para ); + editor->pCursors[0].para = para; + editor->pCursors[0].run = run; editor->pCursors[0].nOffset = 0; i = 1; - } else { + } + else + { /* Insert table row */ - para = ME_AppendTableRow(editor, para->member.para.prev_para); + para = table_append_row( editor, para_prev( para ) ); /* Put cursor at the start of the new table row */ - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + editor->pCursors[0].para = para; + editor->pCursors[0].run = para_first_run( para ); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; ME_WrapMarkedParagraphs(editor); return; } } + else run = run_next( run ); } - if (i == 0) - run = ME_FindItemFwd(run, diRun); - editor->pCursors[i].pRun = run; - editor->pCursors[i].pPara = ME_GetParagraph(run); + if (i == 0) run = run_next_all_paras( run ); + editor->pCursors[i].run = run; + editor->pCursors[i].para = run->para; editor->pCursors[i].nOffset = 0; } } } -void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow) +void table_handle_tab( ME_TextEditor *editor, BOOL selected_row ) { /* FIXME: Shift tab should move to the previous cell. */ ME_Cursor fromCursor, toCursor; @@ -572,43 +483,41 @@ void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow) { fromCursor = editor->pCursors[0]; toCursor = editor->pCursors[1]; - } else { + } + else + { fromCursor = editor->pCursors[1]; toCursor = editor->pCursors[0]; } } if (!editor->bEmulateVersion10) /* v4.1 */ { - if (!ME_IsInTable(toCursor.pRun)) + if (!para_in_table( toCursor.para )) { editor->pCursors[0] = toCursor; editor->pCursors[1] = toCursor; - } else { - ME_SelectOrInsertNextCell(editor, toCursor.pRun); } - } else { /* v1.0 - 3.0 */ - if (!ME_IsInTable(fromCursor.pRun)) { + else table_select_next_cell_or_append( editor, toCursor.run ); + } + else /* v1.0 - 3.0 */ + { + if (!para_in_table( fromCursor.para )) + { editor->pCursors[0] = fromCursor; editor->pCursors[1] = fromCursor; /* FIXME: For some reason the caret is shown at the start of the - * previous paragraph in v1.0 to v3.0, and bCaretAtEnd only works - * within the paragraph for wrapped lines. */ - if (ME_FindItemBack(fromCursor.pRun, diRun)) - editor->bCaretAtEnd = TRUE; - } else if ((bSelectedRow || !ME_IsInTable(toCursor.pRun))) { - ME_SelectOrInsertNextCell(editor, fromCursor.pRun); - } else { - if (ME_IsSelection(editor) && !toCursor.nOffset) - { - ME_DisplayItem *run; - run = ME_FindItemBack(toCursor.pRun, diRunOrParagraphOrEnd); - if (run->type == diRun && run->member.run.nFlags & MERF_TAB) - ME_SelectOrInsertNextCell(editor, run); - else - ME_SelectOrInsertNextCell(editor, toCursor.pRun); - } else { - ME_SelectOrInsertNextCell(editor, toCursor.pRun); - } + * previous paragraph in v1.0 to v3.0 */ + } + else if ((selected_row || !para_in_table( toCursor.para ))) + table_select_next_cell_or_append( editor, fromCursor.run ); + else + { + ME_Run *run = run_prev( toCursor.run ); + + if (ME_IsSelection(editor) && !toCursor.nOffset && run && run->nFlags & MERF_TAB) + table_select_next_cell_or_append( editor, run ); + else + table_select_next_cell_or_append( editor, toCursor.run ); } } ME_InvalidateSelection(editor); @@ -619,16 +528,17 @@ void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow) /* Make sure the cursor is not in the hidden table row start paragraph * without a selection. */ -void ME_MoveCursorFromTableRowStartParagraph(ME_TextEditor *editor) +void table_move_from_row_start( ME_TextEditor *editor ) { - ME_DisplayItem *para = editor->pCursors[0].pPara; - if (para == editor->pCursors[1].pPara && - para->member.para.nFlags & MEPF_ROWSTART) { + ME_Paragraph *para = editor->pCursors[0].para; + + if (para == editor->pCursors[1].para && para->nFlags & MEPF_ROWSTART) + { /* The cursors should not be at the hidden start row paragraph without * a selection, so the cursor is moved into the first cell. */ - para = para->member.para.next_para; - editor->pCursors[0].pPara = para; - editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + para = para_next( para ); + editor->pCursors[0].para = para; + editor->pCursors[0].run = para_first_run( para ); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; } diff --git a/dll/win32/riched20/txthost.c b/dll/win32/riched20/txthost.c index 35e01633b93..73a52c76728 100644 --- a/dll/win32/riched20/txthost.c +++ b/dll/win32/riched20/txthost.c @@ -25,33 +25,85 @@ #include "richole.h" #include "imm.h" #include "textserv.h" -#include "wine/asm.h" #include "wine/debug.h" #include "editstr.h" +#include "rtf.h" +#include "undocuser.h" WINE_DEFAULT_DEBUG_CHANNEL(richedit); -typedef struct ITextHostImpl { - ITextHost ITextHost_iface; +struct host +{ + ITextHost2 ITextHost_iface; LONG ref; - HWND hWnd; - BOOL bEmulateVersion10; + ITextServices *text_srv; + HWND window, parent; + unsigned int emulate_10 : 1; + unsigned int dialog_mode : 1; + unsigned int want_return : 1; + unsigned int sel_bar : 1; + unsigned int client_edge : 1; + unsigned int use_set_rect : 1; + unsigned int use_back_colour : 1; PARAFORMAT2 para_fmt; -} ITextHostImpl; + DWORD props, scrollbars, event_mask; + RECT client_rect, set_rect; + COLORREF back_colour; + WCHAR password_char; +}; + +static const ITextHost2Vtbl textHostVtbl; + +static BOOL listbox_registered; +static BOOL combobox_registered; + +static void host_init_props( struct host *host ) +{ + DWORD style; + + style = GetWindowLongW( host->window, GWL_STYLE ); + + /* text services assumes the scrollbars are originally not shown, so hide them. + However with ES_DISABLENOSCROLL it'll immediately show them, so don't bother */ + if (!(style & ES_DISABLENOSCROLL)) ShowScrollBar( host->window, SB_BOTH, FALSE ); + + host->scrollbars = style & (WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | + ES_AUTOHSCROLL | ES_DISABLENOSCROLL); + if (style & WS_VSCROLL) host->scrollbars |= ES_AUTOVSCROLL; + if ((style & WS_HSCROLL) && !host->emulate_10) host->scrollbars |= ES_AUTOHSCROLL; + + host->props = TXTBIT_RICHTEXT | TXTBIT_ALLOWBEEP; + if (style & ES_MULTILINE) host->props |= TXTBIT_MULTILINE; + if (style & ES_READONLY) host->props |= TXTBIT_READONLY; + if (style & ES_PASSWORD) host->props |= TXTBIT_USEPASSWORD; + if (!(style & ES_NOHIDESEL)) host->props |= TXTBIT_HIDESELECTION; + if (style & ES_SAVESEL) host->props |= TXTBIT_SAVESELECTION; + if (style & ES_VERTICAL) host->props |= TXTBIT_VERTICAL; + if (style & ES_NOOLEDRAGDROP) host->props |= TXTBIT_DISABLEDRAG; + + if (!(host->scrollbars & ES_AUTOHSCROLL)) host->props |= TXTBIT_WORDWRAP; + + host->sel_bar = !!(style & ES_SELECTIONBAR); + host->want_return = !!(style & ES_WANTRETURN); -static const ITextHostVtbl textHostVtbl; + style = GetWindowLongW( host->window, GWL_EXSTYLE ); + host->client_edge = !!(style & WS_EX_CLIENTEDGE); +} -ITextHost *ME_CreateTextHost(HWND hwnd, CREATESTRUCTW *cs, BOOL bEmulateVersion10) +struct host *host_create( HWND hwnd, CREATESTRUCTW *cs, BOOL emulate_10 ) { - ITextHostImpl *texthost; + struct host *texthost; texthost = CoTaskMemAlloc(sizeof(*texthost)); if (!texthost) return NULL; texthost->ITextHost_iface.lpVtbl = &textHostVtbl; texthost->ref = 1; - texthost->hWnd = hwnd; - texthost->bEmulateVersion10 = bEmulateVersion10; + texthost->text_srv = NULL; + texthost->window = hwnd; + texthost->parent = cs->hwndParent; + texthost->emulate_10 = emulate_10; + texthost->dialog_mode = 0; memset( &texthost->para_fmt, 0, sizeof(texthost->para_fmt) ); texthost->para_fmt.cbSize = sizeof(texthost->para_fmt); texthost->para_fmt.dwMask = PFM_ALIGNMENT; @@ -60,357 +112,365 @@ ITextHost *ME_CreateTextHost(HWND hwnd, CREATESTRUCTW *cs, BOOL bEmulateVersion1 texthost->para_fmt.wAlignment = PFA_RIGHT; if (cs->style & ES_CENTER) texthost->para_fmt.wAlignment = PFA_CENTER; - - return &texthost->ITextHost_iface; + host_init_props( texthost ); + texthost->event_mask = 0; + texthost->use_set_rect = 0; + SetRectEmpty( &texthost->set_rect ); + GetClientRect( hwnd, &texthost->client_rect ); + texthost->use_back_colour = 0; + texthost->password_char = (texthost->props & TXTBIT_USEPASSWORD) ? '*' : 0; + + return texthost; } -static inline ITextHostImpl *impl_from_ITextHost(ITextHost *iface) +static inline struct host *impl_from_ITextHost( ITextHost2 *iface ) { - return CONTAINING_RECORD(iface, ITextHostImpl, ITextHost_iface); + return CONTAINING_RECORD( iface, struct host, ITextHost_iface ); } -static HRESULT WINAPI ITextHostImpl_QueryInterface(ITextHost *iface, REFIID riid, void **ppvObject) +static HRESULT WINAPI ITextHostImpl_QueryInterface( ITextHost2 *iface, REFIID iid, void **obj ) { - ITextHostImpl *This = impl_from_ITextHost(iface); + struct host *host = impl_from_ITextHost( iface ); - if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ITextHost)) { - *ppvObject = &This->ITextHost_iface; - ITextHost_AddRef((ITextHost *)*ppvObject); + if (IsEqualIID( iid, &IID_IUnknown ) || IsEqualIID( iid, &IID_ITextHost ) || IsEqualIID( iid, &IID_ITextHost2 )) + { + *obj = &host->ITextHost_iface; + ITextHost_AddRef( (ITextHost *)*obj ); return S_OK; } - FIXME("Unknown interface: %s\n", debugstr_guid(riid)); + FIXME( "Unknown interface: %s\n", debugstr_guid( iid ) ); return E_NOINTERFACE; } -static ULONG WINAPI ITextHostImpl_AddRef(ITextHost *iface) +static ULONG WINAPI ITextHostImpl_AddRef( ITextHost2 *iface ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - ULONG ref = InterlockedIncrement(&This->ref); + struct host *host = impl_from_ITextHost( iface ); + ULONG ref = InterlockedIncrement( &host->ref ); return ref; } -static ULONG WINAPI ITextHostImpl_Release(ITextHost *iface) +static ULONG WINAPI ITextHostImpl_Release( ITextHost2 *iface ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - ULONG ref = InterlockedDecrement(&This->ref); + struct host *host = impl_from_ITextHost( iface ); + ULONG ref = InterlockedDecrement( &host->ref ); if (!ref) { - SetWindowLongPtrW(This->hWnd, 0, 0); - CoTaskMemFree(This); + SetWindowLongPtrW( host->window, 0, 0 ); + ITextServices_Release( host->text_srv ); + CoTaskMemFree( host ); } return ref; } -DECLSPEC_HIDDEN HDC __thiscall ITextHostImpl_TxGetDC(ITextHost *iface) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetDC,4) +DECLSPEC_HIDDEN HDC __thiscall ITextHostImpl_TxGetDC( ITextHost2 *iface ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - return GetDC(This->hWnd); + struct host *host = impl_from_ITextHost( iface ); + return GetDC( host->window ); } -DECLSPEC_HIDDEN INT __thiscall ITextHostImpl_TxReleaseDC(ITextHost *iface, HDC hdc) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxReleaseDC,8) +DECLSPEC_HIDDEN INT __thiscall ITextHostImpl_TxReleaseDC( ITextHost2 *iface, HDC hdc ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - return ReleaseDC(This->hWnd, hdc); + struct host *host = impl_from_ITextHost( iface ); + return ReleaseDC( host->window, hdc ); } -DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxShowScrollBar(ITextHost *iface, INT fnBar, BOOL fShow) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowScrollBar,12) +DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxShowScrollBar( ITextHost2 *iface, INT bar, BOOL show ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - return ShowScrollBar(This->hWnd, fnBar, fShow); + struct host *host = impl_from_ITextHost( iface ); + return ShowScrollBar( host->window, bar, show ); } -DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxEnableScrollBar(ITextHost *iface, INT fuSBFlags, INT fuArrowflags) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxEnableScrollBar,12) +DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxEnableScrollBar( ITextHost2 *iface, INT bar, INT arrows ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - return EnableScrollBar(This->hWnd, fuSBFlags, fuArrowflags); + struct host *host = impl_from_ITextHost( iface ); + return EnableScrollBar( host->window, bar, arrows ); } -DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetScrollRange(ITextHost *iface, INT fnBar, LONG nMinPos, INT nMaxPos, - BOOL fRedraw) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollRange,20) +DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetScrollRange( ITextHost2 *iface, INT bar, LONG min_pos, INT max_pos, BOOL redraw ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - return SetScrollRange(This->hWnd, fnBar, nMinPos, nMaxPos, fRedraw); + struct host *host = impl_from_ITextHost( iface ); + SCROLLINFO info = { .cbSize = sizeof(info), .fMask = SIF_PAGE | SIF_RANGE }; + + if (bar != SB_HORZ && bar != SB_VERT) + { + FIXME( "Unexpected bar %d\n", bar ); + return FALSE; + } + + if (host->scrollbars & ES_DISABLENOSCROLL) info.fMask |= SIF_DISABLENOSCROLL; + + if (host->text_srv) /* This can be called during text services creation */ + { + if (bar == SB_HORZ) ITextServices_TxGetHScroll( host->text_srv, NULL, NULL, NULL, (LONG *)&info.nPage, NULL ); + else ITextServices_TxGetVScroll( host->text_srv, NULL, NULL, NULL, (LONG *)&info.nPage, NULL ); + } + + info.nMin = min_pos; + info.nMax = max_pos; + return SetScrollInfo( host->window, bar, &info, redraw ); } -DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetScrollPos(ITextHost *iface, INT fnBar, INT nPos, BOOL fRedraw) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollPos,16) +DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetScrollPos( ITextHost2 *iface, INT bar, INT pos, BOOL redraw ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - return SetScrollPos(This->hWnd, fnBar, nPos, fRedraw) != 0; + struct host *host = impl_from_ITextHost( iface ); + DWORD style = GetWindowLongW( host->window, GWL_STYLE ); + DWORD mask = (bar == SB_HORZ) ? WS_HSCROLL : WS_VSCROLL; + BOOL show = TRUE, shown = style & mask; + + if (bar != SB_HORZ && bar != SB_VERT) + { + FIXME( "Unexpected bar %d\n", bar ); + return FALSE; + } + + /* If the application has adjusted the scrollbar's visibility it is reset */ + if (!(host->scrollbars & ES_DISABLENOSCROLL)) + { + if (bar == SB_HORZ) ITextServices_TxGetHScroll( host->text_srv, NULL, NULL, NULL, NULL, &show ); + else ITextServices_TxGetVScroll( host->text_srv, NULL, NULL, NULL, NULL, &show ); + } + + if (!show ^ !shown) ShowScrollBar( host->window, bar, show ); + return SetScrollPos( host->window, bar, pos, redraw ) != 0; } -DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxInvalidateRect(ITextHost *iface, LPCRECT prc, BOOL fMode) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxInvalidateRect,12) +DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxInvalidateRect( ITextHost2 *iface, const RECT *rect, BOOL mode ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - InvalidateRect(This->hWnd, prc, fMode); + struct host *host = impl_from_ITextHost( iface ); + InvalidateRect( host->window, rect, mode ); } -DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxViewChange(ITextHost *iface, BOOL fUpdate) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxViewChange,8) +DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxViewChange( ITextHost2 *iface, BOOL update ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - if (fUpdate) - UpdateWindow(This->hWnd); + struct host *host = impl_from_ITextHost( iface ); + if (update) UpdateWindow( host->window ); } -DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxCreateCaret(ITextHost *iface, HBITMAP hbmp, INT xWidth, INT yHeight) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxCreateCaret,16) +DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxCreateCaret( ITextHost2 *iface, HBITMAP bitmap, INT width, INT height ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - return CreateCaret(This->hWnd, hbmp, xWidth, yHeight); + struct host *host = impl_from_ITextHost( iface ); + return CreateCaret( host->window, bitmap, width, height ); } -DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxShowCaret(ITextHost *iface, BOOL fShow) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowCaret,8) +DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxShowCaret( ITextHost2 *iface, BOOL show ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - if (fShow) - return ShowCaret(This->hWnd); - else - return HideCaret(This->hWnd); + struct host *host = impl_from_ITextHost( iface ); + if (show) return ShowCaret( host->window ); + else return HideCaret( host->window ); } -DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetCaretPos(ITextHost *iface, - INT x, INT y) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCaretPos,12) +DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetCaretPos( ITextHost2 *iface, INT x, INT y ) { return SetCaretPos(x, y); } -DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetTimer(ITextHost *iface, UINT idTimer, UINT uTimeout) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetTimer,12) +DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetTimer( ITextHost2 *iface, UINT id, UINT timeout ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - return SetTimer(This->hWnd, idTimer, uTimeout, NULL) != 0; + struct host *host = impl_from_ITextHost( iface ); + return SetTimer( host->window, id, timeout, NULL ) != 0; } -DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxKillTimer(ITextHost *iface, UINT idTimer) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxKillTimer,8) +DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxKillTimer( ITextHost2 *iface, UINT id ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - KillTimer(This->hWnd, idTimer); + struct host *host = impl_from_ITextHost( iface ); + KillTimer( host->window, id ); } -DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxScrollWindowEx(ITextHost *iface, INT dx, INT dy, LPCRECT lprcScroll, - LPCRECT lprcClip, HRGN hRgnUpdate, LPRECT lprcUpdate, - UINT fuScroll) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScrollWindowEx,32) +DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxScrollWindowEx( ITextHost2 *iface, INT dx, INT dy, const RECT *scroll, + const RECT *clip, HRGN update_rgn, RECT *update_rect, + UINT flags ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - ScrollWindowEx(This->hWnd, dx, dy, lprcScroll, lprcClip, - hRgnUpdate, lprcUpdate, fuScroll); + struct host *host = impl_from_ITextHost( iface ); + ScrollWindowEx( host->window, dx, dy, scroll, clip, update_rgn, update_rect, flags ); } -DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetCapture(ITextHost *iface, BOOL fCapture) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCapture,8) +DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetCapture( ITextHost2 *iface, BOOL capture ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - if (fCapture) - SetCapture(This->hWnd); - else - ReleaseCapture(); + struct host *host = impl_from_ITextHost( iface ); + if (capture) SetCapture( host->window ); + else ReleaseCapture(); } -DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetFocus(ITextHost *iface) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetFocus,4) +DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetFocus( ITextHost2 *iface ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - SetFocus(This->hWnd); + struct host *host = impl_from_ITextHost( iface ); + SetFocus( host->window ); } -DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetCursor(ITextHost *iface, HCURSOR hcur, BOOL fText) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCursor,12) +DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetCursor( ITextHost2 *iface, HCURSOR cursor, BOOL text ) { - SetCursor(hcur); + SetCursor( cursor ); } -DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxScreenToClient(ITextHost *iface, LPPOINT lppt) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScreenToClient,8) +DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxScreenToClient( ITextHost2 *iface, POINT *pt ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - return ScreenToClient(This->hWnd, lppt); + struct host *host = impl_from_ITextHost( iface ); + return ScreenToClient( host->window, pt ); } -DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxClientToScreen(ITextHost *iface, LPPOINT lppt) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxClientToScreen,8) +DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxClientToScreen( ITextHost2 *iface, POINT *pt ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - return ClientToScreen(This->hWnd, lppt); + struct host *host = impl_from_ITextHost( iface ); + return ClientToScreen( host->window, pt ); } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxActivate(ITextHost *iface, LONG *plOldState) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxActivate,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxActivate( ITextHost2 *iface, LONG *old_state ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - *plOldState = HandleToLong(SetActiveWindow(This->hWnd)); - return (*plOldState ? S_OK : E_FAIL); + struct host *host = impl_from_ITextHost( iface ); + *old_state = HandleToLong( SetActiveWindow( host->window ) ); + return *old_state ? S_OK : E_FAIL; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxDeactivate(ITextHost *iface, LONG lNewState) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxDeactivate,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxDeactivate( ITextHost2 *iface, LONG new_state ) { - HWND ret = SetActiveWindow(LongToHandle(lNewState)); - return (ret ? S_OK : E_FAIL); + HWND ret = SetActiveWindow( LongToHandle( new_state ) ); + return ret ? S_OK : E_FAIL; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetClientRect(ITextHost *iface, LPRECT prc) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetClientRect,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetClientRect( ITextHost2 *iface, RECT *rect ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - int ret = GetClientRect(This->hWnd, prc); - return (ret ? S_OK : E_FAIL); + struct host *host = impl_from_ITextHost( iface ); + + if (!host->use_set_rect) + { + *rect = host->client_rect; + if (host->client_edge) rect->top += 1; + InflateRect( rect, -1, 0 ); + } + else *rect = host->set_rect; + + return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetViewInset(ITextHost *iface, LPRECT prc) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetViewInset,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetViewInset( ITextHost2 *iface, RECT *rect ) { - prc->top = 0; - prc->left = 0; - prc->bottom = 0; - prc->right = 0; + SetRectEmpty( rect ); return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetCharFormat(ITextHost *iface, const CHARFORMATW **ppCF) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetCharFormat,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetCharFormat( ITextHost2 *iface, const CHARFORMATW **ppCF ) { return E_NOTIMPL; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetParaFormat(ITextHost *iface, const PARAFORMAT **fmt) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetParaFormat,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetParaFormat( ITextHost2 *iface, const PARAFORMAT **fmt ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - *fmt = (const PARAFORMAT *)&This->para_fmt; + struct host *host = impl_from_ITextHost( iface ); + *fmt = (const PARAFORMAT *)&host->para_fmt; return S_OK; } -DECLSPEC_HIDDEN COLORREF __thiscall ITextHostImpl_TxGetSysColor(ITextHost *iface, int nIndex) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSysColor,8) +DECLSPEC_HIDDEN COLORREF __thiscall ITextHostImpl_TxGetSysColor( ITextHost2 *iface, int index ) { - return GetSysColor(nIndex); + struct host *host = impl_from_ITextHost( iface ); + + if (index == COLOR_WINDOW && host->use_back_colour) return host->back_colour; + return GetSysColor( index ); } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetBackStyle(ITextHost *iface, TXTBACKSTYLE *pStyle) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetBackStyle,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetBackStyle( ITextHost2 *iface, TXTBACKSTYLE *style ) { - *pStyle = TXTBACK_OPAQUE; + *style = TXTBACK_OPAQUE; return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetMaxLength(ITextHost *iface, DWORD *pLength) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetMaxLength,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetMaxLength( ITextHost2 *iface, DWORD *length ) { - *pLength = INFINITE; + *length = INFINITE; return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetScrollBars(ITextHost *iface, DWORD *pdwScrollBar) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetScrollBars,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetScrollBars( ITextHost2 *iface, DWORD *scrollbars ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - ME_TextEditor *editor = (ME_TextEditor*)GetWindowLongPtrW(This->hWnd, 0); - const DWORD mask = WS_VSCROLL| - WS_HSCROLL| - ES_AUTOVSCROLL| - ES_AUTOHSCROLL| - ES_DISABLENOSCROLL; - if (editor) - { - *pdwScrollBar = editor->styleFlags & mask; - } else { - DWORD style = GetWindowLongW(This->hWnd, GWL_STYLE); - if (style & WS_VSCROLL) - style |= ES_AUTOVSCROLL; - if (!This->bEmulateVersion10 && (style & WS_HSCROLL)) - style |= ES_AUTOHSCROLL; - *pdwScrollBar = style & mask; - } + struct host *host = impl_from_ITextHost( iface ); + + *scrollbars = host->scrollbars; return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetPasswordChar(ITextHost *iface, WCHAR *pch) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPasswordChar,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetPasswordChar( ITextHost2 *iface, WCHAR *c ) { - *pch = '*'; - return S_OK; + struct host *host = impl_from_ITextHost( iface ); + + *c = host->password_char; + return *c ? S_OK : S_FALSE; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetAcceleratorPos(ITextHost *iface, LONG *pch) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetAcceleratorPos,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetAcceleratorPos( ITextHost2 *iface, LONG *pos ) { - *pch = -1; + *pos = -1; return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetExtent(ITextHost *iface, LPSIZEL lpExtent) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetExtent,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetExtent( ITextHost2 *iface, SIZEL *extent ) { return E_NOTIMPL; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_OnTxCharFormatChange(ITextHost *iface, const CHARFORMATW *pcf) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxCharFormatChange,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_OnTxCharFormatChange( ITextHost2 *iface, const CHARFORMATW *pcf ) { return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_OnTxParaFormatChange(ITextHost *iface, const PARAFORMAT *ppf) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxParaFormatChange,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_OnTxParaFormatChange( ITextHost2 *iface, const PARAFORMAT *ppf ) { return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetPropertyBits(ITextHost *iface, DWORD dwMask, DWORD *pdwBits) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPropertyBits,12) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetPropertyBits( ITextHost2 *iface, DWORD mask, DWORD *bits ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongPtrW(This->hWnd, 0); - DWORD style; - DWORD dwBits = 0; - - if (editor) - { - style = editor->styleFlags; - if (editor->mode & TM_RICHTEXT) - dwBits |= TXTBIT_RICHTEXT; - if (editor->bWordWrap) - dwBits |= TXTBIT_WORDWRAP; - if (style & ECO_AUTOWORDSELECTION) - dwBits |= TXTBIT_AUTOWORDSEL; - } else { - DWORD dwScrollBar; - - style = GetWindowLongW(This->hWnd, GWL_STYLE); - ITextHostImpl_TxGetScrollBars(iface, &dwScrollBar); - - dwBits |= TXTBIT_RICHTEXT|TXTBIT_AUTOWORDSEL; - if (!(dwScrollBar & ES_AUTOHSCROLL)) - dwBits |= TXTBIT_WORDWRAP; - } - - /* Bits that correspond to window styles. */ - if (style & ES_MULTILINE) - dwBits |= TXTBIT_MULTILINE; - if (style & ES_READONLY) - dwBits |= TXTBIT_READONLY; - if (style & ES_PASSWORD) - dwBits |= TXTBIT_USEPASSWORD; - if (!(style & ES_NOHIDESEL)) - dwBits |= TXTBIT_HIDESELECTION; - if (style & ES_SAVESEL) - dwBits |= TXTBIT_SAVESELECTION; - if (style & ES_VERTICAL) - dwBits |= TXTBIT_VERTICAL; - if (style & ES_NOOLEDRAGDROP) - dwBits |= TXTBIT_DISABLEDRAG; - - dwBits |= TXTBIT_ALLOWBEEP; - - /* The following bits are always FALSE because they are probably only - * needed for ITextServices_OnTxPropertyBitsChange: - * TXTBIT_VIEWINSETCHANGE - * TXTBIT_BACKSTYLECHANGE - * TXTBIT_MAXLENGTHCHANGE - * TXTBIT_CHARFORMATCHANGE - * TXTBIT_PARAFORMATCHANGE - * TXTBIT_SHOWACCELERATOR - * TXTBIT_EXTENTCHANGE - * TXTBIT_SELBARCHANGE - * TXTBIT_SCROLLBARCHANGE - * TXTBIT_CLIENTRECTCHANGE - * - * Documented by MSDN as not supported: - * TXTBIT_USECURRENTBKG - */ - - *pdwBits = dwBits & dwMask; + struct host *host = impl_from_ITextHost( iface ); + + *bits = host->props & mask; return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxNotify(ITextHost *iface, DWORD iNotify, void *pv) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxNotify,12) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxNotify( ITextHost2 *iface, DWORD iNotify, void *pv ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - ME_TextEditor *editor = (ME_TextEditor*)GetWindowLongPtrW(This->hWnd, 0); - HWND hwnd = This->hWnd; + struct host *host = impl_from_ITextHost( iface ); UINT id; - if (!editor || !editor->hwndParent) return S_OK; + if (!host->parent) return S_OK; - id = GetWindowLongW(hwnd, GWLP_ID); + id = GetWindowLongW( host->window, GWLP_ID ); switch (iNotify) { @@ -428,16 +488,16 @@ DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxNotify(ITextHost *iface, DWOR if (!info) return E_FAIL; - info->hwndFrom = hwnd; + info->hwndFrom = host->window; info->idFrom = id; info->code = iNotify; - SendMessageW(editor->hwndParent, WM_NOTIFY, id, (LPARAM)info); + SendMessageW( host->parent, WM_NOTIFY, id, (LPARAM)info ); break; } case EN_UPDATE: /* Only sent when the window is visible. */ - if (!IsWindowVisible(hwnd)) + if (!IsWindowVisible( host->window )) break; /* Fall through */ case EN_CHANGE: @@ -447,7 +507,7 @@ DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxNotify(ITextHost *iface, DWOR case EN_MAXTEXT: case EN_SETFOCUS: case EN_VSCROLL: - SendMessageW(editor->hwndParent, WM_COMMAND, MAKEWPARAM(id, iNotify), (LPARAM)hwnd); + SendMessageW( host->parent, WM_COMMAND, MAKEWPARAM( id, iNotify ), (LPARAM)host->window ); break; case EN_MSGFILTER: @@ -459,69 +519,105 @@ DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxNotify(ITextHost *iface, DWOR return S_OK; } -DECLSPEC_HIDDEN HIMC __thiscall ITextHostImpl_TxImmGetContext(ITextHost *iface) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmGetContext,4) +DECLSPEC_HIDDEN HIMC __thiscall ITextHostImpl_TxImmGetContext( ITextHost2 *iface ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - return ImmGetContext(This->hWnd); + struct host *host = impl_from_ITextHost( iface ); + return ImmGetContext( host->window ); } -DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxImmReleaseContext(ITextHost *iface, HIMC himc) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmReleaseContext,8) +DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxImmReleaseContext( ITextHost2 *iface, HIMC context ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - ImmReleaseContext(This->hWnd, himc); + struct host *host = impl_from_ITextHost( iface ); + ImmReleaseContext( host->window, context ); } -DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetSelectionBarWidth(ITextHost *iface, LONG *lSelBarWidth) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSelectionBarWidth,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetSelectionBarWidth( ITextHost2 *iface, LONG *width ) { - ITextHostImpl *This = impl_from_ITextHost(iface); - ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongPtrW(This->hWnd, 0); + struct host *host = impl_from_ITextHost( iface ); - DWORD style = editor ? editor->styleFlags - : GetWindowLongW(This->hWnd, GWL_STYLE); - *lSelBarWidth = (style & ES_SELECTIONBAR) ? 225 : 0; /* in HIMETRIC */ + *width = host->sel_bar ? 225 : 0; /* in HIMETRIC */ return S_OK; } -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetDC,4) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxReleaseDC,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowScrollBar,12) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxEnableScrollBar,12) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollRange,20) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollPos,16) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxInvalidateRect,12) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxViewChange,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxCreateCaret,16) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowCaret,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCaretPos,12) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetTimer,12) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxKillTimer,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScrollWindowEx,32) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCapture,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetFocus,4) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCursor,12) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScreenToClient,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxClientToScreen,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxActivate,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxDeactivate,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetClientRect,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetViewInset,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetCharFormat,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetParaFormat,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSysColor,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetBackStyle,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetMaxLength,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetScrollBars,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPasswordChar,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetAcceleratorPos,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetExtent,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxCharFormatChange,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxParaFormatChange,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPropertyBits,12) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxNotify,12) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmGetContext,4) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmReleaseContext,8) -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSelectionBarWidth,8) -#if defined(__i386__) && !defined(__MINGW32__) /* thiscall functions are i386-specific */ +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxIsDoubleClickPending,4) +DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxIsDoubleClickPending( ITextHost2 *iface ) +{ + return FALSE; +} + +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetWindow,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetWindow( ITextHost2 *iface, HWND *hwnd ) +{ + struct host *host = impl_from_ITextHost( iface ); + *hwnd = host->window; + return S_OK; +} + +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetForegroundWindow,4) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxSetForegroundWindow( ITextHost2 *iface ) +{ + return E_NOTIMPL; +} + +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPalette,4) +DECLSPEC_HIDDEN HPALETTE __thiscall ITextHostImpl_TxGetPalette( ITextHost2 *iface ) +{ + return NULL; +} + +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetEastAsianFlags,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetEastAsianFlags( ITextHost2 *iface, LONG *flags ) +{ + return E_NOTIMPL; +} + +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCursor2,12) +DECLSPEC_HIDDEN HCURSOR __thiscall ITextHostImpl_TxSetCursor2( ITextHost2 *iface, HCURSOR cursor, BOOL text ) +{ + return NULL; +} + +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxFreeTextServicesNotification,4) +DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxFreeTextServicesNotification( ITextHost2 *iface ) +{ + return; +} + +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetEditStyle,12) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetEditStyle( ITextHost2 *iface, DWORD item, DWORD *data ) +{ + return E_NOTIMPL; +} + +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetWindowStyles,12) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetWindowStyles( ITextHost2 *iface, DWORD *style, DWORD *ex_style ) +{ + return E_NOTIMPL; +} + +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowDropCaret,16) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxShowDropCaret( ITextHost2 *iface, BOOL show, HDC hdc, const RECT *rect ) +{ + return E_NOTIMPL; +} + +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxDestroyCaret,4) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxDestroyCaret( ITextHost2 *iface ) +{ + return E_NOTIMPL; +} + +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetHorzExtent,8) +DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetHorzExtent( ITextHost2 *iface, LONG *horz_extent ) +{ + return E_NOTIMPL; +} + + +#ifdef __ASM_USE_THISCALL_WRAPPER #define STDCALL(func) (void *) __stdcall_ ## func #ifdef _MSC_VER @@ -584,8 +680,22 @@ DEFINE_STDCALL_WRAPPER(38,ITextHostImpl_TxNotify,12) DEFINE_STDCALL_WRAPPER(39,ITextHostImpl_TxImmGetContext,4) DEFINE_STDCALL_WRAPPER(40,ITextHostImpl_TxImmReleaseContext,8) DEFINE_STDCALL_WRAPPER(41,ITextHostImpl_TxGetSelectionBarWidth,8) - -const ITextHostVtbl itextHostStdcallVtbl = { +/* ITextHost2 */ +DEFINE_STDCALL_WRAPPER(42,ITextHostImpl_TxIsDoubleClickPending,4) +DEFINE_STDCALL_WRAPPER(43,ITextHostImpl_TxGetWindow,8) +DEFINE_STDCALL_WRAPPER(44,ITextHostImpl_TxSetForegroundWindow,4) +DEFINE_STDCALL_WRAPPER(45,ITextHostImpl_TxGetPalette,4) +DEFINE_STDCALL_WRAPPER(46,ITextHostImpl_TxGetEastAsianFlags,8) +DEFINE_STDCALL_WRAPPER(47,ITextHostImpl_TxSetCursor2,12) +DEFINE_STDCALL_WRAPPER(48,ITextHostImpl_TxFreeTextServicesNotification,4) +DEFINE_STDCALL_WRAPPER(49,ITextHostImpl_TxGetEditStyle,12) +DEFINE_STDCALL_WRAPPER(50,ITextHostImpl_TxGetWindowStyles,12) +DEFINE_STDCALL_WRAPPER(51,ITextHostImpl_TxShowDropCaret,16) +DEFINE_STDCALL_WRAPPER(52,ITextHostImpl_TxDestroyCaret,4) +DEFINE_STDCALL_WRAPPER(53,ITextHostImpl_TxGetHorzExtent,8) + +const ITextHost2Vtbl text_host2_stdcall_vtbl = +{ NULL, NULL, NULL, @@ -628,11 +738,25 @@ const ITextHostVtbl itextHostStdcallVtbl = { STDCALL(ITextHostImpl_TxImmGetContext), STDCALL(ITextHostImpl_TxImmReleaseContext), STDCALL(ITextHostImpl_TxGetSelectionBarWidth), +/* ITextHost2 */ + STDCALL(ITextHostImpl_TxIsDoubleClickPending), + STDCALL(ITextHostImpl_TxGetWindow), + STDCALL(ITextHostImpl_TxSetForegroundWindow), + STDCALL(ITextHostImpl_TxGetPalette), + STDCALL(ITextHostImpl_TxGetEastAsianFlags), + STDCALL(ITextHostImpl_TxSetCursor2), + STDCALL(ITextHostImpl_TxFreeTextServicesNotification), + STDCALL(ITextHostImpl_TxGetEditStyle), + STDCALL(ITextHostImpl_TxGetWindowStyles), + STDCALL(ITextHostImpl_TxShowDropCaret), + STDCALL(ITextHostImpl_TxDestroyCaret), + STDCALL(ITextHostImpl_TxGetHorzExtent) }; -#endif /* __i386__ */ +#endif /* __ASM_USE_THISCALL_WRAPPER */ -static const ITextHostVtbl textHostVtbl = { +static const ITextHost2Vtbl textHostVtbl = +{ ITextHostImpl_QueryInterface, ITextHostImpl_AddRef, ITextHostImpl_Release, @@ -675,4 +799,864 @@ static const ITextHostVtbl textHostVtbl = { THISCALL(ITextHostImpl_TxImmGetContext), THISCALL(ITextHostImpl_TxImmReleaseContext), THISCALL(ITextHostImpl_TxGetSelectionBarWidth), +/* ITextHost2 */ + THISCALL(ITextHostImpl_TxIsDoubleClickPending), + THISCALL(ITextHostImpl_TxGetWindow), + THISCALL(ITextHostImpl_TxSetForegroundWindow), + THISCALL(ITextHostImpl_TxGetPalette), + THISCALL(ITextHostImpl_TxGetEastAsianFlags), + THISCALL(ITextHostImpl_TxSetCursor2), + THISCALL(ITextHostImpl_TxFreeTextServicesNotification), + THISCALL(ITextHostImpl_TxGetEditStyle), + THISCALL(ITextHostImpl_TxGetWindowStyles), + THISCALL(ITextHostImpl_TxShowDropCaret), + THISCALL(ITextHostImpl_TxDestroyCaret), + THISCALL(ITextHostImpl_TxGetHorzExtent) +}; + +static const char * const edit_messages[] = +{ + "EM_GETSEL", "EM_SETSEL", "EM_GETRECT", "EM_SETRECT", + "EM_SETRECTNP", "EM_SCROLL", "EM_LINESCROLL", "EM_SCROLLCARET", + "EM_GETMODIFY", "EM_SETMODIFY", "EM_GETLINECOUNT", "EM_LINEINDEX", + "EM_SETHANDLE", "EM_GETHANDLE", "EM_GETTHUMB", "EM_UNKNOWN_BF", + "EM_UNKNOWN_C0", "EM_LINELENGTH", "EM_REPLACESEL", "EM_UNKNOWN_C3", + "EM_GETLINE", "EM_LIMITTEXT", "EM_CANUNDO", "EM_UNDO", + "EM_FMTLINES", "EM_LINEFROMCHAR", "EM_UNKNOWN_CA", "EM_SETTABSTOPS", + "EM_SETPASSWORDCHAR", "EM_EMPTYUNDOBUFFER", "EM_GETFIRSTVISIBLELINE", "EM_SETREADONLY", + "EM_SETWORDBREAKPROC", "EM_GETWORDBREAKPROC", "EM_GETPASSWORDCHAR", "EM_SETMARGINS", + "EM_GETMARGINS", "EM_GETLIMITTEXT", "EM_POSFROMCHAR", "EM_CHARFROMPOS", + "EM_SETIMESTATUS", "EM_GETIMESTATUS" }; + +static const char * const richedit_messages[] = +{ + "EM_CANPASTE", "EM_DISPLAYBAND", "EM_EXGETSEL", "EM_EXLIMITTEXT", + "EM_EXLINEFROMCHAR", "EM_EXSETSEL", "EM_FINDTEXT", "EM_FORMATRANGE", + "EM_GETCHARFORMAT", "EM_GETEVENTMASK", "EM_GETOLEINTERFACE", "EM_GETPARAFORMAT", + "EM_GETSELTEXT", "EM_HIDESELECTION", "EM_PASTESPECIAL", "EM_REQUESTRESIZE", + "EM_SELECTIONTYPE", "EM_SETBKGNDCOLOR", "EM_SETCHARFORMAT", "EM_SETEVENTMASK", + "EM_SETOLECALLBACK", "EM_SETPARAFORMAT", "EM_SETTARGETDEVICE", "EM_STREAMIN", + "EM_STREAMOUT", "EM_GETTEXTRANGE", "EM_FINDWORDBREAK", "EM_SETOPTIONS", + "EM_GETOPTIONS", "EM_FINDTEXTEX", "EM_GETWORDBREAKPROCEX", "EM_SETWORDBREAKPROCEX", + "EM_SETUNDOLIMIT", "EM_UNKNOWN_USER_83", "EM_REDO", "EM_CANREDO", + "EM_GETUNDONAME", "EM_GETREDONAME", "EM_STOPGROUPTYPING", "EM_SETTEXTMODE", + "EM_GETTEXTMODE", "EM_AUTOURLDETECT", "EM_GETAUTOURLDETECT", "EM_SETPALETTE", + "EM_GETTEXTEX", "EM_GETTEXTLENGTHEX", "EM_SHOWSCROLLBAR", "EM_SETTEXTEX", + "EM_UNKNOWN_USER_98", "EM_UNKNOWN_USER_99", "EM_SETPUNCTUATION", "EM_GETPUNCTUATION", + "EM_SETWORDWRAPMODE", "EM_GETWORDWRAPMODE", "EM_SETIMECOLOR", "EM_GETIMECOLOR", + "EM_SETIMEOPTIONS", "EM_GETIMEOPTIONS", "EM_CONVPOSITION", "EM_UNKNOWN_USER_109", + "EM_UNKNOWN_USER_110", "EM_UNKNOWN_USER_111", "EM_UNKNOWN_USER_112", "EM_UNKNOWN_USER_113", + "EM_UNKNOWN_USER_114", "EM_UNKNOWN_USER_115", "EM_UNKNOWN_USER_116", "EM_UNKNOWN_USER_117", + "EM_UNKNOWN_USER_118", "EM_UNKNOWN_USER_119", "EM_SETLANGOPTIONS", "EM_GETLANGOPTIONS", + "EM_GETIMECOMPMODE", "EM_FINDTEXTW", "EM_FINDTEXTEXW", "EM_RECONVERSION", + "EM_SETIMEMODEBIAS", "EM_GETIMEMODEBIAS" +}; + +static const char *get_msg_name( UINT msg ) +{ + if (msg >= EM_GETSEL && msg <= EM_CHARFROMPOS) + return edit_messages[msg - EM_GETSEL]; + if (msg >= EM_CANPASTE && msg <= EM_GETIMEMODEBIAS) + return richedit_messages[msg - EM_CANPASTE]; + return ""; +} + +static BOOL create_windowed_editor( HWND hwnd, CREATESTRUCTW *create, BOOL emulate_10 ) +{ + struct host *host = host_create( hwnd, create, emulate_10 ); + IUnknown *unk; + HRESULT hr; + + if (!host) return FALSE; + + hr = create_text_services( NULL, (ITextHost *)&host->ITextHost_iface, &unk, emulate_10 ); + if (FAILED( hr )) + { + ITextHost2_Release( &host->ITextHost_iface ); + return FALSE; + } + IUnknown_QueryInterface( unk, &IID_ITextServices, (void **)&host->text_srv ); + IUnknown_Release( unk ); + + SetWindowLongPtrW( hwnd, 0, (LONG_PTR)host ); + + return TRUE; +} + +static HRESULT get_lineA( ITextServices *text_srv, WPARAM wparam, LPARAM lparam, LRESULT *res ) +{ + LRESULT len = USHRT_MAX; + WORD sizeA; + HRESULT hr; + WCHAR *buf; + + *res = 0; + sizeA = *(WORD *)lparam; + *(WORD *)lparam = 0; + if (!sizeA) return S_OK; + buf = heap_alloc( len * sizeof(WCHAR) ); + if (!buf) return E_OUTOFMEMORY; + *(WORD *)buf = len; + hr = ITextServices_TxSendMessage( text_srv, EM_GETLINE, wparam, (LPARAM)buf, &len ); + if (hr == S_OK && len) + { + len = WideCharToMultiByte( CP_ACP, 0, buf, len, (char *)lparam, sizeA, NULL, NULL ); + if (!len && GetLastError() == ERROR_INSUFFICIENT_BUFFER) len = sizeA; + if (len < sizeA) ((char *)lparam)[len] = '\0'; + *res = len; + } + heap_free( buf ); + return hr; +} + +static HRESULT get_text_rangeA( struct host *host, TEXTRANGEA *rangeA, LRESULT *res ) +{ + TEXTRANGEW range; + HRESULT hr; + unsigned int count; + LRESULT len; + + *res = 0; + if (rangeA->chrg.cpMin < 0) return S_OK; + ITextServices_TxSendMessage( host->text_srv, WM_GETTEXTLENGTH, 0, 0, &len ); + range.chrg = rangeA->chrg; + if ((range.chrg.cpMin == 0 && range.chrg.cpMax == -1) || range.chrg.cpMax > len) + range.chrg.cpMax = len; + if (range.chrg.cpMin >= range.chrg.cpMax) return S_OK; + count = range.chrg.cpMax - range.chrg.cpMin + 1; + range.lpstrText = heap_alloc( count * sizeof(WCHAR) ); + if (!range.lpstrText) return E_OUTOFMEMORY; + hr = ITextServices_TxSendMessage( host->text_srv, EM_GETTEXTRANGE, 0, (LPARAM)&range, &len ); + if (hr == S_OK && len) + { + if (!host->emulate_10) count = INT_MAX; + len = WideCharToMultiByte( CP_ACP, 0, range.lpstrText, -1, rangeA->lpstrText, count, NULL, NULL ); + if (!host->emulate_10) *res = len - 1; + else + { + *res = count - 1; + rangeA->lpstrText[*res] = '\0'; + } + } + heap_free( range.lpstrText ); + return hr; +} + +static HRESULT set_options( struct host *host, DWORD op, DWORD value, LRESULT *res ) +{ + DWORD style, old_options, new_options, change, props_mask = 0; + DWORD mask = ECO_AUTOWORDSELECTION | ECO_AUTOVSCROLL | ECO_AUTOHSCROLL | ECO_NOHIDESEL | ECO_READONLY | + ECO_WANTRETURN | ECO_SAVESEL | ECO_SELECTIONBAR | ECO_VERTICAL; + + new_options = old_options = SendMessageW( host->window, EM_GETOPTIONS, 0, 0 ); + + switch (op) + { + case ECOOP_SET: + new_options = value; + break; + case ECOOP_OR: + new_options |= value; + break; + case ECOOP_AND: + new_options &= value; + break; + case ECOOP_XOR: + new_options ^= value; + } + new_options &= mask; + + change = (new_options ^ old_options); + + if (change & ECO_AUTOWORDSELECTION) + { + host->props ^= TXTBIT_AUTOWORDSEL; + props_mask |= TXTBIT_AUTOWORDSEL; + } + if (change & ECO_AUTOVSCROLL) + { + host->scrollbars ^= WS_VSCROLL; + props_mask |= TXTBIT_SCROLLBARCHANGE; + } + if (change & ECO_AUTOHSCROLL) + { + host->scrollbars ^= WS_HSCROLL; + props_mask |= TXTBIT_SCROLLBARCHANGE; + } + if (change & ECO_NOHIDESEL) + { + host->props ^= TXTBIT_HIDESELECTION; + props_mask |= TXTBIT_HIDESELECTION; + } + if (change & ECO_READONLY) + { + host->props ^= TXTBIT_READONLY; + props_mask |= TXTBIT_READONLY; + } + if (change & ECO_SAVESEL) + { + host->props ^= TXTBIT_SAVESELECTION; + props_mask |= TXTBIT_SAVESELECTION; + } + if (change & ECO_SELECTIONBAR) + { + host->sel_bar ^= 1; + props_mask |= TXTBIT_SELBARCHANGE; + if (host->use_set_rect) + { + int width = SELECTIONBAR_WIDTH; + host->set_rect.left += host->sel_bar ? width : -width; + props_mask |= TXTBIT_CLIENTRECTCHANGE; + } + } + if (change & ECO_VERTICAL) + { + host->props ^= TXTBIT_VERTICAL; + props_mask |= TXTBIT_VERTICAL; + } + if (change & ECO_WANTRETURN) host->want_return ^= 1; + + if (props_mask) + ITextServices_OnTxPropertyBitsChange( host->text_srv, props_mask, host->props & props_mask ); + + *res = new_options; + + mask &= ~ECO_AUTOWORDSELECTION; /* doesn't correspond to a window style */ + style = GetWindowLongW( host->window, GWL_STYLE ); + style = (style & ~mask) | (*res & mask); + SetWindowLongW( host->window, GWL_STYLE, style ); + return S_OK; +} + +/* handle dialog mode VK_RETURN. Returns TRUE if message has been processed */ +static BOOL handle_dialog_enter( struct host *host ) +{ + BOOL ctrl_is_down = GetKeyState( VK_CONTROL ) & 0x8000; + + if (ctrl_is_down) return TRUE; + + if (host->want_return) return FALSE; + + if (host->parent) + { + DWORD id = SendMessageW( host->parent, DM_GETDEFID, 0, 0 ); + if (HIWORD( id ) == DC_HASDEFID) + { + HWND ctrl = GetDlgItem( host->parent, LOWORD( id )); + if (ctrl) + { + SendMessageW( host->parent, WM_NEXTDLGCTL, (WPARAM)ctrl, TRUE ); + PostMessageW( ctrl, WM_KEYDOWN, VK_RETURN, 0 ); + } + } + } + return TRUE; +} + +static LRESULT send_msg_filter( struct host *host, UINT msg, WPARAM *wparam, LPARAM *lparam ) +{ + MSGFILTER msgf; + LRESULT res; + + if (!host->parent) return 0; + msgf.nmhdr.hwndFrom = host->window; + msgf.nmhdr.idFrom = GetWindowLongW( host->window, GWLP_ID ); + msgf.nmhdr.code = EN_MSGFILTER; + msgf.msg = msg; + msgf.wParam = *wparam; + msgf.lParam = *lparam; + if ((res = SendMessageW( host->parent, WM_NOTIFY, msgf.nmhdr.idFrom, (LPARAM)&msgf ))) + return res; + *wparam = msgf.wParam; + *lparam = msgf.lParam; + + return 0; +} + +static LRESULT RichEditWndProc_common( HWND hwnd, UINT msg, WPARAM wparam, + LPARAM lparam, BOOL unicode ) +{ + struct host *host; + HRESULT hr = S_OK; + LRESULT res = 0; + + TRACE( "enter hwnd %p msg %04x (%s) %lx %lx, unicode %d\n", + hwnd, msg, get_msg_name(msg), wparam, lparam, unicode ); + + host = (struct host *)GetWindowLongPtrW( hwnd, 0 ); + if (!host) + { + if (msg == WM_NCCREATE) + { + CREATESTRUCTW *pcs = (CREATESTRUCTW *)lparam; + + TRACE( "WM_NCCREATE: hwnd %p style 0x%08x\n", hwnd, pcs->style ); + return create_windowed_editor( hwnd, pcs, FALSE ); + } + else return DefWindowProcW( hwnd, msg, wparam, lparam ); + } + + if ((((host->event_mask & ENM_KEYEVENTS) && msg >= WM_KEYFIRST && msg <= WM_KEYLAST) || + ((host->event_mask & ENM_MOUSEEVENTS) && msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) || + ((host->event_mask & ENM_SCROLLEVENTS) && msg >= WM_HSCROLL && msg <= WM_VSCROLL)) && + send_msg_filter( host, msg, &wparam, &lparam )) + { + TRACE( "exit (filtered) hwnd %p msg %04x (%s) %lx %lx -> %lu\n", + hwnd, msg, get_msg_name(msg), wparam, lparam, res ); + return res; + } + + switch (msg) + { + case WM_CHAR: + { + WCHAR wc = wparam; + + if (!unicode) MultiByteToWideChar( CP_ACP, 0, (char *)&wparam, 1, &wc, 1 ); + if (wparam == '\r' && host->dialog_mode && host->emulate_10 && handle_dialog_enter( host )) break; + hr = ITextServices_TxSendMessage( host->text_srv, msg, wc, lparam, &res ); + break; + } + + case WM_CREATE: + { + CREATESTRUCTW *createW = (CREATESTRUCTW *)lparam; + CREATESTRUCTA *createA = (CREATESTRUCTA *)lparam; + void *text; + WCHAR *textW = NULL; + LONG codepage = unicode ? CP_UNICODE : CP_ACP; + int len; + + ITextServices_OnTxInPlaceActivate( host->text_srv, NULL ); + + if (lparam) + { + text = unicode ? (void *)createW->lpszName : (void *)createA->lpszName; + textW = ME_ToUnicode( codepage, text, &len ); + } + ITextServices_TxSetText( host->text_srv, textW ); + if (lparam) ME_EndToUnicode( codepage, textW ); + break; + } + case WM_DESTROY: + ITextHost2_Release( &host->ITextHost_iface ); + return 0; + + case WM_ERASEBKGND: + { + HDC hdc = (HDC)wparam; + RECT rc; + HBRUSH brush; + + if (GetUpdateRect( hwnd, &rc, TRUE )) + { + brush = CreateSolidBrush( ITextHost_TxGetSysColor( &host->ITextHost_iface, COLOR_WINDOW ) ); + FillRect( hdc, &rc, brush ); + DeleteObject( brush ); + } + return 1; + } + case EM_FINDTEXT: + { + FINDTEXTW *params = (FINDTEXTW *)lparam; + FINDTEXTW new_params; + int len; + + if (!unicode) + { + new_params.chrg = params->chrg; + new_params.lpstrText = ME_ToUnicode( CP_ACP, (char *)params->lpstrText, &len ); + params = &new_params; + } + hr = ITextServices_TxSendMessage( host->text_srv, EM_FINDTEXTW, wparam, (LPARAM)params, &res ); + if (!unicode) ME_EndToUnicode( CP_ACP, (WCHAR *)new_params.lpstrText ); + break; + } + case EM_FINDTEXTEX: + { + FINDTEXTEXA *paramsA = (FINDTEXTEXA *)lparam; + FINDTEXTEXW *params = (FINDTEXTEXW *)lparam; + FINDTEXTEXW new_params; + int len; + + if (!unicode) + { + new_params.chrg = params->chrg; + new_params.lpstrText = ME_ToUnicode( CP_ACP, (char *)params->lpstrText, &len ); + params = &new_params; + } + hr = ITextServices_TxSendMessage( host->text_srv, EM_FINDTEXTEXW, wparam, (LPARAM)params, &res ); + if (!unicode) + { + ME_EndToUnicode( CP_ACP, (WCHAR *)new_params.lpstrText ); + paramsA->chrgText = params->chrgText; + } + break; + } + case WM_GETDLGCODE: + if (lparam) host->dialog_mode = TRUE; + + res = DLGC_WANTCHARS | DLGC_WANTTAB | DLGC_WANTARROWS; + if (host->props & TXTBIT_MULTILINE) res |= DLGC_WANTMESSAGE; + if (!(host->props & TXTBIT_SAVESELECTION)) res |= DLGC_HASSETSEL; + break; + + case EM_GETLINE: + if (unicode) hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res ); + else hr = get_lineA( host->text_srv, wparam, lparam, &res ); + break; + + case EM_GETPASSWORDCHAR: + ITextHost_TxGetPasswordChar( &host->ITextHost_iface, (WCHAR *)&res ); + break; + + case EM_GETRECT: + hr = ITextHost_TxGetClientRect( &host->ITextHost_iface, (RECT *)lparam ); + break; + + case EM_GETSELTEXT: + { + TEXTRANGEA range; + + if (unicode) hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res ); + else + { + ITextServices_TxSendMessage( host->text_srv, EM_EXGETSEL, 0, (LPARAM)&range.chrg, &res ); + range.lpstrText = (char *)lparam; + range.lpstrText[0] = '\0'; + hr = get_text_rangeA( host, &range, &res ); + } + break; + } + case EM_GETOPTIONS: + if (host->props & TXTBIT_READONLY) res |= ECO_READONLY; + if (!(host->props & TXTBIT_HIDESELECTION)) res |= ECO_NOHIDESEL; + if (host->props & TXTBIT_SAVESELECTION) res |= ECO_SAVESEL; + if (host->props & TXTBIT_AUTOWORDSEL) res |= ECO_AUTOWORDSELECTION; + if (host->props & TXTBIT_VERTICAL) res |= ECO_VERTICAL; + if (host->scrollbars & ES_AUTOHSCROLL) res |= ECO_AUTOHSCROLL; + if (host->scrollbars & ES_AUTOVSCROLL) res |= ECO_AUTOVSCROLL; + if (host->want_return) res |= ECO_WANTRETURN; + if (host->sel_bar) res |= ECO_SELECTIONBAR; + break; + + case WM_GETTEXT: + { + GETTEXTEX params; + + params.cb = wparam * (unicode ? sizeof(WCHAR) : sizeof(CHAR)); + params.flags = GT_USECRLF; + params.codepage = unicode ? CP_UNICODE : CP_ACP; + params.lpDefaultChar = NULL; + params.lpUsedDefChar = NULL; + hr = ITextServices_TxSendMessage( host->text_srv, EM_GETTEXTEX, (WPARAM)¶ms, lparam, &res ); + break; + } + case WM_GETTEXTLENGTH: + { + GETTEXTLENGTHEX params; + + params.flags = GTL_CLOSE | (host->emulate_10 ? 0 : GTL_USECRLF) | GTL_NUMCHARS; + params.codepage = unicode ? CP_UNICODE : CP_ACP; + hr = ITextServices_TxSendMessage( host->text_srv, EM_GETTEXTLENGTHEX, (WPARAM)¶ms, 0, &res ); + break; + } + case EM_GETTEXTRANGE: + if (unicode) hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res ); + else hr = get_text_rangeA( host, (TEXTRANGEA *)lparam, &res ); + break; + + case WM_KEYDOWN: + switch (LOWORD( wparam )) + { + case VK_ESCAPE: + if (host->dialog_mode && host->parent) + PostMessageW( host->parent, WM_CLOSE, 0, 0 ); + break; + case VK_TAB: + if (host->dialog_mode && host->parent) + SendMessageW( host->parent, WM_NEXTDLGCTL, GetKeyState( VK_SHIFT ) & 0x8000, 0 ); + break; + case VK_RETURN: + if (host->dialog_mode && !host->emulate_10 && handle_dialog_enter( host )) break; + /* fall through */ + default: + hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res ); + } + break; + + case WM_PAINT: + case WM_PRINTCLIENT: + { + HDC hdc; + RECT rc, client, update; + PAINTSTRUCT ps; + HBRUSH brush = CreateSolidBrush( ITextHost_TxGetSysColor( &host->ITextHost_iface, COLOR_WINDOW ) ); + + ITextHost_TxGetClientRect( &host->ITextHost_iface, &client ); + + if (msg == WM_PAINT) + { + hdc = BeginPaint( hwnd, &ps ); + update = ps.rcPaint; + } + else + { + hdc = (HDC)wparam; + update = client; + } + + brush = SelectObject( hdc, brush ); + + /* Erase area outside of the formatting rectangle */ + if (update.top < client.top) + { + rc = update; + rc.bottom = client.top; + PatBlt( hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY ); + update.top = client.top; + } + if (update.bottom > client.bottom) + { + rc = update; + rc.top = client.bottom; + PatBlt( hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY ); + update.bottom = client.bottom; + } + if (update.left < client.left) + { + rc = update; + rc.right = client.left; + PatBlt( hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY ); + update.left = client.left; + } + if (update.right > client.right) + { + rc = update; + rc.left = client.right; + PatBlt( hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY ); + update.right = client.right; + } + + ITextServices_TxDraw( host->text_srv, DVASPECT_CONTENT, 0, NULL, NULL, hdc, NULL, NULL, NULL, + &update, NULL, 0, TXTVIEW_ACTIVE ); + DeleteObject( SelectObject( hdc, brush ) ); + if (msg == WM_PAINT) EndPaint( hwnd, &ps ); + return 0; + } + case EM_REPLACESEL: + { + int len; + LONG codepage = unicode ? CP_UNICODE : CP_ACP; + WCHAR *text = ME_ToUnicode( codepage, (void *)lparam, &len ); + + hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, (LPARAM)text, &res ); + ME_EndToUnicode( codepage, text ); + res = len; + break; + } + case EM_SETBKGNDCOLOR: + res = ITextHost_TxGetSysColor( &host->ITextHost_iface, COLOR_WINDOW ); + host->use_back_colour = !wparam; + if (host->use_back_colour) host->back_colour = lparam; + InvalidateRect( hwnd, NULL, TRUE ); + break; + + case WM_SETCURSOR: + { + POINT pos; + RECT rect; + + if (hwnd != (HWND)wparam) break; + GetCursorPos( &pos ); + ScreenToClient( hwnd, &pos ); + ITextHost_TxGetClientRect( &host->ITextHost_iface, &rect ); + if (PtInRect( &rect, pos )) + ITextServices_OnTxSetCursor( host->text_srv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, NULL, pos.x, pos.y ); + else ITextHost_TxSetCursor( &host->ITextHost_iface, LoadCursorW( NULL, MAKEINTRESOURCEW( IDC_ARROW ) ), FALSE ); + break; + } + case EM_SETEVENTMASK: + host->event_mask = lparam; + hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res ); + break; + + case EM_SETOPTIONS: + hr = set_options( host, wparam, lparam, &res ); + break; + + case EM_SETPASSWORDCHAR: + if (wparam == host->password_char) break; + host->password_char = wparam; + if (wparam) host->props |= TXTBIT_USEPASSWORD; + else host->props &= ~TXTBIT_USEPASSWORD; + ITextServices_OnTxPropertyBitsChange( host->text_srv, TXTBIT_USEPASSWORD, host->props & TXTBIT_USEPASSWORD ); + break; + + case EM_SETREADONLY: + { + DWORD op = wparam ? ECOOP_OR : ECOOP_AND; + DWORD mask = wparam ? ECO_READONLY : ~ECO_READONLY; + + SendMessageW( hwnd, EM_SETOPTIONS, op, mask ); + return 1; + } + case EM_SETRECT: + case EM_SETRECTNP: + { + RECT *rc = (RECT *)lparam; + + if (!rc) host->use_set_rect = 0; + else + { + if (wparam >= 2) break; + host->set_rect = *rc; + if (host->client_edge) + { + InflateRect( &host->set_rect, 1, 0 ); + host->set_rect.top -= 1; + } + if (!wparam) IntersectRect( &host->set_rect, &host->set_rect, &host->client_rect ); + host->use_set_rect = 1; + } + ITextServices_OnTxPropertyBitsChange( host->text_srv, TXTBIT_CLIENTRECTCHANGE, 0 ); + break; + } + case WM_SETTEXT: + { + char *textA = (char *)lparam; + WCHAR *text = (WCHAR *)lparam; + int len; + + if (!unicode && textA && strncmp( textA, "{\\rtf", 5 ) && strncmp( textA, "{\\urtf", 6 )) + text = ME_ToUnicode( CP_ACP, textA, &len ); + hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, (LPARAM)text, &res ); + if (text != (WCHAR *)lparam) ME_EndToUnicode( CP_ACP, text ); + break; + } + case EM_SHOWSCROLLBAR: + { + DWORD mask = 0, new; + + if (wparam == SB_HORZ) mask = WS_HSCROLL; + else if (wparam == SB_VERT) mask = WS_VSCROLL; + else if (wparam == SB_BOTH) mask = WS_HSCROLL | WS_VSCROLL; + + if (mask) + { + new = lparam ? mask : 0; + if ((host->scrollbars & mask) != new) + { + host->scrollbars &= ~mask; + host->scrollbars |= new; + ITextServices_OnTxPropertyBitsChange( host->text_srv, TXTBIT_SCROLLBARCHANGE, 0 ); + } + } + + res = 0; + break; + } + case WM_WINDOWPOSCHANGED: + { + RECT client; + WINDOWPOS *winpos = (WINDOWPOS *)lparam; + + hr = S_FALSE; /* call defwndproc */ + if (winpos->flags & SWP_NOCLIENTSIZE) break; + GetClientRect( hwnd, &client ); + if (host->use_set_rect) + { + host->set_rect.right += client.right - host->client_rect.right; + host->set_rect.bottom += client.bottom - host->client_rect.bottom; + } + host->client_rect = client; + ITextServices_OnTxPropertyBitsChange( host->text_srv, TXTBIT_CLIENTRECTCHANGE, 0 ); + break; + } + default: + hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res ); + } + + if (hr == S_FALSE) + res = DefWindowProcW( hwnd, msg, wparam, lparam ); + + TRACE( "exit hwnd %p msg %04x (%s) %lx %lx, unicode %d -> %lu\n", + hwnd, msg, get_msg_name(msg), wparam, lparam, unicode, res ); + + return res; +} + +static LRESULT WINAPI RichEditWndProcW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + BOOL unicode = TRUE; + + /* Under Win9x RichEdit20W returns ANSI strings, see the tests. */ + if (msg == WM_GETTEXT && (GetVersion() & 0x80000000)) + unicode = FALSE; + + return RichEditWndProc_common( hwnd, msg, wparam, lparam, unicode ); +} + +static LRESULT WINAPI RichEditWndProcA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + return RichEditWndProc_common( hwnd, msg, wparam, lparam, FALSE ); +} + +/****************************************************************** + * RichEditANSIWndProc (RICHED20.10) + */ +LRESULT WINAPI RichEditANSIWndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + return RichEditWndProcA( hwnd, msg, wparam, lparam ); +} + +/****************************************************************** + * RichEdit10ANSIWndProc (RICHED20.9) + */ +LRESULT WINAPI RichEdit10ANSIWndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + if (msg == WM_NCCREATE && !GetWindowLongPtrW( hwnd, 0 )) + { + CREATESTRUCTW *pcs = (CREATESTRUCTW *)lparam; + + TRACE( "WM_NCCREATE: hwnd %p style 0x%08x\n", hwnd, pcs->style ); + return create_windowed_editor( hwnd, pcs, TRUE ); + } + return RichEditANSIWndProc( hwnd, msg, wparam, lparam ); +} + +static LRESULT WINAPI REComboWndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + /* FIXME: Not implemented */ + TRACE( "hwnd %p msg %04x (%s) %08lx %08lx\n", + hwnd, msg, get_msg_name( msg ), wparam, lparam ); + return DefWindowProcW( hwnd, msg, wparam, lparam ); +} + +static LRESULT WINAPI REListWndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + /* FIXME: Not implemented */ + TRACE( "hwnd %p msg %04x (%s) %08lx %08lx\n", + hwnd, msg, get_msg_name( msg ), wparam, lparam ); + return DefWindowProcW( hwnd, msg, wparam, lparam ); +} + +/****************************************************************** + * REExtendedRegisterClass (RICHED20.8) + * + * FIXME undocumented + * Need to check for errors and implement controls and callbacks + */ +LRESULT WINAPI REExtendedRegisterClass( void ) +{ + WNDCLASSW wc; + UINT result; + + FIXME( "semi stub\n" ); + wc.cbClsExtra = 0; + wc.cbWndExtra = 4; + wc.hInstance = NULL; + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + + if (!listbox_registered) + { + wc.style = CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS; + wc.lpfnWndProc = REListWndProc; + wc.lpszClassName = L"REListBox20W"; + if (RegisterClassW( &wc )) listbox_registered = TRUE; + } + + if (!combobox_registered) + { + wc.style = CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW; + wc.lpfnWndProc = REComboWndProc; + wc.lpszClassName = L"REComboBox20W"; + if (RegisterClassW( &wc )) combobox_registered = TRUE; + } + + result = 0; + if (listbox_registered) result += 1; + if (combobox_registered) result += 2; + + return result; +} + +static BOOL register_classes( HINSTANCE instance ) +{ + WNDCLASSW wcW; + WNDCLASSA wcA; + + wcW.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS; + wcW.lpfnWndProc = RichEditWndProcW; + wcW.cbClsExtra = 0; + wcW.cbWndExtra = sizeof(struct host *); + wcW.hInstance = NULL; /* hInstance would register DLL-local class */ + wcW.hIcon = NULL; + wcW.hCursor = LoadCursorW( NULL, (LPWSTR)IDC_IBEAM ); + wcW.hbrBackground = GetStockObject( NULL_BRUSH ); + wcW.lpszMenuName = NULL; + + if (!(GetVersion() & 0x80000000)) + { + wcW.lpszClassName = RICHEDIT_CLASS20W; + if (!RegisterClassW( &wcW )) return FALSE; + wcW.lpszClassName = MSFTEDIT_CLASS; + if (!RegisterClassW( &wcW )) return FALSE; + } + else + { + /* WNDCLASSA/W have the same layout */ + wcW.lpszClassName = (LPCWSTR)"RichEdit20W"; + if (!RegisterClassA( (WNDCLASSA *)&wcW )) return FALSE; + wcW.lpszClassName = (LPCWSTR)"RichEdit50W"; + if (!RegisterClassA( (WNDCLASSA *)&wcW )) return FALSE; + } + + wcA.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS; + wcA.lpfnWndProc = RichEditWndProcA; + wcA.cbClsExtra = 0; + wcA.cbWndExtra = sizeof(struct host *); + wcA.hInstance = NULL; /* hInstance would register DLL-local class */ + wcA.hIcon = NULL; + wcA.hCursor = LoadCursorW( NULL, (LPWSTR)IDC_IBEAM ); + wcA.hbrBackground = GetStockObject(NULL_BRUSH); + wcA.lpszMenuName = NULL; + wcA.lpszClassName = RICHEDIT_CLASS20A; + if (!RegisterClassA( &wcA )) return FALSE; + wcA.lpszClassName = "RichEdit50A"; + if (!RegisterClassA( &wcA )) return FALSE; + + return TRUE; +} + +BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved ) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + dll_instance = instance; + DisableThreadLibraryCalls( instance ); + me_heap = HeapCreate( 0, 0x10000, 0 ); + if (!register_classes( instance )) return FALSE; + LookupInit(); + break; + + case DLL_PROCESS_DETACH: + if (reserved) break; + UnregisterClassW( RICHEDIT_CLASS20W, 0 ); + UnregisterClassW( MSFTEDIT_CLASS, 0 ); + UnregisterClassA( RICHEDIT_CLASS20A, 0 ); + UnregisterClassA( "RichEdit50A", 0 ); + if (listbox_registered) UnregisterClassW( L"REListBox20W", 0 ); + if (combobox_registered) UnregisterClassW( L"REComboBox20W", 0 ); + LookupCleanup(); + HeapDestroy( me_heap ); + release_typelib(); + break; + } + return TRUE; +} diff --git a/dll/win32/riched20/txtsrv.c b/dll/win32/riched20/txtsrv.c index 725dd471da1..73b8d3ea7e9 100644 --- a/dll/win32/riched20/txtsrv.c +++ b/dll/win32/riched20/txtsrv.c @@ -27,79 +27,63 @@ #include "tom.h" #include "imm.h" #include "textserv.h" -#include "wine/asm.h" #include "wine/debug.h" #include "editstr.h" WINE_DEFAULT_DEBUG_CHANNEL(richedit); -typedef struct ITextServicesImpl { - IUnknown IUnknown_inner; - ITextServices ITextServices_iface; - IUnknown *outer_unk; - LONG ref; - ITextHost *pMyHost; - CRITICAL_SECTION csTxtSrv; - ME_TextEditor *editor; - char spare[256]; -} ITextServicesImpl; - -static inline ITextServicesImpl *impl_from_IUnknown(IUnknown *iface) +static inline struct text_services *impl_from_IUnknown( IUnknown *iface ) { - return CONTAINING_RECORD(iface, ITextServicesImpl, IUnknown_inner); + return CONTAINING_RECORD( iface, struct text_services, IUnknown_inner ); } -static HRESULT WINAPI ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) -{ - ITextServicesImpl *This = impl_from_IUnknown(iface); - - TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); - - if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = &This->IUnknown_inner; - else if (IsEqualIID(riid, &IID_ITextServices)) - *ppv = &This->ITextServices_iface; - else if (IsEqualIID(riid, &IID_IRichEditOle) || IsEqualIID(riid, &IID_ITextDocument) || - IsEqualIID(riid, &IID_ITextDocument2Old)) { - if (!This->editor->reOle) - if (!CreateIRichEditOle(This->outer_unk, This->editor, (void **)(&This->editor->reOle))) - return E_OUTOFMEMORY; - return IUnknown_QueryInterface(This->editor->reOle, riid, ppv); - } else { - *ppv = NULL; - FIXME("Unknown interface: %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; +static HRESULT WINAPI ITextServicesImpl_QueryInterface( IUnknown *iface, REFIID iid, void **obj ) +{ + struct text_services *services = impl_from_IUnknown( iface ); + + TRACE( "(%p)->(%s, %p)\n", iface, debugstr_guid( iid ), obj ); + + if (IsEqualIID( iid, &IID_IUnknown )) *obj = &services->IUnknown_inner; + else if (IsEqualIID( iid, &IID_ITextServices )) *obj = &services->ITextServices_iface; + else if (IsEqualIID( iid, &IID_IRichEditOle )) *obj= &services->IRichEditOle_iface; + else if (IsEqualIID( iid, &IID_IDispatch ) || + IsEqualIID( iid, &IID_ITextDocument ) || + IsEqualIID( iid, &IID_ITextDocument2Old )) *obj = &services->ITextDocument2Old_iface; + else + { + *obj = NULL; + FIXME( "Unknown interface: %s\n", debugstr_guid( iid ) ); + return E_NOINTERFACE; + } + + IUnknown_AddRef( (IUnknown *)*obj ); + return S_OK; } static ULONG WINAPI ITextServicesImpl_AddRef(IUnknown *iface) { - ITextServicesImpl *This = impl_from_IUnknown(iface); - LONG ref = InterlockedIncrement(&This->ref); + struct text_services *services = impl_from_IUnknown( iface ); + LONG ref = InterlockedIncrement( &services->ref ); - TRACE("(%p) ref=%d\n", This, ref); + TRACE( "(%p) ref = %d\n", services, ref ); - return ref; + return ref; } static ULONG WINAPI ITextServicesImpl_Release(IUnknown *iface) { - ITextServicesImpl *This = impl_from_IUnknown(iface); - LONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p) ref=%d\n", This, ref); - - if (!ref) - { - ME_DestroyEditor(This->editor); - This->csTxtSrv.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->csTxtSrv); - CoTaskMemFree(This); - } - return ref; + struct text_services *services = impl_from_IUnknown( iface ); + LONG ref = InterlockedDecrement( &services->ref ); + + TRACE( "(%p) ref = %d\n", services, ref ); + + if (!ref) + { + richole_release_children( services ); + ME_DestroyEditor( services->editor ); + CoTaskMemFree( services ); + } + return ref; } static const IUnknownVtbl textservices_inner_vtbl = @@ -109,306 +93,518 @@ static const IUnknownVtbl textservices_inner_vtbl = ITextServicesImpl_Release }; -static inline ITextServicesImpl *impl_from_ITextServices(ITextServices *iface) +static inline struct text_services *impl_from_ITextServices( ITextServices *iface ) { - return CONTAINING_RECORD(iface, ITextServicesImpl, ITextServices_iface); + return CONTAINING_RECORD( iface, struct text_services, ITextServices_iface ); } -static HRESULT WINAPI fnTextSrv_QueryInterface(ITextServices *iface, REFIID riid, void **ppv) +static HRESULT WINAPI fnTextSrv_QueryInterface( ITextServices *iface, REFIID iid, void **obj ) { - ITextServicesImpl *This = impl_from_ITextServices(iface); - return IUnknown_QueryInterface(This->outer_unk, riid, ppv); + struct text_services *services = impl_from_ITextServices( iface ); + return IUnknown_QueryInterface( services->outer_unk, iid, obj ); } static ULONG WINAPI fnTextSrv_AddRef(ITextServices *iface) { - ITextServicesImpl *This = impl_from_ITextServices(iface); - return IUnknown_AddRef(This->outer_unk); + struct text_services *services = impl_from_ITextServices( iface ); + return IUnknown_AddRef( services->outer_unk ); } static ULONG WINAPI fnTextSrv_Release(ITextServices *iface) { - ITextServicesImpl *This = impl_from_ITextServices(iface); - return IUnknown_Release(This->outer_unk); + struct text_services *services = impl_from_ITextServices( iface ); + return IUnknown_Release( services->outer_unk ); } -DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSendMessage(ITextServices *iface, UINT msg, WPARAM wparam, - LPARAM lparam, LRESULT *plresult) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage,20) +DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSendMessage( ITextServices *iface, UINT msg, WPARAM wparam, + LPARAM lparam, LRESULT *result ) { - ITextServicesImpl *This = impl_from_ITextServices(iface); - HRESULT hresult; - LRESULT lresult; + struct text_services *services = impl_from_ITextServices( iface ); + HRESULT hr; + LRESULT res; - lresult = ME_HandleMessage(This->editor, msg, wparam, lparam, TRUE, &hresult); - if (plresult) *plresult = lresult; - return hresult; + res = editor_handle_message( services->editor, msg, wparam, lparam, &hr ); + if (result) *result = res; + return hr; } -DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxDraw(ITextServices *iface, DWORD dwDrawAspect, LONG lindex, - void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, HDC hdcTargetDev, - LPCRECTL lprcBounds, LPCRECTL lprcWBounds, LPRECT lprcUpdate, - BOOL (CALLBACK * pfnContinue)(DWORD), DWORD dwContinue, - LONG lViewId) +static HRESULT update_client_rect( struct text_services *services, const RECT *client ) +{ + RECT rect; + HRESULT hr; + + if (!client) + { + if (!services->editor->in_place_active) return E_INVALIDARG; + hr = ITextHost_TxGetClientRect( services->editor->texthost, &rect ); + if (FAILED( hr )) return hr; + } + else rect = *client; + + rect.left += services->editor->selofs; + + if (EqualRect( &rect, &services->editor->rcFormat )) return S_FALSE; + services->editor->rcFormat = rect; + return S_OK; +} + +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52) +DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxDraw( ITextServices *iface, DWORD aspect, LONG index, void *aspect_info, + DVTARGETDEVICE *td, HDC draw, HDC target, + const RECTL *bounds, const RECTL *mf_bounds, RECT *update, + BOOL (CALLBACK *continue_fn)(DWORD), DWORD continue_param, + LONG view_id ) { - ITextServicesImpl *This = impl_from_ITextServices(iface); + struct text_services *services = impl_from_ITextServices( iface ); + HRESULT hr; + HDC dc = draw; + BOOL rewrap = FALSE; - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + TRACE( "%p: aspect %d, %d, %p, %p, draw %p, target %p, bounds %s, mf_bounds %s, update %s, %p, %d, view %d\n", + services, aspect, index, aspect_info, td, draw, target, wine_dbgstr_rect( (RECT *)bounds ), + wine_dbgstr_rect( (RECT *)mf_bounds ), wine_dbgstr_rect( update ), continue_fn, continue_param, view_id ); + + if (aspect != DVASPECT_CONTENT || aspect_info || td || target || mf_bounds || continue_fn ) + FIXME( "Many arguments are ignored\n" ); + + hr = update_client_rect( services, (RECT *)bounds ); + if (FAILED( hr )) return hr; + if (hr == S_OK) rewrap = TRUE; + + if (!dc && services->editor->in_place_active) + dc = ITextHost_TxGetDC( services->editor->texthost ); + if (!dc) return E_FAIL; + + if (rewrap) + { + editor_mark_rewrap_all( services->editor ); + wrap_marked_paras_dc( services->editor, dc, FALSE ); + } + + if (!services->editor->bEmulateVersion10 || services->editor->nEventMask & ENM_UPDATE) + ITextHost_TxNotify( services->editor->texthost, EN_UPDATE, NULL ); + + editor_draw( services->editor, dc, update ); + + if (!draw) ITextHost_TxReleaseDC( services->editor->texthost, dc ); + return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetHScroll(ITextServices *iface, LONG *plMin, LONG *plMax, LONG *plPos, - LONG *plPage, BOOL *pfEnabled) -{ - ITextServicesImpl *This = impl_from_ITextServices(iface); - - if (plMin) - *plMin = This->editor->horz_si.nMin; - if (plMax) - *plMax = This->editor->horz_si.nMax; - if (plPos) - *plPos = This->editor->horz_si.nPos; - if (plPage) - *plPage = This->editor->horz_si.nPage; - if (pfEnabled) - *pfEnabled = (This->editor->styleFlags & WS_HSCROLL) != 0; - return S_OK; +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24) +DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetHScroll( ITextServices *iface, LONG *min_pos, LONG *max_pos, LONG *pos, + LONG *page, BOOL *enabled ) +{ + struct text_services *services = impl_from_ITextServices( iface ); + + if (min_pos) *min_pos = services->editor->horz_si.nMin; + if (max_pos) *max_pos = services->editor->horz_si.nMax; + if (pos) *pos = services->editor->horz_si.nPos; + if (page) *page = services->editor->horz_si.nPage; + if (enabled) *enabled = services->editor->horz_sb_enabled; + return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetVScroll(ITextServices *iface, LONG *plMin, LONG *plMax, LONG *plPos, - LONG *plPage, BOOL *pfEnabled) -{ - ITextServicesImpl *This = impl_from_ITextServices(iface); - - if (plMin) - *plMin = This->editor->vert_si.nMin; - if (plMax) - *plMax = This->editor->vert_si.nMax; - if (plPos) - *plPos = This->editor->vert_si.nPos; - if (plPage) - *plPage = This->editor->vert_si.nPage; - if (pfEnabled) - *pfEnabled = (This->editor->styleFlags & WS_VSCROLL) != 0; - return S_OK; +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll,24) +DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetVScroll( ITextServices *iface, LONG *min_pos, LONG *max_pos, LONG *pos, + LONG *page, BOOL *enabled ) +{ + struct text_services *services = impl_from_ITextServices( iface ); + + if (min_pos) *min_pos = services->editor->vert_si.nMin; + if (max_pos) *max_pos = services->editor->vert_si.nMax; + if (pos) *pos = services->editor->vert_si.nPos; + if (page) *page = services->editor->vert_si.nPage; + if (enabled) *enabled = services->editor->vert_sb_enabled; + return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxSetCursor(ITextServices *iface, DWORD dwDrawAspect, LONG lindex, - void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, - HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor,40) +DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxSetCursor( ITextServices *iface, DWORD aspect, LONG index, + void *aspect_info, DVTARGETDEVICE *td, HDC draw, + HDC target, const RECT *client, INT x, INT y ) { - ITextServicesImpl *This = impl_from_ITextServices(iface); + struct text_services *services = impl_from_ITextServices( iface ); + + TRACE( "%p: %d, %d, %p, %p, draw %p target %p client %s pos (%d, %d)\n", services, aspect, index, aspect_info, td, draw, + target, wine_dbgstr_rect( client ), x, y ); + + if (aspect != DVASPECT_CONTENT || index || aspect_info || td || draw || target || client) + FIXME( "Ignoring most params\n" ); - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + link_notify( services->editor, WM_SETCURSOR, 0, MAKELPARAM( x, y ) ); + editor_set_cursor( services->editor, x, y ); + return S_OK; } +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint,44) DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxQueryHitPoint(ITextServices *iface, DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y, DWORD *pHitResult) { - ITextServicesImpl *This = impl_from_ITextServices(iface); + struct text_services *services = impl_from_ITextServices( iface ); - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + FIXME( "%p: STUB\n", services ); + return E_NOTIMPL; } -DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInplaceActivate(ITextServices *iface, LPCRECT prcClient) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInPlaceActivate,8) +DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInPlaceActivate( ITextServices *iface, const RECT *client ) { - ITextServicesImpl *This = impl_from_ITextServices(iface); - - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + struct text_services *services = impl_from_ITextServices( iface ); + HRESULT hr; + BOOL old_active = services->editor->in_place_active; + + TRACE( "%p: %s\n", services, wine_dbgstr_rect( client ) ); + + services->editor->in_place_active = TRUE; + hr = update_client_rect( services, client ); + if (FAILED( hr )) + { + services->editor->in_place_active = old_active; + return hr; + } + ME_RewrapRepaint( services->editor ); + return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInplaceDeactivate(ITextServices *iface) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInPlaceDeactivate,4) +DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInPlaceDeactivate(ITextServices *iface) { - ITextServicesImpl *This = impl_from_ITextServices(iface); + struct text_services *services = impl_from_ITextServices( iface ); - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + TRACE( "%p\n", services ); + services->editor->in_place_active = FALSE; + return S_OK; } +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4) DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxUIActivate(ITextServices *iface) { - ITextServicesImpl *This = impl_from_ITextServices(iface); + struct text_services *services = impl_from_ITextServices( iface ); - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + FIXME( "%p: STUB\n", services ); + return E_NOTIMPL; } +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4) DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxUIDeactivate(ITextServices *iface) { - ITextServicesImpl *This = impl_from_ITextServices(iface); + struct text_services *services = impl_from_ITextServices( iface ); - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + FIXME( "%p: STUB\n", services ); + return E_NOTIMPL; } -DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetText(ITextServices *iface, BSTR *pbstrText) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8) +DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetText( ITextServices *iface, BSTR *text ) { - ITextServicesImpl *This = impl_from_ITextServices(iface); - int length; - - length = ME_GetTextLength(This->editor); - if (length) - { - ME_Cursor start; - BSTR bstr; - bstr = SysAllocStringByteLen(NULL, length * sizeof(WCHAR)); - if (bstr == NULL) - return E_OUTOFMEMORY; - - ME_CursorFromCharOfs(This->editor, 0, &start); - ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE, FALSE); - *pbstrText = bstr; - } else { - *pbstrText = NULL; - } - - return S_OK; + struct text_services *services = impl_from_ITextServices( iface ); + int length; + + length = ME_GetTextLength( services->editor ); + if (length) + { + ME_Cursor start; + BSTR bstr; + bstr = SysAllocStringByteLen( NULL, length * sizeof(WCHAR) ); + if (bstr == NULL) return E_OUTOFMEMORY; + + cursor_from_char_ofs( services->editor, 0, &start ); + ME_GetTextW( services->editor, bstr, length, &start, INT_MAX, FALSE, FALSE ); + *text = bstr; + } + else *text = NULL; + + return S_OK; } -DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSetText(ITextServices *iface, LPCWSTR pszText) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8) +DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSetText( ITextServices *iface, const WCHAR *text ) { - ITextServicesImpl *This = impl_from_ITextServices(iface); - ME_Cursor cursor; - - ME_SetCursorToStart(This->editor, &cursor); - ME_InternalDeleteText(This->editor, &cursor, ME_GetTextLength(This->editor), FALSE); - if(pszText) - ME_InsertTextFromCursor(This->editor, 0, pszText, -1, This->editor->pBuffer->pDefaultStyle); - set_selection_cursors(This->editor, 0, 0); - This->editor->nModifyStep = 0; - OleFlushClipboard(); - ME_EmptyUndoStack(This->editor); - ME_UpdateRepaint(This->editor, FALSE); - - return S_OK; + struct text_services *services = impl_from_ITextServices( iface ); + ME_Cursor cursor; + + ME_SetCursorToStart( services->editor, &cursor ); + ME_InternalDeleteText( services->editor, &cursor, ME_GetTextLength( services->editor ), FALSE ); + if (text) ME_InsertTextFromCursor( services->editor, 0, text, -1, services->editor->pBuffer->pDefaultStyle ); + set_selection_cursors( services->editor, 0, 0); + services->editor->nModifyStep = 0; + OleFlushClipboard(); + ME_EmptyUndoStack( services->editor ); + ME_UpdateRepaint( services->editor, FALSE ); + + return S_OK; } +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8) DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetCurTargetX(ITextServices *iface, LONG *x) { - ITextServicesImpl *This = impl_from_ITextServices(iface); + struct text_services *services = impl_from_ITextServices( iface ); - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + FIXME( "%p: STUB\n", services ); + return E_NOTIMPL; } +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8) DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetBaseLinePos(ITextServices *iface, LONG *x) { - ITextServicesImpl *This = impl_from_ITextServices(iface); + struct text_services *services = impl_from_ITextServices( iface ); - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + FIXME( "%p: STUB\n", services ); + return E_NOTIMPL; } -DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetNaturalSize(ITextServices *iface, DWORD dwAspect, HDC hdcDraw, - HDC hicTargetDev, DVTARGETDEVICE *ptd, DWORD dwMode, - const SIZEL *psizelExtent, LONG *pwidth, LONG *pheight) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36) +DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetNaturalSize( ITextServices *iface, DWORD aspect, HDC draw, + HDC target, DVTARGETDEVICE *td, DWORD mode, + const SIZEL *extent, LONG *width, LONG *height ) { - ITextServicesImpl *This = impl_from_ITextServices(iface); + struct text_services *services = impl_from_ITextServices( iface ); + RECT rect; + HDC dc = draw; + BOOL rewrap = FALSE; + HRESULT hr; + + TRACE( "%p: aspect %d, draw %p, target %p, td %p, mode %08x, extent %s, *width %d, *height %d\n", services, + aspect, draw, target, td, mode, wine_dbgstr_point( (POINT *)extent ), *width, *height ); + + if (aspect != DVASPECT_CONTENT || target || td || mode != TXTNS_FITTOCONTENT ) + FIXME( "Many arguments are ignored\n" ); + + SetRect( &rect, 0, 0, *width, *height ); + + hr = update_client_rect( services, &rect ); + if (FAILED( hr )) return hr; + if (hr == S_OK) rewrap = TRUE; - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + if (!dc && services->editor->in_place_active) + dc = ITextHost_TxGetDC( services->editor->texthost ); + if (!dc) return E_FAIL; + + if (rewrap) + { + editor_mark_rewrap_all( services->editor ); + wrap_marked_paras_dc( services->editor, dc, FALSE ); + } + + *width = services->editor->nTotalWidth; + *height = services->editor->nTotalLength; + + if (!draw) ITextHost_TxReleaseDC( services->editor->texthost, dc ); + return S_OK; } +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8) DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetDropTarget(ITextServices *iface, IDropTarget **ppDropTarget) { - ITextServicesImpl *This = impl_from_ITextServices(iface); + struct text_services *services = impl_from_ITextServices( iface ); - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + FIXME( "%p: STUB\n", services ); + return E_NOTIMPL; } -DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxPropertyBitsChange(ITextServices *iface, DWORD dwMask, DWORD dwBits) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange,12) +DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxPropertyBitsChange( ITextServices *iface, DWORD mask, DWORD bits ) { - ITextServicesImpl *This = impl_from_ITextServices(iface); - - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + struct text_services *services = impl_from_ITextServices( iface ); + DWORD scrollbars; + HRESULT hr; + BOOL repaint = FALSE; + + TRACE( "%p, mask %08x, bits %08x\n", services, mask, bits ); + + services->editor->props = (services->editor->props & ~mask) | (bits & mask); + if (mask & (TXTBIT_WORDWRAP | TXTBIT_MULTILINE)) + services->editor->bWordWrap = (services->editor->props & TXTBIT_WORDWRAP) && (services->editor->props & TXTBIT_MULTILINE); + + if (mask & TXTBIT_SCROLLBARCHANGE) + { + hr = ITextHost_TxGetScrollBars( services->editor->texthost, &scrollbars ); + if (SUCCEEDED( hr )) + { + if ((services->editor->scrollbars ^ scrollbars) & WS_HSCROLL) + ITextHost_TxShowScrollBar( services->editor->texthost, SB_HORZ, (scrollbars & WS_HSCROLL) && + services->editor->nTotalWidth > services->editor->sizeWindow.cx ); + if ((services->editor->scrollbars ^ scrollbars) & WS_VSCROLL) + ITextHost_TxShowScrollBar( services->editor->texthost, SB_VERT, (scrollbars & WS_VSCROLL) && + services->editor->nTotalLength > services->editor->sizeWindow.cy ); + services->editor->scrollbars = scrollbars; + } + } + + if ((mask & TXTBIT_HIDESELECTION) && !services->editor->bHaveFocus) ME_InvalidateSelection( services->editor ); + + if (mask & TXTBIT_SELBARCHANGE) + { + LONG width; + + hr = ITextHost_TxGetSelectionBarWidth( services->editor->texthost, &width ); + if (hr == S_OK) + { + ITextHost_TxInvalidateRect( services->editor->texthost, &services->editor->rcFormat, TRUE ); + services->editor->rcFormat.left -= services->editor->selofs; + services->editor->selofs = width ? SELECTIONBAR_WIDTH : 0; /* FIXME: convert from HIMETRIC */ + services->editor->rcFormat.left += services->editor->selofs; + repaint = TRUE; + } + } + + if (mask & TXTBIT_CLIENTRECTCHANGE) + { + hr = update_client_rect( services, NULL ); + if (SUCCEEDED( hr )) repaint = TRUE; + } + + if (mask & TXTBIT_USEPASSWORD) + { + if (bits & TXTBIT_USEPASSWORD) ITextHost_TxGetPasswordChar( services->editor->texthost, &services->editor->password_char ); + else services->editor->password_char = 0; + repaint = TRUE; + } + + if (repaint) ME_RewrapRepaint( services->editor ); + + return S_OK; } +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize,12) DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetCachedSize(ITextServices *iface, DWORD *pdwWidth, DWORD *pdwHeight) { - ITextServicesImpl *This = impl_from_ITextServices(iface); + struct text_services *services = impl_from_ITextServices( iface ); - FIXME("%p: STUB\n", This); - return E_NOTIMPL; + FIXME( "%p: STUB\n", services ); + return E_NOTIMPL; } -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage,20) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll,24) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor,40) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint,44) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceActivate,8) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceDeactivate,4) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange,12) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize,12) +#ifdef __ASM_USE_THISCALL_WRAPPER + +#define STDCALL(func) (void *) __stdcall_ ## func +#ifdef _MSC_VER +#define DEFINE_STDCALL_WRAPPER(num,func) \ + __declspec(naked) HRESULT __stdcall_##func(void) \ + { \ + __asm pop eax \ + __asm pop ecx \ + __asm push eax \ + __asm mov eax, [ecx] \ + __asm jmp dword ptr [eax + 4*num] \ + } +#else /* _MSC_VER */ +#define DEFINE_STDCALL_WRAPPER(num,func) \ + extern HRESULT __stdcall_ ## func(void); \ + __ASM_GLOBAL_FUNC(__stdcall_ ## func, \ + "popl %eax\n\t" \ + "popl %ecx\n\t" \ + "pushl %eax\n\t" \ + "movl (%ecx), %eax\n\t" \ + "jmp *(4*(" #num "))(%eax)" ) +#endif /* _MSC_VER */ + +DEFINE_STDCALL_WRAPPER(3, ITextServices_TxSendMessage) +DEFINE_STDCALL_WRAPPER(4, ITextServices_TxDraw) +DEFINE_STDCALL_WRAPPER(5, ITextServices_TxGetHScroll) +DEFINE_STDCALL_WRAPPER(6, ITextServices_TxGetVScroll) +DEFINE_STDCALL_WRAPPER(7, ITextServices_OnTxSetCursor) +DEFINE_STDCALL_WRAPPER(8, ITextServices_TxQueryHitPoint) +DEFINE_STDCALL_WRAPPER(9, ITextServices_OnTxInPlaceActivate) +DEFINE_STDCALL_WRAPPER(10, ITextServices_OnTxInPlaceDeactivate) +DEFINE_STDCALL_WRAPPER(11, ITextServices_OnTxUIActivate) +DEFINE_STDCALL_WRAPPER(12, ITextServices_OnTxUIDeactivate) +DEFINE_STDCALL_WRAPPER(13, ITextServices_TxGetText) +DEFINE_STDCALL_WRAPPER(14, ITextServices_TxSetText) +DEFINE_STDCALL_WRAPPER(15, ITextServices_TxGetCurTargetX) +DEFINE_STDCALL_WRAPPER(16, ITextServices_TxGetBaseLinePos) +DEFINE_STDCALL_WRAPPER(17, ITextServices_TxGetNaturalSize) +DEFINE_STDCALL_WRAPPER(18, ITextServices_TxGetDropTarget) +DEFINE_STDCALL_WRAPPER(19, ITextServices_OnTxPropertyBitsChange) +DEFINE_STDCALL_WRAPPER(20, ITextServices_TxGetCachedSize) + +const ITextServicesVtbl text_services_stdcall_vtbl = +{ + NULL, + NULL, + NULL, + STDCALL(ITextServices_TxSendMessage), + STDCALL(ITextServices_TxDraw), + STDCALL(ITextServices_TxGetHScroll), + STDCALL(ITextServices_TxGetVScroll), + STDCALL(ITextServices_OnTxSetCursor), + STDCALL(ITextServices_TxQueryHitPoint), + STDCALL(ITextServices_OnTxInPlaceActivate), + STDCALL(ITextServices_OnTxInPlaceDeactivate), + STDCALL(ITextServices_OnTxUIActivate), + STDCALL(ITextServices_OnTxUIDeactivate), + STDCALL(ITextServices_TxGetText), + STDCALL(ITextServices_TxSetText), + STDCALL(ITextServices_TxGetCurTargetX), + STDCALL(ITextServices_TxGetBaseLinePos), + STDCALL(ITextServices_TxGetNaturalSize), + STDCALL(ITextServices_TxGetDropTarget), + STDCALL(ITextServices_OnTxPropertyBitsChange), + STDCALL(ITextServices_TxGetCachedSize), +}; + +#endif /* __ASM_USE_THISCALL_WRAPPER */ static const ITextServicesVtbl textservices_vtbl = { - fnTextSrv_QueryInterface, - fnTextSrv_AddRef, - fnTextSrv_Release, - THISCALL(fnTextSrv_TxSendMessage), - THISCALL(fnTextSrv_TxDraw), - THISCALL(fnTextSrv_TxGetHScroll), - THISCALL(fnTextSrv_TxGetVScroll), - THISCALL(fnTextSrv_OnTxSetCursor), - THISCALL(fnTextSrv_TxQueryHitPoint), - THISCALL(fnTextSrv_OnTxInplaceActivate), - THISCALL(fnTextSrv_OnTxInplaceDeactivate), - THISCALL(fnTextSrv_OnTxUIActivate), - THISCALL(fnTextSrv_OnTxUIDeactivate), - THISCALL(fnTextSrv_TxGetText), - THISCALL(fnTextSrv_TxSetText), - THISCALL(fnTextSrv_TxGetCurTargetX), - THISCALL(fnTextSrv_TxGetBaseLinePos), - THISCALL(fnTextSrv_TxGetNaturalSize), - THISCALL(fnTextSrv_TxGetDropTarget), - THISCALL(fnTextSrv_OnTxPropertyBitsChange), - THISCALL(fnTextSrv_TxGetCachedSize) + fnTextSrv_QueryInterface, + fnTextSrv_AddRef, + fnTextSrv_Release, + THISCALL(fnTextSrv_TxSendMessage), + THISCALL(fnTextSrv_TxDraw), + THISCALL(fnTextSrv_TxGetHScroll), + THISCALL(fnTextSrv_TxGetVScroll), + THISCALL(fnTextSrv_OnTxSetCursor), + THISCALL(fnTextSrv_TxQueryHitPoint), + THISCALL(fnTextSrv_OnTxInPlaceActivate), + THISCALL(fnTextSrv_OnTxInPlaceDeactivate), + THISCALL(fnTextSrv_OnTxUIActivate), + THISCALL(fnTextSrv_OnTxUIDeactivate), + THISCALL(fnTextSrv_TxGetText), + THISCALL(fnTextSrv_TxSetText), + THISCALL(fnTextSrv_TxGetCurTargetX), + THISCALL(fnTextSrv_TxGetBaseLinePos), + THISCALL(fnTextSrv_TxGetNaturalSize), + THISCALL(fnTextSrv_TxGetDropTarget), + THISCALL(fnTextSrv_OnTxPropertyBitsChange), + THISCALL(fnTextSrv_TxGetCachedSize) }; +HRESULT create_text_services( IUnknown *outer, ITextHost *text_host, IUnknown **unk, BOOL emulate_10 ) +{ + struct text_services *services; + + TRACE( "%p %p --> %p\n", outer, text_host, unk ); + if (text_host == NULL) return E_POINTER; + + services = CoTaskMemAlloc( sizeof(*services) ); + if (services == NULL) return E_OUTOFMEMORY; + services->ref = 1; + services->IUnknown_inner.lpVtbl = &textservices_inner_vtbl; + services->ITextServices_iface.lpVtbl = &textservices_vtbl; + services->IRichEditOle_iface.lpVtbl = &re_ole_vtbl; + services->ITextDocument2Old_iface.lpVtbl = &text_doc2old_vtbl; + services->editor = ME_MakeEditor( text_host, emulate_10 ); + services->editor->richole = &services->IRichEditOle_iface; + + if (outer) services->outer_unk = outer; + else services->outer_unk = &services->IUnknown_inner; + + services->text_selection = NULL; + list_init( &services->rangelist ); + list_init( &services->clientsites ); + + *unk = &services->IUnknown_inner; + return S_OK; +} + /****************************************************************** * CreateTextServices (RICHED20.4) */ -HRESULT WINAPI CreateTextServices(IUnknown *pUnkOuter, ITextHost *pITextHost, IUnknown **ppUnk) -{ - ITextServicesImpl *ITextImpl; - - TRACE("%p %p --> %p\n", pUnkOuter, pITextHost, ppUnk); - if (pITextHost == NULL) - return E_POINTER; - - ITextImpl = CoTaskMemAlloc(sizeof(*ITextImpl)); - if (ITextImpl == NULL) - return E_OUTOFMEMORY; - InitializeCriticalSection(&ITextImpl->csTxtSrv); - ITextImpl->csTxtSrv.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ITextServicesImpl.csTxtSrv"); - ITextImpl->ref = 1; - ITextHost_AddRef(pITextHost); - ITextImpl->pMyHost = pITextHost; - ITextImpl->IUnknown_inner.lpVtbl = &textservices_inner_vtbl; - ITextImpl->ITextServices_iface.lpVtbl = &textservices_vtbl; - ITextImpl->editor = ME_MakeEditor(pITextHost, FALSE); - - if (pUnkOuter) - ITextImpl->outer_unk = pUnkOuter; - else - ITextImpl->outer_unk = &ITextImpl->IUnknown_inner; - - *ppUnk = &ITextImpl->IUnknown_inner; - return S_OK; +HRESULT WINAPI CreateTextServices( IUnknown *outer, ITextHost *text_host, IUnknown **unk ) +{ + return create_text_services( outer, text_host, unk, FALSE ); } diff --git a/dll/win32/riched20/undo.c b/dll/win32/riched20/undo.c index 2f18fc78bb3..d95ce121234 100644 --- a/dll/win32/riched20/undo.c +++ b/dll/win32/riched20/undo.c @@ -335,19 +335,17 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, struct undo_item *undo) case undo_set_para_fmt: { ME_Cursor tmp; - ME_DisplayItem *para; - ME_CursorFromCharOfs(editor, undo->u.set_para_fmt.pos, &tmp); - para = ME_FindItemBack(tmp.pRun, diParagraph); - add_undo_set_para_fmt( editor, ¶->member.para ); - para->member.para.fmt = undo->u.set_para_fmt.fmt; - para->member.para.border = undo->u.set_para_fmt.border; - mark_para_rewrap(editor, para); + cursor_from_char_ofs( editor, undo->u.set_para_fmt.pos, &tmp ); + add_undo_set_para_fmt( editor, tmp.para ); + tmp.para->fmt = undo->u.set_para_fmt.fmt; + tmp.para->border = undo->u.set_para_fmt.border; + para_mark_rewrap( editor, tmp.para ); break; } case undo_set_char_fmt: { ME_Cursor start, end; - ME_CursorFromCharOfs(editor, undo->u.set_char_fmt.pos, &start); + cursor_from_char_ofs( editor, undo->u.set_char_fmt.pos, &start ); end = start; ME_MoveCursorChars(editor, &end, undo->u.set_char_fmt.len, FALSE); ME_SetCharFormat(editor, &start, &end, &undo->u.set_char_fmt.fmt); @@ -356,55 +354,53 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, struct undo_item *undo) case undo_insert_run: { ME_Cursor tmp; - ME_CursorFromCharOfs(editor, undo->u.insert_run.pos, &tmp); - ME_InsertRunAtCursor(editor, &tmp, undo->u.insert_run.style, - undo->u.insert_run.str, - undo->u.insert_run.len, - undo->u.insert_run.flags); + cursor_from_char_ofs( editor, undo->u.insert_run.pos, &tmp ); + run_insert( editor, &tmp, undo->u.insert_run.style, + undo->u.insert_run.str, undo->u.insert_run.len, + undo->u.insert_run.flags ); break; } case undo_delete_run: { ME_Cursor tmp; - ME_CursorFromCharOfs(editor, undo->u.delete_run.pos, &tmp); + cursor_from_char_ofs( editor, undo->u.delete_run.pos, &tmp ); ME_InternalDeleteText(editor, &tmp, undo->u.delete_run.len, TRUE); break; } case undo_join_paras: { ME_Cursor tmp; - ME_CursorFromCharOfs(editor, undo->u.join_paras.pos, &tmp); - ME_JoinParagraphs(editor, tmp.pPara, TRUE); + cursor_from_char_ofs( editor, undo->u.join_paras.pos, &tmp ); + para_join( editor, tmp.para, TRUE ); break; } case undo_split_para: { ME_Cursor tmp; - ME_DisplayItem *this_para, *new_para; + ME_Paragraph *this_para, *new_para; BOOL bFixRowStart; int paraFlags = undo->u.split_para.flags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND); - ME_CursorFromCharOfs(editor, undo->u.split_para.pos, &tmp); - if (tmp.nOffset) - ME_SplitRunSimple(editor, &tmp); - this_para = tmp.pPara; - bFixRowStart = this_para->member.para.nFlags & MEPF_ROWSTART; + + cursor_from_char_ofs( editor, undo->u.split_para.pos, &tmp ); + if (tmp.nOffset) run_split( editor, &tmp ); + this_para = tmp.para; + bFixRowStart = this_para->nFlags & MEPF_ROWSTART; if (bFixRowStart) { /* Re-insert the paragraph before the table, making sure the nFlag value * is correct. */ - this_para->member.para.nFlags &= ~MEPF_ROWSTART; + this_para->nFlags &= ~MEPF_ROWSTART; } - new_para = ME_SplitParagraph(editor, tmp.pRun, tmp.pRun->member.run.style, - undo->u.split_para.eol_str->szData, undo->u.split_para.eol_str->nLen, paraFlags); + new_para = para_split( editor, tmp.run, tmp.run->style, + undo->u.split_para.eol_str->szData, undo->u.split_para.eol_str->nLen, paraFlags ); if (bFixRowStart) - new_para->member.para.nFlags |= MEPF_ROWSTART; - new_para->member.para.fmt = undo->u.split_para.fmt; - new_para->member.para.border = undo->u.split_para.border; + new_para->nFlags |= MEPF_ROWSTART; + new_para->fmt = undo->u.split_para.fmt; + new_para->border = undo->u.split_para.border; if (paraFlags) { - ME_DisplayItem *pCell = new_para->member.para.pCell; - pCell->member.cell.nRightBoundary = undo->u.split_para.cell_right_boundary; - pCell->member.cell.border = undo->u.split_para.cell_border; + para_cell( new_para )->nRightBoundary = undo->u.split_para.cell_right_boundary; + para_cell( new_para )->border = undo->u.split_para.cell_border; } break; } @@ -441,9 +437,8 @@ BOOL ME_Undo(ME_TextEditor *editor) destroy_undo_item( undo ); } - ME_MoveCursorFromTableRowStartParagraph(editor); + table_move_from_row_start( editor ); add_undo( editor, undo_end_transaction ); - ME_CheckTablesForCorruption(editor); editor->nUndoStackSize--; editor->nUndoMode = nMode; ME_UpdateRepaint(editor, FALSE); @@ -478,9 +473,8 @@ BOOL ME_Redo(ME_TextEditor *editor) list_remove( &undo->entry ); destroy_undo_item( undo ); } - ME_MoveCursorFromTableRowStartParagraph(editor); + table_move_from_row_start( editor ); add_undo( editor, undo_end_transaction ); - ME_CheckTablesForCorruption(editor); editor->nUndoMode = nMode; ME_UpdateRepaint(editor, FALSE); return TRUE; diff --git a/dll/win32/riched20/wrap.c b/dll/win32/riched20/wrap.c index c3b5883dbf1..9456d54d815 100644 --- a/dll/win32/riched20/wrap.c +++ b/dll/win32/riched20/wrap.c @@ -43,10 +43,9 @@ typedef struct tagME_WrapContext int nRow; POINT pt; BOOL bOverflown, bWordWrap; - ME_DisplayItem *pPara; - ME_DisplayItem *pRowStart; - - ME_DisplayItem *pLastSplittableRun; + ME_Paragraph *para; + ME_Run *pRowStart; + ME_Run *pLastSplittableRun; } ME_WrapContext; static BOOL get_run_glyph_buffers( ME_Run *run ) @@ -128,31 +127,28 @@ static void calc_run_extent(ME_Context *c, const ME_Paragraph *para, int startx, * Splits a run into two in a given place. It also updates the screen position * and size (extent) of the newly generated runs. */ -static ME_DisplayItem *split_run_extents(ME_WrapContext *wc, ME_DisplayItem *item, int nVChar) +static ME_Run *split_run_extents( ME_WrapContext *wc, ME_Run *run, int nVChar ) { ME_TextEditor *editor = wc->context->editor; - ME_Run *run, *run2; - ME_Paragraph *para = &wc->pPara->member.para; - ME_Cursor cursor = {wc->pPara, item, nVChar}; + ME_Run *run2; + ME_Cursor cursor = { wc->para, run, nVChar }; - assert(item->member.run.nCharOfs != -1); + assert( run->nCharOfs != -1 ); ME_CheckCharOffsets(editor); - run = &item->member.run; - TRACE("Before split: %s(%d, %d)\n", debugstr_run( run ), run->pt.x, run->pt.y); - ME_SplitRunSimple(editor, &cursor); + run_split( editor, &cursor ); - run2 = &cursor.pRun->member.run; + run2 = cursor.run; run2->script_analysis = run->script_analysis; shape_run( wc->context, run ); shape_run( wc->context, run2 ); - calc_run_extent(wc->context, para, wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run); + calc_run_extent(wc->context, wc->para, wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run); - run2->pt.x = run->pt.x+run->nWidth; + run2->pt.x = run->pt.x + run->nWidth; run2->pt.y = run->pt.y; ME_CheckCharOffsets(editor); @@ -161,7 +157,7 @@ static ME_DisplayItem *split_run_extents(ME_WrapContext *wc, ME_DisplayItem *ite debugstr_run( run ), run->pt.x, run->pt.y, debugstr_run( run2 ), run2->pt.x, run2->pt.y); - return cursor.pRun; + return cursor.run; } /****************************************************************************** @@ -177,44 +173,44 @@ static int find_split_point( ME_Context *c, int cx, ME_Run *run ) return ME_CharFromPointContext( c, cx, run, FALSE, FALSE ); } -static ME_DisplayItem *ME_MakeRow(int height, int baseline, int width) +static ME_Row *row_create( int height, int baseline, int width ) { ME_DisplayItem *item = ME_MakeDI(diStartRow); item->member.row.nHeight = height; item->member.row.nBaseline = baseline; item->member.row.nWidth = width; - return item; + return &item->member.row; } static void ME_BeginRow(ME_WrapContext *wc) { - PARAFORMAT2 *pFmt; - ME_DisplayItem *para = wc->pPara; + ME_Cell *cell; - pFmt = ¶->member.para.fmt; wc->pRowStart = NULL; wc->bOverflown = FALSE; wc->pLastSplittableRun = NULL; wc->bWordWrap = wc->context->editor->bWordWrap; - if (para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) { + if (wc->para->nFlags & (MEPF_ROWSTART | MEPF_ROWEND)) + { wc->nAvailWidth = 0; wc->bWordWrap = FALSE; - if (para->member.para.nFlags & MEPF_ROWEND) + if (wc->para->nFlags & MEPF_ROWEND) { - ME_Cell *cell = &ME_FindItemBack(para, diCell)->member.cell; + cell = table_row_end_cell( wc->para ); cell->nWidth = 0; } - } else if (para->member.para.pCell) { - ME_Cell *cell = ¶->member.para.pCell->member.cell; + } + else if (para_cell( wc->para )) + { int width; + cell = para_cell( wc->para ); width = cell->nRightBoundary; - if (cell->prev_cell) - width -= cell->prev_cell->member.cell.nRightBoundary; - if (!cell->prev_cell) + if (cell_prev( cell )) width -= cell_prev( cell )->nRightBoundary; + else { - int rowIndent = ME_GetTableRowEnd(para)->member.para.fmt.dxStartIndent; + int rowIndent = table_row_end( wc->para )->fmt.dxStartIndent; width -= rowIndent; } cell->nWidth = max(ME_twips2pointsX(wc->context, width), 0); @@ -222,33 +218,32 @@ static void ME_BeginRow(ME_WrapContext *wc) wc->nAvailWidth = cell->nWidth - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin; wc->bWordWrap = TRUE; - } else { + } + else wc->nAvailWidth = wc->context->nAvailWidth - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin; - } + wc->pt.x = wc->context->pt.x; if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ - pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) + para_in_table( wc->para )) /* Shift the text down because of the border. */ wc->pt.y++; } -static void layout_row( ME_DisplayItem *start, const ME_DisplayItem *end ) +static void layout_row( ME_Run *start, ME_Run *last ) { - ME_DisplayItem *p; + ME_Run *run; int i, num_runs = 0; int buf[16 * 5]; /* 5 arrays - 4 of int & 1 of BYTE, alloc space for 5 of ints */ int *vis_to_log = buf, *log_to_vis, *widths, *pos; BYTE *levels; BOOL found_black = FALSE; - for (p = end->prev; p != start->prev; p = p->prev) + for (run = last; run; run = run_prev( run )) { - if (p->type == diRun) - { - if (!found_black) found_black = !(p->member.run.nFlags & (MERF_WHITESPACE | MERF_ENDPARA)); - if (found_black) num_runs++; - } + if (!found_black) found_black = !(run->nFlags & (MERF_WHITESPACE | MERF_ENDPARA)); + if (found_black) num_runs++; + if (run == start) break; } TRACE("%d runs\n", num_runs); @@ -262,162 +257,138 @@ static void layout_row( ME_DisplayItem *start, const ME_DisplayItem *end ) pos = vis_to_log + 3 * num_runs; levels = (BYTE*)(vis_to_log + 4 * num_runs); - for (i = 0, p = start; i < num_runs; p = p->next) + for (i = 0, run = start; i < num_runs; run = run_next( run )) { - if (p->type == diRun) - { - levels[i] = p->member.run.script_analysis.s.uBidiLevel; - widths[i] = p->member.run.nWidth; - TRACE( "%d: level %d width %d\n", i, levels[i], widths[i] ); - i++; - } + levels[i] = run->script_analysis.s.uBidiLevel; + widths[i] = run->nWidth; + TRACE( "%d: level %d width %d\n", i, levels[i], widths[i] ); + i++; } ScriptLayout( num_runs, levels, vis_to_log, log_to_vis ); - pos[0] = start->member.run.para->pt.x; + pos[0] = run->para->pt.x; for (i = 1; i < num_runs; i++) pos[i] = pos[i - 1] + widths[ vis_to_log[ i - 1 ] ]; - for (i = 0, p = start; i < num_runs; p = p->next) + for (i = 0, run = start; i < num_runs; run = run_next( run )) { - if (p->type == diRun) - { - p->member.run.pt.x = pos[ log_to_vis[ i ] ]; - TRACE( "%d: x = %d\n", i, p->member.run.pt.x ); - i++; - } + run->pt.x = pos[ log_to_vis[ i ] ]; + TRACE( "%d: x = %d\n", i, run->pt.x ); + i++; } if (vis_to_log != buf) heap_free( vis_to_log ); } -static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) +static void ME_InsertRowStart( ME_WrapContext *wc, ME_Run *last ) { - ME_DisplayItem *p, *row; - ME_Paragraph *para = &wc->pPara->member.para; - BOOL bSkippingSpaces = TRUE; - int ascent = 0, descent = 0, width=0, shift = 0, align = 0; + ME_Run *run; + ME_Row *row; + BOOL bSkippingSpaces = TRUE; + int ascent = 0, descent = 0, width = 0, shift = 0, align = 0; - /* Include height of para numbering label */ - if (wc->nRow == 0 && para->fmt.wNumbering) - { - ascent = para->para_num.style->tm.tmAscent; - descent = para->para_num.style->tm.tmDescent; - } + /* Include height of para numbering label */ + if (wc->nRow == 0 && wc->para->fmt.wNumbering) + { + ascent = wc->para->para_num.style->tm.tmAscent; + descent = wc->para->para_num.style->tm.tmDescent; + } - for (p = pEnd->prev; p!=wc->pRowStart->prev; p = p->prev) - { - /* ENDPARA run shouldn't affect row height, except if it's the only run in the paragraph */ - if (p->type==diRun && ((p==wc->pRowStart) || !(p->member.run.nFlags & MERF_ENDPARA))) { /* FIXME add more run types */ - if (p->member.run.nAscent>ascent) - ascent = p->member.run.nAscent; - if (p->member.run.nDescent>descent) - descent = p->member.run.nDescent; - if (bSkippingSpaces) + for (run = last; run; run = run_prev( run )) + { + /* ENDPARA run shouldn't affect row height, except if it's the only run in the paragraph */ + if (run == wc->pRowStart || !(run->nFlags & MERF_ENDPARA)) { - /* Exclude space characters from run width. - * Other whitespace or delimiters are not treated this way. */ - int len = p->member.run.len; - WCHAR *text = get_text( &p->member.run, len - 1 ); - - assert (len); - if (~p->member.run.nFlags & MERF_GRAPHICS) - while (len && *(text--) == ' ') - len--; - if (len) - { - if (len == p->member.run.len) - width += p->member.run.nWidth; - else - width += ME_PointFromCharContext( wc->context, &p->member.run, len, FALSE ); - } - bSkippingSpaces = !len; - } else if (!(p->member.run.nFlags & MERF_ENDPARA)) - width += p->member.run.nWidth; - } - } + if (run->nAscent > ascent) ascent = run->nAscent; + if (run->nDescent > descent) descent = run->nDescent; + if (bSkippingSpaces) + { + /* Exclude space characters from run width. + * Other whitespace or delimiters are not treated this way. */ + int len = run->len; + WCHAR *text = get_text( run, len - 1 ); + + assert(len); + if (~run->nFlags & MERF_GRAPHICS) + while (len && *(text--) == ' ') len--; + if (len) + { + if (len == run->len) + width += run->nWidth; + else + width += ME_PointFromCharContext( wc->context, run, len, FALSE ); + } + bSkippingSpaces = !len; + } + else if (!(run->nFlags & MERF_ENDPARA)) + width += run->nWidth; + } + if (run == wc->pRowStart) break; + } - para->nWidth = max(para->nWidth, width); - row = ME_MakeRow(ascent+descent, ascent, width); - if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ - (para->fmt.dwMask & PFM_TABLE) && (para->fmt.wEffects & PFE_TABLE)) - { - /* The text was shifted down in ME_BeginRow so move the wrap context - * back to where it should be. */ - wc->pt.y--; - /* The height of the row is increased by the borders. */ - row->member.row.nHeight += 2; - } - row->member.row.pt = wc->pt; - row->member.row.nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin); - row->member.row.nRMargin = wc->nRightMargin; - assert(para->fmt.dwMask & PFM_ALIGNMENT); - align = para->fmt.wAlignment; - if (align == PFA_CENTER) - shift = max((wc->nAvailWidth-width)/2, 0); - if (align == PFA_RIGHT) - shift = max(wc->nAvailWidth-width, 0); - - if (para->nFlags & MEPF_COMPLEX) layout_row( wc->pRowStart, pEnd ); - - row->member.row.pt.x = row->member.row.nLMargin + shift; - for (p = wc->pRowStart; p!=pEnd; p = p->next) - { - if (p->type==diRun) { /* FIXME add more run types */ - p->member.run.pt.x += row->member.row.nLMargin+shift; + wc->para->nWidth = max( wc->para->nWidth, width ); + row = row_create( ascent + descent, ascent, width ); + if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ + (wc->para->fmt.dwMask & PFM_TABLE) && (wc->para->fmt.wEffects & PFE_TABLE)) + { + /* The text was shifted down in ME_BeginRow so move the wrap context + * back to where it should be. */ + wc->pt.y--; + /* The height of the row is increased by the borders. */ + row->nHeight += 2; } - } + row->pt = wc->pt; + row->nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin); + row->nRMargin = wc->nRightMargin; + assert(wc->para->fmt.dwMask & PFM_ALIGNMENT); + align = wc->para->fmt.wAlignment; + if (align == PFA_CENTER) shift = max((wc->nAvailWidth-width)/2, 0); + if (align == PFA_RIGHT) shift = max(wc->nAvailWidth-width, 0); - if (wc->nRow == 0 && para->fmt.wNumbering) - { - para->para_num.pt.x = wc->nParaNumOffset + shift; - para->para_num.pt.y = wc->pt.y + row->member.row.nBaseline; - } + if (wc->para->nFlags & MEPF_COMPLEX) layout_row( wc->pRowStart, last ); + + row->pt.x = row->nLMargin + shift; - ME_InsertBefore(wc->pRowStart, row); - wc->nRow++; - wc->pt.y += row->member.row.nHeight; - ME_BeginRow(wc); + for (run = wc->pRowStart; run; run = run_next( run )) + { + run->pt.x += row->nLMargin + shift; + if (run == last) break; + } + + if (wc->nRow == 0 && wc->para->fmt.wNumbering) + { + wc->para->para_num.pt.x = wc->nParaNumOffset + shift; + wc->para->para_num.pt.y = wc->pt.y + row->nBaseline; + } + + ME_InsertBefore( run_get_di( wc->pRowStart ), row_get_di( row ) ); + wc->nRow++; + wc->pt.y += row->nHeight; + ME_BeginRow( wc ); } -static void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p) +static void ME_WrapEndParagraph( ME_WrapContext *wc ) { - ME_DisplayItem *para = wc->pPara; - PARAFORMAT2 *pFmt = ¶->member.para.fmt; - if (wc->pRowStart) - ME_InsertRowStart(wc, p); + if (wc->pRowStart) ME_InsertRowStart( wc, wc->para->eop_run ); + if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ - pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) + wc->para->fmt.dwMask & PFM_TABLE && wc->para->fmt.wEffects & PFE_TABLE) { /* ME_BeginRow was called an extra time for the paragraph, and it shifts the * text down by one pixel for the border, so fix up the wrap context. */ wc->pt.y--; } - - /* - p = para->next; - while(p) { - if (p->type == diParagraph || p->type == diTextEnd) - return; - if (p->type == diRun) - { - ME_Run *run = &p->member.run; - TRACE("%s - (%d, %d)\n", debugstr_run(run), run->pt.x, run->pt.y); - } - p = p->next; - } - */ } -static void ME_WrapSizeRun(ME_WrapContext *wc, ME_DisplayItem *p) +static void ME_WrapSizeRun( ME_WrapContext *wc, ME_Run *run ) { /* FIXME compose style (out of character and paragraph styles) here */ - ME_UpdateRunFlags(wc->context->editor, &p->member.run); + ME_UpdateRunFlags( wc->context->editor, run ); - calc_run_extent(wc->context, &wc->pPara->member.para, - wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, &p->member.run); + calc_run_extent( wc->context, wc->para, + wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run ); } @@ -453,178 +424,169 @@ static int reverse_find_whitespace(const WCHAR *s, int start) return i; } -static ME_DisplayItem *ME_MaximizeSplit(ME_WrapContext *wc, ME_DisplayItem *p, int i) +static ME_Run *ME_MaximizeSplit( ME_WrapContext *wc, ME_Run *run, int i ) { - ME_DisplayItem *pp, *piter = p; + ME_Run *new_run, *iter = run; int j; if (!i) return NULL; - j = reverse_find_non_whitespace( get_text( &p->member.run, 0 ), i); - if (j>0) { - pp = split_run_extents(wc, piter, j); - wc->pt.x += piter->member.run.nWidth; - return pp; + j = reverse_find_non_whitespace( get_text( run, 0 ), i ); + if (j > 0) + { + new_run = split_run_extents( wc, iter, j ); + wc->pt.x += iter->nWidth; + return new_run; } else { - pp = piter; + new_run = iter; /* omit all spaces before split point */ - while(piter != wc->pRowStart) + while (iter != wc->pRowStart) { - piter = ME_FindItemBack(piter, diRun); - if (piter->member.run.nFlags & MERF_WHITESPACE) + iter = run_prev( iter ); + if (iter->nFlags & MERF_WHITESPACE) { - pp = piter; + new_run = iter; continue; } - if (piter->member.run.nFlags & MERF_ENDWHITE) + if (iter->nFlags & MERF_ENDWHITE) { - i = reverse_find_non_whitespace( get_text( &piter->member.run, 0 ), - piter->member.run.len ); - pp = split_run_extents(wc, piter, i); - wc->pt = pp->member.run.pt; - return pp; + i = reverse_find_non_whitespace( get_text( iter, 0 ), iter->len ); + new_run = split_run_extents( wc, iter, i ); + wc->pt = new_run->pt; + return new_run; } /* this run is the end of spaces, so the run edge is a good point to split */ - wc->pt = pp->member.run.pt; + wc->pt = new_run->pt; wc->bOverflown = TRUE; - TRACE("Split point is: %s|%s\n", debugstr_run( &piter->member.run ), debugstr_run( &pp->member.run )); - return pp; + TRACE( "Split point is: %s|%s\n", debugstr_run( iter ), debugstr_run( new_run ) ); + return new_run; } - wc->pt = piter->member.run.pt; - return piter; + wc->pt = iter->pt; + return iter; } } -static ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem *p, int loc) +static ME_Run *ME_SplitByBacktracking( ME_WrapContext *wc, ME_Run *run, int loc ) { - ME_DisplayItem *piter = p, *pp; + ME_Run *new_run; int i, idesp, len; - ME_Run *run = &p->member.run; idesp = i = find_split_point( wc->context, loc, run ); len = run->len; - assert(len>0); - assert(i 0 ); + assert( i < len ); + if (i) + { /* don't split words */ i = reverse_find_whitespace( get_text( run, 0 ), i ); - pp = ME_MaximizeSplit(wc, p, i); - if (pp) - return pp; + new_run = ME_MaximizeSplit(wc, run, i); + if (new_run) return new_run; } - TRACE("Must backtrack to split at: %s\n", debugstr_run( &p->member.run )); + TRACE("Must backtrack to split at: %s\n", debugstr_run( run )); if (wc->pLastSplittableRun) { - if (wc->pLastSplittableRun->member.run.nFlags & (MERF_GRAPHICS|MERF_TAB)) + if (wc->pLastSplittableRun->nFlags & (MERF_GRAPHICS|MERF_TAB)) { - wc->pt = wc->pLastSplittableRun->member.run.pt; + wc->pt = wc->pLastSplittableRun->pt; return wc->pLastSplittableRun; } - else if (wc->pLastSplittableRun->member.run.nFlags & MERF_SPLITTABLE) + else if (wc->pLastSplittableRun->nFlags & MERF_SPLITTABLE) { /* the following two lines are just to check if we forgot to call UpdateRunFlags earlier, they serve no other purpose */ ME_UpdateRunFlags(wc->context->editor, run); - assert((wc->pLastSplittableRun->member.run.nFlags & MERF_SPLITTABLE)); + assert((wc->pLastSplittableRun->nFlags & MERF_SPLITTABLE)); - piter = wc->pLastSplittableRun; - run = &piter->member.run; + run = wc->pLastSplittableRun; len = run->len; /* don't split words */ i = reverse_find_whitespace( get_text( run, 0 ), len ); if (i == len) i = reverse_find_non_whitespace( get_text( run, 0 ), len ); - if (i) { - ME_DisplayItem *piter2 = split_run_extents(wc, piter, i); - wc->pt = piter2->member.run.pt; - return piter2; - } - /* splittable = must have whitespaces */ - assert(0 == "Splittable, but no whitespaces"); + new_run = split_run_extents(wc, run, i); + wc->pt = new_run->pt; + return new_run; } else { /* restart from the first run beginning with spaces */ - wc->pt = wc->pLastSplittableRun->member.run.pt; + wc->pt = wc->pLastSplittableRun->pt; return wc->pLastSplittableRun; } } - TRACE("Backtracking failed, trying desperate: %s\n", debugstr_run( &p->member.run )); + TRACE("Backtracking failed, trying desperate: %s\n", debugstr_run( run )); /* OK, no better idea, so assume we MAY split words if we can split at all*/ if (idesp) - return split_run_extents(wc, piter, idesp); + return split_run_extents(wc, run, idesp); else - if (wc->pRowStart && piter != wc->pRowStart) + if (wc->pRowStart && run != wc->pRowStart) { /* don't need to break current run, because it's possible to split before this run */ wc->bOverflown = TRUE; - return piter; + return run; } else { /* split point inside first character - no choice but split after that char */ - if (len != 1) { + if (len != 1) /* the run is more than 1 char, so we may split */ - return split_run_extents(wc, piter, 1); - } + return split_run_extents( wc, run, 1 ); + /* the run is one char, can't split it */ - return piter; + return run; } } -static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) +static ME_Run *ME_WrapHandleRun( ME_WrapContext *wc, ME_Run *run ) { - ME_DisplayItem *pp; - ME_Run *run; + ME_Run *new_run; int len; - assert(p->type == diRun); - if (!wc->pRowStart) - wc->pRowStart = p; - run = &p->member.run; + if (!wc->pRowStart) wc->pRowStart = run; run->pt.x = wc->pt.x; run->pt.y = wc->pt.y; - ME_WrapSizeRun(wc, p); + ME_WrapSizeRun( wc, run ); len = run->len; if (wc->bOverflown) /* just skipping final whitespaces */ { /* End paragraph run can't overflow to the next line by itself. */ - if (run->nFlags & MERF_ENDPARA) - return p->next; + if (run->nFlags & MERF_ENDPARA) return run_next( run ); - if (run->nFlags & MERF_WHITESPACE) { + if (run->nFlags & MERF_WHITESPACE) + { wc->pt.x += run->nWidth; /* skip runs consisting of only whitespaces */ - return p->next; + return run_next( run ); } - if (run->nFlags & MERF_STARTWHITE) { + if (run->nFlags & MERF_STARTWHITE) + { /* try to split the run at the first non-white char */ int black; black = find_non_whitespace( get_text( run, 0 ), run->len, 0 ); - if (black) { + if (black) + { + ME_Run *new_run; wc->bOverflown = FALSE; - pp = split_run_extents(wc, p, black); - calc_run_extent(wc->context, &wc->pPara->member.para, - wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, - &pp->member.run); - ME_InsertRowStart(wc, pp); - return pp; + new_run = split_run_extents( wc, run, black ); + calc_run_extent( wc->context, wc->para, + wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run ); + ME_InsertRowStart( wc, run ); + return new_run; } } /* black run: the row goes from pRowStart to the previous run */ - ME_InsertRowStart(wc, p); - return p; + ME_InsertRowStart( wc, run_prev( run ) ); + return run; } /* simply end the current row and move on to next one */ if (run->nFlags & MERF_ENDROW) { - p = p->next; - ME_InsertRowStart(wc, p); - return p; + ME_InsertRowStart( wc, run ); + return run_next( run ); } /* will current run fit? */ @@ -636,35 +598,35 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) if (run->nFlags & (MERF_WHITESPACE | MERF_ENDPARA)) { /* let the overflow logic handle it */ wc->bOverflown = TRUE; - return p; + return run; } /* TAB: we can split before */ if (run->nFlags & MERF_TAB) { wc->bOverflown = TRUE; - if (wc->pRowStart == p) + if (wc->pRowStart == run) /* Don't split before the start of the run, or we will get an * endless loop. */ - return p->next; + return run_next( run ); else - return p; + return run; } /* graphics: we can split before, if run's width is smaller than row's width */ if ((run->nFlags & MERF_GRAPHICS) && run->nWidth <= wc->nAvailWidth) { wc->bOverflown = TRUE; - return p; + return run; } /* can we separate out the last spaces ? (to use overflow logic later) */ if (run->nFlags & MERF_ENDWHITE) { /* we aren't sure if it's *really* necessary, it's a good start however */ int black = reverse_find_non_whitespace( get_text( run, 0 ), len ); - split_run_extents(wc, p, black); + split_run_extents( wc, run, black ); /* handle both parts again */ - return p; + return run; } /* determine the split point by backtracking */ - pp = ME_SplitByBacktracking(wc, p, loc); - if (pp == wc->pRowStart) + new_run = ME_SplitByBacktracking( wc, run, loc ); + if (new_run == wc->pRowStart) { if (run->nFlags & MERF_STARTWHITE) { @@ -676,32 +638,32 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) /* The lines will only contain spaces, and the rest of the run will * overflow onto the next line. */ wc->bOverflown = TRUE; - return p; + return run; } /* Couldn't split the first run, possible because we have a large font * with a single character that caused an overflow. */ wc->pt.x += run->nWidth; - return p->next; + return run_next( run ); } - if (p != pp) /* found a suitable split point */ + if (run != new_run) /* found a suitable split point */ { wc->bOverflown = TRUE; - return pp; + return new_run; } /* we detected that it's best to split on start of this run */ if (wc->bOverflown) - return pp; + return new_run; ERR("failure!\n"); /* not found anything - writing over margins is the only option left */ } if ((run->nFlags & (MERF_SPLITTABLE | MERF_STARTWHITE)) - || ((run->nFlags & (MERF_GRAPHICS|MERF_TAB)) && (p != wc->pRowStart))) + || ((run->nFlags & (MERF_GRAPHICS|MERF_TAB)) && (run != wc->pRowStart))) { - wc->pLastSplittableRun = p; + wc->pLastSplittableRun = run; } wc->pt.x += run->nWidth; - return p->next; + return run_next( run ); } static int ME_GetParaLineSpace(ME_Context* c, ME_Paragraph* para) @@ -727,39 +689,41 @@ static int ME_GetParaLineSpace(ME_Context* c, ME_Paragraph* para) return sp * c->editor->nZoomNumerator / c->editor->nZoomDenominator; } -static void ME_PrepareParagraphForWrapping(ME_TextEditor *editor, ME_Context *c, ME_DisplayItem *tp) { - ME_DisplayItem *p; - - tp->member.para.nWidth = 0; - /* remove row start items as they will be reinserted by the - * paragraph wrapper anyway */ - editor->total_rows -= tp->member.para.nRows; - tp->member.para.nRows = 0; - for (p = tp->next; p != tp->member.para.next_para; p = p->next) { - if (p->type == diStartRow) { - ME_DisplayItem *pRow = p; - p = p->prev; - ME_Remove(pRow); - ME_DestroyDisplayItem(pRow); +static void ME_PrepareParagraphForWrapping( ME_TextEditor *editor, ME_Context *c, ME_Paragraph *para ) +{ + ME_DisplayItem *p; + + para->nWidth = 0; + /* remove row start items as they will be reinserted by the + * paragraph wrapper anyway */ + editor->total_rows -= para->nRows; + para->nRows = 0; + for (p = para_get_di( para ); p != para->next_para; p = p->next) + { + if (p->type == diStartRow) + { + ME_DisplayItem *pRow = p; + p = p->prev; + ME_Remove( pRow ); + ME_DestroyDisplayItem( pRow ); + } } - } - /* join runs that can be joined */ - for (p = tp->next; p != tp->member.para.next_para; p = p->next) { - assert(p->type != diStartRow); /* should have been deleted above */ - if (p->type == diRun) { - while (p->next->type == diRun && /* FIXME */ - ME_CanJoinRuns(&p->member.run, &p->next->member.run)) { - ME_JoinRuns(c->editor, p); - } + + /* join runs that can be joined */ + for (p = para_get_di( para )->next; p != para->next_para; p = p->next) + { + assert(p->type != diStartRow); /* should have been deleted above */ + if (p->type == diRun) + { + while (p->next->type == diRun && ME_CanJoinRuns( &p->member.run, &p->next->member.run )) + run_join( c->editor, &p->member.run ); + } } - } } -static HRESULT itemize_para( ME_Context *c, ME_DisplayItem *p ) +static HRESULT itemize_para( ME_Context *c, ME_Paragraph *para ) { - ME_Paragraph *para = &p->member.para; ME_Run *run; - ME_DisplayItem *di; SCRIPT_ITEM buf[16], *items = buf; int items_passed = ARRAY_SIZE( buf ), num_items, cur_item; SCRIPT_CONTROL control = { LANG_USER_DEFAULT, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, @@ -767,8 +731,6 @@ static HRESULT itemize_para( ME_Context *c, ME_DisplayItem *p ) SCRIPT_STATE state = { 0, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0 }; HRESULT hr; - assert( p->type == diParagraph ); - if (para->fmt.dwMask & PFM_RTLPARA && para->fmt.wEffects & PFE_RTLPARA) state.uBidiLevel = 1; @@ -799,19 +761,13 @@ static HRESULT itemize_para( ME_Context *c, ME_DisplayItem *p ) } TRACE( "before splitting runs into ranges\n" ); - for (di = p->next; di != p->member.para.next_para; di = di->next) - { - if (di->type != diRun) continue; - TRACE( "\t%d: %s\n", di->member.run.nCharOfs, debugstr_run( &di->member.run ) ); - } + for (run = para_first_run( para ); run; run = run_next( run )) + TRACE( "\t%d: %s\n", run->nCharOfs, debugstr_run( run ) ); } /* split runs into ranges at item boundaries */ - for (di = p->next, cur_item = 0; di != p->member.para.next_para; di = di->next) + for (run = para_first_run( para ), cur_item = 0; run; run = run_next( run )) { - if (di->type != diRun) continue; - run = &di->member.run; - if (run->nCharOfs == items[cur_item+1].iCharPos) cur_item++; items[cur_item].a.fLogicalOrder = TRUE; @@ -821,19 +777,16 @@ static HRESULT itemize_para( ME_Context *c, ME_DisplayItem *p ) if (run->nCharOfs + run->len > items[cur_item+1].iCharPos) { - ME_Cursor cursor = {p, di, items[cur_item+1].iCharPos - run->nCharOfs}; - ME_SplitRunSimple( c->editor, &cursor ); + ME_Cursor cursor = { para, run, items[cur_item + 1].iCharPos - run->nCharOfs }; + run_split( c->editor, &cursor ); } } if (TRACE_ON( richedit )) { TRACE( "after splitting into ranges\n" ); - for (di = p->next; di != p->member.para.next_para; di = di->next) - { - if (di->type != diRun) continue; - TRACE( "\t%d: %s\n", di->member.run.nCharOfs, debugstr_run( &di->member.run ) ); - } + for (run = para_first_run( para ); run; run = run_next( run )) + TRACE( "\t%d: %s\n", run->nCharOfs, debugstr_run( run ) ); } para->nFlags |= MEPF_COMPLEX; @@ -844,353 +797,330 @@ end: } -static HRESULT shape_para( ME_Context *c, ME_DisplayItem *p ) +static HRESULT shape_para( ME_Context *c, ME_Paragraph *para ) { - ME_DisplayItem *di; ME_Run *run; HRESULT hr; - for (di = p->next; di != p->member.para.next_para; di = di->next) + for (run = para_first_run( para ); run; run = run_next( run )) { - if (di->type != diRun) continue; - run = &di->member.run; - hr = shape_run( c, run ); if (FAILED( hr )) { - run->para->nFlags &= ~MEPF_COMPLEX; + para->nFlags &= ~MEPF_COMPLEX; return hr; } } return hr; } -static void ME_WrapTextParagraph(ME_TextEditor *editor, ME_Context *c, ME_DisplayItem *tp) { - ME_DisplayItem *p; +static void ME_WrapTextParagraph( ME_TextEditor *editor, ME_Context *c, ME_Paragraph *para ) +{ + ME_Run *run; ME_WrapContext wc; int border = 0; int linespace = 0; - PARAFORMAT2 *pFmt; - assert(tp->type == diParagraph); - if (!(tp->member.para.nFlags & MEPF_REWRAP)) { - return; - } - ME_PrepareParagraphForWrapping(editor, c, tp); + if (!(para->nFlags & MEPF_REWRAP)) return; + + ME_PrepareParagraphForWrapping( editor, c, para ); /* Calculate paragraph numbering label */ - para_num_init( c, &tp->member.para ); + para_num_init( c, para ); /* For now treating all non-password text as complex for better testing */ - if (!c->editor->cPasswordMask /* && + if (!c->editor->password_char /* && ScriptIsComplex( tp->member.para.text->szData, tp->member.para.text->nLen, SIC_COMPLEX ) == S_OK */) { - if (SUCCEEDED( itemize_para( c, tp ) )) - shape_para( c, tp ); + if (SUCCEEDED( itemize_para( c, para ) )) + shape_para( c, para ); } - pFmt = &tp->member.para.fmt; - wc.context = c; - wc.pPara = tp; -/* wc.para_style = tp->member.para.style; */ + wc.para = para; wc.style = NULL; wc.nParaNumOffset = 0; - if (tp->member.para.nFlags & MEPF_ROWEND) { + if (para->nFlags & MEPF_ROWEND) wc.nFirstMargin = wc.nLeftMargin = wc.nRightMargin = 0; - } else { - int dxStartIndent = pFmt->dxStartIndent; - if (tp->member.para.pCell) { - dxStartIndent += ME_GetTableRowEnd(tp)->member.para.fmt.dxOffset; - } - wc.nLeftMargin = ME_twips2pointsX(c, dxStartIndent + pFmt->dxOffset); - wc.nFirstMargin = ME_twips2pointsX(c, dxStartIndent); - if (pFmt->wNumbering) + else + { + int dxStartIndent = para->fmt.dxStartIndent; + if (para_cell( wc.para )) dxStartIndent += table_row_end( para )->fmt.dxOffset; + + wc.nLeftMargin = ME_twips2pointsX( c, dxStartIndent + para->fmt.dxOffset ); + wc.nFirstMargin = ME_twips2pointsX( c, dxStartIndent ); + if (para->fmt.wNumbering) { wc.nParaNumOffset = wc.nFirstMargin; - dxStartIndent = max( ME_twips2pointsX(c, pFmt->wNumberingTab), - tp->member.para.para_num.width ); + dxStartIndent = max( ME_twips2pointsX(c, para->fmt.wNumberingTab), + para->para_num.width ); wc.nFirstMargin += dxStartIndent; } - wc.nRightMargin = ME_twips2pointsX(c, pFmt->dxRightIndent); + wc.nRightMargin = ME_twips2pointsX( c, para->fmt.dxRightIndent ); - if (wc.nFirstMargin < 0) - wc.nFirstMargin = 0; - if (wc.nLeftMargin < 0) - wc.nLeftMargin = 0; + if (wc.nFirstMargin < 0) wc.nFirstMargin = 0; + if (wc.nLeftMargin < 0) wc.nLeftMargin = 0; } if (c->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ - pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) + para->fmt.dwMask & PFM_TABLE && para->fmt.wEffects & PFE_TABLE) { - wc.nFirstMargin += ME_twips2pointsX(c, pFmt->dxOffset * 2); + wc.nFirstMargin += ME_twips2pointsX( c, para->fmt.dxOffset * 2 ); } wc.nRow = 0; wc.pt.y = 0; - if (pFmt->dwMask & PFM_SPACEBEFORE) - wc.pt.y += ME_twips2pointsY(c, pFmt->dySpaceBefore); - if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) && - pFmt->dwMask & PFM_BORDER) + if (para->fmt.dwMask & PFM_SPACEBEFORE) + wc.pt.y += ME_twips2pointsY( c, para->fmt.dySpaceBefore ); + if (!(para->fmt.dwMask & PFM_TABLE && para->fmt.wEffects & PFE_TABLE) && + para->fmt.dwMask & PFM_BORDER) { - border = ME_GetParaBorderWidth(c, tp->member.para.fmt.wBorders); - if (pFmt->wBorders & 1) { + border = ME_GetParaBorderWidth( c, para->fmt.wBorders ); + if (para->fmt.wBorders & 1) + { wc.nFirstMargin += border; wc.nLeftMargin += border; } - if (pFmt->wBorders & 2) - wc.nRightMargin -= border; - if (pFmt->wBorders & 4) - wc.pt.y += border; + if (para->fmt.wBorders & 2) wc.nRightMargin -= border; + if (para->fmt.wBorders & 4) wc.pt.y += border; } - linespace = ME_GetParaLineSpace(c, &tp->member.para); + linespace = ME_GetParaLineSpace( c, para ); - ME_BeginRow(&wc); - for (p = tp->next; p!=tp->member.para.next_para; ) { - assert(p->type != diStartRow); - if (p->type == diRun) { - p = ME_WrapHandleRun(&wc, p); - } - else p = p->next; - if (wc.nRow && p == wc.pRowStart) - wc.pt.y += linespace; + ME_BeginRow( &wc ); + run = para_first_run( para ); + while (run) + { + run = ME_WrapHandleRun( &wc, run ); + if (wc.nRow && run == wc.pRowStart) wc.pt.y += linespace; } - ME_WrapEndParagraph(&wc, p); - if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) && - (pFmt->dwMask & PFM_BORDER) && (pFmt->wBorders & 8)) + ME_WrapEndParagraph( &wc ); + if (!(para->fmt.dwMask & PFM_TABLE && para->fmt.wEffects & PFE_TABLE) && + (para->fmt.dwMask & PFM_BORDER) && (para->fmt.wBorders & 8)) wc.pt.y += border; - if (tp->member.para.fmt.dwMask & PFM_SPACEAFTER) - wc.pt.y += ME_twips2pointsY(c, pFmt->dySpaceAfter); + if (para->fmt.dwMask & PFM_SPACEAFTER) + wc.pt.y += ME_twips2pointsY( c, para->fmt.dySpaceAfter ); - tp->member.para.nFlags &= ~MEPF_REWRAP; - tp->member.para.nHeight = wc.pt.y; - tp->member.para.nRows = wc.nRow; + para->nFlags &= ~MEPF_REWRAP; + para->nHeight = wc.pt.y; + para->nRows = wc.nRow; editor->total_rows += wc.nRow; } -static void ME_MarkRepaintEnd(ME_DisplayItem *para, - ME_DisplayItem **repaint_start, - ME_DisplayItem **repaint_end) +struct repaint_range +{ + ME_Paragraph *start, *end; +}; + +static void update_repaint( ME_Paragraph *para, struct repaint_range *repaint ) { - if (!*repaint_start) - *repaint_start = para; - *repaint_end = para; + if (!repaint->start) repaint->start = para; + repaint->end = para; } -static void adjust_para_y(ME_DisplayItem *item, ME_Context *c, ME_DisplayItem *repaint_start, ME_DisplayItem *repaint_end) +static void adjust_para_y( ME_Paragraph *para, ME_Context *c, struct repaint_range *repaint ) { - if (item->member.para.nFlags & MEPF_ROWSTART) + ME_Cell *cell; + + if (para->nFlags & MEPF_ROWSTART) { - ME_DisplayItem *cell = ME_FindItemFwd(item, diCell); - ME_DisplayItem *endRowPara; + ME_Paragraph *end_row_para = table_row_end( para ); int borderWidth = 0; - cell->member.cell.pt = c->pt; + + cell = table_row_first_cell( para ); + cell->pt = c->pt; /* Offset the text by the largest top border width. */ - while (cell->member.cell.next_cell) + while (cell_next( cell )) { - borderWidth = max(borderWidth, cell->member.cell.border.top.width); - cell = cell->member.cell.next_cell; + borderWidth = max( borderWidth, cell->border.top.width ); + cell = cell_next( cell ); } - endRowPara = ME_FindItemFwd(cell, diParagraph); - assert(endRowPara->member.para.nFlags & MEPF_ROWEND); if (borderWidth > 0) { borderWidth = max(ME_twips2pointsY(c, borderWidth), 1); while (cell) { - cell->member.cell.yTextOffset = borderWidth; - cell = cell->member.cell.prev_cell; + cell->yTextOffset = borderWidth; + cell = cell_prev( cell ); } c->pt.y += borderWidth; } - if (endRowPara->member.para.fmt.dxStartIndent > 0) + if (end_row_para->fmt.dxStartIndent > 0) { - int dxStartIndent = endRowPara->member.para.fmt.dxStartIndent; - cell = ME_FindItemFwd(item, diCell); - cell->member.cell.pt.x += ME_twips2pointsX(c, dxStartIndent); - c->pt.x = cell->member.cell.pt.x; + cell = table_row_first_cell( para ); + cell->pt.x += ME_twips2pointsX( c, end_row_para->fmt.dxStartIndent ); + c->pt.x = cell->pt.x; } } - else if (item->member.para.nFlags & MEPF_ROWEND) + else if (para->nFlags & MEPF_ROWEND) { /* Set all the cells to the height of the largest cell */ - ME_DisplayItem *startRowPara; + ME_Paragraph *start_row_para = table_row_start( para ); int prevHeight, nHeight, bottomBorder = 0; - ME_DisplayItem *cell = ME_FindItemBack(item, diCell); - item->member.para.nWidth = cell->member.cell.pt.x + cell->member.cell.nWidth; - if (!(item->member.para.next_para->member.para.nFlags & MEPF_ROWSTART)) + + cell = table_row_end_cell( para ); + para->nWidth = cell->pt.x + cell->nWidth; + if (!(para_next( para )->nFlags & MEPF_ROWSTART)) { /* Last row, the bottom border is added to the height. */ - cell = cell->member.cell.prev_cell; - while (cell) - { - bottomBorder = max(bottomBorder, cell->member.cell.border.bottom.width); - cell = cell->member.cell.prev_cell; - } + while ((cell = cell_prev( cell ))) + bottomBorder = max( bottomBorder, cell->border.bottom.width ); + bottomBorder = ME_twips2pointsY(c, bottomBorder); - cell = ME_FindItemBack(item, diCell); + cell = table_row_end_cell( para ); } - prevHeight = cell->member.cell.nHeight; - nHeight = cell->member.cell.prev_cell->member.cell.nHeight + bottomBorder; - cell->member.cell.nHeight = nHeight; - item->member.para.nHeight = nHeight; - cell = cell->member.cell.prev_cell; - cell->member.cell.nHeight = nHeight; - while (cell->member.cell.prev_cell) + prevHeight = cell->nHeight; + nHeight = cell_prev( cell )->nHeight + bottomBorder; + cell->nHeight = nHeight; + para->nHeight = nHeight; + while (cell_prev( cell )) { - cell = cell->member.cell.prev_cell; - cell->member.cell.nHeight = nHeight; + cell = cell_prev( cell ); + cell->nHeight = nHeight; } + /* Also set the height of the start row paragraph */ - startRowPara = ME_FindItemBack(cell, diParagraph); - startRowPara->member.para.nHeight = nHeight; - c->pt.x = startRowPara->member.para.pt.x; - c->pt.y = cell->member.cell.pt.y + nHeight; + start_row_para->nHeight = nHeight; + c->pt.x = start_row_para->pt.x; + c->pt.y = cell->pt.y + nHeight; if (prevHeight < nHeight) { /* The height of the cells has grown, so invalidate the bottom of * the cells. */ - ME_MarkRepaintEnd(item, &repaint_start, &repaint_end); - cell = ME_FindItemBack(item, diCell); + update_repaint( para, repaint ); + cell = cell_prev( table_row_end_cell( para ) ); while (cell) { - ME_MarkRepaintEnd(ME_FindItemBack(cell, diParagraph), &repaint_start, &repaint_end); - cell = cell->member.cell.prev_cell; + update_repaint( cell_end_para( cell ), repaint ); + cell = cell_prev( cell ); } } } - else if (item->member.para.pCell && - item->member.para.pCell != item->member.para.next_para->member.para.pCell) + else if ((cell = para_cell( para )) && para == cell_end_para( cell )) { /* The next paragraph is in the next cell in the table row. */ - ME_Cell *cell = &item->member.para.pCell->member.cell; - cell->nHeight = c->pt.y + item->member.para.nHeight - cell->pt.y; + cell->nHeight = c->pt.y + para->nHeight - cell->pt.y; /* Propagate the largest height to the end so that it can be easily * sent back to all the cells at the end of the row. */ - if (cell->prev_cell) - cell->nHeight = max(cell->nHeight, cell->prev_cell->member.cell.nHeight); + if (cell_prev( cell )) + cell->nHeight = max( cell->nHeight, cell_prev( cell )->nHeight ); c->pt.x = cell->pt.x + cell->nWidth; c->pt.y = cell->pt.y; - cell->next_cell->member.cell.pt = c->pt; - if (!(item->member.para.next_para->member.para.nFlags & MEPF_ROWEND)) + cell_next( cell )->pt = c->pt; + if (!(para_next( para )->nFlags & MEPF_ROWEND)) c->pt.y += cell->yTextOffset; } else { - if (item->member.para.pCell) - { - /* Next paragraph in the same cell. */ - c->pt.x = item->member.para.pCell->member.cell.pt.x; - } - else - /* Normal paragraph */ + if ((cell = para_cell( para ))) /* Next paragraph in the same cell. */ + c->pt.x = cell->pt.x; + else /* Normal paragraph */ c->pt.x = 0; - c->pt.y += item->member.para.nHeight; + c->pt.y += para->nHeight; } } -BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) +BOOL wrap_marked_paras_dc( ME_TextEditor *editor, HDC hdc, BOOL invalidate ) { - ME_DisplayItem *item; + ME_Paragraph *para, *next; + struct wine_rb_entry *entry, *next_entry = NULL; ME_Context c; - int totalWidth = editor->nTotalWidth, diff = 0, prev_width; - ME_DisplayItem *repaint_start = NULL, *repaint_end = NULL; - ME_Paragraph *para; + int totalWidth = editor->nTotalWidth, prev_width; + struct repaint_range repaint = { NULL, NULL }; - if (!editor->first_marked_para) - return FALSE; + if (!editor->marked_paras.root) return FALSE; - ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost)); + ME_InitContext( &c, editor, hdc ); - item = editor->first_marked_para; - c.pt = item->member.para.pt; - while (item != editor->pBuffer->pLast) + entry = wine_rb_head( editor->marked_paras.root ); + while (entry) { - assert(item->type == diParagraph); + para = WINE_RB_ENTRY_VALUE( entry, ME_Paragraph, marked_entry ); + + /* If the first entry lies inside a table, go back to the start + of the table to ensure cell heights are kept in sync. */ + if (!next_entry && para_in_table( para ) && para != table_outer_para( para )) + { + para = table_outer_para( para ); + next_entry = entry; + } + else + next_entry = wine_rb_next( entry ); - prev_width = item->member.para.nWidth; - ME_WrapTextParagraph(editor, &c, item); - if (prev_width == totalWidth && item->member.para.nWidth < totalWidth) + c.pt = para->pt; + prev_width = para->nWidth; + ME_WrapTextParagraph( editor, &c, para ); + if (prev_width == totalWidth && para->nWidth < totalWidth) totalWidth = get_total_width(editor); else - totalWidth = max(totalWidth, item->member.para.nWidth); + totalWidth = max(totalWidth, para->nWidth); - if (!item->member.para.nCharOfs) - ME_MarkRepaintEnd(item->member.para.prev_para, &repaint_start, &repaint_end); - ME_MarkRepaintEnd(item, &repaint_start, &repaint_end); - adjust_para_y(item, &c, repaint_start, repaint_end); + update_repaint( para, &repaint ); + adjust_para_y( para, &c, &repaint ); - if (item->member.para.next_para) + if (para_next( para )) { - diff = c.pt.y - item->member.para.next_para->member.para.pt.y; - if (diff) + if (c.pt.x != para_next( para )->pt.x || c.pt.y != para_next( para )->pt.y || + para_in_table( para )) { - para = &item->member.para; - while (para->next_para && para != &item->member.para.next_marked->member.para && - para != &editor->pBuffer->pLast->member.para) + next = para; + while (para_next( next ) && &next->marked_entry != next_entry && + next != &editor->pBuffer->pLast->member.para) { - ME_MarkRepaintEnd(para->next_para, &repaint_start, &repaint_end); - para->next_para->member.para.pt.y = c.pt.y; - adjust_para_y(para->next_para, &c, repaint_start, repaint_end); - para = ¶->next_para->member.para; + update_repaint( para_next( next ), &repaint ); + para_next( next )->pt = c.pt; + adjust_para_y( para_next( next ), &c, &repaint ); + next = para_next( next ); } } } - if (item->member.para.next_marked) - { - ME_DisplayItem *rem = item; - item = item->member.para.next_marked; - remove_marked_para(editor, rem); - } - else - { - remove_marked_para(editor, item); - item = editor->pBuffer->pLast; - } - c.pt.y = item->member.para.pt.y; + entry = next_entry; } + wine_rb_clear( &editor->marked_paras, NULL, NULL ); + editor->sizeWindow.cx = c.rcView.right-c.rcView.left; editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top; - editor->nTotalLength = c.pt.y; + editor->nTotalLength = editor->pBuffer->pLast->member.para.pt.y; editor->nTotalWidth = totalWidth; - editor->pBuffer->pLast->member.para.pt.x = 0; - editor->pBuffer->pLast->member.para.pt.y = c.pt.y; ME_DestroyContext(&c); - if (repaint_start || editor->nTotalLength < editor->nLastTotalLength) - ME_InvalidateParagraphRange(editor, repaint_start, repaint_end); - return !!repaint_start; + if (invalidate && (repaint.start || editor->nTotalLength < editor->nLastTotalLength)) + para_range_invalidate( editor, repaint.start, repaint.end); + return !!repaint.start; } -void ME_InvalidateParagraphRange(ME_TextEditor *editor, - ME_DisplayItem *start_para, - ME_DisplayItem *last_para) +BOOL ME_WrapMarkedParagraphs( ME_TextEditor *editor ) +{ + HDC hdc = ITextHost_TxGetDC( editor->texthost ); + BOOL ret = wrap_marked_paras_dc( editor, hdc, TRUE ); + ITextHost_TxReleaseDC( editor->texthost, hdc ); + return ret; +} + +void para_range_invalidate( ME_TextEditor *editor, ME_Paragraph *start_para, + ME_Paragraph *last_para ) { - ME_Context c; RECT rc; int ofs; - ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost)); - rc = c.rcView; + rc = editor->rcFormat; ofs = editor->vert_si.nPos; - if (start_para) { - start_para = ME_GetOuterParagraph(start_para); - last_para = ME_GetOuterParagraph(last_para); - rc.top = c.rcView.top + start_para->member.para.pt.y - ofs; + if (start_para) + { + start_para = table_outer_para( start_para ); + last_para = table_outer_para( last_para ); + rc.top += start_para->pt.y - ofs; } else { - rc.top = c.rcView.top + editor->nTotalLength - ofs; + rc.top += editor->nTotalLength - ofs; } if (editor->nTotalLength < editor->nLastTotalLength) - rc.bottom = c.rcView.top + editor->nLastTotalLength - ofs; + rc.bottom = editor->rcFormat.top + editor->nLastTotalLength - ofs; else - rc.bottom = c.rcView.top + last_para->member.para.pt.y + last_para->member.para.nHeight - ofs; + rc.bottom = editor->rcFormat.top + last_para->pt.y + last_para->nHeight - ofs; ITextHost_TxInvalidateRect(editor->texthost, &rc, TRUE); - - ME_DestroyContext(&c); } diff --git a/dll/win32/riched20/writer.c b/dll/win32/riched20/writer.c index 94001ee44b2..7c7e648f107 100644 --- a/dll/win32/riched20/writer.c +++ b/dll/win32/riched20/writer.c @@ -311,50 +311,46 @@ static BOOL find_color_in_colortbl( ME_OutStream *stream, COLORREF color, unsign return i < stream->nFontTblLen; } -static BOOL -ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, - ME_DisplayItem *pLastRun) +static BOOL stream_out_font_and_colour_tbls( ME_OutStream *pStream, ME_Run *first, ME_Run *last ) { - ME_DisplayItem *item = pFirstRun; + ME_Run *run = first; ME_FontTableItem *table = pStream->fonttbl; unsigned int i; - ME_DisplayItem *pCell = NULL; + ME_Cell *cell = NULL; ME_Paragraph *prev_para = NULL; - do { - CHARFORMAT2W *fmt = &item->member.run.style->fmt; + do + { + CHARFORMAT2W *fmt = &run->style->fmt; - add_font_to_fonttbl( pStream, item->member.run.style ); + add_font_to_fonttbl( pStream, run->style ); if (fmt->dwMask & CFM_COLOR && !(fmt->dwEffects & CFE_AUTOCOLOR)) add_color_to_colortbl( pStream, fmt->crTextColor ); if (fmt->dwMask & CFM_BACKCOLOR && !(fmt->dwEffects & CFE_AUTOBACKCOLOR)) add_color_to_colortbl( pStream, fmt->crBackColor ); - if (item->member.run.para != prev_para) + if (run->para != prev_para) { /* check for any para numbering text */ - if (item->member.run.para->fmt.wNumbering) - add_font_to_fonttbl( pStream, item->member.run.para->para_num.style ); + if (run->para->fmt.wNumbering) + add_font_to_fonttbl( pStream, run->para->para_num.style ); - if ((pCell = item->member.para.pCell)) + if ((cell = para_cell( run->para ))) { - ME_Border* borders[4] = { &pCell->member.cell.border.top, - &pCell->member.cell.border.left, - &pCell->member.cell.border.bottom, - &pCell->member.cell.border.right }; + ME_Border* borders[4] = { &cell->border.top, &cell->border.left, + &cell->border.bottom, &cell->border.right }; for (i = 0; i < 4; i++) if (borders[i]->width > 0) add_color_to_colortbl( pStream, borders[i]->colorRef ); } - prev_para = item->member.run.para; + prev_para = run->para; } - if (item == pLastRun) - break; - item = ME_FindItemFwd(item, diRun); - } while (item); + if (run == last) break; + run = run_next_all_paras( run ); + } while (run); if (!ME_StreamOutPrint(pStream, "{\\fonttbl")) return FALSE; @@ -388,31 +384,29 @@ ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, return TRUE; } -static BOOL -ME_StreamOutRTFTableProps(ME_TextEditor *editor, ME_OutStream *pStream, - ME_DisplayItem *para) +static BOOL stream_out_table_props( ME_TextEditor *editor, ME_OutStream *pStream, + ME_Paragraph *para ) { - ME_DisplayItem *cell; + ME_Cell *cell; char props[STREAMOUT_BUFFER_SIZE] = ""; int i; const char sideChar[4] = {'t','l','b','r'}; if (!ME_StreamOutPrint(pStream, "\\trowd")) return FALSE; - if (!editor->bEmulateVersion10) { /* v4.1 */ - PARAFORMAT2 *pFmt = &ME_GetTableRowEnd(para)->member.para.fmt; - para = ME_GetTableRowStart(para); - cell = para->member.para.next_para->member.para.pCell; - assert(cell); + if (!editor->bEmulateVersion10) /* v4.1 */ + { + PARAFORMAT2 *pFmt = &table_row_end( para )->fmt; + cell = table_row_first_cell( para ); + assert( cell ); if (pFmt->dxOffset) sprintf(props + strlen(props), "\\trgaph%d", pFmt->dxOffset); if (pFmt->dxStartIndent) sprintf(props + strlen(props), "\\trleft%d", pFmt->dxStartIndent); - do { - ME_Border* borders[4] = { &cell->member.cell.border.top, - &cell->member.cell.border.left, - &cell->member.cell.border.bottom, - &cell->member.cell.border.right }; + do + { + ME_Border* borders[4] = { &cell->border.top, &cell->border.left, + &cell->border.bottom, &cell->border.right }; for (i = 0; i < 4; i++) { if (borders[i]->width) @@ -426,17 +420,19 @@ ME_StreamOutRTFTableProps(ME_TextEditor *editor, ME_OutStream *pStream, sprintf(props + strlen(props), "\\brdrcf%u", idx); } } - sprintf(props + strlen(props), "\\cellx%d", cell->member.cell.nRightBoundary); - cell = cell->member.cell.next_cell; - } while (cell->member.cell.next_cell); - } else { /* v1.0 - 3.0 */ - const ME_Border* borders[4] = { ¶->member.para.border.top, - ¶->member.para.border.left, - ¶->member.para.border.bottom, - ¶->member.para.border.right }; - PARAFORMAT2 *pFmt = ¶->member.para.fmt; - - assert(!(para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL))); + sprintf( props + strlen(props), "\\cellx%d", cell->nRightBoundary ); + cell = cell_next( cell ); + } while (cell_next( cell )); + } + else /* v1.0 - 3.0 */ + { + const ME_Border* borders[4] = { ¶->border.top, + ¶->border.left, + ¶->border.bottom, + ¶->border.right }; + PARAFORMAT2 *pFmt = ¶->fmt; + + assert( !(para->nFlags & (MEPF_ROWSTART | MEPF_ROWEND | MEPF_CELL)) ); if (pFmt->dxOffset) sprintf(props + strlen(props), "\\trgaph%d", pFmt->dxOffset); if (pFmt->dxStartIndent) @@ -535,54 +531,46 @@ static BOOL stream_out_para_num( ME_OutStream *stream, ME_Paragraph *para, BOOL return TRUE; } -static BOOL -ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream, - ME_DisplayItem *para) +static BOOL stream_out_para_props( ME_TextEditor *editor, ME_OutStream *pStream, + ME_Paragraph *para ) { - PARAFORMAT2 *fmt = ¶->member.para.fmt; + PARAFORMAT2 *fmt = ¶->fmt; char props[STREAMOUT_BUFFER_SIZE] = ""; int i; - ME_Paragraph *prev_para = NULL; - - if (para->member.para.prev_para->type == diParagraph) - prev_para = ¶->member.para.prev_para->member.para; + ME_Paragraph *prev_para = para_prev( para ); - if (!editor->bEmulateVersion10) { /* v4.1 */ - if (para->member.para.nFlags & MEPF_ROWSTART) { + if (!editor->bEmulateVersion10) /* v4.1 */ + { + if (para->nFlags & MEPF_ROWSTART) + { pStream->nNestingLevel++; - if (pStream->nNestingLevel == 1) { - if (!ME_StreamOutRTFTableProps(editor, pStream, para)) - return FALSE; - } + if (pStream->nNestingLevel == 1) + if (!stream_out_table_props( editor, pStream, para )) return FALSE; return TRUE; - } else if (para->member.para.nFlags & MEPF_ROWEND) { + } + else if (para->nFlags & MEPF_ROWEND) + { pStream->nNestingLevel--; - if (pStream->nNestingLevel >= 1) { - if (!ME_StreamOutPrint(pStream, "{\\*\\nesttableprops")) - return FALSE; - if (!ME_StreamOutRTFTableProps(editor, pStream, para)) - return FALSE; - if (!ME_StreamOutPrint(pStream, "\\nestrow}{\\nonesttables\\par}\r\n")) - return FALSE; - } else { - if (!ME_StreamOutPrint(pStream, "\\row\r\n")) - return FALSE; + if (pStream->nNestingLevel >= 1) + { + if (!ME_StreamOutPrint(pStream, "{\\*\\nesttableprops")) return FALSE; + if (!stream_out_table_props( editor, pStream, para )) return FALSE; + if (!ME_StreamOutPrint(pStream, "\\nestrow}{\\nonesttables\\par}\r\n")) return FALSE; } + else if (!ME_StreamOutPrint(pStream, "\\row\r\n")) return FALSE; return TRUE; } - } else { /* v1.0 - 3.0 */ - if (para->member.para.fmt.dwMask & PFM_TABLE && - para->member.para.fmt.wEffects & PFE_TABLE) - { - if (!ME_StreamOutRTFTableProps(editor, pStream, para)) - return FALSE; - } + } + else /* v1.0 - 3.0 */ + { + if (para->fmt.dwMask & PFM_TABLE && para->fmt.wEffects & PFE_TABLE) + if (!stream_out_table_props( editor, pStream, para )) return FALSE; } if (prev_para && !memcmp( fmt, &prev_para->fmt, sizeof(*fmt) )) { if (fmt->wNumbering) - return stream_out_para_num( pStream, ¶->member.para, FALSE ); + return stream_out_para_num( pStream, para, FALSE ); return TRUE; } @@ -590,14 +578,15 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream, return FALSE; if (fmt->wNumbering) - if (!stream_out_para_num( pStream, ¶->member.para, TRUE )) return FALSE; + if (!stream_out_para_num( pStream, para, TRUE )) return FALSE; - if (!editor->bEmulateVersion10) { /* v4.1 */ - if (pStream->nNestingLevel > 0) - strcat(props, "\\intbl"); - if (pStream->nNestingLevel > 1) - sprintf(props + strlen(props), "\\itap%d", pStream->nNestingLevel); - } else { /* v1.0 - 3.0 */ + if (!editor->bEmulateVersion10) /* v4.1 */ + { + if (pStream->nNestingLevel > 0) strcat(props, "\\intbl"); + if (pStream->nNestingLevel > 1) sprintf(props + strlen(props), "\\itap%d", pStream->nNestingLevel); + } + else /* v1.0 - 3.0 */ + { if (fmt->dwMask & PFM_TABLE && fmt->wEffects & PFE_TABLE) strcat(props, "\\intbl"); } @@ -607,8 +596,10 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream, * set very different from the documentation. * (Tested with RichEdit 5.50.25.0601) */ - if (fmt->dwMask & PFM_ALIGNMENT) { - switch (fmt->wAlignment) { + if (fmt->dwMask & PFM_ALIGNMENT) + { + switch (fmt->wAlignment) + { case PFA_LEFT: /* Default alignment: not emitted */ break; @@ -624,10 +615,12 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream, } } - if (fmt->dwMask & PFM_LINESPACING) { + if (fmt->dwMask & PFM_LINESPACING) + { /* FIXME: MSDN says that the bLineSpacingRule field is controlled by the * PFM_SPACEAFTER flag. Is that true? I don't believe so. */ - switch (fmt->bLineSpacingRule) { + switch (fmt->bLineSpacingRule) + { case 0: /* Single spacing */ strcat(props, "\\sl-240\\slmult1"); break; @@ -678,8 +671,10 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream, if (fmt->dwMask & PFM_TABSTOPS) { static const char * const leader[6] = { "", "\\tldot", "\\tlhyph", "\\tlul", "\\tlth", "\\tleq" }; - for (i = 0; i < fmt->cTabCount; i++) { - switch ((fmt->rgxTabs[i] >> 24) & 0xF) { + for (i = 0; i < fmt->cTabCount; i++) + { + switch ((fmt->rgxTabs[i] >> 24) & 0xf) + { case 1: strcat(props, "\\tqc"); break; @@ -706,7 +701,8 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream, if (fmt->sStyle != -1) sprintf(props + strlen(props), "\\s%d", fmt->sStyle); - if (fmt->dwMask & PFM_SHADING) { + if (fmt->dwMask & PFM_SHADING) + { static const char * const style[16] = { "", "\\bgdkhoriz", "\\bgdkvert", "\\bgdkfdiag", "\\bgdkbdiag", "\\bgdkcross", "\\bgdkdcross", "\\bghoriz", "\\bgvert", "\\bgfdiag", @@ -943,11 +939,13 @@ static BOOL stream_out_graphics( ME_TextEditor *editor, ME_OutStream *stream, UINT size; SIZE goal, pic; ME_Context c; + HDC hdc; hr = IOleObject_QueryInterface( run->reobj->obj.poleobj, &IID_IDataObject, (void **)&data ); if (FAILED(hr)) return FALSE; - ME_InitContext( &c, editor, ITextHost_TxGetDC( editor->texthost ) ); + hdc = ITextHost_TxGetDC( editor->texthost ); + ME_InitContext( &c, editor, hdc ); hr = IDataObject_QueryGetData( data, &fmt ); if (hr != S_OK) goto done; @@ -989,6 +987,7 @@ static BOOL stream_out_graphics( ME_TextEditor *editor, ME_OutStream *stream, done: ME_DestroyContext( &c ); + ITextHost_TxReleaseDC( editor->texthost, hdc ); HeapFree( GetProcessHeap(), 0, emf_bits ); ReleaseStgMedium( &med ); IDataObject_Release( data ); @@ -999,7 +998,7 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, const ME_Cursor *start, int nChars, int dwFormat) { ME_Cursor cursor = *start; - ME_DisplayItem *prev_para = NULL; + ME_Paragraph *prev_para = NULL; ME_Cursor endCur = cursor; ME_MoveCursorChars(editor, &endCur, nChars, TRUE); @@ -1007,7 +1006,7 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, if (!ME_StreamOutRTFHeader(pStream, dwFormat)) return FALSE; - if (!ME_StreamOutRTFFontAndColorTbl(pStream, cursor.pRun, endCur.pRun)) + if (!stream_out_font_and_colour_tbls( pStream, cursor.run, endCur.run )) return FALSE; /* TODO: stylesheet table */ @@ -1023,77 +1022,95 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, /* TODO: section formatting properties */ - do { - if (cursor.pPara != prev_para) + do + { + if (cursor.para != prev_para) { - prev_para = cursor.pPara; - if (!ME_StreamOutRTFParaProps(editor, pStream, cursor.pPara)) + prev_para = cursor.para; + if (!stream_out_para_props( editor, pStream, cursor.para )) return FALSE; } - if (cursor.pRun == endCur.pRun && !endCur.nOffset) + if (cursor.run == endCur.run && !endCur.nOffset) break; - TRACE("flags %xh\n", cursor.pRun->member.run.nFlags); + + TRACE("flags %xh\n", cursor.run->nFlags); /* TODO: emit embedded objects */ - if (cursor.pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) + if (cursor.para->nFlags & (MEPF_ROWSTART | MEPF_ROWEND)) continue; - if (cursor.pRun->member.run.nFlags & MERF_GRAPHICS) { - if (!stream_out_graphics(editor, pStream, &cursor.pRun->member.run)) + if (cursor.run->nFlags & MERF_GRAPHICS) + { + if (!stream_out_graphics( editor, pStream, cursor.run )) return FALSE; - } else if (cursor.pRun->member.run.nFlags & MERF_TAB) { + } + else if (cursor.run->nFlags & MERF_TAB) + { if (editor->bEmulateVersion10 && /* v1.0 - 3.0 */ - cursor.pPara->member.para.fmt.dwMask & PFM_TABLE && - cursor.pPara->member.para.fmt.wEffects & PFE_TABLE) + para_in_table( cursor.para )) { if (!ME_StreamOutPrint(pStream, "\\cell ")) return FALSE; - } else { + } + else + { if (!ME_StreamOutPrint(pStream, "\\tab ")) return FALSE; } - } else if (cursor.pRun->member.run.nFlags & MERF_ENDCELL) { - if (pStream->nNestingLevel > 1) { + } + else if (cursor.run->nFlags & MERF_ENDCELL) + { + if (pStream->nNestingLevel > 1) + { if (!ME_StreamOutPrint(pStream, "\\nestcell ")) return FALSE; - } else { + } + else + { if (!ME_StreamOutPrint(pStream, "\\cell ")) return FALSE; } nChars--; - } else if (cursor.pRun->member.run.nFlags & MERF_ENDPARA) { - if (!ME_StreamOutRTFCharProps(pStream, &cursor.pRun->member.run.style->fmt)) + } + else if (cursor.run->nFlags & MERF_ENDPARA) + { + if (!ME_StreamOutRTFCharProps( pStream, &cursor.run->style->fmt )) return FALSE; - if (cursor.pPara->member.para.fmt.dwMask & PFM_TABLE && - cursor.pPara->member.para.fmt.wEffects & PFE_TABLE && - !(cursor.pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL))) + if (para_in_table( cursor.para ) && + !(cursor.para->nFlags & (MEPF_ROWSTART | MEPF_ROWEND | MEPF_CELL))) { if (!ME_StreamOutPrint(pStream, "\\row\r\n")) return FALSE; - } else { + } + else + { if (!ME_StreamOutPrint(pStream, "\\par\r\n")) return FALSE; } /* Skip as many characters as required by current line break */ - nChars = max(0, nChars - cursor.pRun->member.run.len); - } else if (cursor.pRun->member.run.nFlags & MERF_ENDROW) { + nChars = max(0, nChars - cursor.run->len); + } + else if (cursor.run->nFlags & MERF_ENDROW) + { if (!ME_StreamOutPrint(pStream, "\\line\r\n")) return FALSE; nChars--; - } else { + } + else + { int nEnd; - TRACE("style %p\n", cursor.pRun->member.run.style); - if (!ME_StreamOutRTFCharProps(pStream, &cursor.pRun->member.run.style->fmt)) + TRACE("style %p\n", cursor.run->style); + if (!ME_StreamOutRTFCharProps( pStream, &cursor.run->style->fmt )) return FALSE; - nEnd = (cursor.pRun == endCur.pRun) ? endCur.nOffset : cursor.pRun->member.run.len; - if (!ME_StreamOutRTFText(pStream, get_text( &cursor.pRun->member.run, cursor.nOffset ), + nEnd = (cursor.run == endCur.run) ? endCur.nOffset : cursor.run->len; + if (!ME_StreamOutRTFText(pStream, get_text( cursor.run, cursor.nOffset ), nEnd - cursor.nOffset)) return FALSE; cursor.nOffset = 0; } - } while (cursor.pRun != endCur.pRun && ME_NextRun(&cursor.pPara, &cursor.pRun, TRUE)); + } while (cursor.run != endCur.run && cursor_next_run( &cursor, TRUE )); if (!ME_StreamOutMove(pStream, "}\0", 2)) return FALSE; @@ -1111,7 +1128,7 @@ static BOOL ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nBufLen = 0; BOOL success = TRUE; - if (!cursor.pRun) + if (!cursor.run) return FALSE; if (dwFormat & SF_USECODEPAGE) @@ -1119,32 +1136,31 @@ static BOOL ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, /* TODO: Handle SF_TEXTIZED */ - while (success && nChars && cursor.pRun) { - nLen = min(nChars, cursor.pRun->member.run.len - cursor.nOffset); + while (success && nChars && cursor.run) + { + nLen = min(nChars, cursor.run->len - cursor.nOffset); - if (!editor->bEmulateVersion10 && cursor.pRun->member.run.nFlags & MERF_ENDPARA) + if (!editor->bEmulateVersion10 && cursor.run->nFlags & MERF_ENDPARA) { - static const WCHAR szEOL[] = { '\r', '\n' }; - /* richedit 2.0 - all line breaks are \r\n */ if (dwFormat & SF_UNICODE) - success = ME_StreamOutMove(pStream, (const char *)szEOL, sizeof(szEOL)); + success = ME_StreamOutMove(pStream, (const char *)L"\r\n", 2 * sizeof(WCHAR)); else success = ME_StreamOutMove(pStream, "\r\n", 2); } else { if (dwFormat & SF_UNICODE) - success = ME_StreamOutMove(pStream, (const char *)(get_text( &cursor.pRun->member.run, cursor.nOffset )), + success = ME_StreamOutMove(pStream, (const char *)(get_text( cursor.run, cursor.nOffset )), sizeof(WCHAR) * nLen); else { int nSize; - nSize = WideCharToMultiByte(nCodePage, 0, get_text( &cursor.pRun->member.run, cursor.nOffset ), + nSize = WideCharToMultiByte(nCodePage, 0, get_text( cursor.run, cursor.nOffset ), nLen, NULL, 0, NULL, NULL); if (nSize > nBufLen) { buffer = heap_realloc(buffer, nSize); nBufLen = nSize; } - WideCharToMultiByte(nCodePage, 0, get_text( &cursor.pRun->member.run, cursor.nOffset ), + WideCharToMultiByte(nCodePage, 0, get_text( cursor.run, cursor.nOffset ), nLen, buffer, nSize, NULL, NULL); success = ME_StreamOutMove(pStream, buffer, nSize); } @@ -1152,7 +1168,7 @@ static BOOL ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, nChars -= nLen; cursor.nOffset = 0; - cursor.pRun = ME_FindItemFwd(cursor.pRun, diRun); + cursor.run = run_next_all_paras( cursor.run ); } heap_free(buffer); diff --git a/sdk/include/psdk/textserv.h b/sdk/include/psdk/textserv.h index 455e88c5581..16a9a534a91 100644 --- a/sdk/include/psdk/textserv.h +++ b/sdk/include/psdk/textserv.h @@ -33,9 +33,9 @@ extern "C" { #define THISCALLMETHOD_(type,method) type (__thiscall *method) #endif -DEFINE_GUID(IID_ITextServices,0x8d33f740,0xcf58,0x11ce,0xa8,0x9d,0x00,0xaa,0x00,0x6c,0xad,0xc5); -DEFINE_GUID(IID_ITextHost, 0xc5bdd8d0,0xd26e,0x11ce,0xa8,0x9e,0x00,0xaa,0x00,0x6c,0xad,0xc5); -DEFINE_GUID(IID_ITextHost2, 0xc5bdd8d0,0xd26e,0x11ce,0xa8,0x9e,0x00,0xaa,0x00,0x6c,0xad,0xc5); +EXTERN_C const IID IID_ITextServices; +EXTERN_C const IID IID_ITextHost; +EXTERN_C const IID IID_ITextHost2; /***************************************************************************** * ITextServices interface @@ -108,10 +108,10 @@ DECLARE_INTERFACE_(ITextServices,IUnknown) INT y, DWORD* pHitResult) PURE; - THISCALLMETHOD_(HRESULT,OnTxInplaceActivate)( THIS_ + THISCALLMETHOD_(HRESULT,OnTxInPlaceActivate)( THIS_ LPCRECT prcClient) PURE; - THISCALLMETHOD_(HRESULT,OnTxInplaceDeactivate)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,OnTxInPlaceDeactivate)( THIS ) PURE; THISCALLMETHOD_(HRESULT,OnTxUIActivate)( THIS ) PURE; @@ -151,6 +151,7 @@ DECLARE_INTERFACE_(ITextServices,IUnknown) DWORD* pdwHeight) PURE; }; +#undef INTERFACE #ifdef COBJMACROS /*** IUnknown methods ***/ @@ -159,8 +160,6 @@ DECLARE_INTERFACE_(ITextServices,IUnknown) #define ITextServices_Release(p) (p)->lpVtbl->Release(p) #endif -#undef INTERFACE - typedef enum _TXTBACKSTYLE { TXTBACK_TRANSPARENT = 0, TXTBACK_OPAQUE @@ -180,7 +179,7 @@ enum TXTNATURALSIZE { enum TXTVIEW { TXTVIEW_ACTIVE = 0, - TXTVIEW_INACTIVE = 1 + TXTVIEW_INACTIVE = -1 }; #define TXTBIT_RICHTEXT 0x000001 @@ -361,6 +360,7 @@ DECLARE_INTERFACE_(ITextHost,IUnknown) LONG* lSelBarWidth) PURE; }; +#undef INTERFACE #ifdef COBJMACROS /*** IUnknown methods ***/ @@ -369,8 +369,80 @@ DECLARE_INTERFACE_(ITextHost,IUnknown) #define ITextHost_Release(p) (p)->lpVtbl->Release(p) #endif +/***************************************************************************** + * ITextHost2 interface + */ +#define INTERFACE ITextHost2 +DECLARE_INTERFACE_(ITextHost2,ITextHost) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)( THIS_ REFIID riid, void** ppvObject ) PURE; + STDMETHOD_(ULONG,AddRef)( THIS ) PURE; + STDMETHOD_(ULONG,Release)( THIS ) PURE; + /*** ITextHost methods ***/ + THISCALLMETHOD_(HDC,TxGetDC)( THIS ) PURE; + THISCALLMETHOD_(INT,TxReleaseDC)( THIS_ HDC hdc ) PURE; + THISCALLMETHOD_(BOOL,TxShowScrollBar)( THIS_ INT fnBar, BOOL fShow ) PURE; + THISCALLMETHOD_(BOOL,TxEnableScrollBar)( THIS_ INT fuSBFlags, INT fuArrowflags ) PURE; + THISCALLMETHOD_(BOOL,TxSetScrollRange)( THIS_ INT fnBar, LONG nMinPos, INT nMaxPos, BOOL fRedraw ) PURE; + THISCALLMETHOD_(BOOL,TxSetScrollPos)( THIS_ INT fnBar, INT nPos, BOOL fRedraw ) PURE; + THISCALLMETHOD_(void,TxInvalidateRect)( THIS_ LPCRECT prc, BOOL fMode ) PURE; + THISCALLMETHOD_(void,TxViewChange)( THIS_ BOOL fUpdate ) PURE; + THISCALLMETHOD_(BOOL,TxCreateCaret)( THIS_ HBITMAP hbmp, INT xWidth, INT yHeight ) PURE; + THISCALLMETHOD_(BOOL,TxShowCaret)( THIS_ BOOL fShow ) PURE; + THISCALLMETHOD_(BOOL,TxSetCaretPos)( THIS_ INT x, INT y ) PURE; + THISCALLMETHOD_(BOOL,TxSetTimer)( THIS_ UINT idTimer, UINT uTimeout ) PURE; + THISCALLMETHOD_(void,TxKillTimer)( THIS_ UINT idTimer ) PURE; + THISCALLMETHOD_(void,TxScrollWindowEx)( THIS_ INT dx, INT dy, LPCRECT lprcScroll, LPCRECT lprcClip, + HRGN hRgnUpdate, LPRECT lprcUpdate, UINT fuScroll ) PURE; + THISCALLMETHOD_(void,TxSetCapture)( THIS_ BOOL fCapture ) PURE; + THISCALLMETHOD_(void,TxSetFocus)( THIS ) PURE; + THISCALLMETHOD_(void,TxSetCursor)( THIS_ HCURSOR hcur, BOOL fText ) PURE; + THISCALLMETHOD_(BOOL,TxScreenToClient)( THIS_ LPPOINT lppt ) PURE; + THISCALLMETHOD_(BOOL,TxClientToScreen)( THIS_ LPPOINT lppt ) PURE; + THISCALLMETHOD_(HRESULT,TxActivate)( THIS_ LONG* plOldState ) PURE; + THISCALLMETHOD_(HRESULT,TxDeactivate)( THIS_ LONG lNewState ) PURE; + THISCALLMETHOD_(HRESULT,TxGetClientRect)( THIS_ LPRECT prc ) PURE; + THISCALLMETHOD_(HRESULT,TxGetViewInset)( THIS_ LPRECT prc ) PURE; + THISCALLMETHOD_(HRESULT,TxGetCharFormat)( THIS_ const CHARFORMATW** ppCF ) PURE; + THISCALLMETHOD_(HRESULT,TxGetParaFormat)( THIS_ const PARAFORMAT** ppPF ) PURE; + THISCALLMETHOD_(COLORREF,TxGetSysColor)( THIS_ int nIndex ) PURE; + THISCALLMETHOD_(HRESULT,TxGetBackStyle)( THIS_ TXTBACKSTYLE* pStyle ) PURE; + THISCALLMETHOD_(HRESULT,TxGetMaxLength)( THIS_ DWORD* plength ) PURE; + THISCALLMETHOD_(HRESULT,TxGetScrollBars)( THIS_ DWORD* pdwScrollBar ) PURE; + THISCALLMETHOD_(HRESULT,TxGetPasswordChar)( THIS_ WCHAR* pch ) PURE; + THISCALLMETHOD_(HRESULT,TxGetAcceleratorPos)( THIS_ LONG* pch ) PURE; + THISCALLMETHOD_(HRESULT,TxGetExtent)( THIS_ LPSIZEL lpExtent ) PURE; + THISCALLMETHOD_(HRESULT,OnTxCharFormatChange)( THIS_ const CHARFORMATW* pcf ) PURE; + THISCALLMETHOD_(HRESULT,OnTxParaFormatChange)( THIS_ const PARAFORMAT* ppf ) PURE; + THISCALLMETHOD_(HRESULT,TxGetPropertyBits)( THIS_ DWORD dwMask, DWORD* pdwBits ) PURE; + THISCALLMETHOD_(HRESULT,TxNotify)( THIS_ DWORD iNotify, void* pv ) PURE; + THISCALLMETHOD_(HIMC,TxImmGetContext)( THIS ) PURE; + THISCALLMETHOD_(void,TxImmReleaseContext)( THIS_ HIMC himc ) PURE; + THISCALLMETHOD_(HRESULT,TxGetSelectionBarWidth)( THIS_ LONG* lSelBarWidth ) PURE; + /* ITextHost2 methods */ + THISCALLMETHOD_(BOOL,TxIsDoubleClickPending)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetWindow)( THIS_ HWND *hwnd ) PURE; + THISCALLMETHOD_(HRESULT,TxSetForegroundWindow)( THIS ) PURE; + THISCALLMETHOD_(HPALETTE,TxGetPalette)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetEastAsianFlags)( THIS_ LONG *flags ) PURE; + THISCALLMETHOD_(HCURSOR,TxSetCursor2)( THIS_ HCURSOR cursor, BOOL text ) PURE; + THISCALLMETHOD_(void,TxFreeTextServicesNotification)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetEditStyle)( THIS_ DWORD item, DWORD *data ) PURE; + THISCALLMETHOD_(HRESULT,TxGetWindowStyles)( THIS_ DWORD *style, DWORD *ex_style ) PURE; + THISCALLMETHOD_(HRESULT,TxShowDropCaret)( THIS_ BOOL show, HDC hdc, const RECT *rect ) PURE; + THISCALLMETHOD_(HRESULT,TxDestroyCaret)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetHorzExtent)( THIS_ LONG *horz_extent ) PURE; +}; #undef INTERFACE +#ifdef COBJMACROS +/*** IUnknown methods ***/ +#define ITextHost2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define ITextHost2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define ITextHost2_Release(p) (p)->lpVtbl->Release(p) +#endif + HRESULT WINAPI CreateTextServices(IUnknown*,ITextHost*,IUnknown**); typedef HRESULT (WINAPI *PCreateTextServices)(IUnknown*,ITextHost*,IUnknown**); @@ -380,3 +452,4 @@ typedef HRESULT (WINAPI *PCreateTextServices)(IUnknown*,ITextHost*,IUnknown**); #endif #endif /* _TEXTSERV_H */ +