[RICHED20] Sync to Wine-6.10 (#7713)

* Restore cherry picked commit limiting tab stops in para.c
* Add 'remove_definitions(-D_CRT_NON_CONFORMING_SWPRINTFS)' to CMakeFiles.txt.
Restore para.c to standard conforming 'swprintf'.

CORE-6727
This commit is contained in:
Doug Lyons
2025-02-19 22:02:06 -06:00
committed by GitHub
parent ae79d1af90
commit 601646e3b0
23 changed files with 5952 additions and 5911 deletions

View File

@@ -1,4 +1,5 @@
remove_definitions(-D_CRT_NON_CONFORMING_SWPRINTFS)
add_definitions(-D__WINESRC__ -D__ROS_LONG64__) add_definitions(-D__WINESRC__ -D__ROS_LONG64__)
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
spec2def(riched20.dll riched20.spec ADD_IMPORTLIB) spec2def(riched20.dll riched20.spec ADD_IMPORTLIB)

File diff suppressed because it is too large Load Diff

View File

@@ -344,13 +344,12 @@ static HGLOBAL get_unicode_text(ME_TextEditor *editor, const ME_Cursor *start, i
int pars = 0; int pars = 0;
WCHAR *data; WCHAR *data;
HANDLE ret; HANDLE ret;
ME_DisplayItem *para; ME_Paragraph *para;
int nEnd = ME_GetCursorOfs(start) + nChars; int nEnd = ME_GetCursorOfs(start) + nChars;
/* count paragraphs in range */ /* count paragraphs in range */
para = start->pPara; para = start->para;
while((para = para->member.para.next_para) && while ((para = para_next( para )) && para->nCharOfs <= nEnd)
para->member.para.nCharOfs <= nEnd)
pars++; pars++;
ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR) * (nChars + pars + 1)); ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR) * (nChars + pars + 1));

File diff suppressed because it is too large Load Diff

View File

@@ -24,6 +24,7 @@
struct _RTF_Info; struct _RTF_Info;
extern HINSTANCE dll_instance DECLSPEC_HIDDEN;
extern HANDLE me_heap DECLSPEC_HIDDEN; extern HANDLE me_heap DECLSPEC_HIDDEN;
#define RUN_IS_HIDDEN(run) ((run)->style->fmt.dwMask & CFM_HIDDEN \ #define RUN_IS_HIDDEN(run) ((run)->style->fmt.dwMask & CFM_HIDDEN \
@@ -49,11 +50,11 @@ static inline const char *debugstr_run( const ME_Run *run )
} }
/* style.c */ /* style.c */
ME_Style *style_get_insert_style( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
ME_Style *ME_MakeStyle(CHARFORMAT2W *style) DECLSPEC_HIDDEN; ME_Style *ME_MakeStyle(CHARFORMAT2W *style) DECLSPEC_HIDDEN;
void ME_AddRefStyle(ME_Style *item) DECLSPEC_HIDDEN; void ME_AddRefStyle(ME_Style *item) DECLSPEC_HIDDEN;
void ME_DestroyStyle(ME_Style *item) DECLSPEC_HIDDEN; void ME_DestroyStyle(ME_Style *item) DECLSPEC_HIDDEN;
void ME_ReleaseStyle(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; 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 select_style(ME_Context *c, ME_Style *s) DECLSPEC_HIDDEN;
void ME_InitCharFormat2W(CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN; void ME_InitCharFormat2W(CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
@@ -69,15 +70,12 @@ void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt) DE
/* list.c */ /* list.c */
void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat) DECLSPEC_HIDDEN; void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat) DECLSPEC_HIDDEN;
void ME_Remove(ME_DisplayItem *diWhere) 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_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_FindItemFwd(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_FindItemBackOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_MakeDI(ME_DIType type) DECLSPEC_HIDDEN; ME_DisplayItem *ME_MakeDI(ME_DIType type) DECLSPEC_HIDDEN;
void ME_DestroyDisplayItem(ME_DisplayItem *item) DECLSPEC_HIDDEN; void ME_DestroyDisplayItem(ME_DisplayItem *item) DECLSPEC_HIDDEN;
void ME_DumpDocument(ME_TextBuffer *buffer) DECLSPEC_HIDDEN; void ME_DumpDocument(ME_TextBuffer *buffer) DECLSPEC_HIDDEN;
void destroy_para(ME_TextEditor *editor, ME_DisplayItem *item) DECLSPEC_HIDDEN;
/* string.c */ /* string.c */
ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars) DECLSPEC_HIDDEN; ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars) DECLSPEC_HIDDEN;
@@ -114,32 +112,47 @@ int ME_ReverseFindNonWhitespaceV(const ME_String *s, int nVChar) DECLSPEC_HIDDEN
int ME_ReverseFindWhitespaceV(const ME_String *s, int nVChar) DECLSPEC_HIDDEN; int ME_ReverseFindWhitespaceV(const ME_String *s, int nVChar) DECLSPEC_HIDDEN;
/* row.c */ /* row.c */
ME_DisplayItem *ME_RowStart(ME_DisplayItem *item) DECLSPEC_HIDDEN; void row_end_cursor( ME_Row *row, ME_Cursor *cursor, BOOL include_eop ) DECLSPEC_HIDDEN;
/* ME_DisplayItem *ME_RowEnd(ME_DisplayItem *item); */ void row_first_cursor( ME_Row *row, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_FindRowWithNumber(ME_TextEditor *editor, int nRow) DECLSPEC_HIDDEN; ME_Run *row_first_run( ME_Row *row ) DECLSPEC_HIDDEN;
int ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs) 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 */ /* run.c */
ME_DisplayItem *ME_MakeRun(ME_Style *s, int nFlags) DECLSPEC_HIDDEN; void cursor_from_char_ofs( ME_TextEditor *editor, int char_ofs, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, 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; ME_Style *style, const WCHAR *str, int len, int flags ) DECLSPEC_HIDDEN;
void ME_CheckCharOffsets(ME_TextEditor *editor) 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 */ /* 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_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_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_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; 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; BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2) DECLSPEC_HIDDEN;
void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) DECLSPEC_HIDDEN; void run_join( ME_TextEditor *editor, ME_Run *run ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_Cursor *cursor) 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; 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, SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, int nLen,
int startx, int *pAscent, int *pDescent) DECLSPEC_HIDDEN; 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_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_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from, void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from,
@@ -147,8 +160,13 @@ void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from,
void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN; void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
void ME_GetDefaultCharFormat(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; 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 */ /* 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; void ME_SetCursorToStart(ME_TextEditor *editor, ME_Cursor *cursor) DECLSPEC_HIDDEN;
int set_selection_cursors(ME_TextEditor *editor, int from, int to) 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; BOOL ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) DECLSPEC_HIDDEN;
@@ -177,7 +195,6 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, int nChars,
int ME_GetTextLength(ME_TextEditor *editor) DECLSPEC_HIDDEN; int ME_GetTextLength(ME_TextEditor *editor) DECLSPEC_HIDDEN;
int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how) DECLSPEC_HIDDEN; int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how) DECLSPEC_HIDDEN;
ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor) 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 */ /* context.c */
void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC) DECLSPEC_HIDDEN; void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC) DECLSPEC_HIDDEN;
@@ -185,36 +202,49 @@ void ME_DestroyContext(ME_Context *c) DECLSPEC_HIDDEN;
/* wrap.c */ /* wrap.c */
BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) DECLSPEC_HIDDEN; 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; 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 */ /* para.c */
ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run) DECLSPEC_HIDDEN; void editor_get_selection_paras(ME_TextEditor *editor, ME_Paragraph **para, ME_Paragraph **para_end ) DECLSPEC_HIDDEN;
void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **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; 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_DumpParaStyle(ME_Paragraph *s) DECLSPEC_HIDDEN;
void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]) 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; int get_total_width(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void mark_para_rewrap(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN; ME_Cell *para_cell( ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_DisplayItem *get_di_from_para(ME_Paragraph *para) DECLSPEC_HIDDEN; void para_destroy( ME_TextEditor *editor, ME_Paragraph *item ) DECLSPEC_HIDDEN;
void add_marked_para(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN; ME_Row *para_end_row( ME_Paragraph *para ) DECLSPEC_HIDDEN;
void remove_marked_para(ME_TextEditor *editor, ME_DisplayItem *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 */ /* 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_Repaint(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_RewrapRepaint(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_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; void ME_InvalidateSelection(ME_TextEditor *editor) DECLSPEC_HIDDEN;
BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator) 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; int ME_twips2pointsX(const ME_Context *c, int x) DECLSPEC_HIDDEN;
@@ -222,9 +252,9 @@ int ME_twips2pointsY(const ME_Context *c, int y) DECLSPEC_HIDDEN;
/* scroll functions in paint.c */ /* scroll functions in paint.c */
void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) DECLSPEC_HIDDEN; void scroll_abs( ME_TextEditor *editor, int x, int y, BOOL notify ) DECLSPEC_HIDDEN;
void ME_HScrollAbs(ME_TextEditor *editor, int x) DECLSPEC_HIDDEN; void scroll_h_abs( ME_TextEditor *editor, int x, BOOL notify ) DECLSPEC_HIDDEN;
void ME_VScrollAbs(ME_TextEditor *editor, int y) 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_ScrollUp(ME_TextEditor *editor, int cy) DECLSPEC_HIDDEN;
void ME_ScrollDown(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; void ME_ScrollLeft(ME_TextEditor *editor, int cx) DECLSPEC_HIDDEN;
@@ -235,18 +265,19 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) DECLSPEC_HIDDEN;
int ME_GetParaBorderWidth(const ME_Context *c, int flags) DECLSPEC_HIDDEN; int ME_GetParaBorderWidth(const ME_Context *c, int flags) DECLSPEC_HIDDEN;
/* richole.c */ /* richole.c */
LRESULT CreateIRichEditOle(IUnknown *outer_unk, ME_TextEditor *editor, LPVOID *ppvObj) DECLSPEC_HIDDEN; void draw_ole( ME_Context *c, int x, int y, ME_Run* run, BOOL selected ) DECLSPEC_HIDDEN;
void ME_DrawOLE(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_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_CopyReObject(REOBJECT *dst, const REOBJECT *src, DWORD flags) DECLSPEC_HIDDEN;
void ME_DeleteReObject(struct re_object *re_object) 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 */ /* editor.c */
ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) DECLSPEC_HIDDEN; ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) DECLSPEC_HIDDEN;
void ME_DestroyEditor(ME_TextEditor *editor) DECLSPEC_HIDDEN; void ME_DestroyEditor(ME_TextEditor *editor) DECLSPEC_HIDDEN;
LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam,
LPARAM lParam, BOOL unicode, HRESULT* phresult) DECLSPEC_HIDDEN; LPARAM lParam, HRESULT* phresult ) DECLSPEC_HIDDEN;
void ME_SendOldNotify(ME_TextEditor *editor, int nCode) DECLSPEC_HIDDEN;
int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen,
const ME_Cursor *start, int srcChars, BOOL bCRLF, BOOL bEOP) DECLSPEC_HIDDEN; const ME_Cursor *start, int srcChars, BOOL bCRLF, BOOL bEOP) DECLSPEC_HIDDEN;
void ME_RTFCharAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN; void ME_RTFCharAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
@@ -257,32 +288,47 @@ void ME_StreamInFill(ME_InStream *stream) DECLSPEC_HIDDEN;
extern BOOL me_debug DECLSPEC_HIDDEN; extern BOOL me_debug DECLSPEC_HIDDEN;
void ME_ReplaceSel(ME_TextEditor *editor, BOOL can_undo, const WCHAR *str, int len) 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; 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 */ /* table.c */
BOOL ME_IsInTable(ME_DisplayItem *pItem) DECLSPEC_HIDDEN; ME_Cell *cell_create( void ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_InsertTableRowStartFromCursor(ME_TextEditor *editor) DECLSPEC_HIDDEN; ME_Paragraph *cell_end_para( ME_Cell *cell ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor, ME_Paragraph *cell_first_para( ME_Cell *cell ) DECLSPEC_HIDDEN;
ME_DisplayItem *para) DECLSPEC_HIDDEN; ME_Cell *cell_next( ME_Cell *cell ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_InsertTableCellFromCursor(ME_TextEditor *editor) DECLSPEC_HIDDEN; ME_Cell *cell_prev( ME_Cell *cell ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_InsertTableRowEndFromCursor(ME_TextEditor *editor) DECLSPEC_HIDDEN; ME_Paragraph *table_append_row( ME_TextEditor *editor, ME_Paragraph *table_row ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_GetTableRowEnd(ME_DisplayItem *para) DECLSPEC_HIDDEN; void table_handle_tab( ME_TextEditor *editor, BOOL selected_row ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_GetTableRowStart(ME_DisplayItem *para) DECLSPEC_HIDDEN; ME_Paragraph *table_insert_cell( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_GetOuterParagraph(ME_DisplayItem *para) DECLSPEC_HIDDEN; ME_Paragraph *table_insert_row_end( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
void ME_CheckTablesForCorruption(ME_TextEditor *editor) DECLSPEC_HIDDEN; ME_Paragraph *table_insert_row_start( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, ME_Cursor *c, int *nChars) DECLSPEC_HIDDEN; ME_Paragraph *table_insert_row_start_at_para( ME_TextEditor *editor, ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, ME_DisplayItem *table_row) DECLSPEC_HIDDEN; void table_move_from_row_start( ME_TextEditor *editor ) DECLSPEC_HIDDEN;
void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow) DECLSPEC_HIDDEN; ME_Paragraph *table_outer_para( ME_Paragraph *para ) DECLSPEC_HIDDEN;
void ME_MoveCursorFromTableRowStartParagraph(ME_TextEditor *editor) 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; struct RTFTable *ME_MakeTableDef(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef) 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 */ /* txthost.c */
ITextHost *ME_CreateTextHost(HWND hwnd, CREATESTRUCTW *cs, BOOL bEmulateVersion10) DECLSPEC_HIDDEN; #ifdef __ASM_USE_THISCALL_WRAPPER
#if defined(__i386__) && !defined(__MINGW32__) /* Use wrappers to perform thiscall on i386 */ extern const struct ITextHost2Vtbl text_host2_stdcall_vtbl DECLSPEC_HIDDEN;
#define TXTHOST_VTABLE(This) (&itextHostStdcallVtbl) #define TXTHOST_VTABLE(This) (&text_host2_stdcall_vtbl)
#else /* __i386__ */ #else
#define TXTHOST_VTABLE(This) (This)->lpVtbl #define TXTHOST_VTABLE(This) (This)->lpVtbl
#endif /* __i386__ */ #endif
/*** ITextHost methods ***/ /*** ITextHost methods ***/
#define ITextHost_TxGetDC(This) TXTHOST_VTABLE(This)->TxGetDC(This) #define ITextHost_TxGetDC(This) TXTHOST_VTABLE(This)->TxGetDC(This)
#define ITextHost_TxReleaseDC(This,a) TXTHOST_VTABLE(This)->TxReleaseDC(This,a) #define ITextHost_TxReleaseDC(This,a) TXTHOST_VTABLE(This)->TxReleaseDC(This,a)
@@ -323,6 +369,19 @@ ITextHost *ME_CreateTextHost(HWND hwnd, CREATESTRUCTW *cs, BOOL bEmulateVersion1
#define ITextHost_TxImmGetContext(This) TXTHOST_VTABLE(This)->TxImmGetContext(This) #define ITextHost_TxImmGetContext(This) TXTHOST_VTABLE(This)->TxImmGetContext(This)
#define ITextHost_TxImmReleaseContext(This,a) TXTHOST_VTABLE(This)->TxImmReleaseContext(This,a) #define ITextHost_TxImmReleaseContext(This,a) TXTHOST_VTABLE(This)->TxImmReleaseContext(This,a)
#define ITextHost_TxGetSelectionBarWidth(This,a) TXTHOST_VTABLE(This)->TxGetSelectionBarWidth(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 */ /* undo.c */
BOOL add_undo_insert_run( ME_TextEditor *, int pos, const WCHAR *str, int len, int flags, ME_Style *style ) DECLSPEC_HIDDEN; BOOL add_undo_insert_run( ME_TextEditor *, int pos, const WCHAR *str, int len, int flags, ME_Style *style ) DECLSPEC_HIDDEN;
@@ -338,6 +397,33 @@ BOOL ME_Undo(ME_TextEditor *editor) DECLSPEC_HIDDEN;
BOOL ME_Redo(ME_TextEditor *editor) DECLSPEC_HIDDEN; BOOL ME_Redo(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_EmptyUndoStack(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 */ /* writer.c */
LRESULT ME_StreamOutRange(ME_TextEditor *editor, DWORD dwFormat, const ME_Cursor *start, int nChars, EDITSTREAM *stream) DECLSPEC_HIDDEN; 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; LRESULT ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream) DECLSPEC_HIDDEN;
@@ -346,3 +432,4 @@ LRESULT ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream)
HRESULT ME_GetDataObject(ME_TextEditor *editor, const ME_Cursor *start, int nChars, LPDATAOBJECT *lplpdataobj) DECLSPEC_HIDDEN; HRESULT ME_GetDataObject(ME_TextEditor *editor, const ME_Cursor *start, int nChars, LPDATAOBJECT *lplpdataobj) DECLSPEC_HIDDEN;
void release_typelib(void) DECLSPEC_HIDDEN; void release_typelib(void) DECLSPEC_HIDDEN;

View File

@@ -41,15 +41,14 @@
#include <richole.h> #include <richole.h>
#include "imm.h" #include "imm.h"
#include <textserv.h> #include <textserv.h>
#include <tom.h>
#include "usp10.h" #include "usp10.h"
#include "wine/asm.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/heap.h" #include "wine/heap.h"
#include "wine/list.h" #include "wine/list.h"
#include "wine/rbtree.h"
#if defined(__i386__) && !defined(__MINGW32__)
extern const struct ITextHostVtbl itextHostStdcallVtbl DECLSPEC_HIDDEN;
#endif /* __i386__ */
typedef struct tagME_String typedef struct tagME_String
{ {
@@ -204,7 +203,7 @@ typedef struct tagME_Paragraph
PARAFORMAT2 fmt; PARAFORMAT2 fmt;
ME_String *text; ME_String *text;
struct tagME_DisplayItem *pCell; /* v4.1 */ struct tagME_Cell *cell; /* v4.1 */
ME_BorderRect border; ME_BorderRect border;
int nCharOfs; int nCharOfs;
@@ -215,7 +214,7 @@ typedef struct tagME_Paragraph
struct para_num para_num; struct para_num para_num;
ME_Run *eop_run; /* ptr to the end-of-para run */ ME_Run *eop_run; /* ptr to the end-of-para run */
struct tagME_DisplayItem *prev_para, *next_para; struct tagME_DisplayItem *prev_para, *next_para;
struct tagME_DisplayItem *prev_marked, *next_marked; struct wine_rb_entry marked_entry;
} ME_Paragraph; } ME_Paragraph;
typedef struct tagME_Cell /* v4.1 */ typedef struct tagME_Cell /* v4.1 */
@@ -226,7 +225,7 @@ typedef struct tagME_Cell /* v4.1 */
POINT pt; POINT pt;
int nHeight, nWidth; int nHeight, nWidth;
int yTextOffset; /* The text offset is caused by the largest top border. */ 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; } ME_Cell;
typedef struct tagME_Row typedef struct tagME_Row
@@ -272,8 +271,8 @@ typedef struct tagME_TextBuffer
typedef struct tagME_Cursor typedef struct tagME_Cursor
{ {
ME_DisplayItem *pPara; ME_Paragraph *para;
ME_DisplayItem *pRun; ME_Run *run;
int nOffset; int nOffset;
} ME_Cursor; } ME_Cursor;
@@ -379,14 +378,20 @@ typedef struct tagME_InStream ME_InStream;
typedef struct tagME_TextEditor typedef struct tagME_TextEditor
{ {
#ifdef __REACTOS__
HWND hWnd, hwndParent; HWND hWnd, hwndParent;
ITextHost *texthost; #endif
IUnknown *reOle; ITextHost2 *texthost;
BOOL bEmulateVersion10; unsigned int bEmulateVersion10 : 1;
unsigned int in_place_active : 1;
unsigned int have_texthost2 : 1;
ME_TextBuffer *pBuffer; ME_TextBuffer *pBuffer;
ME_Cursor *pCursors; ME_Cursor *pCursors;
#ifdef __REACTOS__
DWORD styleFlags; DWORD styleFlags;
DWORD exStyleFlags; #endif
DWORD props;
DWORD scrollbars;
int nCursors; int nCursors;
SIZE sizeWindow; SIZE sizeWindow;
int nTotalLength, nLastTotalLength; int nTotalLength, nLastTotalLength;
@@ -394,9 +399,6 @@ typedef struct tagME_TextEditor
int nAvailWidth; /* 0 = wrap to client area, else wrap width in twips */ int nAvailWidth; /* 0 = wrap to client area, else wrap width in twips */
int nUDArrowX; int nUDArrowX;
int total_rows; int total_rows;
COLORREF rgbBackColor;
HBRUSH hbrBackground;
BOOL bCaretAtEnd;
int nEventMask; int nEventMask;
int nModifyStep; int nModifyStep;
struct list undo_stack; struct list undo_stack;
@@ -406,15 +408,14 @@ typedef struct tagME_TextEditor
ME_UndoMode nUndoMode; ME_UndoMode nUndoMode;
int nParagraphs; int nParagraphs;
int nLastSelStart, nLastSelEnd; int nLastSelStart, nLastSelEnd;
ME_DisplayItem *pLastSelStartPara, *pLastSelEndPara; ME_Paragraph *last_sel_start_para, *last_sel_end_para;
ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE]; ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
int nZoomNumerator, nZoomDenominator; int nZoomNumerator, nZoomDenominator;
RECT prevClientRect;
RECT rcFormat; RECT rcFormat;
BOOL bDefaultFormatRect;
BOOL bWordWrap; BOOL bWordWrap;
int nTextLimit; int nTextLimit;
EDITWORDBREAKPROCW pfnWordBreak; EDITWORDBREAKPROCW pfnWordBreak;
IRichEditOle *richole;
LPRICHEDITOLECALLBACK lpOleCallback; LPRICHEDITOLECALLBACK lpOleCallback;
/*TEXTMODE variable; contains only one of each of the following options: /*TEXTMODE variable; contains only one of each of the following options:
*TM_RICHTEXT or TM_PLAINTEXT *TM_RICHTEXT or TM_PLAINTEXT
@@ -423,29 +424,31 @@ typedef struct tagME_TextEditor
int mode; int mode;
BOOL bHideSelection; BOOL bHideSelection;
BOOL AutoURLDetect_bEnable; BOOL AutoURLDetect_bEnable;
WCHAR cPasswordMask; WCHAR password_char;
BOOL bHaveFocus; BOOL bHaveFocus;
BOOL bDialogMode; /* Indicates that we are inside a dialog window */
#ifndef __REACTOS__ #ifndef __REACTOS__
/*for IME */ /*for IME */
int imeStartIndex; int imeStartIndex;
#endif #endif
DWORD selofs; /* The size of the selection bar on the left side of control */ DWORD selofs; /* The size of the selection bar on the left side of control */
ME_SelectionType nSelectionType; ME_SelectionType nSelectionType;
ME_DisplayItem *first_marked_para;
/* Track previous notified selection */ /* Track previous notified selection */
CHARRANGE notified_cr; CHARRANGE notified_cr;
/* Cache previously set scrollbar info */ /* Cache previously set scrollbar info */
SCROLLINFO vert_si, horz_si; SCROLLINFO vert_si, horz_si;
unsigned int vert_sb_enabled : 1;
unsigned int horz_sb_enabled : 1;
int caret_height; int caret_height;
BOOL caret_hidden; BOOL caret_hidden;
BOOL bMouseCaptured; BOOL bMouseCaptured;
int wheel_remain; int wheel_remain;
TXTBACKSTYLE back_style;
struct list style_list; struct list style_list;
struct list reobj_list; struct list reobj_list;
struct wine_rb_tree marked_paras;
} ME_TextEditor; } ME_TextEditor;
typedef struct tagME_Context typedef struct tagME_Context
@@ -462,4 +465,27 @@ typedef struct tagME_Context
ME_TextEditor *editor; ME_TextEditor *editor;
} ME_Context; } 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 #endif

View File

@@ -63,51 +63,6 @@ static BOOL ME_DITypesEqual(ME_DIType type, ME_DIType nTypeOrClass)
} }
} }
/* Modifies run pointer to point to the next run.
* If all_para is FALSE constrain the search to the current para,
* otherwise modify the paragraph pointer if moving into the next paragraph.
*
* Returns TRUE if next run is found, otherwise returns FALSE. */
BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run, BOOL all_para)
{
ME_DisplayItem *p = (*run)->next;
while (p->type != diTextEnd)
{
if (p->type == diParagraph) {
if (!all_para) return FALSE;
*para = p;
} else if (p->type == diRun) {
*run = p;
return TRUE;
}
p = p->next;
}
return FALSE;
}
/* Modifies run pointer to point to the previous run.
* If all_para is FALSE constrain the search to the current para,
* otherwise modify the paragraph pointer if moving into the previous paragraph.
*
* Returns TRUE if previous run is found, otherwise returns FALSE. */
BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run, BOOL all_para)
{
ME_DisplayItem *p = (*run)->prev;
while (p->type != diTextStart)
{
if (p->type == diParagraph) {
if (!all_para) return FALSE;
if (para && p->member.para.prev_para->type == diParagraph)
*para = p->member.para.prev_para;
} else if (p->type == diRun) {
*run = p;
return TRUE;
}
p = p->prev;
}
return FALSE;
}
ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass) ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass)
{ {
if (!di) if (!di)

File diff suppressed because it is too large Load Diff

View File

@@ -23,42 +23,47 @@
WINE_DEFAULT_DEBUG_CHANNEL(richedit); 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; para->nFlags |= MEPF_REWRAP;
add_marked_para(editor, para); para_mark_add( editor, para );
} }
ME_DisplayItem *get_di_from_para(ME_Paragraph *para) static ME_Paragraph *para_create( ME_TextEditor *editor )
{
return (ME_DisplayItem *)((ptrdiff_t)para - offsetof(ME_DisplayItem, member));
}
static ME_DisplayItem *make_para(ME_TextEditor *editor)
{ {
ME_DisplayItem *item = ME_MakeDI(diParagraph); 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.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 (para->nWidth == editor->nTotalWidth)
if (item->member.para.nWidth == editor->nTotalWidth)
{ {
item->member.para.nWidth = 0; para->nWidth = 0;
editor->nTotalWidth = get_total_width(editor); editor->nTotalWidth = get_total_width(editor);
} }
editor->total_rows -= item->member.para.nRows; editor->total_rows -= para->nRows;
ME_DestroyString(item->member.para.text); ME_DestroyString( para->text );
para_num_clear( &item->member.para.para_num ); para_num_clear( &para->para_num );
remove_marked_para(editor, item); para_mark_remove( editor, para );
ME_DestroyDisplayItem(item); 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 &para->next_para->member.para;
return NULL;
}
ME_Paragraph *para_prev( ME_Paragraph *para )
{
if (para->prev_para && para->prev_para->type == diParagraph) return &para->prev_para->member.para;
return NULL;
} }
int get_total_width(ME_TextEditor *editor) int get_total_width(ME_TextEditor *editor)
@@ -79,90 +84,85 @@ int get_total_width(ME_TextEditor *editor)
return total_width; 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); return *(int *)key - para->nCharOfs;
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;
}
} }
void add_marked_para(ME_TextEditor *editor, ME_DisplayItem *di) void para_mark_remove( ME_TextEditor *editor, ME_Paragraph *para )
{ {
ME_DisplayItem *iter = editor->first_marked_para; wine_rb_remove_key( &editor->marked_paras, &para->nCharOfs );
}
if (!iter) void para_mark_add( ME_TextEditor *editor, ME_Paragraph *para )
{ {
editor->first_marked_para = di; wine_rb_put( &editor->marked_paras, &para->nCharOfs, &para->marked_entry );
return;
} }
while (iter)
ME_Run *para_first_run( ME_Paragraph *para )
{ {
if (iter == di) ME_DisplayItem *di;
return;
else if (di->member.para.nCharOfs < iter->member.para.nCharOfs) for (di = para_get_di( para ); di != para->next_para; di = di->next )
{ {
if (iter == editor->first_marked_para) if (di->type != diRun) continue;
editor->first_marked_para = di; return &di->member.run;
di->member.para.next_marked = iter;
iter->member.para.prev_marked = di;
break;
} }
else if (di->member.para.nCharOfs >= iter->member.para.nCharOfs) ERR( "failed to find run in paragraph\n" );
return NULL;
}
ME_Run *para_end_run( ME_Paragraph *para )
{ {
if (!iter->member.para.next_marked || di->member.para.nCharOfs < iter->member.para.next_marked->member.para.nCharOfs) return para->eop_run;
}
BOOL para_in_table( ME_Paragraph *para )
{ {
if (iter->member.para.next_marked) return para->fmt.wEffects & PFE_TABLE;
}
ME_Cell *para_cell( ME_Paragraph *para )
{ {
di->member.para.next_marked = iter->member.para.next_marked; return para->cell;
iter->member.para.next_marked->member.para.prev_marked = di;
} }
di->member.para.prev_marked = iter;
iter->member.para.next_marked = di; ME_Row *para_first_row( ME_Paragraph *para )
break; {
} ME_DisplayItem *item;
}
iter = iter->member.para.next_marked; 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) void ME_MakeFirstParagraph(ME_TextEditor *editor)
{ {
static const WCHAR cr_lf[] = {'\r','\n',0};
ME_Context c; ME_Context c;
CHARFORMAT2W cf; CHARFORMAT2W cf;
const CHARFORMATW *host_cf; const CHARFORMATW *host_cf;
LOGFONTW lf; LOGFONTW lf;
HFONT hf; HFONT hf;
ME_TextBuffer *text = editor->pBuffer; ME_TextBuffer *text = editor->pBuffer;
ME_DisplayItem *para = make_para(editor); ME_Paragraph *para = para_create( editor );
ME_DisplayItem *run; ME_Run *run;
ME_Style *style; ME_Style *style;
int eol_len; 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); hf = GetStockObject(SYSTEM_FONT);
assert(hf); assert(hf);
@@ -202,59 +202,57 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
} }
eol_len = editor->bEmulateVersion10 ? 2 : 1; 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 = run_create( style, MERF_ENDPARA );
run->member.run.nCharOfs = 0; run->nCharOfs = 0;
run->member.run.len = eol_len; run->len = eol_len;
run->member.run.para = &para->member.para; run->para = para;
para->eop_run = run;
para->member.para.eop_run = &run->member.run; ME_InsertBefore( text->pLast, para_get_di( para) );
ME_InsertBefore( text->pLast, run_get_di( run ) );
ME_InsertBefore(text->pLast, para); para->prev_para = text->pFirst;
ME_InsertBefore(text->pLast, run); para->next_para = text->pLast;
para->member.para.prev_para = text->pFirst; text->pFirst->member.para.next_para = para_get_di( para );
para->member.para.next_para = text->pLast; text->pLast->member.para.prev_para = para_get_di( para );
text->pFirst->member.para.next_para = para;
text->pLast->member.para.prev_para = para;
text->pLast->member.para.nCharOfs = editor->bEmulateVersion10 ? 2 : 1; 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); 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) while (first != end)
{ {
mark_para_rewrap(editor, first); para_mark_rewrap( editor, first );
first = first->member.para.next_para; 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; para->fmt.dwMask |= PFM_TABLE | PFM_TABLEROWDELIMITER;
if (para->member.para.pCell) {
para->member.para.nFlags |= MEPF_CELL; if (para_cell( para )) para->nFlags |= MEPF_CELL;
} else { else para->nFlags &= ~MEPF_CELL;
para->member.para.nFlags &= ~MEPF_CELL;
} if (para->nFlags & MEPF_ROWEND) para->fmt.wEffects |= PFE_TABLEROWDELIMITER;
if (para->member.para.nFlags & MEPF_ROWEND) { else para->fmt.wEffects &= ~PFE_TABLEROWDELIMITER;
para->member.para.fmt.wEffects |= PFE_TABLEROWDELIMITER;
} else { if (para->nFlags & (MEPF_ROWSTART | MEPF_CELL | MEPF_ROWEND))
para->member.para.fmt.wEffects &= ~PFE_TABLEROWDELIMITER; para->fmt.wEffects |= PFE_TABLE;
}
if (para->member.para.nFlags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND))
para->member.para.fmt.wEffects |= PFE_TABLE;
else else
para->member.para.fmt.wEffects &= ~PFE_TABLE; para->fmt.wEffects &= ~PFE_TABLE;
} }
static inline BOOL para_num_same_list( const PARAFORMAT2 *item, const PARAFORMAT2 *base ) 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 + '(' + ')' */ /* max 4 Roman letters (representing '8') / decade + '(' + ')' */
ME_String *str = ME_MakeStringEmpty( 20 + 2 ); ME_String *str = ME_MakeStringEmpty( 20 + 2 );
WCHAR *p; WCHAR *p;
static const WCHAR fmtW[] = {'%', 'd', 0};
static const WORD letter_base[] = { 1, 26, 26 * 26, 26 * 26 * 26 }; 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. /* 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, 'N' and 'O' are what MS uses for 5000 and 10000, their version doesn't work well above 30000,
@@ -312,7 +309,7 @@ static ME_String *para_num_get_str( ME_Paragraph *para, WORD num )
{ {
case PFN_ARABIC: case PFN_ARABIC:
default: default:
p += swprintf( p, fmtW, num ); p += swprintf( p, 20, L"%d", num );
break; break;
case PFN_LCLETTER: case PFN_LCLETTER:
@@ -396,9 +393,6 @@ void para_num_init( ME_Context *c, ME_Paragraph *para )
{ {
ME_Style *style; ME_Style *style;
CHARFORMAT2W cf; 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; SIZE sz;
if (!para->fmt.wNumbering) return; if (!para->fmt.wNumbering) return;
@@ -412,7 +406,7 @@ void para_num_init( ME_Context *c, ME_Paragraph *para )
{ {
cf.cbSize = sizeof(cf); cf.cbSize = sizeof(cf);
cf.dwMask = CFM_FACE | CFM_CHARSET; cf.dwMask = CFM_FACE | CFM_CHARSET;
memcpy( cf.szFaceName, bullet_font, sizeof(bullet_font) ); lstrcpyW( cf.szFaceName, L"Symbol" );
cf.bCharSet = SYMBOL_CHARSET; cf.bCharSet = SYMBOL_CHARSET;
style = ME_ApplyStyle( c->editor, style, &cf ); style = ME_ApplyStyle( c->editor, style, &cf );
} }
@@ -429,13 +423,13 @@ void para_num_init( ME_Context *c, ME_Paragraph *para )
if (para->fmt.wNumbering != PFN_BULLET) if (para->fmt.wNumbering != PFN_BULLET)
para->para_num.text = para_num_get_str( para, para_num_get_num( para ) ); para->para_num.text = para_num_get_str( para, para_num_get_num( para ) );
else 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 ); select_style( c, para->para_num.style );
GetTextExtentPointW( c->hDC, para->para_num.text->szData, para->para_num.text->nLen, &sz ); GetTextExtentPointW( c->hDC, para->para_num.text->szData, para->para_num.text->nLen, &sz );
para->para_num.width = sz.cx; para->para_num.width = sz.cx;
GetTextExtentPointW( c->hDC, spaceW, 1, &sz ); GetTextExtentPointW( c->hDC, L" ", 1, &sz );
para->para_num.width += sz.cx; para->para_num.width += sz.cx;
} }
@@ -454,14 +448,14 @@ static void para_num_clear_list( ME_TextEditor *editor, ME_Paragraph *para, cons
{ {
do do
{ {
mark_para_rewrap(editor, get_di_from_para(para)); para_mark_rewrap( editor, para );
para_num_clear( &para->para_num ); para_num_clear( &para->para_num );
if (para->next_para->type != diParagraph) break; if (para->next_para->type != diParagraph) break;
para = &para->next_para->member.para; para = &para->next_para->member.para;
} while (para_num_same_list( &para->fmt, orig_fmt )); } while (para_num_same_list( &para->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; PARAFORMAT2 copy;
DWORD dwMask; DWORD dwMask;
@@ -494,7 +488,8 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PA
COPY_FIELD(PFM_ALIGNMENT, wAlignment); COPY_FIELD(PFM_ALIGNMENT, wAlignment);
if (dwMask & PFM_TABSTOPS) if (dwMask & PFM_TABSTOPS)
{ {
para->fmt.cTabCount = max(0, min(pFmt->cTabCount, MAX_TAB_STOPS)); /* Clamp between 0 and MAX_TAB_STOPS */ /* Clamp between 0 and MAX_TAB_STOPS */
para->fmt.cTabCount = max(0, min(pFmt->cTabCount, MAX_TAB_STOPS));
memcpy(para->fmt.rgxTabs, pFmt->rgxTabs, para->fmt.cTabCount * sizeof(LONG)); memcpy(para->fmt.rgxTabs, pFmt->rgxTabs, para->fmt.cTabCount * sizeof(LONG));
} }
@@ -529,7 +524,7 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PA
if (memcmp(&copy, &para->fmt, sizeof(PARAFORMAT2))) if (memcmp(&copy, &para->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)) || if (((dwMask & PFM_NUMBERING) && (copy.wNumbering != para->fmt.wNumbering)) ||
((dwMask & PFM_NUMBERINGSTART) && (copy.wNumberingStart != para->fmt.wNumberingStart)) || ((dwMask & PFM_NUMBERINGSTART) && (copy.wNumberingStart != para->fmt.wNumberingStart)) ||
((dwMask & PFM_NUMBERINGSTYLE) && (copy.wNumberingStyle != para->fmt.wNumberingStyle))) ((dwMask & PFM_NUMBERINGSTYLE) && (copy.wNumberingStyle != para->fmt.wNumberingStyle)))
@@ -542,19 +537,16 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PA
} }
/* split paragraph at the beginning of the run */ /* split paragraph at the beginning of the run */
ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME_Paragraph *para_split( ME_TextEditor *editor, ME_Run *run, ME_Style *style,
ME_Style *style, const WCHAR *eol_str, int eol_len, const WCHAR *eol_str, int eol_len, int paraFlags )
int paraFlags)
{ {
ME_DisplayItem *next_para = NULL; ME_Paragraph *new_para = para_create( editor ), *old_para, *next_para;
ME_DisplayItem *run_para = NULL; ME_Run *end_run, *next_run;
ME_DisplayItem *new_para = make_para(editor);
ME_DisplayItem *end_run;
int ofs, i; int ofs, i;
ME_DisplayItem *pp;
int run_flags = MERF_ENDPARA; 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. */ /* At most 1 of MEPF_CELL, MEPF_ROWSTART, or MEPF_ROWEND should be set. */
assert( !(paraFlags & ~(MEPF_CELL | MEPF_ROWSTART | MEPF_ROWEND)) ); assert( !(paraFlags & ~(MEPF_CELL | MEPF_ROWSTART | MEPF_ROWEND)) );
assert( !(paraFlags & (paraFlags-1)) ); assert( !(paraFlags & (paraFlags-1)) );
@@ -562,258 +554,234 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
run_flags |= MERF_ENDCELL; run_flags |= MERF_ENDCELL;
else if (paraFlags == MEPF_ROWSTART) else if (paraFlags == MEPF_ROWSTART)
run_flags |= MERF_TABLESTART | MERF_HIDDEN; run_flags |= MERF_TABLESTART | MERF_HIDDEN;
} else { /* v1.0 - v3.0 */
assert(!(paraFlags & (MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND)));
} }
assert(run->type == diRun); else /* v1.0 - v3.0 */
run_para = ME_GetParagraph(run); assert( !(paraFlags & (MEPF_CELL |MEPF_ROWSTART | MEPF_ROWEND)) );
assert(run_para->member.para.fmt.cbSize == sizeof(PARAFORMAT2));
old_para = run->para;
assert( old_para->fmt.cbSize == sizeof(PARAFORMAT2) );
/* Clear any cached para numbering following this paragraph */ /* Clear any cached para numbering following this paragraph */
if (run_para->member.para.fmt.wNumbering) if (old_para->fmt.wNumbering)
para_num_clear_list( editor, &run_para->member.para, &run_para->member.para.fmt ); 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); end_run = run_create( style, run_flags );
ofs = end_run->member.run.nCharOfs = run->member.run.nCharOfs; ofs = end_run->nCharOfs = run->nCharOfs;
end_run->member.run.len = eol_len; end_run->len = eol_len;
end_run->member.run.para = run->member.run.para; end_run->para = run->para;
ME_AppendString( run_para->member.para.text, eol_str, eol_len ); ME_AppendString( old_para->text, eol_str, eol_len );
next_para = run_para->member.para.next_para; next_para = &old_para->next_para->member.para;
assert(next_para == ME_FindItemFwd(run_para, diParagraphOrEnd));
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. */ /* Update selection cursors to point to the correct paragraph. */
for (i = 0; i < editor->nCursors; i++) { 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)
{ {
editor->pCursors[i].pPara = new_para; if (editor->pCursors[i].para == old_para &&
run->nCharOfs <= editor->pCursors[i].run->nCharOfs)
{
editor->pCursors[i].para = new_para;
} }
} }
/* the new paragraph will have a different starting offset, so let's update its runs */ /* the new paragraph will have a different starting offset, so update its runs */
pp = run; for (next_run = run; next_run; next_run = run_next( next_run ))
while(pp->type == diRun) { {
pp->member.run.nCharOfs -= ofs; next_run->nCharOfs -= ofs;
pp->member.run.para = &new_para->member.para; next_run->para = new_para;
pp = ME_FindItemFwd(pp, diRunOrParagraphOrEnd);
} }
new_para->member.para.nCharOfs = run_para->member.para.nCharOfs + ofs;
new_para->member.para.nCharOfs += eol_len; new_para->nCharOfs = old_para->nCharOfs + ofs;
new_para->member.para.nFlags = 0; new_para->nCharOfs += eol_len;
mark_para_rewrap(editor, new_para); new_para->nFlags = 0;
para_mark_rewrap( editor, new_para );
/* FIXME initialize format style and call ME_SetParaFormat blah blah */ /* FIXME initialize format style and call ME_SetParaFormat blah blah */
new_para->member.para.fmt = run_para->member.para.fmt; new_para->fmt = old_para->fmt;
new_para->member.para.border = run_para->member.para.border; new_para->border = old_para->border;
/* insert paragraph into paragraph double linked list */ /* insert paragraph into paragraph double linked list */
new_para->member.para.prev_para = run_para; new_para->prev_para = para_get_di( old_para );
new_para->member.para.next_para = next_para; new_para->next_para = para_get_di( next_para );
run_para->member.para.next_para = new_para; old_para->next_para = para_get_di( new_para );
next_para->member.para.prev_para = 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 */ /* insert end run of the old paragraph, and new paragraph, into DI double linked list */
ME_InsertBefore(run, new_para); ME_InsertBefore( run_get_di( run ), para_get_di( new_para ) );
ME_InsertBefore(new_para, end_run); ME_InsertBefore( para_get_di( new_para ), run_get_di( end_run ) );
/* Fix up the paras' eop_run ptrs */ /* Fix up the paras' eop_run ptrs */
new_para->member.para.eop_run = run_para->member.para.eop_run; new_para->eop_run = old_para->eop_run;
run_para->member.para.eop_run = &end_run->member.run; old_para->eop_run = end_run;
if (!editor->bEmulateVersion10) { /* v4.1 */ if (!editor->bEmulateVersion10) /* v4.1 */
{
if (paraFlags & (MEPF_ROWSTART | MEPF_CELL)) if (paraFlags & (MEPF_ROWSTART | MEPF_CELL))
{ {
ME_DisplayItem *cell = ME_MakeDI(diCell); ME_Cell *cell = cell_create();
ME_InsertBefore(new_para, cell); ME_InsertBefore( para_get_di( new_para ), cell_get_di( cell ) );
new_para->member.para.pCell = cell; new_para->cell = cell;
cell->member.cell.next_cell = NULL; cell->next_cell = NULL;
if (paraFlags & MEPF_ROWSTART) if (paraFlags & MEPF_ROWSTART)
{ {
run_para->member.para.nFlags |= MEPF_ROWSTART; old_para->nFlags |= MEPF_ROWSTART;
cell->member.cell.prev_cell = NULL; cell->prev_cell = NULL;
cell->member.cell.parent_cell = run_para->member.para.pCell; cell->parent_cell = old_para->cell;
if (run_para->member.para.pCell) if (para_cell( old_para ))
cell->member.cell.nNestingLevel = run_para->member.para.pCell->member.cell.nNestingLevel + 1; cell->nNestingLevel = para_cell( old_para )->nNestingLevel + 1;
else else
cell->member.cell.nNestingLevel = 1; 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;
} }
} else if (paraFlags & MEPF_ROWEND) { else
run_para->member.para.nFlags |= MEPF_ROWEND; {
run_para->member.para.pCell = run_para->member.para.pCell->member.cell.parent_cell; cell->prev_cell = old_para->cell;
new_para->member.para.pCell = run_para->member.para.pCell; cell_prev( cell )->next_cell = cell;
assert(run_para->member.para.prev_para->member.para.nFlags & MEPF_CELL); assert( old_para->nFlags & MEPF_CELL );
assert(!(run_para->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART)); assert( !(old_para->nFlags & MEPF_ROWSTART) );
if (new_para->member.para.pCell != new_para->member.para.next_para->member.para.pCell cell->nNestingLevel = cell_prev( cell )->nNestingLevel;
&& new_para->member.para.next_para->member.para.pCell cell->parent_cell = cell_prev( cell )->parent_cell;
&& !new_para->member.para.next_para->member.para.pCell->member.cell.prev_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. */ /* 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); else new_para->cell = old_para->cell;
ME_UpdateTableFlags(new_para);
table_update_flags( old_para );
table_update_flags( new_para );
} }
/* force rewrap of the */ /* force rewrap of the */
if (run_para->member.para.prev_para->type == diParagraph) if (old_para->prev_para->type == diParagraph)
mark_para_rewrap(editor, run_para->member.para.prev_para); 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 */ /* 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++; editor->nParagraphs++;
return new_para; return new_para;
} }
/* join tp with tp->member.para.next_para, keeping tp's style; this /* join para with the next para keeping para's style using the paragraph fmt
* is consistent with the original */ specified in use_first_fmt */
ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, ME_Paragraph *para_join( ME_TextEditor *editor, ME_Paragraph *para, BOOL use_first_fmt )
BOOL keepFirstParaFormat)
{ {
ME_DisplayItem *pNext, *pFirstRunInNext, *pRun, *pTmp, *pCell = NULL; ME_Paragraph *next = para_next( para );
int i, shift; ME_Run *end_run, *next_first_run, *tmp_run;
int end_len; ME_Cell *cell = NULL;
int i, end_len;
CHARFORMAT2W fmt; CHARFORMAT2W fmt;
ME_Cursor startCur, endCur; ME_Cursor startCur, endCur;
ME_String *eol_str; ME_String *eol_str;
assert(tp->type == diParagraph); assert( next && para_next( next ) );
assert(tp->member.para.next_para);
assert(tp->member.para.next_para->type == diParagraph);
/* Clear any cached para numbering following this paragraph */ /* Clear any cached para numbering following this paragraph */
if (tp->member.para.fmt.wNumbering) if (para->fmt.wNumbering) para_num_clear_list( editor, para, &para->fmt );
para_num_clear_list( editor, &tp->member.para, &tp->member.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 */ end_len = end_run->len;
pRun = ME_FindItemBack(pNext, diRunOrParagraph); eol_str = ME_VSplitString( para->text, end_run->nCharOfs );
ME_AppendString( para->text, next->text->szData, next->text->nLen );
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 );
/* null char format operation to store the original char format for the ENDPARA run */ /* null char format operation to store the original char format for the ENDPARA run */
ME_InitCharFormat2W(&fmt); ME_InitCharFormat2W(&fmt);
endCur.pPara = pNext; startCur.para = para;
endCur.pRun = ME_FindItemFwd(pNext, diRun); startCur.run = end_run;
endCur.nOffset = 0; endCur.para = next;
startCur = endCur; endCur.run = next_first_run;
ME_PrevRun(&startCur.pPara, &startCur.pRun, TRUE); startCur.nOffset = endCur.nOffset = 0;
ME_SetCharFormat(editor, &startCur, &endCur, &fmt); ME_SetCharFormat(editor, &startCur, &endCur, &fmt);
if (!editor->bEmulateVersion10) { /* v4.1 */ 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;
/* Remove cell boundary if it is between the end paragraph run and the next /* Remove cell boundary if it is between the end paragraph run and the next
* paragraph display item. */ * paragraph display item. */
for (pTmp = pRun->next; pTmp != pNext; pTmp = pTmp->next) 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, next, eol_str, cell );
if (cell)
{ {
if (pTmp->type == diCell) 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 (!use_first_fmt)
{ {
pCell = pTmp; add_undo_set_para_fmt( editor, para );
break; para->fmt = next->fmt;
para->border = next->border;
} }
}
}
add_undo_split_para( editor, &pNext->member.para, eol_str, pCell ? &pCell->member.cell : NULL );
if (pCell)
{
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 );
}
if (!keepFirstParaFormat)
{
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;
}
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 /* Update selection cursors so they don't point to the removed end
* paragraph run, and point to the correct paragraph. */ * paragraph run, and point to the correct paragraph. */
for (i=0; i < editor->nCursors; i++) { for (i = 0; i < editor->nCursors; i++)
if (editor->pCursors[i].pRun == pRun) { {
editor->pCursors[i].pRun = pFirstRunInNext; if (editor->pCursors[i].run == end_run)
{
editor->pCursors[i].run = next_first_run;
editor->pCursors[i].nOffset = 0; 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; for (tmp_run = next_first_run; tmp_run; tmp_run = run_next( tmp_run ))
do { {
pTmp = ME_FindItemFwd(pTmp, diRunOrParagraphOrEnd); tmp_run->nCharOfs += next->nCharOfs - para->nCharOfs - end_len;
if (pTmp->type != diRun) tmp_run->para = para;
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);
/* Fix up the para's eop_run ptr */ /* 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_Remove( run_get_di( end_run ) );
ME_DestroyDisplayItem(pRun); ME_DestroyDisplayItem( run_get_di( end_run) );
if (editor->pLastSelStartPara == pNext) if (editor->last_sel_start_para == next)
editor->pLastSelStartPara = tp; editor->last_sel_start_para = para;
if (editor->pLastSelEndPara == pNext) if (editor->last_sel_end_para == next)
editor->pLastSelEndPara = tp; editor->last_sel_end_para = para;
tp->member.para.next_para = pNext->member.para.next_para; para->next_para = next->next_para;
pNext->member.para.next_para->member.para.prev_para = tp; next->next_para->member.para.prev_para = para_get_di( para );
ME_Remove(pNext); ME_Remove( para_get_di(next) );
destroy_para(editor, pNext); 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); ME_CheckCharOffsets(editor);
editor->nParagraphs--; editor->nParagraphs--;
mark_para_rewrap(editor, tp); para_mark_rewrap( editor, para );
return tp; return para;
}
ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *item) {
return ME_FindItemBackOrHere(item, diParagraph);
} }
void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]) void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048])
@@ -879,18 +847,18 @@ void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048])
#undef DUMP_EFFECT #undef DUMP_EFFECT
} }
void void editor_get_selection_paras( ME_TextEditor *editor, ME_Paragraph **para, ME_Paragraph **para_end )
ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end)
{ {
ME_Cursor *pEndCursor = &editor->pCursors[1]; ME_Cursor *pEndCursor = &editor->pCursors[1];
*para = editor->pCursors[0].pPara; *para = editor->pCursors[0].para;
*para_end = editor->pCursors[1].pPara; *para_end = editor->pCursors[1].para;
if (*para == *para_end) if (*para == *para_end)
return; return;
if ((*para_end)->member.para.nCharOfs < (*para)->member.para.nCharOfs) { if ((*para_end)->nCharOfs < (*para)->nCharOfs)
ME_DisplayItem *tmp = *para; {
ME_Paragraph *tmp = *para;
*para = *para_end; *para = *para_end;
*para_end = tmp; *para_end = tmp;
@@ -899,78 +867,78 @@ ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayIte
/* The paragraph at the end of a non-empty selection isn't included /* The paragraph at the end of a non-empty selection isn't included
* if the selection ends at the start of the paragraph. */ * if the selection ends at the start of the paragraph. */
if (!pEndCursor->pRun->member.run.nCharOfs && !pEndCursor->nOffset) if (!pEndCursor->run->nCharOfs && !pEndCursor->nOffset)
*para_end = (*para_end)->member.para.prev_para; *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, &para, &para_end); editor_get_selection_paras( editor, &para, &para_end );
do { do
ME_SetParaFormat(editor, &para->member.para, pFmt); {
if (para == para_end) para_set_fmt( editor, para, fmt );
break; if (para == para_end) break;
para = para->member.para.next_para; para = para_next( para );
} while(1); } while(1);
return TRUE; return TRUE;
} }
static void ME_GetParaFormat(ME_TextEditor *editor, static void para_copy_fmt( const ME_Paragraph *para, PARAFORMAT2 *fmt )
const ME_DisplayItem *para,
PARAFORMAT2 *pFmt)
{ {
UINT cbSize = pFmt->cbSize; UINT size = fmt->cbSize;
if (pFmt->cbSize >= sizeof(PARAFORMAT2)) {
*pFmt = para->member.para.fmt; if (fmt->cbSize >= sizeof(PARAFORMAT2))
} else { *fmt = para->fmt;
CopyMemory(pFmt, &para->member.para.fmt, pFmt->cbSize); else
pFmt->dwMask &= PFM_ALL; {
memcpy( fmt, &para->fmt, fmt->cbSize );
fmt->dwMask &= PFM_ALL;
} }
pFmt->cbSize = cbSize; 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; ME_Paragraph *para, *para_end;
PARAFORMAT2 *curFmt;
if (pFmt->cbSize < sizeof(PARAFORMAT)) { if (fmt->cbSize < sizeof(PARAFORMAT))
pFmt->dwMask = 0; {
fmt->dwMask = 0;
return; return;
} }
ME_GetSelectionParas(editor, &para, &para_end); editor_get_selection_paras( editor, &para, &para_end );
ME_GetParaFormat(editor, para, pFmt); para_copy_fmt( para, fmt );
/* Invalidate values that change across the selected paragraphs. */ /* Invalidate values that change across the selected paragraphs. */
while (para != para_end) while (para != para_end)
{ {
para = para->member.para.next_para; para = para_next( para );
curFmt = &para->member.para.fmt;
#define CHECK_FIELD(m, f) \ #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_NUMBERING, wNumbering);
CHECK_FIELD(PFM_STARTINDENT, dxStartIndent); CHECK_FIELD(PFM_STARTINDENT, dxStartIndent);
CHECK_FIELD(PFM_RIGHTINDENT, dxRightIndent); CHECK_FIELD(PFM_RIGHTINDENT, dxRightIndent);
CHECK_FIELD(PFM_OFFSET, dxOffset); CHECK_FIELD(PFM_OFFSET, dxOffset);
CHECK_FIELD(PFM_ALIGNMENT, wAlignment); CHECK_FIELD(PFM_ALIGNMENT, wAlignment);
if (pFmt->dwMask & PFM_TABSTOPS) { if (fmt->dwMask & PFM_TABSTOPS)
if (pFmt->cTabCount != para->member.para.fmt.cTabCount || {
memcmp(pFmt->rgxTabs, curFmt->rgxTabs, curFmt->cTabCount*sizeof(int))) if (fmt->cTabCount != para->fmt.cTabCount ||
pFmt->dwMask &= ~PFM_TABSTOPS; 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_SPACEBEFORE, dySpaceBefore);
CHECK_FIELD(PFM_SPACEAFTER, dySpaceAfter); CHECK_FIELD(PFM_SPACEAFTER, dySpaceAfter);
CHECK_FIELD(PFM_LINESPACING, dyLineSpacing); CHECK_FIELD(PFM_LINESPACING, dyLineSpacing);
@@ -989,7 +957,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; const PARAFORMAT2 *host_fmt;
HRESULT hr; HRESULT hr;

View File

@@ -2519,7 +2519,7 @@ static void SpecialChar (RTF_Info *info)
case rtfSect: case rtfSect:
case rtfPar: case rtfPar:
RTFFlushOutputBuffer(info); RTFFlushOutputBuffer(info);
ME_SetSelectionParaFormat(info->editor, &info->fmt); editor_set_selection_para_fmt( info->editor, &info->fmt );
memset(&info->fmt, 0, sizeof(info->fmt)); memset(&info->fmt, 0, sizeof(info->fmt));
info->fmt.cbSize = sizeof(info->fmt); info->fmt.cbSize = sizeof(info->fmt);
RTFPutUnicodeChar (info, '\r'); RTFPutUnicodeChar (info, '\r');

View File

@@ -0,0 +1,185 @@
/*
* RichEdit - functions and interfaces around CreateTextServices for txtsrv.c
*
* Copyright 2005, 2006, Maarten Lankhorst
*
* RichEdit - ITextHost implementation for windowed richedit controls for txthost.c
*
* Copyright 2009 by Dylan Smith
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* Forward definitions from txtsrv.c to make MSVC compile in ReactOS. */
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSendMessage( ITextServices *iface, UINT msg, WPARAM wparam,
LPARAM lparam, LRESULT *result );
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 );
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetHScroll( ITextServices *iface, LONG *min_pos, LONG *max_pos, LONG *pos,
LONG *page, BOOL *enabled );
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetVScroll( ITextServices *iface, LONG *min_pos, LONG *max_pos, LONG *pos,
LONG *page, BOOL *enabled );
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 );
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);
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInPlaceActivate( ITextServices *iface, const RECT *client );
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInPlaceDeactivate(ITextServices *iface);
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxUIActivate(ITextServices *iface);
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxUIDeactivate(ITextServices *iface);
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetText( ITextServices *iface, BSTR *text );
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSetText( ITextServices *iface, const WCHAR *text );
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetCurTargetX(ITextServices *iface, LONG *x);
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetBaseLinePos(ITextServices *iface, LONG *x);
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 );
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetDropTarget(ITextServices *iface, IDropTarget **ppDropTarget);
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxPropertyBitsChange( ITextServices *iface, DWORD mask, DWORD bits );
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetCachedSize(ITextServices *iface, DWORD *pdwWidth, DWORD *pdwHeight);
/* Forward definitions from txthost.c to make MSVC compile in ReactOS. */
DECLSPEC_HIDDEN HDC __thiscall ITextHostImpl_TxGetDC( ITextHost2 *iface );
DECLSPEC_HIDDEN INT __thiscall ITextHostImpl_TxReleaseDC( ITextHost2 *iface, HDC hdc );
DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxShowScrollBar( ITextHost2 *iface, INT bar, BOOL show );
DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxEnableScrollBar( ITextHost2 *iface, INT bar, INT arrows );
DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetScrollRange( ITextHost2 *iface, INT bar, LONG min_pos, INT max_pos, BOOL redraw );
DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetScrollPos( ITextHost2 *iface, INT bar, INT pos, BOOL redraw );
DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxInvalidateRect( ITextHost2 *iface, const RECT *rect, BOOL mode );
DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxViewChange( ITextHost2 *iface, BOOL update );
DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxCreateCaret( ITextHost2 *iface, HBITMAP bitmap, INT width, INT height );
DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxShowCaret( ITextHost2 *iface, BOOL show );
DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetCaretPos( ITextHost2 *iface, INT x, INT y );
DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetTimer( ITextHost2 *iface, UINT id, UINT timeout );
DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxKillTimer( ITextHost2 *iface, UINT id );
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 );
DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetCapture( ITextHost2 *iface, BOOL capture );
DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetFocus( ITextHost2 *iface );
DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetCursor( ITextHost2 *iface, HCURSOR cursor, BOOL text );
DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxScreenToClient( ITextHost2 *iface, POINT *pt );
DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxClientToScreen( ITextHost2 *iface, POINT *pt );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxActivate( ITextHost2 *iface, LONG *old_state );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxDeactivate( ITextHost2 *iface, LONG new_state );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetClientRect( ITextHost2 *iface, RECT *rect );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetViewInset( ITextHost2 *iface, RECT *rect );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetCharFormat( ITextHost2 *iface, const CHARFORMATW **ppCF );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetParaFormat( ITextHost2 *iface, const PARAFORMAT **fmt );
DECLSPEC_HIDDEN COLORREF __thiscall ITextHostImpl_TxGetSysColor( ITextHost2 *iface, int index );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetBackStyle( ITextHost2 *iface, TXTBACKSTYLE *style );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetMaxLength( ITextHost2 *iface, DWORD *length );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetScrollBars( ITextHost2 *iface, DWORD *scrollbars );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetPasswordChar( ITextHost2 *iface, WCHAR *c );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetAcceleratorPos( ITextHost2 *iface, LONG *pos );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetExtent( ITextHost2 *iface, SIZEL *extent );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_OnTxCharFormatChange( ITextHost2 *iface, const CHARFORMATW *pcf );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_OnTxParaFormatChange( ITextHost2 *iface, const PARAFORMAT *ppf );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetPropertyBits( ITextHost2 *iface, DWORD mask, DWORD *bits );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxNotify( ITextHost2 *iface, DWORD iNotify, void *pv );
DECLSPEC_HIDDEN HIMC __thiscall ITextHostImpl_TxImmGetContext( ITextHost2 *iface );
DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxImmReleaseContext( ITextHost2 *iface, HIMC context );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetSelectionBarWidth( ITextHost2 *iface, LONG *width );
DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxIsDoubleClickPending( ITextHost2 *iface );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetWindow( ITextHost2 *iface, HWND *hwnd );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxSetForegroundWindow( ITextHost2 *iface );
DECLSPEC_HIDDEN HPALETTE __thiscall ITextHostImpl_TxGetPalette( ITextHost2 *iface );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetEastAsianFlags( ITextHost2 *iface, LONG *flags );
DECLSPEC_HIDDEN HCURSOR __thiscall ITextHostImpl_TxSetCursor2( ITextHost2 *iface, HCURSOR cursor, BOOL text );
DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxFreeTextServicesNotification( ITextHost2 *iface );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetEditStyle( ITextHost2 *iface, DWORD item, DWORD *data );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetWindowStyles( ITextHost2 *iface, DWORD *style, DWORD *ex_style );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxShowDropCaret( ITextHost2 *iface, BOOL show, HDC hdc, const RECT *rect );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxDestroyCaret( ITextHost2 *iface );
DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetHorzExtent( ITextHost2 *iface, LONG *horz_extent );

File diff suppressed because it is too large Load Diff

View File

@@ -24,69 +24,132 @@
#include "editor.h" #include "editor.h"
/* I'm sure these functions would simplify some code in caret ops etc, ME_Row *row_next( ME_Row *row )
* I just didn't remember them when I wrote that code
*/
ME_DisplayItem *ME_RowStart(ME_DisplayItem *item) {
return ME_FindItemBackOrHere(item, diStartRow);
}
/*
ME_DisplayItem *ME_RowEnd(ME_DisplayItem *item) {
ME_DisplayItem *item2 = ME_FindItemFwd(item, diStartRowOrParagraphOrEnd);
if (!item2) return NULL;
return ME_FindItemBack(item, diRun);
}
*/
ME_DisplayItem *
ME_FindRowWithNumber(ME_TextEditor *editor, int nRow)
{ {
ME_DisplayItem *item = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph); ME_DisplayItem *item;
int nCount = 0;
while (item->type == diParagraph && item = ME_FindItemFwd( row_get_di( row ), diStartRowOrParagraphOrEnd );
nCount + item->member.para.nRows <= nRow) if (!item || item->type != diStartRow) return NULL;
{ return &item->member.row;
nCount += item->member.para.nRows;
item = item->member.para.next_para;
} }
if (item->type != diParagraph)
return NULL; ME_Row *row_next_all_paras( ME_Row *row )
for (item = ME_FindItemFwd(item, diStartRow); item && nCount < nRow; nCount++) {
item = ME_FindItemFwd(item, diStartRow); ME_DisplayItem *item;
return 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;
}
void row_first_cursor( ME_Row *row, ME_Cursor *cursor )
{
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 int row_number_from_char_ofs( ME_TextEditor *editor, int ofs )
ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs)
{ {
ME_DisplayItem *item = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph); ME_Paragraph *para = editor_first_para( editor );
int nRow = 0; ME_Row *row;
ME_Cursor cursor;
int row_num = 0;
while (item->type == diParagraph && while (para_next( para ) && para_next( para )->nCharOfs <= ofs)
item->member.para.next_para->member.para.nCharOfs <= nOfs)
{ {
nRow += item->member.para.nRows; row_num += para->nRows;
item = item->member.para.next_para; para = para_next( para );
} }
if (item->type == diParagraph)
{
ME_DisplayItem *next_para = item->member.para.next_para;
nOfs -= item->member.para.nCharOfs; if (para_next( para ))
item = ME_FindItemFwd(item, diRun);
while ((item = ME_FindItemFwd(item, diStartRowOrParagraph)) != NULL)
{ {
if (item == next_para) for (row = para_first_row( para ); row; row = row_next( row ))
break; {
item = ME_FindItemFwd(item, diRun); row_end_cursor( row, &cursor, TRUE );
if (item->member.run.nCharOfs > nOfs) if (ME_GetCursorOfs( &cursor ) > ofs ) break;
break; row_num++;
nRow++;
} }
} }
return nRow;
return row_num;
} }

View File

@@ -1035,10 +1035,10 @@ struct RTFTable
int numCellsInserted; int numCellsInserted;
/* v4.1 */ /* 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 * or it may store the end of the previous row if it may still be
* continued, otherwise NULL is stored. */ * continued, otherwise NULL is stored. */
ME_DisplayItem *tableRowStart; ME_Paragraph *row_start;
/* Table definitions are stored as a stack to support nested tables. */ /* Table definitions are stored as a stack to support nested tables. */
RTFTable *parent; RTFTable *parent;

View File

@@ -27,6 +27,100 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
WINE_DECLARE_DEBUG_CHANNEL(richedit_check); WINE_DECLARE_DEBUG_CHANNEL(richedit_check);
WINE_DECLARE_DEBUG_CHANNEL(richedit_lists); 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 * ME_CanJoinRuns
* *
@@ -43,54 +137,32 @@ BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2)
return TRUE; 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 * 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 assert( !para ^ !run );
* paragraph. If we start the shifting from the run, we need to shift
* all the relative offsets until the end of the paragraph if (run)
*/
if (p->type == diRun) /* propagate in all runs in this para */
{ {
TRACE("PropagateCharOffset(%s, %d)\n", debugstr_run( &p->member.run ), shift); para = para_next( run->para );
do { do
p->member.run.nCharOfs += shift; {
assert(p->member.run.nCharOfs >= 0); run->nCharOfs += shift;
p = ME_FindItemFwd(p, diRunOrParagraphOrEnd); run = run_next( run );
} while(p->type == diRun); } while (run);
} }
/* Runs in next paragraphs don't need their offsets updated, because they,
* again, those offsets are relative to their respective paragraphs. do
* Instead of that, we're updating paragraphs' character offsets.
*/
if (p->type == diParagraph) /* propagate in all next paras */
{ {
do { para->nCharOfs += shift;
p->member.para.nCharOfs += shift; para = para_next( para );
assert(p->member.para.nCharOfs >= 0); } while (para);
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);
}
} }
/****************************************************************************** /******************************************************************************
@@ -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. * 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); return run->para->nCharOfs + run->nCharOfs + ofs;
assert(pPara && pPara->type == diParagraph);
return pPara->member.para.nCharOfs + pRun->member.run.nCharOfs + nOfs;
} }
/****************************************************************************** /******************************************************************************
* ME_CursorFromCharOfs * cursor_from_char_ofs
* *
* Converts a character offset (relative to the start of the document) to * 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 * a cursor structure (which contains a run and a position relative to that
* run). * 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, ME_Paragraph *para;
&pCursor->pRun, &pCursor->nOffset); ME_Run *run;
}
/****************************************************************************** char_ofs = min( max( char_ofs, 0 ), ME_GetTextLength( editor ) );
* 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);
nCharOfs = max(nCharOfs, 0);
nCharOfs = min(nCharOfs, len);
/* Find the paragraph at the offset. */ /* Find the paragraph at the offset. */
next_item = editor->pBuffer->pFirst->member.para.next_para; for (para = editor_first_para( editor );
do { para_next( para )->nCharOfs <= char_ofs;
item = next_item; para = para_next( para ))
next_item = item->member.para.next_para; ;
} while (next_item->member.para.nCharOfs <= nCharOfs);
assert(item->type == diParagraph); char_ofs -= para->nCharOfs;
nCharOfs -= item->member.para.nCharOfs;
if (ppPara) *ppPara = item;
/* Find the run at the offset. */ /* Find the run at the offset. */
next_item = ME_FindItemFwd(item, diRun); for (run = para_first_run( para );
do { run_next( run ) && run_next( run )->nCharOfs <= char_ofs;
item = next_item; run = run_next( run ))
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; char_ofs -= run->nCharOfs;
if (pOfs) {
if (((*ppRun)->member.run.nFlags & MERF_ENDPARA) && endOfs > len) cursor->para = para;
*pOfs = (*ppRun)->member.run.len; cursor->run = run;
else *pOfs = nCharOfs; cursor->nOffset = char_ofs;
}
} }
/****************************************************************************** /******************************************************************************
* ME_JoinRuns * run_join
* *
* Merges two adjacent runs, the one given as a parameter and the next one. * 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; int i;
assert(p->type == diRun && pNext->type == diRun);
assert(p->member.run.nCharOfs != -1); assert( run );
mark_para_rewrap(editor, ME_GetParagraph(p)); assert( run->nCharOfs != -1 );
para_mark_rewrap( editor, run->para );
/* Update all cursors so that they don't contain the soon deleted run */ /* Update all cursors so that they don't contain the soon deleted run */
for (i=0; i<editor->nCursors; i++) { for (i = 0; i < editor->nCursors; i++)
if (editor->pCursors[i].pRun == pNext) { {
editor->pCursors[i].pRun = p; if (editor->pCursors[i].run == next)
editor->pCursors[i].nOffset += p->member.run.len; {
editor->pCursors[i].run = run;
editor->pCursors[i].nOffset += run->len;
} }
} }
p->member.run.len += pNext->member.run.len; run->len += next->len;
ME_Remove(pNext); ME_Remove( run_get_di( next ) );
ME_DestroyDisplayItem(pNext); ME_DestroyDisplayItem( run_get_di( next ) );
ME_UpdateRunFlags(editor, &p->member.run); ME_UpdateRunFlags( editor, run );
ME_CheckCharOffsets( editor ); ME_CheckCharOffsets( editor );
} }
/****************************************************************************** /******************************************************************************
* ME_SplitRunSimple * run_split
* *
* Does the most basic job of splitting a run into two - it does not * Does the most basic job of splitting a run into two - it does not
* update the positions and extents. * 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_Run *run = cursor->run, *new_run;
ME_DisplayItem *new_run;
int i; int i;
int nOffset = cursor->nOffset; int nOffset = cursor->nOffset;
assert(!(run->member.run.nFlags & MERF_NONTEXT)); assert( !(run->nFlags & MERF_NONTEXT) );
new_run = ME_MakeRun(run->member.run.style, new_run = run_create( run->style, run->nFlags & MERF_SPLITMASK );
run->member.run.nFlags & MERF_SPLITMASK); new_run->nCharOfs = run->nCharOfs + nOffset;
new_run->member.run.nCharOfs = run->member.run.nCharOfs + nOffset; new_run->len = run->len - nOffset;
new_run->member.run.len = run->member.run.len - nOffset; new_run->para = run->para;
new_run->member.run.para = run->member.run.para; run->len = nOffset;
run->member.run.len = nOffset; cursor->run = new_run;
cursor->pRun = new_run;
cursor->nOffset = 0; cursor->nOffset = 0;
ME_InsertBefore(run->next, new_run); ME_InsertBefore( run_get_di( run )->next, run_get_di( new_run ) );
ME_UpdateRunFlags(editor, &run->member.run); ME_UpdateRunFlags( editor, run );
ME_UpdateRunFlags(editor, &new_run->member.run); ME_UpdateRunFlags( editor, new_run );
for (i = 0; i < editor->nCursors; i++) { for (i = 0; i < editor->nCursors; i++)
if (editor->pCursors[i].pRun == run && {
editor->pCursors[i].nOffset >= nOffset) { if (editor->pCursors[i].run == run &&
editor->pCursors[i].pRun = new_run; editor->pCursors[i].nOffset >= nOffset)
{
editor->pCursors[i].run = new_run;
editor->pCursors[i].nOffset -= nOffset; editor->pCursors[i].nOffset -= nOffset;
} }
} }
mark_para_rewrap(editor, cursor->pPara); para_mark_rewrap( editor, run->para );
return run; return run;
} }
/****************************************************************************** /******************************************************************************
* ME_MakeRun * run_create
* *
* A helper function to create run structures quickly. * 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 ); ME_DisplayItem *item = ME_MakeDI( diRun );
item->member.run.style = s; ME_Run *run = &item->member.run;
item->member.run.reobj = NULL;
item->member.run.nFlags = nFlags; if (!item) return NULL;
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 ); ME_AddRefStyle( s );
return item; 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, * 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 * which is passed as a cursor structure (which consists of a run and
* a run-relative character offset). * a run-relative character offset).
*/ */
ME_DisplayItem * ME_Run *run_insert( ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style,
ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style,
const WCHAR *str, int len, int flags ) 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)
{ {
if (cursor->nOffset == cursor->pRun->member.run.len) if (cursor->nOffset == insert_before->len)
{ {
insert_before = ME_FindItemFwd( cursor->pRun, diRun ); insert_before = run_next_all_paras( insert_before );
if (!insert_before) insert_before = cursor->pRun; /* Always insert before the final eop run */ if (!insert_before) insert_before = cursor->run; /* Always insert before the final eop run */
} }
else else
{ {
ME_SplitRunSimple( editor, cursor ); run_split( editor, cursor );
insert_before = cursor->pRun; insert_before = cursor->run;
} }
} }
add_undo_delete_run( editor, insert_before->member.run.para->nCharOfs + add_undo_delete_run( editor, insert_before->para->nCharOfs + insert_before->nCharOfs, len );
insert_before->member.run.nCharOfs, len );
pDI = ME_MakeRun(style, flags); run = run_create( style, flags );
pDI->member.run.nCharOfs = insert_before->member.run.nCharOfs; run->nCharOfs = insert_before->nCharOfs;
pDI->member.run.len = len; run->len = len;
pDI->member.run.para = insert_before->member.run.para; run->para = insert_before->para;
ME_InsertString( pDI->member.run.para->text, pDI->member.run.nCharOfs, str, len ); ME_InsertString( run->para->text, run->nCharOfs, str, len );
ME_InsertBefore( insert_before, pDI ); ME_InsertBefore( run_get_di( insert_before ), run_get_di( run ) );
TRACE("Shift length:%d\n", len); TRACE("Shift length:%d\n", len);
ME_PropagateCharOffset( insert_before, len ); editor_propagate_char_ofs( NULL, insert_before, len );
mark_para_rewrap(editor, get_di_from_para(insert_before->member.run.para)); 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 */ /* 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) if (prev)
{ {
int i; int i;
for (i = 0; i < editor->nCursors; i++) for (i = 0; i < editor->nCursors; i++)
{ {
if (editor->pCursors[i].pRun == prev && if (editor->pCursors[i].run == prev &&
editor->pCursors[i].nOffset == prev->member.run.len) editor->pCursors[i].nOffset == prev->len)
{ {
editor->pCursors[i].pRun = pDI; editor->pCursors[i].run = run;
editor->pCursors[i].nOffset = len; editor->pCursors[i].nOffset = len;
} }
} }
} }
return pDI; return run;
} }
static BOOL run_is_splittable( const ME_Run *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; 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; str = mask_text->szData;
} }
else else
@@ -522,10 +571,12 @@ int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, B
{ {
ME_Context c; ME_Context c;
int ret; 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 ); ret = ME_CharFromPointContext( &c, cx, run, closest, visual_order );
ME_DestroyContext(&c); ME_DestroyContext(&c);
ITextHost_TxReleaseDC( editor->texthost, hdc );
return ret; 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; if (visual_order && pRun->script_analysis.fRTL) x = pRun->nWidth - x - 1;
return x; 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; str = mask_text->szData;
} }
else else
@@ -599,10 +650,12 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visu
{ {
ME_Context c; ME_Context c;
int ret; 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 ); ret = ME_PointFromCharContext( &c, pRun, nOffset, visual_order );
ME_DestroyContext(&c); ME_DestroyContext(&c);
ITextHost_TxReleaseDC( editor->texthost, hdc );
return ret; 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, SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, int nLen,
int startx, int *pAscent, int *pDescent) int startx, int *pAscent, int *pDescent)
{ {
static const WCHAR spaceW[] = {' ',0};
SIZE size; SIZE size;
nLen = min( nLen, run->len ); 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) if (run->nFlags & MERF_ENDPARA)
{ {
nLen = min( nLen, 1 ); 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) else if (para->nFlags & MEPF_COMPLEX)
{ {
size.cx = run->nWidth; 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_GetTextExtent(c, szMasked->szData, nLen,run->style, &size);
ME_DestroyString(szMasked); ME_DestroyString(szMasked);
} }
@@ -699,7 +751,7 @@ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
{ {
ME_Style *s; ME_Style *s;
if (!editor->pBuffer->pCharStyle) 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); s = ME_ApplyStyle(editor, editor->pBuffer->pCharStyle, pFmt);
ME_ReleaseStyle(editor->pBuffer->pCharStyle); ME_ReleaseStyle(editor->pBuffer->pCharStyle);
editor->pBuffer->pCharStyle = s; 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. * 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; return;
if (start->nOffset == start->pRun->member.run.len) if (start->nOffset == start->run->len)
start_run = ME_FindItemFwd( start->pRun, diRun ); start_run = run_next_all_paras( start->run );
else if (start->nOffset) 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. */ * are selection cursors, but we need to make sure they are valid. */
int split_offset = start->nOffset; int split_offset = start->nOffset;
ME_DisplayItem *split_run = ME_SplitRunSimple(editor, start); ME_Run *split_run = run_split( editor, start );
start_run = start->pRun; start_run = start->run;
if (end && end->pRun == split_run) if (end && end->run == split_run)
{ {
end->pRun = start->pRun; end->run = start->run;
end->nOffset -= split_offset; end->nOffset -= split_offset;
} }
} }
if (end) if (end)
{ {
if (end->nOffset == end->pRun->member.run.len) if (end->nOffset == end->run->len)
end_run = ME_FindItemFwd( end->pRun, diRun ); end_run = run_next_all_paras( end->run );
else else
{ {
if (end->nOffset) ME_SplitRunSimple(editor, end); if (end->nOffset) run_split( editor, end );
end_run = end->pRun; 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_Style *new_style = ME_ApplyStyle( editor, run->style, fmt );
ME_Paragraph *para = run->member.run.para; ME_Paragraph *para = run->para;
add_undo_set_char_fmt( editor, run->member.run.para->nCharOfs + run->member.run.nCharOfs, add_undo_set_char_fmt( editor, para->nCharOfs + run->nCharOfs,
run->member.run.len, &run->member.run.style->fmt ); run->len, &run->style->fmt );
ME_ReleaseStyle(run->member.run.style); ME_ReleaseStyle( run->style );
run->member.run.style = new_style; run->style = new_style;
/* The para numbering style depends on the eop 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); ME_ReleaseStyle(para->para_num.style);
para->para_num.style = NULL; 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 );
} }
/****************************************************************************** /******************************************************************************
@@ -817,32 +869,24 @@ void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
* in the whole character range. * in the whole character range.
*/ */
void ME_GetCharFormat( ME_TextEditor *editor, const ME_Cursor *from, void ME_GetCharFormat( ME_TextEditor *editor, const ME_Cursor *from,
const ME_Cursor *to, CHARFORMAT2W *pFmt) const ME_Cursor *to, CHARFORMAT2W *fmt )
{ {
ME_DisplayItem *run, *run_end; ME_Run *run, *run_end, *prev_run;
CHARFORMAT2W tmp; CHARFORMAT2W tmp;
run = from->pRun; run = from->run;
/* special case - if selection is empty, take previous char's formatting */ /* 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) if (!from->nOffset && (prev_run = run_prev( run ))) run = prev_run;
{ run_copy_char_fmt( run, fmt );
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);
return; return;
} }
run_end = to->pRun; run_end = to->run;
if (!to->nOffset) if (!to->nOffset) run_end = run_prev_all_paras( run_end );
run_end = ME_FindItemBack(run_end, diRun);
ME_GetRunCharFormat(editor, run, pFmt); run_copy_char_fmt( run, fmt );
if (run == run_end) return; 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 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; 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); tmp.cbSize = sizeof(tmp);
ME_GetRunCharFormat(editor, run, &tmp); run_copy_char_fmt( run, &tmp );
assert((tmp.dwMask & dwAttribs) == dwAttribs); assert((tmp.dwMask & dwAttribs) == dwAttribs);
/* reset flags that differ */ /* reset flags that differ */
if (pFmt->yHeight != tmp.yHeight) if (fmt->yHeight != tmp.yHeight) fmt->dwMask &= ~CFM_SIZE;
pFmt->dwMask &= ~CFM_SIZE; if (fmt->dwMask & CFM_FACE)
if (pFmt->dwMask & CFM_FACE)
{ {
if (!(tmp.dwMask & CFM_FACE)) if (!(tmp.dwMask & CFM_FACE))
pFmt->dwMask &= ~CFM_FACE; fmt->dwMask &= ~CFM_FACE;
else if (wcscmp(pFmt->szFaceName, tmp.szFaceName) || else if (wcscmp( fmt->szFaceName, tmp.szFaceName ) ||
pFmt->bPitchAndFamily != tmp.bPitchAndFamily) fmt->bPitchAndFamily != tmp.bPitchAndFamily)
pFmt->dwMask &= ~CFM_FACE; fmt->dwMask &= ~CFM_FACE;
} }
if (pFmt->yHeight != tmp.yHeight) if (fmt->yHeight != tmp.yHeight) fmt->dwMask &= ~CFM_SIZE;
pFmt->dwMask &= ~CFM_SIZE; if (fmt->bUnderlineType != tmp.bUnderlineType) fmt->dwMask &= ~CFM_UNDERLINETYPE;
if (pFmt->bUnderlineType != tmp.bUnderlineType) if (fmt->dwMask & CFM_COLOR)
pFmt->dwMask &= ~CFM_UNDERLINETYPE;
if (pFmt->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) if (fmt->crTextColor != tmp.crTextColor)
pFmt->dwMask &= ~CFM_COLOR; fmt->dwMask &= ~CFM_COLOR;
} }
} }
pFmt->dwMask &= ~((pFmt->dwEffects ^ tmp.dwEffects) & dwEffects); fmt->dwMask &= ~((fmt->dwEffects ^ tmp.dwEffects) & dwEffects);
pFmt->dwEffects = tmp.dwEffects; fmt->dwEffects = tmp.dwEffects;
} while(run != run_end); } while(run != run_end);
} }

