mirror of
https://github.com/reactos/reactos.git
synced 2025-04-29 10:39:07 +00:00
sync riched20 with wine 1.1.14
svn path=/trunk/; revision=39224
This commit is contained in:
parent
804d0d56f0
commit
5bb24c753a
23 changed files with 1492 additions and 806 deletions
|
@ -151,8 +151,13 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
|
|||
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_CursorFromCharOfs(editor, from, &editor->pCursors[1]);
|
||||
ME_CursorFromCharOfs(editor, to, &editor->pCursors[0]);
|
||||
/* Selection is not allowed in the middle of an end paragraph run. */
|
||||
if (editor->pCursors[1].pRun->member.run.nFlags & MERF_ENDPARA)
|
||||
editor->pCursors[1].nOffset = 0;
|
||||
if (editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA)
|
||||
editor->pCursors[0].nOffset = 0;
|
||||
return to;
|
||||
}
|
||||
|
||||
|
@ -173,7 +178,7 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
|
|||
ME_DisplayItem *row = ME_FindItemBack(pCursorRun, diStartRowOrParagraph);
|
||||
|
||||
if (row) {
|
||||
HDC hDC = GetDC(editor->hWnd);
|
||||
HDC hDC = ITextHost_TxGetDC(editor->texthost);
|
||||
ME_Context c;
|
||||
ME_DisplayItem *run = pCursorRun;
|
||||
ME_DisplayItem *para = NULL;
|
||||
|
@ -217,7 +222,7 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
|
|||
*x = c.rcView.left + run->member.run.pt.x + sz.cx - editor->horz_si.nPos;
|
||||
*y = c.rcView.top + para->member.para.pt.y + row->member.row.nBaseline
|
||||
+ run->member.run.pt.y - pSizeRun->member.run.nAscent - editor->vert_si.nPos;
|
||||
ME_DestroyContext(&c, editor->hWnd);
|
||||
ME_DestroyContext(&c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -238,8 +243,8 @@ ME_MoveCaret(ME_TextEditor *editor)
|
|||
if(editor->bHaveFocus && !ME_IsSelection(editor))
|
||||
{
|
||||
x = min(x, editor->rcFormat.right-1);
|
||||
CreateCaret(editor->hWnd, NULL, 0, height);
|
||||
SetCaretPos(x, y);
|
||||
ITextHost_TxCreateCaret(editor->texthost, NULL, 0, height);
|
||||
ITextHost_TxSetCaretPos(editor->texthost, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,14 +253,14 @@ void ME_ShowCaret(ME_TextEditor *ed)
|
|||
{
|
||||
ME_MoveCaret(ed);
|
||||
if(ed->bHaveFocus && !ME_IsSelection(ed))
|
||||
ShowCaret(ed->hWnd);
|
||||
ITextHost_TxShowCaret(ed->texthost, TRUE);
|
||||
}
|
||||
|
||||
void ME_HideCaret(ME_TextEditor *ed)
|
||||
{
|
||||
if(!ed->bHaveFocus || ME_IsSelection(ed))
|
||||
{
|
||||
HideCaret(ed->hWnd);
|
||||
ITextHost_TxShowCaret(ed->texthost, FALSE);
|
||||
DestroyCaret();
|
||||
}
|
||||
}
|
||||
|
@ -298,14 +303,11 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
|
|||
/* We aren't deleting anything in this run, so we will go back to the
|
||||
* last run we are deleting text in. */
|
||||
c.pRun = ME_FindItemBack(c.pRun, diRun);
|
||||
if (c.pRun->member.run.nFlags & MERF_ENDPARA)
|
||||
c.nOffset = c.pRun->member.run.nCR + c.pRun->member.run.nLF;
|
||||
else
|
||||
c.nOffset = c.pRun->member.run.strText->nLen;
|
||||
c.nOffset = c.pRun->member.run.strText->nLen;
|
||||
}
|
||||
run = &c.pRun->member.run;
|
||||
if (run->nFlags & MERF_ENDPARA) {
|
||||
int eollen = run->nCR + run->nLF;
|
||||
int eollen = c.pRun->member.run.strText->nLen;
|
||||
BOOL keepFirstParaFormat;
|
||||
|
||||
if (!ME_FindItemFwd(c.pRun, diParagraph))
|
||||
|
@ -517,107 +519,72 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
|||
if(editor->nTextLimit < oldLen +len)
|
||||
editor->nTextLimit = oldLen + len;
|
||||
|
||||
pos = str;
|
||||
|
||||
while (len)
|
||||
{
|
||||
pos = str;
|
||||
/* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */
|
||||
while(pos-str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
|
||||
while(pos - str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
|
||||
pos++;
|
||||
if (pos-str < len && *pos == '\t') { /* handle tabs */
|
||||
|
||||
if (pos != str) { /* handle text */
|
||||
ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
|
||||
} else if (*pos == '\t') { /* handle tabs */
|
||||
WCHAR tab = '\t';
|
||||
|
||||
if (pos!=str)
|
||||
ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
|
||||
|
||||
ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB);
|
||||
|
||||
pos++;
|
||||
if(pos-str <= len) {
|
||||
len -= pos - str;
|
||||
str = pos;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* handle special \r\r\n sequence (richedit 2.x and higher only) */
|
||||
if (!editor->bEmulateVersion10 && pos-str < len-2 && pos[0] == '\r' && pos[1] == '\r' && pos[2] == '\n') {
|
||||
WCHAR space = ' ';
|
||||
|
||||
if (pos!=str)
|
||||
ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
|
||||
|
||||
ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, style, 0);
|
||||
|
||||
pos+=3;
|
||||
if(pos-str <= len) {
|
||||
len -= pos - str;
|
||||
str = pos;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (pos-str < len) { /* handle EOLs */
|
||||
} else { /* handle EOLs */
|
||||
ME_DisplayItem *tp, *end_run;
|
||||
ME_Style *tmp_style;
|
||||
int numCR, numLF;
|
||||
int eol_len = 0;
|
||||
|
||||
if (pos!=str)
|
||||
ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
|
||||
p = &editor->pCursors[nCursor];
|
||||
if (p->nOffset) {
|
||||
ME_SplitRunSimple(editor, p->pRun, p->nOffset);
|
||||
p = &editor->pCursors[nCursor];
|
||||
}
|
||||
tmp_style = ME_GetInsertStyle(editor, nCursor);
|
||||
/* ME_SplitParagraph increases style refcount */
|
||||
|
||||
/* Encode and fill number of CR and LF according to emulation mode */
|
||||
if (editor->bEmulateVersion10) {
|
||||
const WCHAR * tpos;
|
||||
|
||||
/* We have to find out how many consecutive \r are there, and if there
|
||||
is a \n terminating the run of \r's. */
|
||||
numCR = 0; numLF = 0;
|
||||
tpos = pos;
|
||||
while (tpos-str < len && *tpos == '\r') {
|
||||
tpos++;
|
||||
numCR++;
|
||||
}
|
||||
if (tpos-str >= len) {
|
||||
/* Reached end of text without finding anything but '\r' */
|
||||
if (tpos != pos) {
|
||||
pos++;
|
||||
}
|
||||
numCR = 1; numLF = 0;
|
||||
} else if (*tpos == '\n') {
|
||||
/* The entire run of \r's plus the one \n is one single line break */
|
||||
pos = tpos + 1;
|
||||
numLF = 1;
|
||||
} else {
|
||||
/* Found some other content past the run of \r's */
|
||||
pos++;
|
||||
numCR = 1; numLF = 0;
|
||||
}
|
||||
/* Find number of CR and LF in end of paragraph run */
|
||||
if (*pos =='\r')
|
||||
{
|
||||
if (len > 1 && pos[1] == '\n')
|
||||
eol_len = 2;
|
||||
else if (len > 2 && pos[1] == '\r' && pos[2] == '\n')
|
||||
eol_len = 3;
|
||||
else
|
||||
eol_len = 1;
|
||||
} else {
|
||||
if(pos-str < len && *pos =='\r')
|
||||
pos++;
|
||||
if(pos-str < len && *pos =='\n')
|
||||
pos++;
|
||||
numCR = 1; numLF = 0;
|
||||
assert(*pos == '\n');
|
||||
eol_len = 1;
|
||||
}
|
||||
tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, numCR, numLF, 0);
|
||||
p->pRun = ME_FindItemFwd(tp, diRun);
|
||||
end_run = ME_FindItemBack(tp, diRun);
|
||||
ME_ReleaseStyle(end_run->member.run.style);
|
||||
end_run->member.run.style = tmp_style;
|
||||
p->nOffset = 0;
|
||||
pos += eol_len;
|
||||
|
||||
if(pos-str <= len) {
|
||||
len -= pos - str;
|
||||
str = pos;
|
||||
continue;
|
||||
if (!editor->bEmulateVersion10 && eol_len == 3)
|
||||
{
|
||||
/* handle special \r\r\n sequence (richedit 2.x and higher only) */
|
||||
WCHAR space = ' ';
|
||||
ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, style, 0);
|
||||
} else {
|
||||
ME_String *eol_str;
|
||||
|
||||
if (!editor->bEmulateVersion10) {
|
||||
WCHAR cr = '\r';
|
||||
eol_str = ME_MakeStringN(&cr, 1);
|
||||
} else {
|
||||
eol_str = ME_MakeStringN(str, eol_len);
|
||||
}
|
||||
|
||||
p = &editor->pCursors[nCursor];
|
||||
if (p->nOffset) {
|
||||
ME_SplitRunSimple(editor, p->pRun, p->nOffset);
|
||||
p = &editor->pCursors[nCursor];
|
||||
}
|
||||
tmp_style = ME_GetInsertStyle(editor, nCursor);
|
||||
/* ME_SplitParagraph increases style refcount */
|
||||
tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, eol_str, 0);
|
||||
p->pRun = ME_FindItemFwd(tp, diRun);
|
||||
end_run = ME_FindItemBack(tp, diRun);
|
||||
ME_ReleaseStyle(end_run->member.run.style);
|
||||
end_run->member.run.style = tmp_style;
|
||||
p->nOffset = 0;
|
||||
}
|
||||
}
|
||||
ME_InternalInsertTextFromCursor(editor, nCursor, str, len, style, 0);
|
||||
len = 0;
|
||||
len -= pos - str;
|
||||
str = pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1020,7 +987,7 @@ int ME_CharFromPos(ME_TextEditor *editor, int x, int y, BOOL *isExact)
|
|||
RECT rc;
|
||||
BOOL bResult;
|
||||
|
||||
GetClientRect(editor->hWnd, &rc);
|
||||
ITextHost_TxGetClientRect(editor->texthost, &rc);
|
||||
if (x < 0 || y < 0 || x >= rc.right || y >= rc.bottom) {
|
||||
if (isExact) *isExact = FALSE;
|
||||
return -1;
|
||||
|
@ -1154,7 +1121,7 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
|
|||
}
|
||||
}
|
||||
ME_InvalidateSelection(editor);
|
||||
HideCaret(editor->hWnd);
|
||||
ITextHost_TxShowCaret(editor->texthost, FALSE);
|
||||
ME_ShowCaret(editor);
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_SendSelChange(editor);
|
||||
|
@ -1188,7 +1155,7 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y)
|
|||
}
|
||||
|
||||
ME_InvalidateSelection(editor);
|
||||
HideCaret(editor->hWnd);
|
||||
ITextHost_TxShowCaret(editor->texthost, FALSE);
|
||||
ME_ShowCaret(editor);
|
||||
ME_SendSelChange(editor);
|
||||
}
|
||||
|
@ -1574,7 +1541,7 @@ void ME_SendSelChange(ME_TextEditor *editor)
|
|||
ME_ClearTempStyle(editor);
|
||||
|
||||
editor->notified_cr = sc.chrg;
|
||||
SendMessageW(GetParent(editor->hWnd), WM_NOTIFY, sc.nmhdr.idFrom, (LPARAM)&sc);
|
||||
ITextHost_TxNotify(editor->texthost, sc.nmhdr.code, &sc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1636,7 +1603,7 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
|
|||
|
||||
ME_InvalidateSelection(editor);
|
||||
ME_Repaint(editor);
|
||||
HideCaret(editor->hWnd);
|
||||
ITextHost_TxShowCaret(editor->texthost, FALSE);
|
||||
ME_EnsureVisible(editor, &tmp_curs);
|
||||
ME_ShowCaret(editor);
|
||||
ME_SendSelChange(editor);
|
||||
|
|
|
@ -54,7 +54,7 @@ static HRESULT WINAPI EnumFormatImpl_QueryInterface(IEnumFORMATETC *iface, REFII
|
|||
|
||||
if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumFORMATETC)) {
|
||||
IEnumFORMATETC_AddRef(iface);
|
||||
*ppvObj = (LPVOID)This;
|
||||
*ppvObj = This;
|
||||
return S_OK;
|
||||
}
|
||||
*ppvObj = NULL;
|
||||
|
@ -170,7 +170,7 @@ static HRESULT WINAPI DataObjectImpl_QueryInterface(IDataObject *iface, REFIID r
|
|||
|
||||
if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDataObject)) {
|
||||
IDataObject_AddRef(iface);
|
||||
*ppvObj = (LPVOID)This;
|
||||
*ppvObj = This;
|
||||
return S_OK;
|
||||
}
|
||||
*ppvObj = NULL;
|
||||
|
|
|
@ -29,12 +29,16 @@ void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC)
|
|||
c->pt.y = 0;
|
||||
c->hbrMargin = CreateSolidBrush(RGB(224,224,224));
|
||||
c->rcView = editor->rcFormat;
|
||||
c->dpi.cx = GetDeviceCaps(hDC, LOGPIXELSX);
|
||||
c->dpi.cy = GetDeviceCaps(hDC, LOGPIXELSY);
|
||||
if (hDC) {
|
||||
c->dpi.cx = GetDeviceCaps(hDC, LOGPIXELSX);
|
||||
c->dpi.cy = GetDeviceCaps(hDC, LOGPIXELSY);
|
||||
} else {
|
||||
c->dpi.cx = c->dpi.cy = 96;
|
||||
}
|
||||
}
|
||||
|
||||
void ME_DestroyContext(ME_Context *c, HWND hWnd)
|
||||
void ME_DestroyContext(ME_Context *c)
|
||||
{
|
||||
if (hWnd) ReleaseDC(hWnd, c->hDC);
|
||||
if (c->hDC) ITextHost_TxReleaseDC(c->editor->texthost, c->hDC);
|
||||
DeleteObject(c->hbrMargin);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -71,7 +71,6 @@ void ME_DumpStyleToBuf(CHARFORMAT2W *pFmt, char buf[2048]);
|
|||
void ME_DumpStyle(ME_Style *s);
|
||||
CHARFORMAT2W *ME_ToCF2W(CHARFORMAT2W *to, CHARFORMAT2W *from);
|
||||
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, const CHARFORMAT2W *pSrc); /* only works with 2W structs */
|
||||
void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt); /* ditto */
|
||||
|
@ -89,7 +88,6 @@ void ME_DumpDocument(ME_TextBuffer *buffer);
|
|||
const char *ME_GetDITypeName(ME_DIType type);
|
||||
|
||||
/* string.c */
|
||||
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);
|
||||
|
@ -205,7 +203,7 @@ ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor);
|
|||
|
||||
/* context.c */
|
||||
void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC);
|
||||
void ME_DestroyContext(ME_Context *c, HWND release);
|
||||
void ME_DestroyContext(ME_Context *c);
|
||||
|
||||
/* wrap.c */
|
||||
BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor);
|
||||
|
@ -216,7 +214,7 @@ void ME_SendRequestResize(ME_TextEditor *editor, BOOL force);
|
|||
ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run);
|
||||
void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end);
|
||||
void ME_MakeFirstParagraph(ME_TextEditor *editor);
|
||||
ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style, int numCR, int numLF, int paraFlags);
|
||||
ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style, ME_String *eol_str, int paraFlags);
|
||||
ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
|
||||
BOOL keepFirstParaFormat);
|
||||
void ME_DumpParaStyle(ME_Paragraph *s);
|
||||
|
@ -235,7 +233,6 @@ void ME_RewrapRepaint(ME_TextEditor *editor);
|
|||
void ME_UpdateRepaint(ME_TextEditor *editor);
|
||||
void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor);
|
||||
void ME_InvalidateSelection(ME_TextEditor *editor);
|
||||
void ME_QueueInvalidateFromCursor(ME_TextEditor *editor, int nCursor);
|
||||
BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator);
|
||||
int ME_twips2pointsX(ME_Context *c, int x);
|
||||
int ME_twips2pointsY(ME_Context *c, int y);
|
||||
|
@ -263,9 +260,11 @@ void ME_CopyReObject(REOBJECT* dst, const REOBJECT* src);
|
|||
void ME_DeleteReObject(REOBJECT* reo);
|
||||
|
||||
/* editor.c */
|
||||
ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10);
|
||||
LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam, BOOL unicode, HRESULT* phresult);
|
||||
void ME_SendOldNotify(ME_TextEditor *editor, int nCode);
|
||||
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_RTFCharAttrHook(struct _RTF_Info *info);
|
||||
void ME_RTFParAttrHook(struct _RTF_Info *info);
|
||||
void ME_RTFTblAttrHook(struct _RTF_Info *info);
|
||||
|
@ -291,6 +290,54 @@ void ME_MoveCursorFromTableRowStartParagraph(ME_TextEditor *editor);
|
|||
struct RTFTable *ME_MakeTableDef(ME_TextEditor *editor);
|
||||
void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef);
|
||||
|
||||
/* txthost.c */
|
||||
ITextHost *ME_CreateTextHost(HWND hwnd, BOOL bEmulateVersion10);
|
||||
#ifdef __i386__ /* Use wrappers to perform thiscall on i386 */
|
||||
#define TXTHOST_VTABLE(This) (&itextHostStdcallVtbl)
|
||||
#else /* __i386__ */
|
||||
#define TXTHOST_VTABLE(This) (This)->lpVtbl
|
||||
#endif /* __i386__ */
|
||||
/*** ITextHost methods ***/
|
||||
#define ITextHost_TxGetDC(This) TXTHOST_VTABLE(This)->TxGetDC(This)
|
||||
#define ITextHost_TxReleaseDC(This,a) TXTHOST_VTABLE(This)->TxReleaseDC(This,a)
|
||||
#define ITextHost_TxShowScrollBar(This,a,b) TXTHOST_VTABLE(This)->TxShowScrollBar(This,a,b)
|
||||
#define ITextHost_TxEnableScrollBar(This,a,b) TXTHOST_VTABLE(This)->TxEnableScrollBar(This,a,b)
|
||||
#define ITextHost_TxSetScrollRange(This,a,b,c,d) TXTHOST_VTABLE(This)->TxSetScrollRange(This,a,b,c,d)
|
||||
#define ITextHost_TxSetScrollPos(This,a,b,c) TXTHOST_VTABLE(This)->TxSetScrollPos(This,a,b,c)
|
||||
#define ITextHost_TxInvalidateRect(This,a,b) TXTHOST_VTABLE(This)->TxInvalidateRect(This,a,b)
|
||||
#define ITextHost_TxViewChange(This,a) TXTHOST_VTABLE(This)->TxViewChange(This,a)
|
||||
#define ITextHost_TxCreateCaret(This,a,b,c) TXTHOST_VTABLE(This)->TxCreateCaret(This,a,b,c)
|
||||
#define ITextHost_TxShowCaret(This,a) TXTHOST_VTABLE(This)->TxShowCaret(This,a)
|
||||
#define ITextHost_TxSetCaretPos(This,a,b) TXTHOST_VTABLE(This)->TxSetCaretPos(This,a,b)
|
||||
#define ITextHost_TxSetTimer(This,a,b) TXTHOST_VTABLE(This)->TxSetTimer(This,a,b)
|
||||
#define ITextHost_TxKillTimer(This,a) TXTHOST_VTABLE(This)->TxKillTimer(This,a)
|
||||
#define ITextHost_TxScrollWindowEx(This,a,b,c,d,e,f,g) TXTHOST_VTABLE(This)->TxScrollWindowEx(This,a,b,c,d,e,f,g)
|
||||
#define ITextHost_TxSetCapture(This,a) TXTHOST_VTABLE(This)->TxSetCapture(This,a)
|
||||
#define ITextHost_TxSetFocus(This) TXTHOST_VTABLE(This)->TxSetFocus(This)
|
||||
#define ITextHost_TxSetCursor(This,a,b) TXTHOST_VTABLE(This)->TxSetCursor(This,a,b)
|
||||
#define ITextHost_TxScreenToClient(This,a) TXTHOST_VTABLE(This)->TxScreenToClient(This,a)
|
||||
#define ITextHost_TxClientToScreen(This,a) TXTHOST_VTABLE(This)->TxClientToScreen(This,a)
|
||||
#define ITextHost_TxActivate(This,a) TXTHOST_VTABLE(This)->TxActivate(This,a)
|
||||
#define ITextHost_TxDeactivate(This,a) TXTHOST_VTABLE(This)->TxDeactivate(This,a)
|
||||
#define ITextHost_TxGetClientRect(This,a) TXTHOST_VTABLE(This)->TxGetClientRect(This,a)
|
||||
#define ITextHost_TxGetViewInset(This,a) TXTHOST_VTABLE(This)->TxGetViewInset(This,a)
|
||||
#define ITextHost_TxGetCharFormat(This,a) TXTHOST_VTABLE(This)->TxGetCharFormat(This,a)
|
||||
#define ITextHost_TxGetParaFormat(This,a) TXTHOST_VTABLE(This)->TxGetParaFormat(This,a)
|
||||
#define ITextHost_TxGetSysColor(This,a) TXTHOST_VTABLE(This)->TxGetSysColor(This,a)
|
||||
#define ITextHost_TxGetBackStyle(This,a) TXTHOST_VTABLE(This)->TxGetBackStyle(This,a)
|
||||
#define ITextHost_TxGetMaxLength(This,a) TXTHOST_VTABLE(This)->TxGetMaxLength(This,a)
|
||||
#define ITextHost_TxGetScrollBars(This,a) TXTHOST_VTABLE(This)->TxGetScrollBars(This,a)
|
||||
#define ITextHost_TxGetPasswordChar(This,a) TXTHOST_VTABLE(This)->TxGetPasswordChar(This,a)
|
||||
#define ITextHost_TxGetAcceleratorPos(This,a) TXTHOST_VTABLE(This)->TxGetAcceleratorPos(This,a)
|
||||
#define ITextHost_TxGetExtent(This,a) TXTHOST_VTABLE(This)->TxGetExtent(This,a)
|
||||
#define ITextHost_OnTxCharFormatChange(This,a) TXTHOST_VTABLE(This)->OnTxCharFormatChange(This,a)
|
||||
#define ITextHost_OnTxParaFormatChange(This,a) TXTHOST_VTABLE(This)->OnTxParaFormatChange(This,a)
|
||||
#define ITextHost_TxGetPropertyBits(This,a,b) TXTHOST_VTABLE(This)->TxGetPropertyBits(This,a,b)
|
||||
#define ITextHost_TxNotify(This,a,b) TXTHOST_VTABLE(This)->TxNotify(This,a,b)
|
||||
#define ITextHost_TxImmGetContext(This) TXTHOST_VTABLE(This)->TxImmGetContext(This)
|
||||
#define ITextHost_TxImmReleaseContext(This,a) TXTHOST_VTABLE(This)->TxImmReleaseContext(This,a)
|
||||
#define ITextHost_TxGetSelectionBarWidth(This,a) TXTHOST_VTABLE(This)->TxGetSelectionBarWidth(This,a)
|
||||
|
||||
/* undo.c */
|
||||
ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_DisplayItem *pdi);
|
||||
void ME_CommitUndo(ME_TextEditor *editor);
|
||||
|
|
|
@ -44,9 +44,15 @@
|
|||
#include <commctrl.h>
|
||||
#include <ole2.h>
|
||||
#include <richole.h>
|
||||
#include "imm.h"
|
||||
#include <textserv.h>
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
#ifdef __i386__
|
||||
extern struct ITextHostVtbl itextHostStdcallVtbl;
|
||||
#endif /* __i386__ */
|
||||
|
||||
typedef struct tagME_String
|
||||
{
|
||||
WCHAR *szData;
|
||||
|
@ -156,7 +162,6 @@ typedef struct tagME_Run
|
|||
int nAscent, nDescent; /* pixels above/below baseline */
|
||||
POINT pt; /* relative to para's position */
|
||||
REOBJECT *ole_obj; /* FIXME: should be a union with strText (at least) */
|
||||
int nCR; int nLF; /* for MERF_ENDPARA: number of \r and \n characters encoded by run */
|
||||
} ME_Run;
|
||||
|
||||
typedef struct tagME_Document {
|
||||
|
@ -246,7 +251,7 @@ typedef struct tagME_UndoItem
|
|||
{
|
||||
ME_DisplayItem di;
|
||||
int nStart, nLen;
|
||||
int nCR, nLF; /* used by diUndoSplitParagraph */
|
||||
ME_String *eol_str; /* used by diUndoSplitParagraph */
|
||||
} ME_UndoItem;
|
||||
|
||||
typedef struct tagME_TextBuffer
|
||||
|
@ -327,10 +332,12 @@ typedef struct tagME_FontCacheItem
|
|||
typedef struct tagME_TextEditor
|
||||
{
|
||||
HWND hWnd;
|
||||
ITextHost *texthost;
|
||||
BOOL bEmulateVersion10;
|
||||
ME_TextBuffer *pBuffer;
|
||||
ME_Cursor *pCursors;
|
||||
DWORD styleFlags;
|
||||
DWORD exStyleFlags;
|
||||
int nCursors;
|
||||
SIZE sizeWindow;
|
||||
int nTotalLength, nLastTotalLength;
|
||||
|
@ -355,7 +362,6 @@ typedef struct tagME_TextEditor
|
|||
RECT rcFormat;
|
||||
BOOL bDefaultFormatRect;
|
||||
BOOL bWordWrap;
|
||||
int nInvalidOfs;
|
||||
int nTextLimit;
|
||||
EDITWORDBREAKPROCW pfnWordBreak;
|
||||
LPRICHEDITOLECALLBACK lpOleCallback;
|
||||
|
|
|
@ -191,10 +191,8 @@ void ME_DumpDocument(ME_TextBuffer *buffer)
|
|||
TRACE(" - StartRow\n");
|
||||
break;
|
||||
case diRun:
|
||||
TRACE(" - Run(\"%s\", %d)\n", debugstr_w(pItem->member.run.strText->szData),
|
||||
pItem->member.run.nCharOfs);
|
||||
if (pItem->member.run.nFlags & MERF_ENDPARA)
|
||||
TRACE(" - Paragraph end: %d CR, %d LF\n", pItem->member.run.nCR, pItem->member.run.nLF);
|
||||
TRACE(" - Run(\"%s\", %d, flags=%x)\n", debugstr_w(pItem->member.run.strText->szData),
|
||||
pItem->member.run.nCharOfs, pItem->member.run.nFlags);
|
||||
break;
|
||||
case diTextEnd:
|
||||
TRACE("End(ofs=%d)\n", pItem->member.para.nCharOfs);
|
||||
|
|
|
@ -74,15 +74,12 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
|
|||
if (!bOnlyNew || (item->member.para.nFlags & MEPF_REPAINT))
|
||||
{
|
||||
/* Draw the pargraph if any of the paragraph is in the update region. */
|
||||
BOOL bPaint = (rcUpdate == NULL);
|
||||
if (rcUpdate)
|
||||
bPaint = ys < rcUpdate->bottom && ye > rcUpdate->top;
|
||||
if (bPaint)
|
||||
if (ys < rcUpdate->bottom && ye > rcUpdate->top)
|
||||
{
|
||||
ME_DrawParagraph(&c, item);
|
||||
/* Clear the repaint flag if the whole paragraph is in the
|
||||
* update region. */
|
||||
if (!rcUpdate || (rcUpdate->top <= ys && rcUpdate->bottom >= ye))
|
||||
if (rcUpdate->top <= ys && rcUpdate->bottom >= ye)
|
||||
item->member.para.nFlags &= ~MEPF_REPAINT;
|
||||
}
|
||||
}
|
||||
|
@ -116,11 +113,13 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
|
|||
ME_SendRequestResize(editor, FALSE);
|
||||
editor->nLastTotalLength = editor->nTotalLength;
|
||||
editor->nLastTotalWidth = editor->nTotalWidth;
|
||||
ME_DestroyContext(&c, NULL);
|
||||
|
||||
SelectClipRgn(hDC, oldRgn);
|
||||
if (oldRgn)
|
||||
DeleteObject(oldRgn);
|
||||
|
||||
c.hDC = NULL;
|
||||
ME_DestroyContext(&c);
|
||||
}
|
||||
|
||||
void ME_Repaint(ME_TextEditor *editor)
|
||||
|
@ -130,11 +129,9 @@ void ME_Repaint(ME_TextEditor *editor)
|
|||
ME_UpdateScrollBar(editor);
|
||||
FIXME("ME_Repaint had to call ME_WrapMarkedParagraphs\n");
|
||||
}
|
||||
if (!IsWindowVisible(editor->hWnd))
|
||||
return;
|
||||
if (!editor->bEmulateVersion10 || (editor->nEventMask & ENM_UPDATE))
|
||||
ME_SendOldNotify(editor, EN_UPDATE);
|
||||
UpdateWindow(editor->hWnd);
|
||||
ITextHost_TxViewChange(editor->texthost, TRUE);
|
||||
}
|
||||
|
||||
void ME_UpdateRepaint(ME_TextEditor *editor)
|
||||
|
@ -232,7 +229,8 @@ static void ME_HighlightSpace(ME_Context *c, int x, int y, LPCWSTR szText,
|
|||
rect.top = ymin;
|
||||
rect.right = x + selWidth;
|
||||
rect.bottom = ymin + cy;
|
||||
hBrush = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
|
||||
hBrush = CreateSolidBrush(ITextHost_TxGetSysColor(c->editor->texthost,
|
||||
COLOR_HIGHLIGHT));
|
||||
FillRect(hDC, &rect, hBrush);
|
||||
DeleteObject(hBrush);
|
||||
}
|
||||
|
@ -274,7 +272,7 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText,
|
|||
if ((s->fmt.dwMask & CFM_LINK) && (s->fmt.dwEffects & CFE_LINK))
|
||||
rgb = RGB(0,0,255);
|
||||
else if ((s->fmt.dwMask & CFM_COLOR) && (s->fmt.dwEffects & CFE_AUTOCOLOR))
|
||||
rgb = GetSysColor(COLOR_WINDOWTEXT);
|
||||
rgb = ITextHost_TxGetSysColor(c->editor->texthost, COLOR_WINDOWTEXT);
|
||||
else
|
||||
rgb = s->fmt.crTextColor;
|
||||
|
||||
|
@ -351,8 +349,10 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText,
|
|||
dim.bottom = ymin + cy;
|
||||
dim.left = xSelStart;
|
||||
dim.right = xSelEnd;
|
||||
SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
||||
rgbBackOld = SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT));
|
||||
SetTextColor(hDC, ITextHost_TxGetSysColor(c->editor->texthost,
|
||||
COLOR_HIGHLIGHTTEXT));
|
||||
rgbBackOld = SetBkColor(hDC, ITextHost_TxGetSysColor(c->editor->texthost,
|
||||
COLOR_HIGHLIGHT));
|
||||
ExtTextOutW(hDC, xSelStart, y-yOffset, ETO_OPAQUE, &dim,
|
||||
szText+nSelFrom, nSelTo-nSelFrom, lpDx);
|
||||
if (hPen)
|
||||
|
@ -418,7 +418,6 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa
|
|||
ME_GetSelection(c->editor, &nSelFrom, &nSelTo);
|
||||
|
||||
/* Draw selected end-of-paragraph mark */
|
||||
/* you can always comment it out if you need visible paragraph marks */
|
||||
if (run->nFlags & MERF_ENDPARA)
|
||||
{
|
||||
if (runofs >= nSelFrom && runofs < nSelTo)
|
||||
|
@ -625,7 +624,8 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
|
|||
POINT pt;
|
||||
|
||||
if (para->pFmt->wBorders & 64) /* autocolor */
|
||||
pencr = GetSysColor(COLOR_WINDOWTEXT);
|
||||
pencr = ITextHost_TxGetSysColor(c->editor->texthost,
|
||||
COLOR_WINDOWTEXT);
|
||||
else
|
||||
pencr = pen_colors[(para->pFmt->wBorders >> 12) & 0xF];
|
||||
|
||||
|
@ -1032,14 +1032,13 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
|
|||
|
||||
void ME_ScrollAbs(ME_TextEditor *editor, int x, int y)
|
||||
{
|
||||
LONG winStyle;
|
||||
BOOL bScrollBarIsVisible, bScrollBarWillBeVisible;
|
||||
int scrollX = 0, scrollY = 0;
|
||||
|
||||
if (editor->horz_si.nPos != x) {
|
||||
x = min(x, editor->horz_si.nMax);
|
||||
x = max(x, editor->horz_si.nMin);
|
||||
SetScrollPos(editor->hWnd, SB_HORZ, x, TRUE);
|
||||
ITextHost_TxSetScrollPos(editor->texthost, SB_HORZ, x, TRUE);
|
||||
scrollX = editor->horz_si.nPos - x;
|
||||
editor->horz_si.nPos = x;
|
||||
}
|
||||
|
@ -1047,32 +1046,39 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y)
|
|||
if (editor->vert_si.nPos != y) {
|
||||
y = min(y, editor->vert_si.nMax - (int)editor->vert_si.nPage);
|
||||
y = max(y, editor->vert_si.nMin);
|
||||
SetScrollPos(editor->hWnd, SB_VERT, y, TRUE);
|
||||
ITextHost_TxSetScrollPos(editor->texthost, SB_VERT, y, TRUE);
|
||||
scrollY = editor->vert_si.nPos - y;
|
||||
editor->vert_si.nPos = y;
|
||||
}
|
||||
|
||||
if (abs(scrollX) > editor->sizeWindow.cx ||
|
||||
abs(scrollY) > editor->sizeWindow.cy)
|
||||
InvalidateRect(editor->hWnd, NULL, TRUE);
|
||||
ITextHost_TxInvalidateRect(editor->texthost, NULL, TRUE);
|
||||
else
|
||||
ScrollWindowEx(editor->hWnd, scrollX, scrollY, &editor->rcFormat,
|
||||
&editor->rcFormat, NULL, NULL, SW_INVALIDATE);
|
||||
ITextHost_TxScrollWindowEx(editor->texthost, scrollX, scrollY,
|
||||
&editor->rcFormat, &editor->rcFormat,
|
||||
NULL, NULL, SW_INVALIDATE);
|
||||
ME_Repaint(editor);
|
||||
|
||||
winStyle = GetWindowLongW(editor->hWnd, GWL_STYLE);
|
||||
bScrollBarIsVisible = (winStyle & WS_HSCROLL) != 0;
|
||||
bScrollBarWillBeVisible = (editor->nTotalWidth > editor->sizeWindow.cx)
|
||||
|| (editor->styleFlags & ES_DISABLENOSCROLL);
|
||||
if (bScrollBarIsVisible != bScrollBarWillBeVisible)
|
||||
ShowScrollBar(editor->hWnd, SB_HORZ, bScrollBarWillBeVisible);
|
||||
|
||||
bScrollBarIsVisible = (winStyle & WS_VSCROLL) != 0;
|
||||
bScrollBarWillBeVisible = (editor->nTotalLength > editor->sizeWindow.cy)
|
||||
|| (editor->styleFlags & ES_DISABLENOSCROLL);
|
||||
if (bScrollBarIsVisible != bScrollBarWillBeVisible)
|
||||
ShowScrollBar(editor->hWnd, SB_VERT, bScrollBarWillBeVisible);
|
||||
if (editor->hWnd)
|
||||
{
|
||||
LONG winStyle = GetWindowLongW(editor->hWnd, GWL_STYLE);
|
||||
bScrollBarIsVisible = (winStyle & WS_HSCROLL) != 0;
|
||||
bScrollBarWillBeVisible = (editor->nTotalWidth > editor->sizeWindow.cx
|
||||
&& (editor->styleFlags & WS_HSCROLL))
|
||||
|| (editor->styleFlags & ES_DISABLENOSCROLL);
|
||||
if (bScrollBarIsVisible != bScrollBarWillBeVisible)
|
||||
ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ,
|
||||
bScrollBarWillBeVisible);
|
||||
|
||||
bScrollBarIsVisible = (winStyle & WS_VSCROLL) != 0;
|
||||
bScrollBarWillBeVisible = (editor->nTotalLength > editor->sizeWindow.cy
|
||||
&& (editor->styleFlags & WS_VSCROLL))
|
||||
|| (editor->styleFlags & ES_DISABLENOSCROLL);
|
||||
if (bScrollBarIsVisible != bScrollBarWillBeVisible)
|
||||
ITextHost_TxShowScrollBar(editor->texthost, SB_VERT,
|
||||
bScrollBarWillBeVisible);
|
||||
}
|
||||
ME_UpdateScrollBar(editor);
|
||||
}
|
||||
|
||||
|
@ -1146,15 +1152,27 @@ void ME_UpdateScrollBar(ME_TextEditor *editor)
|
|||
editor->horz_si.nMin = si.nMin;
|
||||
editor->horz_si.nMax = si.nMax;
|
||||
editor->horz_si.nPage = si.nPage;
|
||||
if (bScrollBarWillBeVisible || bScrollBarWasVisible)
|
||||
SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE);
|
||||
if (bScrollBarWillBeVisible || bScrollBarWasVisible) {
|
||||
if (editor->hWnd) {
|
||||
SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE);
|
||||
} else {
|
||||
ITextHost_TxSetScrollRange(editor->texthost, SB_HORZ, si.nMin, si.nMax, FALSE);
|
||||
ITextHost_TxSetScrollPos(editor->texthost, SB_HORZ, si.nPos, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (si.fMask & SIF_DISABLENOSCROLL)
|
||||
if (si.fMask & SIF_DISABLENOSCROLL) {
|
||||
bScrollBarWillBeVisible = TRUE;
|
||||
} else if (!(editor->styleFlags & WS_HSCROLL)) {
|
||||
/* SetScrollInfo or SetScrollRange may cause the scrollbar to be
|
||||
* shown, so hide the scrollbar if necessary. */
|
||||
bScrollBarWasVisible = bScrollBarWillBeVisible;
|
||||
bScrollBarWillBeVisible = FALSE;
|
||||
}
|
||||
|
||||
if (bScrollBarWasVisible != bScrollBarWillBeVisible)
|
||||
ShowScrollBar(editor->hWnd, SB_HORZ, bScrollBarWillBeVisible);
|
||||
ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ, bScrollBarWillBeVisible);
|
||||
|
||||
/* Update vertical scrollbar */
|
||||
bScrollBarWasVisible = editor->vert_si.nMax > editor->vert_si.nPage;
|
||||
|
@ -1180,15 +1198,28 @@ void ME_UpdateScrollBar(ME_TextEditor *editor)
|
|||
editor->vert_si.nMin = si.nMin;
|
||||
editor->vert_si.nMax = si.nMax;
|
||||
editor->vert_si.nPage = si.nPage;
|
||||
if (bScrollBarWillBeVisible || bScrollBarWasVisible)
|
||||
SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE);
|
||||
if (bScrollBarWillBeVisible || bScrollBarWasVisible) {
|
||||
if (editor->hWnd) {
|
||||
SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE);
|
||||
} else {
|
||||
ITextHost_TxSetScrollRange(editor->texthost, SB_VERT, si.nMin, si.nMax, FALSE);
|
||||
ITextHost_TxSetScrollPos(editor->texthost, SB_VERT, si.nPos, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (si.fMask & SIF_DISABLENOSCROLL)
|
||||
if (si.fMask & SIF_DISABLENOSCROLL) {
|
||||
bScrollBarWillBeVisible = TRUE;
|
||||
} else if (!(editor->styleFlags & WS_VSCROLL)) {
|
||||
/* SetScrollInfo or SetScrollRange may cause the scrollbar to be
|
||||
* shown, so hide the scrollbar if necessary. */
|
||||
bScrollBarWasVisible = bScrollBarWillBeVisible;
|
||||
bScrollBarWillBeVisible = FALSE;
|
||||
}
|
||||
|
||||
if (bScrollBarWasVisible != bScrollBarWillBeVisible)
|
||||
ShowScrollBar(editor->hWnd, SB_VERT, bScrollBarWillBeVisible);
|
||||
ITextHost_TxShowScrollBar(editor->texthost, SB_VERT,
|
||||
bScrollBarWillBeVisible);
|
||||
}
|
||||
|
||||
void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor)
|
||||
|
@ -1219,24 +1250,6 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor)
|
|||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -1285,13 +1298,6 @@ ME_InvalidateSelection(ME_TextEditor *editor)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||
|
||||
static const WCHAR wszParagraphSign[] = {0xB6, 0};
|
||||
|
||||
void ME_MakeFirstParagraph(ME_TextEditor *editor)
|
||||
{
|
||||
ME_Context c;
|
||||
|
@ -35,8 +33,10 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
|
|||
ME_DisplayItem *para = ME_MakeDI(diParagraph);
|
||||
ME_DisplayItem *run;
|
||||
ME_Style *style;
|
||||
ME_String *eol_str;
|
||||
WCHAR cr_lf[] = {'\r','\n',0};
|
||||
|
||||
ME_InitContext(&c, editor, GetDC(editor->hWnd));
|
||||
ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
|
||||
|
||||
hf = GetStockObject(SYSTEM_FONT);
|
||||
assert(hf);
|
||||
|
@ -63,11 +63,10 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
|
|||
|
||||
style = ME_MakeStyle(&cf);
|
||||
text->pDefaultStyle = style;
|
||||
|
||||
run = ME_MakeRun(style, ME_MakeString(wszParagraphSign), MERF_ENDPARA);
|
||||
|
||||
eol_str = ME_MakeStringN(cr_lf, editor->bEmulateVersion10 ? 2 : 1);
|
||||
run = ME_MakeRun(style, eol_str, MERF_ENDPARA);
|
||||
run->member.run.nCharOfs = 0;
|
||||
run->member.run.nCR = 1;
|
||||
run->member.run.nLF = editor->bEmulateVersion10 ? 1 : 0;
|
||||
|
||||
ME_InsertBefore(text->pLast, para);
|
||||
ME_InsertBefore(text->pLast, run);
|
||||
|
@ -78,7 +77,7 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
|
|||
|
||||
text->pLast->member.para.nCharOfs = editor->bEmulateVersion10 ? 2 : 1;
|
||||
|
||||
ME_DestroyContext(&c, editor->hWnd);
|
||||
ME_DestroyContext(&c);
|
||||
}
|
||||
|
||||
static void ME_MarkForWrapping(ME_TextEditor *editor, ME_DisplayItem *first, const ME_DisplayItem *last)
|
||||
|
@ -201,7 +200,7 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const
|
|||
|
||||
/* split paragraph at the beginning of the run */
|
||||
ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
|
||||
ME_Style *style, int numCR, int numLF,
|
||||
ME_Style *style, ME_String *eol_str,
|
||||
int paraFlags)
|
||||
{
|
||||
ME_DisplayItem *next_para = NULL;
|
||||
|
@ -211,8 +210,8 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
|
|||
ME_UndoItem *undo = NULL;
|
||||
int ofs;
|
||||
ME_DisplayItem *pp;
|
||||
int end_len = numCR + numLF;
|
||||
int run_flags = MERF_ENDPARA;
|
||||
|
||||
if (!editor->bEmulateVersion10) { /* v4.1 */
|
||||
/* At most 1 of MEPF_CELL, MEPF_ROWSTART, or MEPF_ROWEND should be set. */
|
||||
assert(!(paraFlags & ~(MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND)));
|
||||
|
@ -224,12 +223,9 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
|
|||
} else { /* v1.0 - v3.0 */
|
||||
assert(!(paraFlags & (MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND)));
|
||||
}
|
||||
end_run = ME_MakeRun(style,ME_MakeString(wszParagraphSign), run_flags);
|
||||
|
||||
assert(run->type == diRun);
|
||||
end_run = ME_MakeRun(style, eol_str, run_flags);
|
||||
|
||||
end_run->member.run.nCR = numCR;
|
||||
end_run->member.run.nLF = numLF;
|
||||
assert(run->type == diRun);
|
||||
run_para = ME_GetParagraph(run);
|
||||
assert(run_para->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
|
||||
|
||||
|
@ -248,7 +244,7 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
|
|||
pp = ME_FindItemFwd(pp, diRunOrParagraphOrEnd);
|
||||
}
|
||||
new_para->member.para.nCharOfs = ME_GetParagraph(run)->member.para.nCharOfs+ofs;
|
||||
new_para->member.para.nCharOfs += end_len;
|
||||
new_para->member.para.nCharOfs += eol_str->nLen;
|
||||
new_para->member.para.nFlags = MEPF_REWRAP;
|
||||
|
||||
/* FIXME initialize format style and call ME_SetParaFormat blah blah */
|
||||
|
@ -315,7 +311,7 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
|
|||
new_para->member.para.prev_para->member.para.nFlags |= MEPF_REWRAP;
|
||||
|
||||
/* we've added the end run, so we need to modify nCharOfs in the next paragraphs */
|
||||
ME_PropagateCharOffset(next_para, end_len);
|
||||
ME_PropagateCharOffset(next_para, eol_str->nLen);
|
||||
editor->nParagraphs++;
|
||||
|
||||
return new_para;
|
||||
|
@ -344,7 +340,7 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
|
|||
assert(pRun->type == diRun);
|
||||
assert(pRun->member.run.nFlags & MERF_ENDPARA);
|
||||
|
||||
end_len = pRun->member.run.nCR + pRun->member.run.nLF;
|
||||
end_len = pRun->member.run.strText->nLen;
|
||||
|
||||
{
|
||||
/* null char format operation to store the original char format for the ENDPARA run */
|
||||
|
@ -356,8 +352,8 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
|
|||
if (undo)
|
||||
{
|
||||
undo->nStart = pNext->member.para.nCharOfs - end_len;
|
||||
undo->nCR = pRun->member.run.nCR;
|
||||
undo->nLF = pRun->member.run.nLF;
|
||||
undo->eol_str = pRun->member.run.strText;
|
||||
pRun->member.run.strText = NULL; /* Avoid freeing the string */
|
||||
}
|
||||
if (!keepFirstParaFormat)
|
||||
{
|
||||
|
|
|
@ -178,6 +178,33 @@ RTFDestroy(RTF_Info *info)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Callback table manipulation routines
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Install or return a writer callback for a token class
|
||||
*/
|
||||
|
||||
static void RTFSetClassCallback(RTF_Info *info, int class, RTFFuncPtr callback)
|
||||
{
|
||||
if (class >= 0 && class < rtfMaxClass)
|
||||
info->ccb[class] = callback;
|
||||
}
|
||||
|
||||
|
||||
static RTFFuncPtr RTFGetClassCallback(const RTF_Info *info, int class)
|
||||
{
|
||||
if (class >= 0 && class < rtfMaxClass)
|
||||
return info->ccb[class];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the reader. This may be called multiple times,
|
||||
* to read multiple files. The only thing not reset is the input
|
||||
|
@ -192,8 +219,10 @@ void RTFInit(RTF_Info *info)
|
|||
{
|
||||
info->rtfTextBuf = heap_alloc (rtfBufSiz);
|
||||
info->pushedTextBuf = heap_alloc (rtfBufSiz);
|
||||
if (info->rtfTextBuf == NULL || info->pushedTextBuf == NULL)
|
||||
if (info->rtfTextBuf == NULL || info->pushedTextBuf == NULL) {
|
||||
ERR ("Cannot allocate text buffers.\n");
|
||||
return;
|
||||
}
|
||||
info->rtfTextBuf[0] = info->pushedTextBuf[0] = '\0';
|
||||
}
|
||||
|
||||
|
@ -281,33 +310,6 @@ char *RTFGetOutputName(const RTF_Info *info)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Callback table manipulation routines
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Install or return a writer callback for a token class
|
||||
*/
|
||||
|
||||
void RTFSetClassCallback(RTF_Info *info, int class, RTFFuncPtr callback)
|
||||
{
|
||||
if (class >= 0 && class < rtfMaxClass)
|
||||
info->ccb[class] = callback;
|
||||
}
|
||||
|
||||
|
||||
RTFFuncPtr RTFGetClassCallback(const RTF_Info *info, int class)
|
||||
{
|
||||
if (class >= 0 && class < rtfMaxClass)
|
||||
return info->ccb[class];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Install or return a writer callback for a destination type
|
||||
*/
|
||||
|
@ -319,7 +321,7 @@ void RTFSetDestinationCallback(RTF_Info *info, int dest, RTFFuncPtr callback)
|
|||
}
|
||||
|
||||
|
||||
RTFFuncPtr RTFGetDestinationCallback(const RTF_Info *info, int dest)
|
||||
static RTFFuncPtr RTFGetDestinationCallback(const RTF_Info *info, int dest)
|
||||
{
|
||||
if (dest >= 0 && dest < rtfMaxDestination)
|
||||
return info->dcb[dest];
|
||||
|
@ -415,6 +417,22 @@ void RTFReadGroup (RTF_Info *info)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Install or return a token reader hook.
|
||||
*/
|
||||
|
||||
void RTFSetReadHook(RTF_Info *info, RTFFuncPtr f)
|
||||
{
|
||||
info->readHook = f;
|
||||
}
|
||||
|
||||
|
||||
static RTFFuncPtr RTFGetReadHook(const RTF_Info *info)
|
||||
{
|
||||
return (info->readHook);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read one token. Call the read hook if there is one. The
|
||||
* token class is the return value. Returns rtfEOF when there
|
||||
|
@ -446,23 +464,7 @@ int RTFGetToken(RTF_Info *info)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Install or return a token reader hook.
|
||||
*/
|
||||
|
||||
void RTFSetReadHook(RTF_Info *info, RTFFuncPtr f)
|
||||
{
|
||||
info->readHook = f;
|
||||
}
|
||||
|
||||
|
||||
RTFFuncPtr RTFGetReadHook(const RTF_Info *info)
|
||||
{
|
||||
return (info->readHook);
|
||||
}
|
||||
|
||||
|
||||
void RTFUngetToken(RTF_Info *info)
|
||||
static void RTFUngetToken(RTF_Info *info)
|
||||
{
|
||||
if (info->pushedClass >= 0) /* there's already an ungotten token */
|
||||
ERR ("cannot unget two tokens\n");
|
||||
|
@ -797,7 +799,7 @@ static int GetChar(RTF_Info *info)
|
|||
* part of the token text.
|
||||
*/
|
||||
|
||||
void RTFSetToken(RTF_Info *info, int class, int major, int minor, int param, const char *text)
|
||||
static void RTFSetToken(RTF_Info *info, int class, int major, int minor, int param, const char *text)
|
||||
{
|
||||
info->rtfClass = class;
|
||||
info->rtfMajor = major;
|
||||
|
@ -871,8 +873,10 @@ static void ReadFontTbl(RTF_Info *info)
|
|||
break;
|
||||
}
|
||||
fp = New (RTFFont);
|
||||
if (fp == NULL)
|
||||
if (fp == NULL) {
|
||||
ERR ( "%s: cannot allocate font entry\n", fn);
|
||||
break;
|
||||
}
|
||||
|
||||
fp->rtfNextFont = info->fontList;
|
||||
info->fontList = fp;
|
||||
|
@ -992,7 +996,7 @@ static void ReadFontTbl(RTF_Info *info)
|
|||
TRACE("default font codepage %d\n", info->codePage);
|
||||
}
|
||||
}
|
||||
if (fp->rtfFNum == -1)
|
||||
if (!fp || (fp->rtfFNum == -1))
|
||||
ERR( "%s: missing font number\n", fn);
|
||||
/*
|
||||
* Could check other pieces of structure here, too, I suppose.
|
||||
|
@ -1044,8 +1048,10 @@ static void ReadColorTbl(RTF_Info *info)
|
|||
}
|
||||
|
||||
cp = New (RTFColor);
|
||||
if (cp == NULL)
|
||||
if (cp == NULL) {
|
||||
ERR ( "%s: cannot allocate color entry\n", fn);
|
||||
break;
|
||||
}
|
||||
cp->rtfCNum = cnum++;
|
||||
cp->rtfCRed = cp->rtfCGreen = cp->rtfCBlue = -1;
|
||||
cp->rtfNextColor = info->colorList;
|
||||
|
@ -1090,8 +1096,10 @@ static void ReadStyleSheet(RTF_Info *info)
|
|||
if (RTFCheckCM (info, rtfGroup, rtfEndGroup))
|
||||
break;
|
||||
sp = New (RTFStyle);
|
||||
if (sp == NULL)
|
||||
if (sp == NULL) {
|
||||
ERR ( "%s: cannot allocate stylesheet entry\n", fn);
|
||||
break;
|
||||
}
|
||||
sp->rtfSName = NULL;
|
||||
sp->rtfSNum = -1;
|
||||
sp->rtfSType = rtfParStyle;
|
||||
|
@ -1269,7 +1277,7 @@ static void ReadObjGroup(RTF_Info *info)
|
|||
*/
|
||||
|
||||
|
||||
RTFStyle *RTFGetStyle(const RTF_Info *info, int num)
|
||||
static RTFStyle *RTFGetStyle(const RTF_Info *info, int num)
|
||||
{
|
||||
RTFStyle *s;
|
||||
|
||||
|
@ -2719,7 +2727,7 @@ RTFFlushCPOutputBuffer(RTF_Info *info)
|
|||
info->dwCPOutputCount = 0;
|
||||
|
||||
RTFPutUnicodeString(info, buffer, length);
|
||||
heap_free((char *)buffer);
|
||||
heap_free(buffer);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<file>string.c</file>
|
||||
<file>style.c</file>
|
||||
<file>table.c</file>
|
||||
<file>txthost.c</file>
|
||||
<file>txtsrv.c</file>
|
||||
<file>undo.c</file>
|
||||
<file>wrap.c</file>
|
||||
|
@ -30,6 +31,7 @@
|
|||
<library>wine</library>
|
||||
<library>uuid</library>
|
||||
<library>ole32</library>
|
||||
<library>oleaut32</library>
|
||||
<library>imm32</library>
|
||||
<library>user32</library>
|
||||
<library>gdi32</library>
|
||||
|
|
|
@ -348,7 +348,7 @@ IRichEditOle_fnGetObjectCount(IRichEditOle *me)
|
|||
{
|
||||
IRichEditOleImpl *This = impl_from_IRichEditOle(me);
|
||||
FIXME("stub %p\n",This);
|
||||
return E_NOTIMPL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
|
@ -1694,7 +1694,7 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj)
|
|||
return 0;
|
||||
}
|
||||
TRACE("Created %p\n",reo);
|
||||
*ppObj = (LPVOID) reo;
|
||||
*ppObj = reo;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1195,17 +1195,11 @@ void RTFSetInputName (RTF_Info *, const char *);
|
|||
char *RTFGetInputName (const RTF_Info *);
|
||||
void RTFSetOutputName (RTF_Info *, const char *);
|
||||
char *RTFGetOutputName (const RTF_Info *);
|
||||
void RTFSetClassCallback (RTF_Info *, int, RTFFuncPtr);
|
||||
RTFFuncPtr RTFGetClassCallback (const RTF_Info *, int);
|
||||
void RTFSetDestinationCallback (RTF_Info *, int, RTFFuncPtr);
|
||||
RTFFuncPtr RTFGetDestinationCallback (const RTF_Info *, int);
|
||||
void RTFRead (RTF_Info *);
|
||||
int RTFGetToken (RTF_Info *); /* writer should rarely need this */
|
||||
void RTFUngetToken (RTF_Info *);
|
||||
int RTFPeekToken (RTF_Info *);
|
||||
void RTFSetToken (RTF_Info *, int, int, int, int, const char *);
|
||||
void RTFSetReadHook (RTF_Info *, RTFFuncPtr);
|
||||
RTFFuncPtr RTFGetReadHook (const RTF_Info *);
|
||||
void RTFRouteToken (RTF_Info *);
|
||||
void RTFSkipGroup (RTF_Info *);
|
||||
void RTFReadGroup (RTF_Info *);
|
||||
|
@ -1215,7 +1209,6 @@ int RTFCheckCMM (const RTF_Info *, int, int, int);
|
|||
int RTFCheckMM (const RTF_Info *, int, int);
|
||||
RTFFont *RTFGetFont (const RTF_Info *, int);
|
||||
RTFColor *RTFGetColor (const RTF_Info *, int);
|
||||
RTFStyle *RTFGetStyle (const RTF_Info *, int);
|
||||
int RTFCharToHex ( char);
|
||||
int RTFHexToChar ( int );
|
||||
|
||||
|
|
|
@ -127,12 +127,8 @@ void ME_CheckCharOffsets(ME_TextEditor *editor)
|
|||
p->member.run.nFlags,
|
||||
p->member.run.style->fmt.dwMask & p->member.run.style->fmt.dwEffects);
|
||||
assert(ofs == p->member.run.nCharOfs);
|
||||
if (p->member.run.nFlags & MERF_ENDPARA) {
|
||||
assert(p->member.run.nCR + p->member.run.nLF > 0);
|
||||
ofs += p->member.run.nCR + p->member.run.nLF;
|
||||
}
|
||||
else
|
||||
ofs += ME_StrLen(p->member.run.strText);
|
||||
assert(p->member.run.strText->nLen);
|
||||
ofs += p->member.run.strText->nLen;
|
||||
break;
|
||||
case diCell:
|
||||
TRACE_(richedit_check)("cell\n");
|
||||
|
@ -166,11 +162,11 @@ int ME_CharOfsFromRunOfs(ME_TextEditor *editor, ME_DisplayItem *pRun, int 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).
|
||||
*/
|
||||
* run).
|
||||
*/
|
||||
void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor)
|
||||
{
|
||||
ME_RunOfsFromCharOfs(editor, nCharOfs, &pCursor->pRun, &pCursor->nOffset);
|
||||
|
@ -178,57 +174,42 @@ void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCurso
|
|||
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*/
|
||||
* Kind of a "global to local" offset conversion.
|
||||
*/
|
||||
void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **ppRun, int *pOfs)
|
||||
{
|
||||
ME_DisplayItem *pPara;
|
||||
int nParaOfs;
|
||||
ME_DisplayItem *item, *next_item;
|
||||
|
||||
pPara = editor->pBuffer->pFirst->member.para.next_para;
|
||||
assert(pPara);
|
||||
assert(ppRun);
|
||||
assert(pOfs);
|
||||
while (pPara->type == diParagraph)
|
||||
{
|
||||
nParaOfs = pPara->member.para.nCharOfs;
|
||||
assert(nCharOfs >= nParaOfs);
|
||||
|
||||
if (nCharOfs < pPara->member.para.next_para->member.para.nCharOfs)
|
||||
{
|
||||
int eollen = 1;
|
||||
*ppRun = ME_FindItemFwd(pPara, diRun);
|
||||
assert(*ppRun);
|
||||
while (!((*ppRun)->member.run.nFlags & MERF_ENDPARA))
|
||||
{
|
||||
ME_DisplayItem *pNext = ME_FindItemFwd(*ppRun, diRun);
|
||||
assert(pNext);
|
||||
assert(pNext->type == diRun);
|
||||
if (nCharOfs < nParaOfs + pNext->member.run.nCharOfs) {
|
||||
*pOfs = ME_PosToVPos((*ppRun)->member.run.strText,
|
||||
nCharOfs - nParaOfs - (*ppRun)->member.run.nCharOfs);
|
||||
return;
|
||||
}
|
||||
*ppRun = pNext;
|
||||
}
|
||||
/* Recover proper character length of this line break */
|
||||
eollen = (*ppRun)->member.run.nCR + (*ppRun)->member.run.nLF;
|
||||
if (nCharOfs >= nParaOfs + (*ppRun)->member.run.nCharOfs &&
|
||||
nCharOfs < nParaOfs + (*ppRun)->member.run.nCharOfs + eollen) {
|
||||
/* FIXME: Might cause problems when actually requiring an offset in the
|
||||
middle of a run that is considered a single line break */
|
||||
*pOfs = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
pPara = pPara->member.para.next_para;
|
||||
}
|
||||
*ppRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
|
||||
*pOfs = 0;
|
||||
assert((*ppRun)->member.run.nFlags & MERF_ENDPARA);
|
||||
nCharOfs = max(nCharOfs, 0);
|
||||
nCharOfs = min(nCharOfs, ME_GetTextLength(editor));
|
||||
|
||||
/* Find the paragraph at the offset. */
|
||||
next_item = editor->pBuffer->pFirst->member.para.next_para;
|
||||
do {
|
||||
item = next_item;
|
||||
next_item = item->member.para.next_para;
|
||||
} while (next_item->member.para.nCharOfs <= nCharOfs);
|
||||
assert(item->type == diParagraph);
|
||||
nCharOfs -= item->member.para.nCharOfs;
|
||||
|
||||
/* Find the run at the offset. */
|
||||
next_item = ME_FindItemFwd(item, diRun);
|
||||
do {
|
||||
item = next_item;
|
||||
next_item = ME_FindItemFwd(item, diRunOrParagraphOrEnd);
|
||||
} while (next_item->type == diRun &&
|
||||
next_item->member.run.nCharOfs <= nCharOfs);
|
||||
assert(item->type == diRun);
|
||||
nCharOfs -= item->member.run.nCharOfs;
|
||||
|
||||
*ppRun = item;
|
||||
*pOfs = nCharOfs;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -550,12 +531,12 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
|
|||
return 0;
|
||||
return 1;
|
||||
}
|
||||
ME_InitContext(&c, editor, GetDC(editor->hWnd));
|
||||
ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
|
||||
if (run->nFlags & MERF_GRAPHICS)
|
||||
{
|
||||
SIZE sz;
|
||||
ME_GetOLEObjectSize(&c, run, &sz);
|
||||
ME_DestroyContext(&c, editor->hWnd);
|
||||
ME_DestroyContext(&c);
|
||||
if (cx < sz.cx/2)
|
||||
return 0;
|
||||
return 1;
|
||||
|
@ -584,7 +565,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
|
|||
ME_DestroyString(strRunText);
|
||||
|
||||
ME_UnselectStyleFont(&c, run->style, hOldFont);
|
||||
ME_DestroyContext(&c, editor->hWnd);
|
||||
ME_DestroyContext(&c);
|
||||
return fit;
|
||||
}
|
||||
|
||||
|
@ -614,22 +595,24 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset)
|
|||
ME_String *strRunText;
|
||||
/* This could point to either the run's real text, or it's masked form in a password control */
|
||||
|
||||
ME_InitContext(&c, editor, GetDC(editor->hWnd));
|
||||
ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
|
||||
if (pRun->nFlags & MERF_GRAPHICS)
|
||||
{
|
||||
if (nOffset)
|
||||
ME_GetOLEObjectSize(&c, pRun, &size);
|
||||
ReleaseDC(editor->hWnd, c.hDC);
|
||||
ITextHost_TxReleaseDC(editor->texthost, c.hDC);
|
||||
return nOffset != 0;
|
||||
} else if (pRun->nFlags & MERF_ENDPARA) {
|
||||
nOffset = 0;
|
||||
}
|
||||
|
||||
if (editor->cPasswordMask)
|
||||
|
||||
if (editor->cPasswordMask)
|
||||
strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(pRun->strText));
|
||||
else
|
||||
strRunText = pRun->strText;
|
||||
|
||||
ME_GetTextExtent(&c, strRunText->szData, nOffset, pRun->style, &size);
|
||||
ReleaseDC(editor->hWnd, c.hDC);
|
||||
ITextHost_TxReleaseDC(editor->texthost, c.hDC);
|
||||
if (editor->cPasswordMask)
|
||||
ME_DestroyString(strRunText);
|
||||
return size.cx;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||
|
||||
int ME_GetOptimalBuffer(int nLen)
|
||||
static int ME_GetOptimalBuffer(int nLen)
|
||||
{
|
||||
return ((2*nLen+1)+128)&~63;
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ ME_String *ME_StrDup(const ME_String *s)
|
|||
|
||||
void ME_DestroyString(ME_String *s)
|
||||
{
|
||||
if (!s) return;
|
||||
FREE_OBJ(s->szData);
|
||||
FREE_OBJ(s);
|
||||
}
|
||||
|
@ -356,12 +357,12 @@ LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz)
|
|||
assert(psz != NULL);
|
||||
|
||||
if (unicode)
|
||||
return (LPWSTR)psz;
|
||||
return psz;
|
||||
else {
|
||||
WCHAR *tmp;
|
||||
int nChars = MultiByteToWideChar(CP_ACP, 0, (char *)psz, -1, NULL, 0);
|
||||
int nChars = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
|
||||
if((tmp = ALLOC_N_OBJ(WCHAR, nChars)) != NULL)
|
||||
MultiByteToWideChar(CP_ACP, 0, (char *)psz, -1, tmp, nChars);
|
||||
MultiByteToWideChar(CP_ACP, 0, psz, -1, tmp, nChars);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ void ME_CopyToCF2W(CHARFORMAT2W *to, CHARFORMAT2W *from)
|
|||
*to = *from;
|
||||
}
|
||||
|
||||
CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from)
|
||||
static CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from)
|
||||
{
|
||||
assert(from->cbSize == sizeof(CHARFORMAT2W));
|
||||
if (to->cbSize == sizeof(CHARFORMATA))
|
||||
|
@ -373,7 +373,6 @@ HFONT ME_SelectStyleFont(ME_Context *c, ME_Style *s)
|
|||
LOGFONTW lf;
|
||||
int i, nEmpty, nAge = 0x7FFFFFFF;
|
||||
ME_FontCacheItem *item;
|
||||
assert(c->hDC);
|
||||
assert(s);
|
||||
|
||||
ME_LogFontFromStyle(c, &lf, s);
|
||||
|
@ -426,7 +425,6 @@ void ME_UnselectStyleFont(ME_Context *c, ME_Style *s, HFONT hOldFont)
|
|||
{
|
||||
int i;
|
||||
|
||||
assert(c->hDC);
|
||||
assert(s);
|
||||
SelectObject(c->hDC, hOldFont);
|
||||
for (i=0; i<HFONT_CACHE_SIZE; i++)
|
||||
|
|
|
@ -58,8 +58,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit_lists);
|
|||
|
||||
static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor,
|
||||
int nCursor,
|
||||
int numCR,
|
||||
int numLF,
|
||||
ME_String *eol_str,
|
||||
int paraFlags)
|
||||
{
|
||||
ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor);
|
||||
|
@ -70,7 +69,7 @@ static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor,
|
|||
cursor = &editor->pCursors[nCursor];
|
||||
}
|
||||
|
||||
tp = ME_SplitParagraph(editor, cursor->pRun, pStyle, numCR, numLF, paraFlags);
|
||||
tp = ME_SplitParagraph(editor, cursor->pRun, pStyle, eol_str, paraFlags);
|
||||
cursor->pRun = ME_FindItemFwd(tp, diRun);
|
||||
return tp;
|
||||
}
|
||||
|
@ -78,7 +77,9 @@ static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor,
|
|||
ME_DisplayItem* ME_InsertTableRowStartFromCursor(ME_TextEditor *editor)
|
||||
{
|
||||
ME_DisplayItem *para;
|
||||
para = ME_InsertEndParaFromCursor(editor, 0, 1, 1, MEPF_ROWSTART);
|
||||
WCHAR cr_lf[] = {'\r', '\n', 0};
|
||||
ME_String *eol_str = ME_MakeStringN(cr_lf, 2);
|
||||
para = ME_InsertEndParaFromCursor(editor, 0, eol_str, MEPF_ROWSTART);
|
||||
return para->member.para.prev_para;
|
||||
}
|
||||
|
||||
|
@ -118,14 +119,18 @@ ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor,
|
|||
ME_DisplayItem* ME_InsertTableCellFromCursor(ME_TextEditor *editor)
|
||||
{
|
||||
ME_DisplayItem *para;
|
||||
para = ME_InsertEndParaFromCursor(editor, 0, 1, 0, MEPF_CELL);
|
||||
WCHAR cr = '\r';
|
||||
ME_String *eol_str = ME_MakeStringN(&cr, 1);
|
||||
para = ME_InsertEndParaFromCursor(editor, 0, eol_str, MEPF_CELL);
|
||||
return para;
|
||||
}
|
||||
|
||||
ME_DisplayItem* ME_InsertTableRowEndFromCursor(ME_TextEditor *editor)
|
||||
{
|
||||
ME_DisplayItem *para;
|
||||
para = ME_InsertEndParaFromCursor(editor, 0, 1, 1, MEPF_ROWEND);
|
||||
WCHAR cr_lf[] = {'\r', '\n', 0};
|
||||
ME_String *eol_str = ME_MakeStringN(cr_lf, 2);
|
||||
para = ME_InsertEndParaFromCursor(editor, 0, eol_str, MEPF_ROWEND);
|
||||
return para->member.para.prev_para;
|
||||
}
|
||||
|
||||
|
@ -283,7 +288,7 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars)
|
|||
- end_para->member.para.nCharOfs;
|
||||
if (remaining)
|
||||
{
|
||||
assert(remaining < c2.pRun->member.run.nCR + c2.pRun->member.run.nLF);
|
||||
assert(remaining < c2.pRun->member.run.strText->nLen);
|
||||
end_para = end_para->member.para.next_para;
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +336,7 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars)
|
|||
{
|
||||
ME_Run *end_run = &ME_FindItemBack(next_para, diRun)->member.run;
|
||||
int nCharsNew = (next_para->member.para.nCharOfs - nOfs
|
||||
- end_run->nCR - end_run->nLF);
|
||||
- end_run->strText->nLen);
|
||||
nCharsNew = max(nCharsNew, 0);
|
||||
assert(nCharsNew <= *nChars);
|
||||
*nChars = nCharsNew;
|
||||
|
@ -581,7 +586,7 @@ void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow)
|
|||
}
|
||||
ME_InvalidateSelection(editor);
|
||||
ME_Repaint(editor);
|
||||
HideCaret(editor->hWnd);
|
||||
ITextHost_TxShowCaret(editor->texthost, FALSE);
|
||||
ME_ShowCaret(editor);
|
||||
ME_SendSelChange(editor);
|
||||
}
|
||||
|
|
727
reactos/dll/win32/riched20/txthost.c
Normal file
727
reactos/dll/win32/riched20/txthost.c
Normal file
|
@ -0,0 +1,727 @@
|
|||
/*
|
||||
* RichEdit - ITextHost implementation for windowed richedit controls
|
||||
*
|
||||
* Copyright 2009 by Dylan Smith
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#define NONAMELESSSTRUCT
|
||||
#define NONAMELESSUNION
|
||||
#define COBJMACROS
|
||||
|
||||
#include "editor.h"
|
||||
#include "ole2.h"
|
||||
#include "richole.h"
|
||||
#include "imm.h"
|
||||
#include "textserv.h"
|
||||
#include "wine/debug.h"
|
||||
#include "editstr.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||
|
||||
typedef struct ITextHostImpl {
|
||||
const ITextHostVtbl *lpVtbl;
|
||||
LONG ref;
|
||||
HWND hWnd;
|
||||
BOOL bEmulateVersion10;
|
||||
} ITextHostImpl;
|
||||
|
||||
static ITextHostVtbl textHostVtbl;
|
||||
|
||||
ITextHost *ME_CreateTextHost(HWND hwnd, BOOL bEmulateVersion10)
|
||||
{
|
||||
ITextHostImpl *texthost;
|
||||
texthost = CoTaskMemAlloc(sizeof(*texthost));
|
||||
if (texthost)
|
||||
{
|
||||
ME_TextEditor *editor;
|
||||
|
||||
texthost->lpVtbl = &textHostVtbl;
|
||||
texthost->ref = 1;
|
||||
texthost->hWnd = hwnd;
|
||||
texthost->bEmulateVersion10 = bEmulateVersion10;
|
||||
|
||||
editor = ME_MakeEditor((ITextHost*)texthost, bEmulateVersion10);
|
||||
editor->exStyleFlags = GetWindowLongW(hwnd, GWL_EXSTYLE);
|
||||
editor->hWnd = hwnd; /* FIXME: Remove editor's dependance on hWnd */
|
||||
SetWindowLongPtrW(hwnd, 0, (LONG_PTR)editor);
|
||||
}
|
||||
|
||||
return (ITextHost*)texthost;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI ITextHostImpl_QueryInterface(ITextHost *iface,
|
||||
REFIID riid,
|
||||
LPVOID *ppvObject)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
|
||||
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ITextHost)) {
|
||||
*ppvObject = This;
|
||||
ITextHost_AddRef((ITextHost *)*ppvObject);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
FIXME("Unknown interface: %s\n", debugstr_guid(riid));
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI ITextHostImpl_AddRef(ITextHost *iface)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
ULONG ref = InterlockedIncrement(&This->ref);
|
||||
return ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI ITextHostImpl_Release(ITextHost *iface)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
ULONG ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
if (!ref)
|
||||
{
|
||||
SetWindowLongPtrW(This->hWnd, 0, 0);
|
||||
CoTaskMemFree(This);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
HDC WINAPI ITextHostImpl_TxGetDC(ITextHost *iface)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
return GetDC(This->hWnd);
|
||||
}
|
||||
|
||||
INT WINAPI ITextHostImpl_TxReleaseDC(ITextHost *iface,
|
||||
HDC hdc)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
return ReleaseDC(This->hWnd, hdc);
|
||||
}
|
||||
|
||||
BOOL WINAPI ITextHostImpl_TxShowScrollBar(ITextHost *iface,
|
||||
INT fnBar,
|
||||
BOOL fShow)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
return ShowScrollBar(This->hWnd, fnBar, fShow);
|
||||
}
|
||||
|
||||
BOOL WINAPI ITextHostImpl_TxEnableScrollBar(ITextHost *iface,
|
||||
INT fuSBFlags,
|
||||
INT fuArrowflags)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
return EnableScrollBar(This->hWnd, fuSBFlags, fuArrowflags);
|
||||
}
|
||||
|
||||
BOOL WINAPI ITextHostImpl_TxSetScrollRange(ITextHost *iface,
|
||||
INT fnBar,
|
||||
LONG nMinPos,
|
||||
INT nMaxPos,
|
||||
BOOL fRedraw)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
return SetScrollRange(This->hWnd, fnBar, nMinPos, nMaxPos, fRedraw);
|
||||
}
|
||||
|
||||
BOOL WINAPI ITextHostImpl_TxSetScrollPos(ITextHost *iface,
|
||||
INT fnBar,
|
||||
INT nPos,
|
||||
BOOL fRedraw)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
int pos = SetScrollPos(This->hWnd, fnBar, nPos, fRedraw);
|
||||
return (pos ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
void WINAPI ITextHostImpl_TxInvalidateRect(ITextHost *iface,
|
||||
LPCRECT prc,
|
||||
BOOL fMode)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
InvalidateRect(This->hWnd, prc, fMode);
|
||||
}
|
||||
|
||||
void WINAPI ITextHostImpl_TxViewChange(ITextHost *iface,
|
||||
BOOL fUpdate)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
if (fUpdate)
|
||||
UpdateWindow(This->hWnd);
|
||||
}
|
||||
|
||||
BOOL WINAPI ITextHostImpl_TxCreateCaret(ITextHost *iface,
|
||||
HBITMAP hbmp,
|
||||
INT xWidth, INT yHeight)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
return CreateCaret(This->hWnd, hbmp, xWidth, yHeight);
|
||||
}
|
||||
|
||||
BOOL WINAPI ITextHostImpl_TxShowCaret(ITextHost *iface, BOOL fShow)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
if (fShow)
|
||||
return ShowCaret(This->hWnd);
|
||||
else
|
||||
return HideCaret(This->hWnd);
|
||||
}
|
||||
|
||||
BOOL WINAPI ITextHostImpl_TxSetCaretPos(ITextHost *iface,
|
||||
INT x, INT y)
|
||||
{
|
||||
return SetCaretPos(x, y);
|
||||
}
|
||||
|
||||
BOOL WINAPI ITextHostImpl_TxSetTimer(ITextHost *iface,
|
||||
UINT idTimer, UINT uTimeout)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
return SetTimer(This->hWnd, idTimer, uTimeout, NULL) != 0;
|
||||
}
|
||||
|
||||
void WINAPI ITextHostImpl_TxKillTimer(ITextHost *iface,
|
||||
UINT idTimer)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
KillTimer(This->hWnd, idTimer);
|
||||
}
|
||||
|
||||
void WINAPI ITextHostImpl_TxScrollWindowEx(ITextHost *iface,
|
||||
INT dx, INT dy,
|
||||
LPCRECT lprcScroll,
|
||||
LPCRECT lprcClip,
|
||||
HRGN hRgnUpdate,
|
||||
LPRECT lprcUpdate,
|
||||
UINT fuScroll)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
ScrollWindowEx(This->hWnd, dx, dy, lprcScroll, lprcClip,
|
||||
hRgnUpdate, lprcUpdate, fuScroll);
|
||||
}
|
||||
|
||||
void WINAPI ITextHostImpl_TxSetCapture(ITextHost *iface,
|
||||
BOOL fCapture)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
if (fCapture)
|
||||
SetCapture(This->hWnd);
|
||||
else
|
||||
ReleaseCapture();
|
||||
}
|
||||
|
||||
void WINAPI ITextHostImpl_TxSetFocus(ITextHost *iface)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
SetFocus(This->hWnd);
|
||||
}
|
||||
|
||||
void WINAPI ITextHostImpl_TxSetCursor(ITextHost *iface,
|
||||
HCURSOR hcur,
|
||||
BOOL fText)
|
||||
{
|
||||
SetCursor(hcur);
|
||||
}
|
||||
|
||||
BOOL WINAPI ITextHostImpl_TxScreenToClient(ITextHost *iface,
|
||||
LPPOINT lppt)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
return ScreenToClient(This->hWnd, lppt);
|
||||
}
|
||||
|
||||
BOOL WINAPI ITextHostImpl_TxClientToScreen(ITextHost *iface,
|
||||
LPPOINT lppt)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
return ClientToScreen(This->hWnd, lppt);
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxActivate(ITextHost *iface,
|
||||
LONG *plOldState)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
*plOldState = (LONG)SetActiveWindow(This->hWnd);
|
||||
return (*plOldState ? S_OK : E_FAIL);
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxDeactivate(ITextHost *iface,
|
||||
LONG lNewState)
|
||||
{
|
||||
HWND ret = SetActiveWindow((HWND)lNewState);
|
||||
return (ret ? S_OK : E_FAIL);
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetClientRect(ITextHost *iface,
|
||||
LPRECT prc)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
int ret = GetClientRect(This->hWnd, prc);
|
||||
return (ret ? S_OK : E_FAIL);
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetViewInset(ITextHost *iface,
|
||||
LPRECT prc)
|
||||
{
|
||||
prc->top = 0;
|
||||
prc->left = 0;
|
||||
prc->bottom = 0;
|
||||
prc->right = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetCharFormat(ITextHost *iface,
|
||||
const CHARFORMATW **ppCF)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetParaFormat(ITextHost *iface,
|
||||
const PARAFORMAT **ppPF)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
COLORREF WINAPI ITextHostImpl_TxGetSysColor(ITextHost *iface,
|
||||
int nIndex)
|
||||
{
|
||||
return GetSysColor(nIndex);
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetBackStyle(ITextHost *iface,
|
||||
TXTBACKSTYLE *pStyle)
|
||||
{
|
||||
*pStyle = TXTBACK_OPAQUE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetMaxLength(ITextHost *iface,
|
||||
DWORD *pLength)
|
||||
{
|
||||
*pLength = INFINITE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetScrollBars(ITextHost *iface,
|
||||
DWORD *pdwScrollBar)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
ME_TextEditor *editor = (ME_TextEditor*)GetWindowLongW(This->hWnd, 0);
|
||||
const DWORD mask = WS_VSCROLL|
|
||||
WS_HSCROLL|
|
||||
ES_AUTOVSCROLL|
|
||||
ES_AUTOHSCROLL|
|
||||
ES_DISABLENOSCROLL;
|
||||
if (editor)
|
||||
{
|
||||
*pdwScrollBar = editor->styleFlags & mask;
|
||||
} else {
|
||||
DWORD style = GetWindowLongW(This->hWnd, GWL_STYLE);
|
||||
if (style & WS_VSCROLL)
|
||||
style |= ES_AUTOVSCROLL;
|
||||
if (!This->bEmulateVersion10 && (style & WS_HSCROLL))
|
||||
style |= ES_AUTOHSCROLL;
|
||||
*pdwScrollBar = style & mask;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetPasswordChar(ITextHost *iface,
|
||||
WCHAR *pch)
|
||||
{
|
||||
*pch = '*';
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetAcceleratorPos(ITextHost *iface,
|
||||
LONG *pch)
|
||||
{
|
||||
*pch = -1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetExtent(ITextHost *iface,
|
||||
LPSIZEL lpExtent)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_OnTxCharFormatChange(ITextHost *iface,
|
||||
const CHARFORMATW *pcf)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_OnTxParaFormatChange(ITextHost *iface,
|
||||
const PARAFORMAT *ppf)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetPropertyBits(ITextHost *iface,
|
||||
DWORD dwMask,
|
||||
DWORD *pdwBits)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongPtrW(This->hWnd, 0);
|
||||
DWORD style;
|
||||
DWORD dwBits = 0;
|
||||
|
||||
if (editor)
|
||||
{
|
||||
style = editor->styleFlags;
|
||||
if (editor->mode & TM_RICHTEXT)
|
||||
dwBits |= TXTBIT_RICHTEXT;
|
||||
if (editor->bWordWrap)
|
||||
dwBits |= TXTBIT_WORDWRAP;
|
||||
if (style & ECO_AUTOWORDSELECTION)
|
||||
dwBits |= TXTBIT_AUTOWORDSEL;
|
||||
} else {
|
||||
DWORD dwScrollBar;
|
||||
|
||||
style = GetWindowLongW(This->hWnd, GWL_STYLE);
|
||||
ITextHostImpl_TxGetScrollBars(iface, &dwScrollBar);
|
||||
|
||||
dwBits |= TXTBIT_RICHTEXT|TXTBIT_AUTOWORDSEL;
|
||||
if (!(dwScrollBar & ES_AUTOHSCROLL))
|
||||
dwBits |= TXTBIT_WORDWRAP;
|
||||
}
|
||||
|
||||
/* Bits that correspond to window styles. */
|
||||
if (style & ES_MULTILINE)
|
||||
dwBits |= TXTBIT_MULTILINE;
|
||||
if (style & ES_READONLY)
|
||||
dwBits |= TXTBIT_READONLY;
|
||||
if (style & ES_PASSWORD)
|
||||
dwBits |= TXTBIT_USEPASSWORD;
|
||||
if (!(style & ES_NOHIDESEL))
|
||||
dwBits |= TXTBIT_HIDESELECTION;
|
||||
if (style & ES_SAVESEL)
|
||||
dwBits |= TXTBIT_SAVESELECTION;
|
||||
if (style & ES_VERTICAL)
|
||||
dwBits |= TXTBIT_VERTICAL;
|
||||
if (style & ES_NOOLEDRAGDROP)
|
||||
dwBits |= TXTBIT_DISABLEDRAG;
|
||||
|
||||
dwBits |= TXTBIT_ALLOWBEEP;
|
||||
|
||||
/* The following bits are always FALSE because they are probably only
|
||||
* needed for ITextServices_OnTxPropertyBitsChange:
|
||||
* TXTBIT_VIEWINSETCHANGE
|
||||
* TXTBIT_BACKSTYLECHANGE
|
||||
* TXTBIT_MAXLENGTHCHANGE
|
||||
* TXTBIT_CHARFORMATCHANGE
|
||||
* TXTBIT_PARAFORMATCHANGE
|
||||
* TXTBIT_SHOWACCELERATOR
|
||||
* TXTBIT_EXTENTCHANGE
|
||||
* TXTBIT_SELBARCHANGE
|
||||
* TXTBIT_SCROLLBARCHANGE
|
||||
* TXTBIT_CLIENTRECTCHANGE
|
||||
*
|
||||
* Documented by MSDN as not supported:
|
||||
* TXTBIT_USECURRENTBKG
|
||||
*/
|
||||
|
||||
*pdwBits = dwBits & dwMask;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxNotify(ITextHost *iface,
|
||||
DWORD iNotify,
|
||||
void *pv)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
HWND hwnd = This->hWnd;
|
||||
HWND parent = GetParent(hwnd);
|
||||
UINT id = GetWindowLongW(hwnd, GWLP_ID);
|
||||
|
||||
/* Note: EN_MSGFILTER is documented as not being sent to TxNotify */
|
||||
|
||||
switch (iNotify)
|
||||
{
|
||||
case EN_DROPFILES:
|
||||
case EN_LINK:
|
||||
case EN_OLEOPFAILED:
|
||||
case EN_PROTECTED:
|
||||
case EN_REQUESTRESIZE:
|
||||
case EN_SAVECLIPBOARD:
|
||||
case EN_SELCHANGE:
|
||||
case EN_STOPNOUNDO:
|
||||
{
|
||||
/* FIXME: Verify this assumption that pv starts with NMHDR. */
|
||||
NMHDR *info = pv;
|
||||
if (!info)
|
||||
return E_FAIL;
|
||||
|
||||
info->hwndFrom = hwnd;
|
||||
info->idFrom = id;
|
||||
info->code = iNotify;
|
||||
SendMessageW(parent, WM_NOTIFY, id, (LPARAM)info);
|
||||
break;
|
||||
}
|
||||
|
||||
case EN_UPDATE:
|
||||
/* Only sent when the window is visible. */
|
||||
if (!IsWindowVisible(This->hWnd))
|
||||
break;
|
||||
/* Fall through */
|
||||
case EN_CHANGE:
|
||||
case EN_ERRSPACE:
|
||||
case EN_HSCROLL:
|
||||
case EN_KILLFOCUS:
|
||||
case EN_MAXTEXT:
|
||||
case EN_SETFOCUS:
|
||||
case EN_VSCROLL:
|
||||
SendMessageW(parent, WM_COMMAND, MAKEWPARAM(id, iNotify), (LPARAM)hwnd);
|
||||
break;
|
||||
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HIMC WINAPI ITextHostImpl_TxImmGetContext(ITextHost *iface)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
return ImmGetContext(This->hWnd);
|
||||
}
|
||||
|
||||
void WINAPI ITextHostImpl_TxImmReleaseContext(ITextHost *iface,
|
||||
HIMC himc)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
ImmReleaseContext(This->hWnd, himc);
|
||||
}
|
||||
|
||||
HRESULT WINAPI ITextHostImpl_TxGetSelectionBarWidth(ITextHost *iface,
|
||||
LONG *lSelBarWidth)
|
||||
{
|
||||
ITextHostImpl *This = (ITextHostImpl *)iface;
|
||||
ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongPtrW(This->hWnd, 0);
|
||||
|
||||
DWORD style = editor ? editor->styleFlags
|
||||
: GetWindowLongW(This->hWnd, GWL_STYLE);
|
||||
*lSelBarWidth = (style & ES_SELECTIONBAR) ? 225 : 0; /* in HIMETRIC */
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
#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__ */
|
||||
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetDC);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxReleaseDC);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowScrollBar);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxEnableScrollBar);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollRange);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollPos);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxInvalidateRect);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxViewChange);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxCreateCaret);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowCaret);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCaretPos);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetTimer);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxKillTimer);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScrollWindowEx);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCapture);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetFocus);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCursor);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScreenToClient);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxClientToScreen);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxActivate);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxDeactivate);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetClientRect);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetViewInset);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetCharFormat);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetParaFormat);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSysColor);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetBackStyle);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetMaxLength);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetScrollBars);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPasswordChar);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetAcceleratorPos);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetExtent);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxCharFormatChange);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxParaFormatChange);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPropertyBits);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxNotify);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmGetContext);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmReleaseContext);
|
||||
DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSelectionBarWidth);
|
||||
|
||||
static ITextHostVtbl textHostVtbl = {
|
||||
ITextHostImpl_QueryInterface,
|
||||
ITextHostImpl_AddRef,
|
||||
ITextHostImpl_Release,
|
||||
THISCALL(ITextHostImpl_TxGetDC),
|
||||
THISCALL(ITextHostImpl_TxReleaseDC),
|
||||
THISCALL(ITextHostImpl_TxShowScrollBar),
|
||||
THISCALL(ITextHostImpl_TxEnableScrollBar),
|
||||
THISCALL(ITextHostImpl_TxSetScrollRange),
|
||||
THISCALL(ITextHostImpl_TxSetScrollPos),
|
||||
THISCALL(ITextHostImpl_TxInvalidateRect),
|
||||
THISCALL(ITextHostImpl_TxViewChange),
|
||||
THISCALL(ITextHostImpl_TxCreateCaret),
|
||||
THISCALL(ITextHostImpl_TxShowCaret),
|
||||
THISCALL(ITextHostImpl_TxSetCaretPos),
|
||||
THISCALL(ITextHostImpl_TxSetTimer),
|
||||
THISCALL(ITextHostImpl_TxKillTimer),
|
||||
THISCALL(ITextHostImpl_TxScrollWindowEx),
|
||||
THISCALL(ITextHostImpl_TxSetCapture),
|
||||
THISCALL(ITextHostImpl_TxSetFocus),
|
||||
THISCALL(ITextHostImpl_TxSetCursor),
|
||||
THISCALL(ITextHostImpl_TxScreenToClient),
|
||||
THISCALL(ITextHostImpl_TxClientToScreen),
|
||||
THISCALL(ITextHostImpl_TxActivate),
|
||||
THISCALL(ITextHostImpl_TxDeactivate),
|
||||
THISCALL(ITextHostImpl_TxGetClientRect),
|
||||
THISCALL(ITextHostImpl_TxGetViewInset),
|
||||
THISCALL(ITextHostImpl_TxGetCharFormat),
|
||||
THISCALL(ITextHostImpl_TxGetParaFormat),
|
||||
THISCALL(ITextHostImpl_TxGetSysColor),
|
||||
THISCALL(ITextHostImpl_TxGetBackStyle),
|
||||
THISCALL(ITextHostImpl_TxGetMaxLength),
|
||||
THISCALL(ITextHostImpl_TxGetScrollBars),
|
||||
THISCALL(ITextHostImpl_TxGetPasswordChar),
|
||||
THISCALL(ITextHostImpl_TxGetAcceleratorPos),
|
||||
THISCALL(ITextHostImpl_TxGetExtent),
|
||||
THISCALL(ITextHostImpl_OnTxCharFormatChange),
|
||||
THISCALL(ITextHostImpl_OnTxParaFormatChange),
|
||||
THISCALL(ITextHostImpl_TxGetPropertyBits),
|
||||
THISCALL(ITextHostImpl_TxNotify),
|
||||
THISCALL(ITextHostImpl_TxImmGetContext),
|
||||
THISCALL(ITextHostImpl_TxImmReleaseContext),
|
||||
THISCALL(ITextHostImpl_TxGetSelectionBarWidth),
|
||||
};
|
||||
|
||||
#ifdef __i386__ /* thiscall functions are i386-specific */
|
||||
|
||||
#define STDCALL(func) __stdcall_ ## func
|
||||
#define DEFINE_STDCALL_WRAPPER(num,func) \
|
||||
extern typeof(func) __stdcall_ ## func; \
|
||||
__ASM_GLOBAL_FUNC(__stdcall_ ## func, \
|
||||
"popl %eax\n\t" \
|
||||
"popl %ecx\n\t" \
|
||||
"pushl %eax\n\t" \
|
||||
"movl (%ecx), %eax\n\t" \
|
||||
"jmp *(4*(" #num "))(%eax)" )
|
||||
|
||||
DEFINE_STDCALL_WRAPPER(3,ITextHostImpl_TxGetDC);
|
||||
DEFINE_STDCALL_WRAPPER(4,ITextHostImpl_TxReleaseDC);
|
||||
DEFINE_STDCALL_WRAPPER(5,ITextHostImpl_TxShowScrollBar);
|
||||
DEFINE_STDCALL_WRAPPER(6,ITextHostImpl_TxEnableScrollBar);
|
||||
DEFINE_STDCALL_WRAPPER(7,ITextHostImpl_TxSetScrollRange);
|
||||
DEFINE_STDCALL_WRAPPER(8,ITextHostImpl_TxSetScrollPos);
|
||||
DEFINE_STDCALL_WRAPPER(9,ITextHostImpl_TxInvalidateRect);
|
||||
DEFINE_STDCALL_WRAPPER(10,ITextHostImpl_TxViewChange);
|
||||
DEFINE_STDCALL_WRAPPER(11,ITextHostImpl_TxCreateCaret);
|
||||
DEFINE_STDCALL_WRAPPER(12,ITextHostImpl_TxShowCaret);
|
||||
DEFINE_STDCALL_WRAPPER(13,ITextHostImpl_TxSetCaretPos);
|
||||
DEFINE_STDCALL_WRAPPER(14,ITextHostImpl_TxSetTimer);
|
||||
DEFINE_STDCALL_WRAPPER(15,ITextHostImpl_TxKillTimer);
|
||||
DEFINE_STDCALL_WRAPPER(16,ITextHostImpl_TxScrollWindowEx);
|
||||
DEFINE_STDCALL_WRAPPER(17,ITextHostImpl_TxSetCapture);
|
||||
DEFINE_STDCALL_WRAPPER(18,ITextHostImpl_TxSetFocus);
|
||||
DEFINE_STDCALL_WRAPPER(19,ITextHostImpl_TxSetCursor);
|
||||
DEFINE_STDCALL_WRAPPER(20,ITextHostImpl_TxScreenToClient);
|
||||
DEFINE_STDCALL_WRAPPER(21,ITextHostImpl_TxClientToScreen);
|
||||
DEFINE_STDCALL_WRAPPER(22,ITextHostImpl_TxActivate);
|
||||
DEFINE_STDCALL_WRAPPER(23,ITextHostImpl_TxDeactivate);
|
||||
DEFINE_STDCALL_WRAPPER(24,ITextHostImpl_TxGetClientRect);
|
||||
DEFINE_STDCALL_WRAPPER(25,ITextHostImpl_TxGetViewInset);
|
||||
DEFINE_STDCALL_WRAPPER(26,ITextHostImpl_TxGetCharFormat);
|
||||
DEFINE_STDCALL_WRAPPER(27,ITextHostImpl_TxGetParaFormat);
|
||||
DEFINE_STDCALL_WRAPPER(28,ITextHostImpl_TxGetSysColor);
|
||||
DEFINE_STDCALL_WRAPPER(29,ITextHostImpl_TxGetBackStyle);
|
||||
DEFINE_STDCALL_WRAPPER(30,ITextHostImpl_TxGetMaxLength);
|
||||
DEFINE_STDCALL_WRAPPER(31,ITextHostImpl_TxGetScrollBars);
|
||||
DEFINE_STDCALL_WRAPPER(32,ITextHostImpl_TxGetPasswordChar);
|
||||
DEFINE_STDCALL_WRAPPER(33,ITextHostImpl_TxGetAcceleratorPos);
|
||||
DEFINE_STDCALL_WRAPPER(34,ITextHostImpl_TxGetExtent);
|
||||
DEFINE_STDCALL_WRAPPER(35,ITextHostImpl_OnTxCharFormatChange);
|
||||
DEFINE_STDCALL_WRAPPER(36,ITextHostImpl_OnTxParaFormatChange);
|
||||
DEFINE_STDCALL_WRAPPER(37,ITextHostImpl_TxGetPropertyBits);
|
||||
DEFINE_STDCALL_WRAPPER(38,ITextHostImpl_TxNotify);
|
||||
DEFINE_STDCALL_WRAPPER(39,ITextHostImpl_TxImmGetContext);
|
||||
DEFINE_STDCALL_WRAPPER(40,ITextHostImpl_TxImmReleaseContext);
|
||||
DEFINE_STDCALL_WRAPPER(41,ITextHostImpl_TxGetSelectionBarWidth);
|
||||
|
||||
ITextHostVtbl itextHostStdcallVtbl = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
__stdcall_ITextHostImpl_TxGetDC,
|
||||
__stdcall_ITextHostImpl_TxReleaseDC,
|
||||
__stdcall_ITextHostImpl_TxShowScrollBar,
|
||||
__stdcall_ITextHostImpl_TxEnableScrollBar,
|
||||
__stdcall_ITextHostImpl_TxSetScrollRange,
|
||||
__stdcall_ITextHostImpl_TxSetScrollPos,
|
||||
__stdcall_ITextHostImpl_TxInvalidateRect,
|
||||
__stdcall_ITextHostImpl_TxViewChange,
|
||||
__stdcall_ITextHostImpl_TxCreateCaret,
|
||||
__stdcall_ITextHostImpl_TxShowCaret,
|
||||
__stdcall_ITextHostImpl_TxSetCaretPos,
|
||||
__stdcall_ITextHostImpl_TxSetTimer,
|
||||
__stdcall_ITextHostImpl_TxKillTimer,
|
||||
__stdcall_ITextHostImpl_TxScrollWindowEx,
|
||||
__stdcall_ITextHostImpl_TxSetCapture,
|
||||
__stdcall_ITextHostImpl_TxSetFocus,
|
||||
__stdcall_ITextHostImpl_TxSetCursor,
|
||||
__stdcall_ITextHostImpl_TxScreenToClient,
|
||||
__stdcall_ITextHostImpl_TxClientToScreen,
|
||||
__stdcall_ITextHostImpl_TxActivate,
|
||||
__stdcall_ITextHostImpl_TxDeactivate,
|
||||
__stdcall_ITextHostImpl_TxGetClientRect,
|
||||
__stdcall_ITextHostImpl_TxGetViewInset,
|
||||
__stdcall_ITextHostImpl_TxGetCharFormat,
|
||||
__stdcall_ITextHostImpl_TxGetParaFormat,
|
||||
__stdcall_ITextHostImpl_TxGetSysColor,
|
||||
__stdcall_ITextHostImpl_TxGetBackStyle,
|
||||
__stdcall_ITextHostImpl_TxGetMaxLength,
|
||||
__stdcall_ITextHostImpl_TxGetScrollBars,
|
||||
__stdcall_ITextHostImpl_TxGetPasswordChar,
|
||||
__stdcall_ITextHostImpl_TxGetAcceleratorPos,
|
||||
__stdcall_ITextHostImpl_TxGetExtent,
|
||||
__stdcall_ITextHostImpl_OnTxCharFormatChange,
|
||||
__stdcall_ITextHostImpl_OnTxParaFormatChange,
|
||||
__stdcall_ITextHostImpl_TxGetPropertyBits,
|
||||
__stdcall_ITextHostImpl_TxNotify,
|
||||
__stdcall_ITextHostImpl_TxImmGetContext,
|
||||
__stdcall_ITextHostImpl_TxImmReleaseContext,
|
||||
__stdcall_ITextHostImpl_TxGetSelectionBarWidth,
|
||||
};
|
||||
|
||||
#endif /* __i386__ */
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "editor.h"
|
||||
#include "ole2.h"
|
||||
#include "oleauto.h"
|
||||
#include "richole.h"
|
||||
#include "imm.h"
|
||||
#include "textserv.h"
|
||||
|
@ -57,6 +58,7 @@ typedef struct ITextServicesImpl {
|
|||
ITextHost *pMyHost;
|
||||
LONG ref;
|
||||
CRITICAL_SECTION csTxtSrv;
|
||||
ME_TextEditor *editor;
|
||||
char spare[256];
|
||||
} ITextServicesImpl;
|
||||
|
||||
|
@ -70,6 +72,7 @@ HRESULT WINAPI CreateTextServices(IUnknown * pUnkOuter,
|
|||
IUnknown **ppUnk)
|
||||
{
|
||||
ITextServicesImpl *ITextImpl;
|
||||
HRESULT hres;
|
||||
TRACE("%p %p --> %p\n", pUnkOuter, pITextHost, ppUnk);
|
||||
if (pITextHost == NULL)
|
||||
return E_POINTER;
|
||||
|
@ -83,6 +86,8 @@ HRESULT WINAPI CreateTextServices(IUnknown * pUnkOuter,
|
|||
ITextHost_AddRef(pITextHost);
|
||||
ITextImpl->pMyHost = pITextHost;
|
||||
ITextImpl->lpVtbl = &textservices_Vtbl;
|
||||
ITextImpl->editor = ME_MakeEditor(pITextHost, FALSE);
|
||||
ME_HandleMessage(ITextImpl->editor, WM_CREATE, 0, 0, TRUE, &hres);
|
||||
|
||||
if (pUnkOuter)
|
||||
{
|
||||
|
@ -105,7 +110,7 @@ static HRESULT WINAPI fnTextSrv_QueryInterface(ITextServices * 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;
|
||||
*ppv = This;
|
||||
|
||||
if (*ppv)
|
||||
{
|
||||
|
@ -150,9 +155,10 @@ HRESULT WINAPI fnTextSrv_TxSendMessage(ITextServices *iface,
|
|||
LRESULT* plresult)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
HRESULT hresult;
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
*plresult = ME_HandleMessage(This->editor, msg, wparam, lparam, TRUE, &hresult);
|
||||
return hresult;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxDraw(ITextServices *iface,
|
||||
|
@ -184,8 +190,12 @@ HRESULT WINAPI fnTextSrv_TxGetHScroll(ITextServices *iface,
|
|||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
*plMin = This->editor->horz_si.nMin;
|
||||
*plMax = This->editor->horz_si.nMax;
|
||||
*plPos = This->editor->horz_si.nPos;
|
||||
*plPage = This->editor->horz_si.nPage;
|
||||
*pfEnabled = (This->editor->styleFlags & WS_HSCROLL) != 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxGetVScroll(ITextServices *iface,
|
||||
|
@ -197,8 +207,12 @@ HRESULT WINAPI fnTextSrv_TxGetVScroll(ITextServices *iface,
|
|||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
*plMin = This->editor->vert_si.nMin;
|
||||
*plMax = This->editor->vert_si.nMax;
|
||||
*plPos = This->editor->vert_si.nPos;
|
||||
*plPage = This->editor->vert_si.nPage;
|
||||
*pfEnabled = (This->editor->styleFlags & WS_VSCROLL) != 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_OnTxSetCursor(ITextServices *iface,
|
||||
|
@ -271,9 +285,23 @@ HRESULT WINAPI fnTextSrv_TxGetText(ITextServices *iface,
|
|||
BSTR* pbstrText)
|
||||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
int length;
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
length = ME_GetTextLength(This->editor);
|
||||
if (length)
|
||||
{
|
||||
BSTR bstr;
|
||||
bstr = SysAllocStringByteLen(NULL, length * sizeof(WCHAR));
|
||||
if (bstr == NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
ME_GetTextW(This->editor, bstr , 0, length, FALSE);
|
||||
*pbstrText = bstr;
|
||||
} else {
|
||||
*pbstrText = NULL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxSetText(ITextServices *iface,
|
||||
|
@ -281,8 +309,17 @@ HRESULT WINAPI fnTextSrv_TxSetText(ITextServices *iface,
|
|||
{
|
||||
ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface);
|
||||
|
||||
FIXME("%p: STUB\n", This);
|
||||
return E_NOTIMPL;
|
||||
ME_InternalDeleteText(This->editor, 0, ME_GetTextLength(This->editor),
|
||||
FALSE);
|
||||
ME_InsertTextFromCursor(This->editor, 0, pszText, -1,
|
||||
This->editor->pBuffer->pDefaultStyle);
|
||||
ME_SetSelection(This->editor, 0, 0);
|
||||
This->editor->nModifyStep = 0;
|
||||
OleFlushClipboard();
|
||||
ME_EmptyUndoStack(This->editor);
|
||||
ME_UpdateRepaint(This->editor);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI fnTextSrv_TxGetCurrentTargetX(ITextServices *iface,
|
||||
|
|
|
@ -55,8 +55,7 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp
|
|||
return NULL;
|
||||
else
|
||||
{
|
||||
ME_DisplayItem *pItem = (ME_DisplayItem *)ALLOC_OBJ(ME_UndoItem);
|
||||
((ME_UndoItem *)pItem)->nCR = ((ME_UndoItem *)pItem)->nLF = -1;
|
||||
ME_DisplayItem *pItem = ALLOC_OBJ(ME_UndoItem);
|
||||
switch(type)
|
||||
{
|
||||
case diUndoPotentialEndTransaction:
|
||||
|
@ -329,8 +328,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
|
|||
ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
|
||||
if (tmp.nOffset)
|
||||
tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset);
|
||||
assert(pUItem->nCR >= 0);
|
||||
assert(pUItem->nLF >= 0);
|
||||
assert(pUItem->eol_str);
|
||||
this_para = ME_GetParagraph(tmp.pRun);
|
||||
bFixRowStart = this_para->member.para.nFlags & MEPF_ROWSTART;
|
||||
if (bFixRowStart)
|
||||
|
@ -340,7 +338,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
|
|||
this_para->member.para.nFlags &= ~MEPF_ROWSTART;
|
||||
}
|
||||
new_para = ME_SplitParagraph(editor, tmp.pRun, tmp.pRun->member.run.style,
|
||||
pUItem->nCR, pUItem->nLF, paraFlags);
|
||||
pUItem->eol_str, paraFlags);
|
||||
if (bFixRowStart)
|
||||
new_para->member.para.nFlags |= MEPF_ROWSTART;
|
||||
assert(pItem->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
|
||||
|
|
|
@ -582,7 +582,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
|
|||
int yStart = -1;
|
||||
int totalWidth = 0;
|
||||
|
||||
ME_InitContext(&c, editor, GetDC(editor->hWnd));
|
||||
ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
|
||||
c.pt.x = 0;
|
||||
item = editor->pBuffer->pFirst->next;
|
||||
while(item != editor->pBuffer->pLast) {
|
||||
|
@ -723,7 +723,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
|
|||
editor->pBuffer->pLast->member.para.pt.x = 0;
|
||||
editor->pBuffer->pLast->member.para.pt.y = c.pt.y;
|
||||
|
||||
ME_DestroyContext(&c, editor->hWnd);
|
||||
ME_DestroyContext(&c);
|
||||
|
||||
if (bModified || editor->nTotalLength < editor->nLastTotalLength)
|
||||
ME_InvalidateMarkedParagraphs(editor);
|
||||
|
@ -737,7 +737,7 @@ void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor)
|
|||
int ofs;
|
||||
ME_DisplayItem *item;
|
||||
|
||||
ME_InitContext(&c, editor, GetDC(editor->hWnd));
|
||||
ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
|
||||
rc = c.rcView;
|
||||
ofs = editor->vert_si.nPos;
|
||||
|
||||
|
@ -748,7 +748,7 @@ void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor)
|
|||
rc.bottom = max(c.rcView.top + item->member.para.pt.y
|
||||
+ item->member.para.nHeight - ofs,
|
||||
c.rcView.bottom);
|
||||
InvalidateRect(editor->hWnd, &rc, TRUE);
|
||||
ITextHost_TxInvalidateRect(editor->texthost, &rc, TRUE);
|
||||
}
|
||||
item = item->member.para.next_para;
|
||||
}
|
||||
|
@ -756,9 +756,9 @@ void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor)
|
|||
{
|
||||
rc.top = c.rcView.top + editor->nTotalLength - ofs;
|
||||
rc.bottom = c.rcView.top + editor->nLastTotalLength - ofs;
|
||||
InvalidateRect(editor->hWnd, &rc, TRUE);
|
||||
ITextHost_TxInvalidateRect(editor->texthost, &rc, TRUE);
|
||||
}
|
||||
ME_DestroyContext(&c, editor->hWnd);
|
||||
ME_DestroyContext(&c);
|
||||
}
|
||||
|
||||
|
||||
|
@ -769,22 +769,19 @@ ME_SendRequestResize(ME_TextEditor *editor, BOOL force)
|
|||
{
|
||||
RECT rc;
|
||||
|
||||
GetClientRect(editor->hWnd, &rc);
|
||||
ITextHost_TxGetClientRect(editor->texthost, &rc);
|
||||
|
||||
if (force || rc.bottom != editor->nTotalLength)
|
||||
{
|
||||
REQRESIZE info;
|
||||
|
||||
info.nmhdr.hwndFrom = editor->hWnd;
|
||||
info.nmhdr.idFrom = GetWindowLongW(editor->hWnd, GWLP_ID);
|
||||
info.nmhdr.code = EN_REQUESTRESIZE;
|
||||
info.rc = rc;
|
||||
info.rc.right = editor->nTotalWidth;
|
||||
info.rc.bottom = editor->nTotalLength;
|
||||
|
||||
editor->nEventMask &= ~ENM_REQUESTRESIZE;
|
||||
SendMessageW(GetParent(editor->hWnd), WM_NOTIFY,
|
||||
info.nmhdr.idFrom, (LPARAM)&info);
|
||||
ITextHost_TxNotify(editor->texthost, info.nmhdr.code, &info);
|
||||
editor->nEventMask |= ENM_REQUESTRESIZE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -877,8 +877,7 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
|
|||
return FALSE;
|
||||
}
|
||||
/* Skip as many characters as required by current line break */
|
||||
nChars -= (p->member.run.nCR <= nChars) ? p->member.run.nCR : nChars;
|
||||
nChars -= (p->member.run.nLF <= nChars) ? p->member.run.nLF : nChars;
|
||||
nChars = max(0, nChars - p->member.run.strText->nLen);
|
||||
} else if (p->member.run.nFlags & MERF_ENDROW) {
|
||||
if (!ME_StreamOutPrint(pStream, "\\line \r\n"))
|
||||
return FALSE;
|
||||
|
@ -916,63 +915,35 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
|
|||
static BOOL
|
||||
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);
|
||||
ME_DisplayItem *item;
|
||||
int nLen;
|
||||
UINT nCodePage = CP_ACP;
|
||||
char *buffer = NULL;
|
||||
int nBufLen = 0;
|
||||
BOOL success = TRUE;
|
||||
|
||||
ME_RunOfsFromCharOfs(editor, nStart, &item, &nStart);
|
||||
|
||||
if (!item)
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (dwFormat & SF_USECODEPAGE)
|
||||
nCodePage = HIWORD(dwFormat);
|
||||
|
||||
/* TODO: Handle SF_TEXTIZED */
|
||||
|
||||
|
||||
while (success && nChars && item) {
|
||||
nLen = ME_StrLen(item->member.run.strText) - nStart;
|
||||
if (nLen > nChars)
|
||||
nLen = nChars;
|
||||
nLen = min(nChars, ME_StrLen(item->member.run.strText) - nStart);
|
||||
|
||||
if (item->member.run.nFlags & MERF_ENDPARA) {
|
||||
if (!editor->bEmulateVersion10 && item->member.run.nFlags & MERF_ENDPARA)
|
||||
{
|
||||
static const WCHAR szEOL[2] = { '\r', '\n' };
|
||||
|
||||
if (!editor->bEmulateVersion10) {
|
||||
/* richedit 2.0 - all line breaks are \r\n */
|
||||
if (dwFormat & SF_UNICODE)
|
||||
success = ME_StreamOutMove(pStream, (const char *)szEOL, sizeof(szEOL));
|
||||
else
|
||||
success = ME_StreamOutMove(pStream, "\r\n", 2);
|
||||
assert(nLen == 1);
|
||||
} else {
|
||||
int i; int tnLen;
|
||||
|
||||
/* richedit 1.0 - need to honor actual \r and \n amounts */
|
||||
nLen = item->member.run.nCR + item->member.run.nLF;
|
||||
if (nLen > nChars)
|
||||
nLen = nChars;
|
||||
tnLen = nLen;
|
||||
|
||||
i = 0;
|
||||
while (tnLen > 0 && i < item->member.run.nCR) {
|
||||
if (dwFormat & SF_UNICODE)
|
||||
success = ME_StreamOutMove(pStream, (const char *)(&szEOL[0]), sizeof(WCHAR));
|
||||
else
|
||||
success = ME_StreamOutMove(pStream, "\r", 1);
|
||||
tnLen--; i++;
|
||||
}
|
||||
i = 0;
|
||||
while (tnLen > 0 && i < item->member.run.nLF) {
|
||||
if (dwFormat & SF_UNICODE)
|
||||
success = ME_StreamOutMove(pStream, (const char *)(&szEOL[1]), sizeof(WCHAR));
|
||||
else
|
||||
success = ME_StreamOutMove(pStream, "\n", 1);
|
||||
tnLen--; i++;
|
||||
}
|
||||
}
|
||||
/* richedit 2.0 - all line breaks are \r\n */
|
||||
if (dwFormat & SF_UNICODE)
|
||||
success = ME_StreamOutMove(pStream, (const char *)szEOL, sizeof(szEOL));
|
||||
else
|
||||
success = ME_StreamOutMove(pStream, "\r\n", 2);
|
||||
} else {
|
||||
if (dwFormat & SF_UNICODE)
|
||||
success = ME_StreamOutMove(pStream, (const char *)(item->member.run.strText->szData + nStart),
|
||||
|
@ -992,12 +963,12 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n
|
|||
success = ME_StreamOutMove(pStream, buffer, nSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nChars -= nLen;
|
||||
nStart = 0;
|
||||
item = ME_FindItemFwd(item, diRun);
|
||||
}
|
||||
|
||||
|
||||
FREE_OBJ(buffer);
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -357,46 +357,6 @@ DECLARE_INTERFACE_(ITextHost,IUnknown)
|
|||
#define ITextHost_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
|
||||
#define ITextHost_AddRef(p) (p)->lpVtbl->AddRef(p)
|
||||
#define ITextHost_Release(p) (p)->lpVtbl->Release(p)
|
||||
/*** ITextHost methods ***/
|
||||
#define ITextHost_TxGetDC(p) (p)->lpVtbl->TxGetDC(p)
|
||||
#define ITextHost_TxReleaseDC(p,a) (p)->lpVtbl->TxReleaseDC(p,a)
|
||||
#define ITextHost_TxShowScrollBar(p,a,b) (p)->lpVtbl->TxShowScrollBar(p,a,b)
|
||||
#define ITextHost_TxEnableScrollBar(p,a,b) (p)->lpVtbl->TxEnableScrollBar(p,a,b)
|
||||
#define ITextHost_TxSetScrollRange(p,a,b,c,d) (p)->lpVtbl->TxSetScrollRange(p,a,b,c,d)
|
||||
#define ITextHost_TxSetScrollPos(p,a,b,c) (p)->lpVtbl->TxSetScrollPos(p,a,b,c)
|
||||
#define ITextHost_TxInvalidateRect(p,a,b) (p)->lpVtbl->TxInvalidateRect(p,a,b)
|
||||
#define ITextHost_TxViewChange(p,a) (p)->lpVtbl->TxViewChange(p,a)
|
||||
#define ITextHost_TxCreateCaret(p,a,b,c) (p)->lpVtbl->TxCreateCaret(p,a,b,c)
|
||||
#define ITextHost_TxShowCaret(p,a) (p)->lpVtbl->TxShowCaret(p,a)
|
||||
#define ITextHost_TxSetCarentPos(p,a,b) (p)->lpVtbl->TxSetCarentPos(p,a,b)
|
||||
#define ITextHost_TxSetTimer(p,a,b) (p)->lpVtbl->TxSetTimer(p,a,b)
|
||||
#define ITextHost_TxKillTimer(p,a) (p)->lpVtbl->TxKillTimer(p,a)
|
||||
#define ITextHost_TxScrollWindowEx(p,a,b,c,d,e,f,g) (p)->lpVtbl->TxScrollWindowEx(p,a,b,c,d,e,f,g)
|
||||
#define ITextHost_TxSetCapture(p,a) (p)->lpVtbl->TxSetCapture(p,a)
|
||||
#define ITextHost_TxSetFocus(p) (p)->lpVtbl->TxSetFocus(p)
|
||||
#define ITextHost_TxSetCursor(p,a,b) (p)->lpVtbl->TxSetCursor(p,a,b)
|
||||
#define ITextHost_TxScreenToClient(p,a) (p)->lpVtbl->TxScreenToClient(p,a)
|
||||
#define ITextHost_TxClientToScreen(p,a) (p)->lpVtbl->TxClientToScreen(p,a)
|
||||
#define ITextHost_TxActivate(p,a) (p)->lpVtbl->TxActivate(p,a)
|
||||
#define ITextHost_TxDeactivate(p,a) (p)->lpVtbl->TxDeactivate(p,a)
|
||||
#define ITextHost_TxGetClientRect(p,a) (p)->lpVtbl->TxGetClientRect(p,a)
|
||||
#define ITextHost_TxGetViewInset(p,a) (p)->lpVtbl->TxGetViewInset(p,a)
|
||||
#define ITextHost_TxGetCharFormat(p,a) (p)->lpVtbl->TxGetCharFormat(p,a)
|
||||
#define ITextHost_TxGetParaFormat(p,a) (p)->lpVtbl->TxGetParaFormat(p,a)
|
||||
#define ITextHost_TxGetSysColor(p,a) (p)->lpVtbl->TxGetSysColor(p,a)
|
||||
#define ITextHost_TxGetBackStyle(p,a) (p)->lpVtbl->TxGetBackStyle(p,a)
|
||||
#define ITextHost_TxGetMaxLength(p,a) (p)->lpVtbl->TxGetMaxLength(p,a)
|
||||
#define ITextHost_TxGetScrollBars(p,a) (p)->lpVtbl->TxGetScrollBars(p,a)
|
||||
#define ITextHost_TxGetPasswordChar(p,a) (p)->lpVtbl->TxGetPasswordChar(p,a)
|
||||
#define ITextHost_TxGetAcceleratorPos(p,a) (p)->lpVtbl->TxGetAcceleratorPos(p,a)
|
||||
#define ITextHost_TxGetExtent(p,a) (p)->lpVtbl->TxGetExtent(p,a)
|
||||
#define ITextHost_OnTxCharFormatChange(p,a) (p)->lpVtbl->OnTxCharFormatChange(p,a)
|
||||
#define ITextHost_OnTxParaFormatChange(p,a) (p)->lpVtbl->OnTxParaFormatChange(p,a)
|
||||
#define ITextHost_TxGetPropertyBits(p,a,b) (p)->lpVtbl->TxGetPropertyBits(p,a,b)
|
||||
#define ITextHost_TxNotify(p,a,b) (p)->lpVtbl->TxNotify(p,a,b)
|
||||
#define ITextHost_TxImmGetContext(p) (p)->lpVtbl->TxImmGetContext(p)
|
||||
#define ITextHost_TxImmReleaseContext(p,a) (p)->lpVtbl->TxImmReleaseContext(p,a)
|
||||
#define ITextHost_TxGetSelectionBarWidth(p,a) (p)->lpVtbl->TxGetSelectionBarWidth(p,a)
|
||||
#endif
|
||||
|
||||
#undef INTERFACE
|
||||
|
|
Loading…
Reference in a new issue