/*----------------------------------------------------------------------------------------------
	Generate the sort key as a BSTR
----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgUnicodeCollater::get_SortKey(BSTR bstrValue, LgCollatingOptions colopt,
	BSTR * pbstrKey)
{
	BEGIN_COM_METHOD
	ChkComBstrArg(bstrValue);
	ChkComOutPtr(pbstrKey);

	HRESULT hr;
	int cchw;
	*pbstrKey = NULL;
	// Passing 0 and null just produces a length
	IgnoreHr(hr = SortKeyRgch(bstrValue, BstrLen(bstrValue), colopt, 0, NULL, &cchw));
	if (FAILED(hr))
		return hr;

	BSTR bstrOut;
	bstrOut = SysAllocStringLen(NULL, cchw);
	if (!bstrOut)
		return E_OUTOFMEMORY;
	IgnoreHr(hr = SortKeyRgch(bstrValue, BstrLen(bstrValue), colopt, cchw, bstrOut, &cchw));
	if (FAILED(hr))
	{
		SysFreeString(bstrOut);
		return hr;
	}
	*pbstrKey = bstrOut;
	END_COM_METHOD(g_fact, IID_ILgCollatingEngine);
}
Beispiel #2
0
/*----------------------------------------------------------------------------------------------
	Convert the Graphite character offset to the decomposed NFD
	character offset used internally by views code.
----------------------------------------------------------------------------------------------*/
int FwGrTxtSrc::GrToVwOffset(int grOffset)
{
	if (!m_useNFC)
	{
		// the Graphite offset is a NFD offset
		return grOffset;
	}
	else
	{
		// convert NFC offsets to internal NFD offsets
		if (grOffset == 0)
			return 0;

		HRESULT hr;
		int cch;
		IgnoreHr(hr = m_qts->get_Length(&cch));
		if (FAILED(hr))
			throw;

		if (grOffset > cch)
			// grOffset points beyond the available text, i.e. is invalid.
			return cch + 10; // arbitrary number that is bigger than NFD text

		StrUni stuNfd;
		wchar_t* pchNfd;
		stuNfd.SetSize(cch + 1, &pchNfd);
		IgnoreHr(hr = m_qts->Fetch(0, cch, pchNfd));
		if (FAILED(hr))
			throw;
		pchNfd[cch] = '\0';

		wchar_t szOut[kNFDBufferSize];
		UCharIterator iter;
		uiter_setString(&iter, pchNfd, -1);
		int curGrOffset = 0;
		while (iter.hasNext(&iter))
		{
			int index = iter.getIndex(&iter, UITER_CURRENT);
			if (curGrOffset >= grOffset)
				return index;
			UBool neededToNormalize;
			UErrorCode uerr = U_ZERO_ERROR;
			int outLen = unorm_next(&iter, szOut, kNFDBufferSize, UNORM_NFC, 0, TRUE, &neededToNormalize, &uerr);
			Assert(U_SUCCESS(uerr));
			curGrOffset++;
			for (int i = 1; i < outLen; i++)
			{
				if (curGrOffset >= grOffset)
					return index + i;
				curGrOffset++;
			}
		}
		return iter.getIndex(&iter, UITER_CURRENT);
	}
}
Beispiel #3
0
int FwGrTxtSrc::VwToGrOffset(int vwOffset, bool& badOffset)
{
	badOffset = false;
	if (!m_useNFC)
	{
		// the NFD offset is a Graphite offset
		return vwOffset;
	}
	else
	{
		// convert internal NFD offsets to NFC offsets
		if (vwOffset == 0)
			return 0;

		HRESULT hr;
		int cch;
		IgnoreHr(hr = m_qts->get_Length(&cch));
		if (FAILED(hr))
			throw;
		if (vwOffset > cch)
			return vwOffset;

		StrUni stuNfd;
		wchar_t* pchNfd;
		stuNfd.SetSize(cch + 1, &pchNfd);
		IgnoreHr(hr = m_qts->Fetch(0, cch, pchNfd));
		if (FAILED(hr))
			throw;
		pchNfd[cch] = '\0';

		wchar_t szOut[kNFDBufferSize];
		UCharIterator iter;
		uiter_setString(&iter, pchNfd, -1);
		int curGrOffset = 0;
		while (iter.hasNext(&iter))
		{
			int index = iter.getIndex(&iter, UITER_CURRENT);
			UBool neededToNormalize;
			UErrorCode uerr = U_ZERO_ERROR;
			int outLen = unorm_next(&iter, szOut, kNFDBufferSize, UNORM_NFC, 0, TRUE, &neededToNormalize, &uerr);
			Assert(U_SUCCESS(uerr));
			for (int i = 0; i < outLen; i++)
			{
				if (index + i + 1 > vwOffset)
					return curGrOffset;
				curGrOffset++;
			}
			if (neededToNormalize && iter.getIndex(&iter, UITER_CURRENT) > vwOffset)
				badOffset = true;
		}
		return curGrOffset;
	}
}
Beispiel #4
0
/*----------------------------------------------------------------------------------------------
	Calls the Redo method on the action handlers. If fForDataChange is true, this will be done
	on all action handlers that change the data, if fForDataChange is false this will be done
	on all action handlers that don't change the data.
----------------------------------------------------------------------------------------------*/
HRESULT ActionHandler::CallRedo(UndoResult * pures, bool fForDataChange, int iSeqToRedo, int iLastRedoAct)
{
	HRESULT hr = S_OK;

	for (int i = m_viSeqStart[iSeqToRedo]; i <= iLastRedoAct; i++)
	{
		ComBool f;
		CheckHr(m_vquact[i]->get_IsDataChange(&f));
		if (f == fForDataChange)
		{
			ComBool fSuccess = false;
			IgnoreHr(hr = m_vquact[i]->Redo(&fSuccess));
			if (FAILED(hr))
			{
				// we no longer want to continue the chain of actions as one failed catastrophically
				*pures = kuresError;
				return hr;
			}
			if (!fSuccess)
			{
				// we no longer want to continue the chain of actions as one failed (typically because
				// something else changed the data it was trying to fix).
				*pures = kuresFailed;
				break;
			}
		}
	}
	return S_OK;
}
Beispiel #5
0
/*----------------------------------------------------------------------------------------------
	Calls the Undo method on the action handlers. If fForDataChange is true, this will be done
	on all action handlers that change the data, if fForDataChange is false this will be done
	on all action handlers that don't change the data.
----------------------------------------------------------------------------------------------*/
HRESULT ActionHandler::CallUndo(UndoResult * pures, bool & fRedoable, bool fForDataChange)
{
	HRESULT hr = S_OK;

	for (int i = m_iuactCurr; (m_iCurrSeq >= 0) && (i >= m_viSeqStart[m_iCurrSeq]); i--)
	{
		ComBool fDataChange;
		ComBool fThisIsRedoable;
		IUndoActionPtr quact = m_vquact[i];
		CheckHr(quact->get_IsDataChange(&fDataChange));
		CheckHr(quact->get_IsRedoable(&fThisIsRedoable));
		fRedoable &= fThisIsRedoable;
		if (fDataChange == fForDataChange)
		{
			ComBool fSuccess = false;
			IgnoreHr(hr = quact->Undo(&fSuccess));
			if (FAILED(hr))
			{
				// Undo() failed. We no longer want to continue the chain of actions as one failed
				// catastrophically.
				*pures = kuresError;
				return hr;
			}
			if (!fSuccess)
			{
				// we no longer want to continue the chain of actions as one failed (typically because
				// something else changed the data it was trying to fix).
				*pures = kuresFailed;
				break;
			}
		}
	}

	return S_OK;
}
/*----------------------------------------------------------------------------------------------
	Do a direct string comparison.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgUnicodeCollater::Compare(BSTR bstrValue1, BSTR bstrValue2,
	LgCollatingOptions colopt, int * pnVal)
{
	BEGIN_COM_METHOD
	ChkComBstrArg(bstrValue1);
	ChkComBstrArg(bstrValue2);
	ChkComOutPtr(pnVal);

	HRESULT hr;

	int cchw1;
	int cchw2;

	IgnoreHr(hr = SortKeyRgch(bstrValue1, BstrLen(bstrValue1), colopt, 0, NULL, &cchw1));
	if (FAILED(hr))
		return hr;
	IgnoreHr(hr = SortKeyRgch(bstrValue2, BstrLen(bstrValue2), colopt, 0, NULL, &cchw2));
	if (FAILED(hr))
		return hr;

	OLECHAR * pchKey1 = (OLECHAR *) _alloca(cchw1 * isizeof(OLECHAR));
	OLECHAR * pchKey2 = (OLECHAR *) _alloca(cchw2 * isizeof(OLECHAR));

	IgnoreHr(hr = SortKeyRgch(bstrValue1, BstrLen(bstrValue1), colopt, cchw1, pchKey1, &cchw1));
	if (FAILED(hr))
		return hr;
	IgnoreHr(hr = SortKeyRgch(bstrValue2, BstrLen(bstrValue2), colopt, cchw2, pchKey2, &cchw2));
	if (FAILED(hr))
		return hr;
	int nVal = u_strncmp(pchKey1, pchKey2, min(cchw1, cchw2));
	if (!nVal)
	{
		// equal as far as length of shortest key
		if (BstrLen(bstrValue1) < BstrLen(bstrValue2))
			nVal = -1;
		else if (BstrLen(bstrValue1) > BstrLen(bstrValue2))
			nVal = 1;
	}
	*pnVal = nVal;
	END_COM_METHOD(g_fact, IID_ILgCollatingEngine);
}
Beispiel #7
0
DEFINE_THIS_FILE

//:>********************************************************************************************
//:>	FwGrTxtSrc
//:>********************************************************************************************

size_t FwGrTxtSrc::fetch(toffset ichMin, size_t cch, gr::utf16 * prgchwBuffer)
{
	HRESULT hr;
	int cchLen;
	IgnoreHr(hr = (gr::GrResult)m_qts->get_Length(&cchLen));
	if (FAILED(hr))
		throw;

	if (!m_useNFC)
	{
		int cchGet = min(cch, cchLen - ichMin);
		IgnoreHr(hr = (gr::GrResult)m_qts->Fetch(ichMin, ichMin + cchGet, (OLECHAR*)prgchwBuffer));
		if (FAILED(hr))
			throw;
		return cchGet;
	}
	else
	{
		int vwIchMin = GrToVwOffset(ichMin);
		int len = cchLen - vwIchMin;
		wchar_t* pchNfd;
		StrUni stuText;
		stuText.SetSize(len + 1, &pchNfd);
		IgnoreHr(hr = (gr::GrResult)m_qts->Fetch(vwIchMin, vwIchMin + len, pchNfd));
		if (FAILED(hr))
			throw;
		pchNfd[len] = '\0';
		stuText.SetSize(len, &pchNfd);
		StrUtil::NormalizeStrUni(stuText, UNORM_NFC);
		int cchGet = min((int) cch, stuText.Length());
		wcsncpy((wchar_t*) prgchwBuffer, stuText.Chars(), cchGet);
		return cchGet;
	}
}
Beispiel #8
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#Commit}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::Commit()
{
	BEGIN_COM_METHOD;

	HRESULT hr = E_FAIL;
	HRESULT hrFinal = S_OK;
	if (m_vquact.Size())
	{
		// JohnT 10/22/01: this can happen, typically if the only thing in the sequence is a
		// position mark. We could try to check for that but it doesn't seem worth it. Nothing
		// actually depends on having at least one sequence start here.
		//Assert(m_viSeqStart.Size() > 0);

		// Commit all actions.
		for (int i = 0; i <= m_iuactCurr; i++)
		{
			// If for some reason, we cannot commit an action that is part of a sequence, it's
			// just too bad.  We can't undo a commited action so we might as well just amble on
			// and hope for the best.
			IgnoreHr(hr = m_vquact[i]->Commit());
			if (FAILED(hr))
			{
				hrFinal = hr;
			}
		}

		EmptyStack();
	}

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("Commit:");
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	return hrFinal;

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Beispiel #9
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#Redo}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::Redo(UndoResult * pures)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pures);

	*pures = kuresSuccess;
	// Do not allow actions to be redone if they have not been undone.
	Assert(m_viSeqStart.Size() > 0);
	Assert(m_iCurrSeq <= m_viSeqStart.Size() - 1);

	m_fCanContinueTask = false; // Can't 'continue' the previous task from before the Undo.
	m_fUndoOrRedoInProgress = true;
	HRESULT hrFinal = S_OK;
	int iSeqToRedo = m_iCurrSeq + 1;

	try // to ensure in progress gets cleared.
	{
		int handle;
		// Start a 'transaction' if possible to group together all the stuff we're going to Undo.
		if (m_qundg)
		{
			m_qundg->BeginGroup(&handle);
		}

		// Determine the last action to be redone; The last action to redo is the action
		// before the next redo sequence. Or the last existing action if there is not a
		// redo sequence after the sequence we are about to redo.
		int iLastRedoAct = m_vquact.Size() - 1;
		if (iSeqToRedo <= m_viSeqStart.Size() - 2)
			iLastRedoAct = m_viSeqStart[iSeqToRedo + 1] - 1;

		// Loop through all of the actions that are about to be redone and see if any of them
		// require a refresh.
		for (int i = m_viSeqStart[iSeqToRedo]; i <= iLastRedoAct; i++)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(true));
		}

		// Redo all the actions in the next action sequence that change data.
		hrFinal = CallRedo(pures, true, iSeqToRedo, iLastRedoAct);

		// Now do all the PropChangeds
		for (int i = m_viSeqStart[iSeqToRedo]; i <= iLastRedoAct; i++)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(false));
		}

		// REVIEW (TimS/EberhardB): What do we do if the call to CallRedo above failed somewhere?
		// Should we do this at all? Or just until the failed action? Or everything?
		UndoResult uresTmp = kuresSuccess;
		// Redo all the actions in the next action sequence that don't change data.
		HRESULT hr;
		IgnoreHr(hr = CallRedo(&uresTmp, false, iSeqToRedo, iLastRedoAct));
		if (FAILED(hr))
		{
			hrFinal = hr;
			*pures = uresTmp;
		}
		else if (uresTmp == kuresFailed)
		{
			*pures = uresTmp;
		}

		// dlh testing
		if (*pures == kuresError || * pures == kuresFailed)
		{
			if (m_qundg)
				m_qundg->CancelGroup(handle);
			EmptyStack();
		}
		else // normal success case
		{
			// Set the current sequence and action.
			m_iCurrSeq++;
			m_iuactCurr = m_vquact.Size() - 1;
			if (m_iCurrSeq < m_viSeqStart.Size() - 1)
			{
				m_iuactCurr = m_viSeqStart[m_iCurrSeq + 1] - 1;
			}
			if (m_qundg)
				m_qundg->EndGroup(handle);
		}


#ifdef DEBUG_ACTION_HANDLER
		StrAnsi sta;
		sta.Format("Redo:");
		sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
			m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
		::OutputDebugStringA(sta.Chars());
#endif //DEBUG_ACTION_HANDLER
	}
	catch(...)
	{
		m_fUndoOrRedoInProgress = false;
		throw;
	}
	m_fUndoOrRedoInProgress = false;

	return hrFinal;

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Beispiel #10
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#Undo}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::Undo(UndoResult * pures)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pures);

	*pures = kuresSuccess;

	Assert(m_iCurrSeq >= 0);
	Assert(m_vquact.Size() > 0);

	HRESULT hr = E_FAIL;
	HRESULT hrFinal = S_OK;

	m_fCanContinueTask = false; // Can't 'continue' the previous task from before the Undo.
	m_fUndoOrRedoInProgress = true;

	try // to ensure in progress gets cleared.
	{
		int handle;
		// Start a 'transaction' if possible to group together all the stuff we're going to Undo.
		if (m_qundg)
		{
			m_qundg->BeginGroup(&handle);
		}

		// Loop through all of the actions that are about to be undone and see if any of them
		// require a refresh.
		Vector<long> vhvoCreatedObjects;
		for (int i = m_iuactCurr; (m_iCurrSeq >= 0) && (i >= m_viSeqStart[m_iCurrSeq]); i--)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(true));
		}

		// Undo all actions from the current action back to the first action of the current action
		// sequence.
		bool fRedoable = true;
		IgnoreHr(hrFinal = CallUndo(pures, fRedoable, true));

		// Now do all the PropChangeds
		for (int i = m_iuactCurr; (m_iCurrSeq >= 0) && (i >= m_viSeqStart[m_iCurrSeq]); i--)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(false));
		}

		// REVIEW (TimS/EberhardB): What do we do if the call to CallUndo above failed somewhere?
		// Should we do this at all? Or just until the failed action? Or everything?
		UndoResult uresTmp;
		IgnoreHr(hr = CallUndo(&uresTmp, fRedoable, false));
		if (FAILED(hr))
		{
			hrFinal = hr;
			*pures = uresTmp;
		}
		else if (uresTmp == kuresFailed)
		{
			*pures = uresTmp;
		}

		// dlh testing
		if (*pures == kuresError || * pures == kuresFailed)
		{
			if (m_qundg)
				m_qundg->CancelGroup(handle);
			EmptyStack();
		}
		else // normal success case
		{
			// Set the current action and start of the current action sequence.
			if (m_iCurrSeq >= 0)
			{
				m_iuactCurr = m_viSeqStart[m_iCurrSeq] - 1;
				m_iCurrSeq = m_iCurrSeq - 1;
			}
			if (m_qundg)
				m_qundg->EndGroup(handle);
		}

		// Delete any marks that now point after current undo action
		CleanUpMarks();

		if (!fRedoable)
			CleanUpRedoActions(true);

#ifdef DEBUG_ACTION_HANDLER
		StrAnsi sta;
		sta.Format("Undo:");
		sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
			m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
		::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER
	}
	catch(...)
	{
		CleanUpMarks();
		m_fUndoOrRedoInProgress = false;
		throw;
	}
	m_fUndoOrRedoInProgress = false;

	return hrFinal;

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Beispiel #11
0
/*----------------------------------------------------------------------------------------------
	This processes Windows messages on the window. In general, it normally calls the
	appropriate method on the edit class.
----------------------------------------------------------------------------------------------*/
bool TssEdit::FWndProc(uint wm, WPARAM wp, LPARAM lp, long & lnRet)
{
	bool fRet;

	switch (wm)
	{
	case WM_GETDLGCODE:
		// This is essential when embedded in a dialog to tell the dialog manager that it
		// wants to get key strokes. (We could try DLGC_WANTALLKEYS but I think we would then
		// get the Tab and Return keys...we may get them anyway with this combination...)
		// The last value tells Windows that when tabbing to this control we should use
		// EM_SETSEL to select all the text.
		lnRet = DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL;
		return true;
	case EM_GETLINE:	// Use FW_EM_GETLINE.
	case EM_REPLACESEL:	// Use FW_EM_REPLACESEL.
		// We don't support these methods. Use the replacement TsString versions instead.
		Assert(false);
		lnRet = LB_ERR;
		return true;

	// NOTE: DO NOT send this message to a TssEdit if you want the actual text. Send the
	// FW_EM_GETTEXT message instead. This method is required for TssEdit controls on a
	// dialog because Windows will send the message to the control anytime the user hits a
	// key.
	case WM_GETTEXT:
		{
			ITsStringPtr qtss;
			GetText(&qtss);
			const wchar * pwrgch;
			int cch;
			HRESULT hr;
			IgnoreHr(hr = qtss->LockText(&pwrgch, &cch));
			if (FAILED(hr))
				return true;
			StrApp str(pwrgch, cch);
			qtss->UnlockText(pwrgch);
			lnRet = Min(cch + 1, (int)wp);
			achar * psz = reinterpret_cast<achar *>(lp);
			StrCpyN(psz, str.Chars(), lnRet);
		}
		return true;

	// NOTE: You should be sending an FW_EM_SETTEXT message instead of this.
	case WM_SETTEXT:
		{
			achar * psz = reinterpret_cast<achar *>(lp);
			StrUni stu(psz);
			ITsStrFactoryPtr qtsf;
			qtsf.CreateInstance(CLSID_TsStrFactory);
			ITsStringPtr qtss;
			CheckHr(qtsf->MakeStringRgch(stu.Chars(), stu.Length(), m_wsBase, &qtss));
			SetText(qtss);
		}
		return true;

	case EM_CANUNDO:
	case EM_CHARFROMPOS:
	case EM_EMPTYUNDOBUFFER:
	case EM_FMTLINES:
	case EM_GETFIRSTVISIBLELINE:
	case EM_GETHANDLE:
	case EM_GETMODIFY:
	case EM_GETPASSWORDCHAR:
	case EM_GETRECT:
	case EM_GETTHUMB:
	case EM_GETWORDBREAKPROC:
	case EM_POSFROMCHAR:
	case EM_SETHANDLE:
	case EM_SETMODIFY:
	case EM_SETPASSWORDCHAR:
	case EM_SETRECT:
	case EM_SETRECTNP:
	case EM_SETTABSTOPS:
	case EM_SETWORDBREAKPROC:
	case EM_UNDO:
	case WM_GETFONT:
	case WM_SETFONT:
		// We don't support these methods.
		Assert(false);
		lnRet = LB_ERR;
		return true;

	case EM_GETLIMITTEXT:
		lnRet = GetLimitText();
		return true;

	case FW_EM_GETLINE:
		lnRet = GetLine(wp, (ITsString **)lp);
		return true;

	case EM_GETLINECOUNT:
		lnRet = GetLineCount();
		return true;

	case EM_GETMARGINS:
		lnRet = GetMargins();
		return true;

	case FW_EM_GETSTYLE:
		GetStyle((StrUni *)lp, (COLORREF *)wp);
		return true;

	case EM_GETSEL:
		lnRet = GetSel((int *)wp, (int *)lp);
		return true;

	case EM_LINEFROMCHAR:
		lnRet = LineFromChar(wp);
		return true;

	case EM_LINEINDEX:
		lnRet = LineIndex(wp);
		return true;

	case EM_LINELENGTH:
		lnRet = LineLength(wp);
		return true;

	case EM_LINESCROLL:
		LineScroll(lp, wp);
		return true;

	case FW_EM_REPLACESEL:
		ReplaceSel((ITsString *)lp);
		return true;

	case EM_SCROLL:
		lnRet = ::SendMessage(m_hwnd, WM_VSCROLL, LOWORD(wp), 0);
		return true;

	case EM_SCROLLCARET:
		ScrollCaret();
		return true;

	case EM_SETLIMITTEXT:
		SetLimitText(wp);
		return true;

	case EM_SETMARGINS:
		SetMargins(wp, LOWORD(lp), HIWORD(lp));
		return true;

	case EM_SETREADONLY:
		SetReadOnly(wp);
		return true;

	case EM_SETSEL:
		SetSel(wp, lp);
		return true;

	case FW_EM_SETSTYLE:
		SetStyle((StrUni *)lp, (COLORREF)wp);
		return true;

	case WM_GETTEXTLENGTH:
		lnRet = GetTextLength();
		return true;

	case FW_EM_GETTEXT:
		GetText((ITsString **)lp);
		return true;

	case FW_EM_SETTEXT:
		SetText((ITsString *)lp);
		return true;

	case WM_COPY:
		Copy();
		return true;

	case WM_CUT:
		Cut();
		return true;

	case WM_PASTE:
		Paste();
		return true;

	case WM_HSCROLL:
		if (!OnHScroll(LOWORD(wp), HIWORD(wp), (HWND)lp))
		{
			::SendMessage(::GetParent(m_hwnd), WM_COMMAND,
				MAKEWPARAM(::GetDlgCtrlID(m_hwnd), EN_HSCROLL), (LPARAM)m_hwnd);
		}
		return true;

	case WM_VSCROLL:
		if (!OnVScroll(LOWORD(wp), HIWORD(wp), (HWND)lp))
		{
			::SendMessage(::GetParent(m_hwnd), WM_COMMAND,
				MAKEWPARAM(::GetDlgCtrlID(m_hwnd), EN_VSCROLL), (LPARAM)m_hwnd);
		}
		return true;

	case WM_KILLFOCUS:
		if (!OnKillFocus((HWND)wp))
		{
			::SendMessage(::GetParent(m_hwnd), WM_COMMAND,
				MAKEWPARAM(::GetDlgCtrlID(m_hwnd), EN_KILLFOCUS), (LPARAM)m_hwnd);
		}
		return true;

	case WM_SETFOCUS:
		if (!OnSetFocus((HWND)wp))
		{
			::SendMessage(::GetParent(m_hwnd), WM_COMMAND,
				MAKEWPARAM(::GetDlgCtrlID(m_hwnd), EN_SETFOCUS), (LPARAM)m_hwnd);
		}
		return true;
		// Calling SuperClass here causes two OnSetFocus calls for each OnKillFocus.
		//return SuperClass::FWndProc(wm, wp, lp, lnRet);

	case WM_CHAR:
		fRet = false;
		if (wp == VK_TAB)  // '\t'
		{
			fRet = OnCharTab();
		}
		else if (wp == VK_RETURN) // '\r'
		{
			fRet = OnCharEnter();
		}
		else if (wp == VK_ESCAPE) // '\33'
		{
			fRet = OnCharEscape();
		}
		if (fRet)
			return fRet;
		else
			return SuperClass::FWndProc(wm, wp, lp, lnRet);

	case WM_LBUTTONDOWN:
	case WM_LBUTTONUP:
	case WM_MBUTTONDOWN:
	case WM_MBUTTONUP:
	case WM_RBUTTONDOWN:
	case WM_RBUTTONUP:
	case WM_MOUSEMOVE:
		if (HasToolTip())
		{
			// Notify the tooltip belonging to the parent toolbar of the mouse message.
			Assert(m_hwndToolTip);
			MSG msg;
			msg.hwnd = m_hwnd; // ::GetParent(m_hwnd);
			msg.message = wm;
			msg.wParam = wp;
			msg.lParam = lp;
			::SendMessage(m_hwndToolTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
		}
		break;

	default:
		break;
	}
	return SuperClass::FWndProc(wm, wp, lp, lnRet);
}
Beispiel #12
0
/*----------------------------------------------------------------------------------------------
	Set the keyboard through TSF
----------------------------------------------------------------------------------------------*/
bool SetKeyboard_TSF(bool fDoingKeyman, int lcid, int * pnActiveLangId)
{
#ifdef Tracing_KeybdSelection
	StrAnsi sta;
	sta.Format("LgTextServices::SetKeyboard(%d) [making TSF calls]%n", lcid);
	::OutputDebugStringA(sta.Chars());
	sta.Format("LgTextServices::SetKeyboard(%d) - ::GetKeyboardLayout() = %x%n",
		lcid, ::GetKeyboardLayout(0));
	::OutputDebugStringA(sta.Chars());
#endif
	HRESULT hr = S_OK;
	ITfInputProcessorProfilesPtr qtfipp;
	int nLangId = LANGIDFROMLCID(lcid);
	bool fSetInputLang = false;
	// Don't check the HR or use CreateInstance; I (JohnT) think this may fail if TSF is not
	// fully active.
	::CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_ALL,
		IID_ITfInputProcessorProfiles, (void **)&qtfipp);
	if (!qtfipp)
	{
		Warn("Could not get ITfInputProcessorProfiles to set Keyman text service\n");
	}
	else
	{
		// Have to make the language active before we can set the profile;
		// and want to set the language even if we aren't doing Keyman.
		if (*pnActiveLangId != (LANGID)nLangId)
		{
			// Do NOT do this if the right langID is already current. In some bizarre cases
			// during WM_INPUTLANGCHANGED it can lead to a new input-lang-changed in a
			// DIFFERENT language and an infinite loop.
			*pnActiveLangId = (LANGID)nLangId;
			IgnoreHr(hr = qtfipp->ChangeCurrentLanguage((LANGID)nLangId));
		}
#ifdef Tracing_KeybdSelection
		sta.Format(
			"LgTextServices::SetKeyboard(%d) [qtfipp->ChangeCL(%d) => hr = %x]%n",
			lcid, nLangId, hr);
		::OutputDebugStringA(sta.Chars());
#endif
		if (FAILED(hr))
		{
			Warn("failed to change language\n");
		}
		else if (fDoingKeyman)
		{
			// Make sure the Keyman text service is turned on. For some bizarre reason there is
			// no API to just ask for the service to turn on for the langid, we have to do our
			// own search for the profile that corresponds to this langid and text service.
			IEnumTfLanguageProfilesPtr qenum;
	#ifdef Tracing_KeybdSelection
			sta.Format("LgTextServices::SetKeyboard(%d) [qtfipp->EnumLP(%d)]%n",
				lcid, nLangId);
			::OutputDebugStringA(sta.Chars());
			sta.Format("LgTextServices::SetKeyboard(%d) - ::GetKeyboardLayout() = %x%n",
				lcid, ::GetKeyboardLayout(0));
			::OutputDebugStringA(sta.Chars());
	#endif
			IgnoreHr(hr = qtfipp->EnumLanguageProfiles((LANGID)nLangId, &qenum));
			if (FAILED(hr))
			{
				Warn("Could not get enumerator for language profiles\n");
			}
			else
			{
				// If doing keyman try to turn on Keyman text service.
				TF_LANGUAGEPROFILE profile;
				for ( ; ; )
				{
					ULONG cprofile;
					IgnoreHr(hr = qenum->Next(1, &profile, &cprofile));
					if (FAILED(hr) || cprofile != 1)
					{
						Warn("failed to find language profiled for Keyman\n");
						break;
					}
					if (kclsidKMTipTextService == profile.clsid)
					{
						// got it at last!
#ifdef Tracing_KeybdSelection
						StrAnsi sta;
						sta.Format("LgTextServices::SetKeyboard(%d) - "
							"qtfipp->ActivateLanguageProfile(nLangId = %d)\n",
							lcid, nLangId);
						::OutputDebugStringA(sta.Chars());
#endif
						IgnoreHr(hr = qtfipp->ActivateLanguageProfile(
							kclsidKMTipTextService, (LANGID)nLangId, profile.guidProfile));
						if (FAILED(hr))
						{
							Warn("failed to activate language profile\n");
						}
						else
						{
							fSetInputLang = true;
						}
						break;
					}
				}
			}
#ifdef Tracing_KeybdSelection
			sta.Format("LgTextServices::SetKeyboard(%d) [after qtfipp->ChangeCL(%d)]%n",
				lcid, nLangId);
			::OutputDebugStringA(sta.Chars());
			sta.Format("LgTextServices::SetKeyboard(%d) - ::GetKeyboardLayout() = %x%n",
				lcid, ::GetKeyboardLayout(0));
			::OutputDebugStringA(sta.Chars());
#endif
		}
		else
		{
			// We're not doing keyman, but we already set the input language.
			fSetInputLang = true;
		}
	}
	return fSetInputLang;
}