View File

@@ -429,7 +429,7 @@ void select_style( ME_Context *c, ME_Style *s )
c->orig_font = NULL; 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 ); release_font_cache( c->current_style->font_cache );
c->current_style->font_cache = NULL; c->current_style->font_cache = NULL;
@@ -473,42 +473,26 @@ void ME_ReleaseStyle(ME_Style *s)
ME_DestroyStyle(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 )
{ {
ME_Style *style;
ME_Cursor *from, *to;
ME_Run *prev;
if (ME_IsSelection( editor )) if (ME_IsSelection( editor ))
{ {
ME_Cursor *from, *to;
ME_GetSelection( editor, &from, &to ); ME_GetSelection( editor, &from, &to );
ME_AddRefStyle(from->pRun->member.run.style); style = from->run->style;
return from->pRun->member.run.style;
}
if (editor->pBuffer->pCharStyle) {
ME_AddRefStyle(editor->pBuffer->pCharStyle);
return editor->pBuffer->pCharStyle;
} }
else if (editor->pBuffer->pCharStyle)
style = editor->pBuffer->pCharStyle;
else if (!cursor->nOffset && (prev = run_prev( cursor->run )))
style = prev->style;
else else
{ style = cursor->run->style;
ME_Cursor *pCursor = &editor->pCursors[nCursor];
ME_DisplayItem *pRunItem = pCursor->pRun; ME_AddRefStyle( style );
ME_DisplayItem *pPrevItem = NULL; return style;
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)
{
ME_AddRefStyle(pPrevItem->member.run.style);
return pPrevItem->member.run.style;
}
else
{
ME_AddRefStyle(pRunItem->member.run.style);
return pRunItem->member.run.style;
}
}
} }
void ME_SaveTempStyle(ME_TextEditor *editor, ME_Style *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 ); ScriptFreeCache( &def->script_cache );
ME_ReleaseStyle( style ); ME_ReleaseStyle( style );
ME_MarkAllForWrapping( editor ); editor_mark_rewrap_all( editor );
} }

View File

@@ -54,449 +54,362 @@
#include "editor.h" #include "editor.h"
#include "rtf.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 )
static const WCHAR cr_lf[] = {'\r', '\n', 0};
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_Style *style = style_get_insert_style( editor, cursor );
ME_DisplayItem *tp; ME_Paragraph *para;
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); if (cursor->nOffset) run_split( editor, cursor );
ME_ReleaseStyle(pStyle);
cursor->pPara = tp; para = para_split( editor, cursor->run, style, eol_str, eol_len, para_flags );
cursor->pRun = ME_FindItemFwd(tp, diRun); ME_ReleaseStyle( style );
return tp; 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; ME_Paragraph *para;
para = ME_InsertEndParaFromCursor(editor, 0, cr_lf, 2, MEPF_ROWSTART);
return para->member.para.prev_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_Paragraph* table_insert_row_start_at_para( ME_TextEditor *editor, ME_Paragraph *para )
ME_DisplayItem *para)
{ {
ME_DisplayItem *prev_para, *end_para; ME_Paragraph *prev_para, *end_para, *start_row;
ME_Cursor savedCursor = editor->pCursors[0]; ME_Cursor cursor;
ME_DisplayItem *startRowPara;
editor->pCursors[0].pPara = para; cursor.para = para;
editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); cursor.run = para_first_run( para );
editor->pCursors[0].nOffset = 0; cursor.nOffset = 0;
editor->pCursors[1] = editor->pCursors[0];
startRowPara = ME_InsertTableRowStartFromCursor(editor); start_row = table_insert_row_start( editor, &cursor );
savedCursor.pPara = ME_GetParagraph(savedCursor.pRun);
editor->pCursors[0] = savedCursor; end_para = para_next( editor->pCursors[0].para );
editor->pCursors[1] = editor->pCursors[0]; prev_para = para_next( start_row );
para = para_next( prev_para );
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) while (para != end_para)
{ {
para->member.para.pCell = prev_para->member.para.pCell; para->cell = para_cell( prev_para );
para->member.para.nFlags |= MEPF_CELL; para->nFlags |= MEPF_CELL;
para->member.para.nFlags &= ~(MEPF_ROWSTART|MEPF_ROWEND); para->nFlags &= ~(MEPF_ROWSTART | MEPF_ROWEND);
para->member.para.fmt.dwMask |= PFM_TABLE|PFM_TABLEROWDELIMITER; para->fmt.dwMask |= PFM_TABLE | PFM_TABLEROWDELIMITER;
para->member.para.fmt.wEffects |= PFE_TABLE; para->fmt.wEffects |= PFE_TABLE;
para->member.para.fmt.wEffects &= ~PFE_TABLEROWDELIMITER; para->fmt.wEffects &= ~PFE_TABLEROWDELIMITER;
prev_para = para; prev_para = para;
para = para->member.para.next_para; para = para_next( para );
} }
return startRowPara; return start_row;
} }
/* Inserts a diCell and starts a new paragraph for the next cell. /* Inserts a diCell and starts a new paragraph for the next cell.
* *
* Returns the first paragraph of the new 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'; WCHAR tab = '\t';
para = ME_InsertEndParaFromCursor(editor, 0, &tab, 1, MEPF_CELL);
return table_insert_end_para( editor, editor->pCursors, &tab, 1, MEPF_CELL );
}
ME_Paragraph* table_insert_row_end( ME_TextEditor *editor, ME_Cursor *cursor )
{
ME_Paragraph *para;
para = table_insert_end_para( editor, cursor, L"\r\n", 2, MEPF_ROWEND );
return para_prev( para );
}
ME_Paragraph* table_row_end( ME_Paragraph *para )
{
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; return para;
} }
ME_DisplayItem* ME_InsertTableRowEndFromCursor(ME_TextEditor *editor) ME_Paragraph* table_row_start( ME_Paragraph *para )
{ {
ME_DisplayItem *para; ME_Cell *cell;
para = ME_InsertEndParaFromCursor(editor, 0, cr_lf, 2, MEPF_ROWEND);
return para->member.para.prev_para;
}
ME_DisplayItem* ME_GetTableRowEnd(ME_DisplayItem *para) if (para->nFlags & MEPF_ROWSTART) return para;
{ if (para->nFlags & MEPF_ROWEND) para = para_prev( para );
ME_DisplayItem *cell; cell = para_cell( para );
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); while (cell_prev( cell ))
assert(para && para->member.para.nFlags & MEPF_ROWEND); cell = cell_prev( cell );
para = &ME_FindItemBack( cell_get_di( cell ), diParagraph )->member.para;
assert( para && para->nFlags & MEPF_ROWSTART );
return para; return para;
} }
ME_DisplayItem* ME_GetTableRowStart(ME_DisplayItem *para) ME_Paragraph* table_outer_para( ME_Paragraph *para )
{ {
ME_DisplayItem *cell; if (para->nFlags & MEPF_ROWEND) para = para_prev( para );
assert(para); while (para_cell( 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);
return para;
}
ME_DisplayItem* ME_GetOuterParagraph(ME_DisplayItem *para)
{ {
if (para->member.para.nFlags & MEPF_ROWEND) para = table_row_start( para );
para = para->member.para.prev_para; if (!para_cell( para )) break;
while (para->member.para.pCell) para = &ME_FindItemBack( cell_get_di( para_cell( para ) ), diParagraph )->member.para;
{
para = ME_GetTableRowStart(para);
if (!para->member.para.pCell)
break;
para = ME_FindItemBack(para->member.para.pCell, diParagraph);
} }
return para; return para;
} }
/* Make a bunch of assertions to make sure tables haven't been corrupted. ME_Cell *table_row_first_cell( ME_Paragraph *para )
*
* 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)
{ {
if(TRACE_ON(richedit_lists)) if (!para_in_table( para )) return NULL;
{
TRACE("---\n"); para = para_next( table_row_start( para ) );
ME_DumpDocument(editor->pBuffer); return para_cell( para );
}
#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
} }
BOOL ME_IsInTable(ME_DisplayItem *pItem) ME_Cell *table_row_end_cell( ME_Paragraph *para )
{ {
PARAFORMAT2 *pFmt; if (!para_in_table( para )) return NULL;
if (!pItem)
return FALSE; para = para_prev( table_row_end( para ));
if (pItem->type == diRun) return cell_next( para_cell( para ) );
pItem = ME_GetParagraph(pItem); }
if (pItem->type != diParagraph)
return FALSE; ME_Cell *cell_create( void )
pFmt = &pItem->member.para.fmt; {
return pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE; ME_DisplayItem *item = ME_MakeDI( diCell );
return &item->member.cell;
}
ME_Cell *cell_next( ME_Cell *cell )
{
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. */ /* 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_Cursor c2 = *c;
ME_DisplayItem *this_para = c->pPara; ME_Paragraph *this_para = c->para, *end_para;
ME_DisplayItem *end_para;
ME_MoveCursorChars(editor, &c2, *nChars, FALSE); ME_MoveCursorChars( editor, &c2, *num_chars, FALSE );
end_para = c2.pPara; end_para = c2.para;
if (c2.pRun->member.run.nFlags & MERF_ENDPARA) { if (c2.run->nFlags & MERF_ENDPARA)
{
/* End offset might be in the middle of the end paragraph run. /* 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 * If this is the case, then we need to use the next paragraph as the last
* paragraphs. * paragraphs.
*/ */
int remaining = nOfs + *nChars - c2.pRun->member.run.nCharOfs int remaining = start_ofs + *num_chars - c2.run->nCharOfs - end_para->nCharOfs;
- end_para->member.para.nCharOfs;
if (remaining) if (remaining)
{ {
assert(remaining < c2.pRun->member.run.len); assert( remaining < c2.run->len );
end_para = end_para->member.para.next_para; end_para = para_next( end_para );
} }
} }
if (!editor->bEmulateVersion10) { /* v4.1 */ 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) if (para_cell( this_para ) != para_cell( end_para ) ||
& (MEPF_ROWSTART|MEPF_ROWEND))) ((this_para->nFlags | end_para->nFlags) & (MEPF_ROWSTART | MEPF_ROWEND)))
{ {
while (this_para != end_para) while (this_para != end_para)
{ {
ME_DisplayItem *next_para = this_para->member.para.next_para; ME_Paragraph *next_para = para_next( this_para );
BOOL bTruancateDeletion = FALSE; BOOL truancate_del = FALSE;
if (this_para->member.para.nFlags & MEPF_ROWSTART) { if (this_para->nFlags & MEPF_ROWSTART)
{
/* The following while loop assumes that next_para is 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. */ * of the row. */
next_para = this_para; next_para = this_para;
this_para = this_para->member.para.prev_para; this_para = para_prev( this_para );
} else if (next_para->member.para.pCell != this_para->member.para.pCell }
|| this_para->member.para.nFlags & MEPF_ROWEND) 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. */ /* Start of the deletion from after the start of the table row. */
bTruancateDeletion = TRUE; truancate_del = TRUE;
} }
while (!bTruancateDeletion && while (!truancate_del && next_para->nFlags & MEPF_ROWSTART)
next_para->member.para.nFlags & MEPF_ROWSTART)
{ {
next_para = ME_GetTableRowEnd(next_para)->member.para.next_para; next_para = para_next( table_row_end( next_para ) );
if (next_para->member.para.nCharOfs > nOfs + *nChars) if (next_para->nCharOfs > start_ofs + *num_chars)
{ {
/* End of deletion is not past the end of the table row. */ /* 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 /* Delete the end paragraph preceding the table row if the
* preceding table row will be empty. */ * preceding table row will be empty. */
if (this_para->member.para.nCharOfs >= nOfs) if (this_para->nCharOfs >= start_ofs) next_para = para_next( next_para );
truancate_del = TRUE;
}
else this_para = para_prev( next_para );
}
if (truancate_del)
{ {
next_para = next_para->member.para.next_para; ME_Run *end_run = para_end_run( para_prev( next_para ) );
} int new_chars = next_para->nCharOfs - start_ofs - end_run->len;
bTruancateDeletion = TRUE; new_chars = max( new_chars, 0 );
} else { assert( new_chars <= *num_chars);
this_para = next_para->member.para.prev_para; *num_chars = new_chars;
}
}
if (bTruancateDeletion)
{
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;
break; break;
} }
this_para = next_para; this_para = next_para;
} }
} }
} else { /* v1.0 - 3.0 */ }
ME_DisplayItem *pRun; else /* v1.0 - 3.0 */
int nCharsToBoundary;
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)
{ {
pRun = c->pRun; ME_Run *run;
int chars_to_boundary;
if ((this_para->nCharOfs != start_ofs || this_para == end_para) && para_in_table( this_para ))
{
run = c->run;
/* Find the next tab or end paragraph to use as a delete boundary */ /* Find the next tab or end paragraph to use as a delete boundary */
while (!(pRun->member.run.nFlags & (MERF_TAB|MERF_ENDPARA))) while (!(run->nFlags & (MERF_TAB | MERF_ENDPARA)))
pRun = ME_FindItemFwd(pRun, diRun); run = run_next( run );
nCharsToBoundary = pRun->member.run.nCharOfs chars_to_boundary = run->nCharOfs - c->run->nCharOfs - c->nOffset;
- c->pRun->member.run.nCharOfs *num_chars = min( *num_chars, chars_to_boundary );
- c->nOffset; }
*nChars = min(*nChars, nCharsToBoundary); else if (para_in_table( end_para ))
} else if (end_para->member.para.fmt.dwMask & PFM_TABLE &&
end_para->member.para.fmt.wEffects & PFE_TABLE)
{ {
/* The deletion starts from before the row, so don't join it with /* The deletion starts from before the row, so don't join it with
* previous non-empty paragraphs. */ * previous non-empty paragraphs. */
ME_DisplayItem *curPara; ME_Paragraph *cur_para;
pRun = NULL; run = NULL;
if (nOfs > this_para->member.para.nCharOfs) { if (start_ofs > this_para->nCharOfs)
pRun = ME_FindItemBack(end_para, diRun);
curPara = end_para->member.para.prev_para;
}
if (!pRun) {
pRun = ME_FindItemFwd(end_para, diRun);
curPara = end_para;
}
if (pRun)
{ {
nCharsToBoundary = curPara->member.para.nCharOfs cur_para = para_prev( end_para );
+ pRun->member.run.nCharOfs run = para_end_run( cur_para );
- nOfs; }
if (nCharsToBoundary >= 0) if (!run)
*nChars = min(*nChars, nCharsToBoundary); {
cur_para = end_para;
run = para_first_run( end_para );
}
if (run)
{
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) if (*num_chars < 0) *num_chars = 0;
*nChars = 0;
} }
} }
ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, ME_Paragraph* table_append_row( ME_TextEditor *editor, ME_Paragraph *table_row )
ME_DisplayItem *table_row)
{ {
WCHAR endl = '\r', tab = '\t'; WCHAR endl = '\r', tab = '\t';
ME_DisplayItem *run; ME_Run *run;
PARAFORMAT2 *pFmt;
int i; int i;
assert(table_row); if (!editor->bEmulateVersion10) /* v4.1 */
assert(table_row->type == diParagraph); {
if (!editor->bEmulateVersion10) { /* v4.1 */ ME_Cell *new_cell, *cell;
ME_DisplayItem *insertedCell, *para, *cell, *prevTableEnd; ME_Paragraph *para, *prev_table_end, *new_row_start;
cell = ME_FindItemFwd(ME_GetTableRowStart(table_row), diCell);
prevTableEnd = ME_GetTableRowEnd(table_row); cell = table_row_first_cell( table_row );
para = prevTableEnd->member.para.next_para; prev_table_end = table_row_end( table_row );
run = ME_FindItemFwd(para, diRun); para = para_next( prev_table_end );
editor->pCursors[0].pPara = para; run = para_first_run( para );
editor->pCursors[0].pRun = run; editor->pCursors[0].para = para;
editor->pCursors[0].run = run;
editor->pCursors[0].nOffset = 0; editor->pCursors[0].nOffset = 0;
editor->pCursors[1] = editor->pCursors[0]; editor->pCursors[1] = editor->pCursors[0];
para = ME_InsertTableRowStartFromCursor(editor); new_row_start = table_insert_row_start( editor, editor->pCursors );
insertedCell = ME_FindItemFwd(para, diCell); new_cell = table_row_first_cell( new_row_start );
/* Copy cell properties */ /* Copy cell properties */
insertedCell->member.cell.nRightBoundary = cell->member.cell.nRightBoundary; new_cell->nRightBoundary = cell->nRightBoundary;
insertedCell->member.cell.border = cell->member.cell.border; new_cell->border = cell->border;
while (cell->member.cell.next_cell) { while (cell_next( cell ))
cell = cell->member.cell.next_cell; {
para = ME_InsertTableCellFromCursor(editor); cell = cell_next( cell );
insertedCell = ME_FindItemBack(para, diCell); para = table_insert_cell( editor, editor->pCursors );
new_cell = para_cell( para );
/* Copy cell properties */ /* Copy cell properties */
insertedCell->member.cell.nRightBoundary = cell->member.cell.nRightBoundary; new_cell->nRightBoundary = cell->nRightBoundary;
insertedCell->member.cell.border = cell->member.cell.border; new_cell->border = cell->border;
}; };
para = ME_InsertTableRowEndFromCursor(editor); para = table_insert_row_end( editor, editor->pCursors );
para->member.para.fmt = prevTableEnd->member.para.fmt; para->fmt = prev_table_end->fmt;
/* return the table row start for the inserted paragraph */ /* return the table row start for the inserted paragraph */
return ME_FindItemFwd(cell, diParagraph)->member.para.next_para; return new_row_start;
} else { /* v1.0 - 3.0 */ }
run = ME_FindItemBack(table_row->member.para.next_para, diRun); else /* v1.0 - 3.0 */
pFmt = &table_row->member.para.fmt; {
assert(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE); run = para_end_run( table_row );
editor->pCursors[0].pPara = table_row; assert( para_in_table( table_row ) );
editor->pCursors[0].pRun = run; editor->pCursors[0].para = table_row;
editor->pCursors[0].run = run;
editor->pCursors[0].nOffset = 0; editor->pCursors[0].nOffset = 0;
editor->pCursors[1] = editor->pCursors[0]; editor->pCursors[1] = editor->pCursors[0];
ME_InsertTextFromCursor(editor, 0, &endl, 1, run->member.run.style); ME_InsertTextFromCursor( editor, 0, &endl, 1, run->style );
run = editor->pCursors[0].pRun; run = editor->pCursors[0].run;
for (i = 0; i < pFmt->cTabCount; i++) { for (i = 0; i < table_row->fmt.cTabCount; i++)
ME_InsertTextFromCursor(editor, 0, &tab, 1, run->member.run.style); ME_InsertTextFromCursor( editor, 0, &tab, 1, run->style );
}
return table_row->member.para.next_para; return para_next( table_row );
} }
} }
/* Selects the next table cell or appends a new table row if at end of table */ /* Selects the next table cell or appends a new table row if at end of table */
static void ME_SelectOrInsertNextCell(ME_TextEditor *editor, static void table_select_next_cell_or_append( ME_TextEditor *editor, ME_Run *run )
ME_DisplayItem *run)
{ {
ME_DisplayItem *para = ME_GetParagraph(run); ME_Paragraph *para = run->para;
ME_Cell *cell;
int i; int i;
assert(run && run->type == diRun); assert( para_in_table( para ) );
assert(ME_IsInTable(run)); if (!editor->bEmulateVersion10) /* v4.1 */
if (!editor->bEmulateVersion10) { /* v4.1 */ {
ME_DisplayItem *cell; /* Get the initial cell */
/* Get the initial cell */ if (para->nFlags & MEPF_ROWSTART) cell = para_cell( para_next( para ) );
if (para->member.para.nFlags & MEPF_ROWSTART) { else if (para->nFlags & MEPF_ROWEND) cell = para_cell( para_prev( para ) );
cell = para->member.para.next_para->member.para.pCell; else cell = para_cell( para );
} else if (para->member.para.nFlags & MEPF_ROWEND) {
cell = para->member.para.prev_para->member.para.pCell; /* Get the next cell. */
} else { if (cell_next( cell ) && cell_next( cell_next( cell ) ))
cell = para->member.para.pCell; cell = cell_next( cell );
} else
assert(cell); {
/* Get the next cell. */ para = para_next( table_row_end( para ) );
if (cell->member.cell.next_cell && if (para->nFlags & MEPF_ROWSTART) cell = para_cell( para_next( para ) );
cell->member.cell.next_cell->member.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 {
/* Insert row */ /* Insert row */
para = para->member.para.prev_para; para = para_prev( para );
para = ME_AppendTableRow(editor, ME_GetTableRowStart(para)); para = table_append_row( editor, table_row_start( para ) );
/* Put cursor at the start of the new table row */ /* Put cursor at the start of the new table row */
para = para->member.para.next_para; para = para_next( para );
editor->pCursors[0].pPara = para; editor->pCursors[0].para = para;
editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].run = para_first_run( para );
editor->pCursors[0].nOffset = 0; editor->pCursors[0].nOffset = 0;
editor->pCursors[1] = editor->pCursors[0]; editor->pCursors[1] = editor->pCursors[0];
ME_WrapMarkedParagraphs(editor); ME_WrapMarkedParagraphs(editor);
@@ -504,62 +417,60 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor,
} }
} }
/* Select cell */ /* Select cell */
editor->pCursors[1].pRun = ME_FindItemFwd(cell, diRun); editor->pCursors[1].para = cell_first_para( cell );
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; editor->pCursors[1].nOffset = 0;
assert(editor->pCursors[0].pRun); editor->pCursors[0].para = cell_end_para( cell );
cell = cell->member.cell.next_cell; editor->pCursors[0].run = para_end_run( editor->pCursors[0].para );
editor->pCursors[0].pRun = ME_FindItemBack(cell, diRun);
editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun);
editor->pCursors[0].nOffset = 0; editor->pCursors[0].nOffset = 0;
assert(editor->pCursors[1].pRun); }
} else { /* v1.0 - 3.0 */ else /* v1.0 - 3.0 */
if (run->member.run.nFlags & MERF_ENDPARA &&
ME_IsInTable(ME_FindItemFwd(run, diParagraphOrEnd)))
{ {
run = ME_FindItemFwd(run, diRun); if (run->nFlags & MERF_ENDPARA && para_in_table( para_next( para ) ))
{
run = run_next_all_paras( run );
assert(run); assert(run);
} }
for (i = 0; i < 2; i++) 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_next( run ))
if (run->type != diRun)
{ {
para = run; para = para_next( run->para );
if (ME_IsInTable(para)) if (para_in_table( para ))
{ {
run = ME_FindItemFwd(para, diRun); run = para_first_run( para );
assert(run); editor->pCursors[0].para = para;
editor->pCursors[0].pPara = para; editor->pCursors[0].run = run;
editor->pCursors[0].pRun = run;
editor->pCursors[0].nOffset = 0; editor->pCursors[0].nOffset = 0;
i = 1; i = 1;
} else { }
else
{
/* Insert table row */ /* 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 */ /* Put cursor at the start of the new table row */
editor->pCursors[0].pPara = para; editor->pCursors[0].para = para;
editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].run = para_first_run( para );
editor->pCursors[0].nOffset = 0; editor->pCursors[0].nOffset = 0;
editor->pCursors[1] = editor->pCursors[0]; editor->pCursors[1] = editor->pCursors[0];
ME_WrapMarkedParagraphs(editor); ME_WrapMarkedParagraphs(editor);
return; return;
} }
} }
else run = run_next( run );
} }
if (i == 0) if (i == 0) run = run_next_all_paras( run );
run = ME_FindItemFwd(run, diRun); editor->pCursors[i].run = run;
editor->pCursors[i].pRun = run; editor->pCursors[i].para = run->para;
editor->pCursors[i].pPara = ME_GetParagraph(run);
editor->pCursors[i].nOffset = 0; 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. */ /* FIXME: Shift tab should move to the previous cell. */
ME_Cursor fromCursor, toCursor; ME_Cursor fromCursor, toCursor;
@@ -572,43 +483,41 @@ void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow)
{ {
fromCursor = editor->pCursors[0]; fromCursor = editor->pCursors[0];
toCursor = editor->pCursors[1]; toCursor = editor->pCursors[1];
} else { }
else
{
fromCursor = editor->pCursors[1]; fromCursor = editor->pCursors[1];
toCursor = editor->pCursors[0]; toCursor = editor->pCursors[0];
} }
} }
if (!editor->bEmulateVersion10) /* v4.1 */ if (!editor->bEmulateVersion10) /* v4.1 */
{ {
if (!ME_IsInTable(toCursor.pRun)) if (!para_in_table( toCursor.para ))
{ {
editor->pCursors[0] = toCursor; editor->pCursors[0] = toCursor;
editor->pCursors[1] = toCursor; editor->pCursors[1] = toCursor;
} else {
ME_SelectOrInsertNextCell(editor, toCursor.pRun);
} }
} else { /* v1.0 - 3.0 */ else table_select_next_cell_or_append( editor, toCursor.run );
if (!ME_IsInTable(fromCursor.pRun)) { }
else /* v1.0 - 3.0 */
{
if (!para_in_table( fromCursor.para ))
{
editor->pCursors[0] = fromCursor; editor->pCursors[0] = fromCursor;
editor->pCursors[1] = fromCursor; editor->pCursors[1] = fromCursor;
/* FIXME: For some reason the caret is shown at the start of the /* 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 * previous paragraph in v1.0 to v3.0 */
* 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);
} }
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); 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 /* Make sure the cursor is not in the hidden table row start paragraph
* without a selection. */ * without a selection. */
void ME_MoveCursorFromTableRowStartParagraph(ME_TextEditor *editor) void table_move_from_row_start( ME_TextEditor *editor )
{
ME_Paragraph *para = editor->pCursors[0].para;
if (para == editor->pCursors[1].para && para->nFlags & MEPF_ROWSTART)
{ {
ME_DisplayItem *para = editor->pCursors[0].pPara;
if (para == editor->pCursors[1].pPara &&
para->member.para.nFlags & MEPF_ROWSTART) {
/* The cursors should not be at the hidden start row paragraph without /* The cursors should not be at the hidden start row paragraph without
* a selection, so the cursor is moved into the first cell. */ * a selection, so the cursor is moved into the first cell. */
para = para->member.para.next_para; para = para_next( para );
editor->pCursors[0].pPara = para; editor->pCursors[0].para = para;
editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].run = para_first_run( para );
editor->pCursors[0].nOffset = 0; editor->pCursors[0].nOffset = 0;
editor->pCursors[1] = editor->pCursors[0]; editor->pCursors[1] = editor->pCursors[0];
} }

File diff suppressed because it is too large Load Diff

View File

@@ -27,77 +27,62 @@
#include "tom.h" #include "tom.h"
#include "imm.h" #include "imm.h"
#include "textserv.h" #include "textserv.h"
#include "wine/asm.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "editstr.h" #include "editstr.h"
#include "riched20.h"
WINE_DEFAULT_DEBUG_CHANNEL(richedit); WINE_DEFAULT_DEBUG_CHANNEL(richedit);
typedef struct ITextServicesImpl { static inline struct text_services *impl_from_IUnknown( IUnknown *iface )
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)
{ {
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) static HRESULT WINAPI ITextServicesImpl_QueryInterface( IUnknown *iface, REFIID iid, void **obj )
{ {
ITextServicesImpl *This = impl_from_IUnknown(iface); struct text_services *services = impl_from_IUnknown( iface );
TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); TRACE( "(%p)->(%s, %p)\n", iface, debugstr_guid( iid ), obj );
if (IsEqualIID(riid, &IID_IUnknown)) if (IsEqualIID( iid, &IID_IUnknown )) *obj = &services->IUnknown_inner;
*ppv = &This->IUnknown_inner; else if (IsEqualIID( iid, &IID_ITextServices )) *obj = &services->ITextServices_iface;
else if (IsEqualIID(riid, &IID_ITextServices)) else if (IsEqualIID( iid, &IID_IRichEditOle )) *obj= &services->IRichEditOle_iface;
*ppv = &This->ITextServices_iface; else if (IsEqualIID( iid, &IID_IDispatch ) ||
else if (IsEqualIID(riid, &IID_IRichEditOle) || IsEqualIID(riid, &IID_ITextDocument) || IsEqualIID( iid, &IID_ITextDocument ) ||
IsEqualIID(riid, &IID_ITextDocument2Old)) { IsEqualIID( iid, &IID_ITextDocument2Old )) *obj = &services->ITextDocument2Old_iface;
if (!This->editor->reOle) else
if (!CreateIRichEditOle(This->outer_unk, This->editor, (void **)(&This->editor->reOle))) {
return E_OUTOFMEMORY; *obj = NULL;
return IUnknown_QueryInterface(This->editor->reOle, riid, ppv); FIXME( "Unknown interface: %s\n", debugstr_guid( iid ) );
} else {
*ppv = NULL;
FIXME("Unknown interface: %s\n", debugstr_guid(riid));
return E_NOINTERFACE; return E_NOINTERFACE;
} }
IUnknown_AddRef((IUnknown*)*ppv); IUnknown_AddRef( (IUnknown *)*obj );
return S_OK; return S_OK;
} }
static ULONG WINAPI ITextServicesImpl_AddRef(IUnknown *iface) static ULONG WINAPI ITextServicesImpl_AddRef(IUnknown *iface)
{ {
ITextServicesImpl *This = impl_from_IUnknown(iface); struct text_services *services = impl_from_IUnknown( iface );
LONG ref = InterlockedIncrement(&This->ref); 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) static ULONG WINAPI ITextServicesImpl_Release(IUnknown *iface)
{ {
ITextServicesImpl *This = impl_from_IUnknown(iface); struct text_services *services = impl_from_IUnknown( iface );
LONG ref = InterlockedDecrement(&This->ref); LONG ref = InterlockedDecrement( &services->ref );
TRACE("(%p) ref=%d\n", This, ref); TRACE( "(%p) ref = %d\n", services, ref );
if (!ref) if (!ref)
{ {
ME_DestroyEditor(This->editor); richole_release_children( services );
This->csTxtSrv.DebugInfo->Spare[0] = 0; ME_DestroyEditor( services->editor );
DeleteCriticalSection(&This->csTxtSrv); CoTaskMemFree( services );
CoTaskMemFree(This);
} }
return ref; return ref;
} }
@@ -109,252 +94,460 @@ static const IUnknownVtbl textservices_inner_vtbl =
ITextServicesImpl_Release 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); struct text_services *services = impl_from_ITextServices( iface );
return IUnknown_QueryInterface(This->outer_unk, riid, ppv); return IUnknown_QueryInterface( services->outer_unk, iid, obj );
} }
static ULONG WINAPI fnTextSrv_AddRef(ITextServices *iface) static ULONG WINAPI fnTextSrv_AddRef(ITextServices *iface)
{ {
ITextServicesImpl *This = impl_from_ITextServices(iface); struct text_services *services = impl_from_ITextServices( iface );
return IUnknown_AddRef(This->outer_unk); return IUnknown_AddRef( services->outer_unk );
} }
static ULONG WINAPI fnTextSrv_Release(ITextServices *iface) static ULONG WINAPI fnTextSrv_Release(ITextServices *iface)
{ {
ITextServicesImpl *This = impl_from_ITextServices(iface); struct text_services *services = impl_from_ITextServices( iface );
return IUnknown_Release(This->outer_unk); return IUnknown_Release( services->outer_unk );
} }
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage,20)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSendMessage( ITextServices *iface, UINT msg, WPARAM wparam, DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSendMessage( ITextServices *iface, UINT msg, WPARAM wparam,
LPARAM lparam, LRESULT *plresult) LPARAM lparam, LRESULT *result )
{ {
ITextServicesImpl *This = impl_from_ITextServices(iface); struct text_services *services = impl_from_ITextServices( iface );
HRESULT hresult; HRESULT hr;
LRESULT lresult; LRESULT res;
lresult = ME_HandleMessage(This->editor, msg, wparam, lparam, TRUE, &hresult); res = editor_handle_message( services->editor, msg, wparam, lparam, &hr );
if (plresult) *plresult = lresult; if (result) *result = res;
return hresult; return hr;
} }
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxDraw(ITextServices *iface, DWORD dwDrawAspect, LONG lindex, static HRESULT update_client_rect( struct text_services *services, const RECT *client )
void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, HDC hdcTargetDev,
LPCRECTL lprcBounds, LPCRECTL lprcWBounds, LPRECT lprcUpdate,
BOOL (CALLBACK * pfnContinue)(DWORD), DWORD dwContinue,
LONG lViewId)
{ {
ITextServicesImpl *This = impl_from_ITextServices(iface); RECT rect;
HRESULT hr;
FIXME("%p: STUB\n", This); if (!client)
return E_NOTIMPL; {
if (!services->editor->in_place_active) return E_INVALIDARG;
hr = ITextHost_TxGetClientRect( services->editor->texthost, &rect );
if (FAILED( hr )) return hr;
} }
else rect = *client;
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetHScroll(ITextServices *iface, LONG *plMin, LONG *plMax, LONG *plPos, rect.left += services->editor->selofs;
LONG *plPage, BOOL *pfEnabled)
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
if (plMin) if (EqualRect( &rect, &services->editor->rcFormat )) return S_FALSE;
*plMin = This->editor->horz_si.nMin; services->editor->rcFormat = rect;
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; return S_OK;
} }
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetVScroll(ITextServices *iface, LONG *plMin, LONG *plMax, LONG *plPos, DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52)
LONG *plPage, BOOL *pfEnabled) 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;
if (plMin) TRACE( "%p: aspect %d, %d, %p, %p, draw %p, target %p, bounds %s, mf_bounds %s, update %s, %p, %d, view %d\n",
*plMin = This->editor->vert_si.nMin; services, aspect, index, aspect_info, td, draw, target, wine_dbgstr_rect( (RECT *)bounds ),
if (plMax) wine_dbgstr_rect( (RECT *)mf_bounds ), wine_dbgstr_rect( update ), continue_fn, continue_param, view_id );
*plMax = This->editor->vert_si.nMax;
if (plPos) if (aspect != DVASPECT_CONTENT || aspect_info || td || target || mf_bounds || continue_fn )
*plPos = This->editor->vert_si.nPos; FIXME( "Many arguments are ignored\n" );
if (plPage)
*plPage = This->editor->vert_si.nPage; hr = update_client_rect( services, (RECT *)bounds );
if (pfEnabled) if (FAILED( hr )) return hr;
*pfEnabled = (This->editor->styleFlags & WS_VSCROLL) != 0; 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; return S_OK;
} }
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxSetCursor(ITextServices *iface, DWORD dwDrawAspect, LONG lindex, DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24)
void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetHScroll( ITextServices *iface, LONG *min_pos, LONG *max_pos, LONG *pos,
HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y) LONG *page, BOOL *enabled )
{ {
ITextServicesImpl *This = impl_from_ITextServices(iface); struct text_services *services = impl_from_ITextServices( iface );
FIXME("%p: STUB\n", This); if (min_pos) *min_pos = services->editor->horz_si.nMin;
return E_NOTIMPL; 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;
} }
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;
}
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 )
{
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" );
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, DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxQueryHitPoint(ITextServices *iface, DWORD dwDrawAspect, LONG lindex,
void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw,
HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y, HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y,
DWORD *pHitResult) DWORD *pHitResult)
{ {
ITextServicesImpl *This = impl_from_ITextServices(iface); struct text_services *services = impl_from_ITextServices( iface );
FIXME("%p: STUB\n", This); FIXME( "%p: STUB\n", services );
return E_NOTIMPL; 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); struct text_services *services = impl_from_ITextServices( iface );
HRESULT hr;
BOOL old_active = services->editor->in_place_active;
FIXME("%p: STUB\n", This); TRACE( "%p: %s\n", services, wine_dbgstr_rect( client ) );
return E_NOTIMPL;
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInplaceDeactivate(ITextServices *iface) services->editor->in_place_active = TRUE;
hr = update_client_rect( services, client );
if (FAILED( hr ))
{ {
ITextServicesImpl *This = impl_from_ITextServices(iface); services->editor->in_place_active = old_active;
return hr;
FIXME("%p: STUB\n", This); }
return E_NOTIMPL; ME_RewrapRepaint( services->editor );
return S_OK;
} }
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInPlaceDeactivate,4)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInPlaceDeactivate(ITextServices *iface)
{
struct text_services *services = impl_from_ITextServices( iface );
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) 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); FIXME( "%p: STUB\n", services );
return E_NOTIMPL; return E_NOTIMPL;
} }
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxUIDeactivate(ITextServices *iface) 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); FIXME( "%p: STUB\n", services );
return E_NOTIMPL; 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); struct text_services *services = impl_from_ITextServices( iface );
int length; int length;
length = ME_GetTextLength(This->editor); length = ME_GetTextLength( services->editor );
if (length) if (length)
{ {
ME_Cursor start; ME_Cursor start;
BSTR bstr; BSTR bstr;
bstr = SysAllocStringByteLen( NULL, length * sizeof(WCHAR) ); bstr = SysAllocStringByteLen( NULL, length * sizeof(WCHAR) );
if (bstr == NULL) if (bstr == NULL) return E_OUTOFMEMORY;
return E_OUTOFMEMORY;
ME_CursorFromCharOfs(This->editor, 0, &start); cursor_from_char_ofs( services->editor, 0, &start );
ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE, FALSE); ME_GetTextW( services->editor, bstr, length, &start, INT_MAX, FALSE, FALSE );
*pbstrText = bstr; *text = bstr;
} else {
*pbstrText = NULL;
} }
else *text = NULL;
return S_OK; 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); struct text_services *services = impl_from_ITextServices( iface );
ME_Cursor cursor; ME_Cursor cursor;
ME_SetCursorToStart(This->editor, &cursor); ME_SetCursorToStart( services->editor, &cursor );
ME_InternalDeleteText(This->editor, &cursor, ME_GetTextLength(This->editor), FALSE); ME_InternalDeleteText( services->editor, &cursor, ME_GetTextLength( services->editor ), FALSE );
if(pszText) if (text) ME_InsertTextFromCursor( services->editor, 0, text, -1, services->editor->pBuffer->pDefaultStyle );
ME_InsertTextFromCursor(This->editor, 0, pszText, -1, This->editor->pBuffer->pDefaultStyle); set_selection_cursors( services->editor, 0, 0);
set_selection_cursors(This->editor, 0, 0); services->editor->nModifyStep = 0;
This->editor->nModifyStep = 0;
OleFlushClipboard(); OleFlushClipboard();
ME_EmptyUndoStack(This->editor); ME_EmptyUndoStack( services->editor );
ME_UpdateRepaint(This->editor, FALSE); ME_UpdateRepaint( services->editor, FALSE );
return S_OK; return S_OK;
} }
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetCurTargetX(ITextServices *iface, LONG *x) 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); FIXME( "%p: STUB\n", services );
return E_NOTIMPL; return E_NOTIMPL;
} }
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetBaseLinePos(ITextServices *iface, LONG *x) 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); FIXME( "%p: STUB\n", services );
return E_NOTIMPL; return E_NOTIMPL;
} }
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetNaturalSize(ITextServices *iface, DWORD dwAspect, HDC hdcDraw, DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36)
HDC hicTargetDev, DVTARGETDEVICE *ptd, DWORD dwMode, DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetNaturalSize( ITextServices *iface, DWORD aspect, HDC draw,
const SIZEL *psizelExtent, LONG *pwidth, LONG *pheight) 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;
FIXME("%p: STUB\n", This); TRACE( "%p: aspect %d, draw %p, target %p, td %p, mode %08x, extent %s, *width %d, *height %d\n", services,
return E_NOTIMPL; 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;
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) 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); FIXME( "%p: STUB\n", services );
return E_NOTIMPL; 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); struct text_services *services = impl_from_ITextServices( iface );
DWORD scrollbars;
HRESULT hr;
BOOL repaint = FALSE;
FIXME("%p: STUB\n", This); TRACE( "%p, mask %08x, bits %08x\n", services, mask, bits );
return E_NOTIMPL;
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) 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); FIXME( "%p: STUB\n", services );
return E_NOTIMPL; return E_NOTIMPL;
} }
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage,20) #ifdef __ASM_USE_THISCALL_WRAPPER
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24) #define STDCALL(func) (void *) __stdcall_ ## func
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll,24) #ifdef _MSC_VER
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor,40) #define DEFINE_STDCALL_WRAPPER(num,func) \
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint,44) __declspec(naked) HRESULT __stdcall_##func(void) \
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceActivate,8) { \
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceDeactivate,4) __asm pop eax \
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4) __asm pop ecx \
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4) __asm push eax \
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8) __asm mov eax, [ecx] \
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8) __asm jmp dword ptr [eax + 4*num] \
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8) }
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8) #else /* _MSC_VER */
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36) #define DEFINE_STDCALL_WRAPPER(num,func) \
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8) extern HRESULT __stdcall_ ## func(void); \
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange,12) __ASM_GLOBAL_FUNC(__stdcall_ ## func, \
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize,12) "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 = static const ITextServicesVtbl textservices_vtbl =
{ {
@@ -367,8 +560,8 @@ static const ITextServicesVtbl textservices_vtbl =
THISCALL(fnTextSrv_TxGetVScroll), THISCALL(fnTextSrv_TxGetVScroll),
THISCALL(fnTextSrv_OnTxSetCursor), THISCALL(fnTextSrv_OnTxSetCursor),
THISCALL(fnTextSrv_TxQueryHitPoint), THISCALL(fnTextSrv_TxQueryHitPoint),
THISCALL(fnTextSrv_OnTxInplaceActivate), THISCALL(fnTextSrv_OnTxInPlaceActivate),
THISCALL(fnTextSrv_OnTxInplaceDeactivate), THISCALL(fnTextSrv_OnTxInPlaceDeactivate),
THISCALL(fnTextSrv_OnTxUIActivate), THISCALL(fnTextSrv_OnTxUIActivate),
THISCALL(fnTextSrv_OnTxUIDeactivate), THISCALL(fnTextSrv_OnTxUIDeactivate),
THISCALL(fnTextSrv_TxGetText), THISCALL(fnTextSrv_TxGetText),
@@ -381,34 +574,38 @@ static const ITextServicesVtbl textservices_vtbl =
THISCALL(fnTextSrv_TxGetCachedSize) 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) * CreateTextServices (RICHED20.4)
*/ */
HRESULT WINAPI CreateTextServices(IUnknown *pUnkOuter, ITextHost *pITextHost, IUnknown **ppUnk) HRESULT WINAPI CreateTextServices( IUnknown *outer, ITextHost *text_host, IUnknown **unk )
{ {
ITextServicesImpl *ITextImpl; return create_text_services( outer, text_host, unk, FALSE );
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;
} }

View File

@@ -335,19 +335,17 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, struct undo_item *undo)
case undo_set_para_fmt: case undo_set_para_fmt:
{ {
ME_Cursor tmp; ME_Cursor tmp;
ME_DisplayItem *para; cursor_from_char_ofs( editor, undo->u.set_para_fmt.pos, &tmp );
ME_CursorFromCharOfs(editor, undo->u.set_para_fmt.pos, &tmp); add_undo_set_para_fmt( editor, tmp.para );
para = ME_FindItemBack(tmp.pRun, diParagraph); tmp.para->fmt = undo->u.set_para_fmt.fmt;
add_undo_set_para_fmt( editor, &para->member.para ); tmp.para->border = undo->u.set_para_fmt.border;
para->member.para.fmt = undo->u.set_para_fmt.fmt; para_mark_rewrap( editor, tmp.para );
para->member.para.border = undo->u.set_para_fmt.border;
mark_para_rewrap(editor, para);
break; break;
} }
case undo_set_char_fmt: case undo_set_char_fmt:
{ {
ME_Cursor start, end; 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; end = start;
ME_MoveCursorChars(editor, &end, undo->u.set_char_fmt.len, FALSE); ME_MoveCursorChars(editor, &end, undo->u.set_char_fmt.len, FALSE);
ME_SetCharFormat(editor, &start, &end, &undo->u.set_char_fmt.fmt); 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: case undo_insert_run:
{ {
ME_Cursor tmp; ME_Cursor tmp;
ME_CursorFromCharOfs(editor, undo->u.insert_run.pos, &tmp); cursor_from_char_ofs( editor, undo->u.insert_run.pos, &tmp );
ME_InsertRunAtCursor(editor, &tmp, undo->u.insert_run.style, run_insert( editor, &tmp, undo->u.insert_run.style,
undo->u.insert_run.str, undo->u.insert_run.str, undo->u.insert_run.len,
undo->u.insert_run.len,
undo->u.insert_run.flags ); undo->u.insert_run.flags );
break; break;
} }
case undo_delete_run: case undo_delete_run:
{ {
ME_Cursor tmp; 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); ME_InternalDeleteText(editor, &tmp, undo->u.delete_run.len, TRUE);
break; break;
} }
case undo_join_paras: case undo_join_paras:
{ {
ME_Cursor tmp; ME_Cursor tmp;
ME_CursorFromCharOfs(editor, undo->u.join_paras.pos, &tmp); cursor_from_char_ofs( editor, undo->u.join_paras.pos, &tmp );
ME_JoinParagraphs(editor, tmp.pPara, TRUE); para_join( editor, tmp.para, TRUE );
break; break;
} }
case undo_split_para: case undo_split_para:
{ {
ME_Cursor tmp; ME_Cursor tmp;
ME_DisplayItem *this_para, *new_para; ME_Paragraph *this_para, *new_para;
BOOL bFixRowStart; BOOL bFixRowStart;
int paraFlags = undo->u.split_para.flags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND); 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) cursor_from_char_ofs( editor, undo->u.split_para.pos, &tmp );
ME_SplitRunSimple(editor, &tmp); if (tmp.nOffset) run_split( editor, &tmp );
this_para = tmp.pPara; this_para = tmp.para;
bFixRowStart = this_para->member.para.nFlags & MEPF_ROWSTART; bFixRowStart = this_para->nFlags & MEPF_ROWSTART;
if (bFixRowStart) if (bFixRowStart)
{ {
/* Re-insert the paragraph before the table, making sure the nFlag value /* Re-insert the paragraph before the table, making sure the nFlag value
* is correct. */ * 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, 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 ); undo->u.split_para.eol_str->szData, undo->u.split_para.eol_str->nLen, paraFlags );
if (bFixRowStart) if (bFixRowStart)
new_para->member.para.nFlags |= MEPF_ROWSTART; new_para->nFlags |= MEPF_ROWSTART;
new_para->member.para.fmt = undo->u.split_para.fmt; new_para->fmt = undo->u.split_para.fmt;
new_para->member.para.border = undo->u.split_para.border; new_para->border = undo->u.split_para.border;
if (paraFlags) if (paraFlags)
{ {
ME_DisplayItem *pCell = new_para->member.para.pCell; para_cell( new_para )->nRightBoundary = undo->u.split_para.cell_right_boundary;
pCell->member.cell.nRightBoundary = undo->u.split_para.cell_right_boundary; para_cell( new_para )->border = undo->u.split_para.cell_border;
pCell->member.cell.border = undo->u.split_para.cell_border;
} }
break; break;
} }
@@ -441,9 +437,8 @@ BOOL ME_Undo(ME_TextEditor *editor)
destroy_undo_item( undo ); destroy_undo_item( undo );
} }
ME_MoveCursorFromTableRowStartParagraph(editor); table_move_from_row_start( editor );
add_undo( editor, undo_end_transaction ); add_undo( editor, undo_end_transaction );
ME_CheckTablesForCorruption(editor);
editor->nUndoStackSize--; editor->nUndoStackSize--;
editor->nUndoMode = nMode; editor->nUndoMode = nMode;
ME_UpdateRepaint(editor, FALSE); ME_UpdateRepaint(editor, FALSE);
@@ -478,9 +473,8 @@ BOOL ME_Redo(ME_TextEditor *editor)
list_remove( &undo->entry ); list_remove( &undo->entry );
destroy_undo_item( undo ); destroy_undo_item( undo );
} }
ME_MoveCursorFromTableRowStartParagraph(editor); table_move_from_row_start( editor );
add_undo( editor, undo_end_transaction ); add_undo( editor, undo_end_transaction );
ME_CheckTablesForCorruption(editor);
editor->nUndoMode = nMode; editor->nUndoMode = nMode;
ME_UpdateRepaint(editor, FALSE); ME_UpdateRepaint(editor, FALSE);
return TRUE; return TRUE;

File diff suppressed because it is too large Load Diff

View File

@@ -311,50 +311,46 @@ static BOOL find_color_in_colortbl( ME_OutStream *stream, COLORREF color, unsign
return i < stream->nFontTblLen; return i < stream->nFontTblLen;
} }
static BOOL static BOOL stream_out_font_and_colour_tbls( ME_OutStream *pStream, ME_Run *first, ME_Run *last )
ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun,
ME_DisplayItem *pLastRun)
{ {
ME_DisplayItem *item = pFirstRun; ME_Run *run = first;
ME_FontTableItem *table = pStream->fonttbl; ME_FontTableItem *table = pStream->fonttbl;
unsigned int i; unsigned int i;
ME_DisplayItem *pCell = NULL; ME_Cell *cell = NULL;
ME_Paragraph *prev_para = NULL; ME_Paragraph *prev_para = NULL;
do { do
CHARFORMAT2W *fmt = &item->member.run.style->fmt; {
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)) if (fmt->dwMask & CFM_COLOR && !(fmt->dwEffects & CFE_AUTOCOLOR))
add_color_to_colortbl( pStream, fmt->crTextColor ); add_color_to_colortbl( pStream, fmt->crTextColor );
if (fmt->dwMask & CFM_BACKCOLOR && !(fmt->dwEffects & CFE_AUTOBACKCOLOR)) if (fmt->dwMask & CFM_BACKCOLOR && !(fmt->dwEffects & CFE_AUTOBACKCOLOR))
add_color_to_colortbl( pStream, fmt->crBackColor ); 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 */ /* check for any para numbering text */
if (item->member.run.para->fmt.wNumbering) if (run->para->fmt.wNumbering)
add_font_to_fonttbl( pStream, item->member.run.para->para_num.style ); 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, ME_Border* borders[4] = { &cell->border.top, &cell->border.left,
&pCell->member.cell.border.left, &cell->border.bottom, &cell->border.right };
&pCell->member.cell.border.bottom,
&pCell->member.cell.border.right };
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
if (borders[i]->width > 0) if (borders[i]->width > 0)
add_color_to_colortbl( pStream, borders[i]->colorRef ); add_color_to_colortbl( pStream, borders[i]->colorRef );
} }
prev_para = item->member.run.para; prev_para = run->para;
} }
if (item == pLastRun) if (run == last) break;
break; run = run_next_all_paras( run );
item = ME_FindItemFwd(item, diRun); } while (run);
} while (item);
if (!ME_StreamOutPrint(pStream, "{\\fonttbl")) if (!ME_StreamOutPrint(pStream, "{\\fonttbl"))
return FALSE; return FALSE;
@@ -388,31 +384,29 @@ ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun,
return TRUE; return TRUE;
} }
static BOOL static BOOL stream_out_table_props( ME_TextEditor *editor, ME_OutStream *pStream,
ME_StreamOutRTFTableProps(ME_TextEditor *editor, ME_OutStream *pStream, ME_Paragraph *para )
ME_DisplayItem *para)
{ {
ME_DisplayItem *cell; ME_Cell *cell;
char props[STREAMOUT_BUFFER_SIZE] = ""; char props[STREAMOUT_BUFFER_SIZE] = "";
int i; int i;
const char sideChar[4] = {'t','l','b','r'}; const char sideChar[4] = {'t','l','b','r'};
if (!ME_StreamOutPrint(pStream, "\\trowd")) if (!ME_StreamOutPrint(pStream, "\\trowd"))
return FALSE; return FALSE;
if (!editor->bEmulateVersion10) { /* v4.1 */ if (!editor->bEmulateVersion10) /* v4.1 */
PARAFORMAT2 *pFmt = &ME_GetTableRowEnd(para)->member.para.fmt; {
para = ME_GetTableRowStart(para); PARAFORMAT2 *pFmt = &table_row_end( para )->fmt;
cell = para->member.para.next_para->member.para.pCell; cell = table_row_first_cell( para );
assert( cell ); assert( cell );
if (pFmt->dxOffset) if (pFmt->dxOffset)
sprintf(props + strlen(props), "\\trgaph%d", pFmt->dxOffset); sprintf(props + strlen(props), "\\trgaph%d", pFmt->dxOffset);
if (pFmt->dxStartIndent) if (pFmt->dxStartIndent)
sprintf(props + strlen(props), "\\trleft%d", pFmt->dxStartIndent); sprintf(props + strlen(props), "\\trleft%d", pFmt->dxStartIndent);
do { do
ME_Border* borders[4] = { &cell->member.cell.border.top, {
&cell->member.cell.border.left, ME_Border* borders[4] = { &cell->border.top, &cell->border.left,
&cell->member.cell.border.bottom, &cell->border.bottom, &cell->border.right };
&cell->member.cell.border.right };
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
if (borders[i]->width) 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), "\\brdrcf%u", idx);
} }
} }
sprintf(props + strlen(props), "\\cellx%d", cell->member.cell.nRightBoundary); sprintf( props + strlen(props), "\\cellx%d", cell->nRightBoundary );
cell = cell->member.cell.next_cell; cell = cell_next( cell );
} while (cell->member.cell.next_cell); } while (cell_next( cell ));
} else { /* v1.0 - 3.0 */ }
const ME_Border* borders[4] = { &para->member.para.border.top, else /* v1.0 - 3.0 */
&para->member.para.border.left, {
&para->member.para.border.bottom, const ME_Border* borders[4] = { &para->border.top,
&para->member.para.border.right }; &para->border.left,
PARAFORMAT2 *pFmt = &para->member.para.fmt; &para->border.bottom,
&para->border.right };
PARAFORMAT2 *pFmt = &para->fmt;
assert(!(para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL))); assert( !(para->nFlags & (MEPF_ROWSTART | MEPF_ROWEND | MEPF_CELL)) );
if (pFmt->dxOffset) if (pFmt->dxOffset)
sprintf(props + strlen(props), "\\trgaph%d", pFmt->dxOffset); sprintf(props + strlen(props), "\\trgaph%d", pFmt->dxOffset);
if (pFmt->dxStartIndent) if (pFmt->dxStartIndent)
@@ -535,54 +531,46 @@ static BOOL stream_out_para_num( ME_OutStream *stream, ME_Paragraph *para, BOOL
return TRUE; return TRUE;
} }
static BOOL static BOOL stream_out_para_props( ME_TextEditor *editor, ME_OutStream *pStream,
ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream, ME_Paragraph *para )
ME_DisplayItem *para)
{ {
PARAFORMAT2 *fmt = &para->member.para.fmt; PARAFORMAT2 *fmt = &para->fmt;
char props[STREAMOUT_BUFFER_SIZE] = ""; char props[STREAMOUT_BUFFER_SIZE] = "";
int i; int i;
ME_Paragraph *prev_para = NULL; ME_Paragraph *prev_para = para_prev( para );
if (para->member.para.prev_para->type == diParagraph) if (!editor->bEmulateVersion10) /* v4.1 */
prev_para = &para->member.para.prev_para->member.para;
if (!editor->bEmulateVersion10) { /* v4.1 */
if (para->member.para.nFlags & MEPF_ROWSTART) {
pStream->nNestingLevel++;
if (pStream->nNestingLevel == 1) {
if (!ME_StreamOutRTFTableProps(editor, pStream, para))
return FALSE;
}
return TRUE;
} else if (para->member.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;
}
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)) if (para->nFlags & MEPF_ROWSTART)
return FALSE; {
pStream->nNestingLevel++;
if (pStream->nNestingLevel == 1)
if (!stream_out_table_props( editor, pStream, para )) return FALSE;
return TRUE;
} }
else if (para->nFlags & MEPF_ROWEND)
{
pStream->nNestingLevel--;
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->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 (prev_para && !memcmp( fmt, &prev_para->fmt, sizeof(*fmt) ))
{ {
if (fmt->wNumbering) if (fmt->wNumbering)
return stream_out_para_num( pStream, &para->member.para, FALSE ); return stream_out_para_num( pStream, para, FALSE );
return TRUE; return TRUE;
} }
@@ -590,14 +578,15 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream,
return FALSE; return FALSE;
if (fmt->wNumbering) if (fmt->wNumbering)
if (!stream_out_para_num( pStream, &para->member.para, TRUE )) return FALSE; if (!stream_out_para_num( pStream, para, TRUE )) return FALSE;
if (!editor->bEmulateVersion10) { /* v4.1 */ if (!editor->bEmulateVersion10) /* v4.1 */
if (pStream->nNestingLevel > 0) {
strcat(props, "\\intbl"); if (pStream->nNestingLevel > 0) strcat(props, "\\intbl");
if (pStream->nNestingLevel > 1) if (pStream->nNestingLevel > 1) sprintf(props + strlen(props), "\\itap%d", pStream->nNestingLevel);
sprintf(props + strlen(props), "\\itap%d", pStream->nNestingLevel); }
} else { /* v1.0 - 3.0 */ else /* v1.0 - 3.0 */
{
if (fmt->dwMask & PFM_TABLE && fmt->wEffects & PFE_TABLE) if (fmt->dwMask & PFM_TABLE && fmt->wEffects & PFE_TABLE)
strcat(props, "\\intbl"); strcat(props, "\\intbl");
} }
@@ -607,8 +596,10 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream,
* set very different from the documentation. * set very different from the documentation.
* (Tested with RichEdit 5.50.25.0601) */ * (Tested with RichEdit 5.50.25.0601) */
if (fmt->dwMask & PFM_ALIGNMENT) { if (fmt->dwMask & PFM_ALIGNMENT)
switch (fmt->wAlignment) { {
switch (fmt->wAlignment)
{
case PFA_LEFT: case PFA_LEFT:
/* Default alignment: not emitted */ /* Default alignment: not emitted */
break; 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 /* FIXME: MSDN says that the bLineSpacingRule field is controlled by the
* PFM_SPACEAFTER flag. Is that true? I don't believe so. */ * PFM_SPACEAFTER flag. Is that true? I don't believe so. */
switch (fmt->bLineSpacingRule) { switch (fmt->bLineSpacingRule)
{
case 0: /* Single spacing */ case 0: /* Single spacing */
strcat(props, "\\sl-240\\slmult1"); strcat(props, "\\sl-240\\slmult1");
break; break;
@@ -678,8 +671,10 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream,
if (fmt->dwMask & PFM_TABSTOPS) { if (fmt->dwMask & PFM_TABSTOPS) {
static const char * const leader[6] = { "", "\\tldot", "\\tlhyph", "\\tlul", "\\tlth", "\\tleq" }; static const char * const leader[6] = { "", "\\tldot", "\\tlhyph", "\\tlul", "\\tlth", "\\tleq" };
for (i = 0; i < fmt->cTabCount; i++) { for (i = 0; i < fmt->cTabCount; i++)
switch ((fmt->rgxTabs[i] >> 24) & 0xF) { {
switch ((fmt->rgxTabs[i] >> 24) & 0xf)
{
case 1: case 1:
strcat(props, "\\tqc"); strcat(props, "\\tqc");
break; break;
@@ -706,7 +701,8 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream,
if (fmt->sStyle != -1) if (fmt->sStyle != -1)
sprintf(props + strlen(props), "\\s%d", fmt->sStyle); 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", static const char * const style[16] = { "", "\\bgdkhoriz", "\\bgdkvert", "\\bgdkfdiag",
"\\bgdkbdiag", "\\bgdkcross", "\\bgdkdcross", "\\bgdkbdiag", "\\bgdkcross", "\\bgdkdcross",
"\\bghoriz", "\\bgvert", "\\bgfdiag", "\\bghoriz", "\\bgvert", "\\bgfdiag",
@@ -943,11 +939,13 @@ static BOOL stream_out_graphics( ME_TextEditor *editor, ME_OutStream *stream,
UINT size; UINT size;
SIZE goal, pic; SIZE goal, pic;
ME_Context c; ME_Context c;
HDC hdc;
hr = IOleObject_QueryInterface( run->reobj->obj.poleobj, &IID_IDataObject, (void **)&data ); hr = IOleObject_QueryInterface( run->reobj->obj.poleobj, &IID_IDataObject, (void **)&data );
if (FAILED(hr)) return FALSE; 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 ); hr = IDataObject_QueryGetData( data, &fmt );
if (hr != S_OK) goto done; if (hr != S_OK) goto done;
@@ -989,6 +987,7 @@ static BOOL stream_out_graphics( ME_TextEditor *editor, ME_OutStream *stream,
done: done:
ME_DestroyContext( &c ); ME_DestroyContext( &c );
ITextHost_TxReleaseDC( editor->texthost, hdc );
HeapFree( GetProcessHeap(), 0, emf_bits ); HeapFree( GetProcessHeap(), 0, emf_bits );
ReleaseStgMedium( &med ); ReleaseStgMedium( &med );
IDataObject_Release( data ); 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) const ME_Cursor *start, int nChars, int dwFormat)
{ {
ME_Cursor cursor = *start; ME_Cursor cursor = *start;
ME_DisplayItem *prev_para = NULL; ME_Paragraph *prev_para = NULL;
ME_Cursor endCur = cursor; ME_Cursor endCur = cursor;
ME_MoveCursorChars(editor, &endCur, nChars, TRUE); 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)) if (!ME_StreamOutRTFHeader(pStream, dwFormat))
return FALSE; return FALSE;
if (!ME_StreamOutRTFFontAndColorTbl(pStream, cursor.pRun, endCur.pRun)) if (!stream_out_font_and_colour_tbls( pStream, cursor.run, endCur.run ))
return FALSE; return FALSE;
/* TODO: stylesheet table */ /* TODO: stylesheet table */
@@ -1023,77 +1022,95 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream,
/* TODO: section formatting properties */ /* TODO: section formatting properties */
do { do
if (cursor.pPara != prev_para)
{ {
prev_para = cursor.pPara; if (cursor.para != prev_para)
if (!ME_StreamOutRTFParaProps(editor, pStream, cursor.pPara)) {
prev_para = cursor.para;
if (!stream_out_para_props( editor, pStream, cursor.para ))
return FALSE; return FALSE;
} }
if (cursor.pRun == endCur.pRun && !endCur.nOffset) if (cursor.run == endCur.run && !endCur.nOffset)
break; break;
TRACE("flags %xh\n", cursor.pRun->member.run.nFlags);
TRACE("flags %xh\n", cursor.run->nFlags);
/* TODO: emit embedded objects */ /* TODO: emit embedded objects */
if (cursor.pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) if (cursor.para->nFlags & (MEPF_ROWSTART | MEPF_ROWEND))
continue; continue;
if (cursor.pRun->member.run.nFlags & MERF_GRAPHICS) { if (cursor.run->nFlags & MERF_GRAPHICS)
if (!stream_out_graphics(editor, pStream, &cursor.pRun->member.run)) {
if (!stream_out_graphics( editor, pStream, cursor.run ))
return FALSE; 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 */ if (editor->bEmulateVersion10 && /* v1.0 - 3.0 */
cursor.pPara->member.para.fmt.dwMask & PFM_TABLE && para_in_table( cursor.para ))
cursor.pPara->member.para.fmt.wEffects & PFE_TABLE)
{ {
if (!ME_StreamOutPrint(pStream, "\\cell ")) if (!ME_StreamOutPrint(pStream, "\\cell "))
return FALSE; return FALSE;
} else { }
else
{
if (!ME_StreamOutPrint(pStream, "\\tab ")) if (!ME_StreamOutPrint(pStream, "\\tab "))
return FALSE; 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 ")) if (!ME_StreamOutPrint(pStream, "\\nestcell "))
return FALSE; return FALSE;
} else { }
else
{
if (!ME_StreamOutPrint(pStream, "\\cell ")) if (!ME_StreamOutPrint(pStream, "\\cell "))
return FALSE; return FALSE;
} }
nChars--; 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; return FALSE;
if (cursor.pPara->member.para.fmt.dwMask & PFM_TABLE && if (para_in_table( cursor.para ) &&
cursor.pPara->member.para.fmt.wEffects & PFE_TABLE && !(cursor.para->nFlags & (MEPF_ROWSTART | MEPF_ROWEND | MEPF_CELL)))
!(cursor.pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL)))
{ {
if (!ME_StreamOutPrint(pStream, "\\row\r\n")) if (!ME_StreamOutPrint(pStream, "\\row\r\n"))
return FALSE; return FALSE;
} else { }
else
{
if (!ME_StreamOutPrint(pStream, "\\par\r\n")) if (!ME_StreamOutPrint(pStream, "\\par\r\n"))
return FALSE; return FALSE;
} }
/* Skip as many characters as required by current line break */ /* Skip as many characters as required by current line break */
nChars = max(0, nChars - cursor.pRun->member.run.len); nChars = max(0, nChars - cursor.run->len);
} else if (cursor.pRun->member.run.nFlags & MERF_ENDROW) { }
else if (cursor.run->nFlags & MERF_ENDROW)
{
if (!ME_StreamOutPrint(pStream, "\\line\r\n")) if (!ME_StreamOutPrint(pStream, "\\line\r\n"))
return FALSE; return FALSE;
nChars--; nChars--;
} else { }
else
{
int nEnd; int nEnd;
TRACE("style %p\n", cursor.pRun->member.run.style); TRACE("style %p\n", cursor.run->style);
if (!ME_StreamOutRTFCharProps(pStream, &cursor.pRun->member.run.style->fmt)) if (!ME_StreamOutRTFCharProps( pStream, &cursor.run->style->fmt ))
return FALSE; return FALSE;
nEnd = (cursor.pRun == endCur.pRun) ? endCur.nOffset : cursor.pRun->member.run.len; nEnd = (cursor.run == endCur.run) ? endCur.nOffset : cursor.run->len;
if (!ME_StreamOutRTFText(pStream, get_text( &cursor.pRun->member.run, cursor.nOffset ), if (!ME_StreamOutRTFText(pStream, get_text( cursor.run, cursor.nOffset ),
nEnd - cursor.nOffset)) nEnd - cursor.nOffset))
return FALSE; return FALSE;
cursor.nOffset = 0; 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)) if (!ME_StreamOutMove(pStream, "}\0", 2))
return FALSE; return FALSE;
@@ -1111,7 +1128,7 @@ static BOOL ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream,
int nBufLen = 0; int nBufLen = 0;
BOOL success = TRUE; BOOL success = TRUE;
if (!cursor.pRun) if (!cursor.run)
return FALSE; return FALSE;
if (dwFormat & SF_USECODEPAGE) if (dwFormat & SF_USECODEPAGE)
@@ -1119,32 +1136,31 @@ static BOOL ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream,
/* TODO: Handle SF_TEXTIZED */ /* TODO: Handle SF_TEXTIZED */
while (success && nChars && cursor.pRun) { while (success && nChars && cursor.run)
nLen = min(nChars, cursor.pRun->member.run.len - cursor.nOffset);
if (!editor->bEmulateVersion10 && cursor.pRun->member.run.nFlags & MERF_ENDPARA)
{ {
static const WCHAR szEOL[] = { '\r', '\n' }; nLen = min(nChars, cursor.run->len - cursor.nOffset);
if (!editor->bEmulateVersion10 && cursor.run->nFlags & MERF_ENDPARA)
{
/* richedit 2.0 - all line breaks are \r\n */ /* richedit 2.0 - all line breaks are \r\n */
if (dwFormat & SF_UNICODE) 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 else
success = ME_StreamOutMove(pStream, "\r\n", 2); success = ME_StreamOutMove(pStream, "\r\n", 2);
} else { } else {
if (dwFormat & SF_UNICODE) 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); sizeof(WCHAR) * nLen);
else { else {
int nSize; 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); nLen, NULL, 0, NULL, NULL);
if (nSize > nBufLen) { if (nSize > nBufLen) {
buffer = heap_realloc(buffer, nSize); buffer = heap_realloc(buffer, nSize);
nBufLen = 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); nLen, buffer, nSize, NULL, NULL);
success = ME_StreamOutMove(pStream, buffer, nSize); success = ME_StreamOutMove(pStream, buffer, nSize);
} }
@@ -1152,7 +1168,7 @@ static BOOL ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream,
nChars -= nLen; nChars -= nLen;
cursor.nOffset = 0; cursor.nOffset = 0;
cursor.pRun = ME_FindItemFwd(cursor.pRun, diRun); cursor.run = run_next_all_paras( cursor.run );
} }
heap_free(buffer); heap_free(buffer);

View File

@@ -168,7 +168,7 @@ dll/win32/query # Synced to WineStaging-4.18
dll/win32/rasapi32 # Synced to WineStaging-3.3 dll/win32/rasapi32 # Synced to WineStaging-3.3
dll/win32/regapi # Synced to WineStaging-5.7 dll/win32/regapi # Synced to WineStaging-5.7
dll/win32/resutils # Synced to WineStaging-3.3 dll/win32/resutils # Synced to WineStaging-3.3
dll/win32/riched20 # Synced to WineStaging-4.18 dll/win32/riched20 # Synced to Wine-6.10
dll/win32/riched32 # Synced to WineStaging-3.3 dll/win32/riched32 # Synced to WineStaging-3.3
dll/win32/rpcrt4 # Synced to WineStaging-4.18 dll/win32/rpcrt4 # Synced to WineStaging-4.18
dll/win32/rsabase # Synced to WineStaging-3.3 dll/win32/rsabase # Synced to WineStaging-3.3