[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__)
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
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;
WCHAR *data;
HANDLE ret;
ME_DisplayItem *para;
ME_Paragraph *para;
int nEnd = ME_GetCursorOfs(start) + nChars;
/* count paragraphs in range */
para = start->pPara;
while((para = para->member.para.next_para) &&
para->member.para.nCharOfs <= nEnd)
para = start->para;
while ((para = para_next( para )) && para->nCharOfs <= nEnd)
pars++;
ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR) * (nChars + pars + 1));

File diff suppressed because it is too large Load Diff

View File

@@ -24,6 +24,7 @@
struct _RTF_Info;
extern HINSTANCE dll_instance DECLSPEC_HIDDEN;
extern HANDLE me_heap DECLSPEC_HIDDEN;
#define RUN_IS_HIDDEN(run) ((run)->style->fmt.dwMask & CFM_HIDDEN \
@@ -49,11 +50,11 @@ static inline const char *debugstr_run( const ME_Run *run )
}
/* style.c */
ME_Style *style_get_insert_style( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
ME_Style *ME_MakeStyle(CHARFORMAT2W *style) DECLSPEC_HIDDEN;
void ME_AddRefStyle(ME_Style *item) DECLSPEC_HIDDEN;
void ME_DestroyStyle(ME_Style *item) DECLSPEC_HIDDEN;
void ME_ReleaseStyle(ME_Style *item) DECLSPEC_HIDDEN;
ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor) DECLSPEC_HIDDEN;
ME_Style *ME_ApplyStyle(ME_TextEditor *ed, ME_Style *sSrc, CHARFORMAT2W *style) DECLSPEC_HIDDEN;
void select_style(ME_Context *c, ME_Style *s) DECLSPEC_HIDDEN;
void ME_InitCharFormat2W(CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
@@ -69,15 +70,12 @@ void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt) DE
/* list.c */
void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat) DECLSPEC_HIDDEN;
void ME_Remove(ME_DisplayItem *diWhere) DECLSPEC_HIDDEN;
BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run, BOOL all_para) DECLSPEC_HIDDEN;
BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run, BOOL all_para) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_FindItemBackOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_MakeDI(ME_DIType type) DECLSPEC_HIDDEN;
void ME_DestroyDisplayItem(ME_DisplayItem *item) DECLSPEC_HIDDEN;
void ME_DumpDocument(ME_TextBuffer *buffer) DECLSPEC_HIDDEN;
void destroy_para(ME_TextEditor *editor, ME_DisplayItem *item) DECLSPEC_HIDDEN;
/* string.c */
ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars) DECLSPEC_HIDDEN;
@@ -114,32 +112,47 @@ int ME_ReverseFindNonWhitespaceV(const ME_String *s, int nVChar) DECLSPEC_HIDDEN
int ME_ReverseFindWhitespaceV(const ME_String *s, int nVChar) DECLSPEC_HIDDEN;
/* row.c */
ME_DisplayItem *ME_RowStart(ME_DisplayItem *item) DECLSPEC_HIDDEN;
/* ME_DisplayItem *ME_RowEnd(ME_DisplayItem *item); */
ME_DisplayItem *ME_FindRowWithNumber(ME_TextEditor *editor, int nRow) DECLSPEC_HIDDEN;
int ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs) DECLSPEC_HIDDEN;
void row_end_cursor( ME_Row *row, ME_Cursor *cursor, BOOL include_eop ) DECLSPEC_HIDDEN;
void row_first_cursor( ME_Row *row, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
ME_Run *row_first_run( ME_Row *row ) DECLSPEC_HIDDEN;
ME_Row *row_from_cursor( ME_Cursor *cursor ) DECLSPEC_HIDDEN;
ME_Row *row_from_row_number( ME_TextEditor *editor, int row_num ) DECLSPEC_HIDDEN;
ME_Row *row_next( ME_Row *row ) DECLSPEC_HIDDEN;
ME_Row *row_next_all_paras( ME_Row *row ) DECLSPEC_HIDDEN;
ME_Run *row_next_run( ME_Row *row, ME_Run *run ) DECLSPEC_HIDDEN;
int row_number_from_char_ofs( ME_TextEditor *editor, int ofs ) DECLSPEC_HIDDEN;
ME_Paragraph *row_para( ME_Row *row ) DECLSPEC_HIDDEN;
ME_Row *row_prev_all_paras( ME_Row *row ) DECLSPEC_HIDDEN;
static inline ME_DisplayItem *row_get_di( ME_Row *row )
{
return (ME_DisplayItem *)((ptrdiff_t)row - offsetof(ME_DisplayItem, member));
}
/* run.c */
ME_DisplayItem *ME_MakeRun(ME_Style *s, int nFlags) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor,
ME_Style *style, const WCHAR *str, int len, int flags) DECLSPEC_HIDDEN;
void cursor_from_char_ofs( ME_TextEditor *editor, int char_ofs, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
BOOL cursor_next_run( ME_Cursor *cursor, BOOL all_para ) DECLSPEC_HIDDEN;
BOOL cursor_prev_run( ME_Cursor *cursor, BOOL all_para ) DECLSPEC_HIDDEN;
void editor_propagate_char_ofs( ME_Paragraph *para, ME_Run *run, int shift ) DECLSPEC_HIDDEN;
int run_char_ofs( ME_Run *run, int ofs ) DECLSPEC_HIDDEN;
ME_Run *run_create( ME_Style *s, int nFlags ) DECLSPEC_HIDDEN;
ME_Run *run_insert( ME_TextEditor *editor, ME_Cursor *cursor,
ME_Style *style, const WCHAR *str, int len, int flags ) DECLSPEC_HIDDEN;
void ME_CheckCharOffsets(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_PropagateCharOffset(ME_DisplayItem *p, int shift) DECLSPEC_HIDDEN;
/* this one accounts for 1/2 char tolerance */
int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BOOL visual_order) DECLSPEC_HIDDEN;
int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, BOOL visual_order) DECLSPEC_HIDDEN;
int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN;
int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN;
BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2) DECLSPEC_HIDDEN;
void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_Cursor *cursor) DECLSPEC_HIDDEN;
void run_join( ME_TextEditor *editor, ME_Run *run ) DECLSPEC_HIDDEN;
ME_Run *run_next( ME_Run *run ) DECLSPEC_HIDDEN;
ME_Run *run_next_all_paras( ME_Run *run ) DECLSPEC_HIDDEN;
ME_Run *run_prev( ME_Run *run ) DECLSPEC_HIDDEN;
ME_Run *run_prev_all_paras( ME_Run *run ) DECLSPEC_HIDDEN;
ME_Run *run_split( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run) DECLSPEC_HIDDEN;
SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, int nLen,
int startx, int *pAscent, int *pDescent) DECLSPEC_HIDDEN;
void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor) DECLSPEC_HIDDEN;
void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **ppPara, ME_DisplayItem **ppRun, int *pOfs) DECLSPEC_HIDDEN;
int ME_CharOfsFromRunOfs(ME_TextEditor *editor, const ME_DisplayItem *pPara, const ME_DisplayItem *pRun, int nOfs) DECLSPEC_HIDDEN;
void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift) DECLSPEC_HIDDEN;
void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from,
@@ -147,8 +160,13 @@ void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from,
void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
void ME_GetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod) DECLSPEC_HIDDEN;
static inline ME_DisplayItem *run_get_di( ME_Run *run )
{
return (ME_DisplayItem *)((ptrdiff_t)run - offsetof(ME_DisplayItem, member));
}
/* caret.c */
void cursor_coords( ME_TextEditor *editor, ME_Cursor *cursor, int *x, int *y, int *height ) DECLSPEC_HIDDEN;
void ME_SetCursorToStart(ME_TextEditor *editor, ME_Cursor *cursor) DECLSPEC_HIDDEN;
int set_selection_cursors(ME_TextEditor *editor, int from, int to) DECLSPEC_HIDDEN;
BOOL ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) DECLSPEC_HIDDEN;
@@ -177,7 +195,6 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, int nChars,
int ME_GetTextLength(ME_TextEditor *editor) DECLSPEC_HIDDEN;
int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how) DECLSPEC_HIDDEN;
ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, int *x, int *y, int *height) DECLSPEC_HIDDEN;
/* context.c */
void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC) DECLSPEC_HIDDEN;
@@ -185,36 +202,49 @@ void ME_DestroyContext(ME_Context *c) DECLSPEC_HIDDEN;
/* wrap.c */
BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_InvalidateParagraphRange(ME_TextEditor *editor, ME_DisplayItem *start_para, ME_DisplayItem *last_para) DECLSPEC_HIDDEN;
void para_range_invalidate( ME_TextEditor *editor, ME_Paragraph *start_para, ME_Paragraph *last_para ) DECLSPEC_HIDDEN;
void ME_SendRequestResize(ME_TextEditor *editor, BOOL force) DECLSPEC_HIDDEN;
BOOL wrap_marked_paras_dc( ME_TextEditor *editor, HDC hdc, BOOL invalidate ) DECLSPEC_HIDDEN;
/* para.c */
ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run) DECLSPEC_HIDDEN;
void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end) DECLSPEC_HIDDEN;
void editor_get_selection_paras(ME_TextEditor *editor, ME_Paragraph **para, ME_Paragraph **para_end ) DECLSPEC_HIDDEN;
void editor_get_selection_para_fmt( ME_TextEditor *editor, PARAFORMAT2 *fmt ) DECLSPEC_HIDDEN;
void editor_mark_rewrap_all( ME_TextEditor *editor ) DECLSPEC_HIDDEN;
void editor_set_default_para_fmt(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
BOOL editor_set_selection_para_fmt( ME_TextEditor *editor, const PARAFORMAT2 *fmt ) DECLSPEC_HIDDEN;
void ME_MakeFirstParagraph(ME_TextEditor *editor) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style, const WCHAR *eol_str, int eol_len, int paraFlags) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
BOOL keepFirstParaFormat) DECLSPEC_HIDDEN;
void ME_DumpParaStyle(ME_Paragraph *s) DECLSPEC_HIDDEN;
void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]) DECLSPEC_HIDDEN;
BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
void ME_MarkAllForWrapping(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_SetDefaultParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
void para_num_init( ME_Context *c, ME_Paragraph *para ) DECLSPEC_HIDDEN;
void para_num_clear( struct para_num *pn ) DECLSPEC_HIDDEN;
int get_total_width(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void mark_para_rewrap(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN;
ME_DisplayItem *get_di_from_para(ME_Paragraph *para) DECLSPEC_HIDDEN;
void add_marked_para(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN;
void remove_marked_para(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN;
ME_Cell *para_cell( ME_Paragraph *para ) DECLSPEC_HIDDEN;
void para_destroy( ME_TextEditor *editor, ME_Paragraph *item ) DECLSPEC_HIDDEN;
ME_Row *para_end_row( ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_Run *para_end_run( ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_Row *para_first_row( ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_Run *para_first_run( ME_Paragraph *para ) DECLSPEC_HIDDEN;
BOOL para_in_table( ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_Paragraph *para_join( ME_TextEditor *editor, ME_Paragraph *para, BOOL use_first_fmt ) DECLSPEC_HIDDEN;
void para_mark_add( ME_TextEditor *editor, ME_Paragraph *para ) DECLSPEC_HIDDEN;
void para_mark_remove( ME_TextEditor *editor, ME_Paragraph *para ) DECLSPEC_HIDDEN;
void para_mark_rewrap( ME_TextEditor *editor, ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_Paragraph *para_next( ME_Paragraph *para ) DECLSPEC_HIDDEN;
void para_num_clear( struct para_num *pn ) DECLSPEC_HIDDEN;
void para_num_init( ME_Context *c, ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_Paragraph *para_prev( ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_Paragraph *para_split( ME_TextEditor *editor, ME_Run *run, ME_Style *style,
const WCHAR *eol_str, int eol_len, int paraFlags ) DECLSPEC_HIDDEN;
static inline ME_DisplayItem *para_get_di(ME_Paragraph *para)
{
return (ME_DisplayItem *)((ptrdiff_t)para - offsetof(ME_DisplayItem, member));
}
/* paint.c */
void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate) DECLSPEC_HIDDEN;
void editor_draw( ME_TextEditor *editor, HDC hDC, const RECT *update ) DECLSPEC_HIDDEN;
void ME_Repaint(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_RewrapRepaint(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_UpdateRepaint(ME_TextEditor *editor, BOOL update_now) DECLSPEC_HIDDEN;
void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor) DECLSPEC_HIDDEN;
void editor_ensure_visible( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
void ME_InvalidateSelection(ME_TextEditor *editor) DECLSPEC_HIDDEN;
BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator) DECLSPEC_HIDDEN;
int ME_twips2pointsX(const ME_Context *c, int x) DECLSPEC_HIDDEN;
@@ -222,9 +252,9 @@ int ME_twips2pointsY(const ME_Context *c, int y) DECLSPEC_HIDDEN;
/* scroll functions in paint.c */
void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) DECLSPEC_HIDDEN;
void ME_HScrollAbs(ME_TextEditor *editor, int x) DECLSPEC_HIDDEN;
void ME_VScrollAbs(ME_TextEditor *editor, int y) DECLSPEC_HIDDEN;
void scroll_abs( ME_TextEditor *editor, int x, int y, BOOL notify ) DECLSPEC_HIDDEN;
void scroll_h_abs( ME_TextEditor *editor, int x, BOOL notify ) DECLSPEC_HIDDEN;
void scroll_v_abs( ME_TextEditor *editor, int y, BOOL notify ) DECLSPEC_HIDDEN;
void ME_ScrollUp(ME_TextEditor *editor, int cy) DECLSPEC_HIDDEN;
void ME_ScrollDown(ME_TextEditor *editor, int cy) DECLSPEC_HIDDEN;
void ME_ScrollLeft(ME_TextEditor *editor, int cx) DECLSPEC_HIDDEN;
@@ -235,18 +265,19 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) DECLSPEC_HIDDEN;
int ME_GetParaBorderWidth(const ME_Context *c, int flags) DECLSPEC_HIDDEN;
/* richole.c */
LRESULT CreateIRichEditOle(IUnknown *outer_unk, ME_TextEditor *editor, LPVOID *ppvObj) DECLSPEC_HIDDEN;
void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run* run, BOOL selected) DECLSPEC_HIDDEN;
void draw_ole( ME_Context *c, int x, int y, ME_Run* run, BOOL selected ) DECLSPEC_HIDDEN;
void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize) DECLSPEC_HIDDEN;
void ME_CopyReObject(REOBJECT *dst, const REOBJECT *src, DWORD flags) DECLSPEC_HIDDEN;
void ME_DeleteReObject(struct re_object *re_object) DECLSPEC_HIDDEN;
void richole_release_children( struct text_services *services ) DECLSPEC_HIDDEN;
extern const IRichEditOleVtbl re_ole_vtbl DECLSPEC_HIDDEN;
extern const ITextDocument2OldVtbl text_doc2old_vtbl DECLSPEC_HIDDEN;
/* editor.c */
ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) DECLSPEC_HIDDEN;
void ME_DestroyEditor(ME_TextEditor *editor) DECLSPEC_HIDDEN;
LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
LPARAM lParam, BOOL unicode, HRESULT* phresult) DECLSPEC_HIDDEN;
void ME_SendOldNotify(ME_TextEditor *editor, int nCode) DECLSPEC_HIDDEN;
LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam,
LPARAM lParam, HRESULT* phresult ) DECLSPEC_HIDDEN;
int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen,
const ME_Cursor *start, int srcChars, BOOL bCRLF, BOOL bEOP) DECLSPEC_HIDDEN;
void ME_RTFCharAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
@@ -257,32 +288,47 @@ void ME_StreamInFill(ME_InStream *stream) DECLSPEC_HIDDEN;
extern BOOL me_debug DECLSPEC_HIDDEN;
void ME_ReplaceSel(ME_TextEditor *editor, BOOL can_undo, const WCHAR *str, int len) DECLSPEC_HIDDEN;
int set_selection( ME_TextEditor *editor, int to, int from ) DECLSPEC_HIDDEN;
HRESULT editor_copy_or_cut( ME_TextEditor *editor, BOOL cut, ME_Cursor *start, int count,
IDataObject **data_out ) DECLSPEC_HIDDEN;
ME_Paragraph *editor_end_para( ME_TextEditor *editor ) DECLSPEC_HIDDEN;
ME_Paragraph *editor_first_para( ME_TextEditor *editor ) DECLSPEC_HIDDEN;
void editor_set_cursor( ME_TextEditor *editor, int x, int y ) DECLSPEC_HIDDEN;
void link_notify( ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN;
/* table.c */
BOOL ME_IsInTable(ME_DisplayItem *pItem) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_InsertTableRowStartFromCursor(ME_TextEditor *editor) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor,
ME_DisplayItem *para) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_InsertTableCellFromCursor(ME_TextEditor *editor) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_InsertTableRowEndFromCursor(ME_TextEditor *editor) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_GetTableRowEnd(ME_DisplayItem *para) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_GetTableRowStart(ME_DisplayItem *para) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_GetOuterParagraph(ME_DisplayItem *para) DECLSPEC_HIDDEN;
void ME_CheckTablesForCorruption(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, ME_Cursor *c, int *nChars) DECLSPEC_HIDDEN;
ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, ME_DisplayItem *table_row) DECLSPEC_HIDDEN;
void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow) DECLSPEC_HIDDEN;
void ME_MoveCursorFromTableRowStartParagraph(ME_TextEditor *editor) DECLSPEC_HIDDEN;
ME_Cell *cell_create( void ) DECLSPEC_HIDDEN;
ME_Paragraph *cell_end_para( ME_Cell *cell ) DECLSPEC_HIDDEN;
ME_Paragraph *cell_first_para( ME_Cell *cell ) DECLSPEC_HIDDEN;
ME_Cell *cell_next( ME_Cell *cell ) DECLSPEC_HIDDEN;
ME_Cell *cell_prev( ME_Cell *cell ) DECLSPEC_HIDDEN;
ME_Paragraph *table_append_row( ME_TextEditor *editor, ME_Paragraph *table_row ) DECLSPEC_HIDDEN;
void table_handle_tab( ME_TextEditor *editor, BOOL selected_row ) DECLSPEC_HIDDEN;
ME_Paragraph *table_insert_cell( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
ME_Paragraph *table_insert_row_end( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
ME_Paragraph *table_insert_row_start( ME_TextEditor *editor, ME_Cursor *cursor ) DECLSPEC_HIDDEN;
ME_Paragraph *table_insert_row_start_at_para( ME_TextEditor *editor, ME_Paragraph *para ) DECLSPEC_HIDDEN;
void table_move_from_row_start( ME_TextEditor *editor ) DECLSPEC_HIDDEN;
ME_Paragraph *table_outer_para( ME_Paragraph *para ) DECLSPEC_HIDDEN;
void table_protect_partial_deletion( ME_TextEditor *editor, ME_Cursor *c, int *num_chars ) DECLSPEC_HIDDEN;
ME_Paragraph *table_row_end( ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_Cell *table_row_end_cell( ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_Cell *table_row_first_cell( ME_Paragraph *para ) DECLSPEC_HIDDEN;
ME_Paragraph *table_row_start( ME_Paragraph *para ) DECLSPEC_HIDDEN;
struct RTFTable *ME_MakeTableDef(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef) DECLSPEC_HIDDEN;
static inline ME_DisplayItem *cell_get_di(ME_Cell *cell)
{
return (ME_DisplayItem *)((ptrdiff_t)cell - offsetof(ME_DisplayItem, member));
}
/* txthost.c */
ITextHost *ME_CreateTextHost(HWND hwnd, CREATESTRUCTW *cs, BOOL bEmulateVersion10) DECLSPEC_HIDDEN;
#if defined(__i386__) && !defined(__MINGW32__) /* Use wrappers to perform thiscall on i386 */
#define TXTHOST_VTABLE(This) (&itextHostStdcallVtbl)
#else /* __i386__ */
#ifdef __ASM_USE_THISCALL_WRAPPER
extern const struct ITextHost2Vtbl text_host2_stdcall_vtbl DECLSPEC_HIDDEN;
#define TXTHOST_VTABLE(This) (&text_host2_stdcall_vtbl)
#else
#define TXTHOST_VTABLE(This) (This)->lpVtbl
#endif /* __i386__ */
#endif
/*** ITextHost methods ***/
#define ITextHost_TxGetDC(This) TXTHOST_VTABLE(This)->TxGetDC(This)
#define ITextHost_TxReleaseDC(This,a) TXTHOST_VTABLE(This)->TxReleaseDC(This,a)
@@ -323,6 +369,19 @@ ITextHost *ME_CreateTextHost(HWND hwnd, CREATESTRUCTW *cs, BOOL bEmulateVersion1
#define ITextHost_TxImmGetContext(This) TXTHOST_VTABLE(This)->TxImmGetContext(This)
#define ITextHost_TxImmReleaseContext(This,a) TXTHOST_VTABLE(This)->TxImmReleaseContext(This,a)
#define ITextHost_TxGetSelectionBarWidth(This,a) TXTHOST_VTABLE(This)->TxGetSelectionBarWidth(This,a)
/* ITextHost2 */
#define ITextHost2_TxIsDoubleClickPending(This) TXTHOST_VTABLE(This)->TxIsDoubleClickPending(This)
#define ITextHost2_TxGetWindow(This,a) TXTHOST_VTABLE(This)->TxGetWindow(This,a)
#define ITextHost2_TxSetForegroundWindow(This) TXTHOST_VTABLE(This)->TxSetForegroundWindow(This)
#define ITextHost2_TxGetPalette(This) TXTHOST_VTABLE(This)->TxGetPalette(This)
#define ITextHost2_TxGetEastAsianFlags(This,a) TXTHOST_VTABLE(This)->TxGetEastAsianFlags(This,a)
#define ITextHost2_TxSetCursor2(This,a,b) TXTHOST_VTABLE(This)->TxSetCursor2(This,a,b)
#define ITextHost2_TxFreeTextServicesNotification(This) TXTHOST_VTABLE(This)->TxFreeTextServicesNotification(This)
#define ITextHost2_TxGetEditStyle(This,a,b) TXTHOST_VTABLE(This)->TxGetEditStyle(This,a,b)
#define ITextHost2_TxGetWindowStyles(This,a,b) TXTHOST_VTABLE(This)->TxGetWindowStyles(This,a,b)
#define ITextHost2_TxShowDropCaret(This,a,b,c) TXTHOST_VTABLE(This)->TxShowDropCaret(This,a,b,c)
#define ITextHost2_TxDestroyCaret(This) TXTHOST_VTABLE(This)->TxDestroyCaret(This)
#define ITextHost2_TxGetHorzExtent(This,a) TXTHOST_VTABLE(This)->TxGetHorzExtent(This,a)
/* undo.c */
BOOL add_undo_insert_run( ME_TextEditor *, int pos, const WCHAR *str, int len, int flags, ME_Style *style ) DECLSPEC_HIDDEN;
@@ -338,6 +397,33 @@ BOOL ME_Undo(ME_TextEditor *editor) DECLSPEC_HIDDEN;
BOOL ME_Redo(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_EmptyUndoStack(ME_TextEditor *editor) DECLSPEC_HIDDEN;
/* txtsrv.c */
HRESULT create_text_services( IUnknown *outer, ITextHost *text_host, IUnknown **unk, BOOL emulate_10 ) DECLSPEC_HIDDEN;
#ifdef __ASM_USE_THISCALL_WRAPPER
extern const struct ITextServicesVtbl text_services_stdcall_vtbl DECLSPEC_HIDDEN;
#define TXTSERV_VTABLE(This) (&text_services_stdcall_vtbl)
#else
#define TXTSERV_VTABLE(This) (This)->lpVtbl
#endif
#define ITextServices_TxSendMessage(This,a,b,c,d) TXTSERV_VTABLE(This)->TxSendMessage(This,a,b,c,d)
#define ITextServices_TxDraw(This,a,b,c,d,e,f,g,h,i,j,k,l) TXTSERV_VTABLE(This)->TxDraw(This,a,b,c,d,e,f,g,h,i,j,k,l)
#define ITextServices_TxGetHScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetHScroll(This,a,b,c,d,e)
#define ITextServices_TxGetVScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetVScroll(This,a,b,c,d,e)
#define ITextServices_OnTxSetCursor(This,a,b,c,d,e,f,g,h,i) TXTSERV_VTABLE(This)->OnTxSetCursor(This,a,b,c,d,e,f,g,h,i)
#define ITextServices_TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j) TXTSERV_VTABLE(This)->TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j)
#define ITextServices_OnTxInPlaceActivate(This,a) TXTSERV_VTABLE(This)->OnTxInPlaceActivate(This,a)
#define ITextServices_OnTxInPlaceDeactivate(This) TXTSERV_VTABLE(This)->OnTxInPlaceDeactivate(This)
#define ITextServices_OnTxUIActivate(This) TXTSERV_VTABLE(This)->OnTxUIActivate(This)
#define ITextServices_OnTxUIDeactivate(This) TXTSERV_VTABLE(This)->OnTxUIDeactivate(This)
#define ITextServices_TxGetText(This,a) TXTSERV_VTABLE(This)->TxGetText(This,a)
#define ITextServices_TxSetText(This,a) TXTSERV_VTABLE(This)->TxSetText(This,a)
#define ITextServices_TxGetCurTargetX(This,a) TXTSERV_VTABLE(This)->TxGetCurTargetX(This,a)
#define ITextServices_TxGetBaseLinePos(This,a) TXTSERV_VTABLE(This)->TxGetBaseLinePos(This,a)
#define ITextServices_TxGetNaturalSize(This,a,b,c,d,e,f,g,h) TXTSERV_VTABLE(This)->TxGetNaturalSize(This,a,b,c,d,e,f,g,h)
#define ITextServices_TxGetDropTarget(This,a) TXTSERV_VTABLE(This)->TxGetDropTarget(This,a)
#define ITextServices_OnTxPropertyBitsChange(This,a,b) TXTSERV_VTABLE(This)->OnTxPropertyBitsChange(This,a,b)
#define ITextServices_TxGetCachedSize(This,a,b) TXTSERV_VTABLE(This)->TxGetCachedSize(This,a,b)
/* writer.c */
LRESULT ME_StreamOutRange(ME_TextEditor *editor, DWORD dwFormat, const ME_Cursor *start, int nChars, EDITSTREAM *stream) DECLSPEC_HIDDEN;
LRESULT ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream) DECLSPEC_HIDDEN;
@@ -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;
void release_typelib(void) DECLSPEC_HIDDEN;

View File

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

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)
{
if (!di)

File diff suppressed because it is too large Load Diff

View File

@@ -23,42 +23,47 @@
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
void mark_para_rewrap(ME_TextEditor *editor, ME_DisplayItem *para)
void para_mark_rewrap( ME_TextEditor *editor, ME_Paragraph *para )
{
para->member.para.nFlags |= MEPF_REWRAP;
add_marked_para(editor, para);
para->nFlags |= MEPF_REWRAP;
para_mark_add( editor, para );
}
ME_DisplayItem *get_di_from_para(ME_Paragraph *para)
{
return (ME_DisplayItem *)((ptrdiff_t)para - offsetof(ME_DisplayItem, member));
}
static ME_DisplayItem *make_para(ME_TextEditor *editor)
static ME_Paragraph *para_create( ME_TextEditor *editor )
{
ME_DisplayItem *item = ME_MakeDI(diParagraph);
ME_SetDefaultParaFormat(editor, &item->member.para.fmt);
editor_set_default_para_fmt( editor, &item->member.para.fmt );
item->member.para.nFlags = MEPF_REWRAP;
item->member.para.next_marked = item->member.para.prev_marked = NULL;
return item;
return &item->member.para;
}
void destroy_para(ME_TextEditor *editor, ME_DisplayItem *item)
void para_destroy( ME_TextEditor *editor, ME_Paragraph *para )
{
assert(item->type == diParagraph);
if (item->member.para.nWidth == editor->nTotalWidth)
if (para->nWidth == editor->nTotalWidth)
{
item->member.para.nWidth = 0;
para->nWidth = 0;
editor->nTotalWidth = get_total_width(editor);
}
editor->total_rows -= item->member.para.nRows;
ME_DestroyString(item->member.para.text);
para_num_clear( &item->member.para.para_num );
remove_marked_para(editor, item);
ME_DestroyDisplayItem(item);
editor->total_rows -= para->nRows;
ME_DestroyString( para->text );
para_num_clear( &para->para_num );
para_mark_remove( editor, para );
ME_DestroyDisplayItem( para_get_di( para ) );
}
/* Note para_next/prev will return the start and end doc nodes */
ME_Paragraph *para_next( ME_Paragraph *para )
{
if (para->next_para) return &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)
@@ -79,90 +84,85 @@ int get_total_width(ME_TextEditor *editor)
return total_width;
}
void remove_marked_para(ME_TextEditor *editor, ME_DisplayItem *di)
static int para_mark_compare( const void *key, const struct wine_rb_entry *entry )
{
ME_DisplayItem *head = editor->first_marked_para;
ME_Paragraph *para = WINE_RB_ENTRY_VALUE( entry, ME_Paragraph, marked_entry );
assert(di->type == diParagraph);
if (!di->member.para.next_marked && !di->member.para.prev_marked)
{
if (di == head)
editor->first_marked_para = NULL;
}
else if (di->member.para.next_marked && di->member.para.prev_marked)
{
di->member.para.prev_marked->member.para.next_marked = di->member.para.next_marked;
di->member.para.next_marked->member.para.prev_marked = di->member.para.prev_marked;
di->member.para.prev_marked = di->member.para.next_marked = NULL;
}
else if (di->member.para.next_marked)
{
assert(di == editor->first_marked_para);
editor->first_marked_para = di->member.para.next_marked;
di->member.para.next_marked->member.para.prev_marked = NULL;
di->member.para.next_marked = NULL;
}
else
{
di->member.para.prev_marked->member.para.next_marked = NULL;
di->member.para.prev_marked = NULL;
}
return *(int *)key - para->nCharOfs;
}
void 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 )
{
wine_rb_put( &editor->marked_paras, &para->nCharOfs, &para->marked_entry );
}
ME_Run *para_first_run( ME_Paragraph *para )
{
ME_DisplayItem *di;
for (di = para_get_di( para ); di != para->next_para; di = di->next )
{
editor->first_marked_para = di;
return;
}
while (iter)
{
if (iter == di)
return;
else if (di->member.para.nCharOfs < iter->member.para.nCharOfs)
{
if (iter == editor->first_marked_para)
editor->first_marked_para = di;
di->member.para.next_marked = iter;
iter->member.para.prev_marked = di;
break;
}
else if (di->member.para.nCharOfs >= iter->member.para.nCharOfs)
{
if (!iter->member.para.next_marked || di->member.para.nCharOfs < iter->member.para.next_marked->member.para.nCharOfs)
{
if (iter->member.para.next_marked)
{
di->member.para.next_marked = iter->member.para.next_marked;
iter->member.para.next_marked->member.para.prev_marked = di;
}
di->member.para.prev_marked = iter;
iter->member.para.next_marked = di;
break;
}
}
iter = iter->member.para.next_marked;
if (di->type != diRun) continue;
return &di->member.run;
}
ERR( "failed to find run in paragraph\n" );
return NULL;
}
ME_Run *para_end_run( ME_Paragraph *para )
{
return para->eop_run;
}
BOOL para_in_table( ME_Paragraph *para )
{
return para->fmt.wEffects & PFE_TABLE;
}
ME_Cell *para_cell( ME_Paragraph *para )
{
return para->cell;
}
ME_Row *para_first_row( ME_Paragraph *para )
{
ME_DisplayItem *item;
item = ME_FindItemFwd( para_get_di( para ), diStartRowOrParagraph );
if (!item || item->type != diStartRow) return NULL;
return &item->member.row;
}
ME_Row *para_end_row( ME_Paragraph *para )
{
ME_DisplayItem *item;
para = para_next( para );
item = ME_FindItemBack( para_get_di( para ), diStartRowOrParagraph );
if (!item || item->type != diStartRow) return NULL;
return &item->member.row;
}
void ME_MakeFirstParagraph(ME_TextEditor *editor)
{
static const WCHAR cr_lf[] = {'\r','\n',0};
ME_Context c;
CHARFORMAT2W cf;
const CHARFORMATW *host_cf;
LOGFONTW lf;
HFONT hf;
ME_TextBuffer *text = editor->pBuffer;
ME_DisplayItem *para = make_para(editor);
ME_DisplayItem *run;
ME_Paragraph *para = para_create( editor );
ME_Run *run;
ME_Style *style;
int eol_len;
HDC hdc = ITextHost_TxGetDC( editor->texthost );
ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
ME_InitContext( &c, editor, hdc );
hf = GetStockObject(SYSTEM_FONT);
assert(hf);
@@ -202,59 +202,57 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
}
eol_len = editor->bEmulateVersion10 ? 2 : 1;
para->member.para.text = ME_MakeStringN( cr_lf, eol_len );
para->text = ME_MakeStringN( L"\r\n", eol_len );
run = ME_MakeRun(style, MERF_ENDPARA);
run->member.run.nCharOfs = 0;
run->member.run.len = eol_len;
run->member.run.para = &para->member.para;
run = run_create( style, MERF_ENDPARA );
run->nCharOfs = 0;
run->len = eol_len;
run->para = para;
para->eop_run = run;
para->member.para.eop_run = &run->member.run;
ME_InsertBefore(text->pLast, para);
ME_InsertBefore(text->pLast, run);
para->member.para.prev_para = text->pFirst;
para->member.para.next_para = text->pLast;
text->pFirst->member.para.next_para = para;
text->pLast->member.para.prev_para = para;
ME_InsertBefore( text->pLast, para_get_di( para) );
ME_InsertBefore( text->pLast, run_get_di( run ) );
para->prev_para = text->pFirst;
para->next_para = text->pLast;
text->pFirst->member.para.next_para = para_get_di( para );
text->pLast->member.para.prev_para = para_get_di( para );
text->pLast->member.para.nCharOfs = editor->bEmulateVersion10 ? 2 : 1;
add_marked_para(editor, para);
wine_rb_init( &editor->marked_paras, para_mark_compare );
para_mark_add( editor, para );
ME_DestroyContext(&c);
ITextHost_TxReleaseDC( editor->texthost, hdc );
}
static void ME_MarkForWrapping(ME_TextEditor *editor, ME_DisplayItem *first, const ME_DisplayItem *last)
static void para_mark_rewrap_paras( ME_TextEditor *editor, ME_Paragraph *first, const ME_Paragraph *end )
{
while(first != last)
{
mark_para_rewrap(editor, first);
first = first->member.para.next_para;
}
while (first != end)
{
para_mark_rewrap( editor, first );
first = para_next( first );
}
}
void ME_MarkAllForWrapping(ME_TextEditor *editor)
void editor_mark_rewrap_all( ME_TextEditor *editor )
{
ME_MarkForWrapping(editor, editor->pBuffer->pFirst->member.para.next_para, editor->pBuffer->pLast);
para_mark_rewrap_paras( editor, editor_first_para( editor ), editor_end_para( editor ) );
}
static void ME_UpdateTableFlags(ME_DisplayItem *para)
static void table_update_flags( ME_Paragraph *para )
{
para->member.para.fmt.dwMask |= PFM_TABLE|PFM_TABLEROWDELIMITER;
if (para->member.para.pCell) {
para->member.para.nFlags |= MEPF_CELL;
} else {
para->member.para.nFlags &= ~MEPF_CELL;
}
if (para->member.para.nFlags & MEPF_ROWEND) {
para->member.para.fmt.wEffects |= PFE_TABLEROWDELIMITER;
} else {
para->member.para.fmt.wEffects &= ~PFE_TABLEROWDELIMITER;
}
if (para->member.para.nFlags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND))
para->member.para.fmt.wEffects |= PFE_TABLE;
else
para->member.para.fmt.wEffects &= ~PFE_TABLE;
para->fmt.dwMask |= PFM_TABLE | PFM_TABLEROWDELIMITER;
if (para_cell( para )) para->nFlags |= MEPF_CELL;
else para->nFlags &= ~MEPF_CELL;
if (para->nFlags & MEPF_ROWEND) para->fmt.wEffects |= PFE_TABLEROWDELIMITER;
else para->fmt.wEffects &= ~PFE_TABLEROWDELIMITER;
if (para->nFlags & (MEPF_ROWSTART | MEPF_CELL | MEPF_ROWEND))
para->fmt.wEffects |= PFE_TABLE;
else
para->fmt.wEffects &= ~PFE_TABLE;
}
static inline BOOL para_num_same_list( const PARAFORMAT2 *item, const PARAFORMAT2 *base )
@@ -283,7 +281,6 @@ static ME_String *para_num_get_str( ME_Paragraph *para, WORD num )
/* max 4 Roman letters (representing '8') / decade + '(' + ')' */
ME_String *str = ME_MakeStringEmpty( 20 + 2 );
WCHAR *p;
static const WCHAR fmtW[] = {'%', 'd', 0};
static const WORD letter_base[] = { 1, 26, 26 * 26, 26 * 26 * 26 };
/* roman_base should start on a '5' not a '1', otherwise the 'total' code will need adjusting.
'N' and 'O' are what MS uses for 5000 and 10000, their version doesn't work well above 30000,
@@ -312,7 +309,7 @@ static ME_String *para_num_get_str( ME_Paragraph *para, WORD num )
{
case PFN_ARABIC:
default:
p += swprintf( p, fmtW, num );
p += swprintf( p, 20, L"%d", num );
break;
case PFN_LCLETTER:
@@ -396,9 +393,6 @@ void para_num_init( ME_Context *c, ME_Paragraph *para )
{
ME_Style *style;
CHARFORMAT2W cf;
static const WCHAR bullet_font[] = {'S','y','m','b','o','l',0};
static const WCHAR bullet_str[] = {0xb7, 0};
static const WCHAR spaceW[] = {' ', 0};
SIZE sz;
if (!para->fmt.wNumbering) return;
@@ -412,7 +406,7 @@ void para_num_init( ME_Context *c, ME_Paragraph *para )
{
cf.cbSize = sizeof(cf);
cf.dwMask = CFM_FACE | CFM_CHARSET;
memcpy( cf.szFaceName, bullet_font, sizeof(bullet_font) );
lstrcpyW( cf.szFaceName, L"Symbol" );
cf.bCharSet = SYMBOL_CHARSET;
style = ME_ApplyStyle( c->editor, style, &cf );
}
@@ -429,13 +423,13 @@ void para_num_init( ME_Context *c, ME_Paragraph *para )
if (para->fmt.wNumbering != PFN_BULLET)
para->para_num.text = para_num_get_str( para, para_num_get_num( para ) );
else
para->para_num.text = ME_MakeStringConst( bullet_str, 1 );
para->para_num.text = ME_MakeStringConst( L"\x00b7", 1 );
}
select_style( c, para->para_num.style );
GetTextExtentPointW( c->hDC, para->para_num.text->szData, para->para_num.text->nLen, &sz );
para->para_num.width = sz.cx;
GetTextExtentPointW( c->hDC, spaceW, 1, &sz );
GetTextExtentPointW( c->hDC, L" ", 1, &sz );
para->para_num.width += sz.cx;
}
@@ -454,14 +448,14 @@ static void para_num_clear_list( ME_TextEditor *editor, ME_Paragraph *para, cons
{
do
{
mark_para_rewrap(editor, get_di_from_para(para));
para_mark_rewrap( editor, para );
para_num_clear( &para->para_num );
if (para->next_para->type != diParagraph) break;
para = &para->next_para->member.para;
} 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;
DWORD dwMask;
@@ -494,8 +488,9 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PA
COPY_FIELD(PFM_ALIGNMENT, wAlignment);
if (dwMask & PFM_TABSTOPS)
{
para->fmt.cTabCount = max(0, min(pFmt->cTabCount, MAX_TAB_STOPS)); /* Clamp between 0 and MAX_TAB_STOPS */
memcpy(para->fmt.rgxTabs, pFmt->rgxTabs, para->fmt.cTabCount*sizeof(LONG));
/* 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));
}
#define EFFECTS_MASK (PFM_RTLPARA|PFM_KEEP|PFM_KEEPNEXT|PFM_PAGEBREAKBEFORE| \
@@ -529,7 +524,7 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PA
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)) ||
((dwMask & PFM_NUMBERINGSTART) && (copy.wNumberingStart != para->fmt.wNumberingStart)) ||
((dwMask & PFM_NUMBERINGSTYLE) && (copy.wNumberingStyle != para->fmt.wNumberingStyle)))
@@ -542,278 +537,251 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PA
}
/* split paragraph at the beginning of the run */
ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
ME_Style *style, const WCHAR *eol_str, int eol_len,
int paraFlags)
ME_Paragraph *para_split( ME_TextEditor *editor, ME_Run *run, ME_Style *style,
const WCHAR *eol_str, int eol_len, int paraFlags )
{
ME_DisplayItem *next_para = NULL;
ME_DisplayItem *run_para = NULL;
ME_DisplayItem *new_para = make_para(editor);
ME_DisplayItem *end_run;
ME_Paragraph *new_para = para_create( editor ), *old_para, *next_para;
ME_Run *end_run, *next_run;
int ofs, i;
ME_DisplayItem *pp;
int run_flags = MERF_ENDPARA;
if (!editor->bEmulateVersion10) { /* v4.1 */
if (!editor->bEmulateVersion10) /* v4.1 */
{
/* At most 1 of MEPF_CELL, MEPF_ROWSTART, or MEPF_ROWEND should be set. */
assert(!(paraFlags & ~(MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND)));
assert(!(paraFlags & (paraFlags-1)));
assert( !(paraFlags & ~(MEPF_CELL | MEPF_ROWSTART | MEPF_ROWEND)) );
assert( !(paraFlags & (paraFlags-1)) );
if (paraFlags == MEPF_CELL)
run_flags |= MERF_ENDCELL;
run_flags |= MERF_ENDCELL;
else if (paraFlags == MEPF_ROWSTART)
run_flags |= MERF_TABLESTART|MERF_HIDDEN;
} else { /* v1.0 - v3.0 */
assert(!(paraFlags & (MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND)));
run_flags |= MERF_TABLESTART | MERF_HIDDEN;
}
assert(run->type == diRun);
run_para = ME_GetParagraph(run);
assert(run_para->member.para.fmt.cbSize == sizeof(PARAFORMAT2));
else /* v1.0 - v3.0 */
assert( !(paraFlags & (MEPF_CELL |MEPF_ROWSTART | MEPF_ROWEND)) );
old_para = run->para;
assert( old_para->fmt.cbSize == sizeof(PARAFORMAT2) );
/* Clear any cached para numbering following this paragraph */
if (run_para->member.para.fmt.wNumbering)
para_num_clear_list( editor, &run_para->member.para, &run_para->member.para.fmt );
if (old_para->fmt.wNumbering)
para_num_clear_list( editor, old_para, &old_para->fmt );
new_para->member.para.text = ME_VSplitString( run_para->member.para.text, run->member.run.nCharOfs );
new_para->text = ME_VSplitString( old_para->text, run->nCharOfs );
end_run = ME_MakeRun(style, run_flags);
ofs = end_run->member.run.nCharOfs = run->member.run.nCharOfs;
end_run->member.run.len = eol_len;
end_run->member.run.para = run->member.run.para;
ME_AppendString( run_para->member.para.text, eol_str, eol_len );
next_para = run_para->member.para.next_para;
assert(next_para == ME_FindItemFwd(run_para, diParagraphOrEnd));
end_run = run_create( style, run_flags );
ofs = end_run->nCharOfs = run->nCharOfs;
end_run->len = eol_len;
end_run->para = run->para;
ME_AppendString( old_para->text, eol_str, eol_len );
next_para = &old_para->next_para->member.para;
add_undo_join_paras( editor, run_para->member.para.nCharOfs + ofs );
add_undo_join_paras( editor, old_para->nCharOfs + ofs );
/* Update selection cursors to point to the correct paragraph. */
for (i = 0; i < editor->nCursors; i++) {
if (editor->pCursors[i].pPara == run_para &&
run->member.run.nCharOfs <= editor->pCursors[i].pRun->member.run.nCharOfs)
for (i = 0; i < editor->nCursors; i++)
{
if (editor->pCursors[i].para == old_para &&
run->nCharOfs <= editor->pCursors[i].run->nCharOfs)
{
editor->pCursors[i].pPara = new_para;
editor->pCursors[i].para = new_para;
}
}
/* the new paragraph will have a different starting offset, so let's update its runs */
pp = run;
while(pp->type == diRun) {
pp->member.run.nCharOfs -= ofs;
pp->member.run.para = &new_para->member.para;
pp = ME_FindItemFwd(pp, diRunOrParagraphOrEnd);
/* the new paragraph will have a different starting offset, so update its runs */
for (next_run = run; next_run; next_run = run_next( next_run ))
{
next_run->nCharOfs -= ofs;
next_run->para = new_para;
}
new_para->member.para.nCharOfs = run_para->member.para.nCharOfs + ofs;
new_para->member.para.nCharOfs += eol_len;
new_para->member.para.nFlags = 0;
mark_para_rewrap(editor, new_para);
new_para->nCharOfs = old_para->nCharOfs + ofs;
new_para->nCharOfs += eol_len;
new_para->nFlags = 0;
para_mark_rewrap( editor, new_para );
/* FIXME initialize format style and call ME_SetParaFormat blah blah */
new_para->member.para.fmt = run_para->member.para.fmt;
new_para->member.para.border = run_para->member.para.border;
new_para->fmt = old_para->fmt;
new_para->border = old_para->border;
/* insert paragraph into paragraph double linked list */
new_para->member.para.prev_para = run_para;
new_para->member.para.next_para = next_para;
run_para->member.para.next_para = new_para;
next_para->member.para.prev_para = new_para;
new_para->prev_para = para_get_di( old_para );
new_para->next_para = para_get_di( next_para );
old_para->next_para = para_get_di( new_para );
next_para->prev_para = para_get_di( new_para );
/* insert end run of the old paragraph, and new paragraph, into DI double linked list */
ME_InsertBefore(run, new_para);
ME_InsertBefore(new_para, end_run);
ME_InsertBefore( run_get_di( run ), para_get_di( new_para ) );
ME_InsertBefore( para_get_di( new_para ), run_get_di( end_run ) );
/* Fix up the paras' eop_run ptrs */
new_para->member.para.eop_run = run_para->member.para.eop_run;
run_para->member.para.eop_run = &end_run->member.run;
new_para->eop_run = old_para->eop_run;
old_para->eop_run = end_run;
if (!editor->bEmulateVersion10) { /* v4.1 */
if (paraFlags & (MEPF_ROWSTART|MEPF_CELL))
if (!editor->bEmulateVersion10) /* v4.1 */
{
if (paraFlags & (MEPF_ROWSTART | MEPF_CELL))
{
ME_DisplayItem *cell = ME_MakeDI(diCell);
ME_InsertBefore(new_para, cell);
new_para->member.para.pCell = cell;
cell->member.cell.next_cell = NULL;
ME_Cell *cell = cell_create();
ME_InsertBefore( para_get_di( new_para ), cell_get_di( cell ) );
new_para->cell = cell;
cell->next_cell = NULL;
if (paraFlags & MEPF_ROWSTART)
{
run_para->member.para.nFlags |= MEPF_ROWSTART;
cell->member.cell.prev_cell = NULL;
cell->member.cell.parent_cell = run_para->member.para.pCell;
if (run_para->member.para.pCell)
cell->member.cell.nNestingLevel = run_para->member.para.pCell->member.cell.nNestingLevel + 1;
old_para->nFlags |= MEPF_ROWSTART;
cell->prev_cell = NULL;
cell->parent_cell = old_para->cell;
if (para_cell( old_para ))
cell->nNestingLevel = para_cell( old_para )->nNestingLevel + 1;
else
cell->member.cell.nNestingLevel = 1;
} else {
cell->member.cell.prev_cell = run_para->member.para.pCell;
assert(cell->member.cell.prev_cell);
cell->member.cell.prev_cell->member.cell.next_cell = cell;
assert(run_para->member.para.nFlags & MEPF_CELL);
assert(!(run_para->member.para.nFlags & MEPF_ROWSTART));
cell->member.cell.nNestingLevel = cell->member.cell.prev_cell->member.cell.nNestingLevel;
cell->member.cell.parent_cell = cell->member.cell.prev_cell->member.cell.parent_cell;
cell->nNestingLevel = 1;
}
} else if (paraFlags & MEPF_ROWEND) {
run_para->member.para.nFlags |= MEPF_ROWEND;
run_para->member.para.pCell = run_para->member.para.pCell->member.cell.parent_cell;
new_para->member.para.pCell = run_para->member.para.pCell;
assert(run_para->member.para.prev_para->member.para.nFlags & MEPF_CELL);
assert(!(run_para->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART));
if (new_para->member.para.pCell != new_para->member.para.next_para->member.para.pCell
&& new_para->member.para.next_para->member.para.pCell
&& !new_para->member.para.next_para->member.para.pCell->member.cell.prev_cell)
else
{
cell->prev_cell = old_para->cell;
cell_prev( cell )->next_cell = cell;
assert( old_para->nFlags & MEPF_CELL );
assert( !(old_para->nFlags & MEPF_ROWSTART) );
cell->nNestingLevel = cell_prev( cell )->nNestingLevel;
cell->parent_cell = cell_prev( cell )->parent_cell;
}
}
else if (paraFlags & MEPF_ROWEND)
{
old_para->nFlags |= MEPF_ROWEND;
old_para->cell = old_para->cell->parent_cell;
new_para->cell = old_para->cell;
assert( para_prev( old_para )->nFlags & MEPF_CELL );
assert( !(para_prev( old_para )->nFlags & MEPF_ROWSTART) );
if (new_para->cell != para_next( new_para )->cell
&& para_next( new_para )->cell
&& !cell_prev( para_next( new_para )->cell ))
{
/* Row starts just after the row that was ended. */
new_para->member.para.nFlags |= MEPF_ROWSTART;
new_para->nFlags |= MEPF_ROWSTART;
}
} else {
new_para->member.para.pCell = run_para->member.para.pCell;
}
ME_UpdateTableFlags(run_para);
ME_UpdateTableFlags(new_para);
else new_para->cell = old_para->cell;
table_update_flags( old_para );
table_update_flags( new_para );
}
/* force rewrap of the */
if (run_para->member.para.prev_para->type == diParagraph)
mark_para_rewrap(editor, run_para->member.para.prev_para);
if (old_para->prev_para->type == diParagraph)
para_mark_rewrap( editor, &old_para->prev_para->member.para );
mark_para_rewrap(editor, new_para->member.para.prev_para);
para_mark_rewrap( editor, &new_para->prev_para->member.para );
/* we've added the end run, so we need to modify nCharOfs in the next paragraphs */
ME_PropagateCharOffset(next_para, eol_len);
editor_propagate_char_ofs( next_para, NULL, eol_len );
editor->nParagraphs++;
return new_para;
}
/* join tp with tp->member.para.next_para, keeping tp's style; this
* is consistent with the original */
ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
BOOL keepFirstParaFormat)
/* join para with the next para keeping para's style using the paragraph fmt
specified in use_first_fmt */
ME_Paragraph *para_join( ME_TextEditor *editor, ME_Paragraph *para, BOOL use_first_fmt )
{
ME_DisplayItem *pNext, *pFirstRunInNext, *pRun, *pTmp, *pCell = NULL;
int i, shift;
int end_len;
ME_Paragraph *next = para_next( para );
ME_Run *end_run, *next_first_run, *tmp_run;
ME_Cell *cell = NULL;
int i, end_len;
CHARFORMAT2W fmt;
ME_Cursor startCur, endCur;
ME_String *eol_str;
assert(tp->type == diParagraph);
assert(tp->member.para.next_para);
assert(tp->member.para.next_para->type == diParagraph);
assert( next && para_next( next ) );
/* Clear any cached para numbering following this paragraph */
if (tp->member.para.fmt.wNumbering)
para_num_clear_list( editor, &tp->member.para, &tp->member.para.fmt );
if (para->fmt.wNumbering) para_num_clear_list( editor, para, &para->fmt );
pNext = tp->member.para.next_para;
end_run = para_end_run( para );
next_first_run = para_first_run( next );
/* Need to locate end-of-paragraph run here, in order to know end_len */
pRun = ME_FindItemBack(pNext, diRunOrParagraph);
assert(pRun);
assert(pRun->type == diRun);
assert(pRun->member.run.nFlags & MERF_ENDPARA);
end_len = pRun->member.run.len;
eol_str = ME_VSplitString( tp->member.para.text, pRun->member.run.nCharOfs );
ME_AppendString( tp->member.para.text, pNext->member.para.text->szData, pNext->member.para.text->nLen );
end_len = end_run->len;
eol_str = ME_VSplitString( para->text, end_run->nCharOfs );
ME_AppendString( para->text, next->text->szData, next->text->nLen );
/* null char format operation to store the original char format for the ENDPARA run */
ME_InitCharFormat2W(&fmt);
endCur.pPara = pNext;
endCur.pRun = ME_FindItemFwd(pNext, diRun);
endCur.nOffset = 0;
startCur = endCur;
ME_PrevRun(&startCur.pPara, &startCur.pRun, TRUE);
startCur.para = para;
startCur.run = end_run;
endCur.para = next;
endCur.run = next_first_run;
startCur.nOffset = endCur.nOffset = 0;
ME_SetCharFormat(editor, &startCur, &endCur, &fmt);
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;
if (!editor->bEmulateVersion10) /* v4.1 */
{
/* Remove cell boundary if it is between the end paragraph run and the next
* paragraph display item. */
for (pTmp = pRun->next; pTmp != pNext; pTmp = pTmp->next)
{
if (pTmp->type == diCell)
{
pCell = pTmp;
break;
}
}
if (para->cell != next->cell) cell = next->cell;
/* Table cell/row properties are always moved over from the removed para. */
para->nFlags = next->nFlags;
para->cell = next->cell;
}
add_undo_split_para( editor, &pNext->member.para, eol_str, pCell ? &pCell->member.cell : NULL );
add_undo_split_para( editor, next, eol_str, cell );
if (pCell)
if (cell)
{
ME_Remove( pCell );
if (pCell->member.cell.prev_cell)
pCell->member.cell.prev_cell->member.cell.next_cell = pCell->member.cell.next_cell;
if (pCell->member.cell.next_cell)
pCell->member.cell.next_cell->member.cell.prev_cell = pCell->member.cell.prev_cell;
ME_DestroyDisplayItem( pCell );
ME_Remove( cell_get_di( cell ) );
if (cell_prev( cell )) cell_prev( cell )->next_cell = cell_next( cell );
if (cell_next( cell )) cell_next( cell )->prev_cell = cell_prev( cell );
ME_DestroyDisplayItem( cell_get_di( cell ) );
}
if (!keepFirstParaFormat)
if (!use_first_fmt)
{
add_undo_set_para_fmt( editor, &tp->member.para );
tp->member.para.fmt = pNext->member.para.fmt;
tp->member.para.border = pNext->member.para.border;
add_undo_set_para_fmt( editor, para );
para->fmt = next->fmt;
para->border = next->border;
}
shift = pNext->member.para.nCharOfs - tp->member.para.nCharOfs - end_len;
pFirstRunInNext = ME_FindItemFwd(pNext, diRunOrParagraph);
assert(pFirstRunInNext->type == diRun);
/* Update selection cursors so they don't point to the removed end
* paragraph run, and point to the correct paragraph. */
for (i=0; i < editor->nCursors; i++) {
if (editor->pCursors[i].pRun == pRun) {
editor->pCursors[i].pRun = pFirstRunInNext;
for (i = 0; i < editor->nCursors; i++)
{
if (editor->pCursors[i].run == end_run)
{
editor->pCursors[i].run = next_first_run;
editor->pCursors[i].nOffset = 0;
} else if (editor->pCursors[i].pPara == pNext) {
editor->pCursors[i].pPara = tp;
}
else if (editor->pCursors[i].para == next)
editor->pCursors[i].para = para;
}
pTmp = pNext;
do {
pTmp = ME_FindItemFwd(pTmp, diRunOrParagraphOrEnd);
if (pTmp->type != diRun)
break;
TRACE("shifting %s by %d (previous %d)\n", debugstr_run( &pTmp->member.run ), shift, pTmp->member.run.nCharOfs);
pTmp->member.run.nCharOfs += shift;
pTmp->member.run.para = &tp->member.para;
} while(1);
for (tmp_run = next_first_run; tmp_run; tmp_run = run_next( tmp_run ))
{
tmp_run->nCharOfs += next->nCharOfs - para->nCharOfs - end_len;
tmp_run->para = para;
}
/* Fix up the para's eop_run ptr */
tp->member.para.eop_run = pNext->member.para.eop_run;
para->eop_run = next->eop_run;
ME_Remove(pRun);
ME_DestroyDisplayItem(pRun);
ME_Remove( run_get_di( end_run ) );
ME_DestroyDisplayItem( run_get_di( end_run) );
if (editor->pLastSelStartPara == pNext)
editor->pLastSelStartPara = tp;
if (editor->pLastSelEndPara == pNext)
editor->pLastSelEndPara = tp;
if (editor->last_sel_start_para == next)
editor->last_sel_start_para = para;
if (editor->last_sel_end_para == next)
editor->last_sel_end_para = para;
tp->member.para.next_para = pNext->member.para.next_para;
pNext->member.para.next_para->member.para.prev_para = tp;
ME_Remove(pNext);
destroy_para(editor, pNext);
para->next_para = next->next_para;
next->next_para->member.para.prev_para = para_get_di( para );
ME_Remove( para_get_di(next) );
para_destroy( editor, next );
ME_PropagateCharOffset(tp->member.para.next_para, -end_len);
editor_propagate_char_ofs( para_next( para ), NULL, -end_len );
ME_CheckCharOffsets(editor);
editor->nParagraphs--;
mark_para_rewrap(editor, tp);
return tp;
}
ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *item) {
return ME_FindItemBackOrHere(item, diParagraph);
para_mark_rewrap( editor, para );
return para;
}
void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048])
@@ -879,18 +847,18 @@ void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048])
#undef DUMP_EFFECT
}
void
ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end)
void editor_get_selection_paras( ME_TextEditor *editor, ME_Paragraph **para, ME_Paragraph **para_end )
{
ME_Cursor *pEndCursor = &editor->pCursors[1];
*para = editor->pCursors[0].pPara;
*para_end = editor->pCursors[1].pPara;
*para = editor->pCursors[0].para;
*para_end = editor->pCursors[1].para;
if (*para == *para_end)
return;
if ((*para_end)->member.para.nCharOfs < (*para)->member.para.nCharOfs) {
ME_DisplayItem *tmp = *para;
if ((*para_end)->nCharOfs < (*para)->nCharOfs)
{
ME_Paragraph *tmp = *para;
*para = *para_end;
*para_end = tmp;
@@ -899,78 +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
* if the selection ends at the start of the paragraph. */
if (!pEndCursor->pRun->member.run.nCharOfs && !pEndCursor->nOffset)
*para_end = (*para_end)->member.para.prev_para;
if (!pEndCursor->run->nCharOfs && !pEndCursor->nOffset)
*para_end = para_prev( *para_end );
}
BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt)
BOOL editor_set_selection_para_fmt( ME_TextEditor *editor, const PARAFORMAT2 *fmt )
{
ME_DisplayItem *para, *para_end;
ME_Paragraph *para, *para_end;
ME_GetSelectionParas(editor, &para, &para_end);
editor_get_selection_paras( editor, &para, &para_end );
do {
ME_SetParaFormat(editor, &para->member.para, pFmt);
if (para == para_end)
break;
para = para->member.para.next_para;
} while(1);
do
{
para_set_fmt( editor, para, fmt );
if (para == para_end) break;
para = para_next( para );
} while(1);
return TRUE;
return TRUE;
}
static void ME_GetParaFormat(ME_TextEditor *editor,
const ME_DisplayItem *para,
PARAFORMAT2 *pFmt)
static void para_copy_fmt( const ME_Paragraph *para, PARAFORMAT2 *fmt )
{
UINT cbSize = pFmt->cbSize;
if (pFmt->cbSize >= sizeof(PARAFORMAT2)) {
*pFmt = para->member.para.fmt;
} else {
CopyMemory(pFmt, &para->member.para.fmt, pFmt->cbSize);
pFmt->dwMask &= PFM_ALL;
}
pFmt->cbSize = cbSize;
UINT size = fmt->cbSize;
if (fmt->cbSize >= sizeof(PARAFORMAT2))
*fmt = para->fmt;
else
{
memcpy( fmt, &para->fmt, fmt->cbSize );
fmt->dwMask &= PFM_ALL;
}
fmt->cbSize = size;
}
void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
void editor_get_selection_para_fmt( ME_TextEditor *editor, PARAFORMAT2 *fmt )
{
ME_DisplayItem *para, *para_end;
PARAFORMAT2 *curFmt;
ME_Paragraph *para, *para_end;
if (pFmt->cbSize < sizeof(PARAFORMAT)) {
pFmt->dwMask = 0;
if (fmt->cbSize < sizeof(PARAFORMAT))
{
fmt->dwMask = 0;
return;
}
ME_GetSelectionParas(editor, &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. */
while (para != para_end)
{
para = para->member.para.next_para;
curFmt = &para->member.para.fmt;
para = para_next( para );
#define CHECK_FIELD(m, f) \
if (pFmt->f != curFmt->f) pFmt->dwMask &= ~(m);
if (fmt->f != para->fmt.f) fmt->dwMask &= ~(m);
CHECK_FIELD(PFM_NUMBERING, wNumbering);
CHECK_FIELD(PFM_STARTINDENT, dxStartIndent);
CHECK_FIELD(PFM_RIGHTINDENT, dxRightIndent);
CHECK_FIELD(PFM_OFFSET, dxOffset);
CHECK_FIELD(PFM_ALIGNMENT, wAlignment);
if (pFmt->dwMask & PFM_TABSTOPS) {
if (pFmt->cTabCount != para->member.para.fmt.cTabCount ||
memcmp(pFmt->rgxTabs, curFmt->rgxTabs, curFmt->cTabCount*sizeof(int)))
pFmt->dwMask &= ~PFM_TABSTOPS;
if (fmt->dwMask & PFM_TABSTOPS)
{
if (fmt->cTabCount != para->fmt.cTabCount ||
memcmp(fmt->rgxTabs, para->fmt.rgxTabs, para->fmt.cTabCount * sizeof(int) ))
fmt->dwMask &= ~PFM_TABSTOPS;
}
if (pFmt->dwMask >= sizeof(PARAFORMAT2))
if (fmt->cbSize >= sizeof(PARAFORMAT2))
{
pFmt->dwMask &= ~((pFmt->wEffects ^ curFmt->wEffects) << 16);
fmt->dwMask &= ~((fmt->wEffects ^ para->fmt.wEffects) << 16);
CHECK_FIELD(PFM_SPACEBEFORE, dySpaceBefore);
CHECK_FIELD(PFM_SPACEAFTER, dySpaceAfter);
CHECK_FIELD(PFM_LINESPACING, dyLineSpacing);
@@ -989,7 +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;
HRESULT hr;

View File

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

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

View File

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

View File

@@ -27,6 +27,100 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
WINE_DECLARE_DEBUG_CHANNEL(richedit_check);
WINE_DECLARE_DEBUG_CHANNEL(richedit_lists);
BOOL cursor_next_run( ME_Cursor *cursor, BOOL all_para )
{
ME_DisplayItem *p = run_get_di( cursor->run )->next;
while (p->type != diTextEnd)
{
if (p->type == diParagraph && !all_para) return FALSE;
else if (p->type == diRun)
{
cursor->run = &p->member.run;
cursor->para = cursor->run->para;
cursor->nOffset = 0;
return TRUE;
}
p = p->next;
}
return FALSE;
}
BOOL cursor_prev_run( ME_Cursor *cursor, BOOL all_para )
{
ME_DisplayItem *p = run_get_di( cursor->run )->prev;
while (p->type != diTextStart)
{
if (p->type == diParagraph && !all_para) return FALSE;
else if (p->type == diRun)
{
cursor->run = &p->member.run;
cursor->para = cursor->run->para;
cursor->nOffset = 0;
return TRUE;
}
p = p->prev;
}
return FALSE;
}
ME_Run *run_next( ME_Run *run )
{
ME_Cursor cursor;
cursor.run = run;
cursor.para = run->para;
cursor.nOffset = 0;
if (cursor_next_run( &cursor, FALSE ))
return cursor.run;
return NULL;
}
ME_Run *run_prev( ME_Run *run )
{
ME_Cursor cursor;
cursor.run = run;
cursor.para = run->para;
cursor.nOffset = 0;
if (cursor_prev_run( &cursor, FALSE ))
return cursor.run;
return NULL;
}
ME_Run *run_next_all_paras( ME_Run *run )
{
ME_Cursor cursor;
cursor.run = run;
cursor.para = run->para;
cursor.nOffset = 0;
if (cursor_next_run( &cursor, TRUE ))
return cursor.run;
return NULL;
}
ME_Run *run_prev_all_paras( ME_Run *run )
{
ME_Cursor cursor;
cursor.run = run;
cursor.para = run->para;
cursor.nOffset = 0;
if (cursor_prev_run( &cursor, TRUE ))
return cursor.run;
return NULL;
}
/******************************************************************************
* ME_CanJoinRuns
*
@@ -43,54 +137,32 @@ BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2)
return TRUE;
}
void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift)
{
p = ME_FindItemFwd(p, diRunOrParagraphOrEnd);
assert(p);
ME_PropagateCharOffset(p, shift);
}
/******************************************************************************
* ME_PropagateCharOffsets
* editor_propagate_char_ofs
*
* Shifts (increases or decreases) character offset (relative to beginning of
* the document) of the part of the text starting from given place.
* Call with only one of para or run non-NULL.
*/
void ME_PropagateCharOffset(ME_DisplayItem *p, int shift)
void editor_propagate_char_ofs( ME_Paragraph *para, ME_Run *run, int shift )
{
/* Runs in one paragraph contain character offset relative to their owning
* paragraph. If we start the shifting from the run, we need to shift
* all the relative offsets until the end of the paragraph
*/
if (p->type == diRun) /* propagate in all runs in this para */
{
TRACE("PropagateCharOffset(%s, %d)\n", debugstr_run( &p->member.run ), shift);
do {
p->member.run.nCharOfs += shift;
assert(p->member.run.nCharOfs >= 0);
p = ME_FindItemFwd(p, diRunOrParagraphOrEnd);
} while(p->type == diRun);
}
/* Runs in next paragraphs don't need their offsets updated, because they,
* again, those offsets are relative to their respective paragraphs.
* Instead of that, we're updating paragraphs' character offsets.
*/
if (p->type == diParagraph) /* propagate in all next paras */
{
do {
p->member.para.nCharOfs += shift;
assert(p->member.para.nCharOfs >= 0);
p = p->member.para.next_para;
} while(p->type == diParagraph);
}
/* diTextEnd also has character offset in it, which makes finding text length
* easier. But it needs to be up to date first.
*/
if (p->type == diTextEnd)
{
p->member.para.nCharOfs += shift;
assert(p->member.para.nCharOfs >= 0);
}
assert( !para ^ !run );
if (run)
{
para = para_next( run->para );
do
{
run->nCharOfs += shift;
run = run_next( run );
} while (run);
}
do
{
para->nCharOfs += shift;
para = para_next( para );
} while (para);
}
/******************************************************************************
@@ -147,231 +219,208 @@ void ME_CheckCharOffsets(ME_TextEditor *editor)
}
/******************************************************************************
* ME_CharOfsFromRunOfs
* run_char_ofs
*
* Converts a character position relative to the start of the run, to a
* Converts a character position relative to the start of the run to a
* character position relative to the start of the document.
* Kind of a "local to global" offset conversion.
*/
int ME_CharOfsFromRunOfs(ME_TextEditor *editor, const ME_DisplayItem *pPara,
const ME_DisplayItem *pRun, int nOfs)
int run_char_ofs( ME_Run *run, int ofs )
{
assert(pRun && pRun->type == diRun);
assert(pPara && pPara->type == diParagraph);
return pPara->member.para.nCharOfs + pRun->member.run.nCharOfs + nOfs;
return run->para->nCharOfs + run->nCharOfs + ofs;
}
/******************************************************************************
* ME_CursorFromCharOfs
* cursor_from_char_ofs
*
* Converts a character offset (relative to the start of the document) to
* a cursor structure (which contains a run and a position relative to that
* run).
*/
void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor)
void cursor_from_char_ofs( ME_TextEditor *editor, int char_ofs, ME_Cursor *cursor )
{
ME_RunOfsFromCharOfs(editor, nCharOfs, &pCursor->pPara,
&pCursor->pRun, &pCursor->nOffset);
ME_Paragraph *para;
ME_Run *run;
char_ofs = min( max( char_ofs, 0 ), ME_GetTextLength( editor ) );
/* Find the paragraph at the offset. */
for (para = editor_first_para( editor );
para_next( para )->nCharOfs <= char_ofs;
para = para_next( para ))
;
char_ofs -= para->nCharOfs;
/* Find the run at the offset. */
for (run = para_first_run( para );
run_next( run ) && run_next( run )->nCharOfs <= char_ofs;
run = run_next( run ))
;
char_ofs -= run->nCharOfs;
cursor->para = para;
cursor->run = run;
cursor->nOffset = char_ofs;
}
/******************************************************************************
* ME_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. */
next_item = editor->pBuffer->pFirst->member.para.next_para;
do {
item = next_item;
next_item = item->member.para.next_para;
} while (next_item->member.para.nCharOfs <= nCharOfs);
assert(item->type == diParagraph);
nCharOfs -= item->member.para.nCharOfs;
if (ppPara) *ppPara = item;
/* Find the run at the offset. */
next_item = ME_FindItemFwd(item, diRun);
do {
item = next_item;
next_item = ME_FindItemFwd(item, diRunOrParagraphOrEnd);
} while (next_item->type == diRun &&
next_item->member.run.nCharOfs <= nCharOfs);
assert(item->type == diRun);
nCharOfs -= item->member.run.nCharOfs;
if (ppRun) *ppRun = item;
if (pOfs) {
if (((*ppRun)->member.run.nFlags & MERF_ENDPARA) && endOfs > len)
*pOfs = (*ppRun)->member.run.len;
else *pOfs = nCharOfs;
}
}
/******************************************************************************
* ME_JoinRuns
* run_join
*
* Merges two adjacent runs, the one given as a parameter and the next one.
*/
void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p)
void run_join( ME_TextEditor *editor, ME_Run *run )
{
ME_DisplayItem *pNext = p->next;
ME_Run *next = run_next( run );
int i;
assert(p->type == diRun && pNext->type == diRun);
assert(p->member.run.nCharOfs != -1);
mark_para_rewrap(editor, ME_GetParagraph(p));
assert( run );
assert( run->nCharOfs != -1 );
para_mark_rewrap( editor, run->para );
/* Update all cursors so that they don't contain the soon deleted run */
for (i=0; i<editor->nCursors; i++) {
if (editor->pCursors[i].pRun == pNext) {
editor->pCursors[i].pRun = p;
editor->pCursors[i].nOffset += p->member.run.len;
for (i = 0; i < editor->nCursors; i++)
{
if (editor->pCursors[i].run == next)
{
editor->pCursors[i].run = run;
editor->pCursors[i].nOffset += run->len;
}
}
p->member.run.len += pNext->member.run.len;
ME_Remove(pNext);
ME_DestroyDisplayItem(pNext);
ME_UpdateRunFlags(editor, &p->member.run);
ME_CheckCharOffsets(editor);
run->len += next->len;
ME_Remove( run_get_di( next ) );
ME_DestroyDisplayItem( run_get_di( next ) );
ME_UpdateRunFlags( editor, run );
ME_CheckCharOffsets( editor );
}
/******************************************************************************
* ME_SplitRunSimple
* run_split
*
* Does the most basic job of splitting a run into two - it does not
* update the positions and extents.
*/
ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_Cursor *cursor)
ME_Run *run_split( ME_TextEditor *editor, ME_Cursor *cursor )
{
ME_DisplayItem *run = cursor->pRun;
ME_DisplayItem *new_run;
int i;
int nOffset = cursor->nOffset;
ME_Run *run = cursor->run, *new_run;
int i;
int nOffset = cursor->nOffset;
assert(!(run->member.run.nFlags & MERF_NONTEXT));
assert( !(run->nFlags & MERF_NONTEXT) );
new_run = ME_MakeRun(run->member.run.style,
run->member.run.nFlags & MERF_SPLITMASK);
new_run->member.run.nCharOfs = run->member.run.nCharOfs + nOffset;
new_run->member.run.len = run->member.run.len - nOffset;
new_run->member.run.para = run->member.run.para;
run->member.run.len = nOffset;
cursor->pRun = new_run;
cursor->nOffset = 0;
new_run = run_create( run->style, run->nFlags & MERF_SPLITMASK );
new_run->nCharOfs = run->nCharOfs + nOffset;
new_run->len = run->len - nOffset;
new_run->para = run->para;
run->len = nOffset;
cursor->run = new_run;
cursor->nOffset = 0;
ME_InsertBefore(run->next, new_run);
ME_InsertBefore( run_get_di( run )->next, run_get_di( new_run ) );
ME_UpdateRunFlags(editor, &run->member.run);
ME_UpdateRunFlags(editor, &new_run->member.run);
for (i = 0; i < editor->nCursors; i++) {
if (editor->pCursors[i].pRun == run &&
editor->pCursors[i].nOffset >= nOffset) {
editor->pCursors[i].pRun = new_run;
editor->pCursors[i].nOffset -= nOffset;
ME_UpdateRunFlags( editor, run );
ME_UpdateRunFlags( editor, new_run );
for (i = 0; i < editor->nCursors; i++)
{
if (editor->pCursors[i].run == run &&
editor->pCursors[i].nOffset >= nOffset)
{
editor->pCursors[i].run = new_run;
editor->pCursors[i].nOffset -= nOffset;
}
}
}
mark_para_rewrap(editor, cursor->pPara);
return run;
para_mark_rewrap( editor, run->para );
return run;
}
/******************************************************************************
* ME_MakeRun
* run_create
*
* A helper function to create run structures quickly.
*/
ME_DisplayItem *ME_MakeRun(ME_Style *s, int nFlags)
ME_Run *run_create( ME_Style *s, int flags )
{
ME_DisplayItem *item = ME_MakeDI(diRun);
item->member.run.style = s;
item->member.run.reobj = NULL;
item->member.run.nFlags = nFlags;
item->member.run.nCharOfs = -1;
item->member.run.len = 0;
item->member.run.para = NULL;
item->member.run.num_glyphs = 0;
item->member.run.max_glyphs = 0;
item->member.run.glyphs = NULL;
item->member.run.vis_attrs = NULL;
item->member.run.advances = NULL;
item->member.run.offsets = NULL;
item->member.run.max_clusters = 0;
item->member.run.clusters = NULL;
ME_AddRefStyle(s);
return item;
ME_DisplayItem *item = ME_MakeDI( diRun );
ME_Run *run = &item->member.run;
if (!item) return NULL;
ME_AddRefStyle( s );
run->style = s;
run->reobj = NULL;
run->nFlags = flags;
run->nCharOfs = -1;
run->len = 0;
run->para = NULL;
run->num_glyphs = 0;
run->max_glyphs = 0;
run->glyphs = NULL;
run->vis_attrs = NULL;
run->advances = NULL;
run->offsets = NULL;
run->max_clusters = 0;
run->clusters = NULL;
return run;
}
/******************************************************************************
* ME_InsertRunAtCursor
* run_insert
*
* Inserts a new run with given style, flags and content at a given position,
* which is passed as a cursor structure (which consists of a run and
* a run-relative character offset).
*/
ME_DisplayItem *
ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style,
const WCHAR *str, int len, int flags)
ME_Run *run_insert( ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style,
const WCHAR *str, int len, int flags )
{
ME_DisplayItem *pDI, *insert_before = cursor->pRun, *prev;
ME_Run *insert_before = cursor->run, *run, *prev;
if (cursor->nOffset)
{
if (cursor->nOffset == cursor->pRun->member.run.len)
if (cursor->nOffset == insert_before->len)
{
insert_before = ME_FindItemFwd( cursor->pRun, diRun );
if (!insert_before) insert_before = cursor->pRun; /* Always insert before the final eop run */
insert_before = run_next_all_paras( insert_before );
if (!insert_before) insert_before = cursor->run; /* Always insert before the final eop run */
}
else
{
ME_SplitRunSimple( editor, cursor );
insert_before = cursor->pRun;
run_split( editor, cursor );
insert_before = cursor->run;
}
}
add_undo_delete_run( editor, insert_before->member.run.para->nCharOfs +
insert_before->member.run.nCharOfs, len );
add_undo_delete_run( editor, insert_before->para->nCharOfs + insert_before->nCharOfs, len );
pDI = ME_MakeRun(style, flags);
pDI->member.run.nCharOfs = insert_before->member.run.nCharOfs;
pDI->member.run.len = len;
pDI->member.run.para = insert_before->member.run.para;
ME_InsertString( pDI->member.run.para->text, pDI->member.run.nCharOfs, str, len );
ME_InsertBefore( insert_before, pDI );
run = run_create( style, flags );
run->nCharOfs = insert_before->nCharOfs;
run->len = len;
run->para = insert_before->para;
ME_InsertString( run->para->text, run->nCharOfs, str, len );
ME_InsertBefore( run_get_di( insert_before ), run_get_di( run ) );
TRACE("Shift length:%d\n", len);
ME_PropagateCharOffset( insert_before, len );
mark_para_rewrap(editor, get_di_from_para(insert_before->member.run.para));
editor_propagate_char_ofs( NULL, insert_before, len );
para_mark_rewrap( editor, insert_before->para );
/* Move any cursors that were at the end of the previous run to the end of the inserted run */
prev = ME_FindItemBack( pDI, diRun );
prev = run_prev_all_paras( run );
if (prev)
{
int i;
for (i = 0; i < editor->nCursors; i++)
{
if (editor->pCursors[i].pRun == prev &&
editor->pCursors[i].nOffset == prev->member.run.len)
if (editor->pCursors[i].run == prev &&
editor->pCursors[i].nOffset == prev->len)
{
editor->pCursors[i].pRun = pDI;
editor->pCursors[i].run = run;
editor->pCursors[i].nOffset = len;
}
}
}
return pDI;
return run;
}
static BOOL run_is_splittable( const ME_Run *run )
@@ -494,9 +543,9 @@ int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BO
return closest ? cp + trailing : cp;
}
if (c->editor->cPasswordMask)
if (c->editor->password_char)
{
mask_text = ME_MakeStringR( c->editor->cPasswordMask, run->len );
mask_text = ME_MakeStringR( c->editor->password_char, run->len );
str = mask_text->szData;
}
else
@@ -522,10 +571,12 @@ int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, B
{
ME_Context c;
int ret;
HDC hdc = ITextHost_TxGetDC( editor->texthost );
ME_InitContext( &c, editor, ITextHost_TxGetDC( editor->texthost ) );
ME_InitContext( &c, editor, hdc );
ret = ME_CharFromPointContext( &c, cx, run, closest, visual_order );
ME_DestroyContext(&c);
ITextHost_TxReleaseDC( editor->texthost, hdc );
return ret;
}
@@ -577,9 +628,9 @@ int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visua
if (visual_order && pRun->script_analysis.fRTL) x = pRun->nWidth - x - 1;
return x;
}
if (c->editor->cPasswordMask)
if (c->editor->password_char)
{
mask_text = ME_MakeStringR(c->editor->cPasswordMask, pRun->len);
mask_text = ME_MakeStringR( c->editor->password_char, pRun->len );
str = mask_text->szData;
}
else
@@ -599,10 +650,12 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visu
{
ME_Context c;
int ret;
HDC hdc = ITextHost_TxGetDC( editor->texthost );
ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
ME_InitContext( &c, editor, hdc );
ret = ME_PointFromCharContext( &c, pRun, nOffset, visual_order );
ME_DestroyContext(&c);
ITextHost_TxReleaseDC( editor->texthost, hdc );
return ret;
}
@@ -616,7 +669,6 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visu
SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, int nLen,
int startx, int *pAscent, int *pDescent)
{
static const WCHAR spaceW[] = {' ',0};
SIZE size;
nLen = min( nLen, run->len );
@@ -624,15 +676,15 @@ SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, i
if (run->nFlags & MERF_ENDPARA)
{
nLen = min( nLen, 1 );
ME_GetTextExtent(c, spaceW, nLen, run->style, &size);
ME_GetTextExtent( c, L" ", nLen, run->style, &size );
}
else if (para->nFlags & MEPF_COMPLEX)
{
size.cx = run->nWidth;
}
else if (c->editor->cPasswordMask)
else if (c->editor->password_char)
{
ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,nLen);
ME_String *szMasked = ME_MakeStringR( c->editor->password_char, nLen );
ME_GetTextExtent(c, szMasked->szData, nLen,run->style, &size);
ME_DestroyString(szMasked);
}
@@ -699,7 +751,7 @@ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
{
ME_Style *s;
if (!editor->pBuffer->pCharStyle)
editor->pBuffer->pCharStyle = ME_GetInsertStyle(editor, 0);
editor->pBuffer->pCharStyle = style_get_insert_style( editor, editor->pCursors );
s = ME_ApplyStyle(editor, editor->pBuffer->pCharStyle, pFmt);
ME_ReleaseStyle(editor->pBuffer->pCharStyle);
editor->pBuffer->pCharStyle = s;
@@ -722,63 +774,63 @@ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
*
* If no text is selected, then nothing is done.
*/
void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *pFmt)
void ME_SetCharFormat( ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *fmt )
{
ME_DisplayItem *run, *start_run = start->pRun, *end_run = NULL;
ME_Run *run, *start_run = start->run, *end_run = NULL;
if (end && start->pRun == end->pRun && start->nOffset == end->nOffset)
if (end && start->run == end->run && start->nOffset == end->nOffset)
return;
if (start->nOffset == start->pRun->member.run.len)
start_run = ME_FindItemFwd( start->pRun, diRun );
if (start->nOffset == start->run->len)
start_run = run_next_all_paras( start->run );
else if (start->nOffset)
{
/* SplitRunSimple may or may not update the cursors, depending on whether they
/* run_split() may or may not update the cursors, depending on whether they
* are selection cursors, but we need to make sure they are valid. */
int split_offset = start->nOffset;
ME_DisplayItem *split_run = ME_SplitRunSimple(editor, start);
start_run = start->pRun;
if (end && end->pRun == split_run)
ME_Run *split_run = run_split( editor, start );
start_run = start->run;
if (end && end->run == split_run)
{
end->pRun = start->pRun;
end->run = start->run;
end->nOffset -= split_offset;
}
}
if (end)
{
if (end->nOffset == end->pRun->member.run.len)
end_run = ME_FindItemFwd( end->pRun, diRun );
if (end->nOffset == end->run->len)
end_run = run_next_all_paras( end->run );
else
{
if (end->nOffset) ME_SplitRunSimple(editor, end);
end_run = end->pRun;
if (end->nOffset) run_split( editor, end );
end_run = end->run;
}
}
for (run = start_run; run != end_run; run = ME_FindItemFwd( run, diRun ))
for (run = start_run; run != end_run; run = run_next_all_paras( run ))
{
ME_Style *new_style = ME_ApplyStyle(editor, run->member.run.style, pFmt);
ME_Paragraph *para = run->member.run.para;
ME_Style *new_style = ME_ApplyStyle( editor, run->style, fmt );
ME_Paragraph *para = run->para;
add_undo_set_char_fmt( editor, run->member.run.para->nCharOfs + run->member.run.nCharOfs,
run->member.run.len, &run->member.run.style->fmt );
ME_ReleaseStyle(run->member.run.style);
run->member.run.style = new_style;
add_undo_set_char_fmt( editor, para->nCharOfs + run->nCharOfs,
run->len, &run->style->fmt );
ME_ReleaseStyle( run->style );
run->style = new_style;
/* The para numbering style depends on the eop style */
if ((run->member.run.nFlags & MERF_ENDPARA) && para->para_num.style)
if ((run->nFlags & MERF_ENDPARA) && para->para_num.style)
{
ME_ReleaseStyle(para->para_num.style);
para->para_num.style = NULL;
}
mark_para_rewrap(editor, get_di_from_para(para));
para_mark_rewrap( editor, para );
}
}
static void ME_GetRunCharFormat(ME_TextEditor *editor, ME_DisplayItem *run, CHARFORMAT2W *pFmt)
static void run_copy_char_fmt( ME_Run *run, CHARFORMAT2W *fmt )
{
ME_CopyCharFormat(pFmt, &run->member.run.style->fmt);
ME_CopyCharFormat( fmt, &run->style->fmt );
}
/******************************************************************************
@@ -816,33 +868,25 @@ void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
* Returns the style consisting of those attributes which are consistently set
* in the whole character range.
*/
void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from,
const ME_Cursor *to, CHARFORMAT2W *pFmt)
void ME_GetCharFormat( ME_TextEditor *editor, const ME_Cursor *from,
const ME_Cursor *to, CHARFORMAT2W *fmt )
{
ME_DisplayItem *run, *run_end;
ME_Run *run, *run_end, *prev_run;
CHARFORMAT2W tmp;
run = from->pRun;
run = from->run;
/* special case - if selection is empty, take previous char's formatting */
if (from->pRun == to->pRun && from->nOffset == to->nOffset)
if (from->run == to->run && from->nOffset == to->nOffset)
{
if (!from->nOffset)
{
ME_DisplayItem *tmp_run = ME_FindItemBack(run, diRunOrParagraph);
if (tmp_run->type == diRun) {
ME_GetRunCharFormat(editor, tmp_run, pFmt);
return;
}
}
ME_GetRunCharFormat(editor, run, pFmt);
if (!from->nOffset && (prev_run = run_prev( run ))) run = prev_run;
run_copy_char_fmt( run, fmt );
return;
}
run_end = to->pRun;
if (!to->nOffset)
run_end = ME_FindItemBack(run_end, diRun);
run_end = to->run;
if (!to->nOffset) run_end = run_prev_all_paras( run_end );
ME_GetRunCharFormat(editor, run, pFmt);
run_copy_char_fmt( run, fmt );
if (run == run_end) return;
@@ -851,40 +895,37 @@ void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from,
DWORD dwAttribs = CFM_SIZE | CFM_FACE | CFM_COLOR | CFM_UNDERLINETYPE;
DWORD dwEffects = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_STRIKEOUT | CFM_PROTECTED | CFM_LINK | CFM_SUPERSCRIPT;
run = ME_FindItemFwd(run, diRun);
run = run_next_all_paras( run );
ZeroMemory(&tmp, sizeof(tmp));
memset( &tmp, 0, sizeof(tmp) );
tmp.cbSize = sizeof(tmp);
ME_GetRunCharFormat(editor, run, &tmp);
run_copy_char_fmt( run, &tmp );
assert((tmp.dwMask & dwAttribs) == dwAttribs);
/* reset flags that differ */
if (pFmt->yHeight != tmp.yHeight)
pFmt->dwMask &= ~CFM_SIZE;
if (pFmt->dwMask & CFM_FACE)
if (fmt->yHeight != tmp.yHeight) fmt->dwMask &= ~CFM_SIZE;
if (fmt->dwMask & CFM_FACE)
{
if (!(tmp.dwMask & CFM_FACE))
pFmt->dwMask &= ~CFM_FACE;
else if (wcscmp(pFmt->szFaceName, tmp.szFaceName) ||
pFmt->bPitchAndFamily != tmp.bPitchAndFamily)
pFmt->dwMask &= ~CFM_FACE;
fmt->dwMask &= ~CFM_FACE;
else if (wcscmp( fmt->szFaceName, tmp.szFaceName ) ||
fmt->bPitchAndFamily != tmp.bPitchAndFamily)
fmt->dwMask &= ~CFM_FACE;
}
if (pFmt->yHeight != tmp.yHeight)
pFmt->dwMask &= ~CFM_SIZE;
if (pFmt->bUnderlineType != tmp.bUnderlineType)
pFmt->dwMask &= ~CFM_UNDERLINETYPE;
if (pFmt->dwMask & CFM_COLOR)
if (fmt->yHeight != tmp.yHeight) fmt->dwMask &= ~CFM_SIZE;
if (fmt->bUnderlineType != tmp.bUnderlineType) fmt->dwMask &= ~CFM_UNDERLINETYPE;
if (fmt->dwMask & CFM_COLOR)
{
if (!((pFmt->dwEffects&CFE_AUTOCOLOR) & (tmp.dwEffects&CFE_AUTOCOLOR)))
if (!((fmt->dwEffects&CFE_AUTOCOLOR) & (tmp.dwEffects&CFE_AUTOCOLOR)))
{
if (pFmt->crTextColor != tmp.crTextColor)
pFmt->dwMask &= ~CFM_COLOR;
if (fmt->crTextColor != tmp.crTextColor)
fmt->dwMask &= ~CFM_COLOR;
}
}
pFmt->dwMask &= ~((pFmt->dwEffects ^ tmp.dwEffects) & dwEffects);
pFmt->dwEffects = tmp.dwEffects;
fmt->dwMask &= ~((fmt->dwEffects ^ tmp.dwEffects) & dwEffects);
fmt->dwEffects = tmp.dwEffects;
} while(run != run_end);
}

