- WM_COPY (and WM_CUT) can now put both Unicode and RTF format (thanks

to Phil Krylov's RTF generator code).
- New message implemented - WM_PASTE.
- RTF reader: rtfPlain implemented (kind of).
- RTF writer: rewritten main loop (the old one crashed in some
  circumstances when SFF_SELECTION was used).
This commit is contained in:
Krzysztof Foltman 2005-03-15 15:40:52 +00:00 committed by Alexandre Julliard
parent 7f6536c504
commit d4cf45e3f1
2 changed files with 149 additions and 39 deletions

View File

@ -107,12 +107,12 @@
- EM_UNDO - EM_UNDO
+ WM_CHAR + WM_CHAR
+ WM_CLEAR + WM_CLEAR
- WM_COPY (lame implementation, no RTF support) + WM_COPY
- WM_CUT (lame implementation, no RTF support) + WM_CUT
+ WM_GETDLGCODE (the current implementation is incomplete) + WM_GETDLGCODE (the current implementation is incomplete)
+ WM_GETTEXT (ANSI&Unicode) + WM_GETTEXT (ANSI&Unicode)
+ WM_GETTEXTLENGTH (ANSI version sucks) + WM_GETTEXTLENGTH (ANSI version sucks)
- WM_PASTE + WM_PASTE
- WM_SETFONT - WM_SETFONT
+ WM_SETTEXT (resets undo stack !) (proper style?) ANSI&Unicode + WM_SETTEXT (resets undo stack !) (proper style?) ANSI&Unicode
- WM_STYLECHANGING - WM_STYLECHANGING
@ -271,6 +271,7 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM
break; break;
} while(1); } while(1);
ME_CommitUndo(editor); ME_CommitUndo(editor);
ME_Repaint(editor);
return 0; return 0;
} }
@ -282,6 +283,11 @@ void ME_RTFCharAttrHook(RTF_Info *info)
switch(info->rtfMinor) switch(info->rtfMinor)
{ {
case rtfPlain:
FIXME("rtfPlain: how plain should it be ?\n");
fmt.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR | CFM_BACKCOLOR;
fmt.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR;
break;
case rtfBold: case rtfBold:
fmt.dwMask = CFM_BOLD; fmt.dwMask = CFM_BOLD;
fmt.dwEffects = info->rtfParam ? fmt.dwMask : 0; fmt.dwEffects = info->rtfParam ? fmt.dwMask : 0;
@ -449,7 +455,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
editor->nUndoMode = nUndoMode; editor->nUndoMode = nUndoMode;
pUI = ME_AddUndoItem(editor, diUndoDeleteRun, NULL); pUI = ME_AddUndoItem(editor, diUndoDeleteRun, NULL);
FIXME("from %d to %d\n", from, to); TRACE("from %d to %d\n", from, to);
if (pUI && from < to) if (pUI && from < to)
{ {
pUI->nStart = from; pUI->nStart = from;
@ -530,6 +536,70 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
return ed; return ed;
} }
typedef struct tagME_GlobalDestStruct
{
HGLOBAL hData;
int nLength;
} ME_GlobalDestStruct;
static DWORD CALLBACK ME_AppendToHGLOBAL(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb)
{
ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie;
int nMaxSize;
BYTE *pDest;
nMaxSize = GlobalSize(pData->hData);
if (pData->nLength+cb+1 >= cb)
{
/* round up to 2^17 */
int nNewSize = (((nMaxSize+cb+1)|0x1FFFF)+1) & 0xFFFE0000;
pData->hData = GlobalReAlloc(pData->hData, nNewSize, 0);
}
pDest = (BYTE *)GlobalLock(pData->hData);
memcpy(pDest + pData->nLength, lpBuff, cb);
pData->nLength += cb;
pDest[pData->nLength] = '\0';
GlobalUnlock(pData->hData);
*pcb = cb;
return 0;
}
static DWORD CALLBACK ME_ReadFromHGLOBALUnicode(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb)
{
ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie;
int i;
WORD *pSrc, *pDest;
cb = cb >> 1;
pDest = (WORD *)lpBuff;
pSrc = (WORD *)GlobalLock(pData->hData);
for (i = 0; i<cb && pSrc[pData->nLength+i]; i++) {
pDest[i] = pSrc[pData->nLength+i];
}
pData->nLength += i;
*pcb = 2*i;
GlobalUnlock(pData->hData);
return 0;
}
static DWORD CALLBACK ME_ReadFromHGLOBALRTF(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb)
{
ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie;
int i;
BYTE *pSrc, *pDest;
pDest = lpBuff;
pSrc = (BYTE *)GlobalLock(pData->hData);
for (i = 0; i<cb && pSrc[pData->nLength+i]; i++) {
pDest[i] = pSrc[pData->nLength+i];
}
pData->nLength += i;
*pcb = i;
GlobalUnlock(pData->hData);
return 0;
}
void ME_DestroyEditor(ME_TextEditor *editor) void ME_DestroyEditor(ME_TextEditor *editor)
{ {
ME_DisplayItem *pFirst = editor->pBuffer->pFirst; ME_DisplayItem *pFirst = editor->pBuffer->pFirst;
@ -618,7 +688,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
UNSUPPORTED_MSG(EM_SETWORDBREAKPROC) UNSUPPORTED_MSG(EM_SETWORDBREAKPROC)
UNSUPPORTED_MSG(EM_SETWORDBREAKPROCEX) UNSUPPORTED_MSG(EM_SETWORDBREAKPROCEX)
UNSUPPORTED_MSG(WM_SETFONT) UNSUPPORTED_MSG(WM_SETFONT)
UNSUPPORTED_MSG(WM_PASTE)
UNSUPPORTED_MSG(WM_STYLECHANGING) UNSUPPORTED_MSG(WM_STYLECHANGING)
UNSUPPORTED_MSG(WM_STYLECHANGED) UNSUPPORTED_MSG(WM_STYLECHANGED)
/* UNSUPPORTED_MSG(WM_UNICHAR) FIXME missing in Wine headers */ /* UNSUPPORTED_MSG(WM_UNICHAR) FIXME missing in Wine headers */
@ -805,12 +874,40 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
ME_UpdateRepaint(editor); ME_UpdateRepaint(editor);
return 0; return 0;
} }
case WM_PASTE:
{
DWORD dwFormat = 0;
EDITSTREAM es;
ME_GlobalDestStruct gds;
UINT nRTFFormat = RegisterClipboardFormatA("Rich Text Format");
UINT cf = 0;
if (!OpenClipboard(hWnd))
return 0;
if (IsClipboardFormatAvailable(nRTFFormat))
cf = nRTFFormat, dwFormat = SF_RTF;
else if (IsClipboardFormatAvailable(CF_UNICODETEXT))
cf = CF_UNICODETEXT, dwFormat = SF_TEXT|SF_UNICODE;
else
return 0;
gds.hData = GetClipboardData(cf);
gds.nLength = 0;
es.dwCookie = (DWORD)&gds;
es.pfnCallback = dwFormat == SF_RTF ? ME_ReadFromHGLOBALRTF : ME_ReadFromHGLOBALUnicode;
SendMessageW(hWnd, EM_STREAMIN, dwFormat|SFF_SELECTION, (LPARAM)&es);
CloseClipboard();
return 0;
}
case WM_CUT: case WM_CUT:
case WM_COPY: case WM_COPY:
{ {
int from, to, pars; int from, to, pars;
WCHAR *data; WCHAR *data;
HANDLE hData; HANDLE hData;
EDITSTREAM es;
ME_GlobalDestStruct gds;
if (!OpenClipboard(hWnd)) if (!OpenClipboard(hWnd))
return 0; return 0;
@ -822,7 +919,17 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
data = (WCHAR *)GlobalLock(hData); data = (WCHAR *)GlobalLock(hData);
ME_GetTextW(editor, data, from, to-from, TRUE); ME_GetTextW(editor, data, from, to-from, TRUE);
GlobalUnlock(hData); GlobalUnlock(hData);
gds.hData = GlobalAlloc(GMEM_MOVEABLE, 0);
gds.nLength = 0;
es.dwCookie = (DWORD)&gds;
es.pfnCallback = ME_AppendToHGLOBAL;
SendMessageW(hWnd, EM_STREAMOUT, SFF_SELECTION|SF_RTF, (LPARAM)&es);
GlobalReAlloc(gds.hData, gds.nLength+1, 0);
SetClipboardData(CF_UNICODETEXT, hData); SetClipboardData(CF_UNICODETEXT, hData);
SetClipboardData(RegisterClipboardFormatA("Rich Text Format"), gds.hData);
CloseClipboard(); CloseClipboard();
if (msg == WM_CUT) if (msg == WM_CUT)
{ {

View File

@ -107,7 +107,7 @@ ME_StreamOutPrint(ME_TextEditor *editor, char *format, ...)
static BOOL static BOOL
ME_StreamOutRTFHeader(ME_TextEditor *editor, int dwFormat) ME_StreamOutRTFHeader(ME_TextEditor *editor, int dwFormat)
{ {
char *cCharSet; char *cCharSet = NULL;
UINT nCodePage; UINT nCodePage;
LANGID language; LANGID language;
BOOL success; BOOL success;
@ -171,10 +171,9 @@ ME_StreamOutRTFHeader(ME_TextEditor *editor, int dwFormat)
static BOOL static BOOL
ME_StreamOutRTFFontAndColorTbl(ME_TextEditor *editor, ME_DisplayItem *pFirstRun, LONG to) ME_StreamOutRTFFontAndColorTbl(ME_TextEditor *editor, ME_DisplayItem *pFirstRun, ME_DisplayItem *pLastRun)
{ {
ME_DisplayItem *item = pFirstRun; ME_DisplayItem *item = pFirstRun;
ME_DisplayItem *pLastRun = ME_FindItemAtOffset(editor, diRun, to, NULL);
ME_FontTableItem *table = editor->pStream->fonttbl; ME_FontTableItem *table = editor->pStream->fonttbl;
int i; int i;
@ -485,15 +484,15 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars)
static BOOL static BOOL
ME_StreamOutRTF(ME_TextEditor *editor, int nStart, int nChars, int dwFormat) ME_StreamOutRTF(ME_TextEditor *editor, int nStart, int nChars, int dwFormat)
{ {
int nTo; ME_DisplayItem *p, *pEnd;
ME_DisplayItem *para = ME_FindItemAtOffset(editor, diParagraph, nStart, NULL); int nOffset, nEndLen;
ME_DisplayItem *item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart); ME_RunOfsFromCharOfs(editor, nStart, &p, &nOffset);
ME_DisplayItem *last_item = ME_FindItemAtOffset(editor, diRun, nStart + nChars, &nTo); ME_RunOfsFromCharOfs(editor, nStart+nChars, &pEnd, &nEndLen);
if (!ME_StreamOutRTFHeader(editor, dwFormat)) if (!ME_StreamOutRTFHeader(editor, dwFormat))
return FALSE; return FALSE;
if (!ME_StreamOutRTFFontAndColorTbl(editor, item, nStart + nChars)) if (!ME_StreamOutRTFFontAndColorTbl(editor, p, pEnd))
return FALSE; return FALSE;
/* TODO: stylesheet table */ /* TODO: stylesheet table */
@ -510,48 +509,51 @@ ME_StreamOutRTF(ME_TextEditor *editor, int nStart, int nChars, int dwFormat)
/* TODO: section formatting properties */ /* TODO: section formatting properties */
while (para) { if (!ME_StreamOutRTFParaProps(editor, ME_GetParagraph(p)))
ME_DisplayItem *p;
int nLen;
if (!ME_StreamOutRTFParaProps(editor, para))
return FALSE; return FALSE;
if (!item) { while(1)
item = ME_FindItemFwd(para, diRun); {
nStart = 0; switch(p->type)
} {
for (p = item; p && p != para->member.para.next_para; p = p->next) { case diParagraph:
TRACE("type %d\n", p->type); if (!ME_StreamOutRTFParaProps(editor, p))
if (p->type == diRun) { return FALSE;
break;
case diRun:
if (p == pEnd && !nEndLen)
break;
TRACE("flags %xh\n", p->member.run.nFlags); TRACE("flags %xh\n", p->member.run.nFlags);
/* TODO: emit embedded objects */
if (p->member.run.nFlags & MERF_GRAPHICS)
FIXME("embedded objects are not handled\n");
if (p->member.run.nFlags & MERF_ENDPARA) { if (p->member.run.nFlags & MERF_ENDPARA) {
if (!ME_StreamOutPrint(editor, "\r\n\\par")) if (!ME_StreamOutPrint(editor, "\r\n\\par"))
return FALSE; return FALSE;
nChars--; nChars--;
} else { } else {
int nEnd;
if (!ME_StreamOutPrint(editor, "{")) if (!ME_StreamOutPrint(editor, "{"))
return FALSE; return FALSE;
TRACE("style %p\n", p->member.run.style); TRACE("style %p\n", p->member.run.style);
if (!ME_StreamOutRTFCharProps(editor, &p->member.run.style->fmt)) if (!ME_StreamOutRTFCharProps(editor, &p->member.run.style->fmt))
return FALSE; return FALSE;
/* TODO: emit embedded objects as well as text */ nEnd = (p == pEnd) ? nEndLen : ME_StrLen(p->member.run.strText);
nLen = ME_StrLen(p->member.run.strText) - nStart; if (!ME_StreamOutRTFText(editor, p->member.run.strText->szData + nOffset, nEnd - nOffset))
if (!ME_StreamOutRTFText(editor, p->member.run.strText->szData + nStart,
(p == last_item ? nTo - nStart : nLen)))
return FALSE; return FALSE;
nOffset = 0;
if (!ME_StreamOutPrint(editor, "}")) if (!ME_StreamOutPrint(editor, "}"))
return FALSE; return FALSE;
} }
}
if (p == last_item)
break; break;
default: /* we missed the last item */
assert(0);
} }
para = para->member.para.next_para; if (p == pEnd)
item = NULL;
if (p == last_item)
break; break;
p = ME_FindItemFwd(p, diRunOrParagraphOrEnd);
} }
if (!ME_StreamOutPrint(editor, "}")) if (!ME_StreamOutPrint(editor, "}"))
return FALSE; return FALSE;
@ -562,6 +564,7 @@ ME_StreamOutRTF(ME_TextEditor *editor, int nStart, int nChars, int dwFormat)
static BOOL static BOOL
ME_StreamOutText(ME_TextEditor *editor, int nStart, int nChars, DWORD dwFormat) ME_StreamOutText(ME_TextEditor *editor, int nStart, int nChars, DWORD dwFormat)
{ {
/* FIXME: use ME_RunOfsFromCharOfs */
ME_DisplayItem *item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart); ME_DisplayItem *item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart);
int nLen; int nLen;
UINT nCodePage = CP_ACP; UINT nCodePage = CP_ACP;