- 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:
parent
7f6536c504
commit
d4cf45e3f1
|
@ -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
|
||||
|
@ -270,7 +270,8 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM
|
|||
if (nDataSize<STREAMIN_BUFFER_SIZE)
|
||||
break;
|
||||
} while(1);
|
||||
ME_CommitUndo(editor);
|
||||
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);
|
||||
SetClipboardData(CF_UNICODETEXT, 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)
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
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) {
|
||||
if (!ME_StreamOutRTFParaProps(editor, ME_GetParagraph(p)))
|
||||
return FALSE;
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue