Пример #1
0
/*----------------------------------------------------------------------------------------------
	Do a direct string comparison.
	Note that, contrary to what the contract implies, this routine is not more
	efficient than the client just retrieving the keys and comparing them.
	OPTIMIZE: would we benefit significantly by implementing this using CompareString?
	Unfortunately, it is hard to avoid the need to do the WideCharToMultiByte conversion
	for the whole of both strings...
----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgIcuCollator::Compare(BSTR bstrValue1, BSTR bstrValue2,
	LgCollatingOptions colopt, int * pnVal)
{
	BEGIN_COM_METHOD
	ChkComBstrArgN(bstrValue1);
	ChkComBstrArgN(bstrValue2);
	ChkComOutPtr(pnVal);

	EnsureCollator();

	int32_t cbKey1 = keySize;
	byte rgbKey1[keySize+1];
	Vector<byte> vbKey1;
	byte * pbKey1 = GetSortKey(bstrValue1, rgbKey1, &cbKey1, vbKey1);

	int32_t cbKey2 = keySize;
	byte rgbKey2[keySize+1];
	Vector<byte> vbKey2;
	byte * pbKey2 = GetSortKey(bstrValue2, rgbKey2, &cbKey2, vbKey2);

	*pnVal = strcmp((char *)pbKey1, (char *)pbKey2);

	return S_OK;

	END_COM_METHOD(g_fact, IID_ILgCollatingEngine);
}
Пример #2
0
/*----------------------------------------------------------------------------------------------
	Generate the sort key as a "SAFEARRAY".
----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgIcuCollator::get_SortKeyVariant(BSTR bstrValue, LgCollatingOptions colopt,
	VARIANT * psaKey)
{
	BEGIN_COM_METHOD;
	ChkComBstrArgN(bstrValue);
	ChkComArgPtr(psaKey);
	psaKey->vt = VT_NULL;

	EnsureCollator();

	int32_t cbKey = keySize;
	byte rgbKey[keySize+1];
	Vector<byte> vbKey;
	byte * pbKey = GetSortKey(bstrValue, rgbKey, &cbKey, vbKey);

	// Allocate the safe array.
	SAFEARRAYBOUND rgsabound[1];
	rgsabound[0].lLbound = 0;
	rgsabound[0].cElements = cbKey;
	SAFEARRAY FAR * psa = ::SafeArrayCreate(VT_UI1, 1, rgsabound);
	// Copy the key data to the safe array.
	byte * pbOut;
	CheckHr(::SafeArrayAccessData(psa, (void HUGEP **)&pbOut));
	memcpy(pbOut, pbKey, cbKey);
	CheckHr(::SafeArrayUnaccessData(psa));
	// Push the safe array to the output pointer.
	psaKey->vt = VT_UI1 | VT_ARRAY;
	V_ARRAY(psaKey) = psa;

	return S_OK;

	END_COM_METHOD(g_fact, IID_ILgCollatingEngine);
}
Пример #3
0
/*----------------------------------------------------------------------------------------------
	Create a property with the given writing system, old writing system, and named style (ktptNamedStyle).
	Note that ktptCharStyle (which this used to use) is effectively obsolete.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP TsPropsFact::MakeProps(BSTR bstr, int ws, int ows, ITsTextProps ** ppttp)
{
	BEGIN_COM_METHOD;
	ChkComBstrArgN(bstr);
	ChkComOutPtr(ppttp);
	if ((uint)ws > kwsLim)
		ThrowInternalError(E_INVALIDARG, "Magic writing system invalid in string");

	return MakePropsRgch(bstr, BstrLen(bstr), ws, ows, ppttp);

	END_COM_METHOD(g_factPropsFact, IID_ITsPropsFactory);
}
Пример #4
0
/*----------------------------------------------------------------------------------------------
	Initialize the collating engine to the given locale.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgIcuCollator::Open(BSTR bstrLocale)
{
	BEGIN_COM_METHOD;
	ChkComBstrArgN(bstrLocale);

	if (m_pCollator)
	{
		delete m_pCollator;
		m_pCollator = NULL;
	}
	m_stuLocale = bstrLocale;
	EnsureCollator();
	END_COM_METHOD(g_fact, IID_ILgCollatingEngine);
}
Пример #5
0
// Initialize the root resource bundle. The path may be null to use the standard
// FieldWorks ICU data directory.
STDMETHODIMP LgIcuResourceBundle::Init(BSTR bstrPath, BSTR bstrLocale)
{
	BEGIN_COM_METHOD
	ChkComBstrArgN(bstrPath);
	ChkComBstrArg(bstrLocale);
	StrUtil::InitIcuDataDir();
	StrUni stuDir;
	UnicodeString usDir;
	if (bstrPath)
		stuDir = bstrPath;
		// Otherwise let ICU figure out the right directory
	usDir = stuDir.Chars();

	UErrorCode uerr = U_ZERO_ERROR;
	StrAnsi staLocale(bstrLocale);
	ResourceBundle rbt(usDir, Locale(staLocale.Chars()), uerr);
	if (U_FAILURE(uerr))
		ThrowHr(E_FAIL);
	m_rb = rbt;
	END_COM_METHOD(g_factRb, IID_ILgIcuResourceBundle);
}
Пример #6
0
// Get the display name of the locale represented by this enumerator.
// The display name will be in the selected locale if it is non-empty;
// pass null or an empty string to get the system default locale.
STDMETHODIMP LgIcuLocaleEnumerator::get_DisplayName(int iloc, BSTR bstrLocaleName,
	BSTR * pbstrName)
{
	BEGIN_COM_METHOD
	ChkComOutPtr(pbstrName);
	ChkComBstrArgN(bstrLocaleName);
	if (iloc >= m_clocale)
		ThrowHr(WarnHr(E_INVALIDARG));
	UnicodeString ust;
	if (BstrLen(bstrLocaleName) == 0)
		m_prgLocales[iloc].getDisplayName(ust);
	else
	{
		StrAnsi staLocaleName(bstrLocaleName);
		Locale loc = Locale::createFromName(staLocaleName.Chars());
		m_prgLocales[iloc].getDisplayName(loc, ust);
	}

	*pbstrName = UnicodeStringToBstr(ust);
	END_COM_METHOD(g_factLocEnum, IID_ILgIcuLocaleEnumerator);

}
Пример #7
0
/*----------------------------------------------------------------------------------------------
	Set the system keyboard and TSF language.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgTextServices::SetKeyboard(int lcid, BSTR bstrKeymanKbd, int * pnActiveLangId,
	BSTR * pbstrActiveKeymanKbd, ComBool * pfSelectLangPending)
{
	BEGIN_COM_METHOD;
	ChkComBstrArgN(bstrKeymanKbd);
	ChkComArgPtr(pnActiveLangId);
	ChkComArgPtr(pbstrActiveKeymanKbd);
	ChkComArgPtr(pfSelectLangPending);

	HRESULT hr;
	int nLangId = LANGIDFROMLCID(lcid);

	bool fDoingKeyman = BstrLen(bstrKeymanKbd) > 0;
	bool fSetInputLang = false;
#ifdef ENABLE_TSF
	if (IsKeyboardDifferent(bstrKeymanKbd, *pbstrActiveKeymanKbd) ||
		(LANGID)nLangId != (LANGID)*pnActiveLangId)
	{
		fSetInputLang = SetKeyboard_TSF(fDoingKeyman, lcid, pnActiveLangId);
	}
#endif /*ENABLE_TSF*/

	if (fDoingKeyman)
	{
		hr = SetKeyboard_Keyman(lcid, bstrKeymanKbd, pbstrActiveKeymanKbd, pfSelectLangPending);
	}
	else // no keyman keyboard wanted.
	{
		if (!fSetInputLang)
			SetKeyboard_Windows(lcid);

		TurnOffKeymanKbd(pbstrActiveKeymanKbd);
		*pfSelectLangPending = true;
	}

	END_COM_METHOD(g_fact, IID_ILgTextServices);
}
Пример #8
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#BeginUndoTask}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::BeginUndoTask(BSTR bstrUndo, BSTR bstrRedo)
{
	BEGIN_COM_METHOD;
	ChkComBstrArgN(bstrUndo);
	ChkComBstrArgN(bstrRedo);

	if (m_fUndoOrRedoInProgress)
		return S_OK;

	StrUni stuUndo(bstrUndo);
	StrUni stuRedo(bstrRedo);

	if (m_nDepth == 0 && !m_fStartedNext)
	{
		// Outer task.

		CleanUpEmptyTasks();

		// Don't clear the redo stack until we're sure we have at least one action
		// for this task. Instead, just remember the labels and set a flag.
		// Clearing the variables here causes the values from stuUndo to be copied below.
		m_stuNextUndo.Clear();
		m_stuNextRedo.Clear();
		m_fStartedNext = true;
		m_fDataChangeAction = false;

		//::OutputDebugStringA("Begin Undo Task - started next\n");
		//StrAnsi sta;
		//sta.Format("depth = %d; m_fStartedNext = %d; action %d of %d; seq %d of %d; marks %d%n",
		//	m_nDepth, m_fStartedNext, m_iuactCurr, m_vquact.Size(), m_iCurrSeq, m_viSeqStart.Size(), m_viMarks.Size());
		//::OutputDebugStringA(sta.Chars());
	}
	// Otherwise, this task will simply be embedded in the outer task.

	++m_nDepth;

	// However, if this task has labels and the outer one didn't, make use of these labels.
	// This can happen, for example, when ContinueUndoTask has to start a new transaction
	// because of a prior Un/Redo.
	if (m_stuNextUndo.Length() == 0)
	{
		// TODO JohnT(SharonC): temporary code; remove it when we get this issue straightened out.
		if (stuUndo == L"-")
			m_stuNextUndo = L"Undo";
		else
			m_stuNextUndo = stuUndo;
	}
	if (m_stuNextRedo.Length() == 0)
	{
		if (stuRedo == L"-")
			m_stuNextRedo = L"Redo";
		else
			m_stuNextRedo = stuRedo;
	}

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta(bstrUndo);
	if (sta.Length()) // Skip calls without string (eliminates idle loop calls)
	{
		sta.Replace(0, 0, "BeginUndoTask: ");
		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

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Пример #9
0
/*----------------------------------------------------------------------------------------------
Replace
	The default implementation just replaces characters from ichMin to ichLim with
	those from bstrInput, then set *pichModMin to ichMin, and *pichModLim and
	*pichIP both to ichMin + BstrLen(bstrInput).

	 Arguments:
		bstrInput				what user typed
		pttpInput          		text properties desired for new text
		ptsbOld        			original, unedited text, gets modified
		ichMin,	ichLim			range in original to replace
		pichModMin, pichModLim  range in output text affected
		pichIP                  position of IP in modified string

----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgInputMethodEditor::Replace(BSTR bstrInput, ITsTextProps * pttpInput,
		ITsStrBldr * ptsbOld, int ichMin, int ichLim, int * pichModMin, int * pichModLim,
		int * pichIP)
{
	BEGIN_COM_METHOD;
	ChkComBstrArgN(bstrInput);
	ChkComArgPtrN(pttpInput);
	ChkComArgPtr(ptsbOld);
	ChkComOutPtr(pichModMin);
	ChkComOutPtr(pichModLim);
	ChkComOutPtr(pichIP);

	int cCh;
	SmartBstr sbstr;
	CheckHr(ptsbOld->get_Length(&cCh));
	if (ichMin < 0 || ichLim > cCh || ichMin > ichLim)
	{
		*pichModMin = 0;
		*pichModLim = 0;
		*pichIP = 0;
		ThrowHr(WarnHr(E_INVALIDARG));
	}

	// Check to make sure the ichMin is not between a surrognte pair.
	do
	{
		if (0 < ichMin)
		{
			CheckHr(ptsbOld->GetChars(ichMin, ichMin + 1, &sbstr));
			if (sbstr[0] < 0xDC00 || sbstr[0] > 0xDFFF)
				break;
		}
		else
		{
			break;
		}
	} while (--ichMin > 0);

	// Check to make sure the ichLim is not between a surrgante pair.
	do
	{
		if (cCh > ichLim)
		{
			CheckHr(ptsbOld->GetChars(ichLim, ichLim + 1, &sbstr));
			if (sbstr[0] < 0xDC00 || sbstr[0] > 0xDFFF)
				break;
		}
		else
		{
			break;
		}
	} while (++ichLim < cCh);

	// Now, do the real work

	CheckHr(ptsbOld->Replace(ichMin, ichLim, bstrInput, pttpInput));
	*pichModMin = ichMin;
	*pichModLim = ichMin + BstrLen(bstrInput);
	*pichIP = ichMin + BstrLen(bstrInput);

	END_COM_METHOD(g_fact, IID_ILgFontManager);
}
Пример #10
0
/*----------------------------------------------------------------------------------------------
	Initialize the engine. This must be called before any oher methods of the interface.
	How the data is used is implementation dependent. The UniscribeRenderer does not
	use it at all. The Graphite renderer uses font name, bold, and italic settings
	to initialize itself with the proper font tables. For Graphite, bstrData contains
	(optionally) default settings for any font features.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP FwGrEngine::InitRenderer(IVwGraphics * pvg, BSTR bstrData)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pvg);
	ChkComBstrArgN(bstrData);

	// Make sure we can create a Graphite font.
	try
	{
		HDC hdc;
		IVwGraphicsWin32Ptr qvg32;
		CheckHr(pvg->QueryInterface(IID_IVwGraphicsWin32, (void **)&qvg32));
		CheckHr(qvg32->GetDeviceContext(&hdc));
		//FwGrGraphics gg(pvg);
		//gg.GetDeviceContext(&hdc);

		// Remember the font face name.
		LgCharRenderProps chrp;
		pvg->get_FontCharProperties(&chrp);
		memcpy(m_szFaceName, chrp.szFaceName, isizeof(m_szFaceName));

		// Make sure there is a cached font object.
		WinFont * pfontOld = m_pfont;
		m_pfont = new FwWinFont(hdc);
		m_fontSize = gr::GrEngine::RoundFloat(m_pfont->ascent() + m_pfont->descent());

		// Instead a code below, a FontException will be thrown.
		//FontErrorCode ferr = m_pfont->isValidForGraphite();
		//HRESULT hr;
		//std::wstring stuMsgBogus = FontLoadErrorDescription(ferr, 0, 0, &hr);

		// Delete this after creating the new one, so that if there happens to be only one
		// the font cache doesn't get destroyed and recreated!
		delete pfontOld;

		// Store the default feature values, which may be different from the font.
		m_cfeatWDefaults = ParseFeatureString((gr::utf16*)bstrData, BstrLen(bstrData), m_rgfsetDefaults);

		// This is kind of a kludge. The m_pfont may be kind of temporary, because the caller may delete
		// the graphics object and the DC. So call something to get set the FontFace set up while the
		// Font is still valid, so we can at least have access to some basic information from the engine.
		// Ideally we should probably create the WinFont with a private device context.
		int nTemp;
		this->get_ScriptDirection(&nTemp);

		return S_OK;
	}
	catch (FontException & fexptn)
	{
		// There was an error in initializing the font.
		FontErrorCode ferr = fexptn.errorCode;
		//int nVersion = fexptn.version;
		//int nSubVersion = fexptn.subVersion;
		HRESULT hr;
		std::wstring stuMsgBogus = FontLoadErrorDescription(ferr, 0, 0, &hr);
		return hr;
	}
	catch (...)
	{
		return kresUnexpected;
	}

	END_COM_METHOD(g_fact, IID_IRenderEngine);
}