diff options
Diffstat (limited to 'libs/mTextControl/src/FormattedTextDraw.cpp')
-rw-r--r-- | libs/mTextControl/src/FormattedTextDraw.cpp | 517 |
1 files changed, 517 insertions, 0 deletions
diff --git a/libs/mTextControl/src/FormattedTextDraw.cpp b/libs/mTextControl/src/FormattedTextDraw.cpp new file mode 100644 index 0000000000..eca1044a5c --- /dev/null +++ b/libs/mTextControl/src/FormattedTextDraw.cpp @@ -0,0 +1,517 @@ +// Feel free to use this code in your own applications. +// The Author does not guarantee anything about this code. +// Author : Yves Maurer + +// FormattedTextDraw.cpp : Implementation of CFormattedTextDraw + +#include "stdafx.h" +#include "FormattedTextDraw.h" + +const IID IID_ITextServices = { // 8d33f740-cf58-11ce-a89d-00aa006cadc5 + 0x8d33f740, + 0xcf58, + 0x11ce, + { 0xa8, 0x9d, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5 } +}; + +const IID IID_ITextHost = { // c5bdd8d0-d26e-11ce-a89e-00aa006cadc5 + 0xc5bdd8d0, + 0xd26e, + 0x11ce, + { 0xa8, 0x9e, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5 } +}; + +const IID IID_ITextDocument = { + 0x8CC497C0, + 0xA1DF, + 0x11CE, + { 0x80, 0x98, 0x00, 0xAA, 0x00, 0x47, 0xBE, 0x5D } +}; + +///////////////////////////////////////////////////////////////////////////// +// CallBack functions + +DWORD CALLBACK EditStreamInCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) +{ + COOKIE *pCookie = (COOKIE*)dwCookie; + if (pCookie->isUnicode) { + if ((pCookie->cbSize - pCookie->cbCount)*sizeof(WCHAR) < (size_t)cb) + *pcb = LONG(pCookie->cbSize - pCookie->cbCount)*sizeof(WCHAR); + else + *pcb = cb & ~1UL; + memcpy(pbBuff, pCookie->unicode + pCookie->cbCount, *pcb); + pCookie->cbCount += *pcb / sizeof(WCHAR); + } + else { + if (pCookie->cbSize - pCookie->cbCount < (DWORD)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 + +HRESULT CFormattedTextDraw::putRTFTextA(char *newVal) +{ + if (!m_spTextServices) + return S_FALSE; + + m_editCookie.isUnicode = false; + m_editCookie.ansi = newVal; + m_editCookie.cbSize = mir_strlen(m_editCookie.ansi); + m_editCookie.cbCount = 0; + + EDITSTREAM editStream; + editStream.dwCookie = (DWORD_PTR)&m_editCookie; + editStream.dwError = 0; + editStream.pfnCallback = (EDITSTREAMCALLBACK)EditStreamInCallback; + + LRESULT lResult = 0; + m_spTextServices->TxSendMessage(EM_STREAMIN, (WPARAM)(SF_RTF), (LPARAM)&editStream, &lResult); + return S_OK; +} + +HRESULT CFormattedTextDraw::putRTFTextW(WCHAR *newVal) +{ + if (!m_spTextServices) + return S_FALSE; + + m_editCookie.isUnicode = true; + m_editCookie.unicode = newVal; + m_editCookie.cbSize = mir_wstrlen(m_editCookie.unicode); + m_editCookie.cbCount = 0; + + EDITSTREAM editStream; + editStream.dwCookie = (DWORD_PTR)&m_editCookie; + editStream.dwError = 0; + editStream.pfnCallback = (EDITSTREAMCALLBACK)EditStreamInCallback; + + LRESULT lResult = 0; + m_spTextServices->TxSendMessage(EM_STREAMIN, (WPARAM)(SF_RTF | SF_UNICODE), (LPARAM)&editStream, &lResult); + return S_OK; + +} + +HRESULT CFormattedTextDraw::putTextA(char *newVal) +{ + if (!m_spTextServices) + return S_FALSE; + + m_editCookie.isUnicode = false; + m_editCookie.ansi = newVal; + m_editCookie.cbSize = mir_strlen(m_editCookie.ansi); + m_editCookie.cbCount = 0; + + EDITSTREAM editStream; + editStream.dwCookie = (DWORD_PTR)&m_editCookie; + editStream.dwError = 0; + editStream.pfnCallback = (EDITSTREAMCALLBACK)EditStreamInCallback; + + LRESULT lResult = 0; + m_spTextServices->TxSendMessage(EM_STREAMIN, (WPARAM)(SF_TEXT), (LPARAM)&editStream, &lResult); + + CHARFORMAT cf; + cf.cbSize = sizeof(cf); + cf.dwMask = CFM_FACE | CFM_BOLD; + cf.dwEffects = 0; + wcsncpy_s(cf.szFaceName, L"MS Shell Dlg", _TRUNCATE); + m_spTextServices->TxSendMessage(EM_SETCHARFORMAT, (WPARAM)(SCF_ALL), (LPARAM)&cf, &lResult); + + return S_OK; +} + +HRESULT CFormattedTextDraw::putTextW(WCHAR *newVal) +{ + if (!m_spTextServices) + return S_FALSE; + + m_editCookie.isUnicode = true; + m_editCookie.unicode = newVal; + m_editCookie.cbSize = mir_wstrlen(m_editCookie.unicode); + m_editCookie.cbCount = 0; + + EDITSTREAM editStream; + editStream.dwCookie = (DWORD_PTR)&m_editCookie; + editStream.dwError = 0; + editStream.pfnCallback = (EDITSTREAMCALLBACK)EditStreamInCallback; + + LRESULT lResult = 0; + m_spTextServices->TxSendMessage(EM_STREAMIN, (WPARAM)(SF_TEXT | SF_UNICODE), (LPARAM)&editStream, &lResult); + + CHARFORMAT cf; + cf.cbSize = sizeof(cf); + cf.dwMask = CFM_FACE | CFM_BOLD; + cf.dwEffects = 0; + wcsncpy_s(cf.szFaceName, L"MS Shell Dlg", _TRUNCATE); + m_spTextServices->TxSendMessage(EM_SETCHARFORMAT, (WPARAM)(SCF_ALL), (LPARAM)&cf, &lResult); + return S_OK; +} + +HRESULT CFormattedTextDraw::Draw(void *hdcDraw, RECT *prc) +{ + LOGFONT lf; + GetObject(GetCurrentObject((HDC)hdcDraw, OBJ_FONT), sizeof(lf), &lf); + + LRESULT lResult; + CHARFORMAT cf; + cf.cbSize = sizeof(cf); + cf.dwMask = CFM_FACE/*|CFM_COLOR*/ | CFM_CHARSET | CFM_SIZE | + (lf.lfWeight >= FW_BOLD ? CFM_BOLD : 0) | + (lf.lfItalic ? CFM_ITALIC : 0) | + (lf.lfUnderline ? CFM_UNDERLINE : 0) | + (lf.lfStrikeOut ? CFM_STRIKEOUT : 0); + cf.dwEffects = CFE_BOLD | CFE_ITALIC | CFE_STRIKEOUT | CFE_UNDERLINE; + cf.crTextColor = GetTextColor((HDC)hdcDraw); + cf.bCharSet = lf.lfCharSet; + cf.yHeight = 1440 * abs(lf.lfHeight) / GetDeviceCaps((HDC)hdcDraw, LOGPIXELSY); + wcsncpy_s(cf.szFaceName, lf.lfFaceName, _TRUNCATE); + m_spTextServices->TxSendMessage(EM_SETCHARFORMAT, (WPARAM)(SCF_ALL), (LPARAM)&cf, &lResult); + + m_spTextServices->TxDraw( + DVASPECT_CONTENT, // Draw Aspect + 0, // Lindex + nullptr, // Info for drawing optimization + nullptr, // target device information + (HDC)hdcDraw, // Draw device HDC + nullptr, // Target device HDC + (RECTL *)prc, // Bounding client rectangle + nullptr, // Clipping rectangle for metafiles + (RECT *)nullptr, // Update rectangle + nullptr, // Call back function + NULL, // Call back parameter + TXTVIEW_INACTIVE); // What view of the object could be TXTVIEW_ACTIVE + return S_OK; +} + +HRESULT CFormattedTextDraw::Create() +{ + return CreateTextServicesObject(); +} + +HRESULT CFormattedTextDraw::get_NaturalSize(void *hdcDraw, long *Width, long *Height) +{ + LOGFONT lf; + GetObject(GetCurrentObject((HDC)hdcDraw, OBJ_FONT), sizeof(lf), &lf); + + LRESULT lResult; + CHARFORMAT cf; + cf.cbSize = sizeof(cf); + cf.dwMask = CFM_FACE/*|CFM_COLOR*/ | CFM_CHARSET | CFM_SIZE | + (lf.lfWeight >= FW_BOLD ? CFM_BOLD : 0) | + (lf.lfItalic ? CFM_ITALIC : 0) | + (lf.lfUnderline ? CFM_UNDERLINE : 0) | + (lf.lfStrikeOut ? CFM_STRIKEOUT : 0); + cf.dwEffects = CFE_BOLD | CFE_ITALIC | CFE_STRIKEOUT | CFE_UNDERLINE; + cf.crTextColor = GetTextColor((HDC)hdcDraw); + cf.bCharSet = lf.lfCharSet; + cf.yHeight = 1440 * abs(lf.lfHeight) / GetDeviceCaps((HDC)hdcDraw, LOGPIXELSY); + wcsncpy_s(cf.szFaceName, lf.lfFaceName, _TRUNCATE); + + if (!m_spTextServices) + return S_FALSE; + + m_spTextServices->TxSendMessage(EM_SETCHARFORMAT, (WPARAM)(SCF_ALL), (LPARAM)&cf, &lResult); + + *Height = 1; + + SIZEL szExtent; + szExtent.cx = *Width; + szExtent.cy = *Height; + if (m_spTextServices->TxGetNaturalSize(DVASPECT_CONTENT, (HDC)hdcDraw, nullptr, nullptr, TXTNS_FITTOCONTENT, &szExtent, Width, Height) != S_OK) + return S_FALSE; + + return S_OK; +} + +///////////////////////////////////////////////////////////////////////////// +// ITextHost functions + +HDC CFormattedTextDraw::TxGetDC() +{ + return nullptr; +} + +INT CFormattedTextDraw::TxReleaseDC(HDC) +{ + return 1; +} + +BOOL CFormattedTextDraw::TxShowScrollBar(INT, BOOL) +{ + return FALSE; +} + +BOOL CFormattedTextDraw::TxEnableScrollBar(INT, INT) +{ + return FALSE; +} + +BOOL CFormattedTextDraw::TxSetScrollRange(INT, LONG, INT, BOOL) +{ + return FALSE; +} + +BOOL CFormattedTextDraw::TxSetScrollPos(INT, INT, BOOL) +{ + return FALSE; +} + +void CFormattedTextDraw::TxInvalidateRect(LPCRECT, BOOL) +{} + +void CFormattedTextDraw::TxViewChange(BOOL) +{} + +BOOL CFormattedTextDraw::TxCreateCaret(HBITMAP, INT, INT) +{ + return FALSE; +} + +BOOL CFormattedTextDraw::TxShowCaret(BOOL) +{ + return FALSE; +} + +BOOL CFormattedTextDraw::TxSetCaretPos(INT, INT) +{ + return FALSE; +} + +BOOL CFormattedTextDraw::TxSetTimer(UINT, UINT) +{ + return FALSE; +} + +void CFormattedTextDraw::TxKillTimer(UINT) +{ +} + +void CFormattedTextDraw::TxScrollWindowEx(INT, INT, LPCRECT, LPCRECT, HRGN, LPRECT, UINT) +{ +} + +void CFormattedTextDraw::TxSetCapture(BOOL) +{ +} + +void CFormattedTextDraw::TxSetFocus() +{ +} + +void CFormattedTextDraw::TxSetCursor(HCURSOR hcur, BOOL fText) +{ + if (fText) + SetCursor(LoadCursor(nullptr, MAKEINTRESOURCE(IDC_ARROW))); + else + SetCursor(hcur); +} + +BOOL CFormattedTextDraw::TxScreenToClient(LPPOINT lppt) +{ + if (!m_hwndParent) return FALSE; + return ScreenToClient(m_hwndParent, lppt); +} + +BOOL CFormattedTextDraw::TxClientToScreen(LPPOINT lppt) +{ + if (!m_hwndParent) return FALSE; + // BOOL result = ; + // lppt->x -= m_rcClient.left; + // lppt->y -= m_rcClient.left; + return ClientToScreen(m_hwndParent, lppt); +} + +HRESULT CFormattedTextDraw::TxActivate(LONG *) +{ + return S_OK; +} + +HRESULT CFormattedTextDraw::TxDeactivate(LONG) +{ + return S_OK; +} + +HRESULT CFormattedTextDraw::TxGetClientRect(LPRECT prc) +{ + *prc = m_rcClient; + return S_OK; +} + +HRESULT CFormattedTextDraw::TxGetViewInset(LPRECT prc) +{ + *prc = m_rcViewInset; + return S_OK; +} + +HRESULT CFormattedTextDraw::TxGetCharFormat(const CHARFORMATW **ppCF) +{ + *ppCF = m_pCF; + return S_OK; +} + +HRESULT CFormattedTextDraw::TxGetParaFormat(const PARAFORMAT **ppPF) +{ + *ppPF = &m_PF; + return S_OK; +} + +COLORREF CFormattedTextDraw::TxGetSysColor(int nIndex) +{ + return GetSysColor(nIndex); +} + +HRESULT CFormattedTextDraw::TxGetBackStyle(TXTBACKSTYLE *pstyle) +{ + *pstyle = TXTBACK_TRANSPARENT; + return S_OK; +} + +HRESULT CFormattedTextDraw::TxGetMaxLength(DWORD *plength) +{ + *plength = m_dwMaxLength; + return S_OK; +} + +HRESULT CFormattedTextDraw::TxGetScrollBars(DWORD *pdwScrollBar) +{ + *pdwScrollBar = m_dwScrollbar; + return S_OK; +} + +HRESULT CFormattedTextDraw::TxGetPasswordChar(wchar_t *) +{ + return S_FALSE; +} + +HRESULT CFormattedTextDraw::TxGetAcceleratorPos(LONG *pcp) +{ + *pcp = -1; + return S_OK; +} + +HRESULT CFormattedTextDraw::TxGetExtent(LPSIZEL) +{ + return E_NOTIMPL; +} + +HRESULT CFormattedTextDraw::OnTxCharFormatChange(const CHARFORMATW * pcf) +{ + memcpy(m_pCF, pcf, pcf->cbSize); + return S_OK; +} + +HRESULT CFormattedTextDraw::OnTxParaFormatChange(const PARAFORMAT * ppf) +{ + memcpy(&m_PF, ppf, ppf->cbSize); + return S_OK; +} + +HRESULT CFormattedTextDraw::TxGetPropertyBits(DWORD, DWORD *pdwBits) +{ + *pdwBits = m_dwPropertyBits; + return S_OK; +} + +HRESULT CFormattedTextDraw::TxNotify(DWORD, void *) +{ + return S_OK; +} + +HIMC CFormattedTextDraw::TxImmGetContext() +{ + return nullptr; +} + +void CFormattedTextDraw::TxImmReleaseContext(HIMC) +{} + +HRESULT CFormattedTextDraw::TxGetSelectionBarWidth(LONG *lSelBarWidth) +{ + *lSelBarWidth = 100; + return S_OK; +} + +///////////////////////////////////////////////////////////////////////////// +// custom functions + +HRESULT CFormattedTextDraw::CharFormatFromHFONT(CHARFORMAT2W* pCF, HFONT hFont) +// Takes an HFONT and fills in a CHARFORMAT2W structure with the corresponding info +{ + // Get LOGFONT for default font + if (!hFont) + hFont = (HFONT)GetStockObject(SYSTEM_FONT); + + // Get LOGFONT for passed hfont + LOGFONT lf; + if (!GetObject(hFont, sizeof(LOGFONT), &lf)) + return E_FAIL; + + // Set CHARFORMAT structure + memset(pCF, 0, sizeof(CHARFORMAT2W)); + pCF->cbSize = sizeof(CHARFORMAT2W); + + HWND hWnd = GetDesktopWindow(); + HDC hDC = GetDC(hWnd); + LONG yPixPerInch = GetDeviceCaps(hDC, LOGPIXELSY); + pCF->yHeight = -lf.lfHeight * LY_PER_INCH / yPixPerInch; + ReleaseDC(hWnd, hDC); + + pCF->yOffset = 0; + pCF->crTextColor = 0; + + pCF->dwEffects = CFM_EFFECTS | CFE_AUTOBACKCOLOR; + pCF->dwEffects &= ~(CFE_PROTECTED | CFE_LINK | CFE_AUTOCOLOR); + + if (lf.lfWeight < FW_BOLD) + pCF->dwEffects &= ~CFE_BOLD; + + if (!lf.lfItalic) + pCF->dwEffects &= ~CFE_ITALIC; + + if (!lf.lfUnderline) + pCF->dwEffects &= ~CFE_UNDERLINE; + + if (!lf.lfStrikeOut) + pCF->dwEffects &= ~CFE_STRIKEOUT; + + pCF->dwMask = CFM_ALL | CFM_BACKCOLOR | CFM_STYLE; + pCF->bCharSet = lf.lfCharSet; + pCF->bPitchAndFamily = lf.lfPitchAndFamily; + + mir_wstrcpy(pCF->szFaceName, lf.lfFaceName); + return S_OK; +} + +HRESULT CFormattedTextDraw::InitDefaultCharFormat() +{ + return CharFormatFromHFONT(m_pCF, nullptr); +} + +HRESULT CFormattedTextDraw::InitDefaultParaFormat() +{ + memset(&m_PF, 0, sizeof(PARAFORMAT2)); + m_PF.cbSize = sizeof(PARAFORMAT2); + m_PF.dwMask = PFM_ALL; + m_PF.wAlignment = PFA_LEFT; + m_PF.cTabCount = 1; + m_PF.rgxTabs[0] = lDefaultTab; + return S_OK; +} + +HRESULT CFormattedTextDraw::CreateTextServicesObject() +{ + IUnknown *spUnk; + HRESULT hr = MyCreateTextServices(nullptr, static_cast<ITextHost*>(this), &spUnk); + if (hr == S_OK) { + hr = spUnk->QueryInterface(IID_ITextServices, (void**)&m_spTextServices); + hr = spUnk->QueryInterface(IID_ITextDocument, (void**)&m_spTextDocument); + spUnk->Release(); + } + return hr; +} |