HRESULT touchmind::control::DWriteEditControlTextStoreACP::Delete() { if (_IsLocked(TS_LF_READ)) { return S_OK; } _LockDocument(TS_LF_READWRITE); bool changed = false; TS_TEXTCHANGE ts; if (m_acpStart == m_acpEnd) { if (m_acpStart < (LONG)m_text.length()) { _Internal_RemoveText(m_acpStart, 1); ts.acpStart = m_acpStart; ts.acpOldEnd = m_acpStart + 1; ts.acpNewEnd = m_acpStart; changed = true; } } else { _Internal_RemoveText(m_acpStart, m_acpEnd - m_acpStart); ts.acpStart = m_acpStart; ts.acpOldEnd = m_acpEnd; ts.acpNewEnd = m_acpStart; changed = true; } if (changed) { m_AdviseSink.pTextStoreACPSink->OnTextChange(0, &ts); } _UnlockDocument(); m_AdviseSink.pTextStoreACPSink->OnLayoutChange(TS_LC_CHANGE, EDIT_VIEW_COOKIE); return S_OK; }
STDMETHODIMP touchmind::control::DWriteEditControlTextStoreACP::SetSelection(ULONG ulCount, const TS_SELECTION_ACP *pSelection) { if (nullptr == pSelection) { return E_INVALIDARG; } if (ulCount > 1) { return E_INVALIDARG; } if (!_IsLocked(TS_LF_READWRITE)) { return TS_E_NOLOCK; } m_acpStart = pSelection[0].acpStart; m_acpEnd = pSelection[0].acpEnd; m_fInterimChar = pSelection[0].style.fInterimChar; if (m_fInterimChar) { m_ActiveSelEnd = TS_AE_NONE; } else { m_ActiveSelEnd = pSelection[0].style.ase; } LONG lStart = m_acpStart; LONG lEnd = m_acpEnd; if (TS_AE_START == m_ActiveSelEnd) { lStart = m_acpEnd; lEnd = m_acpStart; } m_fNotify = TRUE; return S_OK; }
HRESULT touchmind::control::DWriteEditControlTextStoreACP::InsertTextAtACP(std::wstring &text) { if (_IsLocked(TS_LF_READ)) { return S_OK; } _LockDocument(TS_LF_READWRITE); bool changed = false; TS_TEXTCHANGE ts; if (m_acpStart == m_acpEnd) { _Internal_InsertText(m_acpStart, text); ts.acpStart = m_acpStart; ts.acpOldEnd = m_acpStart; ts.acpNewEnd = m_acpStart + static_cast<LONG>(text.length()); changed = true; m_acpStart = m_acpEnd = m_acpStart + 1; } else { _Internal_ReplaceText(m_acpStart, m_acpEnd - m_acpStart, text); ts.acpStart = m_acpStart; ts.acpOldEnd = m_acpEnd; ts.acpNewEnd = m_acpStart + static_cast<LONG>(text.length()); changed = true; m_acpStart = m_acpEnd = m_acpStart + static_cast<LONG>(text.length()); } if (changed) { m_AdviseSink.pTextStoreACPSink->OnTextChange(0, &ts); } _UnlockDocument(); m_AdviseSink.pTextStoreACPSink->OnLayoutChange(TS_LC_CHANGE, EDIT_VIEW_COOKIE); return S_OK; }
STDMETHODIMP touchmind::control::DWriteEditControlTextStoreACP::GetTextExt(TsViewCookie vcView, LONG acpStart, LONG acpEnd, RECT *prc, BOOL *pfClipped) { if (nullptr == prc || nullptr == pfClipped) { return E_INVALIDARG; } *pfClipped = FALSE; ZeroMemory(prc, sizeof(RECT)); if (EDIT_VIEW_COOKIE != vcView) { return E_INVALIDARG; } if (!_IsLocked(TS_LF_READ)) { return TS_E_NOLOCK; } UINT32 actualCount; std::shared_ptr<control::DWriteEditControl> editControl = m_pEditControl.lock(); if (editControl->GetTextLayout()->HitTestTextRange(acpStart, acpEnd - acpStart + 1, editControl->GetLayoutRect().left, editControl->GetLayoutRect().top, nullptr, 0, &actualCount) != E_NOT_SUFFICIENT_BUFFER) { return E_INVALIDARG; } std::vector<DWRITE_HIT_TEST_METRICS> hitTestMetrics(actualCount); editControl->GetTextLayout()->HitTestTextRange(acpStart, acpEnd - acpStart + 1, editControl->GetLayoutRect().left, editControl->GetLayoutRect().top, hitTestMetrics.data(), actualCount, &actualCount); if (actualCount > 0) { D2D1_POINT_2F p1; p1.x = hitTestMetrics[0].left; p1.y = hitTestMetrics[0].top; D2D1_POINT_2F p2; p2.x = (hitTestMetrics[0].left + hitTestMetrics[0].width); p2.y = (hitTestMetrics[0].top + hitTestMetrics[0].height); POINT pp1; touchmind::util::CoordinateConversion::ConvertModelToWindowCoordinate(m_hWnd, editControl->GetScrollBarHelper(), p1, &pp1); POINT pp2; touchmind::util::CoordinateConversion::ConvertModelToWindowCoordinate(m_hWnd, editControl->GetScrollBarHelper(), p2, &pp2); ClientToScreen(m_hWnd, &pp1); ClientToScreen(m_hWnd, &pp2); prc->left = pp1.x; prc->top = pp1.y; prc->right = pp2.x; prc->bottom = pp2.y; pfClipped = FALSE; } return S_OK; }
HRESULT touchmind::control::DWriteEditControlTextStoreACP::MoveACPToEnd() { if (_IsLocked(TS_LF_READ)) { return S_OK; } _LockDocument(TS_LF_READWRITE); LONG textLength = static_cast<LONG>(GetTextLength()); HRESULT hr = ChangeACPWithoutLock(textLength, textLength, TS_AE_START); _UnlockDocument(); m_AdviseSink.pTextStoreACPSink->OnLayoutChange(TS_LC_CHANGE, EDIT_VIEW_COOKIE); return hr; }
STDMETHODIMP touchmind::control::DWriteEditControlTextStoreACP::GetEndACP(LONG *pacp) { if (!_IsLocked(TS_LF_READWRITE)) { return TS_E_NOLOCK; } if (nullptr == pacp) { return E_INVALIDARG; } *pacp = static_cast<LONG>(m_text.length()); return S_OK; }
STDMETHODIMP touchmind::control::DWriteEditControlTextStoreACP::GetSelection(ULONG ulIndex, ULONG ulCount, TS_SELECTION_ACP *pSelection, ULONG *pcFetched) { UNREFERENCED_PARAMETER(ulCount); if (nullptr == pSelection) { return E_INVALIDARG; } if (nullptr == pcFetched) { return E_INVALIDARG; } *pcFetched = 0; if (!_IsLocked(TS_LF_READ)) { return TS_E_NOLOCK; } if (TF_DEFAULT_SELECTION == ulIndex) { ulIndex = 0; } else if (ulIndex > 1) { return E_INVALIDARG; } pSelection[0].acpStart = m_acpStart; pSelection[0].acpEnd = m_acpEnd; pSelection[0].style.fInterimChar = m_fInterimChar; if (m_fInterimChar) { pSelection[0].style.ase = TS_AE_NONE; } else { pSelection[0].style.ase = m_ActiveSelEnd; } *pcFetched = 1; return S_OK; }
STDMETHODIMP touchmind::control::DWriteEditControlTextStoreACP::InsertTextAtSelection(DWORD dwFlags, const WCHAR *pwszText, // null if cch is 0 ULONG cch, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange) { LONG lTemp; if (!_IsLocked(TS_LF_READWRITE)) { return TS_E_NOLOCK; } if (cch > 0L && nullptr == pwszText) { return E_POINTER; } if (nullptr == pacpStart) { pacpStart = &lTemp; } if (nullptr == pacpEnd) { pacpEnd = &lTemp; } LONG acpStart; LONG acpOldEnd; LONG acpNewEnd; _GetCurrentSelection(); acpOldEnd = m_acpEnd; HRESULT hr = _TestInsert(m_acpStart, m_acpEnd, cch, &acpStart, &acpNewEnd); if (FAILED(hr)) { return hr; } if (dwFlags & TS_IAS_QUERYONLY) { *pacpStart = acpStart; *pacpEnd = acpNewEnd; return S_OK; } m_fNotify = FALSE; std::wstring s(pwszText, cch); if ((acpOldEnd - acpStart > 0) && (acpNewEnd - acpStart > 0)) { _Internal_ReplaceText(acpStart, acpOldEnd - acpStart, s); } else if (acpOldEnd - acpStart > 0) { _Internal_RemoveText(acpStart, acpOldEnd - acpStart); } else if (acpNewEnd - acpStart > 0) { _Internal_InsertText(acpStart, s); } m_fNotify = TRUE; _GetCurrentSelection(); if (!(dwFlags & TS_IAS_NOQUERY)) { *pacpStart = acpStart; *pacpEnd = acpNewEnd; } pChange->acpStart = acpStart; pChange->acpOldEnd = acpOldEnd; pChange->acpNewEnd = acpNewEnd; m_fLayoutChanged = TRUE; Invalidate(); NotifySelectionHasChanged(); return S_OK; }
STDMETHODIMP touchmind::control::DWriteEditControlTextStoreACP::GetText( IN LONG acpStart, IN LONG acpEnd, OUT WCHAR *pchPlain, IN ULONG cchPlainReq, OUT ULONG *pcchPlainRet, OUT TS_RUNINFO *prgRunInfo, IN ULONG ulRunInfoReq, OUT ULONG *pulRunInfoOut, OUT LONG *pacpNext) { if (!_IsLocked(TS_LF_READ)) { return TS_E_NOLOCK; } BOOL fDoText = cchPlainReq > 0; BOOL fDoRunInfo = ulRunInfoReq > 0; LONG cchTotal; HRESULT hr = E_FAIL; if (pcchPlainRet) { *pcchPlainRet = 0; } if (fDoRunInfo) { *pulRunInfoOut = 0; } if (pacpNext) { *pacpNext = acpStart; } std::wstring text; _GetText(text, &cchTotal); if ((acpStart < 0) || (acpStart > cchTotal)) { hr = TS_E_INVALIDPOS; } else { if (acpStart == cchTotal) { hr = S_OK; } else { ULONG cchReq; if (acpEnd >= acpStart) { cchReq = acpEnd - acpStart; } else { cchReq = cchTotal - acpStart; } if (fDoText) { if (cchReq > cchPlainReq) { cchReq = cchPlainReq; } std::wstring substr = text.substr(acpStart, cchReq); if (pchPlain && cchPlainReq) { CopyMemory(pchPlain, substr.c_str(), cchReq * sizeof(WCHAR)); } } if (pcchPlainRet) { *pcchPlainRet = cchReq; } if (fDoRunInfo) { *pulRunInfoOut = 1; prgRunInfo[0].type = TS_RT_PLAIN; prgRunInfo[0].uCount = cchReq; } if (pacpNext) { *pacpNext = acpStart + cchReq; } hr = S_OK; } } return hr; }
void CTSFEditWnd::_Load(IStream *pStream) { if(NULL == pStream) { return; } //can't do this if someone has a lock if(_IsLocked(TS_LF_READ)) { return; } _ClearText(); HRESULT hr; ULONG uRead; LARGE_INTEGER li; ULONG uSize; //set the stream pointer to the start of the stream li.QuadPart = 0; pStream->Seek(li, STREAM_SEEK_SET, NULL); //get the size of the text, in BYTES. This is the first ULONG in the stream hr = pStream->Read(&uSize, sizeof(ULONG), &uRead); if(SUCCEEDED(hr) && (sizeof(ULONG) == uRead)) { LPWSTR pwsz; //allocate a buffer for the text plus one NULL character pwsz = (LPWSTR)GlobalAlloc(GPTR, uSize + sizeof(WCHAR)); if(NULL != pwsz) { //get the plain UNICODE text from the stream hr = pStream->Read(pwsz, uSize, &uRead); if(SUCCEEDED(hr) && (uSize == uRead)) { TF_PERSISTENT_PROPERTY_HEADER_ACP PropHeader; //put the text into the edit control, but don't send a change notification BOOL fOldNotify = m_fNotify; m_fNotify = FALSE; SetWindowTextW(m_hwndEdit, pwsz); m_fNotify = fOldNotify; /* Read each property header and property data from the stream. The list of properties is terminated by a TF_PERSISTENT_PROPERTY_HEADER_ACP structure with a cb member of zero. */ hr = pStream->Read(&PropHeader, sizeof(TF_PERSISTENT_PROPERTY_HEADER_ACP), &uRead); while( SUCCEEDED(hr) && (sizeof(TF_PERSISTENT_PROPERTY_HEADER_ACP) == uRead) && (0 != PropHeader.cb)) { ITfProperty *pProp; hr = m_pContext->GetProperty(PropHeader.guidType, &pProp); if(SUCCEEDED(hr)) { /* Have TSF read the property data from the stream. This call will request a read lock, so make sure it can be granted or else this method will fail. */ CTSFPersistentPropertyLoader *pLoader = new CTSFPersistentPropertyLoader(&PropHeader, pStream); hr = m_pServices->Unserialize(pProp, &PropHeader, NULL, pLoader); pProp->Release(); } hr = pStream->Read(&PropHeader, sizeof(TF_PERSISTENT_PROPERTY_HEADER_ACP), &uRead); } } GlobalFree(pwsz); } } }