From ec9b7581909991cacbcd291becdf17ccbf6194b8 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 19 Oct 2023 18:15:45 +0300 Subject: mTextControl: RTF code redesign --- libs/mTextControl/src/FormattedTextDraw.cpp | 196 ++++++++++++++++------------ libs/mTextControl/src/FormattedTextDraw.h | 8 +- libs/mTextControl/src/services.cpp | 5 +- 3 files changed, 115 insertions(+), 94 deletions(-) (limited to 'libs/mTextControl/src') diff --git a/libs/mTextControl/src/FormattedTextDraw.cpp b/libs/mTextControl/src/FormattedTextDraw.cpp index f18833bd25..8a074430fc 100644 --- a/libs/mTextControl/src/FormattedTextDraw.cpp +++ b/libs/mTextControl/src/FormattedTextDraw.cpp @@ -21,43 +21,6 @@ const IID IID_ITextDocument = { { 0x80, 0x98, 0x00, 0xAA, 0x00, 0x47, 0xBE, 0x5D } }; -///////////////////////////////////////////////////////////////////////////// -// CallBack functions - -struct STREAMDATA -{ - bool isUnicode; - union - { - char *ansi; - wchar_t *unicode; - }; - size_t cbSize, cbCount; -}; - -static DWORD CALLBACK EditStreamInCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) -{ - STREAMDATA *pCookie = (STREAMDATA *)dwCookie; - if (pCookie->isUnicode) { - if ((pCookie->cbSize - pCookie->cbCount) * sizeof(wchar_t) < (size_t)cb) - *pcb = LONG(pCookie->cbSize - pCookie->cbCount) * sizeof(wchar_t); - else - *pcb = cb & ~1UL; - memcpy(pbBuff, pCookie->unicode + pCookie->cbCount, *pcb); - pCookie->cbCount += *pcb / sizeof(wchar_t); - } - else { - if (pCookie->cbSize - pCookie->cbCount < (uint32_t)cb) - *pcb = LONG(pCookie->cbSize - pCookie->cbCount); - else - *pcb = cb; - memcpy(pbBuff, pCookie->ansi + pCookie->cbCount, *pcb); - pCookie->cbCount += *pcb; - } - - return 0; // callback succeeded - no errors -} - ///////////////////////////////////////////////////////////////////////////// // CFormattedTextDraw @@ -73,16 +36,12 @@ CFormattedTextDraw::CFormattedTextDraw() SetRectEmpty(&m_rcClient); SetRectEmpty(&m_rcViewInset); - m_pCF = (CHARFORMAT2W *)malloc(sizeof(CHARFORMAT2W)); - InitDefaultCharFormat(); InitDefaultParaFormat(); m_spTextServices = nullptr; m_spTextDocument = nullptr; m_dwPropertyBits = TXTBIT_RICHTEXT | TXTBIT_MULTILINE | TXTBIT_WORDWRAP | TXTBIT_USECURRENTBKG; - m_dwScrollbar = 0; - m_dwMaxLength = INFINITE; IUnknown *spUnk; HRESULT hr = MyCreateTextServices(nullptr, static_cast(this), &spUnk); @@ -95,51 +54,46 @@ CFormattedTextDraw::CFormattedTextDraw() CFormattedTextDraw::~CFormattedTextDraw() { - free(m_pCF); if (m_spTextServices != nullptr) m_spTextServices->Release(); if (m_spTextDocument != nullptr) m_spTextDocument->Release(); } -HRESULT CFormattedTextDraw::putRTFTextA(char *newVal) -{ - if (!m_spTextServices) - return S_FALSE; - - STREAMDATA streamData = {}; - streamData.isUnicode = false; - streamData.ansi = newVal; - streamData.cbSize = mir_strlen(newVal); - - EDITSTREAM editStream; - editStream.dwCookie = (DWORD_PTR)&streamData; - editStream.dwError = 0; - editStream.pfnCallback = (EDITSTREAMCALLBACK)EditStreamInCallback; - - LRESULT lResult = 0; - m_spTextServices->TxSendMessage(EM_STREAMIN, SF_RTF, (LPARAM)&editStream, &lResult); - return S_OK; -} +///////////////////////////////////////////////////////////////////////////////////////// -HRESULT CFormattedTextDraw::putRTFTextW(wchar_t *newVal) +struct STREAMDATATEXT { - if (!m_spTextServices) - return S_FALSE; - - STREAMDATA streamData = {}; - streamData.isUnicode = true; - streamData.unicode = newVal; - streamData.cbSize = mir_wstrlen(newVal); + bool isUnicode; + union + { + char *ansi; + wchar_t *unicode; + }; + size_t cbSize, cbCount; +}; - EDITSTREAM editStream; - editStream.dwCookie = (DWORD_PTR)&streamData; - editStream.dwError = 0; - editStream.pfnCallback = (EDITSTREAMCALLBACK)EditStreamInCallback; +static DWORD CALLBACK EditStreamTextInCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) +{ + auto *pCookie = (STREAMDATATEXT *)dwCookie; + if (pCookie->isUnicode) { + if ((pCookie->cbSize - pCookie->cbCount) * sizeof(wchar_t) < (size_t)cb) + *pcb = LONG(pCookie->cbSize - pCookie->cbCount) * sizeof(wchar_t); + else + *pcb = cb & ~1UL; + memcpy(pbBuff, pCookie->unicode + pCookie->cbCount, *pcb); + pCookie->cbCount += *pcb / sizeof(wchar_t); + } + else { + if (pCookie->cbSize - pCookie->cbCount < (uint32_t)cb) + *pcb = LONG(pCookie->cbSize - pCookie->cbCount); + else + *pcb = cb; + memcpy(pbBuff, pCookie->ansi + pCookie->cbCount, *pcb); + pCookie->cbCount += *pcb; + } - LRESULT lResult = 0; - m_spTextServices->TxSendMessage(EM_STREAMIN, SF_RTF | SF_UNICODE, (LPARAM)&editStream, &lResult); - return S_OK; + return 0; // callback succeeded - no errors } HRESULT CFormattedTextDraw::putTextA(char *newVal) @@ -147,7 +101,7 @@ HRESULT CFormattedTextDraw::putTextA(char *newVal) if (!m_spTextServices) return S_FALSE; - STREAMDATA streamData = {}; + STREAMDATATEXT streamData = {}; streamData.isUnicode = false; streamData.ansi = newVal; streamData.cbSize = mir_strlen(newVal); @@ -155,7 +109,7 @@ HRESULT CFormattedTextDraw::putTextA(char *newVal) EDITSTREAM editStream; editStream.dwCookie = (DWORD_PTR)&streamData; editStream.dwError = 0; - editStream.pfnCallback = (EDITSTREAMCALLBACK)EditStreamInCallback; + editStream.pfnCallback = EditStreamTextInCallback; LRESULT lResult = 0; m_spTextServices->TxSendMessage(EM_STREAMIN, SF_TEXT, (LPARAM)&editStream, &lResult); @@ -175,7 +129,7 @@ HRESULT CFormattedTextDraw::putTextW(wchar_t *newVal) if (!m_spTextServices) return S_FALSE; - STREAMDATA streamData = {}; + STREAMDATATEXT streamData = {}; streamData.isUnicode = true; streamData.unicode = newVal; streamData.cbSize = mir_wstrlen(newVal); @@ -183,7 +137,7 @@ HRESULT CFormattedTextDraw::putTextW(wchar_t *newVal) EDITSTREAM editStream; editStream.dwCookie = (DWORD_PTR)&streamData; editStream.dwError = 0; - editStream.pfnCallback = (EDITSTREAMCALLBACK)EditStreamInCallback; + editStream.pfnCallback = EditStreamTextInCallback; LRESULT lResult = 0; m_spTextServices->TxSendMessage(EM_STREAMIN, SF_TEXT | SF_UNICODE, (LPARAM)&editStream, &lResult); @@ -197,6 +151,78 @@ HRESULT CFormattedTextDraw::putTextW(wchar_t *newVal) return S_OK; } +///////////////////////////////////////////////////////////////////////////////////////// + +#define STREAMSTAGE_HEADER 0 +#define STREAMSTAGE_EVENTS 1 +#define STREAMSTAGE_TAIL 2 +#define STREAMSTAGE_STOP 3 + +struct STREAMDATA +{ + CMStringA buf; + int iStage = STREAMSTAGE_HEADER; + MRtfProvider *pProv; +}; + +static DWORD CALLBACK EditStreamInCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) +{ + auto *dat = (STREAMDATA *)dwCookie; + + if (dat->buf.IsEmpty()) { + switch (dat->iStage) { + case STREAMSTAGE_HEADER: + dat->buf = dat->pProv->CreateRtfHeader(); + dat->iStage = STREAMSTAGE_EVENTS; + break; + + case STREAMSTAGE_EVENTS: + dat->buf = dat->pProv->CreateRtfBody(); + dat->iStage = STREAMSTAGE_TAIL; + break; + + case STREAMSTAGE_TAIL: + dat->buf = dat->pProv->CreateRtfFooter(); + dat->iStage = STREAMSTAGE_STOP; + break; + + case STREAMSTAGE_STOP: + *pcb = 0; + return 0; + } + } + + *pcb = min(cb, dat->buf.GetLength()); + memcpy(pbBuff, dat->buf.GetBuffer(), *pcb); + if (dat->buf.GetLength() == *pcb) + dat->buf.Empty(); + else + dat->buf.Delete(0, *pcb); + + return 0; // callback succeeded - no errors +} + +HRESULT CFormattedTextDraw::putRTFText(MRtfProvider *pProv) +{ + if (!m_spTextServices) + return S_FALSE; + + STREAMDATA streamData = {}; + streamData.pProv = pProv; + + EDITSTREAM editStream; + editStream.dwCookie = (DWORD_PTR)&streamData; + editStream.dwError = 0; + editStream.pfnCallback = EditStreamInCallback; + + LRESULT lResult = 0; + m_spTextServices->TxSendMessage(EM_STREAMIN, SF_RTF, (LPARAM)&editStream, &lResult); + return S_OK; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Other methods + HRESULT CFormattedTextDraw::Draw(HDC hdcDraw, RECT *prc) { LOGFONT lf; @@ -395,7 +421,7 @@ HRESULT CFormattedTextDraw::TxGetViewInset(LPRECT prc) HRESULT CFormattedTextDraw::TxGetCharFormat(const CHARFORMATW **ppCF) { - *ppCF = m_pCF; + *ppCF = &m_CF; return S_OK; } @@ -418,13 +444,13 @@ HRESULT CFormattedTextDraw::TxGetBackStyle(TXTBACKSTYLE *pstyle) HRESULT CFormattedTextDraw::TxGetMaxLength(DWORD *plength) { - *plength = m_dwMaxLength; + *plength = INFINITE; return S_OK; } HRESULT CFormattedTextDraw::TxGetScrollBars(DWORD *pdwScrollBar) { - *pdwScrollBar = m_dwScrollbar; + *pdwScrollBar = 0; return S_OK; } @@ -446,7 +472,7 @@ HRESULT CFormattedTextDraw::TxGetExtent(LPSIZEL) HRESULT CFormattedTextDraw::OnTxCharFormatChange(const CHARFORMATW *pcf) { - memcpy(m_pCF, pcf, pcf->cbSize); + memcpy(&m_CF, pcf, pcf->cbSize); return S_OK; } @@ -536,7 +562,7 @@ HRESULT CFormattedTextDraw::CharFormatFromHFONT(CHARFORMAT2W *pCF, HFONT hFont) HRESULT CFormattedTextDraw::InitDefaultCharFormat() { - return CharFormatFromHFONT(m_pCF, nullptr); + return CharFormatFromHFONT(&m_CF, nullptr); } HRESULT CFormattedTextDraw::InitDefaultParaFormat() diff --git a/libs/mTextControl/src/FormattedTextDraw.h b/libs/mTextControl/src/FormattedTextDraw.h index cd902e2cae..3ec7a7412e 100644 --- a/libs/mTextControl/src/FormattedTextDraw.h +++ b/libs/mTextControl/src/FormattedTextDraw.h @@ -24,11 +24,10 @@ class CFormattedTextDraw : public ITextHost, public MZeroedObject int nPixelsPerInchX; // Pixels per logical inch along width int nPixelsPerInchY; // Pixels per logical inch along height - CHARFORMAT2W *m_pCF; + CHARFORMAT2W m_CF; PARAFORMAT2 m_PF; - uint32_t m_dwScrollbar; // Scroll bar style + uint32_t m_dwPropertyBits; // Property bits - uint32_t m_dwMaxLength; ITextServices *m_spTextServices; ITextDocument *m_spTextDocument; @@ -39,8 +38,7 @@ public: HRESULT get_NaturalSize(HDC hdcDraw, long *Width, long *pVal); HRESULT Draw(HDC hdcDraw, RECT *prc); - HRESULT putRTFTextA(char *newVal); - HRESULT putRTFTextW(wchar_t *newVal); + HRESULT putRTFText(MRtfProvider *pProv); HRESULT putTextA(char *newVal); HRESULT putTextW(wchar_t *newVal); diff --git a/libs/mTextControl/src/services.cpp b/libs/mTextControl/src/services.cpp index 4eebeeab22..317646dcbb 100644 --- a/libs/mTextControl/src/services.cpp +++ b/libs/mTextControl/src/services.cpp @@ -92,10 +92,7 @@ MTEXTCONTROL_DLL(TextObject *) MTextCreateEx(HANDLE userHandle, void *text, uint MText_InitFormatting0(result->ftd, result->options); if (flags & MTEXT_FLG_RTF) { - if (flags & MTEXT_FLG_WCHAR) - result->ftd->putRTFTextW((wchar_t *)text); - else - result->ftd->putRTFTextA((char *)text); + result->ftd->putRTFText((MRtfProvider *)text); } else { if (flags & MTEXT_FLG_WCHAR) -- cgit v1.2.3