View File

@@ -429,7 +429,7 @@ void select_style( ME_Context *c, ME_Style *s )
c->orig_font = NULL;
}
if (c->current_style && c->current_style->font_cache)
if (c->current_style)
{
release_font_cache( c->current_style->font_cache );
c->current_style->font_cache = NULL;
@@ -473,42 +473,26 @@ void ME_ReleaseStyle(ME_Style *s)
ME_DestroyStyle(s);
}
ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor)
ME_Style *style_get_insert_style( ME_TextEditor *editor, ME_Cursor *cursor )
{
if (ME_IsSelection(editor))
{
ME_Style *style;
ME_Cursor *from, *to;
ME_Run *prev;
ME_GetSelection(editor, &from, &to);
ME_AddRefStyle(from->pRun->member.run.style);
return from->pRun->member.run.style;
}
if (editor->pBuffer->pCharStyle) {
ME_AddRefStyle(editor->pBuffer->pCharStyle);
return editor->pBuffer->pCharStyle;
}
else
{
ME_Cursor *pCursor = &editor->pCursors[nCursor];
ME_DisplayItem *pRunItem = pCursor->pRun;
ME_DisplayItem *pPrevItem = NULL;
if (pCursor->nOffset) {
ME_Run *pRun = &pRunItem->member.run;
ME_AddRefStyle(pRun->style);
return pRun->style;
}
pPrevItem = ME_FindItemBack(pRunItem, diRunOrParagraph);
if (pPrevItem->type == diRun)
if (ME_IsSelection( editor ))
{
ME_AddRefStyle(pPrevItem->member.run.style);
return pPrevItem->member.run.style;
ME_GetSelection( editor, &from, &to );
style = from->run->style;
}
else if (editor->pBuffer->pCharStyle)
style = editor->pBuffer->pCharStyle;
else if (!cursor->nOffset && (prev = run_prev( cursor->run )))
style = prev->style;
else
{
ME_AddRefStyle(pRunItem->member.run.style);
return pRunItem->member.run.style;
}
}
style = cursor->run->style;
ME_AddRefStyle( style );
return style;
}
void ME_SaveTempStyle(ME_TextEditor *editor, ME_Style *style)
@@ -552,5 +536,5 @@ void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod)
}
ScriptFreeCache( &def->script_cache );
ME_ReleaseStyle( style );
ME_MarkAllForWrapping( editor );
editor_mark_rewrap_all( editor );
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -27,79 +27,64 @@
#include "tom.h"
#include "imm.h"
#include "textserv.h"
#include "wine/asm.h"
#include "wine/debug.h"
#include "editstr.h"
#include "riched20.h"
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
typedef struct ITextServicesImpl {
IUnknown IUnknown_inner;
ITextServices ITextServices_iface;
IUnknown *outer_unk;
LONG ref;
ITextHost *pMyHost;
CRITICAL_SECTION csTxtSrv;
ME_TextEditor *editor;
char spare[256];
} ITextServicesImpl;
static inline ITextServicesImpl *impl_from_IUnknown(IUnknown *iface)
static inline struct text_services *impl_from_IUnknown( IUnknown *iface )
{
return CONTAINING_RECORD(iface, ITextServicesImpl, IUnknown_inner);
return CONTAINING_RECORD( iface, struct text_services, IUnknown_inner );
}
static HRESULT WINAPI ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
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))
*ppv = &This->IUnknown_inner;
else if (IsEqualIID(riid, &IID_ITextServices))
*ppv = &This->ITextServices_iface;
else if (IsEqualIID(riid, &IID_IRichEditOle) || IsEqualIID(riid, &IID_ITextDocument) ||
IsEqualIID(riid, &IID_ITextDocument2Old)) {
if (!This->editor->reOle)
if (!CreateIRichEditOle(This->outer_unk, This->editor, (void **)(&This->editor->reOle)))
return E_OUTOFMEMORY;
return IUnknown_QueryInterface(This->editor->reOle, riid, ppv);
} else {
*ppv = NULL;
FIXME("Unknown interface: %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
if (IsEqualIID( iid, &IID_IUnknown )) *obj = &services->IUnknown_inner;
else if (IsEqualIID( iid, &IID_ITextServices )) *obj = &services->ITextServices_iface;
else if (IsEqualIID( iid, &IID_IRichEditOle )) *obj= &services->IRichEditOle_iface;
else if (IsEqualIID( iid, &IID_IDispatch ) ||
IsEqualIID( iid, &IID_ITextDocument ) ||
IsEqualIID( iid, &IID_ITextDocument2Old )) *obj = &services->ITextDocument2Old_iface;
else
{
*obj = NULL;
FIXME( "Unknown interface: %s\n", debugstr_guid( iid ) );
return E_NOINTERFACE;
}
IUnknown_AddRef((IUnknown*)*ppv);
return S_OK;
IUnknown_AddRef( (IUnknown *)*obj );
return S_OK;
}
static ULONG WINAPI ITextServicesImpl_AddRef(IUnknown *iface)
{
ITextServicesImpl *This = impl_from_IUnknown(iface);
LONG ref = InterlockedIncrement(&This->ref);
struct text_services *services = impl_from_IUnknown( iface );
LONG ref = InterlockedIncrement( &services->ref );
TRACE("(%p) ref=%d\n", This, ref);
TRACE( "(%p) ref = %d\n", services, ref );
return ref;
return ref;
}
static ULONG WINAPI ITextServicesImpl_Release(IUnknown *iface)
{
ITextServicesImpl *This = impl_from_IUnknown(iface);
LONG ref = InterlockedDecrement(&This->ref);
struct text_services *services = impl_from_IUnknown( iface );
LONG ref = InterlockedDecrement( &services->ref );
TRACE("(%p) ref=%d\n", This, ref);
TRACE( "(%p) ref = %d\n", services, ref );
if (!ref)
{
ME_DestroyEditor(This->editor);
This->csTxtSrv.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->csTxtSrv);
CoTaskMemFree(This);
}
return ref;
if (!ref)
{
richole_release_children( services );
ME_DestroyEditor( services->editor );
CoTaskMemFree( services );
}
return ref;
}
static const IUnknownVtbl textservices_inner_vtbl =
@@ -109,306 +94,518 @@ static const IUnknownVtbl textservices_inner_vtbl =
ITextServicesImpl_Release
};
static inline ITextServicesImpl *impl_from_ITextServices(ITextServices *iface)
static inline struct text_services *impl_from_ITextServices( ITextServices *iface )
{
return CONTAINING_RECORD(iface, ITextServicesImpl, ITextServices_iface);
return CONTAINING_RECORD( iface, struct text_services, ITextServices_iface );
}
static HRESULT WINAPI fnTextSrv_QueryInterface(ITextServices *iface, REFIID riid, void **ppv)
static HRESULT WINAPI fnTextSrv_QueryInterface( ITextServices *iface, REFIID iid, void **obj )
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
struct text_services *services = impl_from_ITextServices( iface );
return IUnknown_QueryInterface( services->outer_unk, iid, obj );
}
static ULONG WINAPI fnTextSrv_AddRef(ITextServices *iface)
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
return IUnknown_AddRef(This->outer_unk);
struct text_services *services = impl_from_ITextServices( iface );
return IUnknown_AddRef( services->outer_unk );
}
static ULONG WINAPI fnTextSrv_Release(ITextServices *iface)
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
return IUnknown_Release(This->outer_unk);
struct text_services *services = impl_from_ITextServices( iface );
return IUnknown_Release( services->outer_unk );
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSendMessage(ITextServices *iface, UINT msg, WPARAM wparam,
LPARAM lparam, LRESULT *plresult)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage,20)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSendMessage( ITextServices *iface, UINT msg, WPARAM wparam,
LPARAM lparam, LRESULT *result )
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
HRESULT hresult;
LRESULT lresult;
struct text_services *services = impl_from_ITextServices( iface );
HRESULT hr;
LRESULT res;
lresult = ME_HandleMessage(This->editor, msg, wparam, lparam, TRUE, &hresult);
if (plresult) *plresult = lresult;
return hresult;
res = editor_handle_message( services->editor, msg, wparam, lparam, &hr );
if (result) *result = res;
return hr;
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxDraw(ITextServices *iface, DWORD dwDrawAspect, LONG lindex,
void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, HDC hdcTargetDev,
LPCRECTL lprcBounds, LPCRECTL lprcWBounds, LPRECT lprcUpdate,
BOOL (CALLBACK * pfnContinue)(DWORD), DWORD dwContinue,
LONG lViewId)
static HRESULT update_client_rect( struct text_services *services, const RECT *client )
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
RECT rect;
HRESULT hr;
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
if (!client)
{
if (!services->editor->in_place_active) return E_INVALIDARG;
hr = ITextHost_TxGetClientRect( services->editor->texthost, &rect );
if (FAILED( hr )) return hr;
}
else rect = *client;
rect.left += services->editor->selofs;
if (EqualRect( &rect, &services->editor->rcFormat )) return S_FALSE;
services->editor->rcFormat = rect;
return S_OK;
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetHScroll(ITextServices *iface, LONG *plMin, LONG *plMax, LONG *plPos,
LONG *plPage, BOOL *pfEnabled)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxDraw( ITextServices *iface, DWORD aspect, LONG index, void *aspect_info,
DVTARGETDEVICE *td, HDC draw, HDC target,
const RECTL *bounds, const RECTL *mf_bounds, RECT *update,
BOOL (CALLBACK *continue_fn)(DWORD), DWORD continue_param,
LONG view_id )
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
HRESULT hr;
HDC dc = draw;
BOOL rewrap = FALSE;
if (plMin)
*plMin = This->editor->horz_si.nMin;
if (plMax)
*plMax = This->editor->horz_si.nMax;
if (plPos)
*plPos = This->editor->horz_si.nPos;
if (plPage)
*plPage = This->editor->horz_si.nPage;
if (pfEnabled)
*pfEnabled = (This->editor->styleFlags & WS_HSCROLL) != 0;
return S_OK;
TRACE( "%p: aspect %d, %d, %p, %p, draw %p, target %p, bounds %s, mf_bounds %s, update %s, %p, %d, view %d\n",
services, aspect, index, aspect_info, td, draw, target, wine_dbgstr_rect( (RECT *)bounds ),
wine_dbgstr_rect( (RECT *)mf_bounds ), wine_dbgstr_rect( update ), continue_fn, continue_param, view_id );
if (aspect != DVASPECT_CONTENT || aspect_info || td || target || mf_bounds || continue_fn )
FIXME( "Many arguments are ignored\n" );
hr = update_client_rect( services, (RECT *)bounds );
if (FAILED( hr )) return hr;
if (hr == S_OK) rewrap = TRUE;
if (!dc && services->editor->in_place_active)
dc = ITextHost_TxGetDC( services->editor->texthost );
if (!dc) return E_FAIL;
if (rewrap)
{
editor_mark_rewrap_all( services->editor );
wrap_marked_paras_dc( services->editor, dc, FALSE );
}
if (!services->editor->bEmulateVersion10 || services->editor->nEventMask & ENM_UPDATE)
ITextHost_TxNotify( services->editor->texthost, EN_UPDATE, NULL );
editor_draw( services->editor, dc, update );
if (!draw) ITextHost_TxReleaseDC( services->editor->texthost, dc );
return S_OK;
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetVScroll(ITextServices *iface, LONG *plMin, LONG *plMax, LONG *plPos,
LONG *plPage, BOOL *pfEnabled)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetHScroll( ITextServices *iface, LONG *min_pos, LONG *max_pos, LONG *pos,
LONG *page, BOOL *enabled )
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
if (plMin)
*plMin = This->editor->vert_si.nMin;
if (plMax)
*plMax = This->editor->vert_si.nMax;
if (plPos)
*plPos = This->editor->vert_si.nPos;
if (plPage)
*plPage = This->editor->vert_si.nPage;
if (pfEnabled)
*pfEnabled = (This->editor->styleFlags & WS_VSCROLL) != 0;
return S_OK;
if (min_pos) *min_pos = services->editor->horz_si.nMin;
if (max_pos) *max_pos = services->editor->horz_si.nMax;
if (pos) *pos = services->editor->horz_si.nPos;
if (page) *page = services->editor->horz_si.nPage;
if (enabled) *enabled = services->editor->horz_sb_enabled;
return S_OK;
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxSetCursor(ITextServices *iface, DWORD dwDrawAspect, LONG lindex,
void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw,
HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll,24)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetVScroll( ITextServices *iface, LONG *min_pos, LONG *max_pos, LONG *pos,
LONG *page, BOOL *enabled )
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
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,
void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw,
HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y,
DWORD *pHitResult)
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
FIXME( "%p: STUB\n", services );
return E_NOTIMPL;
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInplaceActivate(ITextServices *iface, LPCRECT prcClient)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInPlaceActivate,8)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInPlaceActivate( ITextServices *iface, const RECT *client )
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
HRESULT hr;
BOOL old_active = services->editor->in_place_active;
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
TRACE( "%p: %s\n", services, wine_dbgstr_rect( client ) );
services->editor->in_place_active = TRUE;
hr = update_client_rect( services, client );
if (FAILED( hr ))
{
services->editor->in_place_active = old_active;
return hr;
}
ME_RewrapRepaint( services->editor );
return S_OK;
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInplaceDeactivate(ITextServices *iface)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInPlaceDeactivate,4)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxInPlaceDeactivate(ITextServices *iface)
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
TRACE( "%p\n", services );
services->editor->in_place_active = FALSE;
return S_OK;
}
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxUIActivate(ITextServices *iface)
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
FIXME( "%p: STUB\n", services );
return E_NOTIMPL;
}
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxUIDeactivate(ITextServices *iface)
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
FIXME( "%p: STUB\n", services );
return E_NOTIMPL;
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetText(ITextServices *iface, BSTR *pbstrText)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetText( ITextServices *iface, BSTR *text )
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
int length;
struct text_services *services = impl_from_ITextServices( iface );
int length;
length = ME_GetTextLength(This->editor);
if (length)
{
ME_Cursor start;
BSTR bstr;
bstr = SysAllocStringByteLen(NULL, length * sizeof(WCHAR));
if (bstr == NULL)
return E_OUTOFMEMORY;
length = ME_GetTextLength( services->editor );
if (length)
{
ME_Cursor start;
BSTR bstr;
bstr = SysAllocStringByteLen( NULL, length * sizeof(WCHAR) );
if (bstr == NULL) return E_OUTOFMEMORY;
ME_CursorFromCharOfs(This->editor, 0, &start);
ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE, FALSE);
*pbstrText = bstr;
} else {
*pbstrText = NULL;
}
cursor_from_char_ofs( services->editor, 0, &start );
ME_GetTextW( services->editor, bstr, length, &start, INT_MAX, FALSE, FALSE );
*text = bstr;
}
else *text = NULL;
return S_OK;
return S_OK;
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSetText(ITextServices *iface, LPCWSTR pszText)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxSetText( ITextServices *iface, const WCHAR *text )
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
ME_Cursor cursor;
struct text_services *services = impl_from_ITextServices( iface );
ME_Cursor cursor;
ME_SetCursorToStart(This->editor, &cursor);
ME_InternalDeleteText(This->editor, &cursor, ME_GetTextLength(This->editor), FALSE);
if(pszText)
ME_InsertTextFromCursor(This->editor, 0, pszText, -1, This->editor->pBuffer->pDefaultStyle);
set_selection_cursors(This->editor, 0, 0);
This->editor->nModifyStep = 0;
OleFlushClipboard();
ME_EmptyUndoStack(This->editor);
ME_UpdateRepaint(This->editor, FALSE);
ME_SetCursorToStart( services->editor, &cursor );
ME_InternalDeleteText( services->editor, &cursor, ME_GetTextLength( services->editor ), FALSE );
if (text) ME_InsertTextFromCursor( services->editor, 0, text, -1, services->editor->pBuffer->pDefaultStyle );
set_selection_cursors( services->editor, 0, 0);
services->editor->nModifyStep = 0;
OleFlushClipboard();
ME_EmptyUndoStack( services->editor );
ME_UpdateRepaint( services->editor, FALSE );
return S_OK;
return S_OK;
}
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetCurTargetX(ITextServices *iface, LONG *x)
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
FIXME( "%p: STUB\n", services );
return E_NOTIMPL;
}
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetBaseLinePos(ITextServices *iface, LONG *x)
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
FIXME( "%p: STUB\n", services );
return E_NOTIMPL;
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetNaturalSize(ITextServices *iface, DWORD dwAspect, HDC hdcDraw,
HDC hicTargetDev, DVTARGETDEVICE *ptd, DWORD dwMode,
const SIZEL *psizelExtent, LONG *pwidth, LONG *pheight)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetNaturalSize( ITextServices *iface, DWORD aspect, HDC draw,
HDC target, DVTARGETDEVICE *td, DWORD mode,
const SIZEL *extent, LONG *width, LONG *height )
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
RECT rect;
HDC dc = draw;
BOOL rewrap = FALSE;
HRESULT hr;
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
TRACE( "%p: aspect %d, draw %p, target %p, td %p, mode %08x, extent %s, *width %d, *height %d\n", services,
aspect, draw, target, td, mode, wine_dbgstr_point( (POINT *)extent ), *width, *height );
if (aspect != DVASPECT_CONTENT || target || td || mode != TXTNS_FITTOCONTENT )
FIXME( "Many arguments are ignored\n" );
SetRect( &rect, 0, 0, *width, *height );
hr = update_client_rect( services, &rect );
if (FAILED( hr )) return hr;
if (hr == S_OK) rewrap = TRUE;
if (!dc && services->editor->in_place_active)
dc = ITextHost_TxGetDC( services->editor->texthost );
if (!dc) return E_FAIL;
if (rewrap)
{
editor_mark_rewrap_all( services->editor );
wrap_marked_paras_dc( services->editor, dc, FALSE );
}
*width = services->editor->nTotalWidth;
*height = services->editor->nTotalLength;
if (!draw) ITextHost_TxReleaseDC( services->editor->texthost, dc );
return S_OK;
}
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetDropTarget(ITextServices *iface, IDropTarget **ppDropTarget)
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
FIXME( "%p: STUB\n", services );
return E_NOTIMPL;
}
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxPropertyBitsChange(ITextServices *iface, DWORD dwMask, DWORD dwBits)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange,12)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_OnTxPropertyBitsChange( ITextServices *iface, DWORD mask, DWORD bits )
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
DWORD scrollbars;
HRESULT hr;
BOOL repaint = FALSE;
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
TRACE( "%p, mask %08x, bits %08x\n", services, mask, bits );
services->editor->props = (services->editor->props & ~mask) | (bits & mask);
if (mask & (TXTBIT_WORDWRAP | TXTBIT_MULTILINE))
services->editor->bWordWrap = (services->editor->props & TXTBIT_WORDWRAP) && (services->editor->props & TXTBIT_MULTILINE);
if (mask & TXTBIT_SCROLLBARCHANGE)
{
hr = ITextHost_TxGetScrollBars( services->editor->texthost, &scrollbars );
if (SUCCEEDED( hr ))
{
if ((services->editor->scrollbars ^ scrollbars) & WS_HSCROLL)
ITextHost_TxShowScrollBar( services->editor->texthost, SB_HORZ, (scrollbars & WS_HSCROLL) &&
services->editor->nTotalWidth > services->editor->sizeWindow.cx );
if ((services->editor->scrollbars ^ scrollbars) & WS_VSCROLL)
ITextHost_TxShowScrollBar( services->editor->texthost, SB_VERT, (scrollbars & WS_VSCROLL) &&
services->editor->nTotalLength > services->editor->sizeWindow.cy );
services->editor->scrollbars = scrollbars;
}
}
if ((mask & TXTBIT_HIDESELECTION) && !services->editor->bHaveFocus) ME_InvalidateSelection( services->editor );
if (mask & TXTBIT_SELBARCHANGE)
{
LONG width;
hr = ITextHost_TxGetSelectionBarWidth( services->editor->texthost, &width );
if (hr == S_OK)
{
ITextHost_TxInvalidateRect( services->editor->texthost, &services->editor->rcFormat, TRUE );
services->editor->rcFormat.left -= services->editor->selofs;
services->editor->selofs = width ? SELECTIONBAR_WIDTH : 0; /* FIXME: convert from HIMETRIC */
services->editor->rcFormat.left += services->editor->selofs;
repaint = TRUE;
}
}
if (mask & TXTBIT_CLIENTRECTCHANGE)
{
hr = update_client_rect( services, NULL );
if (SUCCEEDED( hr )) repaint = TRUE;
}
if (mask & TXTBIT_USEPASSWORD)
{
if (bits & TXTBIT_USEPASSWORD) ITextHost_TxGetPasswordChar( services->editor->texthost, &services->editor->password_char );
else services->editor->password_char = 0;
repaint = TRUE;
}
if (repaint) ME_RewrapRepaint( services->editor );
return S_OK;
}
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize,12)
DECLSPEC_HIDDEN HRESULT __thiscall fnTextSrv_TxGetCachedSize(ITextServices *iface, DWORD *pdwWidth, DWORD *pdwHeight)
{
ITextServicesImpl *This = impl_from_ITextServices(iface);
struct text_services *services = impl_from_ITextServices( iface );
FIXME("%p: STUB\n", This);
return E_NOTIMPL;
FIXME( "%p: STUB\n", services );
return E_NOTIMPL;
}
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage,20)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll,24)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor,40)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint,44)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceActivate,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceDeactivate,4)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange,12)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize,12)
#ifdef __ASM_USE_THISCALL_WRAPPER
#define STDCALL(func) (void *) __stdcall_ ## func
#ifdef _MSC_VER
#define DEFINE_STDCALL_WRAPPER(num,func) \
__declspec(naked) HRESULT __stdcall_##func(void) \
{ \
__asm pop eax \
__asm pop ecx \
__asm push eax \
__asm mov eax, [ecx] \
__asm jmp dword ptr [eax + 4*num] \
}
#else /* _MSC_VER */
#define DEFINE_STDCALL_WRAPPER(num,func) \
extern HRESULT __stdcall_ ## func(void); \
__ASM_GLOBAL_FUNC(__stdcall_ ## func, \
"popl %eax\n\t" \
"popl %ecx\n\t" \
"pushl %eax\n\t" \
"movl (%ecx), %eax\n\t" \
"jmp *(4*(" #num "))(%eax)" )
#endif /* _MSC_VER */
DEFINE_STDCALL_WRAPPER(3, ITextServices_TxSendMessage)
DEFINE_STDCALL_WRAPPER(4, ITextServices_TxDraw)
DEFINE_STDCALL_WRAPPER(5, ITextServices_TxGetHScroll)
DEFINE_STDCALL_WRAPPER(6, ITextServices_TxGetVScroll)
DEFINE_STDCALL_WRAPPER(7, ITextServices_OnTxSetCursor)
DEFINE_STDCALL_WRAPPER(8, ITextServices_TxQueryHitPoint)
DEFINE_STDCALL_WRAPPER(9, ITextServices_OnTxInPlaceActivate)
DEFINE_STDCALL_WRAPPER(10, ITextServices_OnTxInPlaceDeactivate)
DEFINE_STDCALL_WRAPPER(11, ITextServices_OnTxUIActivate)
DEFINE_STDCALL_WRAPPER(12, ITextServices_OnTxUIDeactivate)
DEFINE_STDCALL_WRAPPER(13, ITextServices_TxGetText)
DEFINE_STDCALL_WRAPPER(14, ITextServices_TxSetText)
DEFINE_STDCALL_WRAPPER(15, ITextServices_TxGetCurTargetX)
DEFINE_STDCALL_WRAPPER(16, ITextServices_TxGetBaseLinePos)
DEFINE_STDCALL_WRAPPER(17, ITextServices_TxGetNaturalSize)
DEFINE_STDCALL_WRAPPER(18, ITextServices_TxGetDropTarget)
DEFINE_STDCALL_WRAPPER(19, ITextServices_OnTxPropertyBitsChange)
DEFINE_STDCALL_WRAPPER(20, ITextServices_TxGetCachedSize)
const ITextServicesVtbl text_services_stdcall_vtbl =
{
NULL,
NULL,
NULL,
STDCALL(ITextServices_TxSendMessage),
STDCALL(ITextServices_TxDraw),
STDCALL(ITextServices_TxGetHScroll),
STDCALL(ITextServices_TxGetVScroll),
STDCALL(ITextServices_OnTxSetCursor),
STDCALL(ITextServices_TxQueryHitPoint),
STDCALL(ITextServices_OnTxInPlaceActivate),
STDCALL(ITextServices_OnTxInPlaceDeactivate),
STDCALL(ITextServices_OnTxUIActivate),
STDCALL(ITextServices_OnTxUIDeactivate),
STDCALL(ITextServices_TxGetText),
STDCALL(ITextServices_TxSetText),
STDCALL(ITextServices_TxGetCurTargetX),
STDCALL(ITextServices_TxGetBaseLinePos),
STDCALL(ITextServices_TxGetNaturalSize),
STDCALL(ITextServices_TxGetDropTarget),
STDCALL(ITextServices_OnTxPropertyBitsChange),
STDCALL(ITextServices_TxGetCachedSize),
};
#endif /* __ASM_USE_THISCALL_WRAPPER */
static const ITextServicesVtbl textservices_vtbl =
{
fnTextSrv_QueryInterface,
fnTextSrv_AddRef,
fnTextSrv_Release,
THISCALL(fnTextSrv_TxSendMessage),
THISCALL(fnTextSrv_TxDraw),
THISCALL(fnTextSrv_TxGetHScroll),
THISCALL(fnTextSrv_TxGetVScroll),
THISCALL(fnTextSrv_OnTxSetCursor),
THISCALL(fnTextSrv_TxQueryHitPoint),
THISCALL(fnTextSrv_OnTxInplaceActivate),
THISCALL(fnTextSrv_OnTxInplaceDeactivate),
THISCALL(fnTextSrv_OnTxUIActivate),
THISCALL(fnTextSrv_OnTxUIDeactivate),
THISCALL(fnTextSrv_TxGetText),
THISCALL(fnTextSrv_TxSetText),
THISCALL(fnTextSrv_TxGetCurTargetX),
THISCALL(fnTextSrv_TxGetBaseLinePos),
THISCALL(fnTextSrv_TxGetNaturalSize),
THISCALL(fnTextSrv_TxGetDropTarget),
THISCALL(fnTextSrv_OnTxPropertyBitsChange),
THISCALL(fnTextSrv_TxGetCachedSize)
fnTextSrv_QueryInterface,
fnTextSrv_AddRef,
fnTextSrv_Release,
THISCALL(fnTextSrv_TxSendMessage),
THISCALL(fnTextSrv_TxDraw),
THISCALL(fnTextSrv_TxGetHScroll),
THISCALL(fnTextSrv_TxGetVScroll),
THISCALL(fnTextSrv_OnTxSetCursor),
THISCALL(fnTextSrv_TxQueryHitPoint),
THISCALL(fnTextSrv_OnTxInPlaceActivate),
THISCALL(fnTextSrv_OnTxInPlaceDeactivate),
THISCALL(fnTextSrv_OnTxUIActivate),
THISCALL(fnTextSrv_OnTxUIDeactivate),
THISCALL(fnTextSrv_TxGetText),
THISCALL(fnTextSrv_TxSetText),
THISCALL(fnTextSrv_TxGetCurTargetX),
THISCALL(fnTextSrv_TxGetBaseLinePos),
THISCALL(fnTextSrv_TxGetNaturalSize),
THISCALL(fnTextSrv_TxGetDropTarget),
THISCALL(fnTextSrv_OnTxPropertyBitsChange),
THISCALL(fnTextSrv_TxGetCachedSize)
};
HRESULT create_text_services( IUnknown *outer, ITextHost *text_host, IUnknown **unk, BOOL emulate_10 )
{
struct text_services *services;
TRACE( "%p %p --> %p\n", outer, text_host, unk );
if (text_host == NULL) return E_POINTER;
services = CoTaskMemAlloc( sizeof(*services) );
if (services == NULL) return E_OUTOFMEMORY;
services->ref = 1;
services->IUnknown_inner.lpVtbl = &textservices_inner_vtbl;
services->ITextServices_iface.lpVtbl = &textservices_vtbl;
services->IRichEditOle_iface.lpVtbl = &re_ole_vtbl;
services->ITextDocument2Old_iface.lpVtbl = &text_doc2old_vtbl;
services->editor = ME_MakeEditor( text_host, emulate_10 );
services->editor->richole = &services->IRichEditOle_iface;
if (outer) services->outer_unk = outer;
else services->outer_unk = &services->IUnknown_inner;
services->text_selection = NULL;
list_init( &services->rangelist );
list_init( &services->clientsites );
*unk = &services->IUnknown_inner;
return S_OK;
}
/******************************************************************
* CreateTextServices (RICHED20.4)
*/
HRESULT WINAPI CreateTextServices(IUnknown *pUnkOuter, ITextHost *pITextHost, IUnknown **ppUnk)
HRESULT WINAPI CreateTextServices( IUnknown *outer, ITextHost *text_host, IUnknown **unk )
{
ITextServicesImpl *ITextImpl;
TRACE("%p %p --> %p\n", pUnkOuter, pITextHost, ppUnk);
if (pITextHost == NULL)
return E_POINTER;
ITextImpl = CoTaskMemAlloc(sizeof(*ITextImpl));
if (ITextImpl == NULL)
return E_OUTOFMEMORY;
InitializeCriticalSection(&ITextImpl->csTxtSrv);
ITextImpl->csTxtSrv.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ITextServicesImpl.csTxtSrv");
ITextImpl->ref = 1;
ITextHost_AddRef(pITextHost);
ITextImpl->pMyHost = pITextHost;
ITextImpl->IUnknown_inner.lpVtbl = &textservices_inner_vtbl;
ITextImpl->ITextServices_iface.lpVtbl = &textservices_vtbl;
ITextImpl->editor = ME_MakeEditor(pITextHost, FALSE);
if (pUnkOuter)
ITextImpl->outer_unk = pUnkOuter;
else
ITextImpl->outer_unk = &ITextImpl->IUnknown_inner;
*ppUnk = &ITextImpl->IUnknown_inner;
return S_OK;
return create_text_services( outer, text_host, unk, FALSE );
}

View File

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

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

View File

@@ -168,7 +168,7 @@ dll/win32/query # Synced to WineStaging-4.18
dll/win32/rasapi32 # Synced to WineStaging-3.3
dll/win32/regapi # Synced to WineStaging-5.7
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/rpcrt4 # Synced to WineStaging-4.18
dll/win32/rsabase # Synced to WineStaging-3.3