mirror of
https://github.com/reactos/reactos.git
synced 2025-04-26 16:40:27 +00:00
Autosyncing with Wine HEAD
svn path=/trunk/; revision=26433
This commit is contained in:
parent
ac9fa62a28
commit
c1a0a2b00c
23 changed files with 3864 additions and 1342 deletions
|
@ -1,29 +0,0 @@
|
|||
TOPSRCDIR = @top_srcdir@
|
||||
TOPOBJDIR = ../..
|
||||
SRCDIR = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
MODULE = riched20.dll
|
||||
IMPORTLIB = libriched20.$(IMPLIBEXT)
|
||||
IMPORTS = user32 gdi32 kernel32
|
||||
EXTRALIBS = -luuid
|
||||
|
||||
C_SRCS = \
|
||||
caret.c \
|
||||
context.c \
|
||||
editor.c \
|
||||
list.c \
|
||||
paint.c \
|
||||
para.c \
|
||||
reader.c \
|
||||
richole.c \
|
||||
row.c \
|
||||
run.c \
|
||||
string.c \
|
||||
style.c \
|
||||
undo.c \
|
||||
wrap.c \
|
||||
writer.c
|
||||
|
||||
@MAKE_DLL_RULES@
|
||||
|
||||
### Dependencies:
|
|
@ -2,6 +2,7 @@
|
|||
* RichEdit - Caret and selection functions.
|
||||
*
|
||||
* Copyright 2004 by Krzysztof Foltman
|
||||
* Copyright 2005 by Phil Krylov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -15,7 +16,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
|
@ -23,6 +24,10 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||
|
||||
static BOOL
|
||||
ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs);
|
||||
|
||||
|
||||
void ME_GetSelection(ME_TextEditor *editor, int *from, int *to)
|
||||
{
|
||||
*from = ME_GetCursorOfs(editor, 0);
|
||||
|
@ -73,93 +78,165 @@ int ME_GetTextLengthEx(ME_TextEditor *editor, GETTEXTLENGTHEX *how)
|
|||
}
|
||||
|
||||
|
||||
void ME_SetSelection(ME_TextEditor *editor, int from, int to)
|
||||
int ME_SetSelection(ME_TextEditor *editor, int from, int to)
|
||||
{
|
||||
int selectionEnd = 0;
|
||||
const int len = ME_GetTextLength(editor);
|
||||
|
||||
/* all negative values are effectively the same */
|
||||
if (from < 0)
|
||||
from = -1;
|
||||
if (to < 0)
|
||||
to = -1;
|
||||
|
||||
/* select all */
|
||||
if (from == 0 && to == -1)
|
||||
{
|
||||
editor->pCursors[1].pRun = ME_FindItemFwd(editor->pBuffer->pFirst, diRun);
|
||||
editor->pCursors[1].pRun = ME_FindItemFwd(editor->pBuffer->pFirst, diRun);
|
||||
editor->pCursors[1].nOffset = 0;
|
||||
editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
|
||||
editor->pCursors[0].nOffset = 0;
|
||||
ME_Repaint(editor);
|
||||
editor->pCursors[0].nOffset = 0;
|
||||
ME_InvalidateSelection(editor);
|
||||
ME_ClearTempStyle(editor);
|
||||
return;
|
||||
return len + 1;
|
||||
}
|
||||
if (from == -1)
|
||||
|
||||
/* if both values are equal and also out of bound, that means to */
|
||||
/* put the selection at the end of the text */
|
||||
if ((from == to) && (to < 0 || to > len))
|
||||
{
|
||||
editor->pCursors[1] = editor->pCursors[0];
|
||||
ME_Repaint(editor);
|
||||
selectionEnd = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if from is negative and to is positive then selection is */
|
||||
/* deselected and caret moved to end of the current selection */
|
||||
if (from < 0)
|
||||
{
|
||||
int start, end;
|
||||
ME_GetSelection(editor, &start, &end);
|
||||
editor->pCursors[1] = editor->pCursors[0];
|
||||
ME_Repaint(editor);
|
||||
ME_ClearTempStyle(editor);
|
||||
return end;
|
||||
}
|
||||
|
||||
/* adjust to if it's a negative value */
|
||||
if (to < 0)
|
||||
to = len + 1;
|
||||
|
||||
/* flip from and to if they are reversed */
|
||||
if (from>to)
|
||||
{
|
||||
int tmp = from;
|
||||
from = to;
|
||||
to = tmp;
|
||||
}
|
||||
|
||||
/* after fiddling with the values, we find from > len && to > len */
|
||||
if (from > len)
|
||||
selectionEnd = 1;
|
||||
/* special case with to too big */
|
||||
else if (to > len)
|
||||
to = len + 1;
|
||||
}
|
||||
|
||||
if (selectionEnd)
|
||||
{
|
||||
editor->pCursors[1].pRun = editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
|
||||
editor->pCursors[1].nOffset = editor->pCursors[0].nOffset = 0;
|
||||
ME_InvalidateSelection(editor);
|
||||
ME_ClearTempStyle(editor);
|
||||
return;
|
||||
}
|
||||
if (from>to)
|
||||
{
|
||||
int tmp = from;
|
||||
from = to;
|
||||
to = tmp;
|
||||
return len;
|
||||
}
|
||||
|
||||
ME_RunOfsFromCharOfs(editor, from, &editor->pCursors[1].pRun, &editor->pCursors[1].nOffset);
|
||||
ME_RunOfsFromCharOfs(editor, to, &editor->pCursors[0].pRun, &editor->pCursors[0].nOffset);
|
||||
ME_RunOfsFromCharOfs(editor, to, &editor->pCursors[0].pRun, &editor->pCursors[0].nOffset);
|
||||
return to;
|
||||
}
|
||||
|
||||
void ME_MoveCaret(ME_TextEditor *editor)
|
||||
{
|
||||
HDC hDC = GetDC(editor->hWnd);
|
||||
ME_Context c;
|
||||
|
||||
ME_Cursor *pCursor = &editor->pCursors[0];
|
||||
void
|
||||
ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
|
||||
int *x, int *y, int *height)
|
||||
{
|
||||
ME_DisplayItem *pCursorRun = pCursor->pRun;
|
||||
ME_DisplayItem *pSizeRun = pCursor->pRun;
|
||||
|
||||
ME_InitContext(&c, editor, hDC);
|
||||
|
||||
assert(!pCursor->nOffset || !editor->bCaretAtEnd);
|
||||
assert(height && x && y);
|
||||
assert(!(ME_GetParagraph(pCursorRun)->member.para.nFlags & MEPF_REWRAP));
|
||||
assert(pCursor->pRun);
|
||||
assert(pCursor->pRun->type == diRun);
|
||||
|
||||
if (pCursorRun->type == diRun) {
|
||||
ME_DisplayItem *row = ME_FindItemBack(pCursorRun, diStartRowOrParagraph);
|
||||
|
||||
if (row) {
|
||||
HDC hDC = GetDC(editor->hWnd);
|
||||
ME_Context c;
|
||||
ME_DisplayItem *run = pCursorRun;
|
||||
ME_DisplayItem *para;
|
||||
ME_DisplayItem *para = NULL;
|
||||
SIZE sz = {0, 0};
|
||||
|
||||
ME_InitContext(&c, editor, hDC);
|
||||
|
||||
if (!pCursor->nOffset && !editor->bCaretAtEnd)
|
||||
{
|
||||
ME_DisplayItem *prev = ME_FindItemBack(pCursorRun, diRunOrStartRow);
|
||||
assert(prev);
|
||||
if (prev->type == diRun)
|
||||
pSizeRun = prev;
|
||||
}
|
||||
assert(row->type == diStartRow); /* paragraph -> run without start row ?*/
|
||||
para = ME_FindItemBack(row, diParagraph);
|
||||
assert(para);
|
||||
assert(para->type == diParagraph);
|
||||
if (editor->bCaretAtEnd && !pCursor->nOffset &&
|
||||
run == ME_FindItemFwd(row, diRun))
|
||||
{
|
||||
ME_DisplayItem *tmp = ME_FindItemBack(row, diRunOrParagraph);
|
||||
assert(tmp);
|
||||
if (tmp->type == diRun)
|
||||
{
|
||||
row = ME_FindItemBack(tmp, diStartRow);
|
||||
pSizeRun = run = tmp;
|
||||
assert(run);
|
||||
assert(run->type == diRun);
|
||||
sz = ME_GetRunSize(&c, ¶->member.para, &run->member.run, ME_StrLen(run->member.run.strText));
|
||||
}
|
||||
}
|
||||
if (pCursor->nOffset && !(run->member.run.nFlags & MERF_SKIPPED)) {
|
||||
sz = ME_GetRunSize(&c, ¶->member.para, &run->member.run, pCursor->nOffset);
|
||||
}
|
||||
CreateCaret(editor->hWnd, NULL, 0, pSizeRun->member.run.nAscent+pSizeRun->member.run.nDescent);
|
||||
SetCaretPos(run->member.run.pt.x+sz.cx,
|
||||
para->member.para.nYPos+row->member.row.nBaseline+pSizeRun->member.run.pt.y-pSizeRun->member.run.nAscent-ME_GetYScrollPos(editor));
|
||||
} else {
|
||||
assert(0 == "Wrapped paragraph run without a row?");
|
||||
CreateCaret(editor->hWnd, NULL, 0, 10);
|
||||
SetCaretPos(0,0);
|
||||
|
||||
*height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent;
|
||||
*x = run->member.run.pt.x + sz.cx;
|
||||
*y = para->member.para.nYPos + row->member.row.nBaseline + pSizeRun->member.run.pt.y - pSizeRun->member.run.nAscent - ME_GetYScrollPos(editor);
|
||||
|
||||
ME_DestroyContext(&c);
|
||||
ReleaseDC(editor->hWnd, hDC);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(0 == "Cursor not on a run");
|
||||
CreateCaret(editor->hWnd, NULL, 0, 10); /* FIXME use global font */
|
||||
SetCaretPos(0,0);
|
||||
}
|
||||
ME_DestroyContext(&c);
|
||||
ReleaseDC(editor->hWnd, hDC);
|
||||
*height = 10; /* FIXME use global font */
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ME_MoveCaret(ME_TextEditor *editor)
|
||||
{
|
||||
int x, y, height;
|
||||
|
||||
ME_WrapMarkedParagraphs(editor);
|
||||
ME_GetCursorCoordinates(editor, &editor->pCursors[0], &x, &y, &height);
|
||||
CreateCaret(editor->hWnd, NULL, 0, height);
|
||||
SetCaretPos(x, y);
|
||||
}
|
||||
|
||||
|
||||
void ME_ShowCaret(ME_TextEditor *ed)
|
||||
{
|
||||
ME_MoveCaret(ed);
|
||||
|
@ -292,58 +369,60 @@ void ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor,
|
|||
ME_InternalDeleteText(editor, ME_GetCursorOfs(editor, nCursor), nChars);
|
||||
}
|
||||
|
||||
static WCHAR wszSpace[] = {' ', 0};
|
||||
|
||||
/* FIXME this is temporary, just to have something to test how bad graphics handler is */
|
||||
void ME_InsertGraphicsFromCursor(ME_TextEditor *editor, int nCursor)
|
||||
{
|
||||
ME_Cursor *pCursor = &editor->pCursors[nCursor];
|
||||
ME_DisplayItem *pItem = NULL;
|
||||
ME_DisplayItem *pNewRun = NULL;
|
||||
ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor);
|
||||
ME_UndoItem *pUndo;
|
||||
|
||||
/* FIXME no no no */
|
||||
if (ME_IsSelection(editor))
|
||||
ME_DeleteSelection(editor);
|
||||
|
||||
pUndo = ME_AddUndoItem(editor, diUndoDeleteRun, NULL);
|
||||
if (pUndo) {
|
||||
pUndo->nStart = pCursor->nOffset + pCursor->pRun->member.run.nCharOfs + ME_GetParagraph(pCursor->pRun)->member.para.nCharOfs;
|
||||
pUndo->nLen = 1;
|
||||
}
|
||||
if (pCursor->nOffset)
|
||||
{
|
||||
ME_SplitRunSimple(editor, pCursor->pRun, pCursor->nOffset);
|
||||
}
|
||||
pItem = pCursor->pRun;
|
||||
pNewRun = ME_MakeRun(pStyle, ME_MakeStringN(wszSpace, 1), MERF_GRAPHICS);
|
||||
pNewRun->member.run.nCharOfs = pCursor->pRun->member.run.nCharOfs;
|
||||
ME_InsertBefore(pCursor->pRun, pNewRun);
|
||||
ME_PropagateCharOffset(pItem, 1);
|
||||
ME_CheckCharOffsets(editor);
|
||||
ME_SendSelChange(editor);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static ME_DisplayItem *
|
||||
ME_InternalInsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
||||
const WCHAR *str, int len, ME_Style *style,
|
||||
int flags)
|
||||
{
|
||||
ME_DisplayItem *pNewRun = NULL;
|
||||
ME_Cursor *p = &editor->pCursors[nCursor];
|
||||
|
||||
editor->bCaretAtEnd = FALSE;
|
||||
|
||||
assert(p->pRun->type == diRun);
|
||||
|
||||
ME_AddRefStyle(style);
|
||||
return ME_InsertRunAtCursor(editor, p, style, str, len, flags);
|
||||
}
|
||||
|
||||
|
||||
/* FIXME this is temporary, just to have something to test how bad graphics handler is */
|
||||
void ME_InsertGraphicsFromCursor(ME_TextEditor *editor, int nCursor)
|
||||
{
|
||||
ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor);
|
||||
WCHAR space = ' ';
|
||||
|
||||
pNewRun = ME_MakeRun(style, ME_MakeStringN(str, len), flags); /* addrefs style */
|
||||
ME_InsertRun(editor, ME_CharOfsFromRunOfs(editor, p->pRun, p->nOffset), pNewRun);
|
||||
ME_DestroyDisplayItem(pNewRun);
|
||||
ME_ReleaseStyle(style);
|
||||
/* FIXME no no no */
|
||||
if (ME_IsSelection(editor))
|
||||
ME_DeleteSelection(editor);
|
||||
|
||||
ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle,
|
||||
MERF_GRAPHICS);
|
||||
ME_SendSelChange(editor);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ME_InsertTableCellFromCursor(ME_TextEditor *editor, int nCursor)
|
||||
{
|
||||
WCHAR tab = '\t';
|
||||
ME_DisplayItem *p, *run;
|
||||
ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor);
|
||||
|
||||
p = ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, pStyle,
|
||||
MERF_CELL);
|
||||
run = p;
|
||||
while ((run = ME_FindItemBack(run, diRunOrParagraph))->type == diRun)
|
||||
{
|
||||
if (run->member.run.nFlags & MERF_CELL)
|
||||
{
|
||||
assert(run->member.run.pCell->next);
|
||||
p->member.run.pCell = run->member.run.pCell->next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert(run->type == diParagraph);
|
||||
assert(run->member.para.bTable);
|
||||
assert(run->member.para.pCells);
|
||||
p->member.run.pCell = run->member.para.pCells;
|
||||
}
|
||||
|
||||
|
||||
|
@ -352,16 +431,25 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
|||
{
|
||||
const WCHAR *pos;
|
||||
ME_Cursor *p = NULL;
|
||||
|
||||
assert(style);
|
||||
int freeSpace;
|
||||
|
||||
/* FIXME really HERE ? */
|
||||
if (ME_IsSelection(editor))
|
||||
ME_DeleteSelection(editor);
|
||||
|
||||
/* FIXME: is this too slow? */
|
||||
/* Didn't affect performance for WM_SETTEXT (around 50sec/30K) */
|
||||
freeSpace = editor->nTextLimit - ME_GetTextLength(editor);
|
||||
|
||||
/* text operations set modified state */
|
||||
editor->nModifyStep = 1;
|
||||
|
||||
assert(style);
|
||||
|
||||
assert(nCursor>=0 && nCursor<editor->nCursors);
|
||||
if (len == -1)
|
||||
len = lstrlenW(str);
|
||||
len = min(len, freeSpace);
|
||||
while (len)
|
||||
{
|
||||
pos = str;
|
||||
|
@ -385,14 +473,10 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
|||
}
|
||||
if (pos-str < len) { /* handle EOLs */
|
||||
ME_DisplayItem *tp, *end_run;
|
||||
ME_Paragraph *para;
|
||||
ME_Style *tmp_style;
|
||||
if (pos!=str)
|
||||
ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
|
||||
p = &editor->pCursors[nCursor];
|
||||
tp = ME_FindItemBack(p->pRun, diParagraph);
|
||||
para = &tp->member.para;
|
||||
assert(tp);
|
||||
if (p->nOffset) {
|
||||
ME_SplitRunSimple(editor, p->pRun, p->nOffset);
|
||||
p = &editor->pCursors[nCursor];
|
||||
|
@ -420,69 +504,170 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
|||
}
|
||||
}
|
||||
|
||||
static BOOL ME_ArrowLeft(ME_TextEditor *editor, ME_Cursor *p)
|
||||
|
||||
static BOOL
|
||||
ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
|
||||
{
|
||||
if (p->nOffset) {
|
||||
p->nOffset = ME_StrRelPos2(p->pRun->member.run.strText, p->nOffset, -1);
|
||||
ME_DisplayItem *pRun = pCursor->pRun;
|
||||
|
||||
if (nRelOfs == -1)
|
||||
{
|
||||
if (!pCursor->nOffset)
|
||||
{
|
||||
do {
|
||||
pRun = ME_FindItemBack(pRun, diRunOrParagraph);
|
||||
assert(pRun);
|
||||
switch (pRun->type)
|
||||
{
|
||||
case diRun:
|
||||
break;
|
||||
case diParagraph:
|
||||
if (pRun->member.para.prev_para->type == diTextStart)
|
||||
return FALSE;
|
||||
pRun = ME_FindItemBack(pRun, diRunOrParagraph);
|
||||
/* every paragraph ought to have at least one run */
|
||||
assert(pRun && pRun->type == diRun);
|
||||
assert(pRun->member.run.nFlags & MERF_ENDPARA);
|
||||
break;
|
||||
default:
|
||||
assert(pRun->type != diRun && pRun->type != diParagraph);
|
||||
return FALSE;
|
||||
}
|
||||
} while (RUN_IS_HIDDEN(&pRun->member.run));
|
||||
pCursor->pRun = pRun;
|
||||
if (pRun->member.run.nFlags & MERF_ENDPARA)
|
||||
pCursor->nOffset = 0;
|
||||
else
|
||||
pCursor->nOffset = pRun->member.run.strText->nLen;
|
||||
}
|
||||
|
||||
if (pCursor->nOffset)
|
||||
pCursor->nOffset = ME_StrRelPos2(pCursor->pRun->member.run.strText, pCursor->nOffset, nRelOfs);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ME_DisplayItem *pRun = ME_FindItemBack(p->pRun, diRunOrParagraph);
|
||||
assert(pRun);
|
||||
if (pRun->type == diRun) {
|
||||
p->pRun = pRun;
|
||||
assert(p->pRun->type == diRun);
|
||||
assert(pRun->member.run.strText->nLen);
|
||||
p->nOffset = pRun->member.run.strText->nLen;
|
||||
if (p->nOffset) {
|
||||
p->nOffset = ME_StrRelPos2(pRun->member.run.strText, p->nOffset, -1);
|
||||
if (!(pRun->member.run.nFlags & MERF_ENDPARA))
|
||||
{
|
||||
int new_ofs = ME_StrRelPos2(pRun->member.run.strText, pCursor->nOffset, nRelOfs);
|
||||
|
||||
if (new_ofs < pRun->member.run.strText->nLen)
|
||||
{
|
||||
pCursor->nOffset = new_ofs;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
if (pRun->type == diParagraph)
|
||||
do {
|
||||
pRun = ME_FindItemFwd(pRun, diRun);
|
||||
} while (pRun && RUN_IS_HIDDEN(&pRun->member.run));
|
||||
if (pRun)
|
||||
{
|
||||
if (pRun->member.para.prev_para->type == diTextStart)
|
||||
return FALSE;
|
||||
assert(pRun->member.para.prev_para->type == diParagraph);
|
||||
pRun = ME_FindItemBack(pRun, diRunOrParagraph);
|
||||
/* every paragraph ought to have at least one run */
|
||||
assert(pRun && pRun->type == diRun);
|
||||
assert(pRun->member.run.nFlags & MERF_ENDPARA);
|
||||
p->pRun = pRun;
|
||||
p->nOffset = 0;
|
||||
pCursor->pRun = pRun;
|
||||
pCursor->nOffset = 0;
|
||||
return TRUE;
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL ME_ArrowRight(ME_TextEditor *editor, ME_Cursor *p)
|
||||
|
||||
static BOOL
|
||||
ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
|
||||
{
|
||||
ME_DisplayItem *pRun;
|
||||
ME_DisplayItem *pRun = cursor->pRun, *pOtherRun;
|
||||
int nOffset = cursor->nOffset;
|
||||
|
||||
if (!(p->pRun->member.run.nFlags & MERF_ENDPARA))
|
||||
if (nRelOfs == -1)
|
||||
{
|
||||
int new_ofs = ME_StrRelPos2(p->pRun->member.run.strText, p->nOffset, 1);
|
||||
|
||||
if (new_ofs<p->pRun->member.run.strText->nLen)
|
||||
/* Backward movement */
|
||||
while (TRUE)
|
||||
{
|
||||
p->nOffset = new_ofs;
|
||||
return TRUE;
|
||||
nOffset = ME_CallWordBreakProc(editor, pRun->member.run.strText,
|
||||
nOffset, WB_MOVEWORDLEFT);
|
||||
if (nOffset)
|
||||
break;
|
||||
pOtherRun = ME_FindItemBack(pRun, diRunOrParagraph);
|
||||
if (pOtherRun->type == diRun)
|
||||
{
|
||||
if (ME_CallWordBreakProc(editor, pOtherRun->member.run.strText,
|
||||
pOtherRun->member.run.strText->nLen - 1,
|
||||
WB_ISDELIMITER)
|
||||
&& !(pRun->member.run.nFlags & MERF_ENDPARA)
|
||||
&& !(cursor->pRun == pRun && cursor->nOffset == 0)
|
||||
&& !ME_CallWordBreakProc(editor, pRun->member.run.strText, 0,
|
||||
WB_ISDELIMITER))
|
||||
break;
|
||||
pRun = pOtherRun;
|
||||
nOffset = pOtherRun->member.run.strText->nLen;
|
||||
}
|
||||
else if (pOtherRun->type == diParagraph)
|
||||
{
|
||||
if (cursor->pRun == pRun && cursor->nOffset == 0)
|
||||
{
|
||||
/* Paragraph breaks are treated as separate words */
|
||||
if (pOtherRun->member.para.prev_para->type == diTextStart)
|
||||
return FALSE;
|
||||
pRun = ME_FindItemBack(pOtherRun, diRunOrParagraph);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pRun = ME_FindItemFwd(p->pRun, diRun);
|
||||
if (pRun) {
|
||||
p->pRun = pRun;
|
||||
assert(p->pRun->type == diRun);
|
||||
p->nOffset = 0;
|
||||
else
|
||||
{
|
||||
/* Forward movement */
|
||||
BOOL last_delim = FALSE;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (last_delim && !ME_CallWordBreakProc(editor, pRun->member.run.strText,
|
||||
nOffset, WB_ISDELIMITER))
|
||||
break;
|
||||
nOffset = ME_CallWordBreakProc(editor, pRun->member.run.strText,
|
||||
nOffset, WB_MOVEWORDRIGHT);
|
||||
if (nOffset < pRun->member.run.strText->nLen)
|
||||
break;
|
||||
pOtherRun = ME_FindItemFwd(pRun, diRunOrParagraphOrEnd);
|
||||
if (pOtherRun->type == diRun)
|
||||
{
|
||||
last_delim = ME_CallWordBreakProc(editor, pRun->member.run.strText,
|
||||
nOffset - 1, WB_ISDELIMITER);
|
||||
pRun = pOtherRun;
|
||||
nOffset = 0;
|
||||
}
|
||||
else if (pOtherRun->type == diParagraph)
|
||||
{
|
||||
if (cursor->pRun == pRun)
|
||||
pRun = ME_FindItemFwd(pOtherRun, diRun);
|
||||
nOffset = 0;
|
||||
break;
|
||||
}
|
||||
else /* diTextEnd */
|
||||
{
|
||||
if (cursor->pRun == pRun)
|
||||
return FALSE;
|
||||
nOffset = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor->pRun = pRun;
|
||||
cursor->nOffset = nOffset;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ME_SelectWord(ME_TextEditor *editor)
|
||||
{
|
||||
if (!(editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA))
|
||||
ME_MoveCursorWords(editor, &editor->pCursors[0], -1);
|
||||
ME_MoveCursorWords(editor, &editor->pCursors[1], +1);
|
||||
ME_InvalidateSelection(editor);
|
||||
ME_SendSelChange(editor);
|
||||
}
|
||||
|
||||
|
||||
int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor)
|
||||
{
|
||||
ME_Cursor *pCursor = &editor->pCursors[nCursor];
|
||||
|
@ -599,6 +784,7 @@ ME_CharFromPos(ME_TextEditor *editor, int x, int y)
|
|||
GetClientRect(editor->hWnd, &rc);
|
||||
if (x < 0 || y < 0 || x >= rc.right || y >= rc.bottom)
|
||||
return -1;
|
||||
y += ME_GetYScrollPos(editor);
|
||||
ME_FindPixelPos(editor, x, y, &cursor, NULL);
|
||||
return (ME_GetParagraph(cursor.pRun)->member.para.nCharOfs
|
||||
+ cursor.pRun->member.run.nCharOfs + cursor.nOffset);
|
||||
|
@ -630,10 +816,9 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y)
|
|||
is_selection = 1;
|
||||
}
|
||||
}
|
||||
ME_InvalidateSelection(editor);
|
||||
HideCaret(editor->hWnd);
|
||||
ME_MoveCaret(editor);
|
||||
if (is_selection)
|
||||
ME_Repaint(editor);
|
||||
ShowCaret(editor->hWnd);
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_SendSelChange(editor);
|
||||
|
@ -646,16 +831,18 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y)
|
|||
y += ME_GetYScrollPos(editor);
|
||||
|
||||
tmp_cursor = editor->pCursors[0];
|
||||
if (!ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd))
|
||||
/* return */;
|
||||
/* FIXME: do something with the return value of ME_FindPixelPos */
|
||||
ME_FindPixelPos(editor, x, y, &tmp_cursor, &editor->bCaretAtEnd);
|
||||
|
||||
if (tmp_cursor.pRun == editor->pCursors[0].pRun &&
|
||||
tmp_cursor.nOffset == editor->pCursors[0].nOffset)
|
||||
return;
|
||||
|
||||
ME_InvalidateSelection(editor);
|
||||
editor->pCursors[0] = tmp_cursor;
|
||||
HideCaret(editor->hWnd);
|
||||
ME_MoveCaret(editor);
|
||||
ME_Repaint(editor);
|
||||
ME_InvalidateSelection(editor);
|
||||
ShowCaret(editor->hWnd);
|
||||
ME_SendSelChange(editor);
|
||||
}
|
||||
|
@ -726,50 +913,36 @@ static int ME_GetXForArrow(ME_TextEditor *editor, ME_Cursor *pCursor)
|
|||
return x;
|
||||
}
|
||||
|
||||
static void ME_ArrowUp(ME_TextEditor *editor, ME_Cursor *pCursor)
|
||||
{
|
||||
ME_DisplayItem *pRun = pCursor->pRun;
|
||||
ME_DisplayItem *pItem, *pItem2;
|
||||
int x = ME_GetXForArrow(editor, pCursor);
|
||||
|
||||
if (editor->bCaretAtEnd && !pCursor->nOffset)
|
||||
{
|
||||
pRun = ME_FindItemBack(pRun, diRun);
|
||||
if (!pRun)
|
||||
return;
|
||||
}
|
||||
|
||||
/* start of this row */
|
||||
pItem = ME_FindItemBack(pRun, diStartRow);
|
||||
assert(pItem);
|
||||
/* start of the previous row */
|
||||
pItem2 = ME_FindItemBack(pItem, diStartRow);
|
||||
/* no previous row = the first line of the first paragraph */
|
||||
if (!pItem2) /* can't go up - don't go BOL (as in MS richedit) */
|
||||
return;
|
||||
/* FIXME
|
||||
ME_WrapTextParagraph(editor, ME_FindItemBack(pItem2, diParagraph));
|
||||
*/
|
||||
pCursor->pRun = ME_FindRunInRow(editor, pItem2, x, &pCursor->nOffset, &editor->bCaretAtEnd);
|
||||
}
|
||||
|
||||
static void ME_ArrowDown(ME_TextEditor *editor, ME_Cursor *pCursor)
|
||||
static void
|
||||
ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
|
||||
{
|
||||
ME_DisplayItem *pRun = pCursor->pRun;
|
||||
ME_DisplayItem *pItem;
|
||||
int x = ME_GetXForArrow(editor, pCursor);
|
||||
if (!pCursor->nOffset && editor->bCaretAtEnd)
|
||||
{
|
||||
|
||||
if (editor->bCaretAtEnd && !pCursor->nOffset)
|
||||
pRun = ME_FindItemBack(pRun, diRun);
|
||||
/* x = pRun->member.run.pt.x + pRun->member.run.nWidth; */
|
||||
if (!pRun)
|
||||
return;
|
||||
if (nRelOfs == -1)
|
||||
{
|
||||
/* start of this row */
|
||||
pItem = ME_FindItemBack(pRun, diStartRow);
|
||||
assert(pItem);
|
||||
/* start of the previous row */
|
||||
pItem = ME_FindItemBack(pItem, diStartRow);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* start of the next row */
|
||||
pItem = ME_FindItemFwd(pRun, diStartRow);
|
||||
/* FIXME If diParagraph is before diStartRow, wrap the next paragraph?
|
||||
*/
|
||||
}
|
||||
/* start of the next row */
|
||||
pItem = ME_FindItemFwd(pRun, diStartRow);
|
||||
/* FIXME If diParagraph is before diStartRow, wrap the next paragraph?
|
||||
*/
|
||||
if (!pItem)
|
||||
{
|
||||
/* next row not found - ignore */
|
||||
/* row not found - ignore */
|
||||
return;
|
||||
}
|
||||
pCursor->pRun = ME_FindRunInRow(editor, pItem, x, &pCursor->nOffset, &editor->bCaretAtEnd);
|
||||
|
@ -777,6 +950,7 @@ static void ME_ArrowDown(ME_TextEditor *editor, ME_Cursor *pCursor)
|
|||
assert(pCursor->pRun->type == diRun);
|
||||
}
|
||||
|
||||
|
||||
static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
|
||||
{
|
||||
ME_DisplayItem *pRun = pCursor->pRun;
|
||||
|
@ -819,9 +993,9 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
|
|||
ME_EnsureVisible(editor, ME_FindItemFwd(editor->pBuffer->pFirst, diRun));
|
||||
ME_Repaint(editor);
|
||||
}
|
||||
else {
|
||||
ME_Scroll(editor, 0, ys-yprev);
|
||||
ME_Repaint(editor);
|
||||
else
|
||||
{
|
||||
ME_ScrollUp(editor, ys-yprev);
|
||||
}
|
||||
assert(pCursor->pRun);
|
||||
assert(pCursor->pRun->type == diRun);
|
||||
|
@ -872,9 +1046,9 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
|
|||
ME_EnsureVisible(editor, ME_FindItemBack(editor->pBuffer->pLast, diRun));
|
||||
ME_Repaint(editor);
|
||||
}
|
||||
else {
|
||||
ME_Scroll(editor, 0, ys-yprev);
|
||||
ME_Repaint(editor);
|
||||
else
|
||||
{
|
||||
ME_ScrollUp(editor,ys-yprev);
|
||||
}
|
||||
assert(pCursor->pRun);
|
||||
assert(pCursor->pRun->type == diRun);
|
||||
|
@ -883,6 +1057,10 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
|
|||
static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor)
|
||||
{
|
||||
ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow);
|
||||
/* bCaretAtEnd doesn't make sense if the cursor isn't set at the
|
||||
first character of the next row */
|
||||
assert(!editor->bCaretAtEnd || !pCursor->nOffset);
|
||||
ME_WrapMarkedParagraphs(editor);
|
||||
if (pRow) {
|
||||
ME_DisplayItem *pRun;
|
||||
if (editor->bCaretAtEnd && !pCursor->nOffset) {
|
||||
|
@ -962,25 +1140,6 @@ static int ME_GetSelCursor(ME_TextEditor *editor, int dir)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static BOOL ME_CancelSelection(ME_TextEditor *editor, int dir)
|
||||
{
|
||||
int cdir;
|
||||
|
||||
if (GetKeyState(VK_SHIFT)<0)
|
||||
return FALSE;
|
||||
if (!memcmp(&editor->pCursors[0], &editor->pCursors[1], sizeof(ME_Cursor)))
|
||||
return FALSE;
|
||||
|
||||
cdir = ME_GetCursorOfs(editor, 0) - ME_GetCursorOfs(editor, 1);
|
||||
|
||||
if (cdir*dir>0)
|
||||
editor->pCursors[1] = editor->pCursors[0];
|
||||
else
|
||||
editor->pCursors[0] = editor->pCursors[1];
|
||||
ME_Repaint(editor);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL ME_UpdateSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor)
|
||||
{
|
||||
ME_Cursor old_anchor = editor->pCursors[1];
|
||||
|
@ -1007,14 +1166,6 @@ BOOL ME_UpdateSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void ME_RepaintSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor)
|
||||
{
|
||||
if (ME_UpdateSelection(editor, pTempCursor)) {
|
||||
ME_EnsureVisible(editor, editor->pCursors[0].pRun);
|
||||
ME_Repaint(editor);
|
||||
}
|
||||
}
|
||||
|
||||
void ME_DeleteSelection(ME_TextEditor *editor)
|
||||
{
|
||||
int from, to;
|
||||
|
@ -1042,8 +1193,12 @@ ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor)
|
|||
void ME_SendSelChange(ME_TextEditor *editor)
|
||||
{
|
||||
SELCHANGE sc;
|
||||
|
||||
ME_ClearTempStyle(editor);
|
||||
|
||||
if (!(editor->nEventMask & ENM_SELCHANGE))
|
||||
return;
|
||||
|
||||
sc.nmhdr.hwndFrom = editor->hWnd;
|
||||
sc.nmhdr.idFrom = GetWindowLongW(editor->hWnd, GWLP_ID);
|
||||
sc.nmhdr.code = EN_SELCHANGE;
|
||||
|
@ -1056,116 +1211,69 @@ void ME_SendSelChange(ME_TextEditor *editor)
|
|||
SendMessageW(GetParent(editor->hWnd), WM_NOTIFY, sc.nmhdr.idFrom, (LPARAM)&sc);
|
||||
}
|
||||
|
||||
BOOL ME_ArrowKey(ME_TextEditor *editor, int nVKey, int nCtrl)
|
||||
|
||||
BOOL
|
||||
ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
|
||||
{
|
||||
int nCursor = 0;
|
||||
ME_Cursor *p = &editor->pCursors[nCursor];
|
||||
ME_Cursor tmp_curs = *p;
|
||||
BOOL success = FALSE;
|
||||
|
||||
switch(nVKey) {
|
||||
case VK_UP:
|
||||
ME_ArrowUp(editor, p);
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_RepaintSelection(editor, &tmp_curs);
|
||||
ME_SendSelChange(editor);
|
||||
return TRUE;
|
||||
case VK_DOWN:
|
||||
ME_ArrowDown(editor, p);
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_RepaintSelection(editor, &tmp_curs);
|
||||
ME_SendSelChange(editor);
|
||||
return TRUE;
|
||||
case VK_PRIOR:
|
||||
ME_ArrowPageUp(editor, p);
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_SendSelChange(editor);
|
||||
return TRUE;
|
||||
case VK_NEXT:
|
||||
ME_ArrowPageDown(editor, p);
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_SendSelChange(editor);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ME_CheckCharOffsets(editor);
|
||||
editor->nUDArrowX = -1;
|
||||
switch(nVKey) {
|
||||
case VK_BACK: { /* FIXME backspace and delete aren't the same, they act different wrt paragraph style of the merged paragraph */
|
||||
if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_READONLY)
|
||||
return FALSE;
|
||||
if (ME_IsSelection(editor))
|
||||
{
|
||||
editor->bCaretAtEnd = FALSE; /* FIXME or maybe not */
|
||||
ME_DeleteSelection(editor);
|
||||
ME_UpdateRepaint(editor);
|
||||
ME_SendRequestResize(editor, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
if (ME_ArrowLeft(editor, p)) {
|
||||
editor->bCaretAtEnd = FALSE; /* FIXME or maybe not */
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_MoveCaret(editor);
|
||||
ME_DeleteTextAtCursor(editor, nCursor, 1);
|
||||
ME_UpdateRepaint(editor);
|
||||
ME_SendRequestResize(editor, FALSE);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
case VK_DELETE: {
|
||||
if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_READONLY)
|
||||
return FALSE;
|
||||
/* editor->bCaretAtEnd = 0; FIXME or maybe not */
|
||||
if (ME_IsSelection(editor))
|
||||
{
|
||||
ME_DeleteSelection(editor);
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_UpdateRepaint(editor);
|
||||
ME_SendRequestResize(editor, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
ME_DeleteTextAtCursor(editor, nCursor, 1);
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_UpdateRepaint(editor);
|
||||
ME_SendRequestResize(editor, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
case VK_HOME: {
|
||||
if (GetKeyState(VK_CONTROL)<0)
|
||||
ME_ArrowCtrlHome(editor, p);
|
||||
else
|
||||
ME_ArrowHome(editor, p);
|
||||
editor->bCaretAtEnd = 0;
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_RepaintSelection(editor, &tmp_curs);
|
||||
ME_SendSelChange(editor);
|
||||
return TRUE;
|
||||
}
|
||||
case VK_END:
|
||||
if (GetKeyState(VK_CONTROL)<0)
|
||||
ME_ArrowCtrlEnd(editor, p);
|
||||
else
|
||||
ME_ArrowEnd(editor, p);
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_RepaintSelection(editor, &tmp_curs);
|
||||
ME_SendSelChange(editor);
|
||||
return TRUE;
|
||||
case VK_LEFT:
|
||||
editor->bCaretAtEnd = 0;
|
||||
if (ME_CancelSelection(editor, -1))
|
||||
return TRUE;
|
||||
ME_ArrowLeft(editor, p);
|
||||
ME_RepaintSelection(editor, &tmp_curs);
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_SendSelChange(editor);
|
||||
return TRUE;
|
||||
if (ctrl)
|
||||
success = ME_MoveCursorWords(editor, &tmp_curs, -1);
|
||||
else
|
||||
success = ME_MoveCursorChars(editor, &tmp_curs, -1);
|
||||
break;
|
||||
case VK_RIGHT:
|
||||
editor->bCaretAtEnd = 0;
|
||||
if (ME_CancelSelection(editor, +1))
|
||||
return TRUE;
|
||||
ME_ArrowRight(editor, p);
|
||||
ME_RepaintSelection(editor, &tmp_curs);
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_SendSelChange(editor);
|
||||
return TRUE;
|
||||
if (ctrl)
|
||||
success = ME_MoveCursorWords(editor, &tmp_curs, +1);
|
||||
else
|
||||
success = ME_MoveCursorChars(editor, &tmp_curs, +1);
|
||||
break;
|
||||
case VK_UP:
|
||||
ME_MoveCursorLines(editor, &tmp_curs, -1);
|
||||
break;
|
||||
case VK_DOWN:
|
||||
ME_MoveCursorLines(editor, &tmp_curs, +1);
|
||||
break;
|
||||
case VK_PRIOR:
|
||||
ME_ArrowPageUp(editor, &tmp_curs);
|
||||
break;
|
||||
case VK_NEXT:
|
||||
ME_ArrowPageDown(editor, &tmp_curs);
|
||||
break;
|
||||
case VK_HOME: {
|
||||
if (ctrl)
|
||||
ME_ArrowCtrlHome(editor, &tmp_curs);
|
||||
else
|
||||
ME_ArrowHome(editor, &tmp_curs);
|
||||
editor->bCaretAtEnd = 0;
|
||||
break;
|
||||
}
|
||||
case VK_END:
|
||||
if (ctrl)
|
||||
ME_ArrowCtrlEnd(editor, &tmp_curs);
|
||||
else
|
||||
ME_ArrowEnd(editor, &tmp_curs);
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
if (!extend)
|
||||
editor->pCursors[1] = tmp_curs;
|
||||
*p = tmp_curs;
|
||||
|
||||
ME_InvalidateSelection(editor);
|
||||
ME_Repaint(editor);
|
||||
HideCaret(editor->hWnd);
|
||||
ME_EnsureVisible(editor, tmp_curs.pRun);
|
||||
ME_ShowCaret(editor);
|
||||
ME_SendSelChange(editor);
|
||||
return success;
|
||||
}
|
||||
|
|
412
reactos/dll/win32/riched20/clipboard.c
Normal file
412
reactos/dll/win32/riched20/clipboard.c
Normal file
|
@ -0,0 +1,412 @@
|
|||
/*
|
||||
* Richedit clipboard handling
|
||||
*
|
||||
* Copyright (C) 2006 Kevin Koltzau
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "editor.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||
|
||||
static UINT cfRTF = 0;
|
||||
|
||||
typedef struct DataObjectImpl {
|
||||
const IDataObjectVtbl *lpVtbl;
|
||||
LONG ref;
|
||||
|
||||
FORMATETC *fmtetc;
|
||||
UINT fmtetc_cnt;
|
||||
|
||||
HANDLE unicode;
|
||||
HANDLE rtf;
|
||||
} DataObjectImpl;
|
||||
|
||||
typedef struct EnumFormatImpl {
|
||||
const IEnumFORMATETCVtbl *lpVtbl;
|
||||
LONG ref;
|
||||
|
||||
FORMATETC *fmtetc;
|
||||
UINT fmtetc_cnt;
|
||||
|
||||
UINT cur;
|
||||
} EnumFormatImpl;
|
||||
|
||||
static HRESULT EnumFormatImpl_Create(FORMATETC *fmtetc, UINT size, LPENUMFORMATETC *lplpformatetc);
|
||||
|
||||
static HRESULT WINAPI EnumFormatImpl_QueryInterface(IEnumFORMATETC *iface, REFIID riid, LPVOID *ppvObj)
|
||||
{
|
||||
EnumFormatImpl *This = (EnumFormatImpl*)iface;
|
||||
TRACE("%p %s\n", This, debugstr_guid(riid));
|
||||
|
||||
if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumFORMATETC)) {
|
||||
IEnumFORMATETC_AddRef(iface);
|
||||
*ppvObj = (LPVOID)This;
|
||||
return S_OK;
|
||||
}
|
||||
*ppvObj = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI EnumFormatImpl_AddRef(IEnumFORMATETC *iface)
|
||||
{
|
||||
EnumFormatImpl *This = (EnumFormatImpl*)iface;
|
||||
LONG ref = InterlockedIncrement(&This->ref);
|
||||
TRACE("(%p) ref=%d\n", This, ref);
|
||||
return ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI EnumFormatImpl_Release(IEnumFORMATETC *iface)
|
||||
{
|
||||
EnumFormatImpl *This = (EnumFormatImpl*)iface;
|
||||
ULONG ref = InterlockedDecrement(&This->ref);
|
||||
TRACE("(%p) ref=%d\n", This, ref);
|
||||
|
||||
if(!ref) {
|
||||
GlobalFree(This->fmtetc);
|
||||
richedit_free(This);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI EnumFormatImpl_Next(IEnumFORMATETC *iface, ULONG celt,
|
||||
FORMATETC *rgelt, ULONG *pceltFetched)
|
||||
{
|
||||
EnumFormatImpl *This = (EnumFormatImpl*)iface;
|
||||
ULONG count = 0;
|
||||
TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched);
|
||||
|
||||
if(!rgelt)
|
||||
return E_INVALIDARG;
|
||||
|
||||
count = min(celt, This->fmtetc_cnt-This->cur);
|
||||
if(count > 0) {
|
||||
memcpy(rgelt, This->fmtetc+This->cur, count*sizeof(FORMATETC));
|
||||
This->cur += count;
|
||||
}
|
||||
if(pceltFetched)
|
||||
*pceltFetched = count;
|
||||
return count == celt ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI EnumFormatImpl_Skip(IEnumFORMATETC *iface, ULONG celt)
|
||||
{
|
||||
EnumFormatImpl *This = (EnumFormatImpl*)iface;
|
||||
ULONG count = 0;
|
||||
TRACE("(%p)->(%d)\n", This, celt);
|
||||
|
||||
count = min(celt, This->fmtetc_cnt-This->cur);
|
||||
This->cur += count;
|
||||
return count == celt ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI EnumFormatImpl_Reset(IEnumFORMATETC *iface)
|
||||
{
|
||||
EnumFormatImpl *This = (EnumFormatImpl*)iface;
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
This->cur = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI EnumFormatImpl_Clone(IEnumFORMATETC *iface, IEnumFORMATETC **ppenum)
|
||||
{
|
||||
EnumFormatImpl *This = (EnumFormatImpl*)iface;
|
||||
HRESULT hr;
|
||||
TRACE("(%p)->(%p)\n", This, ppenum);
|
||||
|
||||
if(!ppenum)
|
||||
return E_INVALIDARG;
|
||||
hr = EnumFormatImpl_Create(This->fmtetc, This->fmtetc_cnt, ppenum);
|
||||
if(SUCCEEDED(hr))
|
||||
hr = IEnumFORMATETC_Skip(*ppenum, This->cur);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static const IEnumFORMATETCVtbl VT_EnumFormatImpl = {
|
||||
EnumFormatImpl_QueryInterface,
|
||||
EnumFormatImpl_AddRef,
|
||||
EnumFormatImpl_Release,
|
||||
EnumFormatImpl_Next,
|
||||
EnumFormatImpl_Skip,
|
||||
EnumFormatImpl_Reset,
|
||||
EnumFormatImpl_Clone
|
||||
};
|
||||
|
||||
static HRESULT EnumFormatImpl_Create(FORMATETC *fmtetc, UINT fmtetc_cnt, IEnumFORMATETC **lplpformatetc)
|
||||
{
|
||||
EnumFormatImpl *ret;
|
||||
TRACE("\n");
|
||||
|
||||
ret = richedit_alloc(sizeof(EnumFormatImpl));
|
||||
ret->lpVtbl = &VT_EnumFormatImpl;
|
||||
ret->ref = 1;
|
||||
ret->cur = 0;
|
||||
ret->fmtetc_cnt = fmtetc_cnt;
|
||||
ret->fmtetc = GlobalAlloc(GMEM_ZEROINIT, fmtetc_cnt*sizeof(FORMATETC));
|
||||
memcpy(ret->fmtetc, fmtetc, fmtetc_cnt*sizeof(FORMATETC));
|
||||
*lplpformatetc = (LPENUMFORMATETC)ret;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, LPVOID *ppvObj)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
TRACE("(%p)->(%s)\n", This, debugstr_guid(riid));
|
||||
|
||||
if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDataObject)) {
|
||||
IDataObject_AddRef(iface);
|
||||
*ppvObj = (LPVOID)This;
|
||||
return S_OK;
|
||||
}
|
||||
*ppvObj = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI DataObjectImpl_AddRef(IDataObject* iface)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
ULONG ref = InterlockedIncrement(&This->ref);
|
||||
TRACE("(%p) ref=%d\n", This, ref);
|
||||
return ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI DataObjectImpl_Release(IDataObject* iface)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
ULONG ref = InterlockedDecrement(&This->ref);
|
||||
TRACE("(%p) ref=%d\n",This, ref);
|
||||
|
||||
if(!ref) {
|
||||
if(This->unicode) GlobalFree(This->unicode);
|
||||
if(This->rtf) GlobalFree(This->rtf);
|
||||
if(This->fmtetc) GlobalFree(This->fmtetc);
|
||||
richedit_free(This);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DataObjectImpl_GetData(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", This, pformatetc->cfFormat, pformatetc->tymed);
|
||||
|
||||
if(pformatetc->lindex != -1)
|
||||
return DV_E_LINDEX;
|
||||
|
||||
if(!(pformatetc->tymed & TYMED_HGLOBAL))
|
||||
return DV_E_TYMED;
|
||||
|
||||
if(This->unicode && pformatetc->cfFormat == CF_UNICODETEXT)
|
||||
pmedium->u.hGlobal = This->unicode;
|
||||
else if(This->rtf && pformatetc->cfFormat == cfRTF)
|
||||
pmedium->u.hGlobal = This->rtf;
|
||||
else
|
||||
return DV_E_FORMATETC;
|
||||
|
||||
pmedium->tymed = TYMED_HGLOBAL;
|
||||
pmedium->pUnkForRelease = (LPUNKNOWN)iface;
|
||||
IUnknown_AddRef(pmedium->pUnkForRelease);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DataObjectImpl_GetDataHere(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
FIXME("(%p): stub\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DataObjectImpl_QueryGetData(IDataObject* iface, FORMATETC *pformatetc)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
UINT i;
|
||||
BOOL foundFormat = FALSE;
|
||||
TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", This, pformatetc->cfFormat, pformatetc->tymed);
|
||||
|
||||
if(pformatetc->lindex != -1)
|
||||
return DV_E_LINDEX;
|
||||
|
||||
for(i=0; i<This->fmtetc_cnt; i++) {
|
||||
if(This->fmtetc[i].cfFormat == pformatetc->cfFormat) {
|
||||
foundFormat = TRUE;
|
||||
if(This->fmtetc[i].tymed == pformatetc->tymed)
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
return foundFormat?DV_E_FORMATETC:DV_E_TYMED;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DataObjectImpl_GetCanonicalFormatEtc(IDataObject* iface, FORMATETC *pformatectIn,
|
||||
FORMATETC *pformatetcOut)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
TRACE("(%p)->(%p,%p)\n", This, pformatectIn, pformatetcOut);
|
||||
|
||||
if(pformatetcOut) {
|
||||
memcpy(pformatetcOut, pformatectIn, sizeof(FORMATETC));
|
||||
pformatetcOut->ptd = NULL;
|
||||
}
|
||||
return DATA_S_SAMEFORMATETC;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DataObjectImpl_SetData(IDataObject* iface, FORMATETC *pformatetc,
|
||||
STGMEDIUM *pmedium, BOOL fRelease)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
FIXME("(%p): stub\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DataObjectImpl_EnumFormatEtc(IDataObject* iface, DWORD dwDirection,
|
||||
IEnumFORMATETC **ppenumFormatEtc)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
TRACE("(%p)->(%d)\n", This, dwDirection);
|
||||
|
||||
if(dwDirection != DATADIR_GET) {
|
||||
FIXME("Unsupported direction: %d\n", dwDirection);
|
||||
/* WinXP riched20 also returns E_NOTIMPL in this case */
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
return EnumFormatImpl_Create(This->fmtetc, This->fmtetc_cnt, ppenumFormatEtc);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DataObjectImpl_DAdvise(IDataObject* iface, FORMATETC *pformatetc, DWORD advf,
|
||||
IAdviseSink *pAdvSink, DWORD *pdwConnection)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
FIXME("(%p): stub\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DataObjectImpl_DUnadvise(IDataObject* iface, DWORD dwConnection)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
FIXME("(%p): stub\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DataObjectImpl_EnumDAdvise(IDataObject* iface, IEnumSTATDATA **ppenumAdvise)
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
FIXME("(%p): stub\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static const IDataObjectVtbl VT_DataObjectImpl =
|
||||
{
|
||||
DataObjectImpl_QueryInterface,
|
||||
DataObjectImpl_AddRef,
|
||||
DataObjectImpl_Release,
|
||||
DataObjectImpl_GetData,
|
||||
DataObjectImpl_GetDataHere,
|
||||
DataObjectImpl_QueryGetData,
|
||||
DataObjectImpl_GetCanonicalFormatEtc,
|
||||
DataObjectImpl_SetData,
|
||||
DataObjectImpl_EnumFormatEtc,
|
||||
DataObjectImpl_DAdvise,
|
||||
DataObjectImpl_DUnadvise,
|
||||
DataObjectImpl_EnumDAdvise
|
||||
};
|
||||
|
||||
static HGLOBAL get_unicode_text(ME_TextEditor *editor, CHARRANGE *lpchrg)
|
||||
{
|
||||
int pars, len;
|
||||
WCHAR *data;
|
||||
HANDLE ret;
|
||||
|
||||
pars = ME_CountParagraphsBetween(editor, lpchrg->cpMin, lpchrg->cpMax);
|
||||
len = lpchrg->cpMax-lpchrg->cpMin;
|
||||
ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR)*(len+pars+1));
|
||||
data = (WCHAR *)GlobalLock(ret);
|
||||
len = ME_GetTextW(editor, data, lpchrg->cpMin, len, TRUE);
|
||||
data[len] = 0;
|
||||
GlobalUnlock(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct tagME_GlobalDestStruct
|
||||
{
|
||||
HGLOBAL hData;
|
||||
int nLength;
|
||||
} ME_GlobalDestStruct;
|
||||
|
||||
static DWORD CALLBACK ME_AppendToHGLOBAL(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb)
|
||||
{
|
||||
ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie;
|
||||
int nMaxSize;
|
||||
BYTE *pDest;
|
||||
|
||||
nMaxSize = GlobalSize(pData->hData);
|
||||
if (pData->nLength+cb+1 >= cb) {
|
||||
/* round up to 2^17 */
|
||||
int nNewSize = (((nMaxSize+cb+1)|0x1FFFF)+1) & 0xFFFE0000;
|
||||
pData->hData = GlobalReAlloc(pData->hData, nNewSize, 0);
|
||||
}
|
||||
pDest = (BYTE *)GlobalLock(pData->hData);
|
||||
memcpy(pDest + pData->nLength, lpBuff, cb);
|
||||
pData->nLength += cb;
|
||||
pDest[pData->nLength] = '\0';
|
||||
GlobalUnlock(pData->hData);
|
||||
*pcb = cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HGLOBAL get_rtf_text(ME_TextEditor *editor, CHARRANGE *lpchrg)
|
||||
{
|
||||
EDITSTREAM es;
|
||||
ME_GlobalDestStruct gds;
|
||||
|
||||
gds.hData = GlobalAlloc(GMEM_MOVEABLE, 0);
|
||||
gds.nLength = 0;
|
||||
es.dwCookie = (DWORD_PTR)&gds;
|
||||
es.pfnCallback = ME_AppendToHGLOBAL;
|
||||
ME_StreamOutRange(editor, SF_RTF, lpchrg->cpMin, lpchrg->cpMax, &es);
|
||||
GlobalReAlloc(gds.hData, gds.nLength+1, 0);
|
||||
return gds.hData;
|
||||
}
|
||||
|
||||
HRESULT ME_GetDataObject(ME_TextEditor *editor, CHARRANGE *lpchrg, LPDATAOBJECT *lplpdataobj)
|
||||
{
|
||||
DataObjectImpl *obj;
|
||||
TRACE("(%p,%d,%d)\n", editor, lpchrg->cpMin, lpchrg->cpMax);
|
||||
|
||||
obj = richedit_alloc(sizeof(DataObjectImpl));
|
||||
if(cfRTF == 0)
|
||||
cfRTF = RegisterClipboardFormatA("Rich Text Format");
|
||||
|
||||
obj->lpVtbl = &VT_DataObjectImpl;
|
||||
obj->ref = 1;
|
||||
obj->unicode = get_unicode_text(editor, lpchrg);
|
||||
obj->rtf = NULL;
|
||||
|
||||
obj->fmtetc_cnt = 1;
|
||||
if(editor->mode & TM_RICHTEXT)
|
||||
obj->fmtetc_cnt++;
|
||||
obj->fmtetc = GlobalAlloc(GMEM_ZEROINIT, obj->fmtetc_cnt*sizeof(FORMATETC));
|
||||
InitFormatEtc(obj->fmtetc[0], CF_UNICODETEXT, TYMED_HGLOBAL);
|
||||
if(editor->mode & TM_RICHTEXT) {
|
||||
obj->rtf = get_rtf_text(editor, lpchrg);
|
||||
InitFormatEtc(obj->fmtetc[1], cfRTF, TYMED_HGLOBAL);
|
||||
}
|
||||
|
||||
*lplpdataobj = (LPDATAOBJECT)obj;
|
||||
return S_OK;
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "editor.h"
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,14 +15,44 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "editstr.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
#define ALLOC_OBJ(type) HeapAlloc(me_heap, 0, sizeof(type))
|
||||
#define ALLOC_N_OBJ(type, count) HeapAlloc(me_heap, 0, (count)*sizeof(type))
|
||||
#define FREE_OBJ(ptr) HeapFree(me_heap, 0, ptr)
|
||||
extern HANDLE me_heap;
|
||||
|
||||
static inline void *richedit_alloc( size_t len )
|
||||
{
|
||||
return HeapAlloc( me_heap, 0, len );
|
||||
}
|
||||
|
||||
static inline BOOL richedit_free( void *ptr )
|
||||
{
|
||||
return HeapFree( me_heap, 0, ptr );
|
||||
}
|
||||
|
||||
static inline void *richedit_realloc( void *ptr, size_t len )
|
||||
{
|
||||
return HeapReAlloc( me_heap, 0, ptr, len );
|
||||
}
|
||||
|
||||
#define ALLOC_OBJ(type) richedit_alloc(sizeof(type))
|
||||
#define ALLOC_N_OBJ(type, count) richedit_alloc((count)*sizeof(type))
|
||||
#define FREE_OBJ(ptr) richedit_free(ptr)
|
||||
|
||||
#define RUN_IS_HIDDEN(run) ((run)->style->fmt.dwMask & CFM_HIDDEN \
|
||||
&& (run)->style->fmt.dwEffects & CFE_HIDDEN)
|
||||
|
||||
#define InitFormatEtc(fe, cf, med) \
|
||||
{\
|
||||
(fe).cfFormat=cf;\
|
||||
(fe).dwAspect=DVASPECT_CONTENT;\
|
||||
(fe).ptd=NULL;\
|
||||
(fe).tymed=med;\
|
||||
(fe).lindex=-1;\
|
||||
};
|
||||
|
||||
/* style.c */
|
||||
ME_Style *ME_MakeStyle(CHARFORMAT2W *style);
|
||||
|
@ -42,6 +72,7 @@ void ME_CopyToCF2W(CHARFORMAT2W *to, CHARFORMAT2W *from);
|
|||
CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from);
|
||||
void ME_CopyToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from);
|
||||
void ME_CopyCharFormat(CHARFORMAT2W *pDest, CHARFORMAT2W *pSrc); /* only works with 2W structs */
|
||||
void ME_CharFormatFromLogFont(HDC hDC, LOGFONTW *lf, CHARFORMAT2W *fmt); /* ditto */
|
||||
|
||||
/* list.c */
|
||||
void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat);
|
||||
|
@ -53,6 +84,7 @@ ME_DisplayItem *ME_FindItemFwdOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass)
|
|||
BOOL ME_DITypesEqual(ME_DIType type, ME_DIType nTypeOrClass);
|
||||
ME_DisplayItem *ME_MakeDI(ME_DIType type);
|
||||
void ME_DestroyDisplayItem(ME_DisplayItem *item);
|
||||
void ME_DestroyTableCellList(ME_DisplayItem *item);
|
||||
void ME_DumpDocument(ME_TextBuffer *buffer);
|
||||
const char *ME_GetDITypeName(ME_DIType type);
|
||||
|
||||
|
@ -60,6 +92,8 @@ const char *ME_GetDITypeName(ME_DIType type);
|
|||
int ME_GetOptimalBuffer(int nLen);
|
||||
ME_String *ME_MakeString(LPCWSTR szText);
|
||||
ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars);
|
||||
ME_String *ME_MakeStringR(WCHAR cRepeat, int nMaxChars);
|
||||
ME_String *ME_MakeStringB(int nMaxChars);
|
||||
ME_String *ME_StrDup(ME_String *s);
|
||||
void ME_DestroyString(ME_String *s);
|
||||
void ME_AppendString(ME_String *s1, ME_String *s2);
|
||||
|
@ -72,6 +106,7 @@ int ME_StrLen(ME_String *s);
|
|||
int ME_StrVLen(ME_String *s);
|
||||
int ME_FindNonWhitespaceV(ME_String *s, int nVChar);
|
||||
int ME_FindWhitespaceV(ME_String *s, int nVChar);
|
||||
int ME_CallWordBreakProc(ME_TextEditor *editor, ME_String *str, INT start, INT code);
|
||||
int ME_GetCharFwd(ME_String *s, int nPos); /* get char starting from start */
|
||||
int ME_GetCharBack(ME_String *s, int nPos); /* get char starting from \0 */
|
||||
int ME_StrRelPos(ME_String *s, int nVChar, int *pRelChars);
|
||||
|
@ -80,16 +115,19 @@ int ME_VPosToPos(ME_String *s, int nVPos);
|
|||
int ME_PosToVPos(ME_String *s, int nPos);
|
||||
void ME_StrDeleteV(ME_String *s, int nVChar, int nChars);
|
||||
/* smart helpers for A<->W conversions, they reserve/free memory and call MultiByte<->WideChar functions */
|
||||
LPWSTR ME_ToUnicode(HWND hWnd, LPVOID psz);
|
||||
void ME_EndToUnicode(HWND hWnd, LPVOID psz);
|
||||
LPSTR ME_ToAnsi(HWND hWnd, LPVOID psz);
|
||||
void ME_EndToAnsi(HWND hWnd, LPVOID psz);
|
||||
LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz);
|
||||
void ME_EndToUnicode(BOOL unicode, LPVOID psz);
|
||||
|
||||
static inline int ME_IsWSpace(WCHAR ch)
|
||||
{
|
||||
return ch > '\0' && ch <= ' ';
|
||||
}
|
||||
|
||||
static inline int ME_CharCompare(WCHAR a, WCHAR b, int caseSensitive)
|
||||
{
|
||||
return caseSensitive ? (a == b) : (toupperW(a) == toupperW(b));
|
||||
}
|
||||
|
||||
/* note: those two really return the first matching offset (starting from EOS)+1
|
||||
* in other words, an offset of the first trailing white/black */
|
||||
int ME_ReverseFindNonWhitespaceV(ME_String *s, int nVChar);
|
||||
|
@ -107,10 +145,12 @@ int ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs);
|
|||
ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags);
|
||||
/* note: ME_InsertRun inserts a copy of the specified run - so you need to destroy the original */
|
||||
ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem *pItem);
|
||||
ME_DisplayItem *ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor,
|
||||
ME_Style *style, const WCHAR *str, int len, int flags);
|
||||
void ME_CheckCharOffsets(ME_TextEditor *editor);
|
||||
void ME_PropagateCharOffset(ME_DisplayItem *p, int shift);
|
||||
void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize);
|
||||
int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Paragraph *para, ME_Run *run);
|
||||
int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run);
|
||||
/* this one accounts for 1/2 char tolerance */
|
||||
int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run);
|
||||
int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset);
|
||||
|
@ -136,7 +176,8 @@ void ME_GetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt);
|
|||
void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod);
|
||||
|
||||
/* caret.c */
|
||||
void ME_SetSelection(ME_TextEditor *editor, int from, int to);
|
||||
int ME_SetSelection(ME_TextEditor *editor, int from, int to);
|
||||
void ME_SelectWord(ME_TextEditor *editor);
|
||||
void ME_HideCaret(ME_TextEditor *ed);
|
||||
void ME_ShowCaret(ME_TextEditor *ed);
|
||||
void ME_MoveCaret(ME_TextEditor *ed);
|
||||
|
@ -147,13 +188,14 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y);
|
|||
void ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars);
|
||||
void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
||||
const WCHAR *str, int len, ME_Style *style);
|
||||
void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W *pFmt);
|
||||
BOOL ME_ArrowKey(ME_TextEditor *ed, int nVKey, int nCtrl);
|
||||
BOOL ME_ArrowKey(ME_TextEditor *ed, int nVKey, BOOL extend, BOOL ctrl);
|
||||
|
||||
void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC);
|
||||
void ME_DestroyContext(ME_Context *c);
|
||||
ME_Style *GetInsertStyle(ME_TextEditor *editor, int nCursor);
|
||||
void ME_MustBeWrapped(ME_Context *c, ME_DisplayItem *para);
|
||||
void ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
|
||||
int *x, int *y, int *height);
|
||||
int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor);
|
||||
void ME_GetSelection(ME_TextEditor *editor, int *from, int *to);
|
||||
int ME_CountParagraphsBetween(ME_TextEditor *editor, int from, int to);
|
||||
|
@ -161,6 +203,7 @@ BOOL ME_IsSelection(ME_TextEditor *editor);
|
|||
void ME_DeleteSelection(ME_TextEditor *editor);
|
||||
void ME_SendSelChange(ME_TextEditor *editor);
|
||||
void ME_InsertGraphicsFromCursor(ME_TextEditor *editor, int nCursor);
|
||||
void ME_InsertTableCellFromCursor(ME_TextEditor *editor, int nCursor);
|
||||
void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars);
|
||||
int ME_GetTextLength(ME_TextEditor *editor);
|
||||
int ME_GetTextLengthEx(ME_TextEditor *editor, GETTEXTLENGTHEX *how);
|
||||
|
@ -173,10 +216,12 @@ ME_DisplayItem *ME_MakeRow(int height, int baseline, int width);
|
|||
void ME_InsertRowStart(ME_WrapContext *wc, ME_DisplayItem *pEnd);
|
||||
void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp);
|
||||
BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor);
|
||||
void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor);
|
||||
void ME_SendRequestResize(ME_TextEditor *editor, BOOL force);
|
||||
|
||||
/* para.c */
|
||||
ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run);
|
||||
void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end);
|
||||
void ME_MakeFirstParagraph(HDC hDC, ME_TextBuffer *editor);
|
||||
ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style);
|
||||
ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp);
|
||||
|
@ -188,6 +233,7 @@ void ME_GetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, PARAFORMAT2 *
|
|||
void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt);
|
||||
/* marks from first up to (but not including) last */
|
||||
void ME_MarkForWrapping(ME_TextEditor *editor, ME_DisplayItem *first, ME_DisplayItem *last);
|
||||
void ME_MarkForPainting(ME_TextEditor *editor, ME_DisplayItem *first, ME_DisplayItem *last);
|
||||
void ME_MarkAllForWrapping(ME_TextEditor *editor);
|
||||
|
||||
/* paint.c */
|
||||
|
@ -196,23 +242,32 @@ void ME_Repaint(ME_TextEditor *editor);
|
|||
void ME_RewrapRepaint(ME_TextEditor *editor);
|
||||
void ME_UpdateRepaint(ME_TextEditor *editor);
|
||||
void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph);
|
||||
void ME_UpdateScrollBar(ME_TextEditor *editor);
|
||||
int ME_GetYScrollPos(ME_TextEditor *editor);
|
||||
void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun);
|
||||
COLORREF ME_GetBackColor(ME_TextEditor *editor);
|
||||
void ME_Scroll(ME_TextEditor *editor, int cx, int cy);
|
||||
void ME_InvalidateSelection(ME_TextEditor *editor);
|
||||
void ME_QueueInvalidateFromCursor(ME_TextEditor *editor, int nCursor);
|
||||
BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator);
|
||||
|
||||
/* scroll functions in paint.c */
|
||||
|
||||
void ME_ScrollAbs(ME_TextEditor *editor, int absY);
|
||||
void ME_ScrollUp(ME_TextEditor *editor, int cy);
|
||||
void ME_ScrollDown(ME_TextEditor *editor, int cy);
|
||||
void ME_Scroll(ME_TextEditor *editor, int value, int type);
|
||||
void ME_UpdateScrollBar(ME_TextEditor *editor);
|
||||
int ME_GetYScrollPos(ME_TextEditor *editor);
|
||||
BOOL ME_GetYScrollVisible(ME_TextEditor *editor);
|
||||
|
||||
/* richole.c */
|
||||
extern LRESULT CreateIRichEditOle(LPVOID *);
|
||||
extern LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *);
|
||||
|
||||
/* wintest.c */
|
||||
|
||||
/* editor.c */
|
||||
void ME_RegisterEditorClass(HINSTANCE hInstance);
|
||||
ME_TextEditor *ME_MakeEditor(HWND hWnd);
|
||||
void ME_DestroyEditor(ME_TextEditor *editor);
|
||||
void ME_SendOldNotify(ME_TextEditor *editor, int nCode);
|
||||
void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, ME_DisplayItem *di);
|
||||
void ME_CommitUndo(ME_TextEditor *editor);
|
||||
void ME_Undo(ME_TextEditor *editor);
|
||||
|
@ -221,10 +276,13 @@ void ME_EmptyUndoStack(ME_TextEditor *editor);
|
|||
int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, BOOL bCRLF);
|
||||
ME_DisplayItem *ME_FindItemAtOffset(ME_TextEditor *editor, ME_DIType nItemType, int nOffset, int *nItemOffset);
|
||||
void ME_StreamInFill(ME_InStream *stream);
|
||||
|
||||
int ME_AutoURLDetect(ME_TextEditor *editor, WCHAR curChar);
|
||||
extern int me_debug;
|
||||
extern HANDLE me_heap;
|
||||
extern void DoWrap(ME_TextEditor *editor);
|
||||
|
||||
/* writer.c */
|
||||
LRESULT ME_StreamOutRange(ME_TextEditor *editor, DWORD dwFormat, int nStart, int nTo, EDITSTREAM *stream);
|
||||
LRESULT ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream);
|
||||
|
||||
/* clipboard.c */
|
||||
HRESULT ME_GetDataObject(ME_TextEditor *editor, CHARRANGE *lpchrg, LPDATAOBJECT *lplpdataobj);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __EDITSTR_H
|
||||
|
@ -30,6 +30,10 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define COBJMACROS
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winnls.h>
|
||||
|
@ -38,6 +42,8 @@
|
|||
#include <winuser.h>
|
||||
#include <richedit.h>
|
||||
#include <commctrl.h>
|
||||
#include <ole2.h>
|
||||
#include <richole.h>
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -58,6 +64,7 @@ typedef struct tagME_Style
|
|||
} ME_Style;
|
||||
|
||||
typedef enum {
|
||||
diInvalid,
|
||||
diTextStart, /* start of the text buffer */
|
||||
diParagraph, /* paragraph start */
|
||||
diRun, /* run (sequence of chars with the same character format) */
|
||||
|
@ -88,6 +95,10 @@ typedef enum {
|
|||
#define MERF_GRAPHICS 1
|
||||
/* run is a tab (or, in future, any kind of content whose size is dependent on run position) */
|
||||
#define MERF_TAB 2
|
||||
/* run is a cell boundary */
|
||||
#define MERF_CELL 4
|
||||
|
||||
#define MERF_NONTEXT (MERF_GRAPHICS | MERF_TAB | MERF_CELL)
|
||||
|
||||
/* run is splittable (contains white spaces in the middle or end) */
|
||||
#define MERF_SPLITTABLE 0x001000
|
||||
|
@ -103,6 +114,8 @@ typedef enum {
|
|||
#define MERF_CALCBYWRAP 0x0F0000
|
||||
/* the "end of paragraph" run, contains 1 character */
|
||||
#define MERF_ENDPARA 0x100000
|
||||
/* run is hidden */
|
||||
#define MERF_HIDDEN 0x200000
|
||||
|
||||
/* runs with any of these flags set cannot be joined */
|
||||
#define MERF_NOJOIN (MERF_GRAPHICS|MERF_TAB|MERF_ENDPARA)
|
||||
|
@ -131,6 +144,7 @@ typedef struct tagME_Run
|
|||
int nFlags;
|
||||
int nAscent, nDescent; /* pixels above/below baseline */
|
||||
POINT pt; /* relative to para's position */
|
||||
struct tagME_TableCell *pCell; /* for MERF_CELL: points to respective cell in ME_Paragraph */
|
||||
} ME_Run;
|
||||
|
||||
typedef struct tagME_Document {
|
||||
|
@ -139,9 +153,20 @@ typedef struct tagME_Document {
|
|||
int last_wrapped_line;
|
||||
} ME_Document;
|
||||
|
||||
typedef struct tagME_TableCell
|
||||
{
|
||||
int nRightBoundary;
|
||||
struct tagME_TableCell *next;
|
||||
} ME_TableCell;
|
||||
|
||||
typedef struct tagME_Paragraph
|
||||
{
|
||||
PARAFORMAT2 *pFmt;
|
||||
|
||||
BOOL bTable; /* this paragraph is a table row */
|
||||
struct tagME_TableCell *pCells; /* list of cells and their properties */
|
||||
struct tagME_TableCell *pLastCell; /* points to the last cell in the list */
|
||||
|
||||
int nLeftMargin, nRightMargin, nFirstMargin;
|
||||
int nCharOfs;
|
||||
int nFlags;
|
||||
|
@ -268,23 +293,34 @@ typedef struct tagME_TextEditor
|
|||
int nTotalLength, nLastTotalLength;
|
||||
int nUDArrowX;
|
||||
int nSequence;
|
||||
int nOldSelFrom, nOldSelTo;
|
||||
COLORREF rgbBackColor;
|
||||
HBRUSH hbrBackground;
|
||||
BOOL bCaretAtEnd;
|
||||
int nEventMask;
|
||||
int nModifyStep;
|
||||
ME_DisplayItem *pUndoStack, *pRedoStack;
|
||||
ME_DisplayItem *pUndoStack, *pRedoStack, *pUndoStackBottom;
|
||||
int nUndoStackSize;
|
||||
int nUndoLimit;
|
||||
ME_UndoMode nUndoMode;
|
||||
int nParagraphs;
|
||||
int nLastSelStart, nLastSelEnd;
|
||||
ME_DisplayItem *pLastSelStartPara, *pLastSelEndPara;
|
||||
ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
|
||||
ME_OutStream *pStream;
|
||||
BOOL bScrollX, bScrollY;
|
||||
int nScrollPosY;
|
||||
int nZoomNumerator, nZoomDenominator;
|
||||
RECT rcFormat;
|
||||
BOOL bRedraw;
|
||||
int nInvalidOfs;
|
||||
int nTextLimit;
|
||||
EDITWORDBREAKPROCW pfnWordBreak;
|
||||
LPRICHEDITOLECALLBACK lpOleCallback;
|
||||
/*TEXTMODE variable; contains only one of each of the following options:
|
||||
*TM_RICHTEXT or TM_PLAINTEXT
|
||||
*TM_SINGLELEVELUNDO or TM_MULTILEVELUNDO
|
||||
*TM_SINGLECODEPAGE or TM_MULTICODEPAGE*/
|
||||
int mode;
|
||||
BOOL bHideSelection;
|
||||
BOOL AutoURLDetect_bEnable;
|
||||
WCHAR cPasswordMask;
|
||||
} ME_TextEditor;
|
||||
|
||||
typedef struct tagME_Context
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
|
@ -112,6 +112,7 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item) {
|
|||
/* TRACE("type=%s\n", ME_GetDITypeName(item->type)); */
|
||||
if (item->type==diParagraph || item->type == diUndoSetParagraphFormat) {
|
||||
FREE_OBJ(item->member.para.pFmt);
|
||||
ME_DestroyTableCellList(item);
|
||||
}
|
||||
if (item->type==diRun || item->type == diUndoInsertRun) {
|
||||
ME_ReleaseStyle(item->member.run.style);
|
||||
|
@ -120,9 +121,28 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item) {
|
|||
if (item->type==diUndoSetCharFormat || item->type==diUndoSetDefaultCharFormat) {
|
||||
ME_ReleaseStyle(item->member.ustyle);
|
||||
}
|
||||
if (item->type==diUndoSplitParagraph)
|
||||
FREE_OBJ(item->member.para.pFmt);
|
||||
FREE_OBJ(item);
|
||||
}
|
||||
|
||||
void
|
||||
ME_DestroyTableCellList(ME_DisplayItem *item)
|
||||
{
|
||||
if (item->member.para.pCells)
|
||||
{
|
||||
ME_TableCell *pCell = item->member.para.pCells;
|
||||
ME_TableCell *pNext;
|
||||
|
||||
while (pCell) {
|
||||
pNext = pCell->next;
|
||||
FREE_OBJ(pCell);
|
||||
pCell = pNext;
|
||||
}
|
||||
item->member.para.pCells = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ME_DisplayItem *ME_MakeDI(ME_DIType type) {
|
||||
ME_DisplayItem *item = ALLOC_OBJ(ME_DisplayItem);
|
||||
ZeroMemory(item, sizeof(ME_DisplayItem));
|
||||
|
@ -168,20 +188,20 @@ void ME_DumpDocument(ME_TextBuffer *buffer)
|
|||
switch(pItem->type)
|
||||
{
|
||||
case diTextStart:
|
||||
TRACE("Start");
|
||||
TRACE("Start\n");
|
||||
break;
|
||||
case diParagraph:
|
||||
TRACE("\nParagraph(ofs=%d)", pItem->member.para.nCharOfs);
|
||||
TRACE("Paragraph(ofs=%d)\n", pItem->member.para.nCharOfs);
|
||||
break;
|
||||
case diStartRow:
|
||||
TRACE(" - StartRow");
|
||||
TRACE(" - StartRow\n");
|
||||
break;
|
||||
case diRun:
|
||||
TRACE(" - Run(\"%s\", %d)", debugstr_w(pItem->member.run.strText->szData),
|
||||
TRACE(" - Run(\"%s\", %d)\n", debugstr_w(pItem->member.run.strText->szData),
|
||||
pItem->member.run.nCharOfs);
|
||||
break;
|
||||
case diTextEnd:
|
||||
TRACE("\nEnd(ofs=%d)\n", pItem->member.para.nCharOfs);
|
||||
TRACE("End(ofs=%d)\n", pItem->member.para.nCharOfs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* RichEdit - painting functions
|
||||
*
|
||||
* Copyright 2004 by Krzysztof Foltman
|
||||
* Copyright 2005 by Phil Krylov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -15,7 +16,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "editor.h"
|
||||
|
@ -93,95 +94,48 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, RECT *rcUpda
|
|||
ME_DestroyContext(&c);
|
||||
}
|
||||
|
||||
static void ME_MarkParagraphRange(ME_TextEditor *editor, ME_DisplayItem *p1,
|
||||
ME_DisplayItem *p2, int nFlags)
|
||||
{
|
||||
ME_DisplayItem *p3;
|
||||
if (p1 == p2)
|
||||
{
|
||||
p1->member.para.nFlags |= nFlags;
|
||||
return;
|
||||
}
|
||||
if (p1->member.para.nCharOfs > p2->member.para.nCharOfs)
|
||||
p3 = p1, p1 = p2, p2 = p3;
|
||||
|
||||
p1->member.para.nFlags |= nFlags;
|
||||
do {
|
||||
p1 = p1->member.para.next_para;
|
||||
p1->member.para.nFlags |= nFlags;
|
||||
} while (p1 != p2);
|
||||
}
|
||||
|
||||
static void ME_MarkOffsetRange(ME_TextEditor *editor, int from, int to, int nFlags)
|
||||
{
|
||||
ME_Cursor c1, c2;
|
||||
ME_CursorFromCharOfs(editor, from, &c1);
|
||||
ME_CursorFromCharOfs(editor, to, &c2);
|
||||
|
||||
ME_MarkParagraphRange(editor, ME_GetParagraph(c1.pRun), ME_GetParagraph(c2.pRun), nFlags);
|
||||
}
|
||||
|
||||
static void ME_MarkSelectionForRepaint(ME_TextEditor *editor)
|
||||
{
|
||||
int from, to, from2, to2, end;
|
||||
|
||||
end = ME_GetTextLength(editor);
|
||||
ME_GetSelection(editor, &from, &to);
|
||||
from2 = editor->nLastSelStart;
|
||||
to2 = editor->nLastSelEnd;
|
||||
if (from<from2) ME_MarkOffsetRange(editor, from, from2, MEPF_REPAINT);
|
||||
if (from>from2) ME_MarkOffsetRange(editor, from2, from, MEPF_REPAINT);
|
||||
if (to<to2) ME_MarkOffsetRange(editor, to, to2, MEPF_REPAINT);
|
||||
if (to>to2) ME_MarkOffsetRange(editor, to2, to, MEPF_REPAINT);
|
||||
|
||||
editor->nLastSelStart = from;
|
||||
editor->nLastSelEnd = to;
|
||||
}
|
||||
|
||||
void ME_Repaint(ME_TextEditor *editor)
|
||||
{
|
||||
ME_Cursor *pCursor = &editor->pCursors[0];
|
||||
ME_DisplayItem *pRun = NULL;
|
||||
int nOffset = -1;
|
||||
HDC hDC;
|
||||
int nCharOfs = ME_CharOfsFromRunOfs(editor, pCursor->pRun, pCursor->nOffset);
|
||||
|
||||
ME_RunOfsFromCharOfs(editor, nCharOfs, &pRun, &nOffset);
|
||||
assert(pRun == pCursor->pRun);
|
||||
assert(nOffset == pCursor->nOffset);
|
||||
ME_MarkSelectionForRepaint(editor);
|
||||
if (ME_WrapMarkedParagraphs(editor)) {
|
||||
ME_UpdateScrollBar(editor);
|
||||
}
|
||||
if (editor->bRedraw)
|
||||
if (ME_WrapMarkedParagraphs(editor))
|
||||
{
|
||||
hDC = GetDC(editor->hWnd);
|
||||
ME_HideCaret(editor);
|
||||
ME_PaintContent(editor, hDC, TRUE, NULL);
|
||||
ReleaseDC(editor->hWnd, hDC);
|
||||
ME_ShowCaret(editor);
|
||||
ME_EnsureVisible(editor, pCursor->pRun);
|
||||
ME_UpdateScrollBar(editor);
|
||||
FIXME("ME_Repaint had to call ME_WrapMarkedParagraphs\n");
|
||||
}
|
||||
ME_SendOldNotify(editor, EN_UPDATE);
|
||||
UpdateWindow(editor->hWnd);
|
||||
}
|
||||
|
||||
void ME_UpdateRepaint(ME_TextEditor *editor)
|
||||
{
|
||||
/*
|
||||
InvalidateRect(editor->hWnd, NULL, TRUE);
|
||||
*/
|
||||
ME_SendOldNotify(editor, EN_CHANGE);
|
||||
/* Should be called whenever the contents of the control have changed */
|
||||
ME_Cursor *pCursor;
|
||||
|
||||
if (ME_WrapMarkedParagraphs(editor))
|
||||
ME_UpdateScrollBar(editor);
|
||||
|
||||
/* Ensure that the cursor is visible */
|
||||
pCursor = &editor->pCursors[0];
|
||||
ME_EnsureVisible(editor, pCursor->pRun);
|
||||
|
||||
/* send EN_CHANGE if the event mask asks for it */
|
||||
if(editor->nEventMask & ENM_CHANGE)
|
||||
{
|
||||
ME_SendOldNotify(editor, EN_CHANGE);
|
||||
}
|
||||
ME_Repaint(editor);
|
||||
ME_SendOldNotify(editor, EN_UPDATE);
|
||||
ME_SendSelChange(editor);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ME_RewrapRepaint(ME_TextEditor *editor)
|
||||
{
|
||||
{
|
||||
/* RewrapRepaint should be called whenever the control has changed in
|
||||
* looks, but not content. Like resizing. */
|
||||
|
||||
ME_MarkAllForWrapping(editor);
|
||||
ME_WrapMarkedParagraphs(editor);
|
||||
ME_UpdateScrollBar(editor);
|
||||
|
||||
ME_Repaint(editor);
|
||||
}
|
||||
|
||||
|
@ -194,7 +148,9 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, in
|
|||
int yOffset = 0, yTwipsOffset = 0;
|
||||
hOldFont = ME_SelectStyleFont(c->editor, hDC, s);
|
||||
rgbBack = ME_GetBackColor(c->editor);
|
||||
if ((s->fmt.dwMask & CFM_COLOR) && (s->fmt.dwEffects & CFE_AUTOCOLOR))
|
||||
if ((s->fmt.dwMask & CFM_LINK) && (s->fmt.dwEffects & CFE_LINK))
|
||||
rgbOld = SetTextColor(hDC, RGB(0,0,255));
|
||||
else if ((s->fmt.dwMask & CFM_COLOR) && (s->fmt.dwEffects & CFE_AUTOCOLOR))
|
||||
rgbOld = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
|
||||
else
|
||||
rgbOld = SetTextColor(hDC, s->fmt.crTextColor);
|
||||
|
@ -231,7 +187,10 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, in
|
|||
GetTextExtentPoint32W(hDC, szText, nSelFrom, &sz);
|
||||
x += sz.cx;
|
||||
GetTextExtentPoint32W(hDC, szText+nSelFrom, nSelTo-nSelFrom, &sz);
|
||||
PatBlt(hDC, x, ymin, sz.cx, cy, DSTINVERT);
|
||||
|
||||
/* Invert selection if not hidden by EM_HIDESELECTION */
|
||||
if (c->editor->bHideSelection == FALSE)
|
||||
PatBlt(hDC, x, ymin, sz.cx, cy, DSTINVERT);
|
||||
}
|
||||
SetTextColor(hDC, rgbOld);
|
||||
ME_UnselectStyleFont(c->editor, hDC, s, hOldFont);
|
||||
|
@ -247,8 +206,8 @@ static void ME_DebugWrite(HDC hDC, POINT *pt, WCHAR *szText) {
|
|||
SetTextColor(hDC, color);
|
||||
}
|
||||
|
||||
void ME_DrawGraphics(ME_Context *c, int x, int y, ME_Run *run,
|
||||
ME_Paragraph *para, BOOL selected) {
|
||||
static void ME_DrawGraphics(ME_Context *c, int x, int y, ME_Run *run,
|
||||
ME_Paragraph *para, BOOL selected) {
|
||||
SIZE sz;
|
||||
int xs, ys, xe, ye, h, ym, width, eyes;
|
||||
ME_GetGraphicsSize(c->editor, run, &sz);
|
||||
|
@ -275,27 +234,46 @@ void ME_DrawGraphics(ME_Context *c, int x, int y, ME_Run *run,
|
|||
}
|
||||
}
|
||||
|
||||
static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Paragraph *para) {
|
||||
static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Paragraph *para)
|
||||
{
|
||||
ME_Run *run = &rundi->member.run;
|
||||
ME_DisplayItem *start = ME_FindItemBack(rundi, diStartRow);
|
||||
int runofs = run->nCharOfs+para->nCharOfs;
|
||||
int nSelFrom, nSelTo;
|
||||
const WCHAR wszSpace[] = {' ', 0};
|
||||
|
||||
/* you can always comment it out if you need visible paragraph marks */
|
||||
if (run->nFlags & (MERF_ENDPARA|MERF_TAB))
|
||||
if (run->nFlags & MERF_HIDDEN)
|
||||
return;
|
||||
if (run->nFlags & MERF_GRAPHICS) {
|
||||
int blfrom, blto;
|
||||
ME_GetSelection(c->editor, &blfrom, &blto);
|
||||
ME_DrawGraphics(c, x, y, run, para, (runofs >= blfrom) && (runofs < blto));
|
||||
} else
|
||||
|
||||
ME_GetSelection(c->editor, &nSelFrom, &nSelTo);
|
||||
|
||||
/* Draw selected end-of-paragraph mark */
|
||||
if (run->nFlags & MERF_ENDPARA && runofs >= nSelFrom && runofs < nSelTo)
|
||||
ME_DrawTextWithStyle(c, x, y, wszSpace, 1, run->style, NULL, 0, 1,
|
||||
c->pt.y + start->member.row.nYPos,
|
||||
start->member.row.nHeight);
|
||||
|
||||
/* you can always comment it out if you need visible paragraph marks */
|
||||
if (run->nFlags & (MERF_ENDPARA | MERF_TAB | MERF_CELL))
|
||||
return;
|
||||
|
||||
if (run->nFlags & MERF_GRAPHICS)
|
||||
ME_DrawGraphics(c, x, y, run, para, (runofs >= nSelFrom) && (runofs < nSelTo));
|
||||
else
|
||||
{
|
||||
int blfrom, blto;
|
||||
ME_DisplayItem *start = ME_FindItemBack(rundi, diStartRow);
|
||||
ME_GetSelection(c->editor, &blfrom, &blto);
|
||||
|
||||
ME_DrawTextWithStyle(c, x, y,
|
||||
run->strText->szData, ME_StrVLen(run->strText), run->style, NULL,
|
||||
blfrom-runofs, blto-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight);
|
||||
}
|
||||
if (c->editor->cPasswordMask)
|
||||
{
|
||||
ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,ME_StrVLen(run->strText));
|
||||
ME_DrawTextWithStyle(c, x, y,
|
||||
szMasked->szData, ME_StrVLen(szMasked), run->style, NULL,
|
||||
nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight);
|
||||
ME_DestroyString(szMasked);
|
||||
}
|
||||
else
|
||||
ME_DrawTextWithStyle(c, x, y,
|
||||
run->strText->szData, ME_StrVLen(run->strText), run->style, NULL,
|
||||
nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight);
|
||||
}
|
||||
}
|
||||
|
||||
COLORREF ME_GetBackColor(ME_TextEditor *editor)
|
||||
|
@ -378,7 +356,7 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
|
|||
rc.right = c->rcView.left+run->pt.x+run->nWidth;
|
||||
rc.top = c->pt.y+run->pt.y;
|
||||
rc.bottom = c->pt.y+run->pt.y+height;
|
||||
TRACE("rc = (%ld, %ld, %ld, %ld)\n", rc.left, rc.top, rc.right, rc.bottom);
|
||||
TRACE("rc = (%d, %d, %d, %d)\n", rc.left, rc.top, rc.right, rc.bottom);
|
||||
if (run->nFlags & MERF_SKIPPED)
|
||||
DrawFocusRect(c->hDC, &rc);
|
||||
else
|
||||
|
@ -407,80 +385,118 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
|
|||
SetTextAlign(c->hDC, align);
|
||||
}
|
||||
|
||||
void ME_Scroll(ME_TextEditor *editor, int cx, int cy)
|
||||
void ME_ScrollAbs(ME_TextEditor *editor, int absY)
|
||||
{
|
||||
SCROLLINFO si;
|
||||
HWND hWnd = editor->hWnd;
|
||||
|
||||
si.cbSize = sizeof(SCROLLINFO);
|
||||
si.fMask = SIF_POS;
|
||||
GetScrollInfo(hWnd, SB_VERT, &si);
|
||||
si.nPos = editor->nScrollPosY -= cy;
|
||||
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
|
||||
if (editor->bRedraw)
|
||||
{
|
||||
if (abs(cy) > editor->sizeWindow.cy)
|
||||
InvalidateRect(editor->hWnd, NULL, TRUE);
|
||||
else
|
||||
ScrollWindowEx(hWnd, cx, cy, NULL, NULL, NULL, NULL, SW_ERASE|SW_INVALIDATE);
|
||||
}
|
||||
ME_Scroll(editor, absY, 1);
|
||||
}
|
||||
|
||||
void ME_UpdateScrollBar(ME_TextEditor *editor)
|
||||
void ME_ScrollUp(ME_TextEditor *editor, int cy)
|
||||
{
|
||||
ME_Scroll(editor, cy, 2);
|
||||
}
|
||||
|
||||
void ME_ScrollDown(ME_TextEditor *editor, int cy)
|
||||
{
|
||||
ME_Scroll(editor, cy, 3);
|
||||
}
|
||||
|
||||
void ME_Scroll(ME_TextEditor *editor, int value, int type)
|
||||
{
|
||||
HWND hWnd = editor->hWnd;
|
||||
SCROLLINFO si;
|
||||
int nOldLen = editor->nTotalLength;
|
||||
BOOL bScrollY = (editor->nTotalLength > editor->sizeWindow.cy);
|
||||
BOOL bUpdateScrollBars;
|
||||
si.cbSize = sizeof(si);
|
||||
si.fMask = SIF_POS | SIF_RANGE;
|
||||
GetScrollInfo(hWnd, SB_VERT, &si);
|
||||
bUpdateScrollBars = (bScrollY || editor->bScrollY)&& ((si.nMax != nOldLen) || (si.nPage != editor->sizeWindow.cy));
|
||||
int nOrigPos, nNewPos, nActualScroll;
|
||||
|
||||
nOrigPos = ME_GetYScrollPos(editor);
|
||||
|
||||
if (bScrollY != editor->bScrollY)
|
||||
si.cbSize = sizeof(SCROLLINFO);
|
||||
si.fMask = SIF_POS;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
si.fMask = SIF_RANGE | SIF_PAGE;
|
||||
si.nMin = 0;
|
||||
si.nPage = editor->sizeWindow.cy;
|
||||
if (bScrollY) {
|
||||
si.nMax = editor->nTotalLength;
|
||||
} else {
|
||||
si.nMax = 0;
|
||||
}
|
||||
SetScrollInfo(hWnd, SB_VERT, &si, FALSE);
|
||||
ME_MarkAllForWrapping(editor);
|
||||
editor->bScrollY = bScrollY;
|
||||
ME_WrapMarkedParagraphs(editor);
|
||||
bUpdateScrollBars = TRUE;
|
||||
}
|
||||
if (bUpdateScrollBars) {
|
||||
int nScroll = 0;
|
||||
si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
|
||||
if (editor->nTotalLength > editor->sizeWindow.cy) {
|
||||
si.nMax = editor->nTotalLength;
|
||||
si.nPage = editor->sizeWindow.cy;
|
||||
if (si.nPos > si.nMax-si.nPage) {
|
||||
nScroll = (si.nMax-si.nPage)-si.nPos;
|
||||
si.nPos = si.nMax-si.nPage;
|
||||
}
|
||||
}
|
||||
else {
|
||||
si.nMax = 0;
|
||||
si.nPage = 0;
|
||||
case 1:
|
||||
/*Scroll absolutly*/
|
||||
si.nPos = value;
|
||||
break;
|
||||
case 2:
|
||||
/* Scroll up - towards the beginning of the document */
|
||||
si.nPos = nOrigPos - value;
|
||||
break;
|
||||
case 3:
|
||||
/* Scroll down - towards the end of the document */
|
||||
si.nPos = nOrigPos + value;
|
||||
break;
|
||||
default:
|
||||
FIXME("ME_Scroll called incorrectly\n");
|
||||
si.nPos = 0;
|
||||
}
|
||||
TRACE("min=%d max=%d page=%d pos=%d shift=%d\n", si.nMin, si.nMax, si.nPage, si.nPos, nScroll);
|
||||
editor->nScrollPosY = si.nPos;
|
||||
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
|
||||
if (nScroll)
|
||||
ScrollWindow(hWnd, 0, -nScroll, NULL, NULL);
|
||||
}
|
||||
|
||||
nNewPos = SetScrollInfo(editor->hWnd, SB_VERT, &si, editor->bRedraw);
|
||||
nActualScroll = nOrigPos - nNewPos;
|
||||
if (editor->bRedraw)
|
||||
{
|
||||
if (abs(nActualScroll) > editor->sizeWindow.cy)
|
||||
InvalidateRect(editor->hWnd, NULL, TRUE);
|
||||
else
|
||||
ScrollWindowEx(editor->hWnd, 0, nActualScroll, NULL, NULL, NULL, NULL, SW_INVALIDATE);
|
||||
ME_Repaint(editor);
|
||||
}
|
||||
|
||||
ME_UpdateScrollBar(editor);
|
||||
}
|
||||
|
||||
|
||||
void ME_UpdateScrollBar(ME_TextEditor *editor)
|
||||
{
|
||||
/* Note that this is the only funciton that should ever call SetScrolLInfo
|
||||
* with SIF_PAGE or SIF_RANGE. SetScrollPos and SetScrollRange should never
|
||||
* be used at all. */
|
||||
|
||||
HWND hWnd;
|
||||
SCROLLINFO si;
|
||||
BOOL bScrollBarWasVisible,bScrollBarWillBeVisible;
|
||||
|
||||
if (ME_WrapMarkedParagraphs(editor))
|
||||
FIXME("ME_UpdateScrollBar had to call ME_WrapMarkedParagraphs\n");
|
||||
|
||||
hWnd = editor->hWnd;
|
||||
si.cbSize = sizeof(si);
|
||||
bScrollBarWasVisible = ME_GetYScrollVisible(editor);
|
||||
bScrollBarWillBeVisible = editor->nTotalLength > editor->sizeWindow.cy;
|
||||
|
||||
if (bScrollBarWasVisible != bScrollBarWillBeVisible)
|
||||
{
|
||||
ShowScrollBar(hWnd, SB_VERT, bScrollBarWillBeVisible);
|
||||
ME_MarkAllForWrapping(editor);
|
||||
ME_WrapMarkedParagraphs(editor);
|
||||
}
|
||||
|
||||
si.fMask = SIF_PAGE | SIF_RANGE;
|
||||
if (GetWindowLongW(hWnd, GWL_STYLE) & ES_DISABLENOSCROLL)
|
||||
si.fMask |= SIF_DISABLENOSCROLL;
|
||||
|
||||
si.nMin = 0;
|
||||
si.nMax = editor->nTotalLength;
|
||||
|
||||
si.nPage = editor->sizeWindow.cy;
|
||||
|
||||
TRACE("min=%d max=%d page=%d\n", si.nMin, si.nMax, si.nPage);
|
||||
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
|
||||
}
|
||||
|
||||
int ME_GetYScrollPos(ME_TextEditor *editor)
|
||||
{
|
||||
return editor->nScrollPosY;
|
||||
SCROLLINFO si;
|
||||
si.cbSize = sizeof(si);
|
||||
si.fMask = SIF_POS;
|
||||
GetScrollInfo(editor->hWnd, SB_VERT, &si);
|
||||
return si.nPos;
|
||||
}
|
||||
|
||||
BOOL ME_GetYScrollVisible(ME_TextEditor *editor)
|
||||
{ /* Returns true if the scrollbar is visible */
|
||||
SCROLLBARINFO sbi;
|
||||
sbi.cbSize = sizeof(sbi);
|
||||
GetScrollBarInfo(editor->hWnd, OBJID_VSCROLL, &sbi);
|
||||
return ((sbi.rgstate[0] & STATE_SYSTEM_INVISIBLE) == 0);
|
||||
}
|
||||
|
||||
void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun)
|
||||
|
@ -488,7 +504,6 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun)
|
|||
ME_DisplayItem *pRow = ME_FindItemBack(pRun, diStartRow);
|
||||
ME_DisplayItem *pPara = ME_FindItemBack(pRun, diParagraph);
|
||||
int y, yrel, yheight, yold;
|
||||
HWND hWnd = editor->hWnd;
|
||||
|
||||
assert(pRow);
|
||||
assert(pPara);
|
||||
|
@ -497,26 +512,85 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun)
|
|||
yheight = pRow->member.row.nHeight;
|
||||
yold = ME_GetYScrollPos(editor);
|
||||
yrel = y - yold;
|
||||
if (yrel < 0) {
|
||||
editor->nScrollPosY = y;
|
||||
SetScrollPos(hWnd, SB_VERT, y, TRUE);
|
||||
if (editor->bRedraw)
|
||||
{
|
||||
ScrollWindow(hWnd, 0, -yrel, NULL, NULL);
|
||||
UpdateWindow(hWnd);
|
||||
}
|
||||
} else if (yrel + yheight > editor->sizeWindow.cy) {
|
||||
int newy = y+yheight-editor->sizeWindow.cy;
|
||||
editor->nScrollPosY = newy;
|
||||
SetScrollPos(hWnd, SB_VERT, newy, TRUE);
|
||||
if (editor->bRedraw)
|
||||
{
|
||||
ScrollWindow(hWnd, 0, -(newy-yold), NULL, NULL);
|
||||
UpdateWindow(hWnd);
|
||||
}
|
||||
}
|
||||
|
||||
if (y < yold)
|
||||
ME_ScrollAbs(editor,y);
|
||||
else if (yrel + yheight > editor->sizeWindow.cy)
|
||||
ME_ScrollAbs(editor,y+yheight-editor->sizeWindow.cy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ME_InvalidateFromOfs(ME_TextEditor *editor, int nCharOfs)
|
||||
{
|
||||
RECT rc;
|
||||
int x, y, height;
|
||||
ME_Cursor tmp;
|
||||
|
||||
ME_RunOfsFromCharOfs(editor, nCharOfs, &tmp.pRun, &tmp.nOffset);
|
||||
ME_GetCursorCoordinates(editor, &tmp, &x, &y, &height);
|
||||
|
||||
rc.left = 0;
|
||||
rc.top = y;
|
||||
rc.bottom = y + height;
|
||||
rc.right = editor->rcFormat.right;
|
||||
InvalidateRect(editor->hWnd, &rc, FALSE);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ME_InvalidateSelection(ME_TextEditor *editor)
|
||||
{
|
||||
ME_DisplayItem *para1, *para2;
|
||||
int nStart, nEnd;
|
||||
int len = ME_GetTextLength(editor);
|
||||
|
||||
ME_GetSelection(editor, &nStart, &nEnd);
|
||||
/* if both old and new selection are 0-char (= caret only), then
|
||||
there's no (inverted) area to be repainted, neither old nor new */
|
||||
if (nStart == nEnd && editor->nLastSelStart == editor->nLastSelEnd)
|
||||
return;
|
||||
ME_WrapMarkedParagraphs(editor);
|
||||
ME_GetSelectionParas(editor, ¶1, ¶2);
|
||||
assert(para1->type == diParagraph);
|
||||
assert(para2->type == diParagraph);
|
||||
/* last selection markers aren't always updated, which means
|
||||
they can point past the end of the document */
|
||||
if (editor->nLastSelStart > len)
|
||||
editor->nLastSelEnd = len;
|
||||
if (editor->nLastSelEnd > len)
|
||||
editor->nLastSelEnd = len;
|
||||
|
||||
/* if the start part of selection is being expanded or contracted... */
|
||||
if (nStart < editor->nLastSelStart) {
|
||||
ME_MarkForPainting(editor, para1, ME_FindItemFwd(editor->pLastSelStartPara, diParagraphOrEnd));
|
||||
} else
|
||||
if (nStart > editor->nLastSelStart) {
|
||||
ME_MarkForPainting(editor, editor->pLastSelStartPara, ME_FindItemFwd(para1, diParagraphOrEnd));
|
||||
}
|
||||
|
||||
/* if the end part of selection is being contracted or expanded... */
|
||||
if (nEnd < editor->nLastSelEnd) {
|
||||
ME_MarkForPainting(editor, para2, ME_FindItemFwd(editor->pLastSelEndPara, diParagraphOrEnd));
|
||||
} else
|
||||
if (nEnd > editor->nLastSelEnd) {
|
||||
ME_MarkForPainting(editor, editor->pLastSelEndPara, ME_FindItemFwd(para2, diParagraphOrEnd));
|
||||
}
|
||||
|
||||
ME_InvalidateMarkedParagraphs(editor);
|
||||
/* remember the last invalidated position */
|
||||
ME_GetSelection(editor, &editor->nLastSelStart, &editor->nLastSelEnd);
|
||||
ME_GetSelectionParas(editor, &editor->pLastSelStartPara, &editor->pLastSelEndPara);
|
||||
assert(editor->pLastSelStartPara->type == diParagraph);
|
||||
assert(editor->pLastSelEndPara->type == diParagraph);
|
||||
}
|
||||
|
||||
void
|
||||
ME_QueueInvalidateFromCursor(ME_TextEditor *editor, int nCursor)
|
||||
{
|
||||
editor->nInvalidOfs = ME_GetCursorOfs(editor, nCursor);
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* RichEdit - functions working on paragraphs of text (diParagraph).
|
||||
*
|
||||
* Copyright 2004 by Krzysztof Foltman
|
||||
* Copyright 2006 by Phil Krylov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -15,14 +16,14 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "editor.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||
|
||||
static WCHAR wszParagraphSign[] = {0xB6, 0};
|
||||
static const WCHAR wszParagraphSign[] = {0xB6, 0};
|
||||
|
||||
void ME_MakeFirstParagraph(HDC hDC, ME_TextBuffer *text)
|
||||
{
|
||||
|
@ -91,6 +92,15 @@ void ME_MarkForWrapping(ME_TextEditor *editor, ME_DisplayItem *first, ME_Display
|
|||
}
|
||||
}
|
||||
|
||||
void ME_MarkForPainting(ME_TextEditor *editor, ME_DisplayItem *first, ME_DisplayItem *last)
|
||||
{
|
||||
while(first != last)
|
||||
{
|
||||
first->member.para.nFlags |= MEPF_REPAINT;
|
||||
first = first->member.para.next_para;
|
||||
}
|
||||
}
|
||||
|
||||
/* split paragraph at the beginning of the run */
|
||||
ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME_Style *style)
|
||||
{
|
||||
|
@ -133,6 +143,35 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME
|
|||
new_para->member.para.nLeftMargin = run_para->member.para.nLeftMargin;
|
||||
new_para->member.para.nRightMargin = run_para->member.para.nRightMargin;
|
||||
new_para->member.para.nFirstMargin = run_para->member.para.nFirstMargin;
|
||||
|
||||
new_para->member.para.bTable = run_para->member.para.bTable;
|
||||
|
||||
/* Inherit previous cell definitions if any */
|
||||
new_para->member.para.pCells = NULL;
|
||||
if (run_para->member.para.pCells)
|
||||
{
|
||||
ME_TableCell *pCell, *pNewCell;
|
||||
|
||||
for (pCell = run_para->member.para.pCells; pCell; pCell = pCell->next)
|
||||
{
|
||||
pNewCell = ALLOC_OBJ(ME_TableCell);
|
||||
pNewCell->nRightBoundary = pCell->nRightBoundary;
|
||||
pNewCell->next = NULL;
|
||||
if (new_para->member.para.pCells)
|
||||
new_para->member.para.pLastCell->next = pNewCell;
|
||||
else
|
||||
new_para->member.para.pCells = pNewCell;
|
||||
new_para->member.para.pLastCell = pNewCell;
|
||||
}
|
||||
}
|
||||
|
||||
/* fix paragraph properties. FIXME only needed when called from RTF reader */
|
||||
if (run_para->member.para.pCells && !run_para->member.para.bTable)
|
||||
{
|
||||
/* Paragraph does not have an \intbl keyword, so any table definition
|
||||
* stored is invalid */
|
||||
ME_DestroyTableCellList(run_para);
|
||||
}
|
||||
|
||||
/* insert paragraph into paragraph double linked list */
|
||||
new_para->member.para.prev_para = run_para;
|
||||
|
@ -215,6 +254,11 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp)
|
|||
ME_Remove(pRun);
|
||||
ME_DestroyDisplayItem(pRun);
|
||||
|
||||
if (editor->pLastSelStartPara == pNext)
|
||||
editor->pLastSelStartPara = tp;
|
||||
if (editor->pLastSelEndPara == pNext)
|
||||
editor->pLastSelEndPara = tp;
|
||||
|
||||
tp->member.para.next_para = pNext->member.para.next_para;
|
||||
pNext->member.para.next_para->member.para.prev_para = tp;
|
||||
ME_Remove(pNext);
|
||||
|
@ -303,21 +347,37 @@ void ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, PARAFORMAT2 *
|
|||
para->member.para.nFlags |= MEPF_REWRAP;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end)
|
||||
{
|
||||
ME_Cursor *pEndCursor = &editor->pCursors[1];
|
||||
|
||||
*para = ME_GetParagraph(editor->pCursors[0].pRun);
|
||||
*para_end = ME_GetParagraph(editor->pCursors[1].pRun);
|
||||
if ((*para_end)->member.para.nCharOfs < (*para)->member.para.nCharOfs) {
|
||||
ME_DisplayItem *tmp = *para;
|
||||
|
||||
*para = *para_end;
|
||||
*para_end = tmp;
|
||||
pEndCursor = &editor->pCursors[0];
|
||||
}
|
||||
|
||||
/* selection consists of chars from nFrom up to nTo-1 */
|
||||
if ((*para_end)->member.para.nCharOfs > (*para)->member.para.nCharOfs) {
|
||||
if (!pEndCursor->nOffset) {
|
||||
*para_end = ME_GetParagraph(ME_FindItemBack(pEndCursor->pRun, diRun));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ME_SetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
|
||||
{
|
||||
int nFrom, nTo;
|
||||
ME_DisplayItem *para, *para_end, *run;
|
||||
int nOffset;
|
||||
|
||||
ME_GetSelection(editor, &nFrom, &nTo);
|
||||
if (nTo>nFrom) /* selection consists of chars from nFrom up to nTo-1 */
|
||||
nTo--;
|
||||
|
||||
ME_RunOfsFromCharOfs(editor, nFrom, &run, &nOffset);
|
||||
para = ME_GetParagraph(run);
|
||||
ME_RunOfsFromCharOfs(editor, nTo, &run, &nOffset);
|
||||
para_end = ME_GetParagraph(run);
|
||||
ME_DisplayItem *para, *para_end;
|
||||
|
||||
ME_GetSelectionParas(editor, ¶, ¶_end);
|
||||
|
||||
do {
|
||||
ME_SetParaFormat(editor, para, pFmt);
|
||||
if (para == para_end)
|
||||
|
@ -338,19 +398,10 @@ void ME_GetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, PARAFORMAT2 *
|
|||
|
||||
void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
|
||||
{
|
||||
int nFrom, nTo;
|
||||
ME_DisplayItem *para, *para_end, *run;
|
||||
int nOffset;
|
||||
ME_DisplayItem *para, *para_end;
|
||||
PARAFORMAT2 tmp;
|
||||
|
||||
ME_GetSelection(editor, &nFrom, &nTo);
|
||||
if (nTo>nFrom) /* selection consists of chars from nFrom up to nTo-1 */
|
||||
nTo--;
|
||||
|
||||
ME_RunOfsFromCharOfs(editor, nFrom, &run, &nOffset);
|
||||
para = ME_GetParagraph(run);
|
||||
ME_RunOfsFromCharOfs(editor, nTo, &run, &nOffset);
|
||||
para_end = ME_GetParagraph(run);
|
||||
ME_GetSelectionParas(editor, ¶, ¶_end);
|
||||
|
||||
ME_GetParaFormat(editor, para, pFmt);
|
||||
if (para == para_end) return;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* WINE RTF file reader
|
||||
*
|
||||
* Portions Copyright 2004 Mike McCormack for CodeWeavers
|
||||
* Portions Copyright 2006 by Phil Krylov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -15,7 +16,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -63,9 +64,8 @@ static void ReadStyleSheet (RTF_Info *);
|
|||
static void ReadInfoGroup (RTF_Info *);
|
||||
static void ReadPictGroup (RTF_Info *);
|
||||
static void ReadObjGroup (RTF_Info *);
|
||||
static void LookupInit (void);
|
||||
static void Lookup (RTF_Info *, char *);
|
||||
static int Hash (char*);
|
||||
static int Hash (const char *);
|
||||
|
||||
static void CharAttr(RTF_Info *info);
|
||||
static void CharSet(RTF_Info *info);
|
||||
|
@ -85,17 +85,9 @@ static void RTFPutCodePageChar(RTF_Info *info, int c);
|
|||
* Return pointer to block of size bytes, or NULL if there's
|
||||
* not enough memory available.
|
||||
*/
|
||||
static inline void *RTFAlloc(int size)
|
||||
{
|
||||
return HeapAlloc(me_heap, 0, size);
|
||||
}
|
||||
|
||||
|
||||
static inline void * RTFReAlloc(void *ptr, int size)
|
||||
{
|
||||
return HeapReAlloc(me_heap, 0, ptr, size);
|
||||
}
|
||||
|
||||
#define RTFAlloc(size) richedit_alloc(size)
|
||||
#define RTFReAlloc(ptr, size) richedit_realloc(ptr, size)
|
||||
#define RTFFree(ptr) richedit_free(ptr)
|
||||
|
||||
/*
|
||||
* Saves a string on the heap and returns a pointer to it.
|
||||
|
@ -111,12 +103,6 @@ static inline char *RTFStrSave(char *s)
|
|||
}
|
||||
|
||||
|
||||
static inline void RTFFree(void *p)
|
||||
{
|
||||
HeapFree(me_heap, 0, p);
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
@ -125,8 +111,6 @@ int _RTFGetChar(RTF_Info *info)
|
|||
int ch;
|
||||
ME_InStream *stream = info->stream;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if (stream->dwSize <= stream->dwUsed)
|
||||
{
|
||||
ME_StreamInFill(stream);
|
||||
|
@ -145,8 +129,6 @@ int _RTFGetChar(RTF_Info *info)
|
|||
|
||||
void RTFSetEditStream(RTF_Info *info, ME_InStream *stream)
|
||||
{
|
||||
TRACE("\n");
|
||||
|
||||
info->stream = stream;
|
||||
}
|
||||
|
||||
|
@ -212,8 +194,6 @@ void RTFInit(RTF_Info *info)
|
|||
{
|
||||
int i;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if (info->rtfTextBuf == NULL) /* initialize the text buffers */
|
||||
{
|
||||
info->rtfTextBuf = RTFAlloc (rtfBufSiz);
|
||||
|
@ -227,9 +207,6 @@ void RTFInit(RTF_Info *info)
|
|||
RTFFree (info->outputName);
|
||||
info->inputName = info->outputName = NULL;
|
||||
|
||||
/* initialize lookup table */
|
||||
LookupInit ();
|
||||
|
||||
for (i = 0; i < rtfMaxClass; i++)
|
||||
RTFSetClassCallback (info, i, NULL);
|
||||
for (i = 0; i < rtfMaxDestination; i++)
|
||||
|
@ -279,8 +256,6 @@ void RTFInit(RTF_Info *info)
|
|||
|
||||
void RTFSetInputName(RTF_Info *info, char *name)
|
||||
{
|
||||
TRACE("\n");
|
||||
|
||||
info->inputName = RTFStrSave (name);
|
||||
if (info->inputName == NULL)
|
||||
ERR ("RTFSetInputName: out of memory\n");
|
||||
|
@ -295,8 +270,6 @@ char *RTFGetInputName(RTF_Info *info)
|
|||
|
||||
void RTFSetOutputName(RTF_Info *info, char *name)
|
||||
{
|
||||
TRACE("\n");
|
||||
|
||||
info->outputName = RTFStrSave (name);
|
||||
if (info->outputName == NULL)
|
||||
ERR ("RTFSetOutputName: out of memory\n");
|
||||
|
@ -384,8 +357,6 @@ void RTFRouteToken(RTF_Info *info)
|
|||
{
|
||||
RTFFuncPtr p;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if (info->rtfClass < 0 || info->rtfClass >= rtfMaxClass) /* watchdog */
|
||||
{
|
||||
ERR( "Unknown class %d: %s (reader malfunction)\n",
|
||||
|
@ -419,8 +390,6 @@ void RTFSkipGroup(RTF_Info *info)
|
|||
{
|
||||
int level = 1;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
while (RTFGetToken (info) != rtfEOF)
|
||||
{
|
||||
if (info->rtfClass == rtfGroup)
|
||||
|
@ -447,7 +416,6 @@ int RTFGetToken(RTF_Info *info)
|
|||
{
|
||||
RTFFuncPtr p;
|
||||
|
||||
TRACE("\n");
|
||||
/* don't try to return anything once EOF is reached */
|
||||
if (info->rtfClass == rtfEOF) {
|
||||
return rtfEOF;
|
||||
|
@ -487,8 +455,6 @@ RTFFuncPtr RTFGetReadHook(RTF_Info *info)
|
|||
|
||||
void RTFUngetToken(RTF_Info *info)
|
||||
{
|
||||
TRACE("\n");
|
||||
|
||||
if (info->pushedClass >= 0) /* there's already an ungotten token */
|
||||
ERR ("cannot unget two tokens\n");
|
||||
if (info->rtfClass < 0)
|
||||
|
@ -511,8 +477,6 @@ int RTFPeekToken(RTF_Info *info)
|
|||
|
||||
static void _RTFGetToken(RTF_Info *info)
|
||||
{
|
||||
TRACE("\n");
|
||||
|
||||
if (info->rtfFormat == SF_TEXT)
|
||||
{
|
||||
info->rtfMajor = GetChar (info);
|
||||
|
@ -596,7 +560,7 @@ RTFCharSetToCodePage(RTF_Info *info, int charset)
|
|||
{
|
||||
CHARSETINFO csi;
|
||||
DWORD n = charset;
|
||||
|
||||
|
||||
/* FIXME: TranslateCharsetInfo does not work as good as it
|
||||
* should, so let's use it only when all else fails */
|
||||
if (!TranslateCharsetInfo(&n, &csi, TCI_SRCCHARSET))
|
||||
|
@ -616,8 +580,6 @@ static void _RTFGetToken2(RTF_Info *info)
|
|||
int sign;
|
||||
int c;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
/* initialize token vars */
|
||||
|
||||
info->rtfClass = rtfUnknown;
|
||||
|
@ -787,8 +749,6 @@ static int GetChar(RTF_Info *info)
|
|||
int c;
|
||||
int oldBumpLine;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if ((c = _RTFGetChar(info)) != EOF)
|
||||
{
|
||||
info->rtfTextBuf[info->rtfTextLen++] = c;
|
||||
|
@ -828,8 +788,6 @@ static int GetChar(RTF_Info *info)
|
|||
|
||||
void RTFSetToken(RTF_Info *info, int class, int major, int minor, int param, const char *text)
|
||||
{
|
||||
TRACE("\n");
|
||||
|
||||
info->rtfClass = class;
|
||||
info->rtfMajor = major;
|
||||
info->rtfMinor = minor;
|
||||
|
@ -877,8 +835,6 @@ static void ReadFontTbl(RTF_Info *info)
|
|||
int old = -1;
|
||||
const char *fn = "ReadFontTbl";
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
RTFGetToken (info);
|
||||
|
@ -929,7 +885,7 @@ static void ReadFontTbl(RTF_Info *info)
|
|||
{
|
||||
default:
|
||||
/* ignore token but announce it */
|
||||
ERR ("%s: unknown token \"%s\"\n",
|
||||
WARN ("%s: unknown token \"%s\"\n",
|
||||
fn, info->rtfTextBuf);
|
||||
break;
|
||||
case rtfFontFamily:
|
||||
|
@ -999,7 +955,7 @@ static void ReadFontTbl(RTF_Info *info)
|
|||
else
|
||||
{
|
||||
/* ignore token but announce it */
|
||||
ERR ( "%s: unknown token \"%s\"\n",
|
||||
WARN ( "%s: unknown token \"%s\"\n",
|
||||
fn,info->rtfTextBuf);
|
||||
}
|
||||
RTFGetToken (info);
|
||||
|
@ -1056,8 +1012,7 @@ static void ReadColorTbl(RTF_Info *info)
|
|||
RTFColor *cp;
|
||||
int cnum = 0;
|
||||
const char *fn = "ReadColorTbl";
|
||||
|
||||
TRACE("\n");
|
||||
int group_level = 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
@ -1065,7 +1020,18 @@ static void ReadColorTbl(RTF_Info *info)
|
|||
if (info->rtfClass == rtfEOF)
|
||||
break;
|
||||
if (RTFCheckCM (info, rtfGroup, rtfEndGroup))
|
||||
break;
|
||||
{
|
||||
group_level--;
|
||||
if (!group_level)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
else if (RTFCheckCM(info, rtfGroup, rtfBeginGroup))
|
||||
{
|
||||
group_level++;
|
||||
continue;
|
||||
}
|
||||
|
||||
cp = New (RTFColor);
|
||||
if (cp == NULL)
|
||||
ERR ( "%s: cannot allocate color entry\n", fn);
|
||||
|
@ -1105,8 +1071,6 @@ static void ReadStyleSheet(RTF_Info *info)
|
|||
const char *fn = "ReadStyleSheet";
|
||||
int real_style;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
RTFGetToken (info);
|
||||
|
@ -1229,7 +1193,7 @@ static void ReadStyleSheet(RTF_Info *info)
|
|||
else /* unrecognized */
|
||||
{
|
||||
/* ignore token but announce it */
|
||||
ERR ( "%s: unknown token \"%s\"\n",
|
||||
WARN ( "%s: unknown token \"%s\"\n",
|
||||
fn, info->rtfTextBuf);
|
||||
}
|
||||
}
|
||||
|
@ -1351,8 +1315,6 @@ void RTFExpandStyle(RTF_Info *info, int n)
|
|||
RTFStyle *s;
|
||||
RTFStyleElt *se;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if (n == -1)
|
||||
return;
|
||||
s = RTFGetStyle (info, n);
|
||||
|
@ -1817,7 +1779,7 @@ static RTFKey rtfKey[] =
|
|||
|
||||
{ rtfDocAttr, rtfRTLDoc, "rtldoc", 0 },
|
||||
{ rtfDocAttr, rtfLTRDoc, "ltrdoc", 0 },
|
||||
|
||||
|
||||
{ rtfDocAttr, rtfAnsiCodePage, "ansicpg", 0 },
|
||||
{ rtfDocAttr, rtfUTF8RTF, "urtf", 0 },
|
||||
|
||||
|
@ -2326,26 +2288,34 @@ static RTFHashTableEntry rtfHashTable[RTF_KEY_COUNT * 2];
|
|||
* Initialize lookup table hash values. Only need to do this once.
|
||||
*/
|
||||
|
||||
static void LookupInit(void)
|
||||
void LookupInit(void)
|
||||
{
|
||||
static int inited = 0;
|
||||
RTFKey *rp;
|
||||
|
||||
if (inited == 0)
|
||||
memset(rtfHashTable, 0, sizeof rtfHashTable);
|
||||
for (rp = rtfKey; rp->rtfKStr != NULL; rp++)
|
||||
{
|
||||
memset(rtfHashTable, 0, RTF_KEY_COUNT * 2 * sizeof(*rtfHashTable));
|
||||
for (rp = rtfKey; rp->rtfKStr != NULL; rp++) {
|
||||
int index;
|
||||
|
||||
rp->rtfKHash = Hash ((char*)rp->rtfKStr);
|
||||
index = rp->rtfKHash % (RTF_KEY_COUNT * 2);
|
||||
if (!rtfHashTable[index].count)
|
||||
rtfHashTable[index].value = RTFAlloc(sizeof(RTFKey *));
|
||||
else
|
||||
rtfHashTable[index].value = RTFReAlloc(rtfHashTable[index].value, sizeof(RTFKey *) * (rtfHashTable[index].count + 1));
|
||||
rtfHashTable[index].value[rtfHashTable[index].count++] = rp;
|
||||
}
|
||||
++inited;
|
||||
int index;
|
||||
|
||||
rp->rtfKHash = Hash (rp->rtfKStr);
|
||||
index = rp->rtfKHash % (RTF_KEY_COUNT * 2);
|
||||
if (!rtfHashTable[index].count)
|
||||
rtfHashTable[index].value = RTFAlloc(sizeof(RTFKey *));
|
||||
else
|
||||
rtfHashTable[index].value = RTFReAlloc(rtfHashTable[index].value, sizeof(RTFKey *) * (rtfHashTable[index].count + 1));
|
||||
rtfHashTable[index].value[rtfHashTable[index].count++] = rp;
|
||||
}
|
||||
}
|
||||
|
||||
void LookupCleanup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<RTF_KEY_COUNT*2; i++)
|
||||
{
|
||||
RTFFree( rtfHashTable[i].value );
|
||||
rtfHashTable[i].value = NULL;
|
||||
rtfHashTable[i].count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2362,7 +2332,6 @@ static void Lookup(RTF_Info *info, char *s)
|
|||
RTFHashTableEntry *entry;
|
||||
int i;
|
||||
|
||||
TRACE("\n");
|
||||
++s; /* skip over the leading \ character */
|
||||
hash = Hash (s);
|
||||
entry = &rtfHashTable[hash % (RTF_KEY_COUNT * 2)];
|
||||
|
@ -2385,7 +2354,7 @@ static void Lookup(RTF_Info *info, char *s)
|
|||
* Compute hash value of symbol
|
||||
*/
|
||||
|
||||
static int Hash(char *s)
|
||||
static int Hash(const char *s)
|
||||
{
|
||||
char c;
|
||||
int val = 0;
|
||||
|
@ -2495,8 +2464,6 @@ TextClass (RTF_Info *info)
|
|||
static void
|
||||
ControlClass (RTF_Info *info)
|
||||
{
|
||||
TRACE("\n");
|
||||
|
||||
switch (info->rtfMajor)
|
||||
{
|
||||
case rtfCharAttr:
|
||||
|
@ -2525,7 +2492,7 @@ static void
|
|||
CharAttr(RTF_Info *info)
|
||||
{
|
||||
RTFFont *font;
|
||||
|
||||
|
||||
switch (info->rtfMinor)
|
||||
{
|
||||
case rtfFontNum:
|
||||
|
@ -2578,7 +2545,6 @@ CharSet(RTF_Info *info)
|
|||
static void
|
||||
Destination (RTF_Info *info)
|
||||
{
|
||||
TRACE("\n");
|
||||
if (!RTFGetDestinationCallback(info, info->rtfMinor))
|
||||
RTFSkipGroup (info);
|
||||
}
|
||||
|
@ -2611,9 +2577,6 @@ DocAttr(RTF_Info *info)
|
|||
|
||||
static void SpecialChar (RTF_Info *info)
|
||||
{
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
switch (info->rtfMinor)
|
||||
{
|
||||
case rtfOptDest:
|
||||
|
@ -2628,9 +2591,9 @@ static void SpecialChar (RTF_Info *info)
|
|||
case rtfUnicode:
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
RTFPutUnicodeChar(info, info->rtfParam);
|
||||
|
||||
|
||||
/* After \u we must skip number of character tokens set by \ucN */
|
||||
for (i = 0; i < info->unicodeLength; i++)
|
||||
{
|
||||
|
@ -2652,9 +2615,6 @@ static void SpecialChar (RTF_Info *info)
|
|||
case rtfPar:
|
||||
RTFPutUnicodeChar (info, '\n');
|
||||
break;
|
||||
case rtfCell:
|
||||
RTFPutUnicodeChar (info, ' '); /* make sure cells are separated */
|
||||
break;
|
||||
case rtfNoBrkSpace:
|
||||
RTFPutUnicodeChar (info, 0x00A0);
|
||||
break;
|
||||
|
|
|
@ -3,17 +3,20 @@
|
|||
<include base="riched20">.</include>
|
||||
<include base="ReactOS">include/reactos/wine</include>
|
||||
<define name="__REACTOS__" />
|
||||
<define name="__WINESRC__" />
|
||||
<define name="__USE_W32API" />
|
||||
<define name="_WIN32_IE">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x501</define>
|
||||
<define name="WINVER">0x501</define>
|
||||
<library>uuid</library>
|
||||
<library>wine</library>
|
||||
<library>ntdll</library>
|
||||
<library>kernel32</library>
|
||||
<library>ole32</library>
|
||||
<library>user32</library>
|
||||
<library>gdi32</library>
|
||||
<library>kernel32</library>
|
||||
<library>uuid</library>
|
||||
<library>ntdll</library>
|
||||
<file>caret.c</file>
|
||||
<file>clipboard.c</file>
|
||||
<file>context.c</file>
|
||||
<file>editor.c</file>
|
||||
<file>list.c</file>
|
||||
|
@ -25,8 +28,10 @@
|
|||
<file>run.c</file>
|
||||
<file>string.c</file>
|
||||
<file>style.c</file>
|
||||
<file>txtsrv.c</file>
|
||||
<file>undo.c</file>
|
||||
<file>wrap.c</file>
|
||||
<file>writer.c</file>
|
||||
<file>version.rc</file>
|
||||
<file>riched20.spec</file>
|
||||
</module>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
@ -31,37 +31,58 @@
|
|||
#include "winuser.h"
|
||||
#include "ole2.h"
|
||||
#include "richole.h"
|
||||
#include "editor.h"
|
||||
#include "tom.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||
|
||||
typedef struct IRichEditOleImpl {
|
||||
const IRichEditOleVtbl *lpVtbl;
|
||||
LONG ref;
|
||||
} IRichEditOleImpl;
|
||||
|
||||
/* there is no way to be consistent across different sets of headers - mingw, Wine, Win32 SDK*/
|
||||
|
||||
/* FIXME: the next 6 lines should be in textserv.h */
|
||||
#include "initguid.h"
|
||||
#define TEXTSERV_GUID(name, l, w1, w2, b1, b2) \
|
||||
GUID name = { l, w1, w2, {b1, b2, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5}}
|
||||
DEFINE_GUID(name, l, w1, w2, b1, b2, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5)
|
||||
|
||||
TEXTSERV_GUID(IID_ITextServices, 0x8d33f740, 0xcf58, 0x11ce, 0xa8, 0x9d);
|
||||
TEXTSERV_GUID(IID_ITextHost, 0xc5bdd8d0, 0xd26e, 0x11ce, 0xa8, 0x9e);
|
||||
TEXTSERV_GUID(IID_ITextHost2, 0xc5bdd8d0, 0xd26e, 0x11ce, 0xa8, 0x9e);
|
||||
DEFINE_GUID(IID_ITextDocument, 0x8cc497c0, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
|
||||
|
||||
typedef struct IRichEditOleImpl {
|
||||
const IRichEditOleVtbl *lpRichEditOleVtbl;
|
||||
const ITextDocumentVtbl *lpTextDocumentVtbl;
|
||||
LONG ref;
|
||||
|
||||
ME_TextEditor *editor;
|
||||
} IRichEditOleImpl;
|
||||
|
||||
static inline IRichEditOleImpl *impl_from_IRichEditOle(IRichEditOle *iface)
|
||||
{
|
||||
return (IRichEditOleImpl *)((BYTE*)iface - FIELD_OFFSET(IRichEditOleImpl, lpRichEditOleVtbl));
|
||||
}
|
||||
|
||||
static inline IRichEditOleImpl *impl_from_ITextDocument(ITextDocument *iface)
|
||||
{
|
||||
return (IRichEditOleImpl *)((BYTE*)iface - FIELD_OFFSET(IRichEditOleImpl, lpTextDocumentVtbl));
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
IRichEditOle_fnQueryInterface(IRichEditOle *me, REFIID riid, LPVOID *ppvObj)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
|
||||
TRACE("%p %s\n", This, debugstr_guid(riid) );
|
||||
|
||||
*ppvObj = NULL;
|
||||
if (IsEqualGUID(riid, &IID_IUnknown) ||
|
||||
IsEqualGUID(riid, &IID_IRichEditOle))
|
||||
*ppvObj = &This->lpRichEditOleVtbl;
|
||||
else if (IsEqualGUID(riid, &IID_ITextDocument))
|
||||
*ppvObj = &This->lpTextDocumentVtbl;
|
||||
if (*ppvObj)
|
||||
{
|
||||
IRichEditOle_AddRef(me);
|
||||
*ppvObj = (LPVOID) This;
|
||||
return S_OK;
|
||||
}
|
||||
FIXME("%p: unhandled interface %s\n", This, debugstr_guid(riid) );
|
||||
|
@ -72,10 +93,10 @@ IRichEditOle_fnQueryInterface(IRichEditOle *me, REFIID riid, LPVOID *ppvObj)
|
|||
static ULONG WINAPI
|
||||
IRichEditOle_fnAddRef(IRichEditOle *me)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
ULONG ref = InterlockedIncrement( &This->ref );
|
||||
|
||||
TRACE("%p ref = %lu\n", This, ref);
|
||||
TRACE("%p ref = %u\n", This, ref);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
@ -83,15 +104,15 @@ IRichEditOle_fnAddRef(IRichEditOle *me)
|
|||
static ULONG WINAPI
|
||||
IRichEditOle_fnRelease(IRichEditOle *me)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
ULONG ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
TRACE ("%p ref=%lu\n", This, ref);
|
||||
TRACE ("%p ref=%u\n", This, ref);
|
||||
|
||||
if (!ref)
|
||||
{
|
||||
TRACE ("Destroying %p\n", This);
|
||||
HeapFree(GetProcessHeap(),0,This);
|
||||
richedit_free(This);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
@ -99,7 +120,7 @@ IRichEditOle_fnRelease(IRichEditOle *me)
|
|||
static HRESULT WINAPI
|
||||
IRichEditOle_fnActivateAs(IRichEditOle *me, REFCLSID rclsid, REFCLSID rclsidAs)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -107,7 +128,7 @@ IRichEditOle_fnActivateAs(IRichEditOle *me, REFCLSID rclsid, REFCLSID rclsidAs)
|
|||
static HRESULT WINAPI
|
||||
IRichEditOle_fnContextSensitiveHelp(IRichEditOle *me, BOOL fEnterMode)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -116,7 +137,7 @@ static HRESULT WINAPI
|
|||
IRichEditOle_fnConvertObject(IRichEditOle *me, LONG iob,
|
||||
REFCLSID rclsidNew, LPCSTR lpstrUserTypeNew)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -125,7 +146,7 @@ static HRESULT WINAPI
|
|||
IRichEditOle_fnGetClientSite(IRichEditOle *me,
|
||||
LPOLECLIENTSITE *lplpolesite)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -134,14 +155,22 @@ static HRESULT WINAPI
|
|||
IRichEditOle_fnGetClipboardData(IRichEditOle *me, CHARRANGE *lpchrg,
|
||||
DWORD reco, LPDATAOBJECT *lplpdataobj)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
CHARRANGE tmpchrg;
|
||||
|
||||
TRACE("(%p,%p,%d)\n",This, lpchrg, reco);
|
||||
if(!lplpdataobj)
|
||||
return E_INVALIDARG;
|
||||
if(!lpchrg) {
|
||||
ME_GetSelection(This->editor, (int*)&tmpchrg.cpMin, (int*)&tmpchrg.cpMax);
|
||||
lpchrg = &tmpchrg;
|
||||
}
|
||||
return ME_GetDataObject(This->editor, lpchrg, lplpdataobj);
|
||||
}
|
||||
|
||||
static LONG WINAPI IRichEditOle_fnGetLinkCount(IRichEditOle *me)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -150,7 +179,7 @@ static HRESULT WINAPI
|
|||
IRichEditOle_fnGetObject(IRichEditOle *me, LONG iob,
|
||||
REOBJECT *lpreobject, DWORD dwFlags)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -158,7 +187,7 @@ IRichEditOle_fnGetObject(IRichEditOle *me, LONG iob,
|
|||
static LONG WINAPI
|
||||
IRichEditOle_fnGetObjectCount(IRichEditOle *me)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -166,7 +195,7 @@ IRichEditOle_fnGetObjectCount(IRichEditOle *me)
|
|||
static HRESULT WINAPI
|
||||
IRichEditOle_fnHandsOffStorage(IRichEditOle *me, LONG iob)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -175,7 +204,7 @@ static HRESULT WINAPI
|
|||
IRichEditOle_fnImportDataObject(IRichEditOle *me, LPDATAOBJECT lpdataobj,
|
||||
CLIPFORMAT cf, HGLOBAL hMetaPict)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -183,7 +212,7 @@ IRichEditOle_fnImportDataObject(IRichEditOle *me, LPDATAOBJECT lpdataobj,
|
|||
static HRESULT WINAPI
|
||||
IRichEditOle_fnInPlaceDeactivate(IRichEditOle *me)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -191,7 +220,7 @@ IRichEditOle_fnInPlaceDeactivate(IRichEditOle *me)
|
|||
static HRESULT WINAPI
|
||||
IRichEditOle_fnInsertObject(IRichEditOle *me, REOBJECT *lpreobject)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -199,7 +228,7 @@ IRichEditOle_fnInsertObject(IRichEditOle *me, REOBJECT *lpreobject)
|
|||
static HRESULT WINAPI IRichEditOle_fnSaveCompleted(IRichEditOle *me, LONG iob,
|
||||
LPSTORAGE lpstg)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -207,7 +236,7 @@ static HRESULT WINAPI IRichEditOle_fnSaveCompleted(IRichEditOle *me, LONG iob,
|
|||
static HRESULT WINAPI
|
||||
IRichEditOle_fnSetDvaspect(IRichEditOle *me, LONG iob, DWORD dvaspect)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -215,7 +244,7 @@ IRichEditOle_fnSetDvaspect(IRichEditOle *me, LONG iob, DWORD dvaspect)
|
|||
static HRESULT WINAPI IRichEditOle_fnSetHostNames(IRichEditOle *me,
|
||||
LPCSTR lpstrContainerApp, LPCSTR lpstrContainerObj)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p %s %s\n",This, lpstrContainerApp, lpstrContainerObj);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -223,7 +252,7 @@ static HRESULT WINAPI IRichEditOle_fnSetHostNames(IRichEditOle *me,
|
|||
static HRESULT WINAPI
|
||||
IRichEditOle_fnSetLinkAvailable(IRichEditOle *me, LONG iob, BOOL fAvailable)
|
||||
{
|
||||
IRichEditOleImpl *This = (IRichEditOleImpl *)me;
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -250,16 +279,264 @@ static const IRichEditOleVtbl revt = {
|
|||
IRichEditOle_fnImportDataObject
|
||||
};
|
||||
|
||||
LRESULT CreateIRichEditOle(LPVOID *ppObj)
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnQueryInterface(ITextDocument* me, REFIID riid,
|
||||
void** ppvObject)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
return IRichEditOle_fnQueryInterface((IRichEditOle*)&This->lpRichEditOleVtbl,
|
||||
riid, ppvObject);
|
||||
}
|
||||
|
||||
static ULONG WINAPI
|
||||
ITextDocument_fnAddRef(ITextDocument* me)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
return IRichEditOle_fnAddRef((IRichEditOle*)&This->lpRichEditOleVtbl);
|
||||
}
|
||||
|
||||
static ULONG WINAPI
|
||||
ITextDocument_fnRelease(ITextDocument* me)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
return IRichEditOle_fnRelease((IRichEditOle*)&This->lpRichEditOleVtbl);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnGetTypeInfoCount(ITextDocument* me,
|
||||
UINT* pctinfo)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnGetTypeInfo(ITextDocument* me, UINT iTInfo, LCID lcid,
|
||||
ITypeInfo** ppTInfo)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnGetIDsOfNames(ITextDocument* me, REFIID riid,
|
||||
LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnInvoke(ITextDocument* me, DISPID dispIdMember,
|
||||
REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
|
||||
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnGetName(ITextDocument* me, BSTR* pName)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnGetSelection(ITextDocument* me, ITextSelection** ppSel)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnGetStoryCount(ITextDocument* me, long* pCount)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnGetStoryRanges(ITextDocument* me,
|
||||
ITextStoryRanges** ppStories)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnGetSaved(ITextDocument* me, long* pValue)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnSetSaved(ITextDocument* me, long Value)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnGetDefaultTabStop(ITextDocument* me, float* pValue)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnSetDefaultTabStop(ITextDocument* me, float Value)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnNew(ITextDocument* me)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnOpen(ITextDocument* me, VARIANT* pVar, long Flags,
|
||||
long CodePage)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnSave(ITextDocument* me, VARIANT* pVar, long Flags,
|
||||
long CodePage)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnFreeze(ITextDocument* me, long* pCount)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnUnfreeze(ITextDocument* me, long* pCount)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnBeginEditCollection(ITextDocument* me)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnEndEditCollection(ITextDocument* me)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnUndo(ITextDocument* me, long Count, long* prop)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnRedo(ITextDocument* me, long Count, long* prop)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnRange(ITextDocument* me, long cp1, long cp2,
|
||||
ITextRange** ppRange)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ITextDocument_fnRangeFromPoint(ITextDocument* me, long x, long y,
|
||||
ITextRange** ppRange)
|
||||
{
|
||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static const ITextDocumentVtbl tdvt = {
|
||||
ITextDocument_fnQueryInterface,
|
||||
ITextDocument_fnAddRef,
|
||||
ITextDocument_fnRelease,
|
||||
ITextDocument_fnGetTypeInfoCount,
|
||||
ITextDocument_fnGetTypeInfo,
|
||||
ITextDocument_fnGetIDsOfNames,
|
||||
ITextDocument_fnInvoke,
|
||||
ITextDocument_fnGetName,
|
||||
ITextDocument_fnGetSelection,
|
||||
ITextDocument_fnGetStoryCount,
|
||||
ITextDocument_fnGetStoryRanges,
|
||||
ITextDocument_fnGetSaved,
|
||||
ITextDocument_fnSetSaved,
|
||||
ITextDocument_fnGetDefaultTabStop,
|
||||
ITextDocument_fnSetDefaultTabStop,
|
||||
ITextDocument_fnNew,
|
||||
ITextDocument_fnOpen,
|
||||
ITextDocument_fnSave,
|
||||
ITextDocument_fnFreeze,
|
||||
ITextDocument_fnUnfreeze,
|
||||
ITextDocument_fnBeginEditCollection,
|
||||
ITextDocument_fnEndEditCollection,
|
||||
ITextDocument_fnUndo,
|
||||
ITextDocument_fnRedo,
|
||||
ITextDocument_fnRange,
|
||||
ITextDocument_fnRangeFromPoint
|
||||
};
|
||||
|
||||
LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj)
|
||||
{
|
||||
IRichEditOleImpl *reo;
|
||||
|
||||
reo = HeapAlloc(GetProcessHeap(), 0, sizeof(IRichEditOleImpl));
|
||||
reo = richedit_alloc(sizeof(IRichEditOleImpl));
|
||||
if (!reo)
|
||||
return 0;
|
||||
|
||||
reo->lpVtbl = &revt;
|
||||
reo->lpRichEditOleVtbl = &revt;
|
||||
reo->lpTextDocumentVtbl = &tdvt;
|
||||
reo->ref = 1;
|
||||
reo->editor = editor;
|
||||
TRACE("Created %p\n",reo);
|
||||
*ppObj = (LPVOID) reo;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
|
@ -28,8 +28,8 @@ ME_DisplayItem *ME_FindRowStart(ME_Context *c, ME_DisplayItem *item,
|
|||
int nRelPos) {
|
||||
ME_DisplayItem *para = ME_GetParagraph(item);
|
||||
ME_MustBeWrapped(c, para);
|
||||
if(nRelPos>=0) { /* if this or preceding row */
|
||||
while(nRelPos<=0) {
|
||||
if(nRelPos<=0) { /* if this or preceding row */
|
||||
do {
|
||||
ME_DisplayItem *item2 = ME_FindItemBack(item, diStartRowOrParagraph);
|
||||
if (item2->type == diParagraph)
|
||||
{
|
||||
|
@ -50,8 +50,7 @@ ME_DisplayItem *ME_FindRowStart(ME_Context *c, ME_DisplayItem *item,
|
|||
}
|
||||
assert(0 == "bug in FindItemBack(item, diStartRowOrParagraph)");
|
||||
item = item2;
|
||||
}
|
||||
return item;
|
||||
} while(1);
|
||||
}
|
||||
while(nRelPos>0) { /* if one of the next rows */
|
||||
ME_DisplayItem *item2 = ME_FindItemFwd(item, diStartRowOrParagraph);
|
||||
|
|
|
@ -1147,4 +1147,7 @@ int BeginFile (RTF_Info *);
|
|||
|
||||
int RTFCharSetToCodePage(RTF_Info *info, int charset);
|
||||
|
||||
void LookupInit (void);
|
||||
void LookupCleanup (void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Character/pixel conversions.
|
||||
*
|
||||
* Copyright 2004 by Krzysztof Foltman
|
||||
* Copyright 2006 by Phil Krylov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -17,7 +18,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "editor.h"
|
||||
|
@ -26,6 +27,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
|||
WINE_DECLARE_DEBUG_CHANNEL(richedit_check);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(richedit_lists);
|
||||
|
||||
/******************************************************************************
|
||||
* ME_CanJoinRuns
|
||||
*
|
||||
* Returns 1 if two runs can be safely merged into one, 0 otherwise.
|
||||
*/
|
||||
int ME_CanJoinRuns(ME_Run *run1, ME_Run *run2)
|
||||
{
|
||||
if ((run1->nFlags | run2->nFlags) & MERF_NOJOIN)
|
||||
|
@ -44,8 +50,18 @@ void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift)
|
|||
ME_PropagateCharOffset(p, shift);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_PropagateCharOffsets
|
||||
*
|
||||
* Shifts (increases or decreases) character offset (relative to beginning of
|
||||
* the document) of the part of the text starting from given place.
|
||||
*/
|
||||
void ME_PropagateCharOffset(ME_DisplayItem *p, 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_w(p->member.run.strText->szData), shift);
|
||||
|
@ -55,6 +71,10 @@ void ME_PropagateCharOffset(ME_DisplayItem *p, int shift)
|
|||
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 {
|
||||
|
@ -63,6 +83,9 @@ void ME_PropagateCharOffset(ME_DisplayItem *p, int shift)
|
|||
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;
|
||||
|
@ -70,6 +93,11 @@ void ME_PropagateCharOffset(ME_DisplayItem *p, int shift)
|
|||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_CheckCharOffsets
|
||||
*
|
||||
* Checks if editor lists' validity and optionally dumps the document structure
|
||||
*/
|
||||
void ME_CheckCharOffsets(ME_TextEditor *editor)
|
||||
{
|
||||
ME_DisplayItem *p = editor->pBuffer->pFirst;
|
||||
|
@ -93,7 +121,7 @@ void ME_CheckCharOffsets(ME_TextEditor *editor)
|
|||
ofs = 0;
|
||||
break;
|
||||
case diRun:
|
||||
TRACE_(richedit_check)("run, real ofs = %d (+ofsp = %d), counted = %d, len = %d, txt = \"%s\", flags=%08x, fx&mask = %08lx\n",
|
||||
TRACE_(richedit_check)("run, real ofs = %d (+ofsp = %d), counted = %d, len = %d, txt = \"%s\", flags=%08x, fx&mask = %08x\n",
|
||||
p->member.run.nCharOfs, p->member.run.nCharOfs+ofsp, ofsp+ofs,
|
||||
p->member.run.strText->nLen, debugstr_w(p->member.run.strText->szData),
|
||||
p->member.run.nFlags,
|
||||
|
@ -110,6 +138,13 @@ void ME_CheckCharOffsets(ME_TextEditor *editor)
|
|||
} while(1);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_CharOfsFromRunOfs
|
||||
*
|
||||
* 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, ME_DisplayItem *pRun, int nOfs)
|
||||
{
|
||||
ME_DisplayItem *pPara;
|
||||
|
@ -124,11 +159,25 @@ int ME_CharOfsFromRunOfs(ME_TextEditor *editor, ME_DisplayItem *pRun, int nOfs)
|
|||
+ ME_VPosToPos(pRun->member.run.strText, nOfs);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_CursorFromCharOfs
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
ME_RunOfsFromCharOfs(editor, nCharOfs, &pCursor->pRun, &pCursor->nOffset);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* 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 **ppRun, int *pOfs)
|
||||
{
|
||||
ME_DisplayItem *pPara;
|
||||
|
@ -175,6 +224,11 @@ void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **
|
|||
assert((*ppRun)->member.run.nFlags & MERF_ENDPARA);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_JoinRuns
|
||||
*
|
||||
* Merges two adjacent runs, the one given as a parameter and the next one.
|
||||
*/
|
||||
void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p)
|
||||
{
|
||||
ME_DisplayItem *pNext = p->next;
|
||||
|
@ -183,8 +237,11 @@ void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p)
|
|||
assert(p->member.run.nCharOfs != -1);
|
||||
ME_GetParagraph(p)->member.para.nFlags |= MEPF_REWRAP;
|
||||
|
||||
if (editor->bCaretAtEnd && editor->pCursors[0].pRun == pNext)
|
||||
/* if we were at the end of screen line, and the next run is in the new
|
||||
* line, then it's not the end of the line anymore */
|
||||
if (editor->bCaretAtEnd && editor->pCursors[0].pRun == pNext)
|
||||
editor->bCaretAtEnd = FALSE;
|
||||
/* 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;
|
||||
|
@ -204,6 +261,12 @@ void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p)
|
|||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_SplitRun
|
||||
*
|
||||
* Splits a run into two in a given place. It also updates the screen position
|
||||
* and size (extent) of the newly generated runs.
|
||||
*/
|
||||
ME_DisplayItem *ME_SplitRun(ME_Context *c, ME_DisplayItem *item, int nVChar)
|
||||
{
|
||||
ME_TextEditor *editor = c->editor;
|
||||
|
@ -221,7 +284,7 @@ ME_DisplayItem *ME_SplitRun(ME_Context *c, ME_DisplayItem *item, int nVChar)
|
|||
|
||||
run = &item->member.run;
|
||||
|
||||
TRACE("Before split: %s(%ld, %ld)\n", debugstr_w(run->strText->szData),
|
||||
TRACE("Before split: %s(%d, %d)\n", debugstr_w(run->strText->szData),
|
||||
run->pt.x, run->pt.y);
|
||||
|
||||
item2 = ME_SplitRunSimple(editor, item, nVChar);
|
||||
|
@ -239,7 +302,7 @@ ME_DisplayItem *ME_SplitRun(ME_Context *c, ME_DisplayItem *item, int nVChar)
|
|||
TRACE("Before check after split\n");
|
||||
ME_CheckCharOffsets(editor);
|
||||
TRACE("After check after split\n");
|
||||
TRACE("After split: %s(%ld, %ld), %s(%ld, %ld)\n",
|
||||
TRACE("After split: %s(%d, %d), %s(%d, %d)\n",
|
||||
debugstr_w(run->strText->szData), run->pt.x, run->pt.y,
|
||||
debugstr_w(run2->strText->szData), run2->pt.x, run2->pt.y);
|
||||
}
|
||||
|
@ -247,7 +310,12 @@ ME_DisplayItem *ME_SplitRun(ME_Context *c, ME_DisplayItem *item, int nVChar)
|
|||
return item2;
|
||||
}
|
||||
|
||||
/* split a run starting from voffset */
|
||||
/******************************************************************************
|
||||
* ME_SplitRunSimple
|
||||
*
|
||||
* 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_DisplayItem *item, int nVChar)
|
||||
{
|
||||
ME_Run *run = &item->member.run;
|
||||
|
@ -256,7 +324,7 @@ ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_DisplayItem *item, i
|
|||
int i;
|
||||
assert(nVChar > 0 && nVChar < ME_StrVLen(run->strText));
|
||||
assert(item->type == diRun);
|
||||
assert(!(item->member.run.nFlags & (MERF_GRAPHICS | MERF_TAB)));
|
||||
assert(!(item->member.run.nFlags & MERF_NONTEXT));
|
||||
assert(item->member.run.nCharOfs != -1);
|
||||
|
||||
item2 = ME_MakeRun(run->style,
|
||||
|
@ -282,6 +350,11 @@ ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_DisplayItem *item, i
|
|||
return item2;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_MakeRun
|
||||
*
|
||||
* A helper function to create run structures quickly.
|
||||
*/
|
||||
ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags)
|
||||
{
|
||||
ME_DisplayItem *item = ME_MakeDI(diRun);
|
||||
|
@ -293,37 +366,80 @@ ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags)
|
|||
return item;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_InsertRun
|
||||
*
|
||||
* Inserts a run at a given character position (offset).
|
||||
*/
|
||||
ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem *pItem)
|
||||
{
|
||||
ME_Cursor tmp;
|
||||
ME_DisplayItem *pDI;
|
||||
ME_UndoItem *pUI;
|
||||
|
||||
assert(pItem->type == diRun || pItem->type == diUndoInsertRun);
|
||||
|
||||
pUI = ME_AddUndoItem(editor, diUndoDeleteRun, NULL);
|
||||
if (pUI) {
|
||||
pUI->nStart = nCharOfs;
|
||||
pUI->nLen = pItem->member.run.strText->nLen;
|
||||
}
|
||||
ME_CursorFromCharOfs(editor, nCharOfs, &tmp);
|
||||
if (tmp.nOffset) {
|
||||
tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset);
|
||||
tmp.nOffset = 0;
|
||||
}
|
||||
pDI = ME_MakeRun(pItem->member.run.style, ME_StrDup(pItem->member.run.strText), pItem->member.run.nFlags);
|
||||
pDI->member.run.nCharOfs = tmp.pRun->member.run.nCharOfs;
|
||||
ME_InsertBefore(tmp.pRun, pDI);
|
||||
TRACE("Shift length:%d\n", pDI->member.run.strText->nLen);
|
||||
ME_PropagateCharOffset(tmp.pRun, pDI->member.run.strText->nLen);
|
||||
ME_GetParagraph(tmp.pRun)->member.para.nFlags |= MEPF_REWRAP;
|
||||
|
||||
pDI = ME_InsertRunAtCursor(editor, &tmp, pItem->member.run.style,
|
||||
pItem->member.run.strText->szData,
|
||||
pItem->member.run.strText->nLen,
|
||||
pItem->member.run.nFlags);
|
||||
|
||||
return pDI;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_InsertRunAtCursor
|
||||
*
|
||||
* 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_DisplayItem *pDI;
|
||||
ME_UndoItem *pUI;
|
||||
|
||||
if (cursor->nOffset) {
|
||||
/* We're inserting at the middle of the existing run, which means that
|
||||
* that run must be split. It isn't always necessary, but */
|
||||
cursor->pRun = ME_SplitRunSimple(editor, cursor->pRun, cursor->nOffset);
|
||||
cursor->nOffset = 0;
|
||||
}
|
||||
|
||||
pUI = ME_AddUndoItem(editor, diUndoDeleteRun, NULL);
|
||||
if (pUI) {
|
||||
pUI->nStart = (ME_GetParagraph(cursor->pRun)->member.para.nCharOfs
|
||||
+ cursor->pRun->member.run.nCharOfs);
|
||||
pUI->nLen = len;
|
||||
}
|
||||
|
||||
pDI = ME_MakeRun(style, ME_MakeStringN(str, len), flags);
|
||||
pDI->member.run.nCharOfs = cursor->pRun->member.run.nCharOfs;
|
||||
ME_InsertBefore(cursor->pRun, pDI);
|
||||
TRACE("Shift length:%d\n", len);
|
||||
ME_PropagateCharOffset(cursor->pRun, len);
|
||||
ME_GetParagraph(cursor->pRun)->member.para.nFlags |= MEPF_REWRAP;
|
||||
return pDI;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_UpdateRunFlags
|
||||
*
|
||||
* Determine some of run attributes given its content (style, text content).
|
||||
* Some flags cannot be determined by this function (MERF_GRAPHICS,
|
||||
* MERF_ENDPARA)
|
||||
*/
|
||||
void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run)
|
||||
{
|
||||
assert(run->nCharOfs != -1);
|
||||
|
||||
if (RUN_IS_HIDDEN(run))
|
||||
run->nFlags |= MERF_HIDDEN;
|
||||
else
|
||||
run->nFlags &= ~MERF_HIDDEN;
|
||||
|
||||
if (ME_IsSplitable(run->strText))
|
||||
run->nFlags |= MERF_SPLITTABLE;
|
||||
else
|
||||
|
@ -351,6 +467,12 @@ void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run)
|
|||
run->nFlags &= ~(MERF_WHITESPACE | MERF_STARTWHITE | MERF_ENDWHITE);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_GetGraphicsSize
|
||||
*
|
||||
* Sets run extent for graphics runs. This functionality is just a placeholder
|
||||
* for future OLE object support, and will be removed.
|
||||
*/
|
||||
void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize)
|
||||
{
|
||||
assert(run->nFlags & MERF_GRAPHICS);
|
||||
|
@ -358,7 +480,14 @@ void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize)
|
|||
pSize->cy = 64;
|
||||
}
|
||||
|
||||
int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Paragraph *para, ME_Run *run)
|
||||
/******************************************************************************
|
||||
* ME_CharFromPoint
|
||||
*
|
||||
* Returns a character position inside the run given a run-relative
|
||||
* pixel horizontal position. This version rounds left (ie. if the second
|
||||
* character is at pixel position 8, then for cx=0..7 it returns 0).
|
||||
*/
|
||||
int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run)
|
||||
{
|
||||
int fit = 0;
|
||||
HGDIOBJ hOldFont;
|
||||
|
@ -367,9 +496,9 @@ int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Paragraph *para, ME_Run *
|
|||
if (!run->strText->nLen)
|
||||
return 0;
|
||||
|
||||
if (run->nFlags & MERF_TAB)
|
||||
if (run->nFlags & (MERF_TAB | MERF_CELL))
|
||||
{
|
||||
if (cx < run->nWidth/2)
|
||||
if (cx < run->nWidth/2)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -383,15 +512,41 @@ int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Paragraph *para, ME_Run *
|
|||
}
|
||||
hDC = GetDC(editor->hWnd);
|
||||
hOldFont = ME_SelectStyleFont(editor, hDC, run->style);
|
||||
GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen,
|
||||
cx, &fit, NULL, &sz);
|
||||
|
||||
if (editor->cPasswordMask)
|
||||
{
|
||||
ME_String *strMasked = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(run->strText));
|
||||
GetTextExtentExPointW(hDC, strMasked->szData, run->strText->nLen,
|
||||
cx, &fit, NULL, &sz);
|
||||
ME_DestroyString(strMasked);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen,
|
||||
cx, &fit, NULL, &sz);
|
||||
}
|
||||
|
||||
ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);
|
||||
ReleaseDC(editor->hWnd, hDC);
|
||||
return fit;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_CharFromPointCursor
|
||||
*
|
||||
* Returns a character position inside the run given a run-relative
|
||||
* pixel horizontal position. This version rounds to the nearest character edge
|
||||
* (ie. if the second character is at pixel position 8, then for cx=0..3
|
||||
* it returns 0, and for cx=4..7 it returns 1).
|
||||
*
|
||||
* It is used for mouse click handling, for better usability (and compatibility
|
||||
* with the native control).
|
||||
*/
|
||||
int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
|
||||
{
|
||||
ME_String *strRunText;
|
||||
/* This could point to either the run's real text, or it's masked form in a password control */
|
||||
|
||||
int fit = 0, fit1 = 0;
|
||||
HGDIOBJ hOldFont;
|
||||
HDC hDC;
|
||||
|
@ -399,7 +554,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
|
|||
if (!run->strText->nLen)
|
||||
return 0;
|
||||
|
||||
if (run->nFlags & MERF_TAB)
|
||||
if (run->nFlags & (MERF_TAB | MERF_CELL))
|
||||
{
|
||||
if (cx < run->nWidth/2)
|
||||
return 0;
|
||||
|
@ -413,31 +568,48 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
|
|||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (editor->cPasswordMask)
|
||||
strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(run->strText));
|
||||
else
|
||||
strRunText = run->strText;
|
||||
|
||||
hDC = GetDC(editor->hWnd);
|
||||
hOldFont = ME_SelectStyleFont(editor, hDC, run->style);
|
||||
GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen,
|
||||
GetTextExtentExPointW(hDC, strRunText->szData, strRunText->nLen,
|
||||
cx, &fit, NULL, &sz);
|
||||
if (fit != run->strText->nLen)
|
||||
if (fit != strRunText->nLen)
|
||||
{
|
||||
int chars = 1;
|
||||
|
||||
GetTextExtentPoint32W(hDC, run->strText->szData, fit, &sz2);
|
||||
fit1 = ME_StrRelPos(run->strText, fit, &chars);
|
||||
GetTextExtentPoint32W(hDC, run->strText->szData, fit1, &sz3);
|
||||
GetTextExtentPoint32W(hDC, strRunText->szData, fit, &sz2);
|
||||
fit1 = ME_StrRelPos(strRunText, fit, &chars);
|
||||
GetTextExtentPoint32W(hDC, strRunText->szData, fit1, &sz3);
|
||||
if (cx >= (sz2.cx+sz3.cx)/2)
|
||||
fit = fit1;
|
||||
}
|
||||
|
||||
if (editor->cPasswordMask)
|
||||
ME_DestroyString(strRunText);
|
||||
|
||||
ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);
|
||||
ReleaseDC(editor->hWnd, hDC);
|
||||
return fit;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_PointFromChar
|
||||
*
|
||||
* Returns a run-relative pixel position given a run-relative character
|
||||
* position (character offset)
|
||||
*/
|
||||
int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset)
|
||||
{
|
||||
SIZE size;
|
||||
HDC hDC = GetDC(editor->hWnd);
|
||||
HGDIOBJ hOldFont;
|
||||
ME_String *strRunText;
|
||||
/* This could point to either the run's real text, or it's masked form in a password control */
|
||||
|
||||
if (pRun->nFlags & MERF_GRAPHICS)
|
||||
{
|
||||
|
@ -445,15 +617,27 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset)
|
|||
ME_GetGraphicsSize(editor, pRun, &size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (editor->cPasswordMask)
|
||||
strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(pRun->strText));
|
||||
else
|
||||
strRunText = pRun->strText;
|
||||
|
||||
hOldFont = ME_SelectStyleFont(editor, hDC, pRun->style);
|
||||
GetTextExtentPoint32W(hDC, pRun->strText->szData, nOffset, &size);
|
||||
GetTextExtentPoint32W(hDC, strRunText->szData, nOffset, &size);
|
||||
ME_UnselectStyleFont(editor, hDC, pRun->style, hOldFont);
|
||||
ReleaseDC(editor->hWnd, hDC);
|
||||
if (editor->cPasswordMask)
|
||||
ME_DestroyString(strRunText);
|
||||
return size.cx;
|
||||
}
|
||||
|
||||
void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s,
|
||||
SIZE *size)
|
||||
/******************************************************************************
|
||||
* ME_GetTextExtent
|
||||
*
|
||||
* Finds a width and a height of the text using a specified style
|
||||
*/
|
||||
static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size)
|
||||
{
|
||||
HDC hDC = c->hDC;
|
||||
HGDIOBJ hOldFont;
|
||||
|
@ -462,7 +646,14 @@ void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s,
|
|||
ME_UnselectStyleFont(c->editor, hDC, s, hOldFont);
|
||||
}
|
||||
|
||||
SIZE ME_GetRunSizeCommon(ME_Context *c, ME_Paragraph *para, ME_Run *run, int nLen, int *pAscent, int *pDescent)
|
||||
/******************************************************************************
|
||||
* ME_GetRunSizeCommon
|
||||
*
|
||||
* Finds width, height, ascent and descent of a run, up to given character
|
||||
* (nLen).
|
||||
*/
|
||||
static SIZE ME_GetRunSizeCommon(ME_Context *c, ME_Paragraph *para, ME_Run *run, int nLen,
|
||||
int *pAscent, int *pDescent)
|
||||
{
|
||||
SIZE size;
|
||||
int nMaxLen = ME_StrVLen(run->strText);
|
||||
|
@ -471,10 +662,20 @@ SIZE ME_GetRunSizeCommon(ME_Context *c, ME_Paragraph *para, ME_Run *run, int nLe
|
|||
nLen = nMaxLen;
|
||||
|
||||
/* FIXME the following call also ensures that TEXTMETRIC structure is filled
|
||||
* this is wasteful for graphics and TAB runs, but that shouldn't matter
|
||||
* this is wasteful for MERF_NONTEXT runs, but that shouldn't matter
|
||||
* in practice
|
||||
*/
|
||||
ME_GetTextExtent(c, run->strText->szData, nLen, run->style, &size);
|
||||
|
||||
if (c->editor->cPasswordMask)
|
||||
{
|
||||
ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,nLen);
|
||||
ME_GetTextExtent(c, szMasked->szData, nLen,run->style, &size);
|
||||
ME_DestroyString(szMasked);
|
||||
}
|
||||
else
|
||||
{
|
||||
ME_GetTextExtent(c, run->strText->szData, nLen, run->style, &size);
|
||||
}
|
||||
*pAscent = run->style->tm.tmAscent;
|
||||
*pDescent = run->style->tm.tmDescent;
|
||||
size.cy = *pAscent + *pDescent;
|
||||
|
@ -511,31 +712,67 @@ SIZE ME_GetRunSizeCommon(ME_Context *c, ME_Paragraph *para, ME_Run *run, int nLe
|
|||
/* descent is unchanged */
|
||||
return size;
|
||||
}
|
||||
if (run->nFlags & MERF_CELL)
|
||||
{
|
||||
int lpsx = GetDeviceCaps(c->hDC, LOGPIXELSX);
|
||||
|
||||
size.cx = run->pCell->nRightBoundary * lpsx / 1440 - run->pt.x;
|
||||
return size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_GetRunSize
|
||||
*
|
||||
* Finds width and height (but not ascent and descent) of a part of the run
|
||||
* up to given character.
|
||||
*/
|
||||
SIZE ME_GetRunSize(ME_Context *c, ME_Paragraph *para, ME_Run *run, int nLen)
|
||||
{
|
||||
int asc, desc;
|
||||
return ME_GetRunSizeCommon(c, para, run, nLen, &asc, &desc);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_CalcRunExtent
|
||||
*
|
||||
* Updates the size of the run (fills width, ascent and descent). The height
|
||||
* is calculated based on whole row's ascent and descent anyway, so no need
|
||||
* to use it here.
|
||||
*/
|
||||
void ME_CalcRunExtent(ME_Context *c, ME_Paragraph *para, ME_Run *run)
|
||||
{
|
||||
int nEnd = ME_StrVLen(run->strText);
|
||||
SIZE size = ME_GetRunSizeCommon(c, para, run, nEnd, &run->nAscent, &run->nDescent);
|
||||
run->nWidth = size.cx;
|
||||
if (!size.cx)
|
||||
WARN("size.cx == 0\n");
|
||||
if (run->nFlags & MERF_HIDDEN)
|
||||
run->nWidth = 0;
|
||||
else
|
||||
{
|
||||
int nEnd = ME_StrVLen(run->strText);
|
||||
SIZE size = ME_GetRunSizeCommon(c, para, run, nEnd, &run->nAscent, &run->nDescent);
|
||||
run->nWidth = size.cx;
|
||||
if (!size.cx)
|
||||
WARN("size.cx == 0\n");
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_MustBeWrapped
|
||||
*
|
||||
* This should ensure that the given paragraph is wrapped so that its screen
|
||||
* row structure may be used. But it doesn't, yet.
|
||||
*/
|
||||
void ME_MustBeWrapped(ME_Context *c, ME_DisplayItem *para)
|
||||
{
|
||||
assert(para->type == diParagraph);
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_SetSelectionCharFormat
|
||||
*
|
||||
* Applies a style change, either to a current selection, or to insert cursor
|
||||
* (ie. the style next typed characters will use).
|
||||
*/
|
||||
void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
|
||||
{
|
||||
int nFrom, nTo;
|
||||
|
@ -553,6 +790,11 @@ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
|
|||
ME_SetCharFormat(editor, nFrom, nTo-nFrom, pFmt);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_SetCharFormat
|
||||
*
|
||||
* Applies a style change to the specified part of the text
|
||||
*/
|
||||
void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W *pFmt)
|
||||
{
|
||||
ME_Cursor tmp, tmp2;
|
||||
|
@ -597,6 +839,11 @@ void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W
|
|||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_SetDefaultCharFormat
|
||||
*
|
||||
* Applies a style change to the default character style.
|
||||
*/
|
||||
void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod)
|
||||
{
|
||||
ME_Style *style;
|
||||
|
@ -618,11 +865,17 @@ void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod)
|
|||
/* pcf = editor->pBuffer->pDefaultStyle->fmt; */
|
||||
}
|
||||
|
||||
void ME_GetRunCharFormat(ME_TextEditor *editor, ME_DisplayItem *run, CHARFORMAT2W *pFmt)
|
||||
static void ME_GetRunCharFormat(ME_TextEditor *editor, ME_DisplayItem *run, CHARFORMAT2W *pFmt)
|
||||
{
|
||||
ME_CopyCharFormat(pFmt, &run->member.run.style->fmt);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_GetDefaultCharFormat
|
||||
*
|
||||
* Retrieves the current default character style (the one applied where no
|
||||
* other style was applied) .
|
||||
*/
|
||||
void ME_GetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
|
||||
{
|
||||
int nFrom, nTo;
|
||||
|
@ -630,6 +883,12 @@ void ME_GetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
|
|||
ME_CopyCharFormat(pFmt, &editor->pBuffer->pDefaultStyle->fmt);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_GetSelectionCharFormat
|
||||
*
|
||||
* If selection exists, it returns all style elements that are set consistently
|
||||
* in the whole selection. If not, it just returns the current style.
|
||||
*/
|
||||
void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
|
||||
{
|
||||
int nFrom, nTo;
|
||||
|
@ -642,6 +901,12 @@ void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
|
|||
ME_GetCharFormat(editor, nFrom, nTo, pFmt);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ME_GetCharFormat
|
||||
*
|
||||
* Returns the style consisting of those attributes which are consistently set
|
||||
* in the whole character range.
|
||||
*/
|
||||
void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *pFmt)
|
||||
{
|
||||
ME_DisplayItem *run, *run_end;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "editor.h"
|
||||
|
@ -40,13 +40,39 @@ ME_String *ME_MakeString(LPCWSTR szText)
|
|||
ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars)
|
||||
{
|
||||
ME_String *s = ALLOC_OBJ(ME_String);
|
||||
int i;
|
||||
for (i=0; i<nMaxChars && szText[i]; i++)
|
||||
;
|
||||
s->nLen = i;
|
||||
|
||||
s->nLen = nMaxChars;
|
||||
s->nBuffer = ME_GetOptimalBuffer(s->nLen+1);
|
||||
s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer);
|
||||
lstrcpynW(s->szData, szText, s->nLen+1);
|
||||
/* Native allows NUL chars */
|
||||
memmove(s->szData, szText, s->nLen * sizeof(WCHAR));
|
||||
s->szData[s->nLen] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
ME_String *ME_MakeStringR(WCHAR cRepeat, int nMaxChars)
|
||||
{ /* Make a string by repeating a char nMaxChars times */
|
||||
int i;
|
||||
ME_String *s = ALLOC_OBJ(ME_String);
|
||||
|
||||
s->nLen = nMaxChars;
|
||||
s->nBuffer = ME_GetOptimalBuffer(s->nLen+1);
|
||||
s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer);
|
||||
|
||||
for (i = 0;i<nMaxChars;i++)
|
||||
s->szData[i] = cRepeat;
|
||||
s->szData[s->nLen] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
ME_String *ME_MakeStringB(int nMaxChars)
|
||||
{ /* Create a buffer (uninitialized string) of size nMaxChars */
|
||||
ME_String *s = ALLOC_OBJ(ME_String);
|
||||
|
||||
s->nLen = nMaxChars;
|
||||
s->nBuffer = ME_GetOptimalBuffer(s->nLen+1);
|
||||
s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer);
|
||||
s->szData[s->nLen] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -155,29 +181,22 @@ int ME_StrVLen(ME_String *s) {
|
|||
return s->nLen;
|
||||
}
|
||||
|
||||
/* FIXME we use widechars, not multibytes, inside, no need for complex logic anymore */
|
||||
int ME_StrRelPos(ME_String *s, int nVChar, int *pRelChars)
|
||||
{
|
||||
int nRelChars = *pRelChars;
|
||||
|
||||
TRACE("%s,%d,&%d\n", debugstr_w(s->szData), nVChar, *pRelChars);
|
||||
|
||||
assert(*pRelChars);
|
||||
if (!*pRelChars) return nVChar;
|
||||
|
||||
if (*pRelChars>0)
|
||||
{
|
||||
while(nVChar<s->nLen && *pRelChars>0)
|
||||
{
|
||||
nVChar++;
|
||||
(*pRelChars)--;
|
||||
}
|
||||
if (!nRelChars)
|
||||
return nVChar;
|
||||
}
|
||||
|
||||
while(nVChar>0 && *pRelChars<0)
|
||||
{
|
||||
nVChar--;
|
||||
(*pRelChars)++;
|
||||
}
|
||||
|
||||
if (nRelChars>0)
|
||||
nRelChars = min(*pRelChars, s->nLen - nVChar);
|
||||
else
|
||||
nRelChars = max(*pRelChars, -nVChar);
|
||||
nVChar += nRelChars;
|
||||
*pRelChars -= nRelChars;
|
||||
return nVChar;
|
||||
}
|
||||
|
||||
|
@ -278,9 +297,57 @@ int ME_ReverseFindWhitespaceV(ME_String *s, int nVChar) {
|
|||
return i;
|
||||
}
|
||||
|
||||
LPWSTR ME_ToUnicode(HWND hWnd, LPVOID psz)
|
||||
|
||||
static int
|
||||
ME_WordBreakProc(LPWSTR s, INT start, INT len, INT code)
|
||||
{
|
||||
if (IsWindowUnicode(hWnd))
|
||||
/* FIXME: Native also knows about punctuation */
|
||||
TRACE("s==%s, start==%d, len==%d, code==%d\n",
|
||||
debugstr_wn(s, len), start, len, code);
|
||||
switch (code)
|
||||
{
|
||||
case WB_ISDELIMITER:
|
||||
return ME_IsWSpace(s[start]);
|
||||
case WB_LEFT:
|
||||
case WB_MOVEWORDLEFT:
|
||||
while (start && ME_IsWSpace(s[start - 1]))
|
||||
start--;
|
||||
while (start && !ME_IsWSpace(s[start - 1]))
|
||||
start--;
|
||||
return start;
|
||||
case WB_RIGHT:
|
||||
case WB_MOVEWORDRIGHT:
|
||||
if (start && ME_IsWSpace(s[start - 1]))
|
||||
{
|
||||
while (start < len && ME_IsWSpace(s[start]))
|
||||
start++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (start < len && !ME_IsWSpace(s[start]))
|
||||
start++;
|
||||
while (start < len && ME_IsWSpace(s[start]))
|
||||
start++;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ME_CallWordBreakProc(ME_TextEditor *editor, ME_String *str, INT start, INT code)
|
||||
{
|
||||
/* FIXME: ANSIfy the string when bEmulateVersion10 is TRUE */
|
||||
if (!editor->pfnWordBreak)
|
||||
return ME_WordBreakProc(str->szData, start, str->nLen, code);
|
||||
else
|
||||
return editor->pfnWordBreak(str->szData, start, str->nLen, code);
|
||||
}
|
||||
|
||||
LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz)
|
||||
{
|
||||
if (unicode)
|
||||
return (LPWSTR)psz;
|
||||
else {
|
||||
WCHAR *tmp;
|
||||
|
@ -291,27 +358,8 @@ LPWSTR ME_ToUnicode(HWND hWnd, LPVOID psz)
|
|||
}
|
||||
}
|
||||
|
||||
void ME_EndToUnicode(HWND hWnd, LPVOID psz)
|
||||
void ME_EndToUnicode(BOOL unicode, LPVOID psz)
|
||||
{
|
||||
if (IsWindowUnicode(hWnd))
|
||||
FREE_OBJ(psz);
|
||||
}
|
||||
|
||||
LPSTR ME_ToAnsi(HWND hWnd, LPVOID psz)
|
||||
{
|
||||
if (!IsWindowUnicode(hWnd))
|
||||
return (LPSTR)psz;
|
||||
else {
|
||||
char *tmp;
|
||||
int nChars = WideCharToMultiByte(CP_ACP, 0, (WCHAR *)psz, -1, NULL, 0, NULL, NULL);
|
||||
if((tmp = ALLOC_N_OBJ(char, nChars)) != NULL)
|
||||
WideCharToMultiByte(CP_ACP, 0, (WCHAR *)psz, -1, tmp, nChars, NULL, NULL);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void ME_EndToAnsi(HWND hWnd, LPVOID psz)
|
||||
{
|
||||
if (!IsWindowUnicode(hWnd))
|
||||
if (!unicode)
|
||||
FREE_OBJ(psz);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "editor.h"
|
||||
|
@ -237,6 +237,7 @@ void ME_DumpStyleToBuf(CHARFORMAT2W *pFmt, char buf[2048])
|
|||
ME_DumpStyleEffect(&p, "Font italic:", pFmt, CFM_ITALIC);
|
||||
ME_DumpStyleEffect(&p, "Font underline:", pFmt, CFM_UNDERLINE);
|
||||
ME_DumpStyleEffect(&p, "Font strikeout:", pFmt, CFM_STRIKEOUT);
|
||||
ME_DumpStyleEffect(&p, "Hidden text:", pFmt, CFM_HIDDEN);
|
||||
p += sprintf(p, "Text color: ");
|
||||
if (pFmt->dwMask & CFM_COLOR)
|
||||
{
|
||||
|
@ -274,7 +275,7 @@ ME_LogFontFromStyle(HDC hDC, LOGFONTW *lf, ME_Style *s, int nZoomNumerator, int
|
|||
lf->lfWeight = s->fmt.wWeight;
|
||||
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_ITALIC)
|
||||
lf->lfItalic = 1;
|
||||
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_UNDERLINE)
|
||||
if (s->fmt.dwEffects & s->fmt.dwMask & (CFM_UNDERLINE | CFE_LINK))
|
||||
lf->lfUnderline = 1;
|
||||
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_STRIKEOUT)
|
||||
lf->lfStrikeOut = 1;
|
||||
|
@ -285,8 +286,29 @@ ME_LogFontFromStyle(HDC hDC, LOGFONTW *lf, ME_Style *s, int nZoomNumerator, int
|
|||
lf->lfCharSet = s->fmt.bCharSet;
|
||||
}
|
||||
|
||||
void ME_CharFormatFromLogFont(HDC hDC, LOGFONTW *lf, CHARFORMAT2W *fmt)
|
||||
{
|
||||
int rx, ry;
|
||||
|
||||
ME_InitCharFormat2W(fmt);
|
||||
rx = GetDeviceCaps(hDC, LOGPIXELSX);
|
||||
ry = GetDeviceCaps(hDC, LOGPIXELSY);
|
||||
lstrcpyW(fmt->szFaceName, lf->lfFaceName);
|
||||
fmt->dwEffects = 0;
|
||||
fmt->dwMask = CFM_WEIGHT|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT|CFM_SIZE|CFM_FACE|CFM_CHARSET;
|
||||
fmt->wWeight = lf->lfWeight;
|
||||
fmt->yHeight = -lf->lfHeight*1440/ry;
|
||||
if (lf->lfWeight>400) fmt->dwEffects |= CFM_BOLD;
|
||||
if (lf->lfItalic) fmt->dwEffects |= CFM_ITALIC;
|
||||
if (lf->lfUnderline) fmt->dwEffects |= CFM_UNDERLINE;
|
||||
/* notice that if a logfont was created with underline due to CFM_LINK, this
|
||||
would add an erronious CFM_UNDERLINE. This isn't currently ever a problem */
|
||||
if (lf->lfStrikeOut) fmt->dwEffects |= CFM_STRIKEOUT;
|
||||
fmt->bPitchAndFamily = lf->lfPitchAndFamily;
|
||||
fmt->bCharSet = lf->lfCharSet;
|
||||
}
|
||||
|
||||
BOOL ME_IsFontEqual(LOGFONTW *p1, LOGFONTW *p2)
|
||||
static BOOL ME_IsFontEqual(LOGFONTW *p1, LOGFONTW *p2)
|
||||
{
|
||||
if (memcmp(p1, p2, sizeof(LOGFONTW)-sizeof(p1->lfFaceName)))
|
||||
return FALSE;
|
||||
|
@ -316,7 +338,7 @@ HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s)
|
|||
if (item->nAge > nAge)
|
||||
nEmpty = i, nAge = item->nAge;
|
||||
}
|
||||
if (ME_IsFontEqual(&item->lfSpecs, &lf))
|
||||
if (item->hFont && ME_IsFontEqual(&item->lfSpecs, &lf))
|
||||
break;
|
||||
}
|
||||
if (i < HFONT_CACHE_SIZE) /* found */
|
||||
|
@ -371,7 +393,7 @@ void ME_UnselectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s, HFONT hOl
|
|||
assert(0 == "UnselectStyleFont without SelectStyleFont");
|
||||
}
|
||||
|
||||
void ME_DestroyStyle(ME_Style *s) {
|
||||
static void ME_DestroyStyle(ME_Style *s) {
|
||||
if (s->hFont)
|
||||
{
|
||||
DeleteObject(s->hFont);
|
||||
|
|
393
reactos/dll/win32/riched20/txtsrv.c
Normal file
393
reactos/dll/win32/riched20/txtsrv.c
Normal file
|
@ -0,0 +1,393 @@
|
|||
/*
|
||||
* RichEdit - functions and interfaces around CreateTextServices
|
||||
*
|
||||
* Copyright 2005, 2006, Maarten Lankhorst
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#define NONAMELESSSTRUCT
|
||||
#define NONAMELESSUNION
|
||||
#define COBJMACROS
|
||||
|
||||
#include "editor.h"
|
||||
#include "ole2.h"
|
||||
#include "richole.h"
|
||||
#include "winreg.h"
|
||||
#include "imm.h"
|
||||
#include "textserv.h"
|
||||
#include "wine/debug.h"
|
||||
#include "editstr.h"
|
||||
|
||||
#ifdef __i386__ /* thiscall functions are i386-specific */
|
||||
|
||||
#define THISCALL(func) __thiscall_ ## func
|
||||
#define DEFINE_THISCALL_WRAPPER(func) \
|
||||
extern typeof(func) THISCALL(func); \
|
||||
__ASM_GLOBAL_FUNC(__thiscall_ ## func, \
|
||||
"popl %eax\n\t" \
|
||||
"pushl %ecx\n\t" \
|
||||
"pushl %eax\n\t" \
|
||||
"jmp " __ASM_NAME(#func) )
|
||||
#else /* __i386__ */
|
||||
|
||||
#define THISCALL(func) func
|
||||
#define DEFINE_THISCALL_WRAPPER(func) /* nothing */
|
||||
|
||||
#endif /* __i386__ */
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||
|
||||
typedef struct ITextServicesImpl {
|
||||
const ITextServicesVtbl *lpVtbl;
|
||||
ITextHost *pMyHost;
|
||||
LONG ref;
|
||||
CRITICAL_SECTION csTxtSrv;
|
||||
} ITextServicesImpl;
|
||||
|
||||
static const ITextServicesVtbl textservices_Vtbl;
|
||||
|
||||
/******************************************************************
|
||||
* CreateTextServices (RICHED20.4)
|
||||
*/
|
||||
HRESULT WINAPI CreateTextServices(IUnknown * pUnkOuter,
|
||||
ITextHost * pITextHost,
|
||||
IUnknown **ppUnk)
|
||||
{
|
||||
ITextServicesImpl *ITextImpl;
|
||||
TRACE("%p %p --> %p\n", pUnkOuter, pITextHost, ppUnk);
|
||||
if (pITextHost == NULL)
|
||||
return E_POINTER;
|
||||
|
||||
ITextImpl = CoTaskMemAlloc(sizeof(*ITextImpl));
|
||||
if (ITextImpl == NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
InitializeCriticalSection(&ITextImpl->csTxtSrv);
|
||||
ITextImpl->csTxtSrv.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ITextServicesImpl.csTxtSrv");
|
||||
ITextImpl->ref = 1;
|
||||
ITextHost_AddRef(pITextHost);
|
||||
ITextImpl->pMyHost = pITextHost;
|
||||
ITextImpl->lpVtbl = &textservices_Vtbl;
|
||||
|
||||
if (pUnkOuter)
|
||||
{
|
||||
FIXME("Support aggregation\n");
|
||||
return CLASS_E_NOAGGREGATION;
|
||||
}
|
||||
|
||||
*ppUnk = (IUnknown *)ITextImpl;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#define ICOM_THIS_MULTI(impl,field,iface) \
|
||||
impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
|
||||
|
||||
static HRESULT WINAPI fnTextSrv_QueryInterface(ITextServices * iface,
|
||||
REFIID riid,
|
||||
LPVOID * ppv)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
|
||||
*ppv = NULL;
|
||||
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ITextServices))
|
||||
*ppv = (LPVOID)This;
|
||||
|
||||
if (*ppv)
|
||||
{
|
||||
IUnknown_AddRef((IUnknown *)(*ppv));
|
||||
TRACE ("-- Interface = %p\n", *ppv);
|
||||
return S_OK;
|
||||
}
|
||||
FIXME("Unknown interface: %s\n", debugstr_guid(riid));
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI fnTextSrv_AddRef(ITextServices *iface)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
DWORD ref = InterlockedIncrement(&This->ref);
|
||||
|
||||
TRACE("(%p/%p)->() AddRef from %d\n", This, iface, ref - 1);
|
||||
return ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI fnTextSrv_Release(ITextServices *iface)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
DWORD ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
TRACE("(%p/%p)->() Release from %d\n", This, iface, ref + 1);
|
||||
|
||||
if (!ref)
|
||||
{
|
||||
ITextHost_Release(This->pMyHost);
|
||||
This->csTxtSrv.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection(&This->csTxtSrv);
|
||||
CoTaskMemFree(This);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxSendMessage(ITextServices *iface,
|
||||
UINT msg,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam,
|
||||
LRESULT* plresult)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI 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)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxGetHScroll(ITextServices *iface,
|
||||
LONG* plMin,
|
||||
LONG* plMax,
|
||||
LONG* plPos,
|
||||
LONG* plPage,
|
||||
BOOL* pfEnabled)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxGetVScroll(ITextServices *iface,
|
||||
LONG* plMin,
|
||||
LONG* plMax,
|
||||
LONG* plPos,
|
||||
LONG* plPage,
|
||||
BOOL* pfEnabled)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_OnTxSetCursor(ITextServices *iface,
|
||||
DWORD dwDrawAspect,
|
||||
LONG lindex,
|
||||
void* pvAspect,
|
||||
DVTARGETDEVICE* ptd,
|
||||
HDC hdcDraw,
|
||||
HDC hicTargetDev,
|
||||
LPCRECT lprcClient,
|
||||
INT x, INT y)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxQueryHitPoint(ITextServices *iface,
|
||||
DWORD dwDrawAspect,
|
||||
LONG lindex,
|
||||
void* pvAspect,
|
||||
DVTARGETDEVICE* ptd,
|
||||
HDC hdcDraw,
|
||||
HDC hicTargetDev,
|
||||
LPCRECT lprcClient,
|
||||
INT x, INT y,
|
||||
DWORD* pHitResult)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_OnTxInplaceActivate(ITextServices *iface,
|
||||
LPCRECT prcClient)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_OnTxInplaceDeactivate(ITextServices *iface)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_OnTxUIActivate(ITextServices *iface)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_OnTxUIDeactivate(ITextServices *iface)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxGetText(ITextServices *iface,
|
||||
BSTR* pbstrText)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxSetText(ITextServices *iface,
|
||||
LPCWSTR pszText)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxGetCurrentTargetX(ITextServices *iface,
|
||||
LONG* x)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxGetBaseLinePos(ITextServices *iface,
|
||||
LONG* x)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxGetNaturalSize(ITextServices *iface,
|
||||
DWORD dwAspect,
|
||||
HDC hdcDraw,
|
||||
HDC hicTargetDev,
|
||||
DVTARGETDEVICE* ptd,
|
||||
DWORD dwMode,
|
||||
const SIZEL* psizelExtent,
|
||||
LONG* pwidth,
|
||||
LONG* pheight)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxGetDropTarget(ITextServices *iface,
|
||||
IDropTarget** ppDropTarget)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_OnTxPropertyBitsChange(ITextServices *iface,
|
||||
DWORD dwMask,
|
||||
DWORD dwBits)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxGetCachedSize(ITextServices *iface,
|
||||
DWORD* pdwWidth,
|
||||
DWORD* pdwHeight)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceActivate)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceDeactivate)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurrentTargetX)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange)
|
||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize)
|
||||
|
||||
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_TxGetCurrentTargetX),
|
||||
THISCALL(fnTextSrv_TxGetBaseLinePos),
|
||||
THISCALL(fnTextSrv_TxGetNaturalSize),
|
||||
THISCALL(fnTextSrv_TxGetDropTarget),
|
||||
THISCALL(fnTextSrv_OnTxPropertyBitsChange),
|
||||
THISCALL(fnTextSrv_TxGetCachedSize)
|
||||
};
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "editor.h"
|
||||
|
@ -32,7 +32,8 @@ void ME_EmptyUndoStack(ME_TextEditor *editor)
|
|||
TRACE("Emptying undo stack\n");
|
||||
|
||||
p = editor->pUndoStack;
|
||||
editor->pUndoStack = NULL;
|
||||
editor->pUndoStack = editor->pUndoStackBottom = NULL;
|
||||
editor->nUndoStackSize = 0;
|
||||
while(p) {
|
||||
pNext = p->next;
|
||||
ME_DestroyDisplayItem(p);
|
||||
|
@ -50,6 +51,8 @@ void ME_EmptyUndoStack(ME_TextEditor *editor)
|
|||
ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, ME_DisplayItem *pdi) {
|
||||
if (editor->nUndoMode == umIgnore)
|
||||
return NULL;
|
||||
else if (editor->nUndoLimit == 0)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
ME_DisplayItem *pItem = (ME_DisplayItem *)ALLOC_OBJ(ME_UndoItem);
|
||||
|
@ -93,10 +96,31 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, ME_DisplayIte
|
|||
TRACE("Pushing id=%s to undo stack, deleting redo stack\n", ME_GetDITypeName(type));
|
||||
else
|
||||
TRACE("Pushing id=%s to undo stack\n", ME_GetDITypeName(type));
|
||||
|
||||
pItem->next = editor->pUndoStack;
|
||||
if (type == diUndoEndTransaction)
|
||||
editor->nUndoStackSize++;
|
||||
if (editor->pUndoStack)
|
||||
editor->pUndoStack->prev = pItem;
|
||||
else
|
||||
editor->pUndoStackBottom = pItem;
|
||||
editor->pUndoStack = pItem;
|
||||
|
||||
if (editor->nUndoStackSize > editor->nUndoLimit)
|
||||
{ /* remove oldest undo from stack */
|
||||
ME_DisplayItem *p = editor->pUndoStackBottom;
|
||||
while (p->type !=diUndoEndTransaction)
|
||||
p = p->prev; /*find new stack bottom */
|
||||
editor->pUndoStackBottom = p->prev;
|
||||
editor->pUndoStackBottom->next = NULL;
|
||||
do
|
||||
{
|
||||
ME_DisplayItem *pp = p->next;
|
||||
ME_DestroyDisplayItem(p);
|
||||
p = pp;
|
||||
} while (p);
|
||||
editor->nUndoStackSize--;
|
||||
}
|
||||
/* any new operation (not redo) clears the redo stack */
|
||||
if (editor->nUndoMode == umAddToUndo) {
|
||||
ME_DisplayItem *p = editor->pRedoStack;
|
||||
|
@ -124,7 +148,6 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, ME_DisplayIte
|
|||
}
|
||||
|
||||
void ME_CommitUndo(ME_TextEditor *editor) {
|
||||
|
||||
if (editor->nUndoMode == umIgnore)
|
||||
return;
|
||||
|
||||
|
@ -140,10 +163,9 @@ void ME_CommitUndo(ME_TextEditor *editor) {
|
|||
|
||||
ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
|
||||
ME_SendSelChange(editor);
|
||||
editor->nModifyStep++;
|
||||
}
|
||||
|
||||
void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
|
||||
static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
|
||||
{
|
||||
ME_UndoItem *pUItem = (ME_UndoItem *)pItem;
|
||||
|
||||
|
@ -233,10 +255,10 @@ void ME_Undo(ME_TextEditor *editor) {
|
|||
} while(p && p->type != diUndoEndTransaction);
|
||||
ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
|
||||
editor->pUndoStack = p;
|
||||
editor->nUndoStackSize--;
|
||||
if (p)
|
||||
p->prev = NULL;
|
||||
editor->nUndoMode = nMode;
|
||||
editor->nModifyStep--;
|
||||
ME_UpdateRepaint(editor);
|
||||
}
|
||||
|
||||
|
@ -269,6 +291,5 @@ void ME_Redo(ME_TextEditor *editor) {
|
|||
if (p)
|
||||
p->prev = NULL;
|
||||
editor->nUndoMode = nMode;
|
||||
editor->nModifyStep++;
|
||||
ME_UpdateRepaint(editor);
|
||||
}
|
||||
|
|
26
reactos/dll/win32/riched20/version.rc
Normal file
26
reactos/dll/win32/riched20/version.rc
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2006 Mike McCormack
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define WINE_FILEDESCRIPTION_STR "Wine Richedit dll"
|
||||
#define WINE_FILENAME_STR "riched20.dll"
|
||||
#define WINE_FILEVERSION 5,30,23,1215
|
||||
#define WINE_FILEVERSION_STR "5,30,23,1215"
|
||||
#define WINE_PRODUCTVERSION 5,30,23,1215
|
||||
#define WINE_PRODUCTVERSION_STR "5,30,23,1215"
|
||||
|
||||
#include "wine/wine_common_ver.rc"
|
|
@ -16,7 +16,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
|
@ -168,7 +168,7 @@ static ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem
|
|||
int i, idesp, len;
|
||||
ME_Run *run = &p->member.run;
|
||||
|
||||
idesp = i = ME_CharFromPoint(wc->context->editor, loc, &ME_GetParagraph(p)->member.para, run);
|
||||
idesp = i = ME_CharFromPoint(wc->context->editor, loc, run);
|
||||
len = ME_StrVLen(run->strText);
|
||||
assert(len>0);
|
||||
assert(i<len);
|
||||
|
@ -380,15 +380,17 @@ void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
|
|||
|
||||
|
||||
void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp) {
|
||||
ME_DisplayItem *p;
|
||||
ME_DisplayItem *p, *pRow;
|
||||
|
||||
/* remove all items that will be reinserted by paragraph wrapper anyway */
|
||||
tp->member.para.nRows = 0;
|
||||
for (p = tp->next; p!=tp->member.para.next_para; p = p->next) {
|
||||
switch(p->type) {
|
||||
case diStartRow:
|
||||
pRow = p;
|
||||
p = p->prev;
|
||||
ME_Remove(p->next);
|
||||
ME_Remove(pRow);
|
||||
ME_DestroyDisplayItem(pRow);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -422,6 +424,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
|
|||
ME_DisplayItem *item;
|
||||
ME_Context c;
|
||||
BOOL bModified = FALSE;
|
||||
int yStart = -1, yEnd = -1;
|
||||
|
||||
ME_InitContext(&c, editor, hDC);
|
||||
c.pt.x = 0;
|
||||
|
@ -439,11 +442,17 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
|
|||
ME_WrapTextParagraph(&c, item);
|
||||
|
||||
if (bRedraw)
|
||||
{
|
||||
item->member.para.nFlags |= MEPF_REPAINT;
|
||||
if (yStart == -1)
|
||||
yStart = c.pt.y;
|
||||
}
|
||||
|
||||
bModified = bModified | bRedraw;
|
||||
|
||||
c.pt.y += item->member.para.nHeight;
|
||||
if (bRedraw)
|
||||
yEnd = c.pt.y;
|
||||
item = item->member.para.next_para;
|
||||
}
|
||||
editor->sizeWindow.cx = c.rcView.right-c.rcView.left;
|
||||
|
@ -453,9 +462,42 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
|
|||
|
||||
ME_DestroyContext(&c);
|
||||
ReleaseDC(hWnd, hDC);
|
||||
|
||||
if (bModified || editor->nTotalLength < editor->nLastTotalLength)
|
||||
ME_InvalidateMarkedParagraphs(editor);
|
||||
return bModified;
|
||||
}
|
||||
|
||||
void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor) {
|
||||
ME_Context c;
|
||||
HDC hDC = GetDC(editor->hWnd);
|
||||
|
||||
ME_InitContext(&c, editor, hDC);
|
||||
if (editor->bRedraw)
|
||||
{
|
||||
RECT rc = c.rcView;
|
||||
int ofs = ME_GetYScrollPos(editor);
|
||||
|
||||
ME_DisplayItem *item = editor->pBuffer->pFirst;
|
||||
while(item != editor->pBuffer->pLast) {
|
||||
if (item->member.para.nFlags & MEPF_REPAINT) {
|
||||
rc.top = item->member.para.nYPos - ofs;
|
||||
rc.bottom = item->member.para.nYPos + item->member.para.nHeight - ofs;
|
||||
InvalidateRect(editor->hWnd, &rc, TRUE);
|
||||
}
|
||||
item = item->member.para.next_para;
|
||||
}
|
||||
if (editor->nTotalLength < editor->nLastTotalLength)
|
||||
{
|
||||
rc.top = editor->nTotalLength - ofs;
|
||||
rc.bottom = editor->nLastTotalLength - ofs;
|
||||
InvalidateRect(editor->hWnd, &rc, TRUE);
|
||||
}
|
||||
}
|
||||
ME_DestroyContext(&c);
|
||||
ReleaseDC(editor->hWnd, hDC);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ME_SendRequestResize(ME_TextEditor *editor, BOOL force)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "editor.h"
|
||||
|
@ -25,71 +25,69 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
|||
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars);
|
||||
ME_StreamOutRTFText(ME_OutStream *pStream, WCHAR *text, LONG nChars);
|
||||
|
||||
|
||||
static void
|
||||
static ME_OutStream*
|
||||
ME_StreamOutInit(ME_TextEditor *editor, EDITSTREAM *stream)
|
||||
{
|
||||
editor->pStream = ALLOC_OBJ(ME_OutStream);
|
||||
editor->pStream->stream = stream;
|
||||
editor->pStream->stream->dwError = 0;
|
||||
editor->pStream->pos = 0;
|
||||
editor->pStream->written = 0;
|
||||
editor->pStream->nFontTblLen = 0;
|
||||
editor->pStream->nColorTblLen = 1;
|
||||
ME_OutStream *pStream = ALLOC_OBJ(ME_OutStream);
|
||||
pStream->stream = stream;
|
||||
pStream->stream->dwError = 0;
|
||||
pStream->pos = 0;
|
||||
pStream->written = 0;
|
||||
pStream->nFontTblLen = 0;
|
||||
pStream->nColorTblLen = 1;
|
||||
return pStream;
|
||||
}
|
||||
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutFlush(ME_TextEditor *editor)
|
||||
ME_StreamOutFlush(ME_OutStream *pStream)
|
||||
{
|
||||
LONG nStart = 0;
|
||||
LONG nWritten = 0;
|
||||
LONG nRemaining = 0;
|
||||
EDITSTREAM *stream = editor->pStream->stream;
|
||||
EDITSTREAM *stream = pStream->stream;
|
||||
|
||||
do {
|
||||
TRACE("sending %lu bytes\n", editor->pStream->pos - nStart);
|
||||
TRACE("sending %u bytes\n", pStream->pos - nStart);
|
||||
/* Some apps seem not to set *pcb unless a problem arises, relying
|
||||
on initial random nWritten value, which is usually >STREAMOUT_BUFFER_SIZE */
|
||||
nRemaining = editor->pStream->pos - nStart;
|
||||
nRemaining = pStream->pos - nStart;
|
||||
nWritten = 0xDEADBEEF;
|
||||
stream->dwError = stream->pfnCallback(stream->dwCookie, (LPBYTE)editor->pStream->buffer + nStart,
|
||||
editor->pStream->pos - nStart, &nWritten);
|
||||
TRACE("error=%lu written=%lu\n", stream->dwError, nWritten);
|
||||
if (nWritten > (editor->pStream->pos - nStart) || nWritten<0) {
|
||||
FIXME("Invalid returned written size *pcb: 0x%x (%ld) instead of %ld\n",
|
||||
stream->dwError = stream->pfnCallback(stream->dwCookie, (LPBYTE)pStream->buffer + nStart,
|
||||
pStream->pos - nStart, &nWritten);
|
||||
TRACE("error=%u written=%u\n", stream->dwError, nWritten);
|
||||
if (nWritten > (pStream->pos - nStart) || nWritten<0) {
|
||||
FIXME("Invalid returned written size *pcb: 0x%x (%d) instead of %d\n",
|
||||
(unsigned)nWritten, nWritten, nRemaining);
|
||||
nWritten = nRemaining;
|
||||
}
|
||||
if (nWritten == 0 || stream->dwError)
|
||||
return FALSE;
|
||||
editor->pStream->written += nWritten;
|
||||
pStream->written += nWritten;
|
||||
nStart += nWritten;
|
||||
} while (nStart < editor->pStream->pos);
|
||||
editor->pStream->pos = 0;
|
||||
} while (nStart < pStream->pos);
|
||||
pStream->pos = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static LONG
|
||||
ME_StreamOutFree(ME_TextEditor *editor)
|
||||
ME_StreamOutFree(ME_OutStream *pStream)
|
||||
{
|
||||
LONG written = editor->pStream->written;
|
||||
TRACE("total length = %lu\n", written);
|
||||
LONG written = pStream->written;
|
||||
TRACE("total length = %u\n", written);
|
||||
|
||||
FREE_OBJ(editor->pStream);
|
||||
editor->pStream = NULL;
|
||||
FREE_OBJ(pStream);
|
||||
return written;
|
||||
}
|
||||
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutMove(ME_TextEditor *editor, const char *buffer, int len)
|
||||
ME_StreamOutMove(ME_OutStream *pStream, const char *buffer, int len)
|
||||
{
|
||||
ME_OutStream *pStream = editor->pStream;
|
||||
|
||||
while (len) {
|
||||
int space = STREAMOUT_BUFFER_SIZE - pStream->pos;
|
||||
int fit = min(space, len);
|
||||
|
@ -100,7 +98,7 @@ ME_StreamOutMove(ME_TextEditor *editor, const char *buffer, int len)
|
|||
buffer += fit;
|
||||
pStream->pos += fit;
|
||||
if (pStream->pos == STREAMOUT_BUFFER_SIZE) {
|
||||
if (!ME_StreamOutFlush(editor))
|
||||
if (!ME_StreamOutFlush(pStream))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -109,22 +107,22 @@ ME_StreamOutMove(ME_TextEditor *editor, const char *buffer, int len)
|
|||
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutPrint(ME_TextEditor *editor, const char *format, ...)
|
||||
ME_StreamOutPrint(ME_OutStream *pStream, const char *format, ...)
|
||||
{
|
||||
char string[STREAMOUT_BUFFER_SIZE]; /* This is going to be enough */
|
||||
int len;
|
||||
va_list valist;
|
||||
|
||||
va_start(valist, format);
|
||||
len = _vsnprintf(string, sizeof(string), format, valist);
|
||||
len = vsnprintf(string, sizeof(string), format, valist);
|
||||
va_end(valist);
|
||||
|
||||
return ME_StreamOutMove(editor, string, len);
|
||||
return ME_StreamOutMove(pStream, string, len);
|
||||
}
|
||||
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutRTFHeader(ME_TextEditor *editor, int dwFormat)
|
||||
ME_StreamOutRTFHeader(ME_OutStream *pStream, int dwFormat)
|
||||
{
|
||||
const char *cCharSet = NULL;
|
||||
UINT nCodePage;
|
||||
|
@ -171,33 +169,33 @@ ME_StreamOutRTFHeader(ME_TextEditor *editor, int dwFormat)
|
|||
nCodePage = GetACP();
|
||||
}
|
||||
if (nCodePage == CP_UTF8)
|
||||
success = ME_StreamOutPrint(editor, "{\\urtf");
|
||||
success = ME_StreamOutPrint(pStream, "{\\urtf");
|
||||
else
|
||||
success = ME_StreamOutPrint(editor, "{\\rtf1\\%s\\ansicpg%u\\uc1", cCharSet, nCodePage);
|
||||
success = ME_StreamOutPrint(pStream, "{\\rtf1\\%s\\ansicpg%u\\uc1", cCharSet, nCodePage);
|
||||
|
||||
if (!success)
|
||||
return FALSE;
|
||||
|
||||
editor->pStream->nDefaultCodePage = nCodePage;
|
||||
pStream->nDefaultCodePage = nCodePage;
|
||||
|
||||
/* FIXME: This should be a document property */
|
||||
/* TODO: handle SFF_PLAINRTF */
|
||||
language = GetUserDefaultLangID();
|
||||
if (!ME_StreamOutPrint(editor, "\\deff0\\deflang%u\\deflangfe%u", language, language))
|
||||
if (!ME_StreamOutPrint(pStream, "\\deff0\\deflang%u\\deflangfe%u", language, language))
|
||||
return FALSE;
|
||||
|
||||
/* FIXME: This should be a document property */
|
||||
editor->pStream->nDefaultFont = 0;
|
||||
pStream->nDefaultFont = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutRTFFontAndColorTbl(ME_TextEditor *editor, ME_DisplayItem *pFirstRun, ME_DisplayItem *pLastRun)
|
||||
ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, ME_DisplayItem *pLastRun)
|
||||
{
|
||||
ME_DisplayItem *item = pFirstRun;
|
||||
ME_FontTableItem *table = editor->pStream->fonttbl;
|
||||
ME_FontTableItem *table = pStream->fonttbl;
|
||||
int i;
|
||||
|
||||
do {
|
||||
|
@ -208,35 +206,35 @@ ME_StreamOutRTFFontAndColorTbl(ME_TextEditor *editor, ME_DisplayItem *pFirstRun,
|
|||
WCHAR *face = fmt->szFaceName;
|
||||
BYTE bCharSet = (fmt->dwMask & CFM_CHARSET) ? fmt->bCharSet : DEFAULT_CHARSET;
|
||||
|
||||
for (i = 0; i < editor->pStream->nFontTblLen; i++)
|
||||
for (i = 0; i < pStream->nFontTblLen; i++)
|
||||
if (table[i].bCharSet == bCharSet
|
||||
&& (table[i].szFaceName == face || !lstrcmpW(table[i].szFaceName, face)))
|
||||
break;
|
||||
if (i == editor->pStream->nFontTblLen) {
|
||||
if (i == pStream->nFontTblLen) {
|
||||
table[i].bCharSet = bCharSet;
|
||||
table[i].szFaceName = face;
|
||||
editor->pStream->nFontTblLen++;
|
||||
pStream->nFontTblLen++;
|
||||
}
|
||||
}
|
||||
|
||||
if (fmt->dwMask & CFM_COLOR && !(fmt->dwEffects & CFE_AUTOCOLOR)) {
|
||||
crColor = fmt->crTextColor;
|
||||
for (i = 1; i < editor->pStream->nColorTblLen; i++)
|
||||
if (editor->pStream->colortbl[i] == crColor)
|
||||
for (i = 1; i < pStream->nColorTblLen; i++)
|
||||
if (pStream->colortbl[i] == crColor)
|
||||
break;
|
||||
if (i == editor->pStream->nColorTblLen) {
|
||||
editor->pStream->colortbl[i] = crColor;
|
||||
editor->pStream->nColorTblLen++;
|
||||
if (i == pStream->nColorTblLen) {
|
||||
pStream->colortbl[i] = crColor;
|
||||
pStream->nColorTblLen++;
|
||||
}
|
||||
}
|
||||
if (fmt->dwMask & CFM_BACKCOLOR && !(fmt->dwEffects & CFE_AUTOBACKCOLOR)) {
|
||||
crColor = fmt->crBackColor;
|
||||
for (i = 1; i < editor->pStream->nColorTblLen; i++)
|
||||
if (editor->pStream->colortbl[i] == crColor)
|
||||
for (i = 1; i < pStream->nColorTblLen; i++)
|
||||
if (pStream->colortbl[i] == crColor)
|
||||
break;
|
||||
if (i == editor->pStream->nColorTblLen) {
|
||||
editor->pStream->colortbl[i] = crColor;
|
||||
editor->pStream->nColorTblLen++;
|
||||
if (i == pStream->nColorTblLen) {
|
||||
pStream->colortbl[i] = crColor;
|
||||
pStream->nColorTblLen++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,37 +243,37 @@ ME_StreamOutRTFFontAndColorTbl(ME_TextEditor *editor, ME_DisplayItem *pFirstRun,
|
|||
item = ME_FindItemFwd(item, diRun);
|
||||
} while (item);
|
||||
|
||||
if (!ME_StreamOutPrint(editor, "{\\fonttbl"))
|
||||
if (!ME_StreamOutPrint(pStream, "{\\fonttbl"))
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < editor->pStream->nFontTblLen; i++) {
|
||||
for (i = 0; i < pStream->nFontTblLen; i++) {
|
||||
if (table[i].bCharSet != DEFAULT_CHARSET) {
|
||||
if (!ME_StreamOutPrint(editor, "{\\f%u\\fcharset%u ", i, table[i].bCharSet))
|
||||
if (!ME_StreamOutPrint(pStream, "{\\f%u\\fcharset%u ", i, table[i].bCharSet))
|
||||
return FALSE;
|
||||
} else {
|
||||
if (!ME_StreamOutPrint(editor, "{\\f%u ", i))
|
||||
if (!ME_StreamOutPrint(pStream, "{\\f%u ", i))
|
||||
return FALSE;
|
||||
}
|
||||
if (!ME_StreamOutRTFText(editor, table[i].szFaceName, -1))
|
||||
if (!ME_StreamOutRTFText(pStream, table[i].szFaceName, -1))
|
||||
return FALSE;
|
||||
if (!ME_StreamOutPrint(editor, ";}\r\n"))
|
||||
if (!ME_StreamOutPrint(pStream, ";}\r\n"))
|
||||
return FALSE;
|
||||
}
|
||||
if (!ME_StreamOutPrint(editor, "}"))
|
||||
if (!ME_StreamOutPrint(pStream, "}"))
|
||||
return FALSE;
|
||||
|
||||
/* Output colors table if not empty */
|
||||
if (editor->pStream->nColorTblLen > 1) {
|
||||
if (!ME_StreamOutPrint(editor, "{\\colortbl;"))
|
||||
if (pStream->nColorTblLen > 1) {
|
||||
if (!ME_StreamOutPrint(pStream, "{\\colortbl;"))
|
||||
return FALSE;
|
||||
for (i = 1; i < editor->pStream->nColorTblLen; i++) {
|
||||
if (!ME_StreamOutPrint(editor, "\\red%u\\green%u\\blue%u;",
|
||||
editor->pStream->colortbl[i] & 0xFF,
|
||||
(editor->pStream->colortbl[i] >> 8) & 0xFF,
|
||||
(editor->pStream->colortbl[i] >> 16) & 0xFF))
|
||||
for (i = 1; i < pStream->nColorTblLen; i++) {
|
||||
if (!ME_StreamOutPrint(pStream, "\\red%u\\green%u\\blue%u;",
|
||||
pStream->colortbl[i] & 0xFF,
|
||||
(pStream->colortbl[i] >> 8) & 0xFF,
|
||||
(pStream->colortbl[i] >> 16) & 0xFF))
|
||||
return FALSE;
|
||||
}
|
||||
if (!ME_StreamOutPrint(editor, "}"))
|
||||
if (!ME_StreamOutPrint(pStream, "}"))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -284,15 +282,33 @@ ME_StreamOutRTFFontAndColorTbl(ME_TextEditor *editor, ME_DisplayItem *pFirstRun,
|
|||
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_DisplayItem *para)
|
||||
ME_StreamOutRTFParaProps(ME_OutStream *pStream, ME_DisplayItem *para)
|
||||
{
|
||||
PARAFORMAT2 *fmt = para->member.para.pFmt;
|
||||
char props[STREAMOUT_BUFFER_SIZE] = "";
|
||||
int i;
|
||||
|
||||
if (para->member.para.pCells)
|
||||
{
|
||||
ME_TableCell *cell = para->member.para.pCells;
|
||||
|
||||
if (!ME_StreamOutPrint(pStream, "\\trowd"))
|
||||
return FALSE;
|
||||
do {
|
||||
sprintf(props, "\\cellx%d", cell->nRightBoundary);
|
||||
if (!ME_StreamOutPrint(pStream, props))
|
||||
return FALSE;
|
||||
cell = cell->next;
|
||||
} while (cell);
|
||||
props[0] = '\0';
|
||||
}
|
||||
|
||||
/* TODO: Don't emit anything if the last PARAFORMAT2 is inherited */
|
||||
if (!ME_StreamOutPrint(editor, "\\pard"))
|
||||
if (!ME_StreamOutPrint(pStream, "\\pard"))
|
||||
return FALSE;
|
||||
|
||||
if (para->member.para.bTable)
|
||||
strcat(props, "\\intbl");
|
||||
|
||||
/* TODO: PFM_BORDER. M$ does not emit any keywords for these properties, and
|
||||
* when streaming border keywords in, PFM_BORDER is set, but wBorder field is
|
||||
|
@ -330,13 +346,13 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_DisplayItem *para)
|
|||
strcat(props, "\\sl-480\\slmult1");
|
||||
break;
|
||||
case 3:
|
||||
sprintf(props + strlen(props), "\\sl%ld\\slmult0", fmt->dyLineSpacing);
|
||||
sprintf(props + strlen(props), "\\sl%d\\slmult0", fmt->dyLineSpacing);
|
||||
break;
|
||||
case 4:
|
||||
sprintf(props + strlen(props), "\\sl-%ld\\slmult0", fmt->dyLineSpacing);
|
||||
sprintf(props + strlen(props), "\\sl-%d\\slmult0", fmt->dyLineSpacing);
|
||||
break;
|
||||
case 5:
|
||||
sprintf(props + strlen(props), "\\sl-%ld\\slmult1", fmt->dyLineSpacing * 240 / 20);
|
||||
sprintf(props + strlen(props), "\\sl-%d\\slmult1", fmt->dyLineSpacing * 240 / 20);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -361,20 +377,20 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_DisplayItem *para)
|
|||
strcat(props, "\\intbl");
|
||||
|
||||
if (fmt->dwMask & PFM_OFFSET)
|
||||
sprintf(props + strlen(props), "\\li%ld", fmt->dxOffset);
|
||||
sprintf(props + strlen(props), "\\li%d", fmt->dxOffset);
|
||||
if (fmt->dwMask & PFM_OFFSETINDENT || fmt->dwMask & PFM_STARTINDENT)
|
||||
sprintf(props + strlen(props), "\\fi%ld", fmt->dxStartIndent);
|
||||
sprintf(props + strlen(props), "\\fi%d", fmt->dxStartIndent);
|
||||
if (fmt->dwMask & PFM_RIGHTINDENT)
|
||||
sprintf(props + strlen(props), "\\ri%ld", fmt->dxRightIndent);
|
||||
sprintf(props + strlen(props), "\\ri%d", fmt->dxRightIndent);
|
||||
if (fmt->dwMask & PFM_SPACEAFTER)
|
||||
sprintf(props + strlen(props), "\\sa%ld", fmt->dySpaceAfter);
|
||||
sprintf(props + strlen(props), "\\sa%d", fmt->dySpaceAfter);
|
||||
if (fmt->dwMask & PFM_SPACEBEFORE)
|
||||
sprintf(props + strlen(props), "\\sb%ld", fmt->dySpaceBefore);
|
||||
sprintf(props + strlen(props), "\\sb%d", fmt->dySpaceBefore);
|
||||
if (fmt->dwMask & PFM_STYLE)
|
||||
sprintf(props + strlen(props), "\\s%d", fmt->sStyle);
|
||||
|
||||
if (fmt->dwMask & PFM_TABSTOPS) {
|
||||
static const char *leader[6] = { "", "\\tldot", "\\tlhyph", "\\tlul", "\\tlth", "\\tleq" };
|
||||
static const char * const leader[6] = { "", "\\tldot", "\\tlhyph", "\\tlul", "\\tlth", "\\tleq" };
|
||||
|
||||
for (i = 0; i < fmt->cTabCount; i++) {
|
||||
switch ((fmt->rgxTabs[i] >> 24) & 0xF) {
|
||||
|
@ -393,13 +409,13 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_DisplayItem *para)
|
|||
}
|
||||
if (fmt->rgxTabs[i] >> 28 <= 5)
|
||||
strcat(props, leader[fmt->rgxTabs[i] >> 28]);
|
||||
sprintf(props+strlen(props), "\\tx%ld", fmt->rgxTabs[i]&0x00FFFFFF);
|
||||
sprintf(props+strlen(props), "\\tx%d", fmt->rgxTabs[i]&0x00FFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fmt->dwMask & PFM_SHADING) {
|
||||
static const char *style[16] = { "", "\\bgdkhoriz", "\\bgdkvert", "\\bgdkfdiag",
|
||||
static const char * const style[16] = { "", "\\bgdkhoriz", "\\bgdkvert", "\\bgdkfdiag",
|
||||
"\\bgdkbdiag", "\\bgdkcross", "\\bgdkdcross",
|
||||
"\\bghoriz", "\\bgvert", "\\bgfdiag",
|
||||
"\\bgbdiag", "\\bgcross", "\\bgdcross",
|
||||
|
@ -412,7 +428,7 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_DisplayItem *para)
|
|||
(fmt->wShadingStyle >> 4) & 0xF, (fmt->wShadingStyle >> 8) & 0xF);
|
||||
}
|
||||
|
||||
if (*props && !ME_StreamOutPrint(editor, props))
|
||||
if (*props && !ME_StreamOutPrint(pStream, props))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
@ -420,7 +436,7 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_DisplayItem *para)
|
|||
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutRTFCharProps(ME_TextEditor *editor, CHARFORMAT2W *fmt)
|
||||
ME_StreamOutRTFCharProps(ME_OutStream *pStream, CHARFORMAT2W *fmt)
|
||||
{
|
||||
char props[STREAMOUT_BUFFER_SIZE] = "";
|
||||
int i;
|
||||
|
@ -431,8 +447,8 @@ ME_StreamOutRTFCharProps(ME_TextEditor *editor, CHARFORMAT2W *fmt)
|
|||
sprintf(props + strlen(props), "\\animtext%u", fmt->bAnimation);
|
||||
if (fmt->dwMask & CFM_BACKCOLOR) {
|
||||
if (!(fmt->dwEffects & CFE_AUTOBACKCOLOR)) {
|
||||
for (i = 1; i < editor->pStream->nColorTblLen; i++)
|
||||
if (editor->pStream->colortbl[i] == fmt->crBackColor) {
|
||||
for (i = 1; i < pStream->nColorTblLen; i++)
|
||||
if (pStream->colortbl[i] == fmt->crBackColor) {
|
||||
sprintf(props + strlen(props), "\\cb%u", i);
|
||||
break;
|
||||
}
|
||||
|
@ -442,8 +458,8 @@ ME_StreamOutRTFCharProps(ME_TextEditor *editor, CHARFORMAT2W *fmt)
|
|||
strcat(props, "\\b");
|
||||
if (fmt->dwMask & CFM_COLOR) {
|
||||
if (!(fmt->dwEffects & CFE_AUTOCOLOR)) {
|
||||
for (i = 1; i < editor->pStream->nColorTblLen; i++)
|
||||
if (editor->pStream->colortbl[i] == fmt->crTextColor) {
|
||||
for (i = 1; i < pStream->nColorTblLen; i++)
|
||||
if (pStream->colortbl[i] == fmt->crTextColor) {
|
||||
sprintf(props + strlen(props), "\\cf%u", i);
|
||||
break;
|
||||
}
|
||||
|
@ -470,9 +486,9 @@ ME_StreamOutRTFCharProps(ME_TextEditor *editor, CHARFORMAT2W *fmt)
|
|||
/* CFM_LINK is not streamed out by M$ */
|
||||
if (fmt->dwMask & CFM_OFFSET) {
|
||||
if (fmt->yOffset >= 0)
|
||||
sprintf(props + strlen(props), "\\up%ld", fmt->yOffset);
|
||||
sprintf(props + strlen(props), "\\up%d", fmt->yOffset);
|
||||
else
|
||||
sprintf(props + strlen(props), "\\dn%ld", -fmt->yOffset);
|
||||
sprintf(props + strlen(props), "\\dn%d", -fmt->yOffset);
|
||||
}
|
||||
if (fmt->dwMask & CFM_OUTLINE && fmt->dwEffects & CFE_OUTLINE)
|
||||
strcat(props, "\\outl");
|
||||
|
@ -482,7 +498,7 @@ ME_StreamOutRTFCharProps(ME_TextEditor *editor, CHARFORMAT2W *fmt)
|
|||
if (fmt->dwMask & CFM_SHADOW && fmt->dwEffects & CFE_SHADOW)
|
||||
strcat(props, "\\shad");
|
||||
if (fmt->dwMask & CFM_SIZE)
|
||||
sprintf(props + strlen(props), "\\fs%ld", fmt->yHeight / 10);
|
||||
sprintf(props + strlen(props), "\\fs%d", fmt->yHeight / 10);
|
||||
if (fmt->dwMask & CFM_SMALLCAPS && fmt->dwEffects & CFE_SMALLCAPS)
|
||||
strcat(props, "\\scaps");
|
||||
if (fmt->dwMask & CFM_SPACING)
|
||||
|
@ -531,40 +547,39 @@ ME_StreamOutRTFCharProps(ME_TextEditor *editor, CHARFORMAT2W *fmt)
|
|||
if (fmt->dwMask & CFM_FACE)
|
||||
szFaceName = fmt->szFaceName;
|
||||
else
|
||||
szFaceName = editor->pStream->fonttbl[0].szFaceName;
|
||||
for (i = 0; i < editor->pStream->nFontTblLen; i++) {
|
||||
if (szFaceName == editor->pStream->fonttbl[i].szFaceName
|
||||
|| !lstrcmpW(szFaceName, editor->pStream->fonttbl[i].szFaceName))
|
||||
szFaceName = pStream->fonttbl[0].szFaceName;
|
||||
for (i = 0; i < pStream->nFontTblLen; i++) {
|
||||
if (szFaceName == pStream->fonttbl[i].szFaceName
|
||||
|| !lstrcmpW(szFaceName, pStream->fonttbl[i].szFaceName))
|
||||
if (!(fmt->dwMask & CFM_CHARSET)
|
||||
|| fmt->bCharSet == editor->pStream->fonttbl[i].bCharSet)
|
||||
|| fmt->bCharSet == pStream->fonttbl[i].bCharSet)
|
||||
break;
|
||||
}
|
||||
if (i < editor->pStream->nFontTblLen)
|
||||
if (i < pStream->nFontTblLen)
|
||||
{
|
||||
if (i != editor->pStream->nDefaultFont)
|
||||
if (i != pStream->nDefaultFont)
|
||||
sprintf(props + strlen(props), "\\f%u", i);
|
||||
|
||||
/* In UTF-8 mode, charsets/codepages are not used */
|
||||
if (editor->pStream->nDefaultCodePage != CP_UTF8)
|
||||
if (pStream->nDefaultCodePage != CP_UTF8)
|
||||
{
|
||||
if (editor->pStream->fonttbl[i].bCharSet == DEFAULT_CHARSET)
|
||||
editor->pStream->nCodePage = editor->pStream->nDefaultCodePage;
|
||||
if (pStream->fonttbl[i].bCharSet == DEFAULT_CHARSET)
|
||||
pStream->nCodePage = pStream->nDefaultCodePage;
|
||||
else
|
||||
editor->pStream->nCodePage = RTFCharSetToCodePage(NULL,
|
||||
editor->pStream->fonttbl[i].bCharSet);
|
||||
pStream->nCodePage = RTFCharSetToCodePage(NULL, pStream->fonttbl[i].bCharSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*props)
|
||||
strcat(props, " ");
|
||||
if (!ME_StreamOutPrint(editor, props))
|
||||
if (!ME_StreamOutPrint(pStream, props))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars)
|
||||
ME_StreamOutRTFText(ME_OutStream *pStream, WCHAR *text, LONG nChars)
|
||||
{
|
||||
char buffer[STREAMOUT_BUFFER_SIZE];
|
||||
int pos = 0;
|
||||
|
@ -575,7 +590,7 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars)
|
|||
|
||||
while (nChars) {
|
||||
/* In UTF-8 mode, font charsets are not used. */
|
||||
if (editor->pStream->nDefaultCodePage == CP_UTF8) {
|
||||
if (pStream->nDefaultCodePage == CP_UTF8) {
|
||||
/* 6 is the maximum character length in UTF-8 */
|
||||
fit = min(nChars, STREAMOUT_BUFFER_SIZE / 6);
|
||||
nBytes = WideCharToMultiByte(CP_UTF8, 0, text, fit, buffer,
|
||||
|
@ -584,12 +599,12 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars)
|
|||
text += fit;
|
||||
for (i = 0; i < nBytes; i++)
|
||||
if (buffer[i] == '{' || buffer[i] == '}' || buffer[i] == '\\') {
|
||||
if (!ME_StreamOutPrint(editor, "%.*s\\", i - pos, buffer + pos))
|
||||
if (!ME_StreamOutPrint(pStream, "%.*s\\", i - pos, buffer + pos))
|
||||
return FALSE;
|
||||
pos = i;
|
||||
}
|
||||
if (pos < nBytes)
|
||||
if (!ME_StreamOutMove(editor, buffer + pos, nBytes - pos))
|
||||
if (!ME_StreamOutMove(pStream, buffer + pos, nBytes - pos))
|
||||
return FALSE;
|
||||
pos = 0;
|
||||
} else if (*text < 128) {
|
||||
|
@ -605,9 +620,9 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars)
|
|||
* codepages including CP_SYMBOL for which the last parameter must be set
|
||||
* to NULL for the function to succeed. But in Wine we need to care only
|
||||
* about CP_SYMBOL */
|
||||
nBytes = WideCharToMultiByte(editor->pStream->nCodePage, 0, text, 1,
|
||||
nBytes = WideCharToMultiByte(pStream->nCodePage, 0, text, 1,
|
||||
letter, 3, NULL,
|
||||
(editor->pStream->nCodePage == CP_SYMBOL) ? NULL : &unknown);
|
||||
(pStream->nCodePage == CP_SYMBOL) ? NULL : &unknown);
|
||||
if (unknown)
|
||||
pos += sprintf(buffer + pos, "\\u%d?", (short)*text);
|
||||
else if ((BYTE)*letter < 128) {
|
||||
|
@ -622,33 +637,36 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars)
|
|||
nChars--;
|
||||
}
|
||||
if (pos >= STREAMOUT_BUFFER_SIZE - 11) {
|
||||
if (!ME_StreamOutMove(editor, buffer, pos))
|
||||
if (!ME_StreamOutMove(pStream, buffer, pos))
|
||||
return FALSE;
|
||||
pos = 0;
|
||||
}
|
||||
}
|
||||
return ME_StreamOutMove(editor, buffer, pos);
|
||||
return ME_StreamOutMove(pStream, buffer, pos);
|
||||
}
|
||||
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutRTF(ME_TextEditor *editor, int nStart, int nChars, int dwFormat)
|
||||
ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nChars, int dwFormat)
|
||||
{
|
||||
ME_DisplayItem *p, *pEnd;
|
||||
int nOffset, nEndLen;
|
||||
ME_DisplayItem *p, *pEnd, *pPara;
|
||||
int nOffset, nEndLen;
|
||||
|
||||
ME_RunOfsFromCharOfs(editor, nStart, &p, &nOffset);
|
||||
ME_RunOfsFromCharOfs(editor, nStart+nChars, &pEnd, &nEndLen);
|
||||
|
||||
if (!ME_StreamOutRTFHeader(editor, dwFormat))
|
||||
pPara = ME_GetParagraph(p);
|
||||
|
||||
if (!ME_StreamOutRTFHeader(pStream, dwFormat))
|
||||
return FALSE;
|
||||
|
||||
if (!ME_StreamOutRTFFontAndColorTbl(editor, p, pEnd))
|
||||
if (!ME_StreamOutRTFFontAndColorTbl(pStream, p, pEnd))
|
||||
return FALSE;
|
||||
|
||||
/* TODO: stylesheet table */
|
||||
|
||||
/* FIXME: maybe emit something smarter for the generator? */
|
||||
if (!ME_StreamOutPrint(editor, "{\\*\\generator Wine Riched20 2.0.????;}"))
|
||||
if (!ME_StreamOutPrint(pStream, "{\\*\\generator Wine Riched20 2.0.????;}"))
|
||||
return FALSE;
|
||||
|
||||
/* TODO: information group */
|
||||
|
@ -659,7 +677,7 @@ ME_StreamOutRTF(ME_TextEditor *editor, int nStart, int nChars, int dwFormat)
|
|||
|
||||
/* TODO: section formatting properties */
|
||||
|
||||
if (!ME_StreamOutRTFParaProps(editor, ME_GetParagraph(p)))
|
||||
if (!ME_StreamOutRTFParaProps(pStream, ME_GetParagraph(p)))
|
||||
return FALSE;
|
||||
|
||||
while(1)
|
||||
|
@ -667,8 +685,9 @@ ME_StreamOutRTF(ME_TextEditor *editor, int nStart, int nChars, int dwFormat)
|
|||
switch(p->type)
|
||||
{
|
||||
case diParagraph:
|
||||
if (!ME_StreamOutRTFParaProps(editor, p))
|
||||
if (!ME_StreamOutRTFParaProps(pStream, p))
|
||||
return FALSE;
|
||||
pPara = p;
|
||||
break;
|
||||
case diRun:
|
||||
if (p == pEnd && !nEndLen)
|
||||
|
@ -677,26 +696,35 @@ ME_StreamOutRTF(ME_TextEditor *editor, int nStart, int nChars, int dwFormat)
|
|||
/* TODO: emit embedded objects */
|
||||
if (p->member.run.nFlags & MERF_GRAPHICS)
|
||||
FIXME("embedded objects are not handled\n");
|
||||
if (p->member.run.nFlags & MERF_ENDPARA) {
|
||||
if (!ME_StreamOutPrint(editor, "\r\n\\par"))
|
||||
if (p->member.run.nFlags & MERF_CELL) {
|
||||
if (!ME_StreamOutPrint(pStream, "\\cell "))
|
||||
return FALSE;
|
||||
nChars--;
|
||||
} else if (p->member.run.nFlags & MERF_ENDPARA) {
|
||||
if (pPara->member.para.bTable) {
|
||||
if (!ME_StreamOutPrint(pStream, "\\row \r\n"))
|
||||
return FALSE;
|
||||
} else {
|
||||
if (!ME_StreamOutPrint(pStream, "\r\n\\par"))
|
||||
return FALSE;
|
||||
}
|
||||
nChars--;
|
||||
if (editor->bEmulateVersion10 && nChars)
|
||||
nChars--;
|
||||
} else {
|
||||
int nEnd;
|
||||
|
||||
if (!ME_StreamOutPrint(editor, "{"))
|
||||
if (!ME_StreamOutPrint(pStream, "{"))
|
||||
return FALSE;
|
||||
TRACE("style %p\n", p->member.run.style);
|
||||
if (!ME_StreamOutRTFCharProps(editor, &p->member.run.style->fmt))
|
||||
if (!ME_StreamOutRTFCharProps(pStream, &p->member.run.style->fmt))
|
||||
return FALSE;
|
||||
|
||||
nEnd = (p == pEnd) ? nEndLen : ME_StrLen(p->member.run.strText);
|
||||
if (!ME_StreamOutRTFText(editor, p->member.run.strText->szData + nOffset, nEnd - nOffset))
|
||||
if (!ME_StreamOutRTFText(pStream, p->member.run.strText->szData + nOffset, nEnd - nOffset))
|
||||
return FALSE;
|
||||
nOffset = 0;
|
||||
if (!ME_StreamOutPrint(editor, "}"))
|
||||
if (!ME_StreamOutPrint(pStream, "}"))
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
@ -707,14 +735,14 @@ ME_StreamOutRTF(ME_TextEditor *editor, int nStart, int nChars, int dwFormat)
|
|||
break;
|
||||
p = ME_FindItemFwd(p, diRunOrParagraphOrEnd);
|
||||
}
|
||||
if (!ME_StreamOutPrint(editor, "}"))
|
||||
if (!ME_StreamOutPrint(pStream, "}"))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutText(ME_TextEditor *editor, int nStart, int nChars, DWORD dwFormat)
|
||||
ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nChars, DWORD dwFormat)
|
||||
{
|
||||
/* FIXME: use ME_RunOfsFromCharOfs */
|
||||
ME_DisplayItem *item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart);
|
||||
|
@ -741,12 +769,12 @@ ME_StreamOutText(ME_TextEditor *editor, int nStart, int nChars, DWORD dwFormat)
|
|||
static const WCHAR szEOL[2] = { '\r', '\n' };
|
||||
|
||||
if (dwFormat & SF_UNICODE)
|
||||
success = ME_StreamOutMove(editor, (const char *)szEOL, sizeof(szEOL));
|
||||
success = ME_StreamOutMove(pStream, (const char *)szEOL, sizeof(szEOL));
|
||||
else
|
||||
success = ME_StreamOutMove(editor, "\r\n", 2);
|
||||
success = ME_StreamOutMove(pStream, "\r\n", 2);
|
||||
} else {
|
||||
if (dwFormat & SF_UNICODE)
|
||||
success = ME_StreamOutMove(editor, (const char *)(item->member.run.strText->szData + nStart),
|
||||
success = ME_StreamOutMove(pStream, (const char *)(item->member.run.strText->szData + nStart),
|
||||
sizeof(WCHAR) * nLen);
|
||||
else {
|
||||
int nSize;
|
||||
|
@ -754,14 +782,13 @@ ME_StreamOutText(ME_TextEditor *editor, int nStart, int nChars, DWORD dwFormat)
|
|||
nSize = WideCharToMultiByte(nCodePage, 0, item->member.run.strText->szData + nStart,
|
||||
nLen, NULL, 0, NULL, NULL);
|
||||
if (nSize > nBufLen) {
|
||||
if (buffer)
|
||||
FREE_OBJ(buffer);
|
||||
FREE_OBJ(buffer);
|
||||
buffer = ALLOC_N_OBJ(char, nSize);
|
||||
nBufLen = nSize;
|
||||
}
|
||||
WideCharToMultiByte(nCodePage, 0, item->member.run.strText->szData + nStart,
|
||||
nLen, buffer, nSize, NULL, NULL);
|
||||
success = ME_StreamOutMove(editor, buffer, nSize);
|
||||
success = ME_StreamOutMove(pStream, buffer, nSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -772,25 +799,16 @@ ME_StreamOutText(ME_TextEditor *editor, int nStart, int nChars, DWORD dwFormat)
|
|||
item = ME_FindItemFwd(item, diRun);
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
FREE_OBJ(buffer);
|
||||
FREE_OBJ(buffer);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
LRESULT
|
||||
ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream)
|
||||
ME_StreamOutRange(ME_TextEditor *editor, DWORD dwFormat, int nStart, int nTo, EDITSTREAM *stream)
|
||||
{
|
||||
int nStart, nTo;
|
||||
|
||||
ME_StreamOutInit(editor, stream);
|
||||
ME_OutStream *pStream = ME_StreamOutInit(editor, stream);
|
||||
|
||||
if (dwFormat & SFF_SELECTION)
|
||||
ME_GetSelection(editor, &nStart, &nTo);
|
||||
else {
|
||||
nStart = 0;
|
||||
nTo = -1;
|
||||
}
|
||||
if (nTo == -1)
|
||||
{
|
||||
nTo = ME_GetTextLength(editor);
|
||||
|
@ -799,12 +817,26 @@ ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream)
|
|||
nTo++;
|
||||
}
|
||||
TRACE("from %d to %d\n", nStart, nTo);
|
||||
|
||||
|
||||
if (dwFormat & SF_RTF)
|
||||
ME_StreamOutRTF(editor, nStart, nTo - nStart, dwFormat);
|
||||
ME_StreamOutRTF(editor, pStream, nStart, nTo - nStart, dwFormat);
|
||||
else if (dwFormat & SF_TEXT || dwFormat & SF_TEXTIZED)
|
||||
ME_StreamOutText(editor, nStart, nTo - nStart, dwFormat);
|
||||
if (!editor->pStream->stream->dwError)
|
||||
ME_StreamOutFlush(editor);
|
||||
return ME_StreamOutFree(editor);
|
||||
ME_StreamOutText(editor, pStream, nStart, nTo - nStart, dwFormat);
|
||||
if (!pStream->stream->dwError)
|
||||
ME_StreamOutFlush(pStream);
|
||||
return ME_StreamOutFree(pStream);
|
||||
}
|
||||
|
||||
LRESULT
|
||||
ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream)
|
||||
{
|
||||
int nStart, nTo;
|
||||
|
||||
if (dwFormat & SFF_SELECTION)
|
||||
ME_GetSelection(editor, &nStart, &nTo);
|
||||
else {
|
||||
nStart = 0;
|
||||
nTo = -1;
|
||||
}
|
||||
return ME_StreamOutRange(editor, dwFormat, nStart, nTo, stream);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue