- 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
+ WM_CHAR
+ WM_CLEAR
- WM_COPY (lame implementation, no RTF support)
- WM_CUT (lame implementation, no RTF support)
+ WM_COPY
+ WM_CUT
+ WM_GETDLGCODE (the current implementation is incomplete)
+ WM_GETTEXT (ANSI&Unicode)
+ WM_GETTEXTLENGTH (ANSI version sucks)
- WM_PASTE
+ WM_PASTE
- WM_SETFONT
+ WM_SETTEXT (resets undo stack !) (proper style?) ANSI&Unicode
- WM_STYLECHANGING
@ -271,6 +271,7 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM
break;
} while(1);
ME_CommitUndo(editor);
ME_Repaint(editor);
return 0;
}
@ -282,6 +283,11 @@ void ME_RTFCharAttrHook(RTF_Info *info)
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:
fmt.dwMask = CFM_BOLD;
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;
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)
{
pUI->nStart = from;
@ -530,6 +536,70 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
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)
{
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_SETWORDBREAKPROCEX)
UNSUPPORTED_MSG(WM_SETFONT)
UNSUPPORTED_MSG(WM_PASTE)
UNSUPPORTED_MSG(WM_STYLECHANGING)
UNSUPPORTED_MSG(WM_STYLECHANGED)
/* 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);
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_COPY:
{
int from, to, pars;
WCHAR *data;
HANDLE hData;
EDITSTREAM es;
ME_GlobalDestStruct gds;
if (!OpenClipboard(hWnd))
return 0;
@ -822,7 +919,17 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
data = (WCHAR *)GlobalLock(hData);
ME_GetTextW(editor, data, from, to-from, TRUE);
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(RegisterClipboardFormatA("Rich Text Format"), gds.hData);
CloseClipboard();
if (msg == WM_CUT)
{

View File

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