diff options
-rw-r--r-- | libs/mTextControl/src/FormattedTextDraw.cpp | 196 | ||||
-rw-r--r-- | libs/mTextControl/src/FormattedTextDraw.h | 8 | ||||
-rw-r--r-- | libs/mTextControl/src/services.cpp | 5 | ||||
-rw-r--r-- | plugins/ExternalAPI/m_text.h | 7 | ||||
-rw-r--r-- | plugins/NewStory/src/history_array.cpp | 10 | ||||
-rw-r--r-- | plugins/NewStory/src/templates.cpp | 24 | ||||
-rw-r--r-- | plugins/NewStory/src/templates.h | 14 |
7 files changed, 158 insertions, 106 deletions
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 @@ -22,43 +22,6 @@ const IID IID_ITextDocument = { }; ///////////////////////////////////////////////////////////////////////////// -// 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 CFormattedTextDraw::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<ITextHost *>(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) diff --git a/plugins/ExternalAPI/m_text.h b/plugins/ExternalAPI/m_text.h index 1c231c2fd2..bc3fc25237 100644 --- a/plugins/ExternalAPI/m_text.h +++ b/plugins/ExternalAPI/m_text.h @@ -46,6 +46,13 @@ enum MTEXT_FLG_RTF = 0x00000004,
};
+struct MRtfProvider
+{
+ virtual CMStringA CreateRtfHeader() = 0;
+ virtual CMStringA CreateRtfBody() = 0;
+ virtual CMStringA CreateRtfFooter() = 0;
+};
+
// subscribe to MText services
MTEXTCONTROL_DLL(HANDLE) MTextRegister(const char *userTitle, uint32_t options);
diff --git a/plugins/NewStory/src/history_array.cpp b/plugins/NewStory/src/history_array.cpp index efd3fe9267..72d2b2e4ea 100644 --- a/plugins/NewStory/src/history_array.cpp +++ b/plugins/NewStory/src/history_array.cpp @@ -372,10 +372,12 @@ void ItemData::load(bool bFullLoad) void ItemData::setText() { - if (m_bRtf) - data = MTextCreateEx(htuLog, (void*)TplFormatRtf(getTemplate(), hContact, this).c_str(), MTEXT_FLG_RTF); - else - data = MTextCreateW(htuLog, Proto_GetBaseAccountName(hContact), TplFormatString(getTemplate(), hContact, this)); + if (m_bRtf) { + NSRtfProvider prov(this); + data = MTextCreateEx(htuLog, &prov, MTEXT_FLG_RTF); + } + else data = MTextCreateW(htuLog, Proto_GetBaseAccountName(hContact), TplFormatString(getTemplate(), hContact, this)); + savedHeight = -1; } diff --git a/plugins/NewStory/src/templates.cpp b/plugins/NewStory/src/templates.cpp index cab175563a..7010ff1e85 100644 --- a/plugins/NewStory/src/templates.cpp +++ b/plugins/NewStory/src/templates.cpp @@ -121,27 +121,37 @@ static void AppendUnicodeToBuffer(CMStringA &buf, const wchar_t *p) buf.AppendChar('}'); } -CMStringA TplFormatRtf(int tpl, MCONTACT hContact, ItemData *item) +CMStringA NSRtfProvider::CreateRtfHeader() { - CMStringW wszText = TplFormatString(tpl, hContact, item); - CMStringA buf; buf.Append("{\\rtf1\\ansi\\deff0"); - auto &F = g_fontTable[(item->dbe.flags & DBEF_SENT) ? FONT_OUTMSG : FONT_INMSG]; + auto &F = g_fontTable[(m_pItem->dbe.flags & DBEF_SENT) ? FONT_OUTMSG : FONT_INMSG]; buf.AppendFormat("{\\fonttbl{\\f0\\fnil\\fcharset1 %s;}}", F.lf.lfFaceName); COLORREF cr = GetSysColor(COLOR_WINDOWTEXT); buf.AppendFormat("{\\colortbl \\red%u\\green%u\\blue%u;", GetRValue(cr), GetGValue(cr), GetBValue(cr)); - cr = g_colorTable[(item->dbe.flags & DBEF_SENT) ? COLOR_OUTNICK : COLOR_INNICK].cl; + cr = g_colorTable[(m_pItem->dbe.flags & DBEF_SENT) ? COLOR_OUTNICK : COLOR_INNICK].cl; buf.AppendFormat("\\red%u\\green%u\\blue%u;}", GetRValue(cr), GetGValue(cr), GetBValue(cr)); + return buf; +} + +CMStringA NSRtfProvider::CreateRtfBody() +{ + auto &F = g_fontTable[(m_pItem->dbe.flags & DBEF_SENT) ? FONT_OUTMSG : FONT_INMSG]; + CMStringW wszText = TplFormatString(m_pItem->getTemplate(), m_pItem->hContact, m_pItem); - buf.AppendFormat("\\par\\ltrpar \\f0\\cf0\\b0\\i0\\fs%d ", -F.lf.lfHeight); + CMStringA buf; + // buf.AppendFormat("\\f0\\cf0\\b0\\i0\\fs%d ", -F.lf.lfHeight); AppendUnicodeToBuffer(buf, wszText); - buf.AppendChar('}'); return buf; } +CMStringA NSRtfProvider::CreateRtfFooter() +{ + return "}"; +} + /////////////////////////////////////////////////////////////////////////////// // Template formatting for copying text diff --git a/plugins/NewStory/src/templates.h b/plugins/NewStory/src/templates.h index 932f9dc437..1ad2deed48 100644 --- a/plugins/NewStory/src/templates.h +++ b/plugins/NewStory/src/templates.h @@ -71,9 +71,21 @@ extern TemplateInfo templates[TPL_COUNT]; void LoadTemplates(); void SaveTemplates(); -CMStringA TplFormatRtf(int tpl, MCONTACT hContact, ItemData *args); CMStringW TplFormatString(int tpl, MCONTACT hContact, ItemData *item); CMStringW TplFormatStringEx(int tpl, wchar_t *sztpl, ItemData *args); +class NSRtfProvider : public MRtfProvider +{ + ItemData *m_pItem; + +public: + NSRtfProvider(ItemData *pItem) : + m_pItem(pItem) + {} + + CMStringA CreateRtfHeader() override; + CMStringA CreateRtfBody() override; + CMStringA CreateRtfFooter() override; +}; #endif // __templates_h__
\ No newline at end of